mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
feat(routing): add hooks and utilities for directory-based board routing
This commit is contained in:
@@ -0,0 +1,48 @@
|
|||||||
|
import { useMemo } from 'react';
|
||||||
|
import { useParams } from 'react-router-dom';
|
||||||
|
import { useDefaultSubplebbits } from './use-default-subplebbits';
|
||||||
|
import { getSubplebbitAddress, getBoardPath } from '../lib/utils/route-utils';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook to resolve boardIdentifier from URL params to subplebbitAddress
|
||||||
|
* Handles both directory codes (e.g., "biz") and full addresses (e.g., "someboard.eth")
|
||||||
|
*
|
||||||
|
* Performance: Uses useMemo to avoid recalculating when params/defaultSubplebbits haven't changed.
|
||||||
|
* The defaultSubplebbits reference is stable (from cache) after initial load, so memoization works effectively.
|
||||||
|
*/
|
||||||
|
export const useResolvedSubplebbitAddress = (): string | undefined => {
|
||||||
|
const params = useParams();
|
||||||
|
const defaultSubplebbits = useDefaultSubplebbits();
|
||||||
|
|
||||||
|
// Try boardIdentifier first (new format), then subplebbitAddress (old format for backward compatibility)
|
||||||
|
const boardIdentifier = params.boardIdentifier || params.subplebbitAddress;
|
||||||
|
|
||||||
|
return useMemo(() => {
|
||||||
|
if (!boardIdentifier) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resolve directory code to address if needed
|
||||||
|
// getSubplebbitAddress uses internal caching, so this is efficient
|
||||||
|
return getSubplebbitAddress(boardIdentifier, defaultSubplebbits);
|
||||||
|
}, [boardIdentifier, defaultSubplebbits]);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook to get the board path (directory code or address) for use in links
|
||||||
|
*
|
||||||
|
* Performance: Uses useMemo to avoid recalculating when subplebbitAddress/defaultSubplebbits haven't changed.
|
||||||
|
* The defaultSubplebbits reference is stable (from cache) after initial load, so memoization works effectively.
|
||||||
|
*/
|
||||||
|
export const useBoardPath = (subplebbitAddress: string | undefined): string | undefined => {
|
||||||
|
const defaultSubplebbits = useDefaultSubplebbits();
|
||||||
|
|
||||||
|
return useMemo(() => {
|
||||||
|
if (!subplebbitAddress) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
// getBoardPath uses internal caching, so this is efficient
|
||||||
|
return getBoardPath(subplebbitAddress, defaultSubplebbits);
|
||||||
|
}, [subplebbitAddress, defaultSubplebbits]);
|
||||||
|
};
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
import { MultisubSubplebbit } from '../../hooks/use-default-subplebbits';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract directory short code from title (e.g., "/biz/ - Business & Finance" -> "biz")
|
||||||
|
*/
|
||||||
|
export const extractDirectoryFromTitle = (title: string): string | null => {
|
||||||
|
const match = title.match(/^\/([^/]+)\//);
|
||||||
|
return match ? match[1] : null;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Cache for maps to avoid recreating them on every call
|
||||||
|
let cachedSubplebbits: MultisubSubplebbit[] | null = null;
|
||||||
|
let cachedDirectoryToAddressMap: Map<string, string> | null = null;
|
||||||
|
let cachedAddressToDirectoryMap: Map<string, string> | null = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a map from directory codes to subplebbit addresses
|
||||||
|
* Uses caching to avoid recreating the map when subplebbits array hasn't changed
|
||||||
|
*/
|
||||||
|
export const getDirectoryToAddressMap = (subplebbits: MultisubSubplebbit[]): Map<string, string> => {
|
||||||
|
// Check if we can use cached map (same array reference)
|
||||||
|
if (cachedDirectoryToAddressMap && cachedSubplebbits === subplebbits) {
|
||||||
|
return cachedDirectoryToAddressMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
const map = new Map<string, string>();
|
||||||
|
for (const subplebbit of subplebbits) {
|
||||||
|
if (subplebbit.title) {
|
||||||
|
const directory = extractDirectoryFromTitle(subplebbit.title);
|
||||||
|
if (directory && subplebbit.address) {
|
||||||
|
map.set(directory, subplebbit.address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache the map and array reference
|
||||||
|
cachedDirectoryToAddressMap = map;
|
||||||
|
cachedSubplebbits = subplebbits;
|
||||||
|
return map;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a map from subplebbit addresses to directory codes
|
||||||
|
* Uses caching to avoid recreating the map when subplebbits array hasn't changed
|
||||||
|
*/
|
||||||
|
export const getAddressToDirectoryMap = (subplebbits: MultisubSubplebbit[]): Map<string, string> => {
|
||||||
|
// Check if we can use cached map (same array reference)
|
||||||
|
if (cachedAddressToDirectoryMap && cachedSubplebbits === subplebbits) {
|
||||||
|
return cachedAddressToDirectoryMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
const map = new Map<string, string>();
|
||||||
|
for (const subplebbit of subplebbits) {
|
||||||
|
if (subplebbit.title && subplebbit.address) {
|
||||||
|
const directory = extractDirectoryFromTitle(subplebbit.title);
|
||||||
|
if (directory) {
|
||||||
|
map.set(subplebbit.address, directory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache the map and array reference
|
||||||
|
cachedAddressToDirectoryMap = map;
|
||||||
|
cachedSubplebbits = subplebbits;
|
||||||
|
return map;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert subplebbit address to URL path (directory code if available, otherwise full address)
|
||||||
|
*/
|
||||||
|
export const getBoardPath = (subplebbitAddress: string, subplebbits: MultisubSubplebbit[]): string => {
|
||||||
|
const addressToDirectory = getAddressToDirectoryMap(subplebbits);
|
||||||
|
const directory = addressToDirectory.get(subplebbitAddress);
|
||||||
|
return directory || subplebbitAddress;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert URL path (directory code or address) to subplebbit address
|
||||||
|
*/
|
||||||
|
export const getSubplebbitAddress = (boardIdentifier: string, subplebbits: MultisubSubplebbit[]): string => {
|
||||||
|
const directoryToAddress = getDirectoryToAddressMap(subplebbits);
|
||||||
|
|
||||||
|
// Check if it's a directory code
|
||||||
|
const address = directoryToAddress.get(boardIdentifier);
|
||||||
|
if (address) {
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, assume it's already an address
|
||||||
|
return boardIdentifier;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if an identifier is a directory short code
|
||||||
|
*/
|
||||||
|
export const isDirectoryBoard = (identifier: string, subplebbits: MultisubSubplebbit[]): boolean => {
|
||||||
|
const directoryToAddress = getDirectoryToAddressMap(subplebbits);
|
||||||
|
return directoryToAddress.has(identifier);
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user