fix(fonts): load Google font previews
This commit is contained in:
parent
59550c1c07
commit
83af1453d8
|
|
@ -2,6 +2,10 @@
|
||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
- Fix the web font picker so Google Fonts remain available in Safari, local font access is requested on first open when supported, font sources are labeled, and Google font previews load lazily for visible rows.
|
||||||
|
|
||||||
## 0.12.0 — 2026-05-18
|
## 0.12.0 — 2026-05-18
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,12 @@ import { FontPickerRoot } from '@open-pencil/vue'
|
||||||
|
|
||||||
import { useSelectUI } from '@/components/ui/select'
|
import { useSelectUI } from '@/components/ui/select'
|
||||||
import { usePopoverUI } from '@/components/ui/popover'
|
import { usePopoverUI } from '@/components/ui/popover'
|
||||||
import { listFamilies, localFontAccessState, requestLocalFontAccess } from '@/app/editor/fonts'
|
import {
|
||||||
|
listFamilies,
|
||||||
|
loadFont,
|
||||||
|
localFontAccessState,
|
||||||
|
requestLocalFontAccess
|
||||||
|
} from '@/app/editor/fonts'
|
||||||
|
|
||||||
import type { FontPickerUi } from '@open-pencil/vue'
|
import type { FontPickerUi } from '@open-pencil/vue'
|
||||||
|
|
||||||
|
|
@ -29,10 +34,19 @@ const ui = computed<FontPickerUi>(() => ({
|
||||||
emptyAction: 'mt-2 rounded bg-accent px-2 py-1 text-xs font-medium text-white disabled:opacity-50'
|
emptyAction: 'mt-2 rounded bg-accent px-2 py-1 text-xs font-medium text-white disabled:opacity-50'
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
const previewFontLoads = new Set<string>()
|
||||||
|
|
||||||
const localFontAccess = {
|
const localFontAccess = {
|
||||||
state: localFontAccessState,
|
state: localFontAccessState,
|
||||||
load: requestLocalFontAccess
|
load: requestLocalFontAccess
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function loadPreviewFont(family: string, source: string) {
|
||||||
|
if (source !== 'google') return
|
||||||
|
if (previewFontLoads.has(family)) return
|
||||||
|
previewFontLoads.add(family)
|
||||||
|
void loadFont(family)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
@ -53,7 +67,11 @@ const localFontAccess = {
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #item="{ family, selected, source }">
|
<template #item="{ family, selected, source }">
|
||||||
<div data-test-id="font-picker-item" class="flex min-w-0 flex-1 items-center gap-2">
|
<div
|
||||||
|
data-test-id="font-picker-item"
|
||||||
|
class="flex min-w-0 flex-1 items-center gap-2"
|
||||||
|
@vue:mounted="loadPreviewFont(family, source)"
|
||||||
|
>
|
||||||
<icon-lucide-check v-if="selected" class="size-3 shrink-0 text-accent" />
|
<icon-lucide-check v-if="selected" class="size-3 shrink-0 text-accent" />
|
||||||
<span v-else class="size-3 shrink-0" />
|
<span v-else class="size-3 shrink-0" />
|
||||||
<span class="truncate" :style="{ fontFamily: `'${family}', sans-serif` }">{{
|
<span class="truncate" :style="{ fontFamily: `'${family}', sans-serif` }">{{
|
||||||
|
|
|
||||||
|
|
@ -23,20 +23,31 @@ async function openFontPicker(page: Page) {
|
||||||
|
|
||||||
async function installGoogleFontsMock(page: Page, families = ['Inter', 'OpenPencil Google Font']) {
|
async function installGoogleFontsMock(page: Page, families = ['Inter', 'OpenPencil Google Font']) {
|
||||||
await page.addInitScript((googleFamilies) => {
|
await page.addInitScript((googleFamilies) => {
|
||||||
const win = window as Window & { __googleFontsFetchCount?: number }
|
const win = window as Window & {
|
||||||
|
__googleFontsFetchCount?: number
|
||||||
|
__googleFontPreviewFetchCount?: number
|
||||||
|
}
|
||||||
win.__googleFontsFetchCount = 0
|
win.__googleFontsFetchCount = 0
|
||||||
|
win.__googleFontPreviewFetchCount = 0
|
||||||
const originalFetch = window.fetch.bind(window)
|
const originalFetch = window.fetch.bind(window)
|
||||||
window.fetch = async (input, init) => {
|
window.fetch = async (input, init) => {
|
||||||
let url: string
|
let url: string
|
||||||
if (typeof input === 'string') url = input
|
if (typeof input === 'string') url = input
|
||||||
else if (input instanceof URL) url = input.href
|
else if (input instanceof URL) url = input.href
|
||||||
else url = input.url
|
else url = input.url
|
||||||
|
if (url.startsWith('https://fonts.openpencil.test/')) {
|
||||||
|
win.__googleFontPreviewFetchCount = (win.__googleFontPreviewFetchCount ?? 0) + 1
|
||||||
|
return new Response(new ArrayBuffer(8), { status: 200 })
|
||||||
|
}
|
||||||
if (url.startsWith('https://www.googleapis.com/webfonts/v1/webfonts')) {
|
if (url.startsWith('https://www.googleapis.com/webfonts/v1/webfonts')) {
|
||||||
if (!url.includes('family='))
|
if (!url.includes('family='))
|
||||||
win.__googleFontsFetchCount = (win.__googleFontsFetchCount ?? 0) + 1
|
win.__googleFontsFetchCount = (win.__googleFontsFetchCount ?? 0) + 1
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
items: googleFamilies.map((family) => ({ family }))
|
items: googleFamilies.map((family) => ({
|
||||||
|
family,
|
||||||
|
files: { regular: `https://fonts.openpencil.test/${encodeURIComponent(family)}.ttf` }
|
||||||
|
}))
|
||||||
}),
|
}),
|
||||||
{ status: 200, headers: { 'content-type': 'application/json' } }
|
{ status: 200, headers: { 'content-type': 'application/json' } }
|
||||||
)
|
)
|
||||||
|
|
@ -109,6 +120,15 @@ test('font picker lists Google fonts when local font API is unavailable', async
|
||||||
await expect(
|
await expect(
|
||||||
page.getByTestId('font-picker-item').filter({ hasText: 'OpenPencil Google Font' })
|
page.getByTestId('font-picker-item').filter({ hasText: 'OpenPencil Google Font' })
|
||||||
).toBeVisible()
|
).toBeVisible()
|
||||||
|
await expect
|
||||||
|
.poll(() =>
|
||||||
|
page.evaluate(
|
||||||
|
() =>
|
||||||
|
(window as Window & { __googleFontPreviewFetchCount?: number })
|
||||||
|
.__googleFontPreviewFetchCount
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.toBeGreaterThan(0)
|
||||||
await expect(page.getByText('Local fonts are not available in this browser.')).toHaveCount(0)
|
await expect(page.getByText('Local fonts are not available in this browser.')).toHaveCount(0)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue