feat: implement 5chan-specific default board list

This commit is contained in:
plebeius
2025-11-03 22:06:18 +01:00
parent 4fd9a9c1a9
commit bae6faa929
13 changed files with 87 additions and 288 deletions
-77
View File
@@ -1,77 +0,0 @@
import { useEffect } from 'react';
import { useAccount, setAccount } from '@plebbit/plebbit-react-hooks';
import { getAutoSubscribeAddresses, useDefaultSubplebbits } from './use-default-subplebbits';
import { useAutoSubscribeStore } from '../stores/use-auto-subscribe-store';
const AUTO_SUBSCRIBE_KEY_PREFIX = '5chan-auto-subscribe-done-';
// Keep track of which accounts have been processed globally
const processedAccounts = new Set<string>();
export const useAutoSubscribe = () => {
const account = useAccount();
const accountAddress = account?.author?.address;
const defaultSubplebbits = useDefaultSubplebbits();
const { addCheckingAccount, removeCheckingAccount, isCheckingAccount } = useAutoSubscribeStore();
useEffect(() => {
if (!accountAddress) return;
// Mark as checking immediately when account changes
addCheckingAccount(accountAddress);
const processAutoSubscribe = async () => {
if (!account || !defaultSubplebbits?.length) return;
if (processedAccounts.has(accountAddress)) {
removeCheckingAccount(accountAddress);
return;
}
const storageKey = AUTO_SUBSCRIBE_KEY_PREFIX + accountAddress;
const hasAutoSubscribed = localStorage.getItem(storageKey);
if (account.subscriptions?.length > 0 || hasAutoSubscribed) {
processedAccounts.add(accountAddress);
removeCheckingAccount(accountAddress);
return;
}
const autoSubscribeAddresses = getAutoSubscribeAddresses();
if (autoSubscribeAddresses.length) {
try {
const currentSubscriptions = account.subscriptions || [];
const mergedSubscriptions = [...currentSubscriptions];
for (const address of autoSubscribeAddresses) {
if (!mergedSubscriptions.includes(address)) {
mergedSubscriptions.push(address);
}
}
await setAccount({
...account,
subscriptions: mergedSubscriptions,
});
localStorage.setItem(storageKey, 'true');
} catch (error) {
console.error('Auto-subscribe error:', error);
}
}
processedAccounts.add(accountAddress);
removeCheckingAccount(accountAddress);
};
processAutoSubscribe();
return () => {
if (accountAddress) removeCheckingAccount(accountAddress);
};
}, [account, accountAddress, defaultSubplebbits, addCheckingAccount, removeCheckingAccount]);
return {
isCheckingSubscriptions: !accountAddress || isCheckingAccount(accountAddress),
};
};
+8 -33
View File
@@ -10,10 +10,7 @@ export interface MultisubMetadata {
export interface MultisubSubplebbit {
title?: string;
address: string;
tags?: string[];
features?: string[];
autoSubscribe5Chan?: boolean;
lowUptime?: boolean;
nsfw?: boolean;
}
export interface DefaultSubplebbitsState {
@@ -24,7 +21,6 @@ export interface DefaultSubplebbitsState {
let cacheSubplebbits: MultisubSubplebbit[] | null = null;
let cacheMetadata: MultisubMetadata | null = null;
let cacheAutoSubscribeAddresses: string[] | null = null;
export const useDefaultSubplebbits = () => {
const [state, setState] = useState<DefaultSubplebbitsState>({
@@ -45,24 +41,17 @@ export const useDefaultSubplebbits = () => {
(async () => {
try {
const multisub = await fetch('https://raw.githubusercontent.com/plebbit/temporary-default-subplebbits/master/multisub.json').then((res) => {
const multisub = await fetch('https://raw.githubusercontent.com/plebbit/lists/master/5chan-multisub.json').then((res) => {
if (!res.ok) {
throw new Error(`HTTP error! status: ${res.status}`);
}
return res.json();
});
const filteredSubplebbits = multisub.subplebbits.filter((sub: MultisubSubplebbit) => !sub.lowUptime);
cacheSubplebbits = filteredSubplebbits;
// Cache auto-subscribe addresses when we fetch subplebbits
cacheAutoSubscribeAddresses = filteredSubplebbits
.filter((sub: MultisubSubplebbit) => sub.autoSubscribe5Chan && sub.address)
.map((sub: MultisubSubplebbit) => sub.address);
cacheSubplebbits = multisub.subplebbits;
setState({
subplebbits: filteredSubplebbits,
subplebbits: multisub.subplebbits,
loading: false,
error: null,
});
@@ -81,8 +70,6 @@ export const useDefaultSubplebbits = () => {
return cacheSubplebbits || state.subplebbits;
};
export const getAutoSubscribeAddresses = () => cacheAutoSubscribeAddresses || [];
export const useDefaultSubplebbitsState = () => {
const [state, setState] = useState<DefaultSubplebbitsState>({
subplebbits: cacheSubplebbits || [],
@@ -102,13 +89,15 @@ export const useDefaultSubplebbitsState = () => {
(async () => {
try {
const multisub = await fetch('https://raw.githubusercontent.com/plebbit/temporary-default-subplebbits/master/multisub.json').then((res) => {
const multisub = await fetch('https://raw.githubusercontent.com/plebbit/lists/master/5chan-multisub.json').then((res) => {
if (!res.ok) {
throw new Error(`HTTP error! status: ${res.status}`);
}
return res.json();
});
cacheSubplebbits = multisub.subplebbits;
setState({
subplebbits: multisub.subplebbits,
loading: false,
@@ -143,7 +132,7 @@ export const useMultisubMetadata = () => {
(async () => {
try {
const multisub = await fetch(
'https://raw.githubusercontent.com/plebbit/temporary-default-subplebbits/master/multisub.json',
'https://raw.githubusercontent.com/plebbit/lists/master/5chan-multisub.json',
// { cache: 'no-cache' }
).then((res) => res.json());
const { title, description, createdAt, updatedAt } = multisub;
@@ -158,17 +147,3 @@ export const useMultisubMetadata = () => {
return cacheMetadata || metadata;
};
const getUniqueTags = (multisub: any) => {
const allTags = new Set<string>();
Object.values(multisub).forEach((sub: any) => {
if (sub?.tags?.length) {
sub.tags.forEach((tag: string) => allTags.add(tag));
}
});
return Array.from(allTags).sort();
};
export const useDefaultSubplebbitTags = (subplebbits: any) => {
return useMemo(() => getUniqueTags(subplebbits), [subplebbits]);
};
+2 -3
View File
@@ -3,7 +3,6 @@ import { useLocation, useParams } from 'react-router-dom';
import useThemeStore from '../stores/use-theme-store';
import { useDefaultSubplebbits } from './use-default-subplebbits';
import { isAllView, isHomeView, isNotFoundView, isPendingPostView, isSubscriptionsView, isModView } from '../lib/utils/view-utils';
import { nsfwTags } from '../constants/nsfwTags';
import { useAccountComment } from '@plebbit/plebbit-react-hooks';
const useInitialTheme = (pendingPostSubplebbitAddress?: string) => {
@@ -29,7 +28,7 @@ const useInitialTheme = (pendingPostSubplebbitAddress?: string) => {
const subplebbitAddress = pendingPostSubplebbitAddress || pendingPost?.subplebbitAddress;
if (subplebbitAddress) {
const subplebbit = subplebbits.find((s) => s.address === subplebbitAddress);
if (subplebbit && subplebbit.tags && subplebbit.tags.some((tag) => nsfwTags.includes(tag))) {
if (subplebbit?.nsfw) {
theme = themes.nsfw || 'yotsuba';
} else {
theme = themes.sfw || 'yotsuba-b';
@@ -43,7 +42,7 @@ const useInitialTheme = (pendingPostSubplebbitAddress?: string) => {
theme = 'yotsuba';
} else if (paramsSubplebbitAddress) {
const subplebbit = subplebbits.find((s) => s.address === paramsSubplebbitAddress);
if (subplebbit && subplebbit.tags && subplebbit.tags.some((tag) => nsfwTags.includes(tag))) {
if (subplebbit?.nsfw) {
theme = themes.nsfw || 'yotsuba';
} else {
theme = themes.sfw || 'yotsuba-b';
+14 -3
View File
@@ -22,7 +22,18 @@ const usePopularPosts = (subplebbits: Subplebbit[]) => {
if (subplebbit?.posts?.pages?.hot?.comments) {
for (const post of Object.values(subplebbit.posts.pages.hot.comments as Comment)) {
const { deleted, link, linkHeight, linkWidth, locked, pinned, removed, replyCount, thumbnailUrl, timestamp } = post;
const {
deleted,
link,
linkHeight,
linkWidth,
locked,
pinned,
removed,
replyCount,
thumbnailUrl,
// timestamp
} = post;
try {
const commentMediaInfo = getCommentMediaInfo(link, thumbnailUrl, linkWidth, linkHeight);
@@ -30,12 +41,12 @@ const usePopularPosts = (subplebbits: Subplebbit[]) => {
if (
hasThumbnail &&
(replyCount > 0 || postsPerSub > 1) &&
replyCount > 1 &&
!deleted &&
!removed &&
!locked &&
!pinned &&
timestamp > Date.now() / 1000 - 60 * 60 * 24 * 30 &&
// timestamp > Date.now() / 1000 - 60 * 60 * 24 * 30 &&
!uniqueLinks.has(link)
) {
subplebbitPosts.push(post);
+2 -3
View File
@@ -3,7 +3,6 @@ import { useLocation, useParams } from 'react-router-dom';
import { isAllView, isSubscriptionsView, isModView } from '../lib/utils/view-utils';
import useThemeStore from '../stores/use-theme-store';
import { useDefaultSubplebbits } from './use-default-subplebbits';
import { nsfwTags } from '../constants/nsfwTags';
import { useAccountComment } from '@plebbit/plebbit-react-hooks';
import useSpecialThemeStore from '../stores/use-special-theme-store';
import { isChristmas } from '../lib/utils/time-utils';
@@ -64,7 +63,7 @@ const useTheme = (): [string, (theme: string) => void] => {
storedTheme = themes.sfw;
} else if (subplebbitAddress) {
const subplebbit = subplebbits.find((s) => s.address === subplebbitAddress);
if (subplebbit && subplebbit.tags && subplebbit.tags.some((tag) => nsfwTags.includes(tag))) {
if (subplebbit?.nsfw) {
storedTheme = themes.nsfw;
} else {
storedTheme = themes.sfw;
@@ -85,7 +84,7 @@ const useTheme = (): [string, (theme: string) => void] => {
await setThemeStore('sfw', newTheme);
} else if (subplebbitAddress) {
const subplebbit = subplebbits.find((s) => s.address === subplebbitAddress);
if (subplebbit && subplebbit.tags && subplebbit.tags.some((tag) => nsfwTags.includes(tag))) {
if (subplebbit?.nsfw) {
await setThemeStore('nsfw', newTheme);
} else {
await setThemeStore('sfw', newTheme);