Move preference handling into useExplorerPreferences (#2343)

* move preference handling into useExplorerPreferences

* oops
This commit is contained in:
Brendan Allan 2024-04-18 22:16:11 +08:00 committed by GitHub
parent 663d1e9f1e
commit 029250e1b2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 98 additions and 106 deletions

View file

@ -0,0 +1,69 @@
import { useMemo } from 'react';
import {
ExplorerSettings,
LibraryPreferences,
Ordering,
useExplorerLayoutStore,
useLibraryMutation,
useLibraryQuery,
useRspcLibraryContext
} from '@sd/client';
import { createDefaultExplorerSettings } from './store';
// preferences are settings persisted to the db and synced
export function useExplorerPreferences<TData, TOrder extends Ordering>({
data,
createDefaultSettings,
getSettings,
writeSettings
}: {
data: TData;
createDefaultSettings(): ReturnType<typeof createDefaultExplorerSettings<TOrder>>;
getSettings: (prefs: LibraryPreferences) => ExplorerSettings<TOrder> | undefined;
writeSettings: (settings: ExplorerSettings<TOrder>) => LibraryPreferences;
}) {
const rspc = useRspcLibraryContext();
const explorerLayout = useExplorerLayoutStore();
const preferences = useLibraryQuery(['preferences.get']);
const updatePreferences = useLibraryMutation('preferences.update');
const settings = useMemo(() => {
const defaults = createDefaultSettings();
if (!location || !preferences.data) return defaults;
const settings = getSettings(preferences.data);
// Overwrite the default layout with the user's preference
Object.assign(defaults, { layoutMode: explorerLayout.defaultView });
if (!settings) return defaults;
for (const [key, value] of Object.entries(settings)) {
if (value !== null) Object.assign(defaults, { [key]: value });
}
return defaults;
}, [preferences.data, getSettings, createDefaultSettings, explorerLayout.defaultView]);
const onSettingsChanged = async (settings: ExplorerSettings<TOrder>) => {
if (preferences.isLoading) return;
try {
await updatePreferences.mutateAsync(writeSettings(settings));
rspc.queryClient.invalidateQueries(['preferences.get']);
} catch (e) {
alert('An error has occurred while updating your preferences.');
}
};
return Object.assign(preferences, {
explorerSettingsProps: {
settings,
onSettingsChanged,
data
}
});
}

View file

@ -3,7 +3,6 @@ import { useEffect, useMemo } from 'react';
import { stringify } from 'uuid';
import {
arraysEqual,
ExplorerSettings,
FilePathOrder,
Location,
useCache,
@ -12,8 +11,7 @@ import {
useLibraryQuery,
useLibrarySubscription,
useNodes,
useOnlineLocations,
useRspcLibraryContext
useOnlineLocations
} from '@sd/client';
import { Loader, Tooltip } from '@sd/ui';
import { LocationIdParamsSchema } from '~/app/route-schemas';
@ -37,6 +35,7 @@ import {
} from '../Explorer/store';
import { DefaultTopBarOptions } from '../Explorer/TopBarOptions';
import { useExplorer, useExplorerSettings } from '../Explorer/useExplorer';
import { useExplorerPreferences } from '../Explorer/useExplorerPreferences';
import { useExplorerSearchParams } from '../Explorer/util';
import { EmptyNotice } from '../Explorer/View/EmptyNotice';
import { SearchContextProvider, SearchOptions, useSearchFromSearchParams } from '../search';
@ -225,59 +224,22 @@ function getLastSectionOfPath(path: string): string | undefined {
}
function useLocationExplorerSettings(location: Location) {
const rspc = useRspcLibraryContext();
const preferences = useLibraryQuery(['preferences.get']);
const updatePreferences = useLibraryMutation('preferences.update');
const explorerLayout = useExplorerLayoutStore();
const settings = useMemo(() => {
const defaults = createDefaultExplorerSettings<FilePathOrder>({
order: { field: 'name', value: 'Asc' }
});
if (!location) return defaults;
const pubId = stringify(location.pub_id);
const settings = preferences.data?.location?.[pubId]?.explorer;
// Overwrite the default layout with the user's preference
Object.assign(defaults, { layoutMode: explorerLayout.defaultView });
if (!settings) return defaults;
for (const [key, value] of Object.entries(settings)) {
if (value !== null) Object.assign(defaults, { [key]: value });
}
return defaults;
}, [explorerLayout.defaultView, location, preferences.data?.location]);
const onSettingsChanged = async (
settings: ExplorerSettings<FilePathOrder>,
changedLocation: Location
) => {
if (changedLocation.id === location.id && preferences.isLoading) return;
const pubId = stringify(changedLocation.pub_id);
try {
await updatePreferences.mutateAsync({
location: { [pubId]: { explorer: settings } }
});
rspc.queryClient.invalidateQueries(['preferences.get']);
} catch (e) {
alert('An error has occurred while updating your preferences.');
}
};
const preferences = useExplorerPreferences({
data: location,
createDefaultSettings: () =>
createDefaultExplorerSettings<FilePathOrder>({
order: { field: 'name', value: 'Asc' }
}),
getSettings: (prefs) => prefs.location?.[stringify(location.pub_id)]?.explorer,
writeSettings: (settings) => ({
location: { [stringify(location.pub_id)]: { explorer: settings } }
})
});
return {
explorerSettings: useExplorerSettings({
settings,
onSettingsChanged,
orderingKeys: filePathOrderingKeysSchema,
data: location
...preferences.explorerSettingsProps,
orderingKeys: filePathOrderingKeysSchema
}),
preferences
};

View file

@ -1,14 +1,5 @@
import { useMemo } from 'react';
import {
ExplorerSettings,
ObjectOrder,
Tag,
useCache,
useLibraryMutation,
useLibraryQuery,
useNodes,
useRspcLibraryContext
} from '@sd/client';
import { ObjectOrder, Tag, useCache, useLibraryQuery, useNodes } from '@sd/client';
import { LocationIdParamsSchema } from '~/app/route-schemas';
import { Icon } from '~/components';
import { useLocale, useRouteTitle, useZodRouteParams } from '~/hooks';
@ -19,6 +10,7 @@ import { ExplorerContextProvider } from '../Explorer/Context';
import { createDefaultExplorerSettings, objectOrderingKeysSchema } from '../Explorer/store';
import { DefaultTopBarOptions } from '../Explorer/TopBarOptions';
import { useExplorer, useExplorerSettings } from '../Explorer/useExplorer';
import { useExplorerPreferences } from '../Explorer/useExplorerPreferences';
import { EmptyNotice } from '../Explorer/View/EmptyNotice';
import { SearchContextProvider, SearchOptions, useSearchFromSearchParams } from '../search';
import SearchBar from '../search/SearchBar';
@ -97,51 +89,20 @@ export function Component() {
}
function useTagExplorerSettings(tag: Tag) {
const rspc = useRspcLibraryContext();
const preferences = useLibraryQuery(['preferences.get']);
const updatePreferences = useLibraryMutation('preferences.update');
const settings = useMemo(() => {
const defaults = createDefaultExplorerSettings<ObjectOrder>({ order: null });
if (!location) return defaults;
const pubId = stringify(tag.pub_id);
const settings = preferences.data?.tag?.[pubId]?.explorer;
if (!settings) return defaults;
for (const [key, value] of Object.entries(settings)) {
if (value !== null) Object.assign(defaults, { [key]: value });
}
return defaults;
}, [tag, preferences.data?.tag]);
const onSettingsChanged = async (settings: ExplorerSettings<ObjectOrder>, changedTag: Tag) => {
if (changedTag.id === tag.id && preferences.isLoading) return;
const pubId = stringify(changedTag.pub_id);
try {
await updatePreferences.mutateAsync({
tag: { [pubId]: { explorer: settings } }
});
rspc.queryClient.invalidateQueries(['preferences.get']);
} catch (e) {
alert('An error has occurred while updating your preferences.');
}
};
const preferences = useExplorerPreferences({
data: tag,
createDefaultSettings: () => createDefaultExplorerSettings<ObjectOrder>({ order: null }),
getSettings: (prefs) => prefs.tag?.[stringify(tag.pub_id)]?.explorer,
writeSettings: (settings) => ({
tag: { [stringify(tag.pub_id)]: { explorer: settings } }
})
});
return {
preferences,
explorerSettings: useExplorerSettings({
settings,
onSettingsChanged,
orderingKeys: objectOrderingKeysSchema,
data: tag
}),
preferences
...preferences.explorerSettingsProps,
orderingKeys: objectOrderingKeysSchema
})
};
}