refactor: migrate 5chan to the community hooks API (#1073)

* refactor(community-api): migrate 5chan to community hooks

* fix(review): address PR feedback

* fix(review): preserve legacy board context fallbacks

* fix(review): address latest bot feedback

* fix(review): use communityAddress in edit menu privileges
This commit is contained in:
Tommaso Casaburi
2026-03-13 13:25:10 +08:00
committed by GitHub
parent 9dc4d96d27
commit d7703953fb
105 changed files with 2659 additions and 1491 deletions
+130 -90
View File
@@ -8,6 +8,9 @@ interface FilterItem {
enabled: boolean;
count: number;
filteredCids: Set<string>;
communityCounts: Map<string, number>;
communityFilteredCids: Map<string, Set<string>>;
// legacy read/write compatibility
subplebbitCounts: Map<string, number>;
subplebbitFilteredCids: Map<string, Set<string>>;
hide: boolean;
@@ -26,20 +29,64 @@ interface CatalogFiltersStore {
initializeFilter: () => void;
filteredCount: number;
filteredCids: Set<string>;
incrementFilterCount: (filterIndex: number, cid: string, subplebbitAddress: string) => void;
incrementFilterCount: (filterIndex: number, cid: string, communityAddress: string) => void;
recalcFilteredCount: () => void;
currentSubplebbitAddress: string | null;
setCurrentSubplebbitAddress: (address: string | null) => void;
getFilteredCountForCurrentSubplebbit: () => number;
currentCommunityAddress: string | null;
setCurrentCommunityAddress: (address: string | null) => void;
getFilteredCountForCurrentCommunity: () => number;
searchText: string;
setSearchFilter: (text: string) => void;
clearSearchFilter: () => void;
resetCountsForCurrentCommunity: () => void;
// legacy compatibility aliases
currentSubplebbitAddress: string | null;
setCurrentSubplebbitAddress: (address: string | null) => void;
getFilteredCountForCurrentSubplebbit: () => number;
resetCountsForCurrentSubplebbit: () => void;
matchedFilters: Map<string, string>;
setMatchedFilter: (cid: string, color: string) => void;
clearMatchedFilters: () => void;
}
type RawFilterItem = {
text?: string;
enabled?: boolean;
count?: number;
filteredCids?: Set<string>;
communityCounts?: Map<string, number>;
communityFilteredCids?: Map<string, Set<string>>;
subplebbitCounts?: Map<string, number>;
subplebbitFilteredCids?: Map<string, Set<string>>;
hide?: boolean;
top?: boolean;
color?: string;
};
const getCommentCommunityAddress = (comment: Comment): string | undefined => {
return ((comment as { communityAddress?: string }).communityAddress || (comment as { subplebbitAddress?: string }).subplebbitAddress) as string | undefined;
};
const toMap = (value: unknown, fallback: Map<any, any>): Map<string, any> => (value instanceof Map ? (value as Map<string, any>) : fallback);
const normalizeFilterItem = (item: RawFilterItem): FilterItem => {
const communityCounts = toMap(item.communityCounts ?? item.subplebbitCounts, new Map<string, number>());
const communityFilteredCids = toMap(item.communityFilteredCids ?? item.subplebbitFilteredCids, new Map<string, Set<string>>());
return {
text: item.text || '',
enabled: item.enabled ?? true,
count: item.count || 0,
filteredCids: item.filteredCids || new Set<string>(),
communityCounts,
communityFilteredCids,
subplebbitCounts: communityCounts,
subplebbitFilteredCids: communityFilteredCids,
hide: item.hide ?? true,
top: item.top ?? false,
color: item.color || '',
};
};
const useCatalogFiltersStore = create(
persist<CatalogFiltersStore>(
(set, get) => ({
@@ -48,6 +95,7 @@ const useCatalogFiltersStore = create(
filterItems: [],
filteredCount: 0,
filteredCids: new Set<string>(),
currentCommunityAddress: null,
currentSubplebbitAddress: null,
matchedFilters: new Map<string, string>(),
setMatchedFilter: (cid: string, color: string) => {
@@ -64,8 +112,8 @@ const useCatalogFiltersStore = create(
clearMatchedFilters: () => {
set({ matchedFilters: new Map<string, string>() });
},
setCurrentSubplebbitAddress: (address: string | null) => {
const prevAddress = get().currentSubplebbitAddress;
setCurrentCommunityAddress: (address: string | null) => {
const prevAddress = get().currentCommunityAddress;
if (address !== prevAddress) {
set((state) => {
@@ -77,44 +125,49 @@ const useCatalogFiltersStore = create(
newItem.count = 0;
newItem.filteredCids = new Set();
// Ensure subplebbitCounts is a Map
if (!newItem.subplebbitCounts || !(newItem.subplebbitCounts instanceof Map)) {
newItem.subplebbitCounts = new Map();
if (!newItem.communityCounts || !(newItem.communityCounts instanceof Map)) {
newItem.communityCounts = new Map();
}
if (!newItem.communityFilteredCids || !(newItem.communityFilteredCids instanceof Map)) {
newItem.communityFilteredCids = new Map();
}
// Ensure subplebbitFilteredCids is a Map
if (!newItem.subplebbitFilteredCids || !(newItem.subplebbitFilteredCids instanceof Map)) {
newItem.subplebbitFilteredCids = new Map();
}
// keep legacy aliases in sync
newItem.subplebbitCounts = newItem.communityCounts;
newItem.subplebbitFilteredCids = newItem.communityFilteredCids;
// Only initialize for the new address if it doesn't already exist
if (!newItem.subplebbitFilteredCids.has(address)) {
newItem.subplebbitFilteredCids.set(address, new Set<string>());
if (!newItem.communityFilteredCids.has(address)) {
newItem.communityFilteredCids.set(address, new Set<string>());
}
if (!newItem.subplebbitCounts.has(address)) {
newItem.subplebbitCounts.set(address, 0);
if (!newItem.communityCounts.has(address)) {
newItem.communityCounts.set(address, 0);
}
return newItem;
});
return {
currentCommunityAddress: address,
currentSubplebbitAddress: address,
filterItems: updatedFilterItems,
filteredCount: 0, // This will be recalculated below
};
}
return { currentSubplebbitAddress: address };
return {
currentCommunityAddress: address,
currentSubplebbitAddress: address,
};
});
// Recalculate the filtered count for the current subplebbit
// Recalculate the filtered count for the current community
get().recalcFilteredCount();
get().updateFilter();
} else {
set({ currentSubplebbitAddress: address });
set({ currentCommunityAddress: address, currentSubplebbitAddress: address });
}
},
setCurrentSubplebbitAddress: (address: string | null) => get().setCurrentCommunityAddress(address),
searchText: '',
setSearchFilter: (text: string) => {
set({ searchText: text });
@@ -125,34 +178,12 @@ const useCatalogFiltersStore = create(
get().updateFilter();
},
setFilterItems: (items: FilterItem[]) => {
const nonEmptyItems = items
.filter((item) => item.text.trim() !== '')
.map((item) => ({
...item,
count: item.count || 0,
filteredCids: item.filteredCids || new Set(),
subplebbitCounts: item.subplebbitCounts || new Map(),
subplebbitFilteredCids: item.subplebbitFilteredCids || new Map(),
hide: item.hide ?? true,
top: item.top ?? false,
color: item.color || '',
}));
const nonEmptyItems = items.filter((item) => item.text.trim() !== '').map((item) => normalizeFilterItem(item));
set({ filterItems: nonEmptyItems });
get().recalcFilteredCount();
},
saveAndApplyFilters: (items: FilterItem[]) => {
const nonEmptyItems = items
.filter((item) => item.text.trim() !== '')
.map((item) => ({
...item,
count: item.count || 0,
filteredCids: item.filteredCids || new Set(),
subplebbitCounts: item.subplebbitCounts || new Map(),
subplebbitFilteredCids: item.subplebbitFilteredCids || new Map(),
hide: item.hide ?? true,
top: item.top ?? false,
color: item.color || '',
}));
const nonEmptyItems = items.filter((item) => item.text.trim() !== '').map((item) => normalizeFilterItem(item));
// Compare new filter items with existing ones to detect pattern changes
const existingItems = get().filterItems;
@@ -166,8 +197,10 @@ const useCatalogFiltersStore = create(
...newItem,
count: existingItem.count,
filteredCids: existingItem.filteredCids,
subplebbitCounts: existingItem.subplebbitCounts,
subplebbitFilteredCids: existingItem.subplebbitFilteredCids,
communityCounts: existingItem.communityCounts,
communityFilteredCids: existingItem.communityFilteredCids,
subplebbitCounts: existingItem.communityCounts,
subplebbitFilteredCids: existingItem.communityFilteredCids,
color: newItem.color || '',
};
}
@@ -177,6 +210,8 @@ const useCatalogFiltersStore = create(
...newItem,
count: 0,
filteredCids: new Set<string>(),
communityCounts: new Map<string, number>(),
communityFilteredCids: new Map<string, Set<string>>(),
subplebbitCounts: new Map<string, number>(),
subplebbitFilteredCids: new Map<string, Set<string>>(),
color: newItem.color || '',
@@ -200,7 +235,7 @@ const useCatalogFiltersStore = create(
filter: (comment: Comment) => {
if (!comment?.cid) return true;
const currentSubplebbit = state.currentSubplebbitAddress;
const currentCommunityAddress = state.currentCommunityAddress;
// Apply search filter
if (state.searchText.trim() !== '') {
@@ -212,18 +247,19 @@ const useCatalogFiltersStore = create(
// Apply content filters
const { filterItems } = state;
let shouldHide = false;
const commentCommunityAddress = getCommentCommunityAddress(comment);
for (let i = 0; i < filterItems.length; i++) {
const item = filterItems[i];
if (item.enabled && item.text.trim() !== '') {
if (commentMatchesPattern(comment, item.text)) {
// If we have a current subplebbit and this is a match, increment the count
if (currentSubplebbit && comment.subplebbitAddress === currentSubplebbit) {
// If we have a current community and this is a match, increment the count
if (currentCommunityAddress && commentCommunityAddress && commentCommunityAddress === currentCommunityAddress) {
// We need to use a timeout to avoid modifying state during a state update
setTimeout(() => {
const filterIndex = filterItems.findIndex((f) => f.text === item.text && f.enabled);
if (filterIndex !== -1) {
get().incrementFilterCount(filterIndex, comment.cid, comment.subplebbitAddress);
get().incrementFilterCount(filterIndex, comment.cid, commentCommunityAddress);
}
}, 0);
}
@@ -242,37 +278,39 @@ const useCatalogFiltersStore = create(
initializeFilter: () => {
get().updateFilter();
},
incrementFilterCount: (filterIndex: number, cid: string, subplebbitAddress: string) => {
incrementFilterCount: (filterIndex: number, cid: string, communityAddress: string) => {
set((state) => {
const newFilterItems = [...state.filterItems];
if (newFilterItems[filterIndex]) {
const item = newFilterItems[filterIndex];
// Ensure subplebbitFilteredCids is a Map
const subplebbitFilteredCids = new Map(item.subplebbitFilteredCids);
if (!subplebbitFilteredCids.has(subplebbitAddress)) {
subplebbitFilteredCids.set(subplebbitAddress, new Set());
// Ensure communityFilteredCids is a Map
const communityFilteredCids = new Map(item.communityFilteredCids);
if (!communityFilteredCids.has(communityAddress)) {
communityFilteredCids.set(communityAddress, new Set());
}
const cidSet = subplebbitFilteredCids.get(subplebbitAddress)!;
const cidSet = communityFilteredCids.get(communityAddress)!;
// Only increment the count if this CID hasn't been counted for this subplebbit yet
// Only increment the count if this CID hasn't been counted for this community yet
if (!cidSet.has(cid)) {
const newItemFilteredCids = new Set(item.filteredCids);
newItemFilteredCids.add(cid);
cidSet.add(cid);
subplebbitFilteredCids.set(subplebbitAddress, cidSet);
communityFilteredCids.set(communityAddress, cidSet);
const subplebbitCounts = new Map(item.subplebbitCounts);
const currentCount = subplebbitCounts.get(subplebbitAddress) || 0;
subplebbitCounts.set(subplebbitAddress, currentCount + 1);
const communityCounts = new Map(item.communityCounts);
const currentCount = communityCounts.get(communityAddress) || 0;
communityCounts.set(communityAddress, currentCount + 1);
newFilterItems[filterIndex] = {
...item,
count: item.count + 1,
filteredCids: newItemFilteredCids,
subplebbitCounts,
subplebbitFilteredCids,
communityCounts,
communityFilteredCids,
subplebbitCounts: communityCounts,
subplebbitFilteredCids: communityFilteredCids,
};
return { filterItems: newFilterItems };
@@ -285,13 +323,13 @@ const useCatalogFiltersStore = create(
},
recalcFilteredCount: () => {
set((state) => {
const currentSubplebbit = state.currentSubplebbitAddress;
if (!currentSubplebbit) return { filteredCount: 0 };
const currentCommunityAddress = state.currentCommunityAddress;
if (!currentCommunityAddress) return { filteredCount: 0 };
let filteredCount = 0;
for (const item of state.filterItems) {
if (item.enabled && item.hide) {
const subCount = item.subplebbitCounts?.get(currentSubplebbit) || 0;
const subCount = item.communityCounts?.get(currentCommunityAddress) || 0;
filteredCount += subCount;
}
}
@@ -299,40 +337,45 @@ const useCatalogFiltersStore = create(
return { filteredCount };
});
},
getFilteredCountForCurrentSubplebbit: () => {
getFilteredCountForCurrentCommunity: () => {
const state = get();
const currentSubplebbit = state.currentSubplebbitAddress;
if (!currentSubplebbit) return 0;
const currentCommunityAddress = state.currentCommunityAddress;
if (!currentCommunityAddress) return 0;
let filteredCount = 0;
for (const item of state.filterItems) {
if (item.enabled && item.hide) {
const subCount = item.subplebbitCounts?.get(currentSubplebbit) || 0;
const subCount = item.communityCounts?.get(currentCommunityAddress) || 0;
filteredCount += subCount;
}
}
return filteredCount;
},
resetCountsForCurrentSubplebbit: () => {
const currentSubplebbit = get().currentSubplebbitAddress;
if (!currentSubplebbit) return;
getFilteredCountForCurrentSubplebbit: () => get().getFilteredCountForCurrentCommunity(),
resetCountsForCurrentCommunity: () => {
const currentCommunityAddress = get().currentCommunityAddress;
if (!currentCommunityAddress) return;
set((state) => {
const updatedFilterItems = state.filterItems.map((item) => {
const newItem = { ...item };
// Ensure maps are properly initialized
if (!newItem.subplebbitCounts || !(newItem.subplebbitCounts instanceof Map)) {
newItem.subplebbitCounts = new Map();
if (!newItem.communityCounts || !(newItem.communityCounts instanceof Map)) {
newItem.communityCounts = new Map();
}
if (!newItem.subplebbitFilteredCids || !(newItem.subplebbitFilteredCids instanceof Map)) {
newItem.subplebbitFilteredCids = new Map();
if (!newItem.communityFilteredCids || !(newItem.communityFilteredCids instanceof Map)) {
newItem.communityFilteredCids = new Map();
}
// Reset counts for current subplebbit
newItem.subplebbitCounts.set(currentSubplebbit, 0);
newItem.subplebbitFilteredCids.set(currentSubplebbit, new Set<string>());
// keep legacy aliases in sync
newItem.subplebbitCounts = newItem.communityCounts;
newItem.subplebbitFilteredCids = newItem.communityFilteredCids;
// Reset counts for current community
newItem.communityCounts.set(currentCommunityAddress, 0);
newItem.communityFilteredCids.set(currentCommunityAddress, new Set<string>());
return newItem;
});
@@ -346,6 +389,7 @@ const useCatalogFiltersStore = create(
// Trigger filter reapplication to start counting again
get().updateFilter();
},
resetCountsForCurrentSubplebbit: () => get().resetCountsForCurrentCommunity(),
}),
{
name: 'catalog-filters-storage',
@@ -365,19 +409,15 @@ const useCatalogFiltersStore = create(
if (persistedObj && persistedObj.filterItems) {
return {
...persistedObj,
filterItems: persistedObj.filterItems.map((item: any) => ({
text: item.text,
enabled: item.enabled,
hide: item.hide,
top: item.top,
count: 0,
filteredCids: new Set<string>(),
subplebbitCounts: new Map<string, number>(),
subplebbitFilteredCids: new Map<string, Set<string>>(),
currentCommunityAddress: persistedObj.currentCommunityAddress || persistedObj.currentSubplebbitAddress || null,
currentSubplebbitAddress: persistedObj.currentCommunityAddress || persistedObj.currentSubplebbitAddress || null,
filterItems: persistedObj.filterItems.map((item: RawFilterItem) => ({
...normalizeFilterItem(item),
})),
filteredCount: 0,
};
}
return persistedObj || persisted;
},
},
@@ -0,0 +1,46 @@
import { useEffect, useMemo } from 'react';
import { create } from 'zustand';
interface CommunitiesLoadingStartTimestampsState {
timestamps: Record<string, number>;
addCommunities: (communityAddresses: string[]) => void;
}
const useCommunitiesLoadingStartTimestampsStore = create<CommunitiesLoadingStartTimestampsState>((set, get) => ({
timestamps: {},
addCommunities: (communityAddresses) => {
const { timestamps } = get();
const newTimestamps: Record<string, number> = {};
communityAddresses.forEach((communityAddress) => {
if (!timestamps[communityAddress]) {
newTimestamps[communityAddress] = Math.round(Date.now() / 1000);
}
});
if (Object.keys(newTimestamps).length) {
set((state) => ({ timestamps: { ...state.timestamps, ...newTimestamps } }));
}
},
}));
const useCommunitiesLoadingStartTimestamps = (communityAddresses?: string[]) => {
const timestampsStore = useCommunitiesLoadingStartTimestampsStore((state) => state.timestamps);
const addCommunities = useCommunitiesLoadingStartTimestampsStore((state) => state.addCommunities);
useEffect(() => {
if (communityAddresses) {
addCommunities(communityAddresses);
}
}, [communityAddresses, addCommunities]);
const communitiesLoadingStartTimestamps = useMemo(() => {
return communityAddresses?.map((communityAddress) => timestampsStore[communityAddress]) || [];
}, [timestampsStore, communityAddresses]);
return communitiesLoadingStartTimestamps;
};
export const useSubplebbitsLoadingStartTimestamps = useCommunitiesLoadingStartTimestamps;
export default useCommunitiesLoadingStartTimestamps;
+58
View File
@@ -0,0 +1,58 @@
import { create } from 'zustand';
interface CommunityOfflineState {
state?: string;
updatedAt?: number;
updatingState?: string;
initialLoad: boolean;
}
interface CommunityOfflineStore {
communityOfflineState: Record<string, CommunityOfflineState>;
setCommunityOfflineState: (address: string, state: Partial<CommunityOfflineState>) => void;
initializeCommunityOfflineState: (address: string) => void;
}
const useCommunityOfflineStore = create<CommunityOfflineStore>((set) => ({
communityOfflineState: {},
setCommunityOfflineState: (address, newState) =>
set((state) => ({
communityOfflineState: {
...state.communityOfflineState,
[address]: {
...state.communityOfflineState[address],
...newState,
},
},
})),
initializeCommunityOfflineState: (address) => {
set((state) => ({
communityOfflineState: {
...state.communityOfflineState,
[address]: {
initialLoad: true,
},
},
}));
setTimeout(() => {
set((state) => ({
communityOfflineState: {
...state.communityOfflineState,
[address]: {
...state.communityOfflineState[address],
initialLoad: false,
},
},
}));
}, 30_000);
},
}));
/**
* Back-compat exports for old naming.
*/
export const useSubplebbitOfflineStore = useCommunityOfflineStore;
export const useCommunityOfflineStoreForLegacy = useCommunityOfflineStore;
export default useCommunityOfflineStore;
+2 -3
View File
@@ -2,8 +2,7 @@ import { create } from 'zustand';
import type { Comment } from '@bitsocialnet/bitsocial-react-hooks';
interface PostNumberState {
// Post numbers are only unique within a subplebbit, so scope by address
// to avoid collisions in /all/ where multiple boards are shown together.
// Post numbers are only unique within a board, so scope by canonical community address.
numberToCid: Record<string, Record<number, string>>;
cidToNumber: Record<string, number>;
registerComments: (comments: Comment[]) => void;
@@ -23,7 +22,7 @@ const usePostNumberStore = create<PostNumberState>((set) => ({
for (const c of comments) {
const num = c?.number;
const cid = c?.cid;
const addr = c?.subplebbitAddress;
const addr = c?.communityAddress || c?.subplebbitAddress;
if (typeof num !== 'number' || !cid || !addr) continue;
const existingCid = nextNumberToCid[addr]?.[num];
+8 -2
View File
@@ -5,6 +5,7 @@ import { alertChallengeVerificationFailed } from '../lib/utils/challenge-utils';
type SubmitState = {
author?: any | undefined;
displayName?: string | undefined;
communityAddress: string | undefined;
subplebbitAddress: string | undefined;
title: string | undefined;
content: string | undefined;
@@ -18,6 +19,7 @@ type SubmitState = {
const usePublishPostStore = create<SubmitState>((set) => ({
author: undefined,
displayName: undefined,
communityAddress: undefined,
subplebbitAddress: undefined,
title: undefined,
content: undefined,
@@ -27,6 +29,7 @@ const usePublishPostStore = create<SubmitState>((set) => ({
setPublishPostStore: (comment: Comment) =>
set(() => {
const { subplebbitAddress, author, content, link, spoiler, title } = comment;
const communityAddress = (comment as { communityAddress?: string }).communityAddress || subplebbitAddress;
const displayName = 'displayName' in comment ? comment.displayName || undefined : author?.displayName;
@@ -36,7 +39,8 @@ const usePublishPostStore = create<SubmitState>((set) => ({
const updatedAuthor = displayName ? { ...baseAuthor, displayName } : baseAuthor;
const publishCommentOptions: PublishCommentOptions = {
subplebbitAddress,
communityAddress,
subplebbitAddress: communityAddress,
title,
content,
link,
@@ -57,7 +61,8 @@ const usePublishPostStore = create<SubmitState>((set) => ({
return {
author: updatedAuthor,
displayName,
subplebbitAddress,
communityAddress,
subplebbitAddress: communityAddress,
title,
content,
link,
@@ -70,6 +75,7 @@ const usePublishPostStore = create<SubmitState>((set) => ({
author: undefined,
displayName: undefined,
subplebbitAddress: undefined,
communityAddress: undefined,
title: undefined,
content: undefined,
link: undefined,
+4 -2
View File
@@ -23,7 +23,8 @@ const usePublishReplyStore = create<ReplyState>((set) => ({
setPublishReplyStore: (comment: Comment) =>
set((state) => {
const { subplebbitAddress, parentCid, author, content, link, spoiler } = comment;
const { parentCid, author, content, link, spoiler } = comment;
const communityAddress = (comment as { communityAddress?: string }).communityAddress || (comment as { subplebbitAddress?: string }).subplebbitAddress;
const displayName = 'displayName' in comment ? comment.displayName || undefined : author?.displayName;
@@ -33,7 +34,8 @@ const usePublishReplyStore = create<ReplyState>((set) => ({
const updatedAuthor = displayName ? { ...baseAuthor, displayName } : baseAuthor;
const publishCommentOptions: PublishCommentOptions = {
subplebbitAddress,
communityAddress,
subplebbitAddress: communityAddress,
parentCid,
postCid: comment?.postCid || parentCid,
content,
+31 -43
View File
@@ -1,51 +1,39 @@
import { create } from 'zustand';
import useCommunityOfflineStore from './use-community-offline-store';
interface SubplebbitOfflineState {
type LegacySubplebbitOfflineState = {
initialLoad: boolean;
state?: string;
updatedAt?: number;
updatingState?: string;
initialLoad: boolean;
}
};
interface SubplebbitOfflineStore {
subplebbitOfflineState: Record<string, SubplebbitOfflineState>;
setSubplebbitOfflineState: (address: string, state: Partial<SubplebbitOfflineState>) => void;
type LegacySubplebbitOfflineStore = {
subplebbitOfflineState: Record<string, LegacySubplebbitOfflineState>;
setSubplebbitOfflineState: (address: string, state: Partial<LegacySubplebbitOfflineState>) => void;
initializesubplebbitOfflineState: (address: string) => void;
}
};
const useSubplebbitOfflineStore = create<SubplebbitOfflineStore>((set) => ({
subplebbitOfflineState: {},
setSubplebbitOfflineState: (address, newState) =>
set((state) => ({
subplebbitOfflineState: {
...state.subplebbitOfflineState,
[address]: {
...state.subplebbitOfflineState[address],
...newState,
},
},
})),
initializesubplebbitOfflineState: (address) => {
set((state) => ({
subplebbitOfflineState: {
...state.subplebbitOfflineState,
[address]: {
initialLoad: true,
},
},
}));
setTimeout(() => {
set((state) => ({
subplebbitOfflineState: {
...state.subplebbitOfflineState,
[address]: {
...state.subplebbitOfflineState[address],
initialLoad: false,
},
},
}));
}, 30000);
},
}));
type CommunityOfflineStoreState = {
communityOfflineState: Record<string, LegacySubplebbitOfflineState>;
setCommunityOfflineState: (address: string, state: Partial<LegacySubplebbitOfflineState>) => void;
initializeCommunityOfflineState: (address: string) => void;
};
export default useSubplebbitOfflineStore;
const toLegacyState = (state: CommunityOfflineStoreState) => ({
subplebbitOfflineState: state.communityOfflineState,
setSubplebbitOfflineState: state.setCommunityOfflineState,
initializesubplebbitOfflineState: state.initializeCommunityOfflineState,
});
const useSubplebbitOfflineStore = (): LegacySubplebbitOfflineStore => {
const state = useCommunityOfflineStore();
return toLegacyState(state);
};
const useSubplebbitOfflineStoreWithState = useSubplebbitOfflineStore as typeof useSubplebbitOfflineStore & {
getState: () => LegacySubplebbitOfflineStore;
};
useSubplebbitOfflineStoreWithState.getState = () => toLegacyState(useCommunityOfflineStore.getState());
export { useSubplebbitOfflineStore };
export default useSubplebbitOfflineStoreWithState;
@@ -1,42 +1,8 @@
import { useEffect, useMemo } from 'react';
import { create } from 'zustand';
import useSubplebbitStore from './use-communities-loading-start-timestamps-store';
interface SubplebbitsLoadingStartTimestampsState {
timestamps: Record<string, number>;
addSubplebbits: (subplebbitAddresses: string[]) => void;
}
const useSubplebbitsLoadingStartTimestampsStore = create<SubplebbitsLoadingStartTimestampsState>((set, get) => ({
timestamps: {},
addSubplebbits: (subplebbitAddresses) => {
const { timestamps } = get();
const newTimestamps: Record<string, number> = {};
subplebbitAddresses.forEach((subplebbitAddress) => {
if (!timestamps[subplebbitAddress]) {
newTimestamps[subplebbitAddress] = Math.round(Date.now() / 1000);
}
});
if (Object.keys(newTimestamps).length) {
set((state) => ({ timestamps: { ...state.timestamps, ...newTimestamps } }));
}
},
}));
const useSubplebbitsLoadingStartTimestamps = (subplebbitAddresses?: string[]) => {
const timestampsStore = useSubplebbitsLoadingStartTimestampsStore((state) => state.timestamps);
const addSubplebbits = useSubplebbitsLoadingStartTimestampsStore((state) => state.addSubplebbits);
useEffect(() => {
if (subplebbitAddresses) {
addSubplebbits(subplebbitAddresses);
}
}, [subplebbitAddresses, addSubplebbits]);
const subplebbitsLoadingStartTimestamps = useMemo(() => {
return subplebbitAddresses?.map((subplebbitAddress) => timestampsStore[subplebbitAddress]) || [];
}, [timestampsStore, subplebbitAddresses]);
return subplebbitsLoadingStartTimestamps;
const useSubplebbitLoadingStartTimestamps = (subplebbitAddresses?: string[]) => {
const addLegacyInput = subplebbitAddresses?.map((address) => address);
return useSubplebbitStore(addLegacyInput);
};
export default useSubplebbitsLoadingStartTimestamps;
export default useSubplebbitLoadingStartTimestamps;