improve font

This commit is contained in:
EYHN
2024-08-19 23:29:40 +08:00
parent 76bc48dd9c
commit 73bbb6c9d2
2 changed files with 62 additions and 75 deletions

View File

@@ -24,7 +24,13 @@ import {
useLiveData,
useService,
} from '@toeverything/infra';
import { type ChangeEvent, useCallback, useMemo, useState } from 'react';
import {
type ChangeEvent,
useCallback,
useEffect,
useMemo,
useState,
} from 'react';
import { menu, menuTrigger, searchInput, settingWrapper } from './style.css';
@@ -92,29 +98,32 @@ const getFontFamily = (font: string) => `${font}, ${fontStyleOptions[0].value}`;
const FontMenuItems = ({ onSelect }: { onSelect: (font: string) => void }) => {
const systemFontFamily = useService(SystemFontFamilyService).systemFontFamily;
const systemFontList = useLiveData(systemFontFamily.fontList$);
useEffect(() => {
systemFontFamily.loadFontList();
systemFontFamily.clearSearch();
}, [systemFontFamily]);
const isLoading = useLiveData(systemFontFamily.isLoading$);
const result = useLiveData(systemFontFamily.result$);
const searchText = useLiveData(systemFontFamily.searchText$);
const [inputValue, setInputValue] = useState('');
const onInputChange = useCallback((e: ChangeEvent<HTMLInputElement>) => {
setInputValue(e.target.value);
}, []);
const onInputChange = useCallback(
(e: ChangeEvent<HTMLInputElement>) => {
systemFontFamily.search(e.target.value);
},
[systemFontFamily]
);
const onInputKeyDown = useCallback(
(e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Enter') {
systemFontFamily.search(inputValue);
} else if (e.key === 'Backspace' || e.key === 'Escape') {
systemFontFamily.clearSearch();
}
e.stopPropagation(); // avoid typeahead search built-in in the menu
},
[inputValue, systemFontFamily]
[]
);
return (
<div>
<input
value={inputValue}
value={searchText ?? ''}
onChange={onInputChange}
onKeyDown={onInputKeyDown}
autoFocus
@@ -131,12 +140,8 @@ const FontMenuItems = ({ onSelect }: { onSelect: (font: string) => void }) => {
result.map(font => (
<FontMenuItem key={font} font={font} onSelect={onSelect} />
))
) : searchText && searchText.length > 0 ? (
<div>not found</div>
) : (
systemFontList.map(font => (
<FontMenuItem key={font} font={font} onSelect={onSelect} />
))
<div>not found</div>
)}
</Scrollable.Viewport>
<Scrollable.Scrollbar />

View File

@@ -1,79 +1,61 @@
import { DebugLogger } from '@affine/debug';
import { apis } from '@affine/electron-api';
import { Entity, LiveData } from '@toeverything/infra';
import {
debounceTime,
distinctUntilChanged,
of,
shareReplay,
switchMap,
tap,
} from 'rxjs';
const logger = new DebugLogger('affine:system-font-family');
effect,
Entity,
fromPromise,
LiveData,
mapInto,
onComplete,
onStart,
} from '@toeverything/infra';
import { exhaustMap } from 'rxjs';
export class SystemFontFamily extends Entity {
constructor() {
super();
this.loadFontList().catch(error => {
logger.error('Failed to load system font list', error);
});
}
readonly searchText$ = new LiveData<string | null>(null);
readonly isLoading$ = new LiveData<boolean>(false);
readonly fontList$ = new LiveData<string[]>([]);
readonly result$ = LiveData.from(
this.searchText$.pipe(
distinctUntilChanged(),
debounceTime(500),
switchMap(searchText => {
if (!searchText) {
return of([]);
readonly result$ = LiveData.computed(get => {
const fontList = get(this.fontList$);
const searchText = get(this.searchText$);
if (!searchText) {
return fontList;
}
const filteredFonts = fontList.filter(font =>
font.toLowerCase().includes(searchText.toLowerCase())
);
return filteredFonts;
}).throttleTime(500);
loadFontList = effect(
exhaustMap(() => {
return fromPromise(async () => {
if (!apis?.fontList) {
return [];
}
return this.fontList$.pipe(
tap(() => {
this.isLoading$.next(true);
}),
switchMap(fontList => {
const filteredFonts = fontList.filter(font =>
font.toLowerCase().includes(searchText.toLowerCase())
);
this.isLoading$.next(false);
return of(filteredFonts);
})
);
}),
shareReplay({
bufferSize: 1,
refCount: true,
})
),
[]
return apis.fontList.getSystemFonts();
}).pipe(
mapInto(this.fontList$),
// TODO: catchErrorInto(this.error$),
onStart(() => {
this.isLoading$.next(true);
}),
onComplete(() => {
this.isLoading$.next(false);
})
);
})
);
async loadFontList() {
if (!apis?.fontList) {
return;
}
try {
this.isLoading$.next(true);
const fontList = await apis.fontList.getSystemFonts();
this.fontList$.next(fontList);
} catch (error) {
logger.error('Failed to load system font list', error);
} finally {
this.isLoading$.next(false);
}
}
search(searchText: string) {
if (!this.searchText$.value) return;
this.searchText$.next(searchText);
}
clearSearch() {
if (!this.searchText$.value) return;
this.searchText$.next(null);
}
}