feat: add font style preferences support
This commit is contained in:
parent
dd88c617f9
commit
49435848ee
|
@ -1,9 +1,13 @@
|
|||
package services
|
||||
|
||||
import (
|
||||
"github.com/adrg/sysfont"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
storage2 "tinyrdm/backend/storage"
|
||||
"tinyrdm/backend/types"
|
||||
"tinyrdm/backend/utils/coll"
|
||||
)
|
||||
|
||||
type preferencesService struct {
|
||||
|
@ -49,3 +53,30 @@ func (p *preferencesService) RestorePreferences() (resp types.JSResp) {
|
|||
resp.Success = true
|
||||
return
|
||||
}
|
||||
|
||||
type FontItem struct {
|
||||
Name string `json:"name"`
|
||||
Path string `json:"path"`
|
||||
}
|
||||
|
||||
func (p *preferencesService) GetFontList() (resp types.JSResp) {
|
||||
finder := sysfont.NewFinder(nil)
|
||||
fontSet := coll.NewSet[string]()
|
||||
var fontList []FontItem
|
||||
for _, font := range finder.List() {
|
||||
if len(font.Family) > 0 && !strings.HasPrefix(font.Family, ".") && fontSet.Add(font.Family) {
|
||||
fontList = append(fontList, FontItem{
|
||||
Name: font.Family,
|
||||
Path: font.Filename,
|
||||
})
|
||||
}
|
||||
}
|
||||
sort.Slice(fontList, func(i, j int) bool {
|
||||
return fontList[i].Name < fontList[j].Name
|
||||
})
|
||||
resp.Data = map[string]any{
|
||||
"fonts": fontList,
|
||||
}
|
||||
resp.Success = true
|
||||
return
|
||||
}
|
||||
|
|
|
@ -20,12 +20,13 @@ const data = reactive({
|
|||
})
|
||||
|
||||
const tabStore = useTabStore()
|
||||
const prefStore = usePreferencesStore()
|
||||
// const preferences = ref({})
|
||||
// provide('preferences', preferences)
|
||||
const i18n = useI18n()
|
||||
|
||||
onMounted(async () => {
|
||||
const prefStore = usePreferencesStore()
|
||||
await prefStore.loadFontList()
|
||||
await prefStore.loadPreferences()
|
||||
await nextTick(() => {
|
||||
i18n.locale.value = get(prefStore.general, 'language', 'en')
|
||||
|
@ -67,7 +68,7 @@ const dragging = computed(() => {
|
|||
|
||||
<template>
|
||||
<!-- app content-->
|
||||
<div id="app-container" :class="{ dragging }" class="flex-box-h">
|
||||
<div id="app-container" :class="{ dragging }" class="flex-box-h" :style="prefStore.generalFont">
|
||||
<nav-menu v-model:value="tabStore.nav" :width="data.navMenuWidth" />
|
||||
<!-- structure page-->
|
||||
<div v-show="tabStore.nav === 'structure'" class="flex-box-h flex-item-expand">
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script setup>
|
||||
import { reactive, ref, watch } from 'vue'
|
||||
import { ref, watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import useDialog from '../../stores/dialog'
|
||||
import usePreferencesStore from '../../stores/preferences.js'
|
||||
|
@ -7,25 +7,30 @@ import { useMessage } from 'naive-ui'
|
|||
|
||||
const prefStore = usePreferencesStore()
|
||||
|
||||
const fontOption = [
|
||||
{
|
||||
label: 'JetBrains Mono',
|
||||
value: 'JetBrains Mono',
|
||||
},
|
||||
]
|
||||
|
||||
const prevPreferences = ref({})
|
||||
const tab = ref('general')
|
||||
const formLabelWidth = '80px'
|
||||
const dialogStore = useDialog()
|
||||
const i18n = useI18n()
|
||||
const message = useMessage()
|
||||
const loading = ref(false)
|
||||
|
||||
watch(
|
||||
() => dialogStore.preferencesDialogVisible,
|
||||
(visible) => {
|
||||
async (visible) => {
|
||||
if (visible) {
|
||||
prefStore.loadPreferences()
|
||||
try {
|
||||
loading.value = true
|
||||
tab.value = 'general'
|
||||
await prefStore.loadFontList()
|
||||
await prefStore.loadPreferences()
|
||||
prevPreferences.value = {
|
||||
general: prefStore.general,
|
||||
editor: prefStore.editor,
|
||||
}
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
@ -44,15 +49,10 @@ watch(
|
|||
(lang) => (i18n.locale.value = lang)
|
||||
)
|
||||
|
||||
watch(
|
||||
() => prefStore.general.font,
|
||||
(font) => {}
|
||||
)
|
||||
|
||||
const onClose = () => {
|
||||
dialogStore.closePreferencesDialog()
|
||||
// restore to old preferences
|
||||
prefStore.restorePreferences()
|
||||
prefStore.resetToLastPreferences()
|
||||
dialogStore.closePreferencesDialog()
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -84,7 +84,7 @@ const onClose = () => {
|
|||
/>
|
||||
</n-form-item>
|
||||
<n-form-item :label="$t('font')" required>
|
||||
<n-select v-model:value="prefStore.general.font" :options="fontOption" filterable />
|
||||
<n-select v-model:value="prefStore.general.font" :options="prefStore.fontOption" filterable />
|
||||
</n-form-item>
|
||||
<n-form-item :label="$t('font_size')">
|
||||
<n-input-number v-model:value="prefStore.general.fontSize" :max="65535" :min="1" />
|
||||
|
@ -115,11 +115,11 @@ const onClose = () => {
|
|||
label-align="right"
|
||||
label-placement="left"
|
||||
>
|
||||
<n-form-item :label="$t('font')" :label-width="formLabelWidth" required>
|
||||
<n-select v-model="prefStore.editor.font" :options="fontOption" filterable />
|
||||
<n-form-item :label="$t('font')" required>
|
||||
<n-select v-model:value="prefStore.editor.font" :options="prefStore.fontOption" filterable />
|
||||
</n-form-item>
|
||||
<n-form-item :label="$t('font_size')" :label-width="formLabelWidth">
|
||||
<n-input-number v-model="prefStore.editor.fontSize" :max="65535" :min="1" />
|
||||
<n-form-item :label="$t('font_size')">
|
||||
<n-input-number v-model:value="prefStore.editor.fontSize" :max="65535" :min="1" />
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
</n-tab-pane>
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
"success": "Success",
|
||||
"warning": "Warning",
|
||||
"save": "Save",
|
||||
"none": "None",
|
||||
"new_conn": "Add New Connection",
|
||||
"new_group": "Add New Group",
|
||||
"rename_group": "Rename Group",
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
"success": "成功",
|
||||
"warning": "警告",
|
||||
"save": "保存",
|
||||
"none": "无",
|
||||
"new_conn": "添加新连接",
|
||||
"new_group": "添加新分组",
|
||||
"rename_group": "重命名分组",
|
||||
|
|
|
@ -1,9 +1,30 @@
|
|||
import { defineStore } from 'pinia'
|
||||
import { lang } from '../langs/index.js'
|
||||
import { camelCase, isObject, map, set, snakeCase, split } from 'lodash'
|
||||
import { GetPreferences, RestorePreferences, SetPreferences } from '../../wailsjs/go/services/preferencesService.js'
|
||||
import { camelCase, clone, find, isEmpty, isObject, map, set, snakeCase, split } from 'lodash'
|
||||
import {
|
||||
GetFontList,
|
||||
GetPreferences,
|
||||
RestorePreferences,
|
||||
SetPreferences,
|
||||
} from '../../wailsjs/go/services/preferencesService.js'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
const usePreferencesStore = defineStore('preferences', {
|
||||
/**
|
||||
* @typedef {Object} FontItem
|
||||
* @property {string} name
|
||||
* @property {string} path
|
||||
*/
|
||||
/**
|
||||
* @typedef {Object} Preferences
|
||||
* @property {Object} general
|
||||
* @property {Object} editor
|
||||
* @property {FontItem[]} fontList
|
||||
*/
|
||||
/**
|
||||
*
|
||||
* @returns {Preferences}
|
||||
*/
|
||||
state: () => ({
|
||||
general: {
|
||||
language: 'en',
|
||||
|
@ -17,6 +38,8 @@ const usePreferencesStore = defineStore('preferences', {
|
|||
font: '',
|
||||
fontSize: 14,
|
||||
},
|
||||
lastPref: {},
|
||||
fontList: [],
|
||||
}),
|
||||
getters: {
|
||||
getSeparator() {
|
||||
|
@ -33,6 +56,34 @@ const usePreferencesStore = defineStore('preferences', {
|
|||
label: `${value['lang_name']}`,
|
||||
}))
|
||||
},
|
||||
|
||||
fontOption() {
|
||||
const i18n = useI18n()
|
||||
const option = map(this.fontList, (font) => ({
|
||||
value: font.name,
|
||||
label: font.name,
|
||||
path: font.path,
|
||||
}))
|
||||
option.splice(0, 0, {
|
||||
value: '',
|
||||
label: i18n.t('none'),
|
||||
path: '',
|
||||
})
|
||||
return option
|
||||
},
|
||||
|
||||
generalFont() {
|
||||
const fontStyle = {
|
||||
fontSize: this.general.fontSize + 'px',
|
||||
}
|
||||
if (!isEmpty(this.general.font) && this.general.font !== 'none') {
|
||||
const font = find(this.fontList, { name: this.general.font })
|
||||
if (font != null) {
|
||||
fontStyle['fontFamily'] = `${font.name}`
|
||||
}
|
||||
}
|
||||
return fontStyle
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
_applyPreferences(data) {
|
||||
|
@ -49,10 +100,26 @@ const usePreferencesStore = defineStore('preferences', {
|
|||
async loadPreferences() {
|
||||
const { success, data } = await GetPreferences()
|
||||
if (success) {
|
||||
this.lastPref = clone(data)
|
||||
this._applyPreferences(data)
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* load system font list
|
||||
* @returns {Promise<string[]>}
|
||||
*/
|
||||
async loadFontList() {
|
||||
const { success, data } = await GetFontList()
|
||||
if (success) {
|
||||
const { fonts = [] } = data
|
||||
this.fontList = fonts
|
||||
} else {
|
||||
this.fontList = []
|
||||
}
|
||||
return this.fontList
|
||||
},
|
||||
|
||||
/**
|
||||
* save preferences to local
|
||||
* @returns {Promise<boolean>}
|
||||
|
@ -62,7 +129,8 @@ const usePreferencesStore = defineStore('preferences', {
|
|||
const result = {}
|
||||
for (const key in obj) {
|
||||
if (isObject(obj[key])) {
|
||||
// TODO: perform sub object
|
||||
const subResult = obj2Map(`${prefix}.${snakeCase(key)}`, obj[key])
|
||||
Object.assign(result, subResult)
|
||||
} else {
|
||||
result[`${prefix}.${snakeCase(key)}`] = obj[key]
|
||||
}
|
||||
|
@ -74,6 +142,16 @@ const usePreferencesStore = defineStore('preferences', {
|
|||
return success === true
|
||||
},
|
||||
|
||||
/**
|
||||
* reset to last loaded preferences
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async resetToLastPreferences() {
|
||||
if (!isEmpty(this.lastPref)) {
|
||||
this._applyPreferences(this.lastPref)
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* restore preferences to default
|
||||
* @returns {Promise<boolean>}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||
// This file is automatically generated. DO NOT EDIT
|
||||
import {types} from '../models';
|
||||
|
||||
export function GetFontList():Promise<types.JSResp>;
|
||||
|
||||
export function GetPreferences():Promise<types.JSResp>;
|
||||
|
||||
export function RestorePreferences():Promise<types.JSResp>;
|
||||
|
||||
export function SetPreferences(arg1:{[key: string]: any}):Promise<types.JSResp>;
|
|
@ -0,0 +1,19 @@
|
|||
// @ts-check
|
||||
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||
// This file is automatically generated. DO NOT EDIT
|
||||
|
||||
export function GetFontList() {
|
||||
return window['go']['services']['preferencesService']['GetFontList']();
|
||||
}
|
||||
|
||||
export function GetPreferences() {
|
||||
return window['go']['services']['preferencesService']['GetPreferences']();
|
||||
}
|
||||
|
||||
export function RestorePreferences() {
|
||||
return window['go']['services']['preferencesService']['RestorePreferences']();
|
||||
}
|
||||
|
||||
export function SetPreferences(arg1) {
|
||||
return window['go']['services']['preferencesService']['SetPreferences'](arg1);
|
||||
}
|
3
go.mod
3
go.mod
|
@ -3,6 +3,7 @@ module tinyrdm
|
|||
go 1.20
|
||||
|
||||
require (
|
||||
github.com/adrg/sysfont v0.1.2
|
||||
github.com/bytedance/sonic v1.9.2
|
||||
github.com/google/go-cmp v0.5.9
|
||||
github.com/redis/go-redis/v9 v9.0.5
|
||||
|
@ -12,6 +13,8 @@ require (
|
|||
)
|
||||
|
||||
require (
|
||||
github.com/adrg/strutil v0.2.2 // indirect
|
||||
github.com/adrg/xdg v0.3.0 // indirect
|
||||
github.com/bep/debounce v1.2.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
|
||||
|
|
7
go.sum
7
go.sum
|
@ -1,3 +1,9 @@
|
|||
github.com/adrg/strutil v0.2.2 h1:XSd9+o2xaOon2oRum0JymNT+f0nfLiAiDzGOcjcIsMI=
|
||||
github.com/adrg/strutil v0.2.2/go.mod h1:EF2fjOFlGTepljfI+FzgTG13oXthR7ZAil9/aginnNQ=
|
||||
github.com/adrg/sysfont v0.1.2 h1:MSU3KREM4RhsQ+7QgH7wPEPTgAgBIz0Hw6Nd4u7QgjE=
|
||||
github.com/adrg/sysfont v0.1.2/go.mod h1:6d3l7/BSjX9VaeXWJt9fcrftFaD/t7l11xgSywCPZGk=
|
||||
github.com/adrg/xdg v0.3.0 h1:BO+k4wFj0IoTolBF1Apn8oZrX3LQrEbBA8+/9vyW9J4=
|
||||
github.com/adrg/xdg v0.3.0/go.mod h1:7I2hH/IT30IsupOpKZ5ue7/qNi3CoKzD6tL3HwpaRMQ=
|
||||
github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY=
|
||||
github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0=
|
||||
github.com/bsm/ginkgo/v2 v2.7.0 h1:ItPMPH90RbmZJt5GtkcNvIRuGEdwlBItdNVoyzaNQao=
|
||||
|
@ -64,6 +70,7 @@ github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXn
|
|||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
|
|
Loading…
Reference in New Issue