Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/components/author-sidebar/author-sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { findAuthorCommunities, estimateAuthorKarma } from '../../lib/utils/user
import getShortAddress from '../../lib/utils/address-utils';
import { getCommunityIdentifiers } from '../../hooks/use-community-identifier';
import { useTranslation } from 'react-i18next';
import { useDefaultSubplebbitAddresses } from '../../hooks/use-default-subplebbits';
import { useDefaultSubscriptionAddresses } from '../../hooks/use-default-subscriptions';

interface AuthorModeratingListProps {
accountCommunities: Record<string, AccountCommunity & Partial<Community>>;
Expand Down Expand Up @@ -70,7 +70,7 @@ const AuthorSidebar = () => {
const { accountCommunities } = useAccountCommunities();
const profileOldestAccountTimestamp = getOldestAccountHistoryTimestamp(oldestAccountComment as { timestamp?: number }[]);

const defaultSubplebbitAddresses = useDefaultSubplebbitAddresses();
const defaultSubplebbitAddresses = useDefaultSubscriptionAddresses();
const accountSubscriptions = userAccount?.subscriptions || [];
const subscriptionsAndDefaults = [...accountSubscriptions, ...defaultSubplebbitAddresses];

Expand Down
4 changes: 2 additions & 2 deletions src/components/search-bar/search-bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
} from '../../lib/utils/view-utils';
import getShortAddress from '../../lib/utils/address-utils';
import useFeedFiltersStore from '../../stores/use-feed-filters-store';
import { useDefaultSubplebbitAddresses } from '../../hooks/use-default-subplebbits';
import { useDefaultSubscriptionAddresses } from '../../hooks/use-default-subscriptions';
import styles from './search-bar.module.css';
import _ from 'lodash';

Expand Down Expand Up @@ -60,7 +60,7 @@ const SearchBar = ({ isFocused = false, onExpandoChange }: SearchBarProps) => {

const account = useAccount();
const subplebbitAddresses = useMemo(() => account?.subscriptions || [], [account?.subscriptions]);
const defaultSubplebbitAddresses = useDefaultSubplebbitAddresses();
const defaultSubplebbitAddresses = useDefaultSubscriptionAddresses();
const [isInputFocused, setIsInputFocused] = useState(false);
const [activeDropdownIndex, setActiveDropdownIndex] = useState<number>(-1);

Expand Down
6 changes: 3 additions & 3 deletions src/components/topbar/topbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useAccount, useAccountCommunities } from '@bitsocial/bitsocial-react-ho
import { isAllView, isDomainView, isHomeView, isModView, isCommunityView } from '../../lib/utils/view-utils';
import getShortAddress from '../../lib/utils/address-utils';
import useContentOptionsStore from '../../stores/use-content-options-store';
import { useDefaultSubplebbitAddresses, useDefaultSubplebbits } from '../../hooks/use-default-subplebbits';
import { useDefaultSubscriptionAddresses, useDefaultSubscriptions } from '../../hooks/use-default-subscriptions';
import useTimeFilter, { setSessionTimeFilterPreference } from '../../hooks/use-time-filter';
import { sortTypes } from '../../constants/sort-types';
import { sortLabels } from '../../constants/sort-labels';
Expand Down Expand Up @@ -56,7 +56,7 @@ const CommunitiesDropdown = () => {
const TagFilterDropdown = () => {
const { t } = useTranslation();
const account = useAccount();
const defaultCommunities = useDefaultSubplebbits();
const defaultCommunities = useDefaultSubscriptions();
const {
hideAdultCommunities,
hideGoreCommunities,
Expand Down Expand Up @@ -291,7 +291,7 @@ const TopBar = memo(() => {
const homeButtonClass = isInHomeView ? styles.selected : styles.choice;

const { hideDefaultCommunities } = useContentOptionsStore();
const communityAddresses = useDefaultSubplebbitAddresses();
const communityAddresses = useDefaultSubscriptionAddresses();
const { accountCommunities } = useAccountCommunities();
const accountCommunityAddresses = useMemo(() => Object.keys(accountCommunities), [accountCommunities]);

Expand Down
9 changes: 6 additions & 3 deletions src/hooks/use-auto-subscribe.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useEffect } from 'react';
import { useAccount, setAccount } from '@bitsocial/bitsocial-react-hooks';
import { getAutoSubscribeAddresses, useDefaultSubplebbits } from './use-default-subplebbits';
import { getAutoSubscribeAddresses, useDefaultSubscriptions } from './use-default-subscriptions';
import { useAutoSubscribeStore } from '../stores/use-auto-subscribe-store';

const AUTO_SUBSCRIBE_KEY_PREFIX = 'seedit-auto-subscribe-done-';
Expand All @@ -11,7 +11,7 @@ const processedAccounts = new Set<string>();
export const useAutoSubscribe = () => {
const account = useAccount();
const accountAddress = account?.author?.address;
const defaultCommunities = useDefaultSubplebbits();
const defaultCommunities = useDefaultSubscriptions();
const { addCheckingAccount, removeCheckingAccount, isCheckingAccount } = useAutoSubscribeStore();

useEffect(() => {
Expand All @@ -21,7 +21,10 @@ export const useAutoSubscribe = () => {
addCheckingAccount(accountAddress);

const processAutoSubscribe = async () => {
if (!account || !defaultCommunities?.length) return;
if (!account || !defaultCommunities?.length) {
removeCheckingAccount(accountAddress);
return;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Premature empty state during initial defaults fetch

Medium Severity

The new branch calls removeCheckingAccount whenever defaultCommunities is empty, but useDefaultSubscriptions returns [] both while the fetch is in flight and after a 404. As a result, isCheckingSubscriptions flips to false during the initial fetch, not only on a real 404. New users on slower networks will see the home page's "no subscriptions" empty state flash after the safeToShowNoSubscriptions debounce, then return to loading once the fetch resolves and auto-subscribe runs.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 0da6e32. Configure here.


if (processedAccounts.has(accountAddress)) {
removeCheckingAccount(accountAddress);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ import { useEffect, useMemo, useState } from 'react';
import { Community } from '@bitsocial/bitsocial-react-hooks';
import useContentOptionsStore from '../stores/use-content-options-store';

export interface MultisubMetadata {
export interface DefaultSubscriptionsMetadata {
title: string;
description: string;
createdAt: number;
updatedAt: number;
}

export interface MultisubSubplebbit {
export interface DefaultSubscription {
title?: string;
address: string;
tags?: string[];
Expand All @@ -19,8 +19,8 @@ export interface MultisubSubplebbit {
lowUptime?: boolean;
}

let cacheSubplebbits: MultisubSubplebbit[] | null = null;
let cacheMetadata: MultisubMetadata | null = null;
let cacheSubscriptions: DefaultSubscription[] | null = null;
let cacheMetadata: DefaultSubscriptionsMetadata | null = null;
let cacheAutoSubscribeAddresses: string[] | null = null;
let pending = false;

Expand All @@ -32,26 +32,33 @@ const notifySubscribers = () => {
};

// Shared fetch function to avoid duplication
const fetchMultisubData = async () => {
const fetchDefaultSubscriptionsData = async () => {
if (pending) {
return;
}
pending = true;

try {
const multisub = await fetch(
'https://raw.githubusercontent.com/plebbit/lists/master/default-multisub.json',
// { cache: 'no-cache' }
).then((res) => res.json());
const res = await fetch('https://raw.githubusercontent.com/bitsocialnet/lists/master/seedit-default-subscriptions.json');

const filteredSubplebbits = multisub.subplebbits.filter((sub: MultisubSubplebbit) => !sub.lowUptime);
if (!res.ok) {
cacheSubscriptions = [];
cacheAutoSubscribeAddresses = [];
cacheMetadata = null;
notifySubscribers();
return;
}
Comment thread
cursor[bot] marked this conversation as resolved.

const multisub = await res.json();

const filteredSubscriptions = multisub.subplebbits.filter((sub: DefaultSubscription) => !sub.lowUptime);

cacheSubplebbits = filteredSubplebbits;
cacheSubscriptions = filteredSubscriptions;

// Cache auto-subscribe addresses when we fetch subplebbits
cacheAutoSubscribeAddresses = filteredSubplebbits
.filter((sub: MultisubSubplebbit) => sub.seeditAutoSubscribe && sub.address)
.map((sub: MultisubSubplebbit) => sub.address);
// Cache auto-subscribe addresses when we fetch subscriptions
cacheAutoSubscribeAddresses = filteredSubscriptions
.filter((sub: DefaultSubscription) => sub.seeditAutoSubscribe && sub.address)
.map((sub: DefaultSubscription) => sub.address);

// Also cache metadata since we have the full response
const { title, description, createdAt, updatedAt } = multisub;
Expand All @@ -60,7 +67,7 @@ const fetchMultisubData = async () => {
// Notify all subscribers that cache has been updated
notifySubscribers();

return { subplebbits: filteredSubplebbits, metadata: cacheMetadata };
return { subscriptions: filteredSubscriptions, metadata: cacheMetadata };
} catch (e) {
console.warn(e);
return null;
Expand All @@ -69,28 +76,28 @@ const fetchMultisubData = async () => {
}
};

export const useDefaultSubplebbits = () => {
const [subplebbits, setSubplebbits] = useState<MultisubSubplebbit[]>(cacheSubplebbits || []);
export const useDefaultSubscriptions = () => {
const [subscriptions, setSubscriptions] = useState<DefaultSubscription[]>(cacheSubscriptions || []);

useEffect(() => {
// If we already have cached data, use it immediately
if (cacheSubplebbits) {
setSubplebbits(cacheSubplebbits);
if (cacheSubscriptions) {
setSubscriptions(cacheSubscriptions);
return;
}

// Subscribe to cache updates
const handleCacheUpdate = () => {
if (cacheSubplebbits) {
setSubplebbits(cacheSubplebbits);
if (cacheSubscriptions) {
setSubscriptions(cacheSubscriptions);
}
};

subscribers.add(handleCacheUpdate);

// Trigger fetch if no cache and not pending
if (!pending) {
fetchMultisubData();
fetchDefaultSubscriptionsData();
}

// Cleanup subscription
Expand All @@ -99,31 +106,31 @@ export const useDefaultSubplebbits = () => {
};
}, []);

return subplebbits;
return subscriptions;
};

export const getAutoSubscribeAddresses = () => cacheAutoSubscribeAddresses || [];

export const useDefaultSubplebbitAddresses = () => {
const defaultSubplebbits = useDefaultSubplebbits();
export const useDefaultSubscriptionAddresses = () => {
const defaultSubscriptions = useDefaultSubscriptions();
const { hideAdultCommunities, hideGoreCommunities, hideAntiCommunities, hideVulgarCommunities } = useContentOptionsStore();

const filteredSubplebbits = useMemo(() => {
return defaultSubplebbits.filter((subplebbit: Community) => {
const tags = subplebbit.tags || [];
const filteredSubscriptions = useMemo(() => {
return defaultSubscriptions.filter((subscription: Community) => {
const tags = subscription.tags || [];
if (hideAdultCommunities && tags.includes('adult')) return false;
if (hideGoreCommunities && tags.includes('gore')) return false;
if (hideAntiCommunities && tags.includes('anti')) return false;
if (hideVulgarCommunities && tags.includes('vulgar')) return false;
return true;
});
}, [defaultSubplebbits, hideAdultCommunities, hideGoreCommunities, hideAntiCommunities, hideVulgarCommunities]);
}, [defaultSubscriptions, hideAdultCommunities, hideGoreCommunities, hideAntiCommunities, hideVulgarCommunities]);

return useMemo(() => filteredSubplebbits.map((subplebbit) => subplebbit.address), [filteredSubplebbits]);
return useMemo(() => filteredSubscriptions.map((subscription) => subscription.address), [filteredSubscriptions]);
};

export const useMultisubMetadata = () => {
const [metadata, setMetadata] = useState<MultisubMetadata | null>(cacheMetadata || null);
export const useDefaultSubscriptionsMetadata = () => {
const [metadata, setMetadata] = useState<DefaultSubscriptionsMetadata | null>(cacheMetadata || null);

useEffect(() => {
// If we already have cached data, use it immediately
Expand All @@ -143,7 +150,7 @@ export const useMultisubMetadata = () => {

// Trigger fetch if no cache and not pending
if (!pending) {
fetchMultisubData();
fetchDefaultSubscriptionsData();
}

// Cleanup subscription
Expand All @@ -165,6 +172,6 @@ const getUniqueTags = (multisub: any) => {
return Array.from(allTags).sort();
};

export const useDefaultSubplebbitTags = (subplebbits: any) => {
return useMemo(() => getUniqueTags(subplebbits), [subplebbits]);
export const useDefaultSubscriptionTags = (subscriptions: any) => {
return useMemo(() => getUniqueTags(subscriptions), [subscriptions]);
};
4 changes: 2 additions & 2 deletions src/hooks/use-is-broadly-nsfw-community.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { useMemo } from 'react';
import { useDefaultSubplebbits } from './use-default-subplebbits';
import { useDefaultSubscriptions } from './use-default-subscriptions';

const SENSITIVE_TAGS = ['adult', 'gore', 'anti', 'vulgar'];

export const useIsBroadlyNsfwCommunity = (communityAddress: string) => {
const defaultCommunities = useDefaultSubplebbits();
const defaultCommunities = useDefaultSubscriptions();

return useMemo(() => {
if (!communityAddress || !defaultCommunities) return false;
Expand Down
4 changes: 2 additions & 2 deletions src/hooks/use-is-nsfw-community.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { useMemo } from 'react';
import { useDefaultSubplebbits } from './use-default-subplebbits';
import { useDefaultSubscriptions } from './use-default-subscriptions';

export const useIsNsfwCommunity = (communityAddress: string) => {
const defaultCommunities = useDefaultSubplebbits();
const defaultCommunities = useDefaultSubscriptions();

return useMemo(() => {
if (!communityAddress || !defaultCommunities) return false;
Expand Down
4 changes: 2 additions & 2 deletions src/views/all/all.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Virtuoso, VirtuosoHandle, StateSnapshot } from 'react-virtuoso';
import { useFeed } from '@bitsocial/bitsocial-react-hooks';
import { commentMatchesPattern } from '../../lib/utils/pattern-utils';
import useFeedFiltersStore from '../../stores/use-feed-filters-store';
import { useDefaultSubplebbitAddresses } from '../../hooks/use-default-subplebbits';
import { useDefaultSubscriptionAddresses } from '../../hooks/use-default-subscriptions';
import useTimeFilter, { isValidTimeFilterName } from '../../hooks/use-time-filter';
import FeedFooter from '../../components/feed-footer';
import { getCommunityIdentifiers } from '../../hooks/use-community-identifier';
Expand All @@ -18,7 +18,7 @@ import styles from '../home/home.module.css';
const lastVirtuosoStates: { [key: string]: StateSnapshot } = {};

const All = () => {
const communityAddresses = useDefaultSubplebbitAddresses();
const communityAddresses = useDefaultSubscriptionAddresses();
const params = useParams<{ sortType?: string; timeFilterName?: string }>();
const [searchParams, setSearchParams] = useSearchParams();
const searchQuery = searchParams.get('q') || '';
Expand Down
12 changes: 6 additions & 6 deletions src/views/communities/communities.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
} from '../../lib/utils/view-utils';
import useErrorStore from '../../stores/use-error-store';
import { getCommunityIdentifier, getCommunityIdentifiers } from '../../hooks/use-community-identifier';
import { useDefaultSubplebbitAddresses, useDefaultSubplebbits } from '../../hooks/use-default-subplebbits';
import { useDefaultSubscriptionAddresses, useDefaultSubscriptions } from '../../hooks/use-default-subscriptions';
import useDisplayedSubscriptions from '../../hooks/use-displayed-subscriptions';
import useIsMobile from '../../hooks/use-is-mobile';
import useIsCommunityOffline from '../../hooks/use-is-community-offline';
Expand Down Expand Up @@ -314,7 +314,7 @@ const AccountSubplebbits = ({ viewRole }: { viewRole: string }) => {
const { accountCommunities, error: accountCommunitiesError } = useAccountCommunities();
const { setError } = useErrorStore();
const location = useLocation();
const defaultCommunities = useDefaultSubplebbits();
const defaultCommunities = useDefaultSubscriptions();

useEffect(() => {
setError('AccountSubplebbits_useAccountCommunities', accountCommunitiesError);
Expand Down Expand Up @@ -356,7 +356,7 @@ const SubscriberSubplebbits = () => {
const account = useAccount();
const { setError } = useErrorStore();
const location = useLocation();
const defaultCommunities = useDefaultSubplebbits();
const defaultCommunities = useDefaultSubscriptions();

const urlParams = new URLSearchParams(location.search);
const currentTag = urlParams.get('tag');
Expand Down Expand Up @@ -416,8 +416,8 @@ const SubscriberSubplebbits = () => {
};

const AllDefaultSubplebbits = () => {
const defaultCommunitiesList = useDefaultSubplebbits();
const communityAddresses = useDefaultSubplebbitAddresses();
const defaultCommunitiesList = useDefaultSubscriptions();
const communityAddresses = useDefaultSubscriptionAddresses();
const location = useLocation();

const urlParams = new URLSearchParams(location.search);
Expand Down Expand Up @@ -460,7 +460,7 @@ const AllAccountSubplebbits = () => {
const { accountCommunities, error: accountCommunitiesError } = useAccountCommunities();
const { setError } = useErrorStore();
const location = useLocation();
const defaultCommunities = useDefaultSubplebbits();
const defaultCommunities = useDefaultSubscriptions();

useEffect(() => {
setError('AllAccountSubplebbits_useAccountCommunities', accountCommunitiesError);
Expand Down
4 changes: 2 additions & 2 deletions src/views/domain/domain.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Virtuoso, VirtuosoHandle, StateSnapshot } from 'react-virtuoso';
import { useFeed, Comment, CommentsFilter } from '@bitsocial/bitsocial-react-hooks';
import { commentMatchesPattern } from '../../lib/utils/pattern-utils';
import useFeedFiltersStore from '../../stores/use-feed-filters-store';
import { useDefaultSubplebbitAddresses } from '../../hooks/use-default-subplebbits';
import { useDefaultSubscriptionAddresses } from '../../hooks/use-default-subscriptions';
import useTimeFilter, { isValidTimeFilterName } from '../../hooks/use-time-filter';
import FeedFooter from '../../components/feed-footer';
import { getCommunityIdentifiers } from '../../hooks/use-community-identifier';
Expand All @@ -17,7 +17,7 @@ import { sortTypes } from '../../constants/sort-types';
const lastVirtuosoStates: { [key: string]: StateSnapshot } = {};

const Domain = () => {
const communityAddresses = useDefaultSubplebbitAddresses();
const communityAddresses = useDefaultSubscriptionAddresses();
const params = useParams<{ domain?: string; sortType?: string; timeFilterName?: string }>();
const [searchParams, setSearchParams] = useSearchParams();
const navigate = useNavigate();
Expand Down
4 changes: 2 additions & 2 deletions src/views/settings/content-options/content-options.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useTranslation } from 'react-i18next';
import { useAccount } from '@bitsocial/bitsocial-react-hooks';
import styles from './content-options.module.css';
import useContentOptionsStore from '../../../stores/use-content-options-store';
import { useDefaultSubplebbits } from '../../../hooks/use-default-subplebbits';
import { useDefaultSubscriptions } from '../../../hooks/use-default-subscriptions';
import { handleNSFWSubscriptionPrompt } from '../../../lib/utils/nsfw-subscription-utils';

const MediaOptions = () => {
Expand Down Expand Up @@ -138,7 +138,7 @@ const MediaOptions = () => {
const CommunitiesOptions = () => {
const { t } = useTranslation();
const account = useAccount();
const defaultCommunities = useDefaultSubplebbits();
const defaultCommunities = useDefaultSubscriptions();
const {
hideAdultCommunities,
hideGoreCommunities,
Expand Down
Loading
Loading