fix: persist font selections across navigation and page reloads
- Use v-model with writable computeds instead of :value+@change so selects re-sync when the options list changes asynchronously - Always include currently chosen fonts in sortedFontFamilies so a selected font not present in .remanso.json fontFamilies still shows in the select - Initialize userSettings instead of returning early in font setters so changes made before async GitHub fetch completes are not silently dropped - Back font choices with localStorage so they survive hard reloads even when PouchDB/IndexedDB fails silently in the web worker
This commit is contained in:
@@ -22,10 +22,28 @@ const DEFAULT_FONT_FAMILIES = [
|
|||||||
const fontFamilies = computed(
|
const fontFamilies = computed(
|
||||||
() => store.userSettings?.fontFamilies ?? DEFAULT_FONT_FAMILIES
|
() => store.userSettings?.fontFamilies ?? DEFAULT_FONT_FAMILIES
|
||||||
)
|
)
|
||||||
const sortedFontFamilies = computed(() =>
|
const sortedFontFamilies = computed(() => {
|
||||||
[...fontFamilies.value].sort((a, b) => a.localeCompare(b))
|
const base = fontFamilies.value
|
||||||
)
|
const extras = [
|
||||||
|
store.userSettings?.chosenTitleFont,
|
||||||
|
store.userSettings?.chosenBodyFont
|
||||||
|
].filter((f): f is string => !!f && !base.includes(f))
|
||||||
|
return [...base, ...extras].sort((a, b) => a.localeCompare(b))
|
||||||
|
})
|
||||||
const fontSizes = Array.from({ length: 7 }, (_, i) => `${9 + i * 2}pt`)
|
const fontSizes = Array.from({ length: 7 }, (_, i) => `${9 + i * 2}pt`)
|
||||||
|
|
||||||
|
const titleFont = computed({
|
||||||
|
get: () => store.userSettings?.chosenTitleFont,
|
||||||
|
set: (value) => store.setTitleFont(value!)
|
||||||
|
})
|
||||||
|
const bodyFont = computed({
|
||||||
|
get: () => store.userSettings?.chosenBodyFont,
|
||||||
|
set: (value) => store.setBodyFont(value!)
|
||||||
|
})
|
||||||
|
const fontSize = computed({
|
||||||
|
get: () => store.userSettings?.chosenFontSize,
|
||||||
|
set: (value) => store.setFontSize(value!)
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -35,8 +53,7 @@ const fontSizes = Array.from({ length: 7 }, (_, i) => `${9 + i * 2}pt`)
|
|||||||
<select
|
<select
|
||||||
id="title-font"
|
id="title-font"
|
||||||
class="select"
|
class="select"
|
||||||
:value="store.userSettings?.chosenTitleFont"
|
v-model="titleFont"
|
||||||
@change="store.setTitleFont(($event.target as HTMLSelectElement).value)"
|
|
||||||
>
|
>
|
||||||
<option v-for="font in sortedFontFamilies" :key="font" :value="font">
|
<option v-for="font in sortedFontFamilies" :key="font" :value="font">
|
||||||
{{ font }}
|
{{ font }}
|
||||||
@@ -47,8 +64,7 @@ const fontSizes = Array.from({ length: 7 }, (_, i) => `${9 + i * 2}pt`)
|
|||||||
<select
|
<select
|
||||||
id="body-font"
|
id="body-font"
|
||||||
class="select"
|
class="select"
|
||||||
:value="store.userSettings?.chosenBodyFont"
|
v-model="bodyFont"
|
||||||
@change="store.setBodyFont(($event.target as HTMLSelectElement).value)"
|
|
||||||
>
|
>
|
||||||
<option v-for="font in sortedFontFamilies" :key="font" :value="font">
|
<option v-for="font in sortedFontFamilies" :key="font" :value="font">
|
||||||
{{ font }}
|
{{ font }}
|
||||||
@@ -62,8 +78,7 @@ const fontSizes = Array.from({ length: 7 }, (_, i) => `${9 + i * 2}pt`)
|
|||||||
<select
|
<select
|
||||||
id="font-size"
|
id="font-size"
|
||||||
class="select"
|
class="select"
|
||||||
:value="store.userSettings?.chosenFontSize"
|
v-model="fontSize"
|
||||||
@change="store.setFontSize(($event.target as HTMLSelectElement).value)"
|
|
||||||
>
|
>
|
||||||
<option v-for="size in fontSizes" :key="size" :value="size">
|
<option v-for="size in fontSizes" :key="size" :value="size">
|
||||||
{{ size }}
|
{{ size }}
|
||||||
|
|||||||
@@ -34,11 +34,37 @@ export const useUserRepoStore = defineStore("USER_REPO_STATE", {
|
|||||||
_requestId: 0
|
_requestId: 0
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
|
_persistFonts() {
|
||||||
|
if (!this.userSettings) return
|
||||||
|
try {
|
||||||
|
const { chosenTitleFont, chosenBodyFont, chosenFontSize, chosenFontFamily } =
|
||||||
|
this.userSettings
|
||||||
|
localStorage.setItem(
|
||||||
|
`remanso:fonts:${this.user}:${this.repo}`,
|
||||||
|
JSON.stringify({ chosenTitleFont, chosenBodyFont, chosenFontSize, chosenFontFamily })
|
||||||
|
)
|
||||||
|
} catch {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
},
|
||||||
async setUserRepo(user: string, repo: string) {
|
async setUserRepo(user: string, repo: string) {
|
||||||
const requestId = ++this._requestId
|
const requestId = ++this._requestId
|
||||||
this.user = user
|
this.user = user
|
||||||
this.repo = repo
|
this.repo = repo
|
||||||
|
|
||||||
|
let lsFonts: Partial<UserSettings> = {}
|
||||||
|
try {
|
||||||
|
const lsRaw = localStorage.getItem(`remanso:fonts:${user}:${repo}`)
|
||||||
|
if (lsRaw) lsFonts = JSON.parse(lsRaw)
|
||||||
|
} catch {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Object.keys(lsFonts).length) {
|
||||||
|
if (!this.userSettings) this.userSettings = { $type: DataType.UserSettings }
|
||||||
|
Object.assign(this.userSettings, lsFonts)
|
||||||
|
}
|
||||||
|
|
||||||
const savedRepoId = generateId(DataType.SavedRepo, `${user}-${repo}`)
|
const savedRepoId = generateId(DataType.SavedRepo, `${user}-${repo}`)
|
||||||
const userSettingsId = `UserSetting-${user}-${repo}`
|
const userSettingsId = `UserSetting-${user}-${repo}`
|
||||||
|
|
||||||
@@ -54,7 +80,8 @@ export const useUserRepoStore = defineStore("USER_REPO_STATE", {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (cachedUserSettings) {
|
if (cachedUserSettings) {
|
||||||
this.userSettings = cachedUserSettings
|
// localStorage font choices take priority over PouchDB cache
|
||||||
|
this.userSettings = { ...cachedUserSettings, ...lsFonts }
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -157,10 +184,11 @@ export const useUserRepoStore = defineStore("USER_REPO_STATE", {
|
|||||||
},
|
},
|
||||||
setFontFamily(fontFamily: string) {
|
setFontFamily(fontFamily: string) {
|
||||||
if (!this.userSettings) {
|
if (!this.userSettings) {
|
||||||
return
|
this.userSettings = { $type: DataType.UserSettings }
|
||||||
}
|
}
|
||||||
this.userSettings.chosenFontFamily = fontFamily
|
this.userSettings.chosenFontFamily = fontFamily
|
||||||
|
|
||||||
|
this._persistFonts()
|
||||||
const userSettingsId = `UserSetting-${this.user}-${this.repo}`
|
const userSettingsId = `UserSetting-${this.user}-${this.repo}`
|
||||||
data.update<DataType.UserSettings, UserSettings>({
|
data.update<DataType.UserSettings, UserSettings>({
|
||||||
...this.userSettings,
|
...this.userSettings,
|
||||||
@@ -169,10 +197,11 @@ export const useUserRepoStore = defineStore("USER_REPO_STATE", {
|
|||||||
},
|
},
|
||||||
setFontSize(fontSize: string) {
|
setFontSize(fontSize: string) {
|
||||||
if (!this.userSettings) {
|
if (!this.userSettings) {
|
||||||
return
|
this.userSettings = { $type: DataType.UserSettings }
|
||||||
}
|
}
|
||||||
this.userSettings.chosenFontSize = fontSize
|
this.userSettings.chosenFontSize = fontSize
|
||||||
|
|
||||||
|
this._persistFonts()
|
||||||
const userSettingsId = `UserSetting-${this.user}-${this.repo}`
|
const userSettingsId = `UserSetting-${this.user}-${this.repo}`
|
||||||
data.update<DataType.UserSettings, UserSettings>({
|
data.update<DataType.UserSettings, UserSettings>({
|
||||||
...this.userSettings,
|
...this.userSettings,
|
||||||
@@ -181,10 +210,11 @@ export const useUserRepoStore = defineStore("USER_REPO_STATE", {
|
|||||||
},
|
},
|
||||||
setTitleFont(font: string) {
|
setTitleFont(font: string) {
|
||||||
if (!this.userSettings) {
|
if (!this.userSettings) {
|
||||||
return
|
this.userSettings = { $type: DataType.UserSettings }
|
||||||
}
|
}
|
||||||
this.userSettings.chosenTitleFont = font
|
this.userSettings.chosenTitleFont = font
|
||||||
|
|
||||||
|
this._persistFonts()
|
||||||
const userSettingsId = `UserSetting-${this.user}-${this.repo}`
|
const userSettingsId = `UserSetting-${this.user}-${this.repo}`
|
||||||
data.update<DataType.UserSettings, UserSettings>({
|
data.update<DataType.UserSettings, UserSettings>({
|
||||||
...this.userSettings,
|
...this.userSettings,
|
||||||
@@ -193,10 +223,11 @@ export const useUserRepoStore = defineStore("USER_REPO_STATE", {
|
|||||||
},
|
},
|
||||||
setBodyFont(font: string) {
|
setBodyFont(font: string) {
|
||||||
if (!this.userSettings) {
|
if (!this.userSettings) {
|
||||||
return
|
this.userSettings = { $type: DataType.UserSettings }
|
||||||
}
|
}
|
||||||
this.userSettings.chosenBodyFont = font
|
this.userSettings.chosenBodyFont = font
|
||||||
|
|
||||||
|
this._persistFonts()
|
||||||
const userSettingsId = `UserSetting-${this.user}-${this.repo}`
|
const userSettingsId = `UserSetting-${this.user}-${this.repo}`
|
||||||
data.update<DataType.UserSettings, UserSettings>({
|
data.update<DataType.UserSettings, UserSettings>({
|
||||||
...this.userSettings,
|
...this.userSettings,
|
||||||
|
|||||||
Reference in New Issue
Block a user