mirror of
https://github.com/Qortal/qapp-core.git
synced 2025-06-14 17:41:20 +00:00
added index manager
This commit is contained in:
parent
86689af488
commit
28fd2fd2d1
118
src/components/IndexManager/IndexManager.tsx
Normal file
118
src/components/IndexManager/IndexManager.tsx
Normal file
@ -0,0 +1,118 @@
|
||||
import {
|
||||
Box,
|
||||
ButtonBase,
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogTitle,
|
||||
IconButton,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import React, { useState } from "react";
|
||||
import { useIndexStore } from "../../state/indexes";
|
||||
import CloseIcon from "@mui/icons-material/Close";
|
||||
import ArrowBackIosIcon from '@mui/icons-material/ArrowBackIos';
|
||||
export const IndexManager = () => {
|
||||
const open = useIndexStore((state) => state.open);
|
||||
const setOpen = useIndexStore((state) => state.setOpen);
|
||||
const [mode, setMode] = useState(1);
|
||||
|
||||
const handleClose = () => {
|
||||
setOpen(null);
|
||||
setMode(1);
|
||||
};
|
||||
return (
|
||||
<Dialog
|
||||
open={!!open}
|
||||
fullWidth={true}
|
||||
maxWidth={"md"}
|
||||
sx={{
|
||||
zIndex: 999990,
|
||||
}}
|
||||
>
|
||||
<DialogTitle>Index manager</DialogTitle>
|
||||
<IconButton
|
||||
aria-label="close"
|
||||
onClick={handleClose}
|
||||
sx={(theme) => ({
|
||||
position: "absolute",
|
||||
right: 8,
|
||||
top: 8,
|
||||
})}
|
||||
>
|
||||
<CloseIcon />
|
||||
</IconButton>
|
||||
<DialogContent>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: "20px",
|
||||
width: "100%",
|
||||
alignItems: 'flex-start'
|
||||
}}
|
||||
>
|
||||
<IconButton disabled={mode === 1} onClick={()=> setMode(1)}><ArrowBackIosIcon /></IconButton>
|
||||
{mode === 1 && (
|
||||
<>
|
||||
<ButtonBase
|
||||
sx={{
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
p: 2,
|
||||
border: "2px solid",
|
||||
borderRadius: 2,
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Typography>Create new index</Typography>
|
||||
</Box>
|
||||
</ButtonBase>
|
||||
<ButtonBase
|
||||
sx={{
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
p: 2,
|
||||
border: "2px solid",
|
||||
borderRadius: 2,
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Typography>Your indices</Typography>
|
||||
</Box>
|
||||
</ButtonBase>
|
||||
<ButtonBase
|
||||
sx={{
|
||||
width: "100%",
|
||||
}}
|
||||
onClick={()=> setMode(4)}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
p: 2,
|
||||
border: "2px solid",
|
||||
borderRadius: 2,
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Typography>Add metadata</Typography>
|
||||
</Box>
|
||||
</ButtonBase>
|
||||
</>
|
||||
)}
|
||||
|
||||
{mode === 4 && <AddMetadata />}
|
||||
</Box>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
const AddMetadata = () => {
|
||||
return <Box>hello</Box>;
|
||||
};
|
@ -5,6 +5,8 @@ import { useAppInfo } from "../hooks/useAppInfo";
|
||||
import { useIdentifiers } from "../hooks/useIdentifiers";
|
||||
import { Toaster } from "react-hot-toast";
|
||||
import { useLocalStorage } from "../hooks/useLocalStorage";
|
||||
import { IndexManager } from "../components/IndexManager/IndexManager";
|
||||
import { useIndexes } from "../hooks/useIndexes";
|
||||
|
||||
|
||||
|
||||
@ -17,6 +19,7 @@ lists: ReturnType<typeof useResources>;
|
||||
appInfo: ReturnType<typeof useAppInfo>;
|
||||
identifierOperations: ReturnType<typeof useIdentifiers>
|
||||
localStorageOperations: ReturnType<typeof useLocalStorage>
|
||||
indexOperations: ReturnType<typeof useIndexes>
|
||||
}
|
||||
|
||||
|
||||
@ -45,8 +48,9 @@ export const GlobalProvider = ({ children, config, toastStyle = {} }: GlobalProv
|
||||
const lists = useResources()
|
||||
const identifierOperations = useIdentifiers(config.publicSalt, config.appName)
|
||||
const localStorageOperations = useLocalStorage(config.publicSalt, config.appName)
|
||||
const indexOperations = useIndexes()
|
||||
// ✅ Merge all hooks into a single `contextValue`
|
||||
const contextValue = useMemo(() => ({ auth, lists, appInfo, identifierOperations, localStorageOperations }), [auth, lists, appInfo, identifierOperations, localStorageOperations]);
|
||||
const contextValue = useMemo(() => ({ auth, lists, appInfo, identifierOperations, localStorageOperations, indexOperations }), [auth, lists, appInfo, identifierOperations, localStorageOperations]);
|
||||
return (
|
||||
<GlobalContext.Provider value={contextValue}>
|
||||
<Toaster
|
||||
@ -57,6 +61,7 @@ export const GlobalProvider = ({ children, config, toastStyle = {} }: GlobalProv
|
||||
}}
|
||||
containerStyle={{zIndex: 999999}}
|
||||
/>
|
||||
<IndexManager />
|
||||
{children}
|
||||
</GlobalContext.Provider>
|
||||
);
|
||||
|
20
src/hooks/useIndexes.tsx
Normal file
20
src/hooks/useIndexes.tsx
Normal file
@ -0,0 +1,20 @@
|
||||
import React, { useCallback } from "react";
|
||||
import { OpenIndex, useIndexStore } from "../state/indexes";
|
||||
|
||||
export const useIndexes = () => {
|
||||
const setOpen = useIndexStore((state) => state.setOpen);
|
||||
const openPageIndexManager = useCallback(
|
||||
({ link, name }: OpenIndex) => {
|
||||
if(!link || !name) return
|
||||
setOpen({
|
||||
name,
|
||||
link,
|
||||
});
|
||||
},
|
||||
[setOpen]
|
||||
);
|
||||
|
||||
return {
|
||||
openPageIndexManager,
|
||||
};
|
||||
};
|
@ -1,5 +1,8 @@
|
||||
export { useResourceStatus } from './hooks/useResourceStatus';
|
||||
export { Spacer } from './common/Spacer';
|
||||
import './index.css'
|
||||
export { hashWordWithoutPublicSalt } from './utils/encryption';
|
||||
export { createAvatarLink } from './utils/qortal';
|
||||
export { objectToBase64 } from './utils/base64';
|
||||
export { generateBloomFilterBase64, isInsideBloom } from './utils/bloomFilter';
|
||||
export { addAndEncryptSymmetricKeys, decryptWithSymmetricKeys, encryptWithSymmetricKeys } from './utils/encryption';
|
||||
@ -20,4 +23,3 @@ export {Service} from './types/interfaces/resources'
|
||||
export {ListItem} from './state/cache'
|
||||
export {SymmetricKeys} from './utils/encryption'
|
||||
|
||||
|
||||
|
18
src/state/indexes.ts
Normal file
18
src/state/indexes.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { create } from "zustand";
|
||||
|
||||
export interface OpenIndex {
|
||||
link: string
|
||||
name: string
|
||||
}
|
||||
|
||||
interface IndexState {
|
||||
open: OpenIndex | null;
|
||||
setOpen: (openIndex: OpenIndex | null ) => void;
|
||||
}
|
||||
|
||||
// ✅ Typed Zustand Store
|
||||
export const useIndexStore = create<IndexState>((set) => ({
|
||||
open: null,
|
||||
setOpen: (openIndex) =>
|
||||
set({ open: openIndex }),
|
||||
}));
|
@ -48,6 +48,35 @@ export async function hashWord(
|
||||
}
|
||||
}
|
||||
|
||||
export async function hashWordWithoutPublicSalt(
|
||||
word: string,
|
||||
collisionStrength: number
|
||||
): Promise<string> {
|
||||
try {
|
||||
if (!crypto?.subtle?.digest) throw new Error("Web Crypto not available");
|
||||
|
||||
const encoded = new TextEncoder().encode(word);
|
||||
const hashBuffer = await crypto.subtle.digest("SHA-256", encoded);
|
||||
|
||||
return Buffer.from(hashBuffer)
|
||||
.toString("base64")
|
||||
.replace(/\+/g, "-")
|
||||
.replace(/\//g, "_")
|
||||
.replace(/=+$/, "")
|
||||
.slice(0, collisionStrength);
|
||||
} catch (err) {
|
||||
const hash = SHA256(word);
|
||||
const base64 = EncBase64.stringify(hash);
|
||||
|
||||
return base64
|
||||
.replace(/\+/g, "-")
|
||||
.replace(/\//g, "_")
|
||||
.replace(/=+$/, "")
|
||||
.slice(0, collisionStrength);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const uid = new ShortUniqueId({ length: 10, dictionary: "alphanum" });
|
||||
|
||||
interface EntityConfig {
|
||||
|
3
src/utils/qortal.ts
Normal file
3
src/utils/qortal.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export const createAvatarLink = (qortalName: string)=> {
|
||||
return `/arbitrary/THUMBNAIL/${encodeURIComponent(qortalName)}/qortal_avatar?async=true`
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user