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:
@@ -0,0 +1,80 @@
|
||||
import useCommunitiesStore from '@bitsocialnet/bitsocial-react-hooks/dist/stores/communities';
|
||||
import type { Community } from '@bitsocialnet/bitsocial-react-hooks';
|
||||
import { normalizeBoardAddress } from './use-directories';
|
||||
|
||||
type CommunityLike = Record<string, unknown> | Community | undefined;
|
||||
|
||||
const getCommunityByAddress = (communities: Record<string, unknown> | undefined, communityAddress: string | undefined) => {
|
||||
if (!communities || !communityAddress) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const exactMatch = communities[communityAddress];
|
||||
if (exactMatch) {
|
||||
return exactMatch;
|
||||
}
|
||||
|
||||
const normalizedAddress = normalizeBoardAddress(communityAddress);
|
||||
return Object.entries(communities).find(([key, community]) => {
|
||||
const candidateAddress = typeof (community as CommunityLike)?.address === 'string' ? (community as CommunityLike)?.address : key;
|
||||
return normalizeBoardAddress(candidateAddress) === normalizedAddress;
|
||||
})?.[1];
|
||||
};
|
||||
|
||||
const shallowEqual = (obj1: Record<string, any> | undefined, obj2: Record<string, any> | undefined): boolean => {
|
||||
if (obj1 === obj2) return true;
|
||||
if (!obj1 || !obj2) return obj1 === obj2;
|
||||
const keys1 = Object.keys(obj1);
|
||||
const keys2 = Object.keys(obj2);
|
||||
if (keys1.length !== keys2.length) return false;
|
||||
|
||||
for (const key of keys1) {
|
||||
if (obj1[key] !== obj2[key]) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Ignore transient lifecycle props when deciding whether to update hook consumers.
|
||||
*/
|
||||
const isCommunityEqual = (prev: any, next: any): boolean => {
|
||||
if (prev === next) return true;
|
||||
if (!prev || !next) return prev === next;
|
||||
|
||||
return (
|
||||
prev.address === next.address &&
|
||||
prev.title === next.title &&
|
||||
prev.shortAddress === next.shortAddress &&
|
||||
prev.createdAt === next.createdAt &&
|
||||
prev.updatedAt === next.updatedAt &&
|
||||
prev.description === next.description &&
|
||||
shallowEqual(prev.roles, next.roles)
|
||||
);
|
||||
};
|
||||
|
||||
export const useStableCommunity = (communityAddress: string | undefined) => {
|
||||
const community = useCommunitiesStore((state) => {
|
||||
return getCommunityByAddress(state.communities, communityAddress) as Community | undefined;
|
||||
}, isCommunityEqual);
|
||||
|
||||
return community;
|
||||
};
|
||||
|
||||
export const useCommunityField = <T>(communityAddress: string | undefined, selector: (community: any) => T): T | undefined => {
|
||||
const field = useCommunitiesStore(
|
||||
(state) => {
|
||||
const community = getCommunityByAddress(state.communities, communityAddress);
|
||||
return community ? selector(community) : undefined;
|
||||
},
|
||||
(prev, next) => prev === next,
|
||||
);
|
||||
|
||||
return field;
|
||||
};
|
||||
|
||||
/**
|
||||
* Back-compat exports for old hook names.
|
||||
*/
|
||||
export const useStableSubplebbit = useStableCommunity;
|
||||
export const useSubplebbitField = useCommunityField;
|
||||
Reference in New Issue
Block a user