Files
grungnet/src/contexts/TokenDataContext.tsx
T

167 lines
4.3 KiB
TypeScript
Raw Normal View History

import React, {
useEffect,
useState,
useContext,
useCallback,
2021-06-25 17:45:14 +10:00
useMemo,
} from "react";
2021-06-25 17:45:14 +10:00
import { useLiveQuery } from "dexie-react-hooks";
import { useDatabase } from "./DatabaseContext";
2021-07-02 15:54:54 +10:00
import { Token } from "../tokens";
2021-06-09 09:29:32 +10:00
import { removeGroupsItems } from "../helpers/group";
2021-06-02 17:49:31 +10:00
type TokenDataContext = {
tokens: Token[];
addToken: (token: Token) => Promise<void>;
2021-07-02 15:54:54 +10:00
tokenGroups: any[];
2021-06-02 17:49:31 +10:00
removeTokens: (ids: string[]) => Promise<void>;
updateToken: (id: string, update: Partial<Token>) => Promise<void>;
2021-07-02 15:54:54 +10:00
getToken: (tokenId: string) => Promise<Token | undefined>;
tokensById: Record<string, Token>;
2021-06-02 17:49:31 +10:00
tokensLoading: boolean;
2021-07-02 15:54:54 +10:00
updateTokenGroups: (groups: any[]) => void;
updateTokensHidden: (ids: string[], hideInSidebar: boolean) => void;
};
2021-06-02 17:49:31 +10:00
2021-07-02 15:54:54 +10:00
const TokenDataContext =
React.createContext<TokenDataContext | undefined>(undefined);
2021-07-02 15:54:54 +10:00
export function TokenDataProvider({ children }: { children: React.ReactNode }) {
2021-06-25 17:45:14 +10:00
const { database } = useDatabase();
2021-07-02 15:54:54 +10:00
const tokensQuery = useLiveQuery<Token[]>(
() => database?.table("tokens").toArray() || [],
2021-06-25 17:45:14 +10:00
[database]
);
2021-06-25 17:45:14 +10:00
const tokens = useMemo(() => tokensQuery || [], [tokensQuery]);
const tokensLoading = useMemo(() => !tokensQuery, [tokensQuery]);
2021-06-25 17:45:14 +10:00
const tokenGroupQuery = useLiveQuery(
() => database?.table("groups").get("tokens"),
[database]
);
const [tokenGroups, setTokenGroups] = useState([]);
useEffect(() => {
2021-06-25 17:45:14 +10:00
async function updateTokenGroups() {
2021-07-02 15:54:54 +10:00
const group = await database?.table("groups").get("tokens");
2021-06-25 17:45:14 +10:00
setTokenGroups(group.items);
}
2021-06-25 17:45:14 +10:00
if (database && tokenGroupQuery) {
updateTokenGroups();
2020-05-19 19:03:36 +10:00
}
2021-06-25 17:45:14 +10:00
}, [tokenGroupQuery, database]);
2020-05-19 19:03:36 +10:00
const getToken = useCallback(
async (tokenId) => {
2021-06-02 17:49:31 +10: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 15:54:54 +10: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 15:54:54 +10: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-30 09:54:35 +10:00
}
2021-06-09 09:29:32 +10:00
2021-07-02 15:54:54 +10:00
const group = await database.table("groups").get("tokens");
let items = removeGroupsItems(group.items, ids);
await database.table("groups").update("tokens", { items });
2021-06-09 09:29:32 +10:00
2021-07-02 15:54:54 +10:00
await database.table("tokens").bulkDelete(ids);
await database.table("assets").bulkDelete(assetIds);
}
},
[database]
);
const updateToken = useCallback(
async (id, update) => {
2021-07-02 15:54:54 +10:00
await database?.table("tokens").update(id, update);
},
[database]
);
2021-06-05 13:34:17 +10:00
const updateTokensHidden = useCallback(
2021-07-02 15:54:54 +10:00
async (ids: string[], hideInSidebar: boolean) => {
await Promise.all(
2021-07-02 15:54:54 +10: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 15:54:54 +10:00
await database?.table("groups").update("tokens", { items: groups });
},
[database]
);
2021-06-10 20:08:11 +10:00
const [tokensById, setTokensById] = useState({});
useEffect(() => {
2021-06-10 20:08:11 +10:00
setTokensById(
2021-07-02 15:54:54 +10:00
tokens.reduce((obj: Record<string, Token>, token: Token) => {
2021-06-10 20:08:11 +10:00
obj[token.id] = token;
return obj;
}, {})
);
}, [tokens]);
2021-06-02 17:49:31 +10:00
const value: TokenDataContext = {
2020-05-19 19:03:36 +10:00
tokens,
addToken,
tokenGroups,
removeTokens,
2020-05-19 19:03:36 +10:00
updateToken,
tokensById,
tokensLoading,
getToken,
updateTokenGroups,
2021-06-05 13:34:17 +10:00
updateTokensHidden,
2020-05-19 19:03:36 +10:00
};
return (
<TokenDataContext.Provider value={value}>
{children}
</TokenDataContext.Provider>
);
}
2021-06-02 17:49:31 +10: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;