aboutsummaryrefslogtreecommitdiffstats
path: root/routers/web
diff options
context:
space:
mode:
authorwxiaoguang <wxiaoguang@gmail.com>2024-02-24 21:12:17 +0800
committerGitHub <noreply@github.com>2024-02-24 13:12:17 +0000
commit29a26d9d8c573c9fb7e79a66ac3d578e8b20dcae (patch)
tree2d51372c6d14b0f1c96c35d1a2cf4ff8f6fb050b /routers/web
parentc42083a33950be6ee9f822c6d0de3c3a79d1f51b (diff)
downloadgitea-29a26d9d8c573c9fb7e79a66ac3d578e8b20dcae.tar.gz
gitea-29a26d9d8c573c9fb7e79a66ac3d578e8b20dcae.zip
Customizable "Open with" applications for repository clone (#29320)
Users could customize the "clone" menu with their own application URLs on the admin panel. Replace #22378 Close #21121 Close #22149
Diffstat (limited to 'routers/web')
-rw-r--r--routers/web/admin/config.go67
-rw-r--r--routers/web/repo/view.go29
-rw-r--r--routers/web/web.go1
3 files changed, 87 insertions, 10 deletions
diff --git a/routers/web/admin/config.go b/routers/web/admin/config.go
index c827f2a4f5..47f9201504 100644
--- a/routers/web/admin/config.go
+++ b/routers/web/admin/config.go
@@ -7,11 +7,11 @@ package admin
import (
"net/http"
"net/url"
+ "strconv"
"strings"
system_model "code.gitea.io/gitea/models/system"
"code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/container"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/json"
@@ -24,7 +24,10 @@ import (
"gitea.com/go-chi/session"
)
-const tplConfig base.TplName = "admin/config"
+const (
+ tplConfig base.TplName = "admin/config"
+ tplConfigSettings base.TplName = "admin/config_settings"
+)
// SendTestMail send test mail to confirm mail service is OK
func SendTestMail(ctx *context.Context) {
@@ -98,8 +101,9 @@ func shadowPassword(provider, cfgItem string) string {
// Config show admin config page
func Config(ctx *context.Context) {
- ctx.Data["Title"] = ctx.Tr("admin.config")
+ ctx.Data["Title"] = ctx.Tr("admin.config_summary")
ctx.Data["PageIsAdminConfig"] = true
+ ctx.Data["PageIsAdminConfigSummary"] = true
ctx.Data["CustomConf"] = setting.CustomConf
ctx.Data["AppUrl"] = setting.AppURL
@@ -161,23 +165,70 @@ func Config(ctx *context.Context) {
ctx.Data["Loggers"] = log.GetManager().DumpLoggers()
config.GetDynGetter().InvalidateCache()
- ctx.Data["SystemConfig"] = setting.Config()
prepareDeprecatedWarningsAlert(ctx)
ctx.HTML(http.StatusOK, tplConfig)
}
+func ConfigSettings(ctx *context.Context) {
+ ctx.Data["Title"] = ctx.Tr("admin.config_settings")
+ ctx.Data["PageIsAdminConfig"] = true
+ ctx.Data["PageIsAdminConfigSettings"] = true
+ ctx.Data["DefaultOpenWithEditorAppsString"] = setting.DefaultOpenWithEditorApps().ToTextareaString()
+ ctx.HTML(http.StatusOK, tplConfigSettings)
+}
+
func ChangeConfig(ctx *context.Context) {
key := strings.TrimSpace(ctx.FormString("key"))
value := ctx.FormString("value")
cfg := setting.Config()
- allowedKeys := container.SetOf(cfg.Picture.DisableGravatar.DynKey(), cfg.Picture.EnableFederatedAvatar.DynKey())
- if !allowedKeys.Contains(key) {
+
+ marshalBool := func(v string) (string, error) {
+ if b, _ := strconv.ParseBool(v); b {
+ return "true", nil
+ }
+ return "false", nil
+ }
+ marshalOpenWithApps := func(value string) (string, error) {
+ lines := strings.Split(value, "\n")
+ var openWithEditorApps setting.OpenWithEditorAppsType
+ for _, line := range lines {
+ line = strings.TrimSpace(line)
+ if line == "" {
+ continue
+ }
+ displayName, openURL, ok := strings.Cut(line, "=")
+ displayName, openURL = strings.TrimSpace(displayName), strings.TrimSpace(openURL)
+ if !ok || displayName == "" || openURL == "" {
+ continue
+ }
+ openWithEditorApps = append(openWithEditorApps, setting.OpenWithEditorApp{
+ DisplayName: strings.TrimSpace(displayName),
+ OpenURL: strings.TrimSpace(openURL),
+ })
+ }
+ b, err := json.Marshal(openWithEditorApps)
+ if err != nil {
+ return "", err
+ }
+ return string(b), nil
+ }
+ marshallers := map[string]func(string) (string, error){
+ cfg.Picture.DisableGravatar.DynKey(): marshalBool,
+ cfg.Picture.EnableFederatedAvatar.DynKey(): marshalBool,
+ cfg.Repository.OpenWithEditorApps.DynKey(): marshalOpenWithApps,
+ }
+ marshaller, hasMarshaller := marshallers[key]
+ if !hasMarshaller {
+ ctx.JSONError(ctx.Tr("admin.config.set_setting_failed", key))
+ return
+ }
+ marshaledValue, err := marshaller(value)
+ if err != nil {
ctx.JSONError(ctx.Tr("admin.config.set_setting_failed", key))
return
}
- if err := system_model.SetSettings(ctx, map[string]string{key: value}); err != nil {
- log.Error("set setting failed: %v", err)
+ if err = system_model.SetSettings(ctx, map[string]string{key: marshaledValue}); err != nil {
ctx.JSONError(ctx.Tr("admin.config.set_setting_failed", key))
return
}
diff --git a/routers/web/repo/view.go b/routers/web/repo/view.go
index 15f22237a8..33a5941d36 100644
--- a/routers/web/repo/view.go
+++ b/routers/web/repo/view.go
@@ -45,6 +45,7 @@ import (
repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/svg"
"code.gitea.io/gitea/modules/typesniffer"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/web/feed"
@@ -792,7 +793,7 @@ func Home(ctx *context.Context) {
return
}
- renderCode(ctx)
+ renderHomeCode(ctx)
}
// LastCommit returns lastCommit data for the provided branch/tag/commit and directory (in url) and filenames in body
@@ -919,9 +920,33 @@ func renderRepoTopics(ctx *context.Context) {
ctx.Data["Topics"] = topics
}
-func renderCode(ctx *context.Context) {
+func prepareOpenWithEditorApps(ctx *context.Context) {
+ var tmplApps []map[string]any
+ apps := setting.Config().Repository.OpenWithEditorApps.Value(ctx)
+ if len(apps) == 0 {
+ apps = setting.DefaultOpenWithEditorApps()
+ }
+ for _, app := range apps {
+ schema, _, _ := strings.Cut(app.OpenURL, ":")
+ var iconHTML template.HTML
+ if schema == "vscode" || schema == "vscodium" || schema == "jetbrains" {
+ iconHTML = svg.RenderHTML(fmt.Sprintf("gitea-open-with-%s", schema), 16, "gt-mr-3")
+ } else {
+ iconHTML = svg.RenderHTML("gitea-git", 16, "gt-mr-3") // TODO: it could support user's customized icon in the future
+ }
+ tmplApps = append(tmplApps, map[string]any{
+ "DisplayName": app.DisplayName,
+ "OpenURL": app.OpenURL,
+ "IconHTML": iconHTML,
+ })
+ }
+ ctx.Data["OpenWithEditorApps"] = tmplApps
+}
+
+func renderHomeCode(ctx *context.Context) {
ctx.Data["PageIsViewCode"] = true
ctx.Data["RepositoryUploadEnabled"] = setting.Repository.Upload.Enabled
+ prepareOpenWithEditorApps(ctx)
if ctx.Repo.Commit == nil || ctx.Repo.Repository.IsEmpty || ctx.Repo.Repository.IsBroken() {
showEmpty := true
diff --git a/routers/web/web.go b/routers/web/web.go
index 8505417c88..b1fa5cf355 100644
--- a/routers/web/web.go
+++ b/routers/web/web.go
@@ -686,6 +686,7 @@ func registerRoutes(m *web.Route) {
m.Get("", admin.Config)
m.Post("", admin.ChangeConfig)
m.Post("/test_mail", admin.SendTestMail)
+ m.Get("/settings", admin.ConfigSettings)
})
m.Group("/monitor", func() {