add aceEditorTheme to config and userDefaults

# Conflicts:
#	cmd/users.go
#	frontend/src/views/files/Editor.vue
#	http/auth.go
This commit is contained in:
Adam Saleh 2025-03-22 16:03:51 +01:00
parent 0eade717ce
commit 580b7100fa
No known key found for this signature in database
GPG Key ID: 8677BAC3D404F36F
10 changed files with 64 additions and 33 deletions

View File

@ -221,6 +221,7 @@ func printSettings(ser *settings.Server, set *settings.Settings, auther auth.Aut
fmt.Fprintf(w, "\tFile Creation Mode:\t%O\n", set.FileMode) fmt.Fprintf(w, "\tFile Creation Mode:\t%O\n", set.FileMode)
fmt.Fprintf(w, "\tDirectory Creation Mode:\t%O\n", set.DirMode) fmt.Fprintf(w, "\tDirectory Creation Mode:\t%O\n", set.DirMode)
fmt.Fprintf(w, "\tCommands:\t%s\n", strings.Join(set.Defaults.Commands, " ")) fmt.Fprintf(w, "\tCommands:\t%s\n", strings.Join(set.Defaults.Commands, " "))
fmt.Fprintf(w, "\tAce editor syntax highlighting theme:\t%s\n", set.Defaults.AceEditorTheme)
fmt.Fprintf(w, "\tSorting:\n") fmt.Fprintf(w, "\tSorting:\n")
fmt.Fprintf(w, "\t\tBy:\t%s\n", set.Defaults.Sorting.By) fmt.Fprintf(w, "\t\tBy:\t%s\n", set.Defaults.Sorting.By)
fmt.Fprintf(w, "\t\tAsc:\t%t\n", set.Defaults.Sorting.Asc) fmt.Fprintf(w, "\t\tAsc:\t%t\n", set.Defaults.Sorting.Asc)

View File

@ -424,9 +424,10 @@ func quickSetup(flags *pflag.FlagSet, d pythonData) error {
MinimumPasswordLength: settings.DefaultMinimumPasswordLength, MinimumPasswordLength: settings.DefaultMinimumPasswordLength,
UserHomeBasePath: settings.DefaultUsersHomeBasePath, UserHomeBasePath: settings.DefaultUsersHomeBasePath,
Defaults: settings.UserDefaults{ Defaults: settings.UserDefaults{
Scope: ".", Scope: ".",
Locale: "en", Locale: "en",
SingleClick: false, SingleClick: false,
AceEditorTheme: getParam(flags, "defaults.aceEditorTheme"),
Perm: users.Permissions{ Perm: users.Permissions{
Admin: false, Admin: false,
Execute: true, Execute: true,

View File

@ -79,6 +79,7 @@ func addUserFlags(flags *pflag.FlagSet) {
flags.Bool("singleClick", false, "use single clicks only") flags.Bool("singleClick", false, "use single clicks only")
flags.Bool("dateFormat", false, "use date format (true for absolute time, false for relative)") flags.Bool("dateFormat", false, "use date format (true for absolute time, false for relative)")
flags.Bool("hideDotfiles", false, "hide dotfiles") flags.Bool("hideDotfiles", false, "hide dotfiles")
flags.String("aceEditorTheme", "", "ace editor's syntax highlighting theme for users")
} }
func getViewMode(flags *pflag.FlagSet) (users.ViewMode, error) { func getViewMode(flags *pflag.FlagSet) (users.ViewMode, error) {
@ -110,6 +111,8 @@ func getUserDefaults(flags *pflag.FlagSet, defaults *settings.UserDefaults, all
defaults.ViewMode, err = getViewMode(flags) defaults.ViewMode, err = getViewMode(flags)
case "singleClick": case "singleClick":
defaults.SingleClick, err = getBool(flags, flag.Name) defaults.SingleClick, err = getBool(flags, flag.Name)
case "aceEditorTheme":
defaults.AceEditorTheme = getString(flags, flag.Name)
case "perm.admin": case "perm.admin":
defaults.Perm.Admin, err = getBool(flags, flag.Name) defaults.Perm.Admin, err = getBool(flags, flag.Name)
case "perm.execute": case "perm.execute":

View File

@ -21,6 +21,7 @@ interface SettingsDefaults {
commands: any[]; commands: any[];
hideDotfiles: boolean; hideDotfiles: boolean;
dateFormat: boolean; dateFormat: boolean;
aceEditorTheme: string;
} }
interface SettingsBranding { interface SettingsBranding {

View File

@ -13,6 +13,7 @@ interface IUser {
dateFormat: boolean; dateFormat: boolean;
viewMode: ViewModeType; viewMode: ViewModeType;
sorting?: Sorting; sorting?: Sorting;
aceEditorTheme: string;
} }
type ViewModeType = "list" | "mosaic" | "mosaic gallery"; type ViewModeType = "list" | "mosaic" | "mosaic gallery";

View File

@ -1,4 +1,6 @@
import { theme } from "./constants"; import { theme } from "./constants";
import "ace-builds";
import { themesByName } from "ace-builds/src-noconflict/ext-themelist";
export const getTheme = (): UserTheme => { export const getTheme = (): UserTheme => {
return (document.documentElement.className as UserTheme) || theme; return (document.documentElement.className as UserTheme) || theme;
@ -32,3 +34,17 @@ export const getMediaPreference = (): UserTheme => {
return "light"; return "light";
} }
}; };
export const getEditorTheme = (themeName: string) => {
if (!themeName.startsWith("ace/theme/")) {
themeName = `ace/theme/${themeName}`;
}
const themeKey = themeName.replace("ace/theme/", "");
if (themesByName[themeKey] !== undefined) {
return themeName;
} else if (getTheme() === "dark") {
return "ace/theme/twilight";
} else {
return "ace/theme/chrome";
}
};

View File

@ -69,7 +69,7 @@ import HeaderBar from "@/components/header/HeaderBar.vue";
import { useAuthStore } from "@/stores/auth"; import { useAuthStore } from "@/stores/auth";
import { useFileStore } from "@/stores/file"; import { useFileStore } from "@/stores/file";
import { useLayoutStore } from "@/stores/layout"; import { useLayoutStore } from "@/stores/layout";
import { getTheme } from "@/utils/theme"; import { getEditorTheme } from "@/utils/theme";
import { marked } from "marked"; import { marked } from "marked";
import { inject, onBeforeUnmount, onMounted, ref, watchEffect } from "vue"; import { inject, onBeforeUnmount, onMounted, ref, watchEffect } from "vue";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
@ -122,7 +122,7 @@ onMounted(() => {
value: fileContent, value: fileContent,
showPrintMargin: false, showPrintMargin: false,
readOnly: fileStore.req?.type === "textImmutable", readOnly: fileStore.req?.type === "textImmutable",
theme: "ace/theme/chrome", theme: getEditorTheme(authStore.user?.aceEditorTheme ?? ""),
mode: modelist.getModeForPath(fileStore.req!.name).mode, mode: modelist.getModeForPath(fileStore.req!.name).mode,
wrap: true, wrap: true,
enableBasicAutocompletion: true, enableBasicAutocompletion: true,
@ -130,10 +130,6 @@ onMounted(() => {
enableSnippets: true, enableSnippets: true,
}); });
if (getTheme() === "dark") {
editor.value!.setTheme("ace/theme/twilight");
}
editor.value.setFontSize(fontSize.value); editor.value.setFontSize(fontSize.value);
editor.value.focus(); editor.value.focus();
}); });
@ -219,6 +215,13 @@ const decreaseFontSize = () => {
}; };
const close = () => { const close = () => {
if (!editor.value?.session.getUndoManager().isClean()) {
layoutStore.showHover("discardEditorChanges");
return;
}
fileStore.updateRequest(null);
const uri = url.removeLastDir(route.path) + "/"; const uri = url.removeLastDir(route.path) + "/";
router.push({ path: uri }); router.push({ path: uri });
}; };

View File

@ -31,6 +31,7 @@ type userInfo struct {
HideDotfiles bool `json:"hideDotfiles"` HideDotfiles bool `json:"hideDotfiles"`
DateFormat bool `json:"dateFormat"` DateFormat bool `json:"dateFormat"`
Username string `json:"username"` Username string `json:"username"`
AceEditorTheme string `json:"aceEditorTheme"`
} }
type authToken struct { type authToken struct {
@ -200,6 +201,7 @@ func printToken(w http.ResponseWriter, _ *http.Request, d *data, user *users.Use
HideDotfiles: user.HideDotfiles, HideDotfiles: user.HideDotfiles,
DateFormat: user.DateFormat, DateFormat: user.DateFormat,
Username: user.Username, Username: user.Username,
AceEditorTheme: user.AceEditorTheme,
}, },
RegisteredClaims: jwt.RegisteredClaims{ RegisteredClaims: jwt.RegisteredClaims{
IssuedAt: jwt.NewNumericDate(time.Now()), IssuedAt: jwt.NewNumericDate(time.Now()),

View File

@ -8,15 +8,16 @@ import (
// UserDefaults is a type that holds the default values // UserDefaults is a type that holds the default values
// for some fields on User. // for some fields on User.
type UserDefaults struct { type UserDefaults struct {
Scope string `json:"scope"` Scope string `json:"scope"`
Locale string `json:"locale"` Locale string `json:"locale"`
ViewMode users.ViewMode `json:"viewMode"` ViewMode users.ViewMode `json:"viewMode"`
SingleClick bool `json:"singleClick"` SingleClick bool `json:"singleClick"`
Sorting files.Sorting `json:"sorting"` Sorting files.Sorting `json:"sorting"`
Perm users.Permissions `json:"perm"` Perm users.Permissions `json:"perm"`
Commands []string `json:"commands"` Commands []string `json:"commands"`
HideDotfiles bool `json:"hideDotfiles"` HideDotfiles bool `json:"hideDotfiles"`
DateFormat bool `json:"dateFormat"` DateFormat bool `json:"dateFormat"`
AceEditorTheme string `json:"aceEditorTheme"`
} }
// Apply applies the default options to a user. // Apply applies the default options to a user.
@ -30,4 +31,5 @@ func (d *UserDefaults) Apply(u *users.User) {
u.Commands = d.Commands u.Commands = d.Commands
u.HideDotfiles = d.HideDotfiles u.HideDotfiles = d.HideDotfiles
u.DateFormat = d.DateFormat u.DateFormat = d.DateFormat
u.AceEditorTheme = d.AceEditorTheme
} }

View File

@ -20,21 +20,22 @@ const (
// User describes a user. // User describes a user.
type User struct { type User struct {
ID uint `storm:"id,increment" json:"id"` ID uint `storm:"id,increment" json:"id"`
Username string `storm:"unique" json:"username"` Username string `storm:"unique" json:"username"`
Password string `json:"password"` Password string `json:"password"`
Scope string `json:"scope"` Scope string `json:"scope"`
Locale string `json:"locale"` Locale string `json:"locale"`
LockPassword bool `json:"lockPassword"` LockPassword bool `json:"lockPassword"`
ViewMode ViewMode `json:"viewMode"` ViewMode ViewMode `json:"viewMode"`
SingleClick bool `json:"singleClick"` SingleClick bool `json:"singleClick"`
Perm Permissions `json:"perm"` Perm Permissions `json:"perm"`
Commands []string `json:"commands"` Commands []string `json:"commands"`
Sorting files.Sorting `json:"sorting"` Sorting files.Sorting `json:"sorting"`
Fs afero.Fs `json:"-" yaml:"-"` Fs afero.Fs `json:"-" yaml:"-"`
Rules []rules.Rule `json:"rules"` Rules []rules.Rule `json:"rules"`
HideDotfiles bool `json:"hideDotfiles"` HideDotfiles bool `json:"hideDotfiles"`
DateFormat bool `json:"dateFormat"` DateFormat bool `json:"dateFormat"`
AceEditorTheme string `json:"aceEditorTheme"`
} }
// GetRules implements rules.Provider. // GetRules implements rules.Provider.