grungnet/src/contexts/TokenDataContext.tsx

167 lines
4.3 KiB
TypeScript
Raw Normal View History

import React, {
useEffect,
useState,
useContext,
useCallback,
useMemo,
} from "react";
import { useLiveQuery } from "dexie-react-hooks";
import { useDatabase } from "./DatabaseContext";
2021-07-02 05:54:54 +00:00
import { Token } from "../tokens";
import { removeGroupsItems } from "../helpers/group";
2021-06-02 07:49:31 +00:00
type TokenDataContext = {
tokens: Token[];
addToken: (token: Token) => Promise<void>;
2021-07-02 05:54:54 +00:00
tokenGroups: any[];
2021-06-02 07:49:31 +00:00
removeTokens: (ids: string[]) => Promise<void>;
updateToken: (id: string, update: Partial<Token>) => Promise<void>;
2021-07-02 05:54:54 +00:00
getToken: (tokenId: string) => Promise<Token | undefined>;
tokensById: Record<string, Token>;
2021-06-02 07:49:31 +00:00
tokensLoading: boolean;
2021-07-02 05:54:54 +00:00
updateTokenGroups: (groups: any[]) => void;
updateTokensHidden: (ids: string[], hideInSidebar: boolean) => void;
};
2021-06-02 07:49:31 +00:00
2021-07-02 05:54:54 +00:00
const TokenDataContext =
React.createContext<TokenDataContext | undefined>(undefined);
2021-07-02 05:54:54 +00:00
export function TokenDataProvider({ children }: { children: React.ReactNode }) {
const { database } = useDatabase();
2021-07-02 05:54:54 +00:00
const tokensQuery = useLiveQuery<Token[]>(
() => database?.table("tokens").toArray() || [],
[database]
);
const tokens = useMemo(() => tokensQuery || [], [tokensQuery]);
const tokensLoading = useMemo(() => !tokensQuery, [tokensQuery]);
const tokenGroupQuery = useLiveQuery(
() => database?.table("groups").get("tokens"),
[database]
);
const [tokenGroups, setTokenGroups] = useState([]);
useEffect(() => {
async function updateTokenGroups() {
2021-07-02 05:54:54 +00:00
const group = await database?.table("groups").get("tokens");
setTokenGroups(group.items);
}
if (database && tokenGroupQuery) {
updateTokenGroups();
}
}, [tokenGroupQuery, database]);
const getToken = useCallback(
async (tokenId) => {
2021-06-02 07:49:31 +00:00
let token = await database?.table("tokens").get(tokenId);
return token;
},
[database]
);
// Add token and add it to the token group
const addToken = useCallback(
async (token) => {
2021-07-02 05:54:54 +00:00
if (database) {
await database.table("tokens").add(token);
const group = await database.table("groups").get("tokens");
await database.table("groups").update("tokens", {
items: [{ id: token.id, type: "item" }, ...group.items],
});
}
},
[database]
);
const removeTokens = useCallback(
async (ids) => {
2021-07-02 05:54:54 +00:00
if (database) {
const tokens = await database.table("tokens").bulkGet(ids);
let assetIds = [];
for (let token of tokens) {
if (token.type === "file") {
assetIds.push(token.file);
assetIds.push(token.thumbnail);
}
2021-04-29 23:54:35 +00:00
}
2021-07-02 05:54:54 +00:00
const group = await database.table("groups").get("tokens");
let items = removeGroupsItems(group.items, ids);
await database.table("groups").update("tokens", { items });
2021-07-02 05:54:54 +00:00
await database.table("tokens").bulkDelete(ids);
await database.table("assets").bulkDelete(assetIds);
}
},
[database]
);
const updateToken = useCallback(
async (id, update) => {
2021-07-02 05:54:54 +00:00
await database?.table("tokens").update(id, update);
},
[database]
);
2021-06-05 03:34:17 +00:00
const updateTokensHidden = useCallback(
2021-07-02 05:54:54 +00:00
async (ids: string[], hideInSidebar: boolean) => {
await Promise.all(
2021-07-02 05:54:54 +00:00
ids.map((id) => database?.table("tokens").update(id, { hideInSidebar }))
);
},
[database]
);
const updateTokenGroups = useCallback(
async (groups) => {
// Update group state immediately to avoid animation delay
setTokenGroups(groups);
2021-07-02 05:54:54 +00:00
await database?.table("groups").update("tokens", { items: groups });
},
[database]
);
2021-06-10 10:08:11 +00:00
const [tokensById, setTokensById] = useState({});
useEffect(() => {
2021-06-10 10:08:11 +00:00
setTokensById(
2021-07-02 05:54:54 +00:00
tokens.reduce((obj: Record<string, Token>, token: Token) => {
2021-06-10 10:08:11 +00:00
obj[token.id] = token;
return obj;
}, {})
);
}, [tokens]);
2021-06-02 07:49:31 +00:00
const value: TokenDataContext = {
tokens,
addToken,
tokenGroups,
removeTokens,
updateToken,
tokensById,
tokensLoading,
getToken,
updateTokenGroups,
2021-06-05 03:34:17 +00:00
updateTokensHidden,
};
return (
<TokenDataContext.Provider value={value}>
{children}
</TokenDataContext.Provider>
);
}
2021-06-02 07:49:31 +00:00
export function useTokenData(): TokenDataContext {
const context = useContext(TokenDataContext);
if (context === undefined) {
throw new Error("useTokenData must be used within a TokenDataProvider");
}
return context;
}
export default TokenDataContext;