added appInfo

This commit is contained in:
PhilReact 2025-03-17 20:29:05 +02:00
parent 148f947fa5
commit 7b4e187fdc
6 changed files with 673 additions and 605 deletions

1189
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{ {
"name": "qapp-core", "name": "qapp-core",
"version": "1.0.4", "version": "1.0.6",
"description": "Qortal's core React library with global state, UI components, and utilities", "description": "Qortal's core React library with global state, UI components, and utilities",
"main": "dist/index.js", "main": "dist/index.js",
"module": "dist/index.mjs", "module": "dist/index.mjs",
@ -26,12 +26,13 @@
"@mui/material": "^6.4.7", "@mui/material": "^6.4.7",
"@tanstack/react-virtual": "^3.13.2", "@tanstack/react-virtual": "^3.13.2",
"@types/react": "^19.0.10", "@types/react": "^19.0.10",
"buffer": "^6.0.3",
"react": "^19.0.0", "react": "^19.0.0",
"react-intersection-observer": "^9.16.0", "react-intersection-observer": "^9.16.0",
"zustand": "^4.3.2" "zustand": "^4.3.2"
}, },
"devDependencies": { "devDependencies": {
"tsup": "^7.0.0", "tsup": "^8.4.0",
"typescript": "^5.2.0" "typescript": "^5.2.0"
}, },
"repository": { "repository": {

View File

@ -1,6 +1,7 @@
import React, { createContext, useContext, useMemo } from "react"; import React, { createContext, useContext, useMemo } from "react";
import { useAuth, UseAuthProps } from "../hooks/useAuth"; import { useAuth, UseAuthProps } from "../hooks/useAuth";
import { useResources } from "../hooks/useResources"; import { useResources } from "../hooks/useResources";
import { useAppInfo } from "../hooks/useAppInfo";
// ✅ Define Global Context Type // ✅ Define Global Context Type
@ -15,6 +16,8 @@ interface GlobalProviderProps {
config?: { config?: {
/** Authentication settings. */ /** Authentication settings. */
auth?: UseAuthProps; auth?: UseAuthProps;
appName: string;
publicSalt: string
}; };
} }
@ -25,10 +28,11 @@ const GlobalContext = createContext<GlobalContextType | null>(null);
export const GlobalProvider = ({ children, config }: GlobalProviderProps) => { export const GlobalProvider = ({ children, config }: GlobalProviderProps) => {
// ✅ Call hooks and pass in options dynamically // ✅ Call hooks and pass in options dynamically
const auth = useAuth(config?.auth || {}); const auth = useAuth(config?.auth || {});
const appInfo = useAppInfo(config?.appName, config?.publicSalt)
const resources = useResources() const resources = useResources()
// ✅ Merge all hooks into a single `contextValue` // ✅ Merge all hooks into a single `contextValue`
const contextValue = useMemo(() => ({ auth, resources }), [auth, resources]); const contextValue = useMemo(() => ({ auth, resources, appInfo }), [auth, resources, appInfo]);
return ( return (
<GlobalContext.Provider value={contextValue}> <GlobalContext.Provider value={contextValue}>

32
src/hooks/useAppInfo.tsx Normal file
View File

@ -0,0 +1,32 @@
import React, { useCallback, useEffect, useMemo, useRef } from "react";
import { useAuthStore } from "../state/auth";
import { useAppStore } from "../state/app";
import { EnumCollisionStrength, hashWord } from "../utils/encryption";
export const useAppInfo = (appName?: string, publicSalt?: string) => {
const setAppState = useAppStore().setAppState
const appNameHashed = useMemo(()=> {
if(!appName) return ""
}, [appName])
const handleAppInfoSetup = useCallback(async (name: string, salt: string)=> {
const appNameHashed = await hashWord(name, EnumCollisionStrength.LOW, salt)
setAppState({
appName: name,
publicSalt: salt,
appNameHashed
})
}, [])
useEffect(()=> {
if(appName && publicSalt){
handleAppInfoSetup(appName, publicSalt)
}
}, [appName, publicSalt, handleAppInfoSetup])
return {
appName,
appNameHashed
};
};

21
src/state/app.ts Normal file
View File

@ -0,0 +1,21 @@
import { create } from "zustand";
interface AppState {
appName: string | null;
publicSalt: string | null;
appNameHashed: string | null;
// Methods
setAppState: (appState: { appName: string; publicSalt: string; appNameHashed: string }) => void;
}
// ✅ Typed Zustand Store
export const useAppStore = create<AppState>((set) => ({
appName: null,
publicSalt: null,
appNameHashed: null,
// Methods
setAppState: (appState) =>
set({ appName: appState.appName, publicSalt: appState.publicSalt, appNameHashed: appState.appNameHashed })
}));

15
src/utils/encryption.ts Normal file
View File

@ -0,0 +1,15 @@
import { Buffer } from "buffer";
export enum EnumCollisionStrength {
LOW = 8,
MEDIUM = 11,
HIGH = 14
}
export async function hashWord(word: string, collisionStrength: number, publicSalt: string) {
const saltedWord = publicSalt + word; // Use public salt directly
const encoded = new TextEncoder().encode(saltedWord);
const hashBuffer = await crypto.subtle.digest("SHA-256", encoded);
return Buffer.from(hashBuffer).toString("base64").slice(0, collisionStrength);
}