[Glitch] Add useStorageState hook
Port f99c60a8f3 to glitch-soc
Signed-off-by: Claire <claire.github-309c@sitedethib.com>
This commit is contained in:
@@ -7,7 +7,7 @@ import {
|
||||
useState,
|
||||
} from 'react';
|
||||
|
||||
import { useStorage } from '@/flavours/glitch/hooks/useStorage';
|
||||
import { useStorageState } from '@/flavours/glitch/hooks/useStorage';
|
||||
|
||||
interface AccountTimelineContextValue {
|
||||
accountId: string;
|
||||
@@ -26,30 +26,34 @@ export const AccountTimelineProvider: FC<{
|
||||
accountId: string;
|
||||
children: ReactNode;
|
||||
}> = ({ accountId, children }) => {
|
||||
const { getItem, setItem } = useStorage({
|
||||
const storageOptions = {
|
||||
type: 'session',
|
||||
prefix: `filters-${accountId}:`,
|
||||
});
|
||||
const [boosts, setBoosts] = useState(
|
||||
() => (getItem('boosts') === '0' ? false : true), // Default to enabled.
|
||||
} as const;
|
||||
|
||||
const [boosts, setBoosts] = useStorageState<boolean>(
|
||||
'boosts',
|
||||
true,
|
||||
storageOptions,
|
||||
);
|
||||
const [replies, setReplies] = useState(() =>
|
||||
getItem('replies') === '1' ? true : false,
|
||||
|
||||
const [replies, setReplies] = useStorageState<boolean>(
|
||||
'replies',
|
||||
false,
|
||||
storageOptions,
|
||||
);
|
||||
|
||||
const handleSetBoosts = useCallback(
|
||||
(value: boolean) => {
|
||||
setBoosts(value);
|
||||
setItem('boosts', value ? '1' : '0');
|
||||
},
|
||||
[setBoosts, setItem],
|
||||
[setBoosts],
|
||||
);
|
||||
const handleSetReplies = useCallback(
|
||||
(value: boolean) => {
|
||||
setReplies(value);
|
||||
setItem('replies', value ? '1' : '0');
|
||||
},
|
||||
[setReplies, setItem],
|
||||
[setReplies],
|
||||
);
|
||||
|
||||
const [showAllPinned, setShowAllPinned] = useState(false);
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
|
||||
interface StorageOptions {
|
||||
type?: 'local' | 'session';
|
||||
prefix?: string;
|
||||
}
|
||||
|
||||
export function useStorage({
|
||||
type = 'local',
|
||||
prefix = '',
|
||||
}: { type?: 'local' | 'session'; prefix?: string } = {}) {
|
||||
}: StorageOptions = {}) {
|
||||
const storageType = type === 'local' ? 'localStorage' : 'sessionStorage';
|
||||
const isAvailable = useMemo(
|
||||
() => storageAvailable(storageType),
|
||||
@@ -23,6 +28,7 @@ export function useStorage({
|
||||
},
|
||||
[isAvailable, storageType, prefix],
|
||||
);
|
||||
|
||||
const setItem = useCallback(
|
||||
(key: string, value: string) => {
|
||||
if (!isAvailable) {
|
||||
@@ -35,13 +41,52 @@ export function useStorage({
|
||||
[isAvailable, storageType, prefix],
|
||||
);
|
||||
|
||||
const removeItem = useCallback(
|
||||
(key: string) => {
|
||||
if (!isAvailable) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
window[storageType].removeItem(prefix ? `${prefix};${key}` : key);
|
||||
} catch {}
|
||||
},
|
||||
[isAvailable, storageType, prefix],
|
||||
);
|
||||
|
||||
return {
|
||||
isAvailable,
|
||||
getItem,
|
||||
setItem,
|
||||
removeItem,
|
||||
};
|
||||
}
|
||||
|
||||
export function useStorageState<T extends string | boolean>(
|
||||
key: string,
|
||||
initialState: T,
|
||||
options?: StorageOptions,
|
||||
) {
|
||||
const { getItem, setItem, removeItem } = useStorage(options);
|
||||
const [state, setState] = useState<T>(
|
||||
() => (retrieveBooleanOrString(getItem(key)) as T | null) ?? initialState,
|
||||
);
|
||||
|
||||
const handleSetState = useCallback(
|
||||
(newValue: T) => {
|
||||
setItem(key, castToString(newValue));
|
||||
setState(newValue);
|
||||
},
|
||||
[key, setItem],
|
||||
);
|
||||
|
||||
const removeState = useCallback(() => {
|
||||
removeItem(key);
|
||||
setState(initialState);
|
||||
}, [initialState, key, removeItem]);
|
||||
|
||||
return [state, handleSetState, removeState] as const;
|
||||
}
|
||||
|
||||
// Tests the storage availability for the given type. Taken from MDN:
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API
|
||||
export function storageAvailable(type: 'localStorage' | 'sessionStorage') {
|
||||
@@ -62,3 +107,21 @@ export function storageAvailable(type: 'localStorage' | 'sessionStorage') {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function castToString(value: string | boolean) {
|
||||
if (typeof value === 'boolean') {
|
||||
return value ? '1' : '0';
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
function retrieveBooleanOrString(value: string | null) {
|
||||
if (value === '1') {
|
||||
return true;
|
||||
} else if (value === '0') {
|
||||
return false;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user