commit: 925fd863fe2be2cd273507dbb2688efb2d0ae07e
parent d5d37849ea6712fa00a077cb219800553b5689ab
Author: Henry Jameson <me@hjkos.com>
Date: Thu, 27 Jun 2024 00:34:25 +0300
Massively simplify and improve font input component
Diffstat:
4 files changed, 99 insertions(+), 154 deletions(-)
diff --git 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
@@ -10,42 +10,18 @@
>
{{ label }}
</label>
- <p>
- <Select
- :id="name + '-font-switcher'"
- v-model="preset"
- :disabled="!present"
- class="font-switcher"
- >
- <option
- v-for="option in availableOptions"
- :key="option"
- :value="option"
- >
- {{ $t('settings.style.themes3.font.' + option) }}
- </option>
- </Select>
- {{ ' ' }}
- <Checkbox
- v-if="typeof fallback !== 'undefined'"
- :id="name + '-o'"
- :modelValue="present"
- @change="$emit('update:modelValue', typeof modelValue === 'undefined' ? fallback : undefined)"
- >
- {{ $t('settings.style.themes3.define') }}
- </Checkbox>
- </p>
- <p v-if="isCustom">
- <label
- v-if="fontsList !== null && !manualEntry"
- :id="name + '-label'"
- :for="preset === 'custom' ? name : name + '-font-switcher'"
- class="label"
- >
- {{ $t('settings.style.themes3.font.select') }}
- </label>
+ {{ ' ' }}
+ <Checkbox
+ v-if="typeof fallback !== 'undefined'"
+ :id="name + '-o'"
+ :modelValue="present"
+ @change="$emit('update:modelValue', typeof modelValue === 'undefined' ? fallback : undefined)"
+ >
+ {{ $t('settings.style.themes3.define') }}
+ </Checkbox>
+ <p v-if="modelValue?.family">
<label
- v-else
+ v-if="manualEntry"
:id="name + '-label'"
:for="preset === 'custom' ? name : name + '-font-switcher'"
class="label"
@@ -59,12 +35,22 @@
</template>
</i18n-t>
</label>
+ <label
+ v-else
+ :id="name + '-label'"
+ :for="preset === 'custom' ? name : name + '-font-switcher'"
+ class="label"
+ >
+ {{ $t('settings.style.themes3.font.select') }}
+ </label>
{{ ' ' }}
- <span class="btn-group">
+ <span
+ v-if="manualEntry"
+ class="btn-group"
+ >
<button
- v-if="fontsListCapable && (fontsList === null || manualEntry)"
class="btn button-default"
- @click="lookupLocalFonts"
+ @click="toggleManualEntry"
:title="$t('settings.style.themes3.font.lookup_local_fonts')"
>
<FAIcon
@@ -72,17 +58,19 @@
icon="font"
/>
</button>
- <input
- v-if="fontsLists === null || manualEntry"
- :id="name"
- v-model="familyCustom"
- class="input custom-font"
- type="text"
- >
+ <input
+ :id="name"
+ :model-value="modelValue.family"
+ class="input custom-font"
+ type="text"
+ @update:modelValue="$emit('update:modelValue', { ...(modelValue || {}), family: $event.target.value })"
+ >
</span>
- <span class="btn-group">
+ <span
+ v-else
+ class="btn-group"
+ >
<button
- v-if="fontsList !== null && !manualEntry"
class="btn button-default"
@click="toggleManualEntry"
:title="$t('settings.style.themes3.font.enter_manually')"
@@ -93,40 +81,49 @@
/>
</button>
<Select
- v-if="fontsList !== null && !manualEntry"
:id="name + '-local-font-switcher'"
- v-model="familyCustom"
+ :model-value="modelValue.family"
class="custom-font"
+ @update:modelValue="$emit('update:modelValue', { ...(modelValue || {}), family: $event.target.value })"
>
- <option
- v-for="option in fontsList.values()"
- :key="option"
- :value="option"
- :style="{ fontFamily: option }"
+ <optgroup
+ :label="$t('settings.style.themes3.font.group-builtin')"
+ >
+ <option
+ v-for="option in availableOptions"
+ :key="option"
+ :value="option"
+ :style="{ fontFamily: option === 'inherit' ? null : option }"
+ >
+ {{ $t('settings.style.themes3.font.builtin.' + option) }}
+ </option>
+ </optgroup>
+ <optgroup
+ v-if="localFontsSize > 0"
+ :label="$t('settings.style.themes3.font.group-local')"
+ >
+ <option
+ v-for="option in localFontsList"
+ :key="option"
+ :value="option"
+ :style="{ fontFamily: option }"
+ >
+ {{ option }}
+ </option>
+ </optgroup>
+ <optgroup
+ v-else
+ :label="$t('settings.style.themes3.font.group-local')"
>
- {{ option }}
- </option>
+ <option disabled>
+ {{ $t('settings.style.themes3.font.local-unavailable1') }}
+ </option>
+ <option disabled>
+ {{ $t('settings.style.themes3.font.local-unavailable2') }}
+ </option>
+ </optgroup>
</Select>
</span>
- <span
- v-if="invalidCustom"
- class="InvalidIndicator"
- >
- <Popover
- trigger="hover"
- :trigger-attrs="{ 'aria-label': $t('settings.style.themes3.font.invalid_custom_reserved') }"
- >
- <template #trigger>
-
- <FAIcon icon="exclamation-triangle" />
- </template>
- <template #content>
- <div class="invalid-tooltip">
- {{ $t('settings.style.themes3.font.invalid_custom_reserved') }}
- </div>
- </template>
- </Popover>
- </span>
</p>
</div>
</template>
diff --git 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
@@ -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) => {