From eba3a43805b5777aebb677df88bf5c8533743ead Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Wed, 26 Jun 2024 14:17:22 +0300 Subject: better font control custom input --- src/components/font_control/font_control.js | 60 +++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 17 deletions(-) (limited to 'src/components/font_control/font_control.js') diff --git a/src/components/font_control/font_control.js b/src/components/font_control/font_control.js index 92ee3f30..52c3e70a 100644 --- a/src/components/font_control/font_control.js +++ b/src/components/font_control/font_control.js @@ -1,9 +1,22 @@ import { set } from 'lodash' import Select from '../select/select.vue' +import Checkbox from 'src/components/checkbox/checkbox.vue' +import Popover from 'src/components/popover/popover.vue' + +import { library } from '@fortawesome/fontawesome-svg-core' +import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons' + +library.add( + faExclamationTriangle +) + +const PRESET_FONTS = new Set(['serif', 'sans-serif', 'monospace', 'inherit']) export default { components: { - Select + Select, + Checkbox, + Popover }, props: [ 'name', 'label', 'modelValue', 'fallback', 'options', 'no-inherit' @@ -11,10 +24,11 @@ export default { emits: ['update:modelValue'], data () { return { - lValue: this.modelValue, + localValue: this.modelValue, + customFamily: '', availableOptions: [ this.noInherit ? '' : 'inherit', - 'custom', + 'local', ...(this.options || []), 'serif', 'monospace', @@ -23,40 +37,52 @@ export default { } }, beforeUpdate () { - this.lValue = this.modelValue + this.localValue = this.modelValue }, computed: { present () { - return typeof this.lValue !== 'undefined' + return typeof this.localValue !== 'undefined' }, - dValue () { - return this.lValue || this.fallback || {} + defaultValue () { + return this.localValue || this.fallback || {} }, family: { get () { - return this.dValue.family + return this.defaultValue.family + }, + set (v) { + set(this.localValue, 'family', v) + this.$emit('update:modelValue', this.localValue) + } + }, + familyCustom: { + get () { + return this.customFamily }, set (v) { - set(this.lValue, 'family', v) - this.$emit('update:modelValue', this.lValue) + this.customFamily = v + if (!PRESET_FONTS.has(this.customFamily)) { + set(this.localValue, 'family', v) + this.$emit('update:modelValue', this.customFamily) + } } }, + invalidCustom () { + return PRESET_FONTS.has(this.customFamily) + }, isCustom () { - return this.preset === 'custom' + return !PRESET_FONTS.has(this.family) }, preset: { get () { - if (this.family === 'serif' || - this.family === 'sans-serif' || - this.family === 'monospace' || - this.family === 'inherit') { + if (PRESET_FONTS.has(this.family)) { return this.family } else { - return 'custom' + return 'local' } }, set (v) { - this.family = v === 'custom' ? '' : v + this.family = v === 'local' ? '' : v } } } -- cgit v1.2.3-70-g09d2 From d5d37849ea6712fa00a077cb219800553b5689ab Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Wed, 26 Jun 2024 17:05:59 +0300 Subject: font selector with proper styles and functionality + local font selector --- src/App.scss | 35 ++++--- src/components/font_control/font_control.js | 61 +++++++++--- src/components/font_control/font_control.vue | 102 +++++++++++++++++---- .../settings_modal/tabs/theme_tab/theme_tab.scss | 4 + src/i18n/en.json | 9 +- src/modules/interface.js | 24 ++++- 6 files changed, 185 insertions(+), 50 deletions(-) (limited to 'src/components/font_control/font_control.js') diff --git a/src/App.scss b/src/App.scss index 6b8875bf..9225075b 100644 --- a/src/App.scss +++ b/src/App.scss @@ -375,7 +375,6 @@ nav { user-select: none; color: var(--text); border: none; - border-radius: var(--roundness); cursor: pointer; background-color: var(--background); box-shadow: var(--shadow); @@ -511,7 +510,6 @@ textarea { --_padding: 0.5em; border: none; - border-radius: var(--roundness); background-color: var(--background); color: var(--text); box-shadow: var(--shadow); @@ -617,6 +615,17 @@ textarea { } } +.input, +.button-default { + --_roundness-left: var(--roundness); + --_roundness-right: var(--roundness); + + border-top-left-radius: var(--_roundness-left); + border-bottom-left-radius: var(--_roundness-left); + border-top-right-radius: var(--_roundness-right); + border-bottom-right-radius: var(--_roundness-right); +} + // Textareas should have stock line-height + vertical padding instead of huge line-height textarea.input { padding: var(--_padding); @@ -662,22 +671,20 @@ option { display: inline-flex; vertical-align: middle; - button, - .button-dropdown { + > * { + --_roundness-left: 0; + --_roundness-right: 0; + position: relative; flex: 1 1 auto; + } - &:not(:last-child), - &:not(:last-child) .button-default { - border-top-right-radius: 0; - border-bottom-right-radius: 0; - } + > *:first-child { + --_roundness-left: var(--roundness); + } - &:not(:first-child), - &:not(:first-child) .button-default { - border-top-left-radius: 0; - border-bottom-left-radius: 0; - } + > *:last-child { + --_roundness-right: var(--roundness); } } diff --git a/src/components/font_control/font_control.js b/src/components/font_control/font_control.js index 52c3e70a..1e33338f 100644 --- a/src/components/font_control/font_control.js +++ b/src/components/font_control/font_control.js @@ -1,13 +1,19 @@ -import { set } from 'lodash' +import { set, clone } from 'lodash' import Select from '../select/select.vue' import Checkbox from 'src/components/checkbox/checkbox.vue' import Popover from 'src/components/popover/popover.vue' import { library } from '@fortawesome/fontawesome-svg-core' -import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons' +import { + faExclamationTriangle, + faKeyboard, + faFont +} from '@fortawesome/free-solid-svg-icons' library.add( - faExclamationTriangle + faExclamationTriangle, + faKeyboard, + faFont ) const PRESET_FONTS = new Set(['serif', 'sans-serif', 'monospace', 'inherit']) @@ -24,20 +30,38 @@ export default { emits: ['update:modelValue'], data () { return { - localValue: this.modelValue, - customFamily: '', + manualEntry: true, + localValue: clone(this.modelValue), + familyCustomLocal: null, availableOptions: [ this.noInherit ? '' : 'inherit', - 'local', - ...(this.options || []), 'serif', + 'sans-serif', 'monospace', - 'sans-serif' + 'local', + ...(this.options || []) ].filter(_ => _) } }, beforeUpdate () { - this.localValue = this.modelValue + this.localValue = clone(this.modelValue) + if (this.familyCustomLocal === null && !this.isInvalidFamily(this.modelValue?.family)) { + this.familyCustomLocal = this.modelValue?.family + } + }, + methods: { + lookupLocalFonts () { + if (!this.fontsList) { + this.$store.dispatch('queryLocalFonts') + } + this.toggleManualEntry() + }, + isInvalidFamily (value) { + return PRESET_FONTS.has(value) || (value === '') + }, + toggleManualEntry () { + this.manualEntry = !this.manualEntry + } }, computed: { present () { @@ -46,32 +70,39 @@ export default { defaultValue () { return this.localValue || this.fallback || {} }, + fontsListCapable () { + return this.$store.state.interface.browserSupport.localFonts + }, + fontsList () { + return this.$store.state.interface.localFonts + }, family: { get () { return this.defaultValue.family }, set (v) { + this.familyCustomLocal = '' set(this.localValue, 'family', v) this.$emit('update:modelValue', this.localValue) } }, familyCustom: { get () { - return this.customFamily + return this.familyCustomLocal }, set (v) { - this.customFamily = v - if (!PRESET_FONTS.has(this.customFamily)) { + this.familyCustomLocal = v + if (!this.isInvalidFamily(v)) { set(this.localValue, 'family', v) - this.$emit('update:modelValue', this.customFamily) + this.$emit('update:modelValue', this.localValue) } } }, invalidCustom () { - return PRESET_FONTS.has(this.customFamily) + return this.isInvalidFamily(this.familyCustomLocal) }, isCustom () { - return !PRESET_FONTS.has(this.family) + return !PRESET_FONTS.has(this.defaultValue.family) }, preset: { get () { diff --git a/src/components/font_control/font_control.vue b/src/components/font_control/font_control.vue index e73862a0..f1b126be 100644 --- a/src/components/font_control/font_control.vue +++ b/src/components/font_control/font_control.vue @@ -10,15 +10,6 @@ > {{ label }} - {{ ' ' }} - - {{ $t('settings.style.themes3.define') }} -

+ {{ ' ' }} + + {{ $t('settings.style.themes3.define') }} +

-

- + + + {{ ' ' }} + + + + + + + + .font-control { - input.custom-font { - min-width: 12em; + .custom-font { + min-width: 20em; + max-width: 20em; } } diff --git a/src/components/settings_modal/tabs/theme_tab/theme_tab.scss b/src/components/settings_modal/tabs/theme_tab/theme_tab.scss index 5e633120..4cb37c1e 100644 --- a/src/components/settings_modal/tabs/theme_tab/theme_tab.scss +++ b/src/components/settings_modal/tabs/theme_tab/theme_tab.scss @@ -10,6 +10,10 @@ margin-right: 0.25em; } + .btn-group .btn { + margin: 0; + } + .style-control { display: flex; align-items: baseline; diff --git a/src/i18n/en.json b/src/i18n/en.json index bd18c6ef..4b216165 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -746,14 +746,19 @@ "more_settings": "More settings", "style": { "themes3": { - "define": "Include in theme", + "define": "Override", "font": { "local": "Local font (must be installed on computer)", "serif": "Serif (browser default)", "sans-serif": "Sans-serif (browser default)", "monospace": "Monospace (browser default)", "inherit": "Same as parent component", - "invalid_custom_reserved": "This is a reserved font name, it will not be saved as custom font - use dropdown instead" + "invalid_custom_reserved": "Empty or reserved font name, it will not be saved as custom font - use dropdown instead", + "font_list_unavailable": "Couldn't get locally installed fonts: {error}", + "lookup_local_fonts": "Load list of fonts installed on this computer", + "enter_manually": "Enter font name family manually", + "entry": "Font's {fontFamily}", + "select": "Select local font" } }, "switcher": { diff --git a/src/modules/interface.js b/src/modules/interface.js index e21b4204..bee503c5 100644 --- a/src/modules/interface.js +++ b/src/modules/interface.js @@ -1,4 +1,5 @@ const defaultState = { + localFonts: null, themeApplied: false, temporaryChangesTimeoutId: null, // used for temporary options that revert after a timeout temporaryChangesConfirm: () => {}, // used for applying temporary options @@ -17,7 +18,8 @@ const defaultState = { cssFilter: window.CSS && window.CSS.supports && ( window.CSS.supports('filter', 'drop-shadow(0 0)') || window.CSS.supports('-webkit-filter', 'drop-shadow(0 0)') - ) + ), + localFonts: typeof window.queryLocalFonts === 'function' }, layoutType: 'normal', globalNotices: [], @@ -104,6 +106,10 @@ const interfaceMod = { }, setLastTimeline (state, value) { state.lastTimeline = value + }, + setFontsList (state, value) { + console.log(value) + state.localFonts = new Set(value.map(font => font.family)) } }, actions: { @@ -178,6 +184,22 @@ const interfaceMod = { commit('setLayoutType', wideLayout ? 'wide' : normalOrMobile) } }, + queryLocalFonts ({ commit, dispatch }) { + window + .queryLocalFonts() + .then((fonts) => { + commit('setFontsList', fonts) + }) + .catch((e) => { + dispatch('pushGlobalNotice', { + messageKey: 'settings.style.themes3.font.font_list_unavailable', + messageArgs: { + error: e + }, + level: 'error' + }) + }) + }, setLastTimeline ({ commit }, value) { commit('setLastTimeline', value) } -- cgit v1.2.3-70-g09d2 From 925fd863fe2be2cd273507dbb2688efb2d0ae07e Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Thu, 27 Jun 2024 00:34:25 +0300 Subject: Massively simplify and improve font input component --- src/components/font_control/font_control.js | 77 ++------------ src/components/font_control/font_control.vue | 147 +++++++++++++-------------- src/i18n/en.json | 20 ++-- src/modules/interface.js | 9 +- 4 files changed, 99 insertions(+), 154 deletions(-) (limited to 'src/components/font_control/font_control.js') diff --git a/src/components/font_control/font_control.js b/src/components/font_control/font_control.js index 1e33338f..f6f45c8c 100644 --- a/src/components/font_control/font_control.js +++ b/src/components/font_control/font_control.js @@ -1,4 +1,3 @@ -import { set, clone } from 'lodash' import Select from '../select/select.vue' import Checkbox from 'src/components/checkbox/checkbox.vue' import Popover from 'src/components/popover/popover.vue' @@ -16,8 +15,6 @@ library.add( faFont ) -const PRESET_FONTS = new Set(['serif', 'sans-serif', 'monospace', 'inherit']) - export default { components: { Select, @@ -27,94 +24,36 @@ export default { props: [ 'name', 'label', 'modelValue', 'fallback', 'options', 'no-inherit' ], + mounted () { + this.$store.dispatch('queryLocalFonts') + }, emits: ['update:modelValue'], data () { return { manualEntry: true, - localValue: clone(this.modelValue), - familyCustomLocal: null, availableOptions: [ this.noInherit ? '' : 'inherit', 'serif', 'sans-serif', 'monospace', - 'local', ...(this.options || []) ].filter(_ => _) } }, - beforeUpdate () { - this.localValue = clone(this.modelValue) - if (this.familyCustomLocal === null && !this.isInvalidFamily(this.modelValue?.family)) { - this.familyCustomLocal = this.modelValue?.family - } - }, methods: { - lookupLocalFonts () { - if (!this.fontsList) { - this.$store.dispatch('queryLocalFonts') - } - this.toggleManualEntry() - }, - isInvalidFamily (value) { - return PRESET_FONTS.has(value) || (value === '') - }, toggleManualEntry () { this.manualEntry = !this.manualEntry } }, computed: { present () { - return typeof this.localValue !== 'undefined' - }, - defaultValue () { - return this.localValue || this.fallback || {} - }, - fontsListCapable () { - return this.$store.state.interface.browserSupport.localFonts - }, - fontsList () { - return this.$store.state.interface.localFonts - }, - family: { - get () { - return this.defaultValue.family - }, - set (v) { - this.familyCustomLocal = '' - set(this.localValue, 'family', v) - this.$emit('update:modelValue', this.localValue) - } - }, - familyCustom: { - get () { - return this.familyCustomLocal - }, - set (v) { - this.familyCustomLocal = v - if (!this.isInvalidFamily(v)) { - set(this.localValue, 'family', v) - this.$emit('update:modelValue', this.localValue) - } - } - }, - invalidCustom () { - return this.isInvalidFamily(this.familyCustomLocal) + return typeof this.modelValue !== 'undefined' }, - isCustom () { - return !PRESET_FONTS.has(this.defaultValue.family) + localFontsList () { + return this.$store.state.interface.localFonts?.values() }, - preset: { - get () { - if (PRESET_FONTS.has(this.family)) { - return this.family - } else { - return 'local' - } - }, - set (v) { - this.family = v === 'local' ? '' : v - } + localFontsSize () { + return this.$store.state.interface.localFonts?.size } } } diff --git a/src/components/font_control/font_control.vue b/src/components/font_control/font_control.vue index f1b126be..f3ab41a2 100644 --- a/src/components/font_control/font_control.vue +++ b/src/components/font_control/font_control.vue @@ -10,42 +10,18 @@ > {{ label }} -

- - {{ ' ' }} - - {{ $t('settings.style.themes3.define') }} - -

-

- + {{ ' ' }} + + {{ $t('settings.style.themes3.define') }} + +

+ {{ ' ' }} - + - + - + - - - - - -

diff --git a/src/i18n/en.json b/src/i18n/en.json index 4b216165..d995163a 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -748,17 +748,21 @@ "themes3": { "define": "Override", "font": { - "local": "Local font (must be installed on computer)", - "serif": "Serif (browser default)", - "sans-serif": "Sans-serif (browser default)", - "monospace": "Monospace (browser default)", - "inherit": "Same as parent component", - "invalid_custom_reserved": "Empty or reserved font name, it will not be saved as custom font - use dropdown instead", + "group-builtin": "Browser default fonts", + "builtin" : { + "serif": "Serif", + "sans-serif": "Sans-serif", + "monospace": "Monospace", + "inherit": "Unchanged" + }, + "group-local": "Locally installed fonts", + "local-unavailable1": "List of locally installed fonts unavailalbe", + "local-unavailable2": "Use manual entry to specify custom font", "font_list_unavailable": "Couldn't get locally installed fonts: {error}", "lookup_local_fonts": "Load list of fonts installed on this computer", "enter_manually": "Enter font name family manually", - "entry": "Font's {fontFamily}", - "select": "Select local font" + "entry": "Enter {fontFamily}", + "select": "Select font" } }, "switcher": { diff --git a/src/modules/interface.js b/src/modules/interface.js index bee503c5..2ccfeef3 100644 --- a/src/modules/interface.js +++ b/src/modules/interface.js @@ -108,7 +108,6 @@ const interfaceMod = { state.lastTimeline = value }, setFontsList (state, value) { - console.log(value) state.localFonts = new Set(value.map(font => font.family)) } }, @@ -184,10 +183,16 @@ const interfaceMod = { commit('setLayoutType', wideLayout ? 'wide' : normalOrMobile) } }, - queryLocalFonts ({ commit, dispatch }) { + queryLocalFonts ({ commit, dispatch, state }) { + if (state.localFonts !== null) return + commit('setFontsList', []) + if (!state.browserSupport.localFonts) { + return + } window .queryLocalFonts() .then((fonts) => { + console.log(fonts) commit('setFontsList', fonts) }) .catch((e) => { -- cgit v1.2.3-70-g09d2 From 80cbf29bdf7c6cd3695d1e4cf49a8e38bff847ed Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Thu, 27 Jun 2024 00:59:24 +0300 Subject: fields for user font overrides --- src/components/font_control/font_control.js | 2 +- .../settings_modal/tabs/appearance_tab.js | 8 +++- .../settings_modal/tabs/appearance_tab.vue | 45 ++++++++++++++++++++++ src/i18n/en.json | 1 + src/modules/config.js | 2 + src/modules/instance.js | 1 + 6 files changed, 57 insertions(+), 2 deletions(-) (limited to 'src/components/font_control/font_control.js') diff --git a/src/components/font_control/font_control.js b/src/components/font_control/font_control.js index f6f45c8c..08d0907e 100644 --- a/src/components/font_control/font_control.js +++ b/src/components/font_control/font_control.js @@ -30,7 +30,7 @@ export default { emits: ['update:modelValue'], data () { return { - manualEntry: true, + manualEntry: false, availableOptions: [ this.noInherit ? '' : 'inherit', 'serif', diff --git a/src/components/settings_modal/tabs/appearance_tab.js b/src/components/settings_modal/tabs/appearance_tab.js index d9a0429a..3776464a 100644 --- a/src/components/settings_modal/tabs/appearance_tab.js +++ b/src/components/settings_modal/tabs/appearance_tab.js @@ -4,6 +4,8 @@ import IntegerSetting from '../helpers/integer_setting.vue' import FloatSetting from '../helpers/float_setting.vue' import UnitSetting, { defaultHorizontalUnits } from '../helpers/unit_setting.vue' +import FontControl from 'src/components/font_control/font_control.vue' + import SharedComputedObject from '../helpers/shared_computed_object.js' import ProfileSettingIndicator from '../helpers/profile_setting_indicator.vue' import { library } from '@fortawesome/fontawesome-svg-core' @@ -36,12 +38,16 @@ const AppearanceTab = { IntegerSetting, FloatSetting, UnitSetting, - ProfileSettingIndicator + ProfileSettingIndicator, + FontControl }, computed: { horizontalUnits () { return defaultHorizontalUnits }, + fontsOverride () { + return this.$store.getters.mergedConfig.fontsOverride + }, columns () { const mode = this.$store.getters.mergedConfig.thirdColumnMode diff --git a/src/components/settings_modal/tabs/appearance_tab.vue b/src/components/settings_modal/tabs/appearance_tab.vue index 5356292e..fb24cc6b 100644 --- a/src/components/settings_modal/tabs/appearance_tab.vue +++ b/src/components/settings_modal/tabs/appearance_tab.vue @@ -34,6 +34,51 @@ +
  • +

    {{ $t('settings.style.interface_font_user_override') }}

    +
      +
    • + +
    • +
    • + +
    • +
    • + +
    • +
    • + +
    • +
    +
  • Date: Sun, 21 Jul 2024 23:45:21 +0300 Subject: fix font selector losing list of local fonts when selecting one --- src/components/font_control/font_control.js | 5 +++-- src/components/font_control/font_control.vue | 2 +- src/modules/interface.js | 3 ++- 3 files changed, 6 insertions(+), 4 deletions(-) (limited to 'src/components/font_control/font_control.js') diff --git a/src/components/font_control/font_control.js b/src/components/font_control/font_control.js index 08d0907e..13daa095 100644 --- a/src/components/font_control/font_control.js +++ b/src/components/font_control/font_control.js @@ -50,10 +50,11 @@ export default { return typeof this.modelValue !== 'undefined' }, localFontsList () { - return this.$store.state.interface.localFonts?.values() + console.log('FONTLIST', this.$store.state.interface.localFonts?.values()) + return this.$store.state.interface.localFonts }, localFontsSize () { - return this.$store.state.interface.localFonts?.size + return this.$store.state.interface.localFonts?.length } } } diff --git a/src/components/font_control/font_control.vue b/src/components/font_control/font_control.vue index b5423a8c..fca3b360 100644 --- a/src/components/font_control/font_control.vue +++ b/src/components/font_control/font_control.vue @@ -82,7 +82,7 @@