Implements public package discovery page in the Explore menu. Shows public and global packages with pagination, filtering by type, and search. Adds admin setting to enable/disable the packages tab. Updates package search to support PublicOrGlobal filter for showing packages that are either public OR global. Includes new locale strings and templates.
132 lines
4.5 KiB
Go
132 lines
4.5 KiB
Go
// Copyright 2023 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package setting
|
|
|
|
import (
|
|
"strings"
|
|
"sync"
|
|
|
|
"code.gitcaddy.com/server/v3/modules/log"
|
|
"code.gitcaddy.com/server/v3/modules/setting/config"
|
|
)
|
|
|
|
type PictureStruct struct {
|
|
DisableGravatar *config.Value[bool]
|
|
EnableFederatedAvatar *config.Value[bool]
|
|
}
|
|
|
|
type OpenWithEditorApp struct {
|
|
DisplayName string
|
|
OpenURL string
|
|
}
|
|
|
|
type OpenWithEditorAppsType []OpenWithEditorApp
|
|
|
|
func (t OpenWithEditorAppsType) ToTextareaString() string {
|
|
var ret strings.Builder
|
|
for _, app := range t {
|
|
ret.WriteString(app.DisplayName + " = " + app.OpenURL + "\n")
|
|
}
|
|
return ret.String()
|
|
}
|
|
|
|
func DefaultOpenWithEditorApps() OpenWithEditorAppsType {
|
|
return OpenWithEditorAppsType{
|
|
{
|
|
DisplayName: "VS Code",
|
|
OpenURL: "vscode://vscode.git/clone?url={url}",
|
|
},
|
|
{
|
|
DisplayName: "VSCodium",
|
|
OpenURL: "vscodium://vscode.git/clone?url={url}",
|
|
},
|
|
{
|
|
DisplayName: "Intellij IDEA",
|
|
OpenURL: "jetbrains://idea/checkout/git?idea.required.plugins.id=Git4Idea&checkout.repo={url}",
|
|
},
|
|
}
|
|
}
|
|
|
|
type RepositoryStruct struct {
|
|
OpenWithEditorApps *config.Value[OpenWithEditorAppsType]
|
|
GitGuideRemoteName *config.Value[string]
|
|
}
|
|
|
|
type ThemeStruct struct {
|
|
DisableRegistration *config.Value[bool]
|
|
HideExploreUsers *config.Value[bool]
|
|
EnableExplorePackages *config.Value[bool]
|
|
HelpURL *config.Value[string]
|
|
CustomSiteIconURL *config.Value[string]
|
|
CustomHomeLogoURL *config.Value[string]
|
|
CustomHomeHTML *config.Value[string]
|
|
APIHeaderURL *config.Value[string]
|
|
CustomHomeTitle *config.Value[string]
|
|
CustomHomeTagline *config.Value[string]
|
|
PinnedOrgDisplayFormat *config.Value[string]
|
|
ExploreOrgDisplayFormat *config.Value[string]
|
|
}
|
|
|
|
type ConfigStruct struct {
|
|
Picture *PictureStruct
|
|
Repository *RepositoryStruct
|
|
Theme *ThemeStruct
|
|
}
|
|
|
|
var (
|
|
defaultConfig *ConfigStruct
|
|
defaultConfigOnce sync.Once
|
|
)
|
|
|
|
func initDefaultConfig() {
|
|
config.SetCfgSecKeyGetter(&cfgSecKeyGetter{})
|
|
defaultConfig = &ConfigStruct{
|
|
Picture: &PictureStruct{
|
|
DisableGravatar: config.ValueJSON[bool]("picture.disable_gravatar").WithFileConfig(config.CfgSecKey{Sec: "picture", Key: "DISABLE_GRAVATAR"}),
|
|
EnableFederatedAvatar: config.ValueJSON[bool]("picture.enable_federated_avatar").WithFileConfig(config.CfgSecKey{Sec: "picture", Key: "ENABLE_FEDERATED_AVATAR"}),
|
|
},
|
|
Repository: &RepositoryStruct{
|
|
OpenWithEditorApps: config.ValueJSON[OpenWithEditorAppsType]("repository.open-with.editor-apps"),
|
|
GitGuideRemoteName: config.ValueJSON[string]("repository.git-guide-remote-name").WithDefault("origin"),
|
|
},
|
|
Theme: &ThemeStruct{
|
|
DisableRegistration: config.ValueJSON[bool]("theme.disable_registration").WithFileConfig(config.CfgSecKey{Sec: "service", Key: "DISABLE_REGISTRATION"}),
|
|
HideExploreUsers: config.ValueJSON[bool]("theme.hide_explore_users").WithDefault(false),
|
|
EnableExplorePackages: config.ValueJSON[bool]("theme.enable_explore_packages").WithFileConfig(config.CfgSecKey{Sec: "service.explore", Key: "ENABLE_PACKAGES_PAGE"}),
|
|
HelpURL: config.ValueJSON[string]("theme.help_url").WithDefault(""),
|
|
CustomSiteIconURL: config.ValueJSON[string]("theme.custom_site_icon_url").WithDefault(""),
|
|
CustomHomeLogoURL: config.ValueJSON[string]("theme.custom_home_logo_url").WithDefault(""),
|
|
CustomHomeHTML: config.ValueJSON[string]("theme.custom_home_html").WithDefault(""),
|
|
APIHeaderURL: config.ValueJSON[string]("theme.api_header_url").WithDefault(""),
|
|
CustomHomeTitle: config.ValueJSON[string]("theme.custom_home_title").WithDefault(""),
|
|
CustomHomeTagline: config.ValueJSON[string]("theme.custom_home_tagline").WithDefault(""),
|
|
PinnedOrgDisplayFormat: config.ValueJSON[string]("theme.pinned_org_display_format").WithDefault("condensed"),
|
|
ExploreOrgDisplayFormat: config.ValueJSON[string]("theme.explore_org_display_format").WithDefault("list"),
|
|
},
|
|
}
|
|
}
|
|
|
|
func Config() *ConfigStruct {
|
|
defaultConfigOnce.Do(initDefaultConfig)
|
|
return defaultConfig
|
|
}
|
|
|
|
type cfgSecKeyGetter struct{}
|
|
|
|
func (c cfgSecKeyGetter) GetValue(sec, key string) (v string, has bool) {
|
|
if key == "" {
|
|
return "", false
|
|
}
|
|
cfgSec, err := CfgProvider.GetSection(sec)
|
|
if err != nil {
|
|
log.Error("Unable to get config section: %q", sec)
|
|
return "", false
|
|
}
|
|
cfgKey := ConfigSectionKey(cfgSec, key)
|
|
if cfgKey == nil {
|
|
return "", false
|
|
}
|
|
return cfgKey.Value(), true
|
|
}
|