mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 16:40:24 +08:00 
			
		
		
		
	Allow for user specific themes (#5668)
* add migration and basic UI for changing a user's theme * update user themem * use right text on button * load theme based on users' selection * load theme based on users' selection in pwa too * update sample config * delete older theme loading * implement AfterLoad to set users' theme properly * set up default theme when creating a user. This uses the installation wide theme * use flash messages for error * set default theme when creating a user from the cli * fix @lunny review
This commit is contained in:
		
				
					committed by
					
						
						techknowlogick
					
				
			
			
				
	
			
			
			
						parent
						
							ea518681d9
						
					
				
				
					commit
					8d2c24f7f9
				
			@@ -340,6 +340,7 @@ func runCreateUser(c *cli.Context) error {
 | 
				
			|||||||
		IsActive:           true,
 | 
							IsActive:           true,
 | 
				
			||||||
		IsAdmin:            c.Bool("admin"),
 | 
							IsAdmin:            c.Bool("admin"),
 | 
				
			||||||
		MustChangePassword: changePassword,
 | 
							MustChangePassword: changePassword,
 | 
				
			||||||
 | 
							Theme:              setting.UI.DefaultTheme,
 | 
				
			||||||
	}); err != nil {
 | 
						}); err != nil {
 | 
				
			||||||
		return fmt.Errorf("CreateUser: %v", err)
 | 
							return fmt.Errorf("CreateUser: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -85,6 +85,8 @@ MAX_DISPLAY_FILE_SIZE = 8388608
 | 
				
			|||||||
SHOW_USER_EMAIL = true
 | 
					SHOW_USER_EMAIL = true
 | 
				
			||||||
; Set the default theme for the Gitea install
 | 
					; Set the default theme for the Gitea install
 | 
				
			||||||
DEFAULT_THEME = gitea
 | 
					DEFAULT_THEME = gitea
 | 
				
			||||||
 | 
					; All available themes
 | 
				
			||||||
 | 
					THEMES = gitea,arc-green
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[ui.admin]
 | 
					[ui.admin]
 | 
				
			||||||
; Number of users that are displayed on one page
 | 
					; Number of users that are displayed on one page
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,7 +18,7 @@ import (
 | 
				
			|||||||
	"github.com/Unknwon/com"
 | 
						"github.com/Unknwon/com"
 | 
				
			||||||
	"github.com/go-xorm/xorm"
 | 
						"github.com/go-xorm/xorm"
 | 
				
			||||||
	gouuid "github.com/satori/go.uuid"
 | 
						gouuid "github.com/satori/go.uuid"
 | 
				
			||||||
	"gopkg.in/ini.v1"
 | 
						ini "gopkg.in/ini.v1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"code.gitea.io/gitea/modules/generate"
 | 
						"code.gitea.io/gitea/modules/generate"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/log"
 | 
						"code.gitea.io/gitea/modules/log"
 | 
				
			||||||
@@ -206,6 +206,8 @@ var migrations = []Migration{
 | 
				
			|||||||
	NewMigration("clear nonused data which not deleted when user was deleted", clearNonusedData),
 | 
						NewMigration("clear nonused data which not deleted when user was deleted", clearNonusedData),
 | 
				
			||||||
	// v76 -> v77
 | 
						// v76 -> v77
 | 
				
			||||||
	NewMigration("add pull request rebase with merge commit", addPullRequestRebaseWithMerge),
 | 
						NewMigration("add pull request rebase with merge commit", addPullRequestRebaseWithMerge),
 | 
				
			||||||
 | 
						// v77 -> v78
 | 
				
			||||||
 | 
						NewMigration("add theme to users", addUserDefaultTheme),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Migrate database to current version
 | 
					// Migrate database to current version
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										17
									
								
								models/migrations/v77.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								models/migrations/v77.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					// Copyright 2019 The Gitea Authors. All rights reserved.
 | 
				
			||||||
 | 
					// Use of this source code is governed by a MIT-style
 | 
				
			||||||
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package migrations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/go-xorm/xorm"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func addUserDefaultTheme(x *xorm.Engine) error {
 | 
				
			||||||
 | 
						type User struct {
 | 
				
			||||||
 | 
							Theme string `xorm:"VARCHAR(30)"`
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return x.Sync2(new(User))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -140,6 +140,7 @@ type User struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// Preferences
 | 
						// Preferences
 | 
				
			||||||
	DiffViewStyle string `xorm:"NOT NULL DEFAULT ''"`
 | 
						DiffViewStyle string `xorm:"NOT NULL DEFAULT ''"`
 | 
				
			||||||
 | 
						Theme         string `xorm:"NOT NULL DEFAULT ''"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// BeforeUpdate is invoked from XORM before updating this object.
 | 
					// BeforeUpdate is invoked from XORM before updating this object.
 | 
				
			||||||
@@ -165,6 +166,13 @@ func (u *User) BeforeUpdate() {
 | 
				
			|||||||
	u.Description = base.TruncateString(u.Description, 255)
 | 
						u.Description = base.TruncateString(u.Description, 255)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// AfterLoad is invoked from XORM after filling all the fields of this object.
 | 
				
			||||||
 | 
					func (u *User) AfterLoad() {
 | 
				
			||||||
 | 
						if u.Theme == "" {
 | 
				
			||||||
 | 
							u.Theme = setting.UI.DefaultTheme
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// SetLastLogin set time to last login
 | 
					// SetLastLogin set time to last login
 | 
				
			||||||
func (u *User) SetLastLogin() {
 | 
					func (u *User) SetLastLogin() {
 | 
				
			||||||
	u.LastLoginUnix = util.TimeStampNow()
 | 
						u.LastLoginUnix = util.TimeStampNow()
 | 
				
			||||||
@@ -176,6 +184,12 @@ func (u *User) UpdateDiffViewStyle(style string) error {
 | 
				
			|||||||
	return UpdateUserCols(u, "diff_view_style")
 | 
						return UpdateUserCols(u, "diff_view_style")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// UpdateTheme updates a users' theme irrespective of the site wide theme
 | 
				
			||||||
 | 
					func (u *User) UpdateTheme(themeName string) error {
 | 
				
			||||||
 | 
						u.Theme = themeName
 | 
				
			||||||
 | 
						return UpdateUserCols(u, "theme")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// getEmail returns an noreply email, if the user has set to keep his
 | 
					// getEmail returns an noreply email, if the user has set to keep his
 | 
				
			||||||
// email address private, otherwise the primary email address.
 | 
					// email address private, otherwise the primary email address.
 | 
				
			||||||
func (u *User) getEmail() string {
 | 
					func (u *User) getEmail() string {
 | 
				
			||||||
@@ -777,6 +791,7 @@ func CreateUser(u *User) (err error) {
 | 
				
			|||||||
	u.HashPassword(u.Passwd)
 | 
						u.HashPassword(u.Passwd)
 | 
				
			||||||
	u.AllowCreateOrganization = setting.Service.DefaultAllowCreateOrganization
 | 
						u.AllowCreateOrganization = setting.Service.DefaultAllowCreateOrganization
 | 
				
			||||||
	u.MaxRepoCreation = -1
 | 
						u.MaxRepoCreation = -1
 | 
				
			||||||
 | 
						u.Theme = setting.UI.DefaultTheme
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if _, err = sess.Insert(u); err != nil {
 | 
						if _, err = sess.Insert(u); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,7 +12,7 @@ import (
 | 
				
			|||||||
	"code.gitea.io/gitea/modules/setting"
 | 
						"code.gitea.io/gitea/modules/setting"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/go-macaron/binding"
 | 
						"github.com/go-macaron/binding"
 | 
				
			||||||
	"gopkg.in/macaron.v1"
 | 
						macaron "gopkg.in/macaron.v1"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// InstallForm form for installation page
 | 
					// InstallForm form for installation page
 | 
				
			||||||
@@ -189,6 +189,30 @@ func (f *AddEmailForm) Validate(ctx *macaron.Context, errs binding.Errors) bindi
 | 
				
			|||||||
	return validate(errs, ctx.Data, f, ctx.Locale)
 | 
						return validate(errs, ctx.Data, f, ctx.Locale)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// UpdateThemeForm form for updating a users' theme
 | 
				
			||||||
 | 
					type UpdateThemeForm struct {
 | 
				
			||||||
 | 
						Theme string `binding:"Required;MaxSize(30)"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Validate validates the field
 | 
				
			||||||
 | 
					func (f *UpdateThemeForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
 | 
				
			||||||
 | 
						return validate(errs, ctx.Data, f, ctx.Locale)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// IsThemeExists checks if the theme is a theme available in the config.
 | 
				
			||||||
 | 
					func (f UpdateThemeForm) IsThemeExists() bool {
 | 
				
			||||||
 | 
						var exists bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, v := range setting.UI.Themes {
 | 
				
			||||||
 | 
							if strings.ToLower(v) == strings.ToLower(f.Theme) {
 | 
				
			||||||
 | 
								exists = true
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return exists
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ChangePasswordForm form for changing password
 | 
					// ChangePasswordForm form for changing password
 | 
				
			||||||
type ChangePasswordForm struct {
 | 
					type ChangePasswordForm struct {
 | 
				
			||||||
	OldPassword string `form:"old_password" binding:"MaxSize(255)"`
 | 
						OldPassword string `form:"old_password" binding:"MaxSize(255)"`
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,4 +8,5 @@ var (
 | 
				
			|||||||
	defaultLangs                             = strings.Split("en-US,zh-CN,zh-HK,zh-TW,de-DE,fr-FR,nl-NL,lv-LV,ru-RU,uk-UA,ja-JP,es-ES,pt-BR,pl-PL,bg-BG,it-IT,fi-FI,tr-TR,cs-CZ,sr-SP,sv-SE,ko-KR", ",")
 | 
						defaultLangs                             = strings.Split("en-US,zh-CN,zh-HK,zh-TW,de-DE,fr-FR,nl-NL,lv-LV,ru-RU,uk-UA,ja-JP,es-ES,pt-BR,pl-PL,bg-BG,it-IT,fi-FI,tr-TR,cs-CZ,sr-SP,sv-SE,ko-KR", ",")
 | 
				
			||||||
	defaultLangNames                         = strings.Split("English,简体中文,繁體中文(香港),繁體中文(台灣),Deutsch,français,Nederlands,latviešu,русский,Українська,日本語,español,português do Brasil,polski,български,italiano,suomi,Türkçe,čeština,српски,svenska,한국어", ",")
 | 
						defaultLangNames                         = strings.Split("English,简体中文,繁體中文(香港),繁體中文(台灣),Deutsch,français,Nederlands,latviešu,русский,Українська,日本語,español,português do Brasil,polski,български,italiano,suomi,Türkçe,čeština,српски,svenska,한국어", ",")
 | 
				
			||||||
	defaultPullRequestWorkInProgressPrefixes = strings.Split("WIP:,[WIP]", ",")
 | 
						defaultPullRequestWorkInProgressPrefixes = strings.Split("WIP:,[WIP]", ",")
 | 
				
			||||||
 | 
						defaultThemes                            = strings.Split("gitea", "arc-green")
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -33,9 +33,9 @@ import (
 | 
				
			|||||||
	"github.com/go-macaron/session"
 | 
						"github.com/go-macaron/session"
 | 
				
			||||||
	_ "github.com/go-macaron/session/redis" // redis plugin for store session
 | 
						_ "github.com/go-macaron/session/redis" // redis plugin for store session
 | 
				
			||||||
	"github.com/go-xorm/core"
 | 
						"github.com/go-xorm/core"
 | 
				
			||||||
	"github.com/kballard/go-shellquote"
 | 
						shellquote "github.com/kballard/go-shellquote"
 | 
				
			||||||
	"github.com/mcuadros/go-version"
 | 
						version "github.com/mcuadros/go-version"
 | 
				
			||||||
	"gopkg.in/ini.v1"
 | 
						ini "gopkg.in/ini.v1"
 | 
				
			||||||
	"strk.kbt.io/projects/go/libravatar"
 | 
						"strk.kbt.io/projects/go/libravatar"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -303,6 +303,7 @@ var (
 | 
				
			|||||||
		MaxDisplayFileSize  int64
 | 
							MaxDisplayFileSize  int64
 | 
				
			||||||
		ShowUserEmail       bool
 | 
							ShowUserEmail       bool
 | 
				
			||||||
		DefaultTheme        string
 | 
							DefaultTheme        string
 | 
				
			||||||
 | 
							Themes              []string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Admin struct {
 | 
							Admin struct {
 | 
				
			||||||
			UserPagingNum   int
 | 
								UserPagingNum   int
 | 
				
			||||||
@@ -329,6 +330,7 @@ var (
 | 
				
			|||||||
		ThemeColorMetaTag:   `#6cc644`,
 | 
							ThemeColorMetaTag:   `#6cc644`,
 | 
				
			||||||
		MaxDisplayFileSize:  8388608,
 | 
							MaxDisplayFileSize:  8388608,
 | 
				
			||||||
		DefaultTheme:        `gitea`,
 | 
							DefaultTheme:        `gitea`,
 | 
				
			||||||
 | 
							Themes:              []string{`gitea`, `arc-green`},
 | 
				
			||||||
		Admin: struct {
 | 
							Admin: struct {
 | 
				
			||||||
			UserPagingNum   int
 | 
								UserPagingNum   int
 | 
				
			||||||
			RepoPagingNum   int
 | 
								RepoPagingNum   int
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -355,6 +355,7 @@ password_username_disabled = Non-local users are not allowed to change their use
 | 
				
			|||||||
full_name = Full Name
 | 
					full_name = Full Name
 | 
				
			||||||
website = Website
 | 
					website = Website
 | 
				
			||||||
location = Location
 | 
					location = Location
 | 
				
			||||||
 | 
					update_theme = Update Theme
 | 
				
			||||||
update_profile = Update Profile
 | 
					update_profile = Update Profile
 | 
				
			||||||
update_profile_success = Your profile has been updated.
 | 
					update_profile_success = Your profile has been updated.
 | 
				
			||||||
change_username = Your username has been changed.
 | 
					change_username = Your username has been changed.
 | 
				
			||||||
@@ -362,6 +363,7 @@ change_username_prompt = Note: username changes also change your account URL.
 | 
				
			|||||||
continue = Continue
 | 
					continue = Continue
 | 
				
			||||||
cancel = Cancel
 | 
					cancel = Cancel
 | 
				
			||||||
language = Language
 | 
					language = Language
 | 
				
			||||||
 | 
					ui = Theme
 | 
				
			||||||
 | 
					
 | 
				
			||||||
lookup_avatar_by_mail = Look Up Avatar by Email Address
 | 
					lookup_avatar_by_mail = Look Up Avatar by Email Address
 | 
				
			||||||
federated_avatar_lookup = Federated Avatar Lookup
 | 
					federated_avatar_lookup = Federated Avatar Lookup
 | 
				
			||||||
@@ -382,14 +384,18 @@ password_change_disabled = Non-local users can not update their password through
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
emails = Email Addresses
 | 
					emails = Email Addresses
 | 
				
			||||||
manage_emails = Manage Email Addresses
 | 
					manage_emails = Manage Email Addresses
 | 
				
			||||||
 | 
					manage_themes = Select default theme
 | 
				
			||||||
manage_openid = Manage OpenID Addresses
 | 
					manage_openid = Manage OpenID Addresses
 | 
				
			||||||
email_desc = Your primary email address will be used for notifications and other operations.
 | 
					email_desc = Your primary email address will be used for notifications and other operations.
 | 
				
			||||||
 | 
					theme_desc = This will be your default theme across the site.
 | 
				
			||||||
primary = Primary
 | 
					primary = Primary
 | 
				
			||||||
primary_email = Make Primary
 | 
					primary_email = Make Primary
 | 
				
			||||||
delete_email = Remove
 | 
					delete_email = Remove
 | 
				
			||||||
email_deletion = Remove Email Address
 | 
					email_deletion = Remove Email Address
 | 
				
			||||||
email_deletion_desc = The email address and related information will be removed from your account. Git commits by this email address will remain unchanged. Continue?
 | 
					email_deletion_desc = The email address and related information will be removed from your account. Git commits by this email address will remain unchanged. Continue?
 | 
				
			||||||
email_deletion_success = The email address has been removed.
 | 
					email_deletion_success = The email address has been removed.
 | 
				
			||||||
 | 
					theme_update_success = Your theme was updated.
 | 
				
			||||||
 | 
					theme_update_error = The selected theme does not exist.
 | 
				
			||||||
openid_deletion = Remove OpenID Address
 | 
					openid_deletion = Remove OpenID Address
 | 
				
			||||||
openid_deletion_desc = Removing this OpenID address from your account will prevent you from signing in with it. Continue?
 | 
					openid_deletion_desc = Removing this OpenID address from your account will prevent you from signing in with it. Continue?
 | 
				
			||||||
openid_deletion_success = The OpenID address has been removed.
 | 
					openid_deletion_success = The OpenID address has been removed.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -42,7 +42,7 @@ import (
 | 
				
			|||||||
	"github.com/go-macaron/toolbox"
 | 
						"github.com/go-macaron/toolbox"
 | 
				
			||||||
	"github.com/prometheus/client_golang/prometheus"
 | 
						"github.com/prometheus/client_golang/prometheus"
 | 
				
			||||||
	"github.com/tstranex/u2f"
 | 
						"github.com/tstranex/u2f"
 | 
				
			||||||
	"gopkg.in/macaron.v1"
 | 
						macaron "gopkg.in/macaron.v1"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewMacaron initializes Macaron instance.
 | 
					// NewMacaron initializes Macaron instance.
 | 
				
			||||||
@@ -243,6 +243,7 @@ func RegisterRoutes(m *macaron.Macaron) {
 | 
				
			|||||||
			m.Post("/email", bindIgnErr(auth.AddEmailForm{}), userSetting.EmailPost)
 | 
								m.Post("/email", bindIgnErr(auth.AddEmailForm{}), userSetting.EmailPost)
 | 
				
			||||||
			m.Post("/email/delete", userSetting.DeleteEmail)
 | 
								m.Post("/email/delete", userSetting.DeleteEmail)
 | 
				
			||||||
			m.Post("/delete", userSetting.DeleteAccount)
 | 
								m.Post("/delete", userSetting.DeleteAccount)
 | 
				
			||||||
 | 
								m.Post("/theme", bindIgnErr(auth.UpdateThemeForm{}), userSetting.UpdateUIThemePost)
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
		m.Group("/security", func() {
 | 
							m.Group("/security", func() {
 | 
				
			||||||
			m.Get("", userSetting.Security)
 | 
								m.Get("", userSetting.Security)
 | 
				
			||||||
@@ -292,6 +293,7 @@ func RegisterRoutes(m *macaron.Macaron) {
 | 
				
			|||||||
		})
 | 
							})
 | 
				
			||||||
	}, reqSignIn, func(ctx *context.Context) {
 | 
						}, reqSignIn, func(ctx *context.Context) {
 | 
				
			||||||
		ctx.Data["PageIsUserSettings"] = true
 | 
							ctx.Data["PageIsUserSettings"] = true
 | 
				
			||||||
 | 
							ctx.Data["AllThemes"] = setting.UI.Themes
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	m.Group("/user", func() {
 | 
						m.Group("/user", func() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -168,6 +168,34 @@ func DeleteAccount(ctx *context.Context) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// UpdateUIThemePost is used to update users' specific theme
 | 
				
			||||||
 | 
					func UpdateUIThemePost(ctx *context.Context, form auth.UpdateThemeForm) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.Data["Title"] = ctx.Tr("settings")
 | 
				
			||||||
 | 
						ctx.Data["PageIsSettingsAccount"] = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ctx.HasError() {
 | 
				
			||||||
 | 
							ctx.Redirect(setting.AppSubURL + "/user/settings/account")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if !form.IsThemeExists() {
 | 
				
			||||||
 | 
							ctx.Flash.Error(ctx.Tr("settings.theme_update_error"))
 | 
				
			||||||
 | 
							ctx.Redirect(setting.AppSubURL + "/user/settings/account")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := ctx.User.UpdateTheme(form.Theme); err != nil {
 | 
				
			||||||
 | 
							ctx.Flash.Error(ctx.Tr("settings.theme_update_error"))
 | 
				
			||||||
 | 
							ctx.Redirect(setting.AppSubURL + "/user/settings/account")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						log.Trace("Update user theme: %s", ctx.User.Name)
 | 
				
			||||||
 | 
						ctx.Flash.Success(ctx.Tr("settings.theme_update_success"))
 | 
				
			||||||
 | 
						ctx.Redirect(setting.AppSubURL + "/user/settings/account")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func loadAccountData(ctx *context.Context) {
 | 
					func loadAccountData(ctx *context.Context) {
 | 
				
			||||||
	emails, err := models.GetEmailAddresses(ctx.User.ID)
 | 
						emails, err := models.GetEmailAddresses(ctx.User.ID)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,7 +6,7 @@
 | 
				
			|||||||
	<meta http-equiv="x-ua-compatible" content="ie=edge">
 | 
						<meta http-equiv="x-ua-compatible" content="ie=edge">
 | 
				
			||||||
	<title>{{if .Title}}{{.Title}} - {{end}}{{AppName}}</title>
 | 
						<title>{{if .Title}}{{.Title}} - {{end}}{{AppName}}</title>
 | 
				
			||||||
	<link rel="manifest" href="{{AppSubUrl}}/manifest.json">
 | 
						<link rel="manifest" href="{{AppSubUrl}}/manifest.json">
 | 
				
			||||||
	
 | 
					
 | 
				
			||||||
	<script>
 | 
						<script>
 | 
				
			||||||
		if ('serviceWorker' in navigator) {
 | 
							if ('serviceWorker' in navigator) {
 | 
				
			||||||
  			window.addEventListener('load', function() {
 | 
					  			window.addEventListener('load', function() {
 | 
				
			||||||
@@ -147,7 +147,11 @@
 | 
				
			|||||||
	<meta property="og:url" content="{{AppUrl}}" />
 | 
						<meta property="og:url" content="{{AppUrl}}" />
 | 
				
			||||||
	<meta property="og:description" content="{{MetaDescription}}">
 | 
						<meta property="og:description" content="{{MetaDescription}}">
 | 
				
			||||||
{{end}}
 | 
					{{end}}
 | 
				
			||||||
{{if ne DefaultTheme "gitea"}}
 | 
					{{if .IsSigned }}
 | 
				
			||||||
 | 
						{{ if ne .SignedUser.Theme "gitea" }}
 | 
				
			||||||
 | 
							<link rel="stylesheet" href="{{AppSubUrl}}/css/theme-{{.SignedUser.Theme}}.css">
 | 
				
			||||||
 | 
						{{end}}
 | 
				
			||||||
 | 
					{{else if ne DefaultTheme "gitea"}}
 | 
				
			||||||
	<link rel="stylesheet" href="{{AppSubUrl}}/css/theme-{{DefaultTheme}}.css">
 | 
						<link rel="stylesheet" href="{{AppSubUrl}}/css/theme-{{DefaultTheme}}.css">
 | 
				
			||||||
{{end}}
 | 
					{{end}}
 | 
				
			||||||
{{template "custom/header" .}}
 | 
					{{template "custom/header" .}}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -32,10 +32,14 @@ var urlsToCache = [
 | 
				
			|||||||
  '{{AppSubUrl}}/vendor/plugins/jquery.minicolors/jquery.minicolors.css',
 | 
					  '{{AppSubUrl}}/vendor/plugins/jquery.minicolors/jquery.minicolors.css',
 | 
				
			||||||
  '{{AppSubUrl}}/vendor/plugins/jquery.datetimepicker/jquery.datetimepicker.css',
 | 
					  '{{AppSubUrl}}/vendor/plugins/jquery.datetimepicker/jquery.datetimepicker.css',
 | 
				
			||||||
  '{{AppSubUrl}}/vendor/plugins/dropzone/dropzone.css',
 | 
					  '{{AppSubUrl}}/vendor/plugins/dropzone/dropzone.css',
 | 
				
			||||||
{{if ne DefaultTheme "gitea"}}
 | 
					{{if .IsSigned }}
 | 
				
			||||||
  '{{AppSubUrl}}/css/theme-{{DefaultTheme}}.css',
 | 
						{{ if ne .SignedUser.Theme "gitea" }}
 | 
				
			||||||
 | 
							'{{AppSubUrl}}/css/theme-{{.SignedUser.Theme}}.css'
 | 
				
			||||||
 | 
						{{end}}
 | 
				
			||||||
 | 
					{{else if ne DefaultTheme "gitea"}}
 | 
				
			||||||
 | 
						'{{AppSubUrl}}/css/theme-{{DefaultTheme}}.css'
 | 
				
			||||||
{{end}}
 | 
					{{end}}
 | 
				
			||||||
  
 | 
					
 | 
				
			||||||
  // img
 | 
					  // img
 | 
				
			||||||
  '{{AppSubUrl}}/img/gitea-sm.png',
 | 
					  '{{AppSubUrl}}/img/gitea-sm.png',
 | 
				
			||||||
  '{{AppSubUrl}}/img/gitea-lg.png',
 | 
					  '{{AppSubUrl}}/img/gitea-lg.png',
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -85,6 +85,44 @@
 | 
				
			|||||||
			</form>
 | 
								</form>
 | 
				
			||||||
		</div>
 | 
							</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							<h4 class="ui top attached header">
 | 
				
			||||||
 | 
								{{.i18n.Tr "settings.manage_themes"}}
 | 
				
			||||||
 | 
							</h4>
 | 
				
			||||||
 | 
							<div class="ui attached segment">
 | 
				
			||||||
 | 
								<div class="ui email list">
 | 
				
			||||||
 | 
									<div class="item">
 | 
				
			||||||
 | 
										{{.i18n.Tr "settings.theme_desc"}}
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								<form class="ui form" action="{{.Link}}/theme" method="post">
 | 
				
			||||||
 | 
									{{.CsrfTokenHtml}}
 | 
				
			||||||
 | 
										<div class="field">
 | 
				
			||||||
 | 
											<label for="ui">{{.i18n.Tr "settings.ui"}}</label>
 | 
				
			||||||
 | 
											<div class="ui selection dropdown" id="ui">
 | 
				
			||||||
 | 
												<input name="theme" type="hidden" value="{{.SignedUser.Theme}}">
 | 
				
			||||||
 | 
												<i class="dropdown icon"></i>
 | 
				
			||||||
 | 
												<div class="text">
 | 
				
			||||||
 | 
													{{range $i,$a := .AllThemes}}
 | 
				
			||||||
 | 
													    {{if eq $.SignedUser.Theme $a}}{{$a}}{{end}}
 | 
				
			||||||
 | 
													{{end}}
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
												<div class="menu">
 | 
				
			||||||
 | 
												{{range $i,$a := .AllThemes}}
 | 
				
			||||||
 | 
													<div class="item{{if eq $.SignedUser.Theme $a}} active selected{{end}}" data-value="{{$a}}">
 | 
				
			||||||
 | 
														{{$a}}
 | 
				
			||||||
 | 
													</div>
 | 
				
			||||||
 | 
												{{end}}
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									<div class="field">
 | 
				
			||||||
 | 
										<button class="ui green button">{{$.i18n.Tr "settings.update_theme"}}</button>
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
								</form>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
		<h4 class="ui top attached warning header">
 | 
							<h4 class="ui top attached warning header">
 | 
				
			||||||
			{{.i18n.Tr "settings.delete_account"}}
 | 
								{{.i18n.Tr "settings.delete_account"}}
 | 
				
			||||||
		</h4>
 | 
							</h4>
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user