diff --git a/src/components/shortcuts-settings.jsx b/src/components/shortcuts-settings.jsx index b3ce27f5..9d5bb516 100644 --- a/src/components/shortcuts-settings.jsx +++ b/src/components/shortcuts-settings.jsx @@ -118,6 +118,14 @@ const TYPE_PARAMS = { }, ], }; +const fetchListTitle = pmem(async ({ id }) => { + const list = await api().masto.v1.lists.$select(id).fetch(); + return list.title; +}); +const fetchAccountTitle = pmem(async ({ id }) => { + const account = await api().masto.v1.accounts.$select(id).fetch(); + return account.username || account.acct || account.displayName; +}); export const SHORTCUTS_META = { following: { id: 'home', @@ -139,10 +147,7 @@ export const SHORTCUTS_META = { }, list: { id: 'list', - title: pmem(async ({ id }) => { - const list = await api().masto.v1.lists.$select(id).fetch(); - return list.title; - }), + title: fetchListTitle, path: ({ id }) => `/l/${id}`, icon: 'list', }, @@ -168,10 +173,7 @@ export const SHORTCUTS_META = { }, 'account-statuses': { id: 'account-statuses', - title: pmem(async ({ id }) => { - const account = await api().masto.v1.accounts.$select(id).fetch(); - return account.username || account.acct || account.displayName; - }), + title: fetchAccountTitle, path: ({ id }) => `/a/${id}`, icon: 'user', }, @@ -201,43 +203,12 @@ export const SHORTCUTS_META = { function ShortcutsSettings({ onClose }) { const snapStates = useSnapshot(states); - const { masto } = api(); const { shortcuts } = snapStates; - - const [lists, setLists] = useState([]); - const [followedHashtags, setFollowedHashtags] = useState([]); const [showForm, setShowForm] = useState(false); const [showImportExport, setShowImportExport] = useState(false); const [shortcutsListParent] = useAutoAnimate(); - useEffect(() => { - (async () => { - try { - const lists = await masto.v1.lists.list(); - lists.sort((a, b) => a.title.localeCompare(b.title)); - setLists(lists); - } catch (e) { - console.error(e); - } - })(); - - (async () => { - try { - const iterator = masto.v1.followedTags.list(); - const tags = []; - do { - const { value, done } = await iterator.next(); - if (done || value?.length === 0) break; - tags.push(...value); - } while (true); - setFollowedHashtags(tags); - } catch (e) { - console.error(e); - } - })(); - }, []); - return (
{!!onClose && ( @@ -454,8 +425,6 @@ function ShortcutsSettings({ onClose }) { { console.log('onSubmit', result); if (mode === 'edit') { @@ -487,9 +456,27 @@ function ShortcutsSettings({ onClose }) { ); } +const FETCH_MAX_AGE = 1000 * 60; // 1 minute +const fetchLists = pmem( + () => { + const { masto } = api(); + return masto.v1.lists.list(); + }, + { + maxAge: FETCH_MAX_AGE, + }, +); +const fetchFollowedHashtags = pmem( + () => { + const { masto } = api(); + return masto.v1.followedTags.list(); + }, + { + maxAge: FETCH_MAX_AGE, + }, +); + function ShortcutForm({ - lists, - followedHashtags, onSubmit, disabled, shortcut, @@ -500,6 +487,41 @@ function ShortcutForm({ const editMode = !!shortcut; const [currentType, setCurrentType] = useState(shortcut?.type || null); + const [uiState, setUIState] = useState('default'); + const [lists, setLists] = useState([]); + const [followedHashtags, setFollowedHashtags] = useState([]); + useEffect(() => { + (async () => { + if (currentType !== 'list') return; + try { + setUIState('loading'); + const lists = await fetchLists(); + lists.sort((a, b) => a.title.localeCompare(b.title)); + setLists(lists); + setUIState('default'); + } catch (e) { + console.error(e); + setUIState('error'); + } + })(); + + (async () => { + if (currentType !== 'hashtag') return; + try { + const iterator = fetchFollowedHashtags(); + const tags = []; + do { + const { value, done } = await iterator.next(); + if (done || value?.length === 0) break; + tags.push(...value); + } while (true); + setFollowedHashtags(tags); + } catch (e) { + console.error(e); + } + })(); + }, [currentType]); + const formRef = useRef(); useEffect(() => { if (editMode && currentType && TYPE_PARAMS[currentType]) { @@ -588,7 +610,8 @@ function ShortcutForm({