mirror of
https://github.com/Qortal/qapp-core.git
synced 2025-06-13 09:21:20 +00:00
modified localstorage data
This commit is contained in:
parent
9663ab2459
commit
f0c1b956ac
11
package-lock.json
generated
11
package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "qapp-core",
|
||||
"version": "1.0.19",
|
||||
"version": "1.0.22",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "qapp-core",
|
||||
"version": "1.0.19",
|
||||
"version": "1.0.22",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@tanstack/react-virtual": "^3.13.2",
|
||||
@ -15,6 +15,7 @@
|
||||
"compressorjs": "^1.2.1",
|
||||
"crypto-js": "^4.2.0",
|
||||
"dayjs": "^1.11.13",
|
||||
"dexie": "^4.0.11",
|
||||
"dompurify": "^3.2.4",
|
||||
"react-dropzone": "^14.3.8",
|
||||
"react-hot-toast": "^2.5.2",
|
||||
@ -1871,6 +1872,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/dexie": {
|
||||
"version": "4.0.11",
|
||||
"resolved": "https://registry.npmjs.org/dexie/-/dexie-4.0.11.tgz",
|
||||
"integrity": "sha512-SOKO002EqlvBYYKQSew3iymBoN2EQ4BDw/3yprjh7kAfFzjBYkaMNa/pZvcA7HSWlcKSQb9XhPe3wKyQ0x4A8A==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/dir-glob": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "qapp-core",
|
||||
"version": "1.0.22",
|
||||
"version": "1.0.24",
|
||||
"description": "Qortal's core React library with global state, UI components, and utilities",
|
||||
"main": "dist/index.js",
|
||||
"module": "dist/index.mjs",
|
||||
@ -29,6 +29,7 @@
|
||||
"compressorjs": "^1.2.1",
|
||||
"crypto-js": "^4.2.0",
|
||||
"dayjs": "^1.11.13",
|
||||
"dexie": "^4.0.11",
|
||||
"dompurify": "^3.2.4",
|
||||
"react-dropzone": "^14.3.8",
|
||||
"react-hot-toast": "^2.5.2",
|
||||
|
@ -4,7 +4,7 @@ import { useResources } from "../hooks/useResources";
|
||||
import { useAppInfo } from "../hooks/useAppInfo";
|
||||
import { useIdentifiers } from "../hooks/useIdentifiers";
|
||||
import { Toaster } from "react-hot-toast";
|
||||
import { useLocalStorage } from "../hooks/useLocalStorage";
|
||||
import { usePersistentStore } from "../hooks/usePersistentStore";
|
||||
import { IndexManager } from "../components/IndexManager/IndexManager";
|
||||
import { useIndexes } from "../hooks/useIndexes";
|
||||
|
||||
@ -18,7 +18,7 @@ auth: ReturnType<typeof useAuth>;
|
||||
lists: ReturnType<typeof useResources>;
|
||||
appInfo: ReturnType<typeof useAppInfo>;
|
||||
identifierOperations: ReturnType<typeof useIdentifiers>
|
||||
localStorageOperations: ReturnType<typeof useLocalStorage>
|
||||
persistentOperations: ReturnType<typeof usePersistentStore>
|
||||
indexOperations: ReturnType<typeof useIndexes>
|
||||
}
|
||||
|
||||
@ -48,10 +48,10 @@ export const GlobalProvider = ({ children, config, toastStyle = {} }: GlobalProv
|
||||
const appInfo = useAppInfo(config.appName, config?.publicSalt)
|
||||
const lists = useResources()
|
||||
const identifierOperations = useIdentifiers(config.publicSalt, config.appName)
|
||||
const localStorageOperations = useLocalStorage(config.publicSalt, config.appName)
|
||||
const persistentOperations = usePersistentStore(config.publicSalt, config.appName, auth?.address)
|
||||
const indexOperations = useIndexes()
|
||||
// ✅ Merge all hooks into a single `contextValue`
|
||||
const contextValue = useMemo(() => ({ auth, lists, appInfo, identifierOperations, localStorageOperations, indexOperations }), [auth, lists, appInfo, identifierOperations, localStorageOperations]);
|
||||
const contextValue = useMemo(() => ({ auth, lists, appInfo, identifierOperations, persistentOperations, indexOperations }), [auth, lists, appInfo, identifierOperations, persistentOperations]);
|
||||
|
||||
|
||||
return (
|
||||
|
@ -1,37 +0,0 @@
|
||||
import React, { useCallback, useEffect, useMemo } from "react";
|
||||
import { useAppStore } from "../state/app";
|
||||
import { EnumCollisionStrength, hashWord } from "../utils/encryption";
|
||||
|
||||
|
||||
export const useLocalStorage = (publicSalt: string, appName: string) => {
|
||||
|
||||
|
||||
const setTimestamp = useCallback(async (timestamp: number, storageId: string)=> {
|
||||
const hashedString = await hashWord(`${appName}-${storageId}`, EnumCollisionStrength.HIGH, publicSalt)
|
||||
localStorage.setItem(hashedString, JSON.stringify(timestamp));
|
||||
return true
|
||||
}, [appName, publicSalt])
|
||||
|
||||
const getTimestamp = useCallback(async ( storageId: string)=> {
|
||||
const hashedString = await hashWord(`${appName}-${storageId}`, EnumCollisionStrength.HIGH, publicSalt)
|
||||
const stored = localStorage.getItem(hashedString);
|
||||
if(stored){
|
||||
return JSON.parse(stored)
|
||||
} else return null
|
||||
}, [appName, publicSalt])
|
||||
|
||||
const isNewTimestamp = useCallback(async( storageId: string, differenceTimestamp: number)=> {
|
||||
const hashedString = await hashWord(`${appName}-${storageId}`, EnumCollisionStrength.HIGH, publicSalt)
|
||||
const stored = localStorage.getItem(hashedString);
|
||||
if(stored){
|
||||
const storedTimestamp = JSON.parse(stored)
|
||||
return (Date.now() - storedTimestamp) > differenceTimestamp
|
||||
} else return true
|
||||
}, [appName, publicSalt])
|
||||
return {
|
||||
setTimestamp,
|
||||
getTimestamp,
|
||||
isNewTimestamp
|
||||
|
||||
};
|
||||
};
|
88
src/hooks/usePersistentStore.tsx
Normal file
88
src/hooks/usePersistentStore.tsx
Normal file
@ -0,0 +1,88 @@
|
||||
import { useCallback } from 'react';
|
||||
import { EnumCollisionStrength, hashWord } from '../utils/encryption';
|
||||
import { db } from '../utils/persistentDb';
|
||||
|
||||
export const usePersistentStore = (
|
||||
publicSalt: string,
|
||||
appName: string,
|
||||
qortalAddress?: string | null
|
||||
) => {
|
||||
const getHashedId = useCallback(
|
||||
async (id: string) => {
|
||||
const key = `${appName}-${qortalAddress ?? 'no-address'}-${id}`;
|
||||
return await hashWord(key, EnumCollisionStrength.HIGH, publicSalt);
|
||||
},
|
||||
[appName, publicSalt, qortalAddress]
|
||||
);
|
||||
|
||||
// --- TIMESTAMP FUNCTIONS ---
|
||||
|
||||
const setTimestamp = useCallback(
|
||||
async (timestamp: number, storageId: string) => {
|
||||
const id = await getHashedId(storageId);
|
||||
await db.timestamps.put({ id, timestamp });
|
||||
return true;
|
||||
},
|
||||
[getHashedId]
|
||||
);
|
||||
|
||||
const getTimestamp = useCallback(
|
||||
async (storageId: string) => {
|
||||
const id = await getHashedId(storageId);
|
||||
const entry = await db.timestamps.get(id);
|
||||
return entry?.timestamp ?? null;
|
||||
},
|
||||
[getHashedId]
|
||||
);
|
||||
|
||||
const isNewTimestamp = useCallback(
|
||||
async (storageId: string, differenceTimestamp: number) => {
|
||||
const id = await getHashedId(storageId);
|
||||
const entry = await db.timestamps.get(id);
|
||||
if (!entry) return true;
|
||||
return Date.now() - entry.timestamp > differenceTimestamp;
|
||||
},
|
||||
[getHashedId]
|
||||
);
|
||||
|
||||
// --- GENERIC CRUD FOR DYNAMIC DATA ---
|
||||
|
||||
const saveData = useCallback(
|
||||
async (id: string, data: any) => {
|
||||
const hashedId = await getHashedId(id);
|
||||
await db.dynamicData.put({ id: hashedId, data });
|
||||
},
|
||||
[getHashedId]
|
||||
);
|
||||
|
||||
const getData = useCallback(
|
||||
async (id: string) => {
|
||||
const hashedId = await getHashedId(id);
|
||||
const entry = await db.dynamicData.get(hashedId);
|
||||
return entry?.data ?? null;
|
||||
},
|
||||
[getHashedId]
|
||||
);
|
||||
|
||||
const deleteData = useCallback(
|
||||
async (id: string) => {
|
||||
const hashedId = await getHashedId(id);
|
||||
await db.dynamicData.delete(hashedId);
|
||||
},
|
||||
[getHashedId]
|
||||
);
|
||||
|
||||
const listAllData = useCallback(async () => {
|
||||
return await db.dynamicData.toArray();
|
||||
}, []);
|
||||
|
||||
return {
|
||||
setTimestamp,
|
||||
getTimestamp,
|
||||
isNewTimestamp,
|
||||
saveData,
|
||||
getData,
|
||||
deleteData,
|
||||
listAllData,
|
||||
};
|
||||
};
|
26
src/utils/persistentDb.ts
Normal file
26
src/utils/persistentDb.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import Dexie, { Table } from 'dexie';
|
||||
|
||||
export interface TimestampEntry {
|
||||
id: string; // hashed key
|
||||
timestamp: number;
|
||||
}
|
||||
|
||||
export interface DynamicEntry {
|
||||
id: string;
|
||||
data: any;
|
||||
}
|
||||
|
||||
class AppDatabase extends Dexie {
|
||||
timestamps!: Table<TimestampEntry>;
|
||||
dynamicData!: Table<DynamicEntry>;
|
||||
|
||||
constructor() {
|
||||
super('MyAppDB');
|
||||
this.version(1).stores({
|
||||
timestamps: 'id',
|
||||
dynamicData: 'id',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export const db = new AppDatabase();
|
Loading…
x
Reference in New Issue
Block a user