feat: add font style preferences support

This commit is contained in:
tiny-craft 2023-07-12 11:48:08 +08:00
parent dd88c617f9
commit 49435848ee
10 changed files with 179 additions and 27 deletions

View File

@ -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
}

View File

@ -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">

View File

@ -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>

View File

@ -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",

View File

@ -5,6 +5,7 @@
"success": "成功",
"warning": "警告",
"save": "保存",
"none": "无",
"new_conn": "添加新连接",
"new_group": "添加新分组",
"rename_group": "重命名分组",

View File

@ -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>}

View File

@ -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>;

View File

@ -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
View File

@ -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
View File

@ -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=