added index manager

This commit is contained in:
PhilReact 2025-04-03 09:01:19 +03:00
parent 86689af488
commit 28fd2fd2d1
7 changed files with 197 additions and 2 deletions

View 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>;
};

View File

@ -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
View 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,
};
};

View File

@ -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
View 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 }),
}));

View File

@ -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
View File

@ -0,0 +1,3 @@
export const createAvatarLink = (qortalName: string)=> {
return `/arbitrary/THUMBNAIL/${encodeURIComponent(qortalName)}/qortal_avatar?async=true`
}