added useBlockedNames

This commit is contained in:
PhilReact 2025-06-29 11:18:06 +03:00
parent 0e23cab129
commit c5ec6fb988
5 changed files with 156 additions and 56 deletions

View File

@ -0,0 +1,42 @@
import { useCallback, useMemo } from "react";
import { useListStore } from "../state/lists";
import { useCacheStore } from "../state/cache";
export const useBlockedNames = () => {
const filterOutItemsByNames = useListStore(state => state.filterOutItemsByNames)
const filterSearchCacheItemsByNames = useCacheStore((s)=> s.filterSearchCacheItemsByNames)
const addToBlockedList = useCallback(async (names: string[]) => {
const response = await qortalRequest({
action: "ADD_LIST_ITEMS",
list_name: "blockedNames",
items: names,
});
if (response === true) {
filterOutItemsByNames(names)
filterSearchCacheItemsByNames(names)
return true;
} else throw new Error("Unable to block names");
}, []);
const removeFromBlockedList = useCallback(async (names: string[]) => {
const response = await qortalRequest({
action: "DELETE_LIST_ITEM",
list_name: "blockedNames",
items: names,
});
if (response === true) {
return true;
} else throw new Error("Unable to remove blocked names");
}, []);
return useMemo(
() => ({
removeFromBlockedList,
addToBlockedList,
}),
[addToBlockedList, removeFromBlockedList]
);
};

View File

@ -23,6 +23,7 @@ export interface Resource {
}
export const useResources = (retryAttempts: number = 2, maxSize = 5242880) => {
const setSearchCache = useCacheStore((s) => s.setSearchCache);
const deleteSearchCache = useCacheStore((s)=> s.deleteSearchCache)
const getSearchCache = useCacheStore((s) => s.getSearchCache);
const getResourceCache = useCacheStore((s) => s.getResourceCache);
const setResourceCache = useCacheStore((s) => s.setResourceCache);
@ -32,7 +33,12 @@ export const useResources = (retryAttempts: number = 2, maxSize = 5242880) => {
const addList = useListStore((s) => s.addList);
const setPublish = usePublishStore((state)=> state.setPublish)
const deleteList = useListStore(state => state.deleteList)
const deleteListInStore = useListStore(state => state.deleteList)
const deleteList = useCallback((listName: string)=> {
deleteListInStore(listName)
deleteSearchCache(listName)
}, [])
const requestControllers = new Map<string, AbortController>();
const getArbitraryResource = async (

View File

@ -11,6 +11,7 @@ export { useListReturn } from './hooks/useListData';
export { useAllResourceStatus } from './hooks/useAllResourceStatus';
export { useQortBalance } from './hooks/useBalance';
export { useAuth } from './hooks/useAuth';
export { useBlockedNames } from './hooks/useBlockedNames';
import './index.css'
export { executeEvent, subscribeToEvent, unsubscribeFromEvent } from './utils/events';
export { formatBytes, formatDuration } from './utils/numbers';

View File

@ -71,6 +71,9 @@ interface CacheState {
resourceCacheExpiryDuration: number;
setSearchCacheExpiryDuration: (duration: number) => void;
setResourceCacheExpiryDuration: (duration: number)=> void;
deleteSearchCache: (listName: string) => void;
filterSearchCacheItemsByNames: (names: string[]) => void;
}
export const useCacheStore = create<CacheState>
@ -128,6 +131,12 @@ export const useCacheStore = create<CacheState>
},
};
}),
deleteSearchCache: (listName) =>
set((state) => {
const updatedSearchCache = { ...state.searchCache };
delete updatedSearchCache[listName];
return { searchCache: updatedSearchCache };
}),
setSearchParamsForList: (listName, searchParamsStringified) =>
set((state) => {
const existingList = state.searchCache[listName] || {};
@ -238,6 +247,27 @@ export const useCacheStore = create<CacheState>
);
return { searchCache: validSearchCache };
}),
filterSearchCacheItemsByNames: (names) =>
set((state) => {
const updatedSearchCache: SearchCache = {};
for (const [listName, list] of Object.entries(state.searchCache)) {
const updatedSearches: { [searchTerm: string]: QortalMetadata[] } = {};
for (const [term, items] of Object.entries(list.searches)) {
updatedSearches[term] = items.filter(
(item) => !names.includes(item.name)
);
}
updatedSearchCache[listName] = {
...list,
searches: updatedSearches,
};
}
return { searchCache: updatedSearchCache };
}),
}),
);

View File

@ -1,8 +1,7 @@
import {create} from "zustand";
import { create } from "zustand";
import { QortalMetadata } from "../types/interfaces/resources";
import { persist } from "zustand/middleware";
interface ListsState {
[listName: string]: {
name: string;
@ -15,15 +14,16 @@ interface ListStore {
// CRUD Operations
addList: (name: string, items: QortalMetadata[]) => void;
removeFromList: (name: string, length: number)=> void;
removeFromList: (name: string, length: number) => void;
addItem: (listName: string, item: QortalMetadata) => void;
addItems: (listName: string, items: QortalMetadata[]) => void;
addItems: (listName: string, items: QortalMetadata[]) => void;
updateItem: (listName: string, item: QortalMetadata) => void;
deleteItem: (listName: string, itemKey: string) => void;
deleteList: (listName: string) => void;
// Getter function
getListByName: (listName: string) => QortalMetadata[]
getListByName: (listName: string) => QortalMetadata[];
filterOutItemsByNames: (names: string[]) => void;
}
export const useListStore = create<ListStore>((set, get) => ({
@ -40,7 +40,13 @@ export const useListStore = create<ListStore>((set, get) => ({
set((state) => ({
lists: {
...state.lists,
[name]: { name, items: state.lists[name].items.slice(0, state.lists[name].items.length - length) }, // ✅ Store items as an array
[name]: {
name,
items: state.lists[name].items.slice(
0,
state.lists[name].items.length - length
),
}, // ✅ Store items as an array
},
})),
@ -50,7 +56,9 @@ export const useListStore = create<ListStore>((set, get) => ({
const itemKey = `${item.name}-${item.service}-${item.identifier}`;
const existingItem = state.lists[listName].items.find(
(existing) => `${existing.name}-${existing.service}-${existing.identifier}` === itemKey
(existing) =>
`${existing.name}-${existing.service}-${existing.identifier}` ===
itemKey
);
if (existingItem) return state; // Avoid duplicates
@ -65,52 +73,51 @@ export const useListStore = create<ListStore>((set, get) => ({
},
};
}),
addItems: (listName, items) =>
set((state) => {
if (!state.lists[listName]) {
console.warn(`List "${listName}" does not exist. Creating a new list.`);
return {
lists: {
...state.lists,
[listName]: { name: listName, items: [...items] }, // ✅ Create new list if missing
},
};
}
// ✅ Generate existing keys correctly
const existingKeys = new Set(
state.lists[listName].items.map(
(item) => `${item.name}-${item.service}-${item.identifier}`
)
);
// ✅ Ensure we correctly compare identifiers
const newItems = items.filter((item) => {
const itemKey = `${item.name}-${item.service}-${item.identifier}`;
const isDuplicate = existingKeys.has(itemKey);
return !isDuplicate; // ✅ Only keep items that are NOT in the existing list
});
if (newItems.length === 0) {
console.warn("No new items were added because they were all considered duplicates.");
return state; // ✅ Prevent unnecessary re-renders if no changes
}
return {
lists: {
...state.lists,
[listName]: {
...state.lists[listName],
items: [...state.lists[listName].items, ...newItems], // ✅ Append only new items
},
},
};
}),
addItems: (listName, items) =>
set((state) => {
if (!state.lists[listName]) {
console.warn(`List "${listName}" does not exist. Creating a new list.`);
return {
lists: {
...state.lists,
[listName]: { name: listName, items: [...items] }, // ✅ Create new list if missing
},
};
}
// ✅ Generate existing keys correctly
const existingKeys = new Set(
state.lists[listName].items.map(
(item) => `${item.name}-${item.service}-${item.identifier}`
)
);
// ✅ Ensure we correctly compare identifiers
const newItems = items.filter((item) => {
const itemKey = `${item.name}-${item.service}-${item.identifier}`;
const isDuplicate = existingKeys.has(itemKey);
return !isDuplicate; // ✅ Only keep items that are NOT in the existing list
});
if (newItems.length === 0) {
console.warn(
"No new items were added because they were all considered duplicates."
);
return state; // ✅ Prevent unnecessary re-renders if no changes
}
return {
lists: {
...state.lists,
[listName]: {
...state.lists[listName],
items: [...state.lists[listName].items, ...newItems], // ✅ Append only new items
},
},
};
}),
updateItem: (listName, item) =>
set((state) => {
if (!state.lists[listName]) return state;
@ -123,7 +130,8 @@ export const useListStore = create<ListStore>((set, get) => ({
[listName]: {
...state.lists[listName],
items: state.lists[listName].items.map((existing) =>
`${existing.name}-${existing.service}-${existing.identifier}` === itemKey
`${existing.name}-${existing.service}-${existing.identifier}` ===
itemKey
? item // ✅ Update item
: existing
),
@ -142,7 +150,8 @@ export const useListStore = create<ListStore>((set, get) => ({
[listName]: {
...state.lists[listName],
items: state.lists[listName].items.filter(
(item) => `${item.name}-${item.service}-${item.identifier}` !== itemKey
(item) =>
`${item.name}-${item.service}-${item.identifier}` !== itemKey
), // ✅ Remove from array
},
},
@ -160,4 +169,16 @@ export const useListStore = create<ListStore>((set, get) => ({
}),
getListByName: (listName) => get().lists[listName]?.items || [], // ✅ Get a list by name
filterOutItemsByNames: (names) =>
set((state) => {
const updatedLists: ListsState = {};
for (const [listName, listData] of Object.entries(state.lists)) {
updatedLists[listName] = {
...listData,
items: listData.items.filter((item) => !names.includes(item.name)),
};
}
return { lists: updatedLists };
}),
}));