mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
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:
@@ -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;
|
||||
@@ -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,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];
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user