mirror of
https://github.com/plebbit/seedit.git
synced 2026-06-11 01:25:48 -04:00
refactor: rename subplebbit -> community across seedit
Apply the broader subplebbit -> community rebrand on top of the package switch: - Rename hook usages (useSubplebbit -> useCommunity, useSubplebbits -> useCommunities, useSubplebbitStats -> useCommunityStats, useSubplebbitsStates -> useCommunitiesStates, useAccountSubplebbits -> useAccountCommunities, usePublishSubplebbitEdit -> usePublishCommunityEdit, usePlebbitRpcSettings -> usePkcRpcSettings) and types (Subplebbit -> Community, PublishSubplebbitEditOptions -> PublishCommunityEditOptions). - Rename seedit identifiers (variables, types, store names) from subplebbit/Subplebbit to community/Community. - git mv view directories, store files, hook files, and CSS modules from subplebbit-* to community-*. Update all imports. - Rename the React Router :subplebbitAddress route param to :communityAddress (path /s/ unchanged). - Update English translation values for community-related strings. - Drop src/lib/bitsocial-react-hooks-compat.ts (no longer needed now that @bitsocial/bitsocial-react-hooks exposes the community names natively). - Add src/hooks/use-community-identifier.ts and src/lib/utils/address-utils.ts as small adapters for the new CommunityIdentifier shape and short-address utility. - Fix src/hooks/use-default-subplebbits.ts to import Community instead of Subplebbit (PR #813 will rename the file in a follow-up; tiny merge conflict expected on that one file). Build, lint, and type-check all pass.
This commit is contained in:
@@ -293,8 +293,8 @@
|
||||
"more_posts_last_month": "{{count}} posts last {{currentTimeFilterName}}: <1>show more posts from last month</1>",
|
||||
"profile_info": "Your account u/{{shortAddress}} was created. <1>Set display name</1>, <2>export backup</2>, <3>learn more</3>.",
|
||||
"show_all_instead": "Showing posts since {{timeFilterName}}, <1>show all instead</1>",
|
||||
"subplebbit_offline_info": "The subplebbit might be offline and publishing might fail.",
|
||||
"posts_last_synced_info": "Posts last synced {{time}}, the subplebbit might be offline and publishing might fail.",
|
||||
"subplebbit_offline_info": "The community might be offline and publishing might fail.",
|
||||
"posts_last_synced_info": "Posts last synced {{time}}, the community might be offline and publishing might fail.",
|
||||
"import_account_backup": "<1>import</1> account backup",
|
||||
"export_account_backup": "<1>export</1> account backup",
|
||||
"save_reset_changes": "<1>save</1> or <2>reset</2> changes",
|
||||
|
||||
40
src/app.tsx
40
src/app.tsx
@@ -15,11 +15,11 @@ import PostPage from './views/post-page';
|
||||
import Profile from './views/profile';
|
||||
import Settings from './views/settings';
|
||||
import AccountDataEditor from './views/settings/account-data-editor';
|
||||
import SubplebbitDataEditor from './views/subplebbit-settings/subplebbit-data-editor';
|
||||
import CommunityDataEditor from './views/community-settings/community-data-editor';
|
||||
import SubmitPage from './views/submit-page';
|
||||
import Subplebbit from './views/subplebbit';
|
||||
import SubplebbitSettings from './views/subplebbit-settings';
|
||||
import Subplebbits from './views/subplebbits';
|
||||
import CommunityView from './views/community';
|
||||
import CommunitySettings from './views/community-settings';
|
||||
import Communities from './views/communities';
|
||||
import AccountBar from './components/account-bar/';
|
||||
import ChallengeModal from './components/challenge-modal';
|
||||
import Header from './components/header';
|
||||
@@ -90,15 +90,15 @@ const App = () => {
|
||||
<Route path='/about' element={<AboutView />} />
|
||||
<Route path='/submit' element={<SubmitPage />} />
|
||||
|
||||
<Route path='/s/:subplebbitAddress/c/:commentCid' element={<PostPage />} />
|
||||
<Route path='/s/:subplebbitAddress/c/:commentCid/about' element={<AboutView />} />
|
||||
<Route path='/s/:communityAddress/c/:commentCid' element={<PostPage />} />
|
||||
<Route path='/s/:communityAddress/c/:commentCid/about' element={<AboutView />} />
|
||||
|
||||
<Route path='/s/:subplebbitAddress/submit' element={<SubmitPage />} />
|
||||
<Route path='/s/:subplebbitAddress/about' element={<AboutView />} />
|
||||
<Route path='/s/:communityAddress/submit' element={<SubmitPage />} />
|
||||
<Route path='/s/:communityAddress/about' element={<AboutView />} />
|
||||
|
||||
<Route path='/settings' element={<Settings />} />
|
||||
<Route path='/s/:subplebbitAddress/settings' element={<SubplebbitSettings />} />
|
||||
<Route path='/s/:subplebbitAddress/settings/editor' element={<SubplebbitDataEditor />} />
|
||||
<Route path='/s/:communityAddress/settings' element={<CommunitySettings />} />
|
||||
<Route path='/s/:communityAddress/settings/editor' element={<CommunityDataEditor />} />
|
||||
<Route path='/settings/plebbit-options' element={<Settings />} />
|
||||
<Route path='/settings/content-options' element={<Settings />} />
|
||||
<Route path='/settings/account-data' element={<AccountDataEditor />} />
|
||||
@@ -112,15 +112,15 @@ const App = () => {
|
||||
<Route path='/inbox/commentreplies' element={<Inbox />} />
|
||||
<Route path='/inbox/postreplies' element={<Inbox />} />
|
||||
|
||||
<Route path='/communities' element={<Subplebbits />} />
|
||||
<Route path='/communities/subscriber' element={<Subplebbits />} />
|
||||
<Route path='/communities/moderator' element={<Subplebbits />} />
|
||||
<Route path='/communities/admin' element={<Subplebbits />} />
|
||||
<Route path='/communities/owner' element={<Subplebbits />} />
|
||||
<Route path='/communities/vote' element={<Subplebbits />} />
|
||||
<Route path='/communities/vote/passing' element={<Subplebbits />} />
|
||||
<Route path='/communities/vote/rejecting' element={<Subplebbits />} />
|
||||
<Route path='/communities/create' element={<SubplebbitSettings />} />
|
||||
<Route path='/communities' element={<Communities />} />
|
||||
<Route path='/communities/subscriber' element={<Communities />} />
|
||||
<Route path='/communities/moderator' element={<Communities />} />
|
||||
<Route path='/communities/admin' element={<Communities />} />
|
||||
<Route path='/communities/owner' element={<Communities />} />
|
||||
<Route path='/communities/vote' element={<Communities />} />
|
||||
<Route path='/communities/vote/passing' element={<Communities />} />
|
||||
<Route path='/communities/vote/rejecting' element={<Communities />} />
|
||||
<Route path='/communities/create' element={<CommunitySettings />} />
|
||||
</Route>
|
||||
<Route element={feedLayout}>
|
||||
<Route path='/:sortType?/:timeFilterName?' element={<Home />} />
|
||||
@@ -129,7 +129,7 @@ const App = () => {
|
||||
|
||||
<Route path='/s/mod/:sortType?/:timeFilterName?' element={<Mod />} />
|
||||
|
||||
<Route path='/s/:subplebbitAddress/:sortType?/:timeFilterName?' element={<Subplebbit />} />
|
||||
<Route path='/s/:communityAddress/:sortType?/:timeFilterName?' element={<CommunityView />} />
|
||||
|
||||
<Route path='/domain/:domain/:sortType?/:timeFilterName?' element={<Domain />} />
|
||||
|
||||
|
||||
@@ -3,26 +3,28 @@ import { Link, useLocation, useParams } from 'react-router-dom';
|
||||
import {
|
||||
useAccount,
|
||||
useAccountComments,
|
||||
useAccountSubplebbits,
|
||||
AccountSubplebbit,
|
||||
useAccountCommunities,
|
||||
AccountCommunity,
|
||||
Community,
|
||||
useAuthor,
|
||||
useAuthorAvatar,
|
||||
useAuthorComments,
|
||||
useBlock,
|
||||
useComment,
|
||||
useSubplebbits,
|
||||
useCommunities,
|
||||
} from '@bitsocial/bitsocial-react-hooks';
|
||||
import Plebbit from '@plebbit/plebbit-js';
|
||||
import styles from './author-sidebar.module.css';
|
||||
import { getFormattedTimeDuration } from '../../lib/utils/time-utils';
|
||||
import { getOldestAccountHistoryTimestamp } from '../../lib/utils/account-history-utils';
|
||||
import { isAuthorView, isProfileView } from '../../lib/utils/view-utils';
|
||||
import { findAuthorSubplebbits, estimateAuthorKarma } from '../../lib/utils/user-utils';
|
||||
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';
|
||||
|
||||
interface AuthorModeratingListProps {
|
||||
accountSubplebbits: Record<string, AccountSubplebbit>;
|
||||
accountSubplebbits: Record<string, AccountCommunity & Partial<Community>>;
|
||||
authorSubplebbits: string[];
|
||||
isAuthor?: boolean;
|
||||
}
|
||||
@@ -39,7 +41,7 @@ const AuthorModeratingList = ({ accountSubplebbits, authorSubplebbits, isAuthor
|
||||
<ul className={`${styles.modListContent} ${styles.modsList}`}>
|
||||
{subplebbitAddresses.map((address, index) => (
|
||||
<li key={index}>
|
||||
<Link to={`/s/${address}`}>s/{Plebbit.getShortAddress({ address })}</Link>
|
||||
<Link to={`/s/${address}`}>s/{getShortAddress(address)}</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
@@ -65,7 +67,7 @@ const AuthorSidebar = () => {
|
||||
const userAccount = useAccount();
|
||||
const { imageUrl: profilePageAvatar } = useAuthorAvatar({ author: userAccount?.author });
|
||||
const { accountComments: oldestAccountComment } = useAccountComments({ page: 0, pageSize: 1, order: 'asc' });
|
||||
const { accountSubplebbits } = useAccountSubplebbits();
|
||||
const { accountCommunities: accountSubplebbits } = useAccountCommunities();
|
||||
const profileOldestAccountTimestamp = getOldestAccountHistoryTimestamp(oldestAccountComment as { timestamp?: number }[]);
|
||||
|
||||
const defaultSubplebbitAddresses = useDefaultSubplebbitAddresses();
|
||||
@@ -73,10 +75,10 @@ const AuthorSidebar = () => {
|
||||
const subscriptionsAndDefaults = [...accountSubscriptions, ...defaultSubplebbitAddresses];
|
||||
|
||||
const subplebbits =
|
||||
useSubplebbits({
|
||||
subplebbitAddresses: subscriptionsAndDefaults || [],
|
||||
useCommunities({
|
||||
communities: getCommunityIdentifiers(subscriptionsAndDefaults || []),
|
||||
onlyIfCached: true,
|
||||
}).subplebbits?.filter(Boolean) || [];
|
||||
}).communities?.filter(Boolean) || [];
|
||||
|
||||
const authorAccount = useAuthor({ authorAddress, commentCid });
|
||||
const { authorComments } = useAuthorComments({ authorAddress, commentCid });
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Link, useLocation, useParams } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useAccount, useAccountComment, useSubplebbit } from '@bitsocial/bitsocial-react-hooks';
|
||||
import Plebbit from '@plebbit/plebbit-js';
|
||||
import { useAccount, useAccountComment, useCommunity } from '@bitsocial/bitsocial-react-hooks';
|
||||
import { sortTypes } from '../../constants/sort-types';
|
||||
import { sortLabels } from '../../constants/sort-labels';
|
||||
import {
|
||||
@@ -11,7 +10,7 @@ import {
|
||||
isAuthorView,
|
||||
isAuthorCommentsView,
|
||||
isAuthorSubmittedView,
|
||||
isCreateSubplebbitView,
|
||||
isCreateCommunityView,
|
||||
isHomeAboutView,
|
||||
isHomeView,
|
||||
isInboxView,
|
||||
@@ -25,23 +24,24 @@ import {
|
||||
isProfileHiddenView,
|
||||
isSettingsView,
|
||||
isSubmitView,
|
||||
isSubplebbitView,
|
||||
isSubplebbitSettingsView,
|
||||
isSubplebbitSubmitView,
|
||||
isSubplebbitsView,
|
||||
isSubplebbitsSubscriberView,
|
||||
isSubplebbitsModeratorView,
|
||||
isSubplebbitsAdminView,
|
||||
isSubplebbitsVoteView,
|
||||
isSubplebbitsOwnerView,
|
||||
isCommunityView,
|
||||
isCommunitySettingsView,
|
||||
isCommunitySubmitView,
|
||||
isCommunitiesView,
|
||||
isCommunitiesSubscriberView,
|
||||
isCommunitiesModeratorView,
|
||||
isCommunitiesAdminView,
|
||||
isCommunitiesVoteView,
|
||||
isCommunitiesOwnerView,
|
||||
isProfileUpvotedView,
|
||||
isSettingsContentOptionsView,
|
||||
isSettingsPlebbitOptionsView,
|
||||
isSubplebbitAboutView,
|
||||
isCommunityAboutView,
|
||||
isDomainView,
|
||||
isPostPageAboutView,
|
||||
isSettingsAccountDataView,
|
||||
} from '../../lib/utils/view-utils';
|
||||
import getShortAddress from '../../lib/utils/address-utils';
|
||||
import useContentOptionsStore from '../../stores/use-content-options-store';
|
||||
import useNotFoundStore from '../../stores/use-not-found-store';
|
||||
import { useIsBroadlyNsfwSubplebbit } from '../../hooks/use-is-broadly-nsfw-subplebbit';
|
||||
@@ -56,10 +56,10 @@ const AboutButton = () => {
|
||||
const aboutLink = getAboutLink(location.pathname, params);
|
||||
const isInHomeAboutView = isHomeAboutView(location.pathname);
|
||||
const isInPostPageAboutView = isPostPageAboutView(location.pathname, params);
|
||||
const isInSubplebbitAboutView = isSubplebbitAboutView(location.pathname, params);
|
||||
const isInCommunityAboutView = isCommunityAboutView(location.pathname, params);
|
||||
|
||||
return (
|
||||
<li className={`${styles.about} ${isInHomeAboutView || isInSubplebbitAboutView || isInPostPageAboutView ? styles.selected : styles.choice}`}>
|
||||
<li className={`${styles.about} ${isInHomeAboutView || isInCommunityAboutView || isInPostPageAboutView ? styles.selected : styles.choice}`}>
|
||||
<Link to={aboutLink}>{t('about')}</Link>
|
||||
</li>
|
||||
);
|
||||
@@ -76,7 +76,7 @@ const CommentsButton = () => {
|
||||
|
||||
return (
|
||||
<li className={(isInPostPageView || isInPendingPostView) && !isInHomeAboutView && !isInPostPageAboutView ? styles.selected : styles.choice}>
|
||||
<Link to={`/s/${params.subplebbitAddress}/c/${params.commentCid}`} onClick={(e) => isInPendingPostView && e.preventDefault()}>
|
||||
<Link to={`/s/${params.communityAddress}/c/${params.commentCid}`} onClick={(e) => isInPendingPostView && e.preventDefault()}>
|
||||
{t('comments')}
|
||||
</Link>
|
||||
</li>
|
||||
@@ -89,18 +89,18 @@ const SortItems = () => {
|
||||
const location = useLocation();
|
||||
const isInHomeAboutView = isHomeAboutView(location.pathname);
|
||||
const isInPostPageAboutView = isPostPageAboutView(location.pathname, params);
|
||||
const isInSubplebbitAboutView = isSubplebbitAboutView(location.pathname, params);
|
||||
const isInCommunityAboutView = isCommunityAboutView(location.pathname, params);
|
||||
const isInAllView = isAllView(location.pathname);
|
||||
const isInModView = isModView(location.pathname);
|
||||
const isInDomainView = isDomainView(location.pathname);
|
||||
const isInSubplebbitView = isSubplebbitView(location.pathname, params);
|
||||
const isInCommunityView = isCommunityView(location.pathname, params);
|
||||
// Derive selection directly from route instead of syncing via an effect
|
||||
const selectedSortType = isInHomeAboutView || isInSubplebbitAboutView || isInPostPageAboutView ? '' : params.sortType || 'hot';
|
||||
const selectedSortType = isInHomeAboutView || isInCommunityAboutView || isInPostPageAboutView ? '' : params.sortType || 'hot';
|
||||
const timeFilterName = params.timeFilterName;
|
||||
|
||||
return sortTypes.map((sortType, index) => {
|
||||
let sortLink = isInSubplebbitView
|
||||
? `/s/${params.subplebbitAddress}/${sortType}`
|
||||
let sortLink = isInCommunityView
|
||||
? `/s/${params.communityAddress}/${sortType}`
|
||||
: isInAllView
|
||||
? `/s/all/${sortType}`
|
||||
: isInModView
|
||||
@@ -196,27 +196,27 @@ const InboxHeaderTabs = () => {
|
||||
const SubplebbitsHeaderTabs = () => {
|
||||
const { t } = useTranslation();
|
||||
const location = useLocation();
|
||||
const isInSubplebbitsSubscriberView = isSubplebbitsSubscriberView(location.pathname);
|
||||
const isInSubplebbitsModeratorView = isSubplebbitsModeratorView(location.pathname);
|
||||
const isInSubplebbitsAdminView = isSubplebbitsAdminView(location.pathname);
|
||||
const isInSubplebbitsOwnerView = isSubplebbitsOwnerView(location.pathname);
|
||||
const isInSubplebbitsVoteView = isSubplebbitsVoteView(location.pathname);
|
||||
const isInSubplebbitsView =
|
||||
isSubplebbitsView(location.pathname) &&
|
||||
!isInSubplebbitsSubscriberView &&
|
||||
!isInSubplebbitsModeratorView &&
|
||||
!isInSubplebbitsAdminView &&
|
||||
!isInSubplebbitsOwnerView &&
|
||||
!isInSubplebbitsVoteView;
|
||||
const isInCommunitiesSubscriberView = isCommunitiesSubscriberView(location.pathname);
|
||||
const isInCommunitiesModeratorView = isCommunitiesModeratorView(location.pathname);
|
||||
const isInCommunitiesAdminView = isCommunitiesAdminView(location.pathname);
|
||||
const isInCommunitiesOwnerView = isCommunitiesOwnerView(location.pathname);
|
||||
const isInCommunitiesVoteView = isCommunitiesVoteView(location.pathname);
|
||||
const isInCommunitiesView =
|
||||
isCommunitiesView(location.pathname) &&
|
||||
!isInCommunitiesSubscriberView &&
|
||||
!isInCommunitiesModeratorView &&
|
||||
!isInCommunitiesAdminView &&
|
||||
!isInCommunitiesOwnerView &&
|
||||
!isInCommunitiesVoteView;
|
||||
|
||||
return (
|
||||
<>
|
||||
<li className={`${isInSubplebbitsVoteView ? styles.selected : styles.choice}`}>
|
||||
<li className={`${isInCommunitiesVoteView ? styles.selected : styles.choice}`}>
|
||||
<Link to={'/communities/vote'}>{t('vote')}</Link>
|
||||
</li>
|
||||
<li
|
||||
className={
|
||||
isInSubplebbitsSubscriberView || isInSubplebbitsModeratorView || isInSubplebbitsAdminView || isInSubplebbitsOwnerView || isInSubplebbitsView
|
||||
isInCommunitiesSubscriberView || isInCommunitiesModeratorView || isInCommunitiesAdminView || isInCommunitiesOwnerView || isInCommunitiesView
|
||||
? styles.selected
|
||||
: styles.choice
|
||||
}
|
||||
@@ -263,11 +263,11 @@ const HeaderTabs = () => {
|
||||
const isInPendingPostView = isPendingPostView(location.pathname, params);
|
||||
const isInPostPageView = isPostPageView(location.pathname, params);
|
||||
const isInProfileView = isProfileView(location.pathname);
|
||||
const isInSubplebbitView = isSubplebbitView(location.pathname, params);
|
||||
const isInSubplebbitSettingsView = isSubplebbitSettingsView(location.pathname, params);
|
||||
const isInSubplebbitSubmitView = isSubplebbitSubmitView(location.pathname, params);
|
||||
const isInSubplebbitsView = isSubplebbitsView(location.pathname);
|
||||
const isInCreateSubplebbitView = isCreateSubplebbitView(location.pathname);
|
||||
const isInCommunityView = isCommunityView(location.pathname, params);
|
||||
const isInCommunitySettingsView = isCommunitySettingsView(location.pathname, params);
|
||||
const isInCommunitySubmitView = isCommunitySubmitView(location.pathname, params);
|
||||
const isInCommunitiesView = isCommunitiesView(location.pathname);
|
||||
const isInCreateCommunityView = isCreateCommunityView(location.pathname);
|
||||
const isInSettingsView = isSettingsView(location.pathname);
|
||||
const isInSettingsContentOptionsView = isSettingsContentOptionsView(location.pathname);
|
||||
const isInSettingsPlebbitOptionsView = isSettingsPlebbitOptionsView(location.pathname);
|
||||
@@ -278,7 +278,7 @@ const HeaderTabs = () => {
|
||||
isInHomeView ||
|
||||
isInHomeAboutView ||
|
||||
isInPostPageAboutView ||
|
||||
(isInSubplebbitView && !isInSubplebbitSubmitView && !isInSubplebbitSettingsView) ||
|
||||
(isInCommunityView && !isInCommunitySubmitView && !isInCommunitySettingsView) ||
|
||||
isInAllView ||
|
||||
isInModView ||
|
||||
isInDomainView
|
||||
@@ -288,7 +288,7 @@ const HeaderTabs = () => {
|
||||
return <AuthorHeaderTabs />;
|
||||
} else if (isInInboxView) {
|
||||
return <InboxHeaderTabs />;
|
||||
} else if (isInSubplebbitsView && !isInCreateSubplebbitView) {
|
||||
} else if (isInCommunitiesView && !isInCreateCommunityView) {
|
||||
return <SubplebbitsHeaderTabs />;
|
||||
} else if (isInSettingsView || isInSettingsPlebbitOptionsView || isInSettingsContentOptionsView) {
|
||||
return <SettingsHeaderTabs />;
|
||||
@@ -313,14 +313,14 @@ const HeaderTitle = ({ title, pendingPostSubplebbitAddress }: { title: string; p
|
||||
const isInSettingsContentOptionsView = isSettingsContentOptionsView(location.pathname);
|
||||
const isInSettingsPlebbitOptionsView = isSettingsPlebbitOptionsView(location.pathname);
|
||||
const isInSubmitView = isSubmitView(location.pathname);
|
||||
const isInSubplebbitView = isSubplebbitView(location.pathname, params);
|
||||
const isInSubplebbitSubmitView = isSubplebbitSubmitView(location.pathname, params);
|
||||
const isInSubplebbitSettingsView = isSubplebbitSettingsView(location.pathname, params);
|
||||
const isInSubplebbitsView = isSubplebbitsView(location.pathname);
|
||||
const isInCreateSubplebbitView = isCreateSubplebbitView(location.pathname);
|
||||
const isInCommunityView = isCommunityView(location.pathname, params);
|
||||
const isInCommunitySubmitView = isCommunitySubmitView(location.pathname, params);
|
||||
const isInCommunitySettingsView = isCommunitySettingsView(location.pathname, params);
|
||||
const isInCommunitiesView = isCommunitiesView(location.pathname);
|
||||
const isInCreateCommunityView = isCreateCommunityView(location.pathname);
|
||||
const isInNotFoundView = useNotFoundStore((state) => state.isNotFound);
|
||||
|
||||
const subplebbitAddress = params.subplebbitAddress;
|
||||
const subplebbitAddress = params.communityAddress;
|
||||
|
||||
const { hideAdultCommunities, hideGoreCommunities, hideAntiCommunities, hideVulgarCommunities } = useContentOptionsStore();
|
||||
const hasUnhiddenAnyNsfwCommunity = !hideAdultCommunities || !hideGoreCommunities || !hideAntiCommunities || !hideVulgarCommunities;
|
||||
@@ -328,27 +328,23 @@ const HeaderTitle = ({ title, pendingPostSubplebbitAddress }: { title: string; p
|
||||
|
||||
const subplebbitTitle = (
|
||||
<Link to={`/s/${isInPendingPostView ? pendingPostSubplebbitAddress : subplebbitAddress}`}>
|
||||
{title ||
|
||||
(subplebbitAddress && Plebbit.getShortAddress({ address: subplebbitAddress })) ||
|
||||
(pendingPostSubplebbitAddress && Plebbit.getShortAddress({ address: pendingPostSubplebbitAddress }))}
|
||||
{title || (subplebbitAddress && getShortAddress(subplebbitAddress)) || (pendingPostSubplebbitAddress && getShortAddress(pendingPostSubplebbitAddress))}
|
||||
</Link>
|
||||
);
|
||||
const domainTitle = <Link to={`/domain/${params.domain}`}>{params.domain}</Link>;
|
||||
const submitTitle = <span className={styles.submitTitle}>{t('submit')}</span>;
|
||||
const profileTitle = <Link to='/profile'>{account?.author?.shortAddress}</Link>;
|
||||
const authorTitle = (
|
||||
<Link to={`/u/${params.authorAddress}/c/${params.commentCid}`}>{params.authorAddress && Plebbit.getShortAddress({ address: params.authorAddress })}</Link>
|
||||
);
|
||||
const authorTitle = <Link to={`/u/${params.authorAddress}/c/${params.commentCid}`}>{params.authorAddress && getShortAddress(params.authorAddress)}</Link>;
|
||||
|
||||
if (isBroadlyNsfwSubplebbit && !hasUnhiddenAnyNsfwCommunity) {
|
||||
return <span>{t('over_18')}</span>;
|
||||
} else if (isInSubplebbitSubmitView) {
|
||||
} else if (isInCommunitySubmitView) {
|
||||
return (
|
||||
<>
|
||||
{subplebbitTitle}: {submitTitle}
|
||||
</>
|
||||
);
|
||||
} else if (isInSubplebbitSettingsView) {
|
||||
} else if (isInCommunitySettingsView) {
|
||||
return (
|
||||
<>
|
||||
{subplebbitTitle}: <span className={styles.lowercase}>{t('community_settings')}</span>
|
||||
@@ -360,15 +356,15 @@ const HeaderTitle = ({ title, pendingPostSubplebbitAddress }: { title: string; p
|
||||
return t('preferences');
|
||||
} else if (isInProfileView && !isInPendingPostView) {
|
||||
return profileTitle;
|
||||
} else if (isInPostPageView || isInPendingPostView || (isInSubplebbitView && !isInSubplebbitSettingsView)) {
|
||||
} else if (isInPostPageView || isInPendingPostView || (isInCommunityView && !isInCommunitySettingsView)) {
|
||||
return subplebbitTitle;
|
||||
} else if (isInAuthorView) {
|
||||
return authorTitle;
|
||||
} else if (isInInboxView) {
|
||||
return t('messages');
|
||||
} else if (isInCreateSubplebbitView) {
|
||||
} else if (isInCreateCommunityView) {
|
||||
return <span className={styles.lowercase}>{t('create_community')}</span>;
|
||||
} else if (isInSubplebbitsView) {
|
||||
} else if (isInCommunitiesView) {
|
||||
return t('communities');
|
||||
} else if (isInNotFoundView) {
|
||||
return <span className={styles.lowercase}>{t('page_not_found')}</span>;
|
||||
@@ -387,7 +383,7 @@ const Header = () => {
|
||||
const [theme] = useTheme();
|
||||
const location = useLocation();
|
||||
const params = useParams();
|
||||
const subplebbit = useSubplebbit({ subplebbitAddress: params?.subplebbitAddress, onlyIfCached: true });
|
||||
const subplebbit = useCommunity(params?.communityAddress ? { community: { name: params?.communityAddress }, onlyIfCached: true } : undefined);
|
||||
const { suggested, title } = subplebbit || {};
|
||||
|
||||
const commentIndex = params?.accountCommentIndex ? parseInt(params?.accountCommentIndex) : undefined;
|
||||
@@ -407,24 +403,23 @@ const Header = () => {
|
||||
const isInPendingPostView = isPendingPostView(location.pathname, params);
|
||||
const isInProfileView = isProfileView(location.pathname);
|
||||
const isInSettingsView = isSettingsView(location.pathname);
|
||||
const isInSubplebbitView = isSubplebbitView(location.pathname, params);
|
||||
const isInSubplebbitAboutView = isSubplebbitAboutView(location.pathname, params);
|
||||
const isInCommunityView = isCommunityView(location.pathname, params);
|
||||
const isInCommunityAboutView = isCommunityAboutView(location.pathname, params);
|
||||
const isInSubmitView = isSubmitView(location.pathname);
|
||||
const isInSubplebbitSubmitView = isSubplebbitSubmitView(location.pathname, params);
|
||||
const isInSubplebbitSettingsView = isSubplebbitSettingsView(location.pathname, params);
|
||||
const isInCommunitySubmitView = isCommunitySubmitView(location.pathname, params);
|
||||
const isInCommunitySettingsView = isCommunitySettingsView(location.pathname, params);
|
||||
const isInNotFoundView = useNotFoundStore((state) => state.isNotFound);
|
||||
|
||||
const hasFewTabs =
|
||||
isInPostPageView || isInSubmitView || isInSubplebbitSubmitView || isInSubplebbitSettingsView || isInSettingsView || isInInboxView || isInSettingsView;
|
||||
const hasFewTabs = isInPostPageView || isInSubmitView || isInCommunitySubmitView || isInCommunitySettingsView || isInSettingsView || isInInboxView || isInSettingsView;
|
||||
const hasStickyHeader =
|
||||
isInHomeView ||
|
||||
isInNotFoundView ||
|
||||
(isInSubplebbitView &&
|
||||
!isInSubplebbitSubmitView &&
|
||||
!isInSubplebbitSettingsView &&
|
||||
(isInCommunityView &&
|
||||
!isInCommunitySubmitView &&
|
||||
!isInCommunitySettingsView &&
|
||||
!isInPostPageView &&
|
||||
!isInHomeAboutView &&
|
||||
!isInSubplebbitAboutView &&
|
||||
!isInCommunityAboutView &&
|
||||
!isInPostPageAboutView) ||
|
||||
(isInProfileView && !isInHomeAboutView) ||
|
||||
(isInAllView && !isInAllAboutView) ||
|
||||
@@ -432,7 +427,7 @@ const Header = () => {
|
||||
(isInDomainView && !isInHomeAboutView) ||
|
||||
(isInAuthorView && !isInHomeAboutView);
|
||||
|
||||
const subplebbitAddress = params.subplebbitAddress;
|
||||
const subplebbitAddress = params.communityAddress;
|
||||
|
||||
const contentOptionsStore = useContentOptionsStore();
|
||||
const hasUnhiddenAnyNsfwCommunity =
|
||||
@@ -442,7 +437,7 @@ const Header = () => {
|
||||
!contentOptionsStore.hideVulgarCommunities;
|
||||
const isBroadlyNsfwSubplebbit = useIsBroadlyNsfwSubplebbit(subplebbitAddress || '');
|
||||
|
||||
const logoIsAvatar = isInSubplebbitView && suggested?.avatarUrl && !(isBroadlyNsfwSubplebbit && !hasUnhiddenAnyNsfwCommunity);
|
||||
const logoIsAvatar = isInCommunityView && suggested?.avatarUrl && !(isBroadlyNsfwSubplebbit && !hasUnhiddenAnyNsfwCommunity);
|
||||
const logoSrc = logoIsAvatar ? suggested?.avatarUrl : 'assets/sprout/sprout.png';
|
||||
const logoLink = '/';
|
||||
|
||||
@@ -459,15 +454,15 @@ const Header = () => {
|
||||
<div className={styles.header}>
|
||||
<div
|
||||
className={`${styles.container} ${hasFewTabs && styles.reducedHeight} ${
|
||||
isInSubmitView && isInSubplebbitSubmitView && !isInSubplebbitView && isMobile && styles.reduceSubmitPageHeight
|
||||
isInSubmitView && isInCommunitySubmitView && !isInCommunityView && isMobile && styles.reduceSubmitPageHeight
|
||||
} ${hasStickyHeader && styles.increasedHeight}`}
|
||||
>
|
||||
<div className={styles.logoContainer}>
|
||||
<Link to={logoLink} className={styles.logoLink}>
|
||||
{(logoIsAvatar || (!isInSubplebbitView && !isInProfileView && !isInAuthorView) || !logoIsAvatar) && (
|
||||
{(logoIsAvatar || (!isInCommunityView && !isInProfileView && !isInAuthorView) || !logoIsAvatar) && (
|
||||
<img className={`${logoIsAvatar ? styles.avatar : styles.logo}`} src={logoSrc} alt='' />
|
||||
)}
|
||||
{((!isInSubplebbitView && !isInProfileView && !isInAuthorView) || !logoIsAvatar) && (
|
||||
{((!isInCommunityView && !isInProfileView && !isInAuthorView) || !logoIsAvatar) && (
|
||||
<img src={`assets/sprout/seedit-text-${theme === 'dark' ? 'dark' : 'light'}.svg`} className={styles.logoText} alt='' />
|
||||
)}
|
||||
</Link>
|
||||
@@ -489,10 +484,10 @@ const Header = () => {
|
||||
</ul>
|
||||
)}
|
||||
</div>
|
||||
{isMobile && !isInSubplebbitSubmitView && !(isBroadlyNsfwSubplebbit && !hasUnhiddenAnyNsfwCommunity) && (
|
||||
{isMobile && !isInCommunitySubmitView && !(isBroadlyNsfwSubplebbit && !hasUnhiddenAnyNsfwCommunity) && (
|
||||
<ul className={`${styles.tabMenu} ${isInProfileView ? styles.horizontalScroll : ''}`}>
|
||||
<HeaderTabs />
|
||||
{(isInHomeView || isInHomeAboutView || isInSubplebbitView || isInHomeAboutView || isInPostPageView) && <AboutButton />}
|
||||
{(isInHomeView || isInHomeAboutView || isInCommunityView || isInHomeAboutView || isInPostPageView) && <AboutButton />}
|
||||
{!isInSubmitView && !isInSettingsView && (
|
||||
<li>
|
||||
<Link to={mobileSubmitButtonRoute} className={styles.submitButton}>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useCallback, useState } from 'react';
|
||||
import { Link, useLocation } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Author, useAccount, useComment, useSubplebbit } from '@bitsocial/bitsocial-react-hooks';
|
||||
import { Author, useAccount, useComment, useCommunity } from '@bitsocial/bitsocial-react-hooks';
|
||||
import useScheduledReset from '../../../hooks/use-scheduled-reset';
|
||||
import styles from './comment-tools.module.css';
|
||||
import EditMenu from './edit-menu';
|
||||
@@ -296,7 +296,7 @@ const CommentTools = ({
|
||||
}: CommentToolsProps) => {
|
||||
const account = useAccount();
|
||||
const isAuthor = account?.author?.address === author?.address;
|
||||
const subplebbit = useSubplebbit({ subplebbitAddress, onlyIfCached: true });
|
||||
const subplebbit = useCommunity(subplebbitAddress ? { community: { name: subplebbitAddress }, onlyIfCached: true } : undefined);
|
||||
const accountAuthorRole = subplebbit?.roles?.[account?.author?.address]?.role;
|
||||
const commentAuthorRole = subplebbit?.roles?.[author?.address]?.role;
|
||||
const isAccountMod = accountAuthorRole === 'admin' || accountAuthorRole === 'owner' || accountAuthorRole === 'moderator';
|
||||
|
||||
@@ -2,9 +2,9 @@ import { useState } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Author, useBlock } from '@bitsocial/bitsocial-react-hooks';
|
||||
import Plebbit from '@plebbit/plebbit-js';
|
||||
import { autoUpdate, flip, FloatingFocusManager, offset, shift, useClick, useDismiss, useFloating, useId, useInteractions, useRole } from '@floating-ui/react';
|
||||
import { isProfileHiddenView } from '../../../../lib/utils/view-utils';
|
||||
import getShortAddress from '../../../../lib/utils/address-utils';
|
||||
import styles from './hide-menu.module.css';
|
||||
|
||||
type HideMenuProps = {
|
||||
@@ -38,7 +38,7 @@ const BlockSubplebbitButton = ({ subplebbitAddress }: HideMenuProps) => {
|
||||
|
||||
return (
|
||||
<div className={styles.menuItem} onClick={blocked ? unblock : block}>
|
||||
{blocked ? `${t('unblock')}` : `${t('block')}`} s/{subplebbitAddress && Plebbit.getShortAddress({ address: subplebbitAddress })}
|
||||
{blocked ? `${t('unblock')}` : `${t('block')}`} s/{subplebbitAddress && getShortAddress(subplebbitAddress)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -79,7 +79,7 @@ const Expando = ({
|
||||
mediaComponent = <Embed url={commentMediaInfo.url} />;
|
||||
}
|
||||
|
||||
const pageSubplebbitAddress = useParams().subplebbitAddress;
|
||||
const pageSubplebbitAddress = useParams().communityAddress;
|
||||
const isNsfwSubplebbit = useIsNsfwSubplebbit(pageSubplebbitAddress || '');
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Link, useLocation, useParams, useSearchParams } from 'react-router-dom';
|
||||
import { Comment, useAuthorAddress, useBlock, useComment, useEditedComment, useSubplebbit, useSubscribe } from '@bitsocial/bitsocial-react-hooks';
|
||||
import Plebbit from '@plebbit/plebbit-js';
|
||||
import { Comment, useAuthorAddress, useBlock, useComment, useEditedComment, useCommunity, useSubscribe } from '@bitsocial/bitsocial-react-hooks';
|
||||
import { getHasThumbnail } from '../../lib/utils/media-utils';
|
||||
import getShortAddress from '../../lib/utils/address-utils';
|
||||
import { getPostScore, formatScore } from '../../lib/utils/post-utils';
|
||||
import { getFormattedTimeAgo, formatLocalizedUTCTimestamp } from '../../lib/utils/time-utils';
|
||||
import { getHostname } from '../../lib/utils/url-utils';
|
||||
import { isAllView, isAuthorView, isPendingPostView, isPostPageView, isProfileHiddenView, isProfileView, isSubplebbitView } from '../../lib/utils/view-utils';
|
||||
import { isAllView, isAuthorView, isPendingPostView, isPostPageView, isProfileHiddenView, isProfileView, isCommunityView } from '../../lib/utils/view-utils';
|
||||
import { highlightMatchedText } from '../../lib/utils/pattern-utils';
|
||||
import { usePinnedPostsStore } from '../../stores/use-pinned-posts-store';
|
||||
import { useCommentMediaInfo } from '../../hooks/use-comment-media-info';
|
||||
@@ -133,7 +133,7 @@ const Post = ({ index, post = {} }: PostProps) => {
|
||||
const postDate = formatLocalizedUTCTimestamp(timestamp, language);
|
||||
const params = useParams();
|
||||
const location = useLocation();
|
||||
const subplebbit = useSubplebbit({ subplebbitAddress, onlyIfCached: true });
|
||||
const subplebbit = useCommunity(subplebbitAddress ? { community: { name: subplebbitAddress }, onlyIfCached: true } : undefined);
|
||||
|
||||
const authorRole = subplebbit?.roles?.[post.author?.address]?.role;
|
||||
|
||||
@@ -143,7 +143,7 @@ const Post = ({ index, post = {} }: PostProps) => {
|
||||
const isInProfileView = isProfileView(location.pathname);
|
||||
const isInAuthorView = isAuthorView(location.pathname);
|
||||
const isInProfileHiddenView = isProfileHiddenView(location.pathname);
|
||||
const isInSubplebbitView = isSubplebbitView(location.pathname, params);
|
||||
const isInCommunityView = isCommunityView(location.pathname, params);
|
||||
|
||||
const commentMediaInfo = useCommentMediaInfo(post);
|
||||
|
||||
@@ -176,7 +176,7 @@ const Post = ({ index, post = {} }: PostProps) => {
|
||||
const { blocked, unblock } = useBlock({ cid });
|
||||
|
||||
const [hasClickedSubscribe, setHasClickedSubscribe] = useState(false);
|
||||
const { subscribe, subscribed } = useSubscribe({ subplebbitAddress });
|
||||
const { subscribe, subscribed } = useSubscribe({ communityAddress: subplebbitAddress });
|
||||
|
||||
// show gray dotted border around last clicked post
|
||||
const isLastClicked = sessionStorage.getItem('lastClickedPost') === cid && !isInPostPageView;
|
||||
@@ -194,7 +194,7 @@ const Post = ({ index, post = {} }: PostProps) => {
|
||||
const windowWidth = useWindowWidth();
|
||||
const pinnedPostsCount = usePinnedPostsStore((state) => state.pinnedPostsCount);
|
||||
let rank = (index ?? 0) + 1;
|
||||
if (isInSubplebbitView) {
|
||||
if (isInCommunityView) {
|
||||
rank = rank - pinnedPostsCount;
|
||||
}
|
||||
|
||||
@@ -260,9 +260,7 @@ const Post = ({ index, post = {} }: PostProps) => {
|
||||
{hostname ? (
|
||||
<Link to={`/domain/${hostname}`}>{hostname.length > 25 ? hostname.slice(0, 25) + '...' : hostname}</Link>
|
||||
) : (
|
||||
<Link to={`/s/${subplebbitAddress}`}>
|
||||
self.{subplebbit?.shortAddress || (subplebbitAddress && Plebbit.getShortAddress({ address: subplebbitAddress }))}
|
||||
</Link>
|
||||
<Link to={`/s/${subplebbitAddress}`}>self.{subplebbit?.shortAddress || (subplebbitAddress && getShortAddress(subplebbitAddress))}</Link>
|
||||
)}
|
||||
)
|
||||
</span>
|
||||
@@ -293,7 +291,7 @@ const Post = ({ index, post = {} }: PostProps) => {
|
||||
shortAuthorAddress={shortAuthorAddress}
|
||||
authorAddressChanged={authorAddressChanged}
|
||||
/>
|
||||
{!isInSubplebbitView && (
|
||||
{!isInCommunityView && (
|
||||
<>
|
||||
{t('post_to')}
|
||||
<span className={styles.subscribeHoverGroup}>
|
||||
@@ -309,7 +307,7 @@ const Post = ({ index, post = {} }: PostProps) => {
|
||||
</span>
|
||||
)}
|
||||
<Link className={`${styles.subplebbit} ${subscribed && hasClickedSubscribe ? styles.greenSubplebbitAddress : ''}`} to={`/s/${subplebbitAddress}`}>
|
||||
s/{subplebbit?.shortAddress || (subplebbitAddress && Plebbit.getShortAddress({ address: subplebbitAddress }))}
|
||||
s/{subplebbit?.shortAddress || (subplebbitAddress && getShortAddress(subplebbitAddress))}
|
||||
</Link>
|
||||
</span>
|
||||
</>
|
||||
|
||||
@@ -45,7 +45,7 @@ const Thumbnail = ({
|
||||
const thumbnailClass = expanded ? styles.thumbnailHidden : styles.thumbnailVisible;
|
||||
|
||||
const { blurNsfwThumbnails } = useContentOptionsStore();
|
||||
const pageSubplebbitAddress = useParams().subplebbitAddress;
|
||||
const pageSubplebbitAddress = useParams().communityAddress;
|
||||
const isNsfwSubplebbit = useIsNsfwSubplebbit(pageSubplebbitAddress || '');
|
||||
|
||||
if (linkWidth && linkHeight) {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useSubplebbit } from '@bitsocial/bitsocial-react-hooks';
|
||||
import { useCommunity } from '@bitsocial/bitsocial-react-hooks';
|
||||
import { isValidURL } from '../../lib/utils/url-utils';
|
||||
import useIsSubplebbitOffline from '../../hooks/use-is-subplebbit-offline';
|
||||
import useIsCommunityOffline from '../../hooks/use-is-community-offline';
|
||||
import usePublishReply from '../../hooks/use-publish-reply';
|
||||
import Markdown from '../markdown';
|
||||
import styles from './reply-form.module.css';
|
||||
@@ -122,8 +122,8 @@ const ReplyForm = ({ cid, isReplyingToReply, hideReplyForm, subplebbitAddress, p
|
||||
const spoilerClass = showOptions ? styles.spoilerVisible : styles.spoilerHidden;
|
||||
const nsfwClass = showOptions ? styles.spoilerVisible : styles.spoilerHidden;
|
||||
|
||||
const subplebbit = useSubplebbit({ subplebbitAddress, onlyIfCached: true });
|
||||
const { isOffline, offlineTitle } = useIsSubplebbitOffline(subplebbit);
|
||||
const subplebbit = useCommunity(subplebbitAddress ? { community: { name: subplebbitAddress }, onlyIfCached: true } : undefined);
|
||||
const { isOffline, offlineTitle } = useIsCommunityOffline(subplebbit);
|
||||
|
||||
// focus on the textarea when replying to a reply
|
||||
const textRef = useRef<HTMLTextAreaElement>(null);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Fragment, useEffect, useMemo, useState, useRef } from 'react';
|
||||
import { Link, useLocation, useParams } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Plebbit from '@plebbit/plebbit-js';
|
||||
import { Comment, useAccountComment, useAuthorAddress, useAuthorAvatar, useBlock, useComment, useEditedComment, useSubplebbit } from '@bitsocial/bitsocial-react-hooks';
|
||||
import { Comment, useAccountComment, useAuthorAddress, useAuthorAvatar, useBlock, useComment, useEditedComment, useCommunity } from '@bitsocial/bitsocial-react-hooks';
|
||||
import { isInboxView, isPostContextView, isPostPageView } from '../../lib/utils/view-utils';
|
||||
import getShortAddress from '../../lib/utils/address-utils';
|
||||
import { getHostname } from '../../lib/utils/url-utils';
|
||||
import { formatScore, getReplyScore } from '../../lib/utils/post-utils';
|
||||
import { flattenCommentsPages } from '@bitsocial/bitsocial-react-hooks/dist/lib/utils';
|
||||
@@ -282,7 +282,7 @@ const InboxShowParentButton = ({ parentCid }: { parentCid: string | undefined })
|
||||
|
||||
const InboxParentInfo = ({ address, cid, markedAsRead, parentCid, postCid, shortAddress, subplebbitAddress, timestamp }: ParentLinkProps) => {
|
||||
const { t } = useTranslation();
|
||||
const shortSubplebbitAddress = subplebbitAddress ? (subplebbitAddress.includes('.') ? subplebbitAddress : Plebbit.getShortAddress({ address: subplebbitAddress })) : '';
|
||||
const shortSubplebbitAddress = subplebbitAddress ? (subplebbitAddress.includes('.') ? subplebbitAddress : getShortAddress(subplebbitAddress)) : '';
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -342,7 +342,7 @@ const Reply = ({ cidOfReplyWithContext, depth = 0, isSingleComment, isSingleRepl
|
||||
timestamp,
|
||||
upvoteCount,
|
||||
} = reply || {};
|
||||
const subplebbit = useSubplebbit({ subplebbitAddress, onlyIfCached: true });
|
||||
const subplebbit = useCommunity(subplebbitAddress ? { community: { name: subplebbitAddress }, onlyIfCached: true } : undefined);
|
||||
|
||||
const pendingReply = useAccountComment({ commentIndex: reply?.index });
|
||||
const parentOfPendingReply = useComment({ commentCid: pendingReply?.parentCid, onlyIfCached: true });
|
||||
|
||||
@@ -3,17 +3,17 @@ import { useLocation, useNavigate, useParams, useSearchParams } from 'react-rout
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useFloating, autoUpdate, offset, shift, FloatingPortal } from '@floating-ui/react';
|
||||
import { useAccount } from '@bitsocial/bitsocial-react-hooks';
|
||||
import Plebbit from '@plebbit/plebbit-js';
|
||||
import {
|
||||
isHomeView,
|
||||
isHomeAboutView,
|
||||
isPostPageView,
|
||||
isPostPageAboutView,
|
||||
isSubplebbitView,
|
||||
isCommunityView,
|
||||
isAllView,
|
||||
isModView,
|
||||
isSubplebbitAboutView,
|
||||
isCommunityAboutView,
|
||||
} 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 styles from './search-bar.module.css';
|
||||
@@ -33,14 +33,14 @@ const SearchBar = ({ isFocused = false, onExpandoChange }: SearchBarProps) => {
|
||||
|
||||
const isInHomeAboutView = isHomeAboutView(location.pathname);
|
||||
const isInPostPageAboutView = isPostPageAboutView(location.pathname, params);
|
||||
const isInSubplebbitView = isSubplebbitView(location.pathname, params);
|
||||
const isInSubplebbitAboutView = isSubplebbitAboutView(location.pathname, params);
|
||||
const isInCommunityView = isCommunityView(location.pathname, params);
|
||||
const isInCommunityAboutView = isCommunityAboutView(location.pathname, params);
|
||||
const isInHomeView = isHomeView(location.pathname);
|
||||
const isInPostPageView = isPostPageView(location.pathname, params);
|
||||
const isInAllView = isAllView(location.pathname);
|
||||
const isInModView = isModView(location.pathname);
|
||||
|
||||
const isInFeedView = (isInSubplebbitView || isInHomeView || isInAllView || isInModView) && !isInPostPageView;
|
||||
const isInFeedView = (isInCommunityView || isInHomeView || isInAllView || isInModView) && !isInPostPageView;
|
||||
|
||||
const currentQuery = searchParams.get('q') || '';
|
||||
const [isInCommunitySearch, setIsInCommunitySearch] = useState(() => {
|
||||
@@ -141,7 +141,7 @@ const SearchBar = ({ isFocused = false, onExpandoChange }: SearchBarProps) => {
|
||||
}
|
||||
const searchInput = searchInputRef.current?.value;
|
||||
if (searchInput) {
|
||||
if (searchInput.toLowerCase() === params.subplebbitAddress?.toLowerCase()) {
|
||||
if (searchInput.toLowerCase() === params.communityAddress?.toLowerCase()) {
|
||||
alert(t('already_in_community'));
|
||||
return;
|
||||
}
|
||||
@@ -183,7 +183,7 @@ const SearchBar = ({ isFocused = false, onExpandoChange }: SearchBarProps) => {
|
||||
|
||||
const handleCommunitySelect = useCallback(
|
||||
(address: string) => {
|
||||
if (address.toLowerCase() === params.subplebbitAddress?.toLowerCase()) {
|
||||
if (address.toLowerCase() === params.communityAddress?.toLowerCase()) {
|
||||
alert(t('already_in_community'));
|
||||
return;
|
||||
}
|
||||
@@ -194,7 +194,7 @@ const SearchBar = ({ isFocused = false, onExpandoChange }: SearchBarProps) => {
|
||||
searchInputRef.current?.blur();
|
||||
navigate(`/s/${address}`);
|
||||
},
|
||||
[navigate, setInputValue, setIsInputFocused, setActiveDropdownIndex, params.subplebbitAddress, t],
|
||||
[navigate, setInputValue, setIsInputFocused, setActiveDropdownIndex, params.communityAddress, t],
|
||||
);
|
||||
|
||||
const handleKeyDown = useCallback(
|
||||
@@ -228,7 +228,7 @@ const SearchBar = ({ isFocused = false, onExpandoChange }: SearchBarProps) => {
|
||||
);
|
||||
|
||||
return (
|
||||
<div ref={wrapperRef} className={`${styles.searchBarWrapper} ${isInHomeAboutView || isInSubplebbitAboutView || isInPostPageAboutView ? styles.mobileInfobar : ''}`}>
|
||||
<div ref={wrapperRef} className={`${styles.searchBarWrapper} ${isInHomeAboutView || isInCommunityAboutView || isInPostPageAboutView ? styles.mobileInfobar : ''}`}>
|
||||
<form className={styles.searchBar} ref={searchBarRef} onSubmit={handleSearchSubmit}>
|
||||
<input
|
||||
type='text'
|
||||
@@ -272,7 +272,7 @@ const SearchBar = ({ isFocused = false, onExpandoChange }: SearchBarProps) => {
|
||||
onTouchEnd={() => handleCommunitySelect(address)}
|
||||
onMouseEnter={() => setActiveDropdownIndex(index)}
|
||||
>
|
||||
{Plebbit.getShortAddress({ address })}
|
||||
{getShortAddress(address)}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { Link, useLocation, useNavigate, useParams } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Comment, useAccount, useBlock, Role, Subplebbit, useSubplebbitStats, useAccountComment, usePlebbitRpcSettings } from '@bitsocial/bitsocial-react-hooks';
|
||||
import Plebbit from '@plebbit/plebbit-js';
|
||||
import { Comment, useAccount, useBlock, Role, Community, useCommunityStats, useAccountComment, usePkcRpcSettings } from '@bitsocial/bitsocial-react-hooks';
|
||||
import { getPostScore } from '../../lib/utils/post-utils';
|
||||
import { getFormattedDate, getFormattedTimeDuration, getFormattedTimeAgo } from '../../lib/utils/time-utils';
|
||||
import { findSubplebbitCreator } from '../../lib/utils/user-utils';
|
||||
import getShortAddress from '../../lib/utils/address-utils';
|
||||
import {
|
||||
isAllView,
|
||||
isDomainView,
|
||||
@@ -15,14 +15,14 @@ import {
|
||||
isPendingPostView,
|
||||
isPostPageAboutView,
|
||||
isPostPageView,
|
||||
isSubplebbitAboutView,
|
||||
isSubplebbitSettingsView,
|
||||
isSubplebbitsView,
|
||||
isSubplebbitView,
|
||||
isCommunityAboutView,
|
||||
isCommunitySettingsView,
|
||||
isCommunitiesView,
|
||||
isCommunityView,
|
||||
} from '../../lib/utils/view-utils';
|
||||
import useCommunitySubtitles from '../../hooks/use-community-subtitles';
|
||||
import useIsMobile from '../../hooks/use-is-mobile';
|
||||
import useIsSubplebbitOffline from '../../hooks/use-is-subplebbit-offline';
|
||||
import useIsCommunityOffline from '../../hooks/use-is-community-offline';
|
||||
import { FAQ } from '../../views/about/about';
|
||||
import LoadingEllipsis from '../loading-ellipsis';
|
||||
import Markdown from '../markdown';
|
||||
@@ -55,7 +55,7 @@ const ModeratorsList = ({ roles }: { roles: Record<string, Role> }) => {
|
||||
<ul className={`${styles.listContent} ${styles.modsList}`}>
|
||||
{rolesList.map(({ address }, index) => (
|
||||
<li key={index} onClick={() => window.alert('Direct profile links are not supported yet.')}>
|
||||
u/{Plebbit.getShortAddress({ address })}
|
||||
u/{getShortAddress(address)}
|
||||
</li>
|
||||
))}
|
||||
{/* TODO: https://github.com/bitsocialhq/seedit/issues/274
|
||||
@@ -97,13 +97,13 @@ const ModerationTools = ({ address }: { address?: string }) => {
|
||||
const { t } = useTranslation();
|
||||
const location = useLocation();
|
||||
const params = useParams();
|
||||
const isInSubplebbitSettingsView = isSubplebbitSettingsView(location.pathname, params);
|
||||
const isInCommunitySettingsView = isCommunitySettingsView(location.pathname, params);
|
||||
|
||||
return (
|
||||
<div className={styles.list}>
|
||||
<div className={styles.listTitle}>{t('moderation_tools')}</div>
|
||||
<ul className={`${styles.listContent} ${styles.modsList}`}>
|
||||
<li className={`${styles.moderationTool} ${isInSubplebbitSettingsView ? styles.selectedTool : ''}`}>
|
||||
<li className={`${styles.moderationTool} ${isInCommunitySettingsView ? styles.selectedTool : ''}`}>
|
||||
<Link className={styles.communitySettingsTool} to={`/s/${address}/settings`}>
|
||||
{t('community_settings')}
|
||||
</Link>
|
||||
@@ -117,7 +117,7 @@ interface SidebarProps {
|
||||
comment?: Comment;
|
||||
isSubCreatedButNotYetPublished?: boolean;
|
||||
settings?: any;
|
||||
subplebbit?: Subplebbit;
|
||||
subplebbit?: Community;
|
||||
reset?: () => void;
|
||||
}
|
||||
|
||||
@@ -127,12 +127,12 @@ export const Footer = () => {
|
||||
const isMobile = useIsMobile();
|
||||
const isInHomeAboutView = isHomeAboutView(location.pathname);
|
||||
const isInPostPageAboutView = isPostPageAboutView(location.pathname, params);
|
||||
const isInSubplebbitView = isSubplebbitView(location.pathname, params);
|
||||
const isInCommunityView = isCommunityView(location.pathname, params);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`${styles.footer} ${isMobile && (isInHomeAboutView || isInPostPageAboutView) ? styles.mobileFooter : ''} ${
|
||||
isInSubplebbitView ? styles.subplebbitFooterMargin : ''
|
||||
isInCommunityView ? styles.subplebbitFooterMargin : ''
|
||||
}`}
|
||||
>
|
||||
<div className={styles.footerLinks}>
|
||||
@@ -173,8 +173,8 @@ export const Footer = () => {
|
||||
const Sidebar = ({ comment, isSubCreatedButNotYetPublished, settings, subplebbit, reset }: SidebarProps) => {
|
||||
const { t } = useTranslation();
|
||||
const { address, createdAt, description, roles, rules, title, updatedAt } = subplebbit || {};
|
||||
const { allActiveUserCount, hourActiveUserCount } = useSubplebbitStats({ subplebbitAddress: address });
|
||||
const { isOffline, offlineTitle } = useIsSubplebbitOffline(subplebbit || {});
|
||||
const { allActiveUserCount, hourActiveUserCount } = useCommunityStats(address ? { community: { name: address } } : undefined);
|
||||
const { isOffline, offlineTitle } = useIsCommunityOffline(subplebbit || {});
|
||||
const onlineNotice = t('users_online', { count: hourActiveUserCount || 0 });
|
||||
const offlineNotice = updatedAt ? t('posts_last_synced', { dateAgo: getFormattedTimeAgo(updatedAt) }) : offlineTitle;
|
||||
const onlineStatus = !isOffline ? onlineNotice : offlineNotice;
|
||||
@@ -191,14 +191,14 @@ const Sidebar = ({ comment, isSubCreatedButNotYetPublished, settings, subplebbit
|
||||
const isInModView = isModView(location.pathname);
|
||||
const isInPendingPostView = isPendingPostView(location.pathname, params);
|
||||
const isInPostPageView = isPostPageView(location.pathname, params);
|
||||
const isInSubplebbitsView = isSubplebbitsView(location.pathname);
|
||||
const isInSubplebbitAboutView = isSubplebbitAboutView(location.pathname, params);
|
||||
const isInSubplebbitView = isSubplebbitView(location.pathname, params);
|
||||
const isInCommunitiesView = isCommunitiesView(location.pathname);
|
||||
const isInCommunityAboutView = isCommunityAboutView(location.pathname, params);
|
||||
const isInCommunityView = isCommunityView(location.pathname, params);
|
||||
|
||||
const pendingPost = useAccountComment({ commentIndex: params?.accountCommentIndex as any });
|
||||
|
||||
const subplebbitCreator = findSubplebbitCreator(roles);
|
||||
const creatorAddress = subplebbitCreator === 'anonymous' ? 'anonymous' : `${Plebbit.getShortAddress({ address: subplebbitCreator })}`;
|
||||
const creatorAddress = subplebbitCreator === 'anonymous' ? 'anonymous' : `${getShortAddress(subplebbitCreator)}`;
|
||||
const submitRoute =
|
||||
isInHomeView || isInHomeAboutView || isInAllView || isInModView || isInDomainView
|
||||
? '/submit'
|
||||
@@ -255,7 +255,7 @@ const Sidebar = ({ comment, isSubCreatedButNotYetPublished, settings, subplebbit
|
||||
}
|
||||
}, [communitySubtitles]);
|
||||
|
||||
const isConnectedToRpc = usePlebbitRpcSettings()?.state === 'connected';
|
||||
const isConnectedToRpc = usePkcRpcSettings()?.state === 'connected';
|
||||
const navigate = useNavigate();
|
||||
const handleCreateCommunity = () => {
|
||||
// creating a community only works if the user is running a full node
|
||||
@@ -292,7 +292,7 @@ const Sidebar = ({ comment, isSubCreatedButNotYetPublished, settings, subplebbit
|
||||
}}
|
||||
>
|
||||
{(isInPostPageView || isInPendingPostView) && <PostInfo comment={comment} />}
|
||||
{(isInSubplebbitView || isInHomeView || isInAllView || isInModView || isInDomainView || isInPendingPostView) && (
|
||||
{(isInCommunityView || isInHomeView || isInAllView || isInModView || isInDomainView || isInPendingPostView) && (
|
||||
<Link to={submitRoute}>
|
||||
<div className={styles.largeButton}>
|
||||
{t('submit_post')}
|
||||
@@ -304,7 +304,7 @@ const Sidebar = ({ comment, isSubCreatedButNotYetPublished, settings, subplebbit
|
||||
!isInHomeAboutView &&
|
||||
!isInAllView &&
|
||||
!isInModView &&
|
||||
!isInSubplebbitsView &&
|
||||
!isInCommunitiesView &&
|
||||
!isInHomeAboutView &&
|
||||
!isInDomainView &&
|
||||
!isInPostPageAboutView && (
|
||||
@@ -366,7 +366,7 @@ const Sidebar = ({ comment, isSubCreatedButNotYetPublished, settings, subplebbit
|
||||
</div>
|
||||
)}
|
||||
{(moderatorRole || isOwner) && <ModerationTools address={address} />}
|
||||
{isInSubplebbitsView && (
|
||||
{isInCommunitiesView && (
|
||||
<a href='https://github.com/bitsocialhq/lists' target='_blank' rel='noopener noreferrer'>
|
||||
<div className={styles.largeButton}>
|
||||
<div className={styles.nub} />
|
||||
@@ -386,7 +386,7 @@ const Sidebar = ({ comment, isSubCreatedButNotYetPublished, settings, subplebbit
|
||||
{subtitle2 && <div className={styles.createCommunitySubtitle}>{subtitle2}</div>}
|
||||
</div>
|
||||
{roles && Object.keys(roles).length > 0 && <ModeratorsList roles={roles} />}
|
||||
{(!(isMobile && isInHomeAboutView) || isInSubplebbitAboutView || isInPostPageAboutView) && <Footer />}
|
||||
{(!(isMobile && isInHomeAboutView) || isInCommunityAboutView || isInPostPageAboutView) && <Footer />}
|
||||
{address && !(moderatorRole || isOwner) && (
|
||||
<div className={styles.readOnlySettingsLink}>
|
||||
<Link to={`/s/${address}/settings`}>{t('community_settings')}</Link>
|
||||
|
||||
@@ -10,7 +10,7 @@ interface subscribeButtonProps {
|
||||
}
|
||||
|
||||
const SubscribeButton = ({ address, onUnsubscribe }: subscribeButtonProps) => {
|
||||
const { subscribe, subscribed, unsubscribe } = useSubscribe({ subplebbitAddress: address });
|
||||
const { subscribe, subscribed, unsubscribe } = useSubscribe({ communityAddress: address });
|
||||
const { t } = useTranslation();
|
||||
const location = useLocation();
|
||||
const params = useParams();
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { useEffect, useRef, useState, useMemo, memo } from 'react';
|
||||
import { Link, useLocation, useParams } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useAccount, useAccountSubplebbits } from '@bitsocial/bitsocial-react-hooks';
|
||||
import Plebbit from '@plebbit/plebbit-js';
|
||||
import { isAllView, isDomainView, isHomeView, isModView, isSubplebbitView } from '../../lib/utils/view-utils';
|
||||
import { useAccount, useAccountCommunities } from '@bitsocial/bitsocial-react-hooks';
|
||||
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 useTimeFilter, { setSessionTimeFilterPreference } from '../../hooks/use-time-filter';
|
||||
@@ -42,7 +42,7 @@ const CommunitiesDropdown = () => {
|
||||
<div className={`${styles.dropChoices} ${styles.subsDropChoices} ${subsDropdownClass}`} ref={subsdropdownItemsRef}>
|
||||
{reversedSubscriptions?.map((subscription: string, index: number) => (
|
||||
<Link key={index} to={`/s/${subscription}`} className={styles.dropdownItem}>
|
||||
{Plebbit.getShortAddress({ address: subscription })}
|
||||
{getShortAddress(subscription)}
|
||||
</Link>
|
||||
))}
|
||||
<Link to='/communities/subscriber' className={`${styles.dropdownItem} ${styles.myCommunitiesItemButtonDotted}`}>
|
||||
@@ -168,7 +168,7 @@ const SortTypesDropdown = () => {
|
||||
const { t } = useTranslation();
|
||||
const params = useParams();
|
||||
const location = useLocation();
|
||||
const isInSubplebbitView = isSubplebbitView(location.pathname, params);
|
||||
const isInCommunityView = isCommunityView(location.pathname, params);
|
||||
const isinAllView = isAllView(location.pathname);
|
||||
const { timeFilterName } = useTimeFilter();
|
||||
|
||||
@@ -203,7 +203,7 @@ const SortTypesDropdown = () => {
|
||||
<span className={styles.selectedTitle}>{t(getSelectedSortLabel())}</span>
|
||||
<div className={`${styles.dropChoices} ${styles.sortsDropChoices} ${sortsDropdownClass}`} ref={sortsdropdownItemsRef}>
|
||||
{sortTypes.map((sortType, index) => {
|
||||
let dropdownLink = isInSubplebbitView ? `/s/${params.subplebbitAddress}/${sortType}` : isinAllView ? `/s/all/${sortType}` : sortType;
|
||||
let dropdownLink = isInCommunityView ? `/s/${params.communityAddress}/${sortType}` : isinAllView ? `/s/all/${sortType}` : sortType;
|
||||
if (timeFilterName) {
|
||||
dropdownLink += `/${timeFilterName}`;
|
||||
}
|
||||
@@ -221,12 +221,12 @@ const SortTypesDropdown = () => {
|
||||
const TimeFilterDropdown = () => {
|
||||
const params = useParams();
|
||||
const location = useLocation();
|
||||
const isInSubplebbitView = isSubplebbitView(location.pathname, params);
|
||||
const isInCommunityView = isCommunityView(location.pathname, params);
|
||||
const isInDomainView = isDomainView(location.pathname);
|
||||
const isinAllView = isAllView(location.pathname);
|
||||
const isInModView = isModView(location.pathname);
|
||||
const { timeFilterName, timeFilterNames, sessionKey } = useTimeFilter();
|
||||
const selectedTimeFilter = timeFilterName || (isInSubplebbitView ? 'all' : timeFilterName);
|
||||
const selectedTimeFilter = timeFilterName || (isInCommunityView ? 'all' : timeFilterName);
|
||||
|
||||
const [isTimeFilterDropdownOpen, setIsTimeFilterDropdownOpen] = useState(false);
|
||||
const toggleTimeFilterDropdown = () => setIsTimeFilterDropdownOpen(!isTimeFilterDropdownOpen);
|
||||
@@ -237,8 +237,8 @@ const TimeFilterDropdown = () => {
|
||||
const selectedSortType = params.sortType || 'hot';
|
||||
|
||||
const getTimeFilterLink = (timeFilterName: string) => {
|
||||
return isInSubplebbitView
|
||||
? `/s/${params.subplebbitAddress}/${selectedSortType}/${timeFilterName}`
|
||||
return isInCommunityView
|
||||
? `/s/${params.communityAddress}/${selectedSortType}/${timeFilterName}`
|
||||
: isinAllView
|
||||
? `s/all/${selectedSortType}/${timeFilterName}`
|
||||
: isInModView
|
||||
@@ -292,7 +292,7 @@ const TopBar = memo(() => {
|
||||
|
||||
const { hideDefaultCommunities } = useContentOptionsStore();
|
||||
const subplebbitAddresses = useDefaultSubplebbitAddresses();
|
||||
const { accountSubplebbits } = useAccountSubplebbits();
|
||||
const { accountCommunities: accountSubplebbits } = useAccountCommunities();
|
||||
const accountSubplebbitAddresses = useMemo(() => Object.keys(accountSubplebbits), [accountSubplebbits]);
|
||||
|
||||
const account = useAccount();
|
||||
@@ -331,12 +331,12 @@ const TopBar = memo(() => {
|
||||
)}
|
||||
{subscriptions?.length > 0 && <span className={styles.separator}> | </span>}
|
||||
{reversedSubscriptions?.map((subscription: string, index: number) => {
|
||||
const shortAddress = Plebbit.getShortAddress({ address: subscription });
|
||||
const shortAddress = getShortAddress(subscription);
|
||||
const displayAddress = shortAddress.includes('.eth') ? shortAddress.slice(0, -4) : shortAddress.includes('.sol') ? shortAddress.slice(0, -4) : shortAddress;
|
||||
return (
|
||||
<li key={index}>
|
||||
{index !== 0 && <span className={styles.separator}>-</span>}
|
||||
<Link to={`/s/${subscription}`} className={params.subplebbitAddress === subscription ? styles.selected : styles.choice}>
|
||||
<Link to={`/s/${subscription}`} className={params.communityAddress === subscription ? styles.selected : styles.choice}>
|
||||
{displayAddress}
|
||||
</Link>
|
||||
</li>
|
||||
@@ -345,7 +345,7 @@ const TopBar = memo(() => {
|
||||
{!hideDefaultCommunities && filteredSubplebbitAddresses?.length > 0 && <span className={styles.separator}> | </span>}
|
||||
{!hideDefaultCommunities &&
|
||||
filteredSubplebbitAddresses?.map((address, index) => {
|
||||
const shortAddress = Plebbit.getShortAddress({ address });
|
||||
const shortAddress = getShortAddress(address);
|
||||
const displayAddress = shortAddress.includes('.eth')
|
||||
? shortAddress.slice(0, -4)
|
||||
: shortAddress.includes('.sol')
|
||||
@@ -354,7 +354,7 @@ const TopBar = memo(() => {
|
||||
return (
|
||||
<li key={index}>
|
||||
{index !== 0 && <span className={styles.separator}>-</span>}
|
||||
<Link to={`/s/${address}`} className={params.subplebbitAddress === address ? styles.selected : styles.choice}>
|
||||
<Link to={`/s/${address}`} className={params.communityAddress === address ? styles.selected : styles.choice}>
|
||||
{displayAddress}
|
||||
</Link>
|
||||
</li>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { usePlebbitRpcSettings } from '@bitsocial/bitsocial-react-hooks';
|
||||
import { usePkcRpcSettings } from '@bitsocial/bitsocial-react-hooks';
|
||||
|
||||
const useChallengeSettings = (challengeName: string) => {
|
||||
const { challenges } = usePlebbitRpcSettings().plebbitRpcSettings || {};
|
||||
const { challenges } = usePkcRpcSettings().pkcRpcSettings || {};
|
||||
if (challenges) {
|
||||
return challenges[challengeName] || {};
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { usePlebbitRpcSettings } from '@bitsocial/bitsocial-react-hooks';
|
||||
import { usePkcRpcSettings } from '@bitsocial/bitsocial-react-hooks';
|
||||
|
||||
const useChallengesOptions = () => {
|
||||
const { challenges } = usePlebbitRpcSettings().plebbitRpcSettings || {};
|
||||
const { challenges } = usePkcRpcSettings().pkcRpcSettings || {};
|
||||
|
||||
const options = Object.keys(challenges || {}).reduce(
|
||||
(acc, challengeName) => {
|
||||
|
||||
25
src/hooks/use-community-identifier.ts
Normal file
25
src/hooks/use-community-identifier.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { useMemo } from 'react';
|
||||
import type { CommunityIdentifier } from '@bitsocial/bitsocial-react-hooks';
|
||||
|
||||
const isLikelyCommunityName = (value: string) => value.includes('.');
|
||||
|
||||
export const getCommunityIdentifier = (communityAddress: string | undefined): CommunityIdentifier | undefined => {
|
||||
if (!communityAddress) {
|
||||
return undefined;
|
||||
}
|
||||
return isLikelyCommunityName(communityAddress) ? { name: communityAddress } : { publicKey: communityAddress };
|
||||
};
|
||||
|
||||
export const getCommunityIdentifiers = (communityAddresses: Array<string | undefined>): CommunityIdentifier[] =>
|
||||
communityAddresses.flatMap((communityAddress) => {
|
||||
const community = getCommunityIdentifier(communityAddress);
|
||||
return community ? [community] : [];
|
||||
});
|
||||
|
||||
export const useCommunityIdentifier = (communityAddress: string | undefined): CommunityIdentifier | undefined => {
|
||||
return useMemo(() => getCommunityIdentifier(communityAddress), [communityAddress]);
|
||||
};
|
||||
|
||||
export const useCommunityIdentifiers = (communityAddresses?: Array<string | undefined>): CommunityIdentifier[] => {
|
||||
return useMemo(() => getCommunityIdentifiers(communityAddresses ?? []), [communityAddresses]);
|
||||
};
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { Subplebbit } from '@bitsocial/bitsocial-react-hooks';
|
||||
import { Community } from '@bitsocial/bitsocial-react-hooks';
|
||||
import useContentOptionsStore from '../stores/use-content-options-store';
|
||||
|
||||
export interface MultisubMetadata {
|
||||
@@ -109,7 +109,7 @@ export const useDefaultSubplebbitAddresses = () => {
|
||||
const { hideAdultCommunities, hideGoreCommunities, hideAntiCommunities, hideVulgarCommunities } = useContentOptionsStore();
|
||||
|
||||
const filteredSubplebbits = useMemo(() => {
|
||||
return defaultSubplebbits.filter((subplebbit: Subplebbit) => {
|
||||
return defaultSubplebbits.filter((subplebbit: Community) => {
|
||||
const tags = subplebbit.tags || [];
|
||||
if (hideAdultCommunities && tags.includes('adult')) return false;
|
||||
if (hideGoreCommunities && tags.includes('gore')) return false;
|
||||
|
||||
51
src/hooks/use-is-community-offline.ts
Normal file
51
src/hooks/use-is-community-offline.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useEffect } from 'react';
|
||||
import { Community } from '@bitsocial/bitsocial-react-hooks';
|
||||
import { getFormattedTimeAgo } from '../lib/utils/time-utils';
|
||||
import useCommunityOfflineStore from '../stores/use-community-offline-store';
|
||||
import useCommunitiesLoadingStartTimestamps from '../stores/use-communities-loading-start-timestamps-store';
|
||||
|
||||
const useIsCommunityOffline = (subplebbit: Community) => {
|
||||
const { t } = useTranslation();
|
||||
const { address, state, updatedAt, updatingState } = subplebbit || {};
|
||||
const { communityOfflineState, setCommunityOfflineState, initializeCommunityOfflineState } = useCommunityOfflineStore();
|
||||
const communitiesLoadingStartTimestamps = useCommunitiesLoadingStartTimestamps([address]);
|
||||
|
||||
useEffect(() => {
|
||||
if (address && !communityOfflineState[address]) {
|
||||
initializeCommunityOfflineState(address);
|
||||
}
|
||||
}, [address, communityOfflineState, initializeCommunityOfflineState]);
|
||||
|
||||
useEffect(() => {
|
||||
if (address) {
|
||||
setCommunityOfflineState(address, { state, updatedAt, updatingState });
|
||||
}
|
||||
}, [address, state, updatedAt, updatingState, setCommunityOfflineState]);
|
||||
|
||||
const communityOfflineStore = communityOfflineState[address] || { initialLoad: true };
|
||||
const loadingStartTimestamp = communitiesLoadingStartTimestamps[0] || 0;
|
||||
|
||||
const isLoading = communityOfflineStore.initialLoad && (!updatedAt || Date.now() / 1000 - updatedAt >= 120 * 60) && Date.now() / 1000 - loadingStartTimestamp < 30;
|
||||
|
||||
const isOffline = !isLoading && ((updatedAt && updatedAt < Date.now() / 1000 - 120 * 60) || (!updatedAt && Date.now() / 1000 - loadingStartTimestamp >= 30));
|
||||
|
||||
const isOnline = updatedAt && Date.now() / 1000 - updatedAt < 120 * 60;
|
||||
|
||||
const offlineTitle = isLoading
|
||||
? t('loading')
|
||||
: updatedAt
|
||||
? isOffline && t('posts_last_synced_info', { time: getFormattedTimeAgo(updatedAt), interpolation: { escapeValue: false } })
|
||||
: t('subplebbit_offline_info');
|
||||
|
||||
// ensure isOffline is false until we have enough information
|
||||
const hasEnoughInfo = communityOfflineStore.initialLoad === false || updatedAt !== undefined;
|
||||
|
||||
return {
|
||||
isOffline: hasEnoughInfo && !isOnline && isOffline,
|
||||
isOnlineStatusLoading: !isOnline && isLoading,
|
||||
offlineTitle,
|
||||
};
|
||||
};
|
||||
|
||||
export default useIsCommunityOffline;
|
||||
@@ -1,51 +0,0 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useEffect } from 'react';
|
||||
import { Subplebbit } from '@bitsocial/bitsocial-react-hooks';
|
||||
import { getFormattedTimeAgo } from '../lib/utils/time-utils';
|
||||
import useSubplebbitOfflineStore from '../stores/use-subplebbit-offline-store';
|
||||
import useSubplebbitsLoadingStartTimestamps from '../stores/use-subplebbits-loading-start-timestamps-store';
|
||||
|
||||
const useIsSubplebbitOffline = (subplebbit: Subplebbit) => {
|
||||
const { t } = useTranslation();
|
||||
const { address, state, updatedAt, updatingState } = subplebbit || {};
|
||||
const { subplebbitOfflineState, setSubplebbitOfflineState, initializesubplebbitOfflineState } = useSubplebbitOfflineStore();
|
||||
const subplebbitsLoadingStartTimestamps = useSubplebbitsLoadingStartTimestamps([address]);
|
||||
|
||||
useEffect(() => {
|
||||
if (address && !subplebbitOfflineState[address]) {
|
||||
initializesubplebbitOfflineState(address);
|
||||
}
|
||||
}, [address, subplebbitOfflineState, initializesubplebbitOfflineState]);
|
||||
|
||||
useEffect(() => {
|
||||
if (address) {
|
||||
setSubplebbitOfflineState(address, { state, updatedAt, updatingState });
|
||||
}
|
||||
}, [address, state, updatedAt, updatingState, setSubplebbitOfflineState]);
|
||||
|
||||
const subplebbitOfflineStore = subplebbitOfflineState[address] || { initialLoad: true };
|
||||
const loadingStartTimestamp = subplebbitsLoadingStartTimestamps[0] || 0;
|
||||
|
||||
const isLoading = subplebbitOfflineStore.initialLoad && (!updatedAt || Date.now() / 1000 - updatedAt >= 120 * 60) && Date.now() / 1000 - loadingStartTimestamp < 30;
|
||||
|
||||
const isOffline = !isLoading && ((updatedAt && updatedAt < Date.now() / 1000 - 120 * 60) || (!updatedAt && Date.now() / 1000 - loadingStartTimestamp >= 30));
|
||||
|
||||
const isOnline = updatedAt && Date.now() / 1000 - updatedAt < 120 * 60;
|
||||
|
||||
const offlineTitle = isLoading
|
||||
? t('loading')
|
||||
: updatedAt
|
||||
? isOffline && t('posts_last_synced_info', { time: getFormattedTimeAgo(updatedAt), interpolation: { escapeValue: false } })
|
||||
: t('subplebbit_offline_info');
|
||||
|
||||
// ensure isOffline is false until we have enough information
|
||||
const hasEnoughInfo = subplebbitOfflineStore.initialLoad === false || updatedAt !== undefined;
|
||||
|
||||
return {
|
||||
isOffline: hasEnoughInfo && !isOnline && isOffline,
|
||||
isOnlineStatusLoading: !isOnline && isLoading,
|
||||
offlineTitle,
|
||||
};
|
||||
};
|
||||
|
||||
export default useIsSubplebbitOffline;
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useMemo } from 'react';
|
||||
import { useClientsStates, useSubplebbit, useSubplebbitsStates } from '@bitsocial/bitsocial-react-hooks';
|
||||
import { useClientsStates, useCommunity, useCommunitiesStates } from '@bitsocial/bitsocial-react-hooks';
|
||||
import { debounce } from 'lodash';
|
||||
import { getCommunityIdentifiers } from './use-community-identifier';
|
||||
|
||||
interface CommentOrSubplebbit {
|
||||
state?: string;
|
||||
@@ -81,11 +82,11 @@ const useStateString = (commentOrSubplebbit: CommentOrSubplebbit): string | unde
|
||||
export const useFeedStateString = (subplebbitAddresses?: string[]): string | undefined => {
|
||||
// single subplebbit feed state string
|
||||
const subplebbitAddress = subplebbitAddresses?.length === 1 ? subplebbitAddresses[0] : undefined;
|
||||
const subplebbit = useSubplebbit({ subplebbitAddress });
|
||||
const subplebbit = useCommunity(subplebbitAddress ? { community: { name: subplebbitAddress } } : undefined);
|
||||
const singleSubplebbitFeedStateString = useStateString(subplebbit);
|
||||
|
||||
// multiple subplebbit feed state string
|
||||
const { states } = useSubplebbitsStates({ subplebbitAddresses });
|
||||
const { states } = useCommunitiesStates({ communities: getCommunityIdentifiers(subplebbitAddresses || []) });
|
||||
|
||||
const multipleSubplebbitsFeedStateString = useMemo(() => {
|
||||
if (subplebbitAddress) {
|
||||
@@ -96,25 +97,25 @@ export const useFeedStateString = (subplebbitAddresses?: string[]): string | und
|
||||
let stateString = '';
|
||||
|
||||
if (states['resolving-address']) {
|
||||
const { subplebbitAddresses, clientUrls } = states['resolving-address'];
|
||||
if (subplebbitAddresses.length && clientUrls.length) {
|
||||
stateString += `resolving ${subplebbitAddresses.length} ${subplebbitAddresses.length === 1 ? 'address' : 'addresses'} from ${clientUrls
|
||||
const { communityAddresses, clientUrls } = states['resolving-address'];
|
||||
if (communityAddresses.length && clientUrls.length) {
|
||||
stateString += `resolving ${communityAddresses.length} ${communityAddresses.length === 1 ? 'address' : 'addresses'} from ${clientUrls
|
||||
.map(getClientHost)
|
||||
.join(', ')}`;
|
||||
}
|
||||
}
|
||||
|
||||
// find all page client and sub addresses
|
||||
// find all page client and community addresses
|
||||
const pagesStatesClientHosts = new Set();
|
||||
const pagesStatesSubplebbitAddresses = new Set();
|
||||
const pagesStatesCommunityAddresses = new Set();
|
||||
for (const state in states) {
|
||||
if (state.match('page')) {
|
||||
states[state].clientUrls.forEach((clientUrl) => pagesStatesClientHosts.add(getClientHost(clientUrl)));
|
||||
states[state].subplebbitAddresses.forEach((subplebbitAddress) => pagesStatesSubplebbitAddresses.add(subplebbitAddress));
|
||||
states[state].communityAddresses.forEach((communityAddress) => pagesStatesCommunityAddresses.add(communityAddress));
|
||||
}
|
||||
}
|
||||
|
||||
if (states['fetching-ipns'] || states['fetching-ipfs'] || pagesStatesSubplebbitAddresses.size) {
|
||||
if (states['fetching-ipns'] || states['fetching-ipfs'] || pagesStatesCommunityAddresses.size) {
|
||||
// separate 2 different states using ', '
|
||||
if (stateString) {
|
||||
stateString += ', ';
|
||||
@@ -128,21 +129,19 @@ export const useFeedStateString = (subplebbitAddresses?: string[]): string | und
|
||||
if (clientHosts.size) {
|
||||
stateString += 'downloading ';
|
||||
if (states['fetching-ipns']) {
|
||||
stateString += `${states['fetching-ipns'].subplebbitAddresses.length} ${
|
||||
states['fetching-ipns'].subplebbitAddresses.length === 1 ? 'community' : 'communities'
|
||||
}`;
|
||||
stateString += `${states['fetching-ipns'].communityAddresses.length} ${states['fetching-ipns'].communityAddresses.length === 1 ? 'community' : 'communities'}`;
|
||||
}
|
||||
if (states['fetching-ipfs']) {
|
||||
if (states['fetching-ipns']) {
|
||||
stateString += ', ';
|
||||
}
|
||||
stateString += `${states['fetching-ipfs'].subplebbitAddresses.length} ${states['fetching-ipfs'].subplebbitAddresses.length === 1 ? 'post' : 'posts'}`;
|
||||
stateString += `${states['fetching-ipfs'].communityAddresses.length} ${states['fetching-ipfs'].communityAddresses.length === 1 ? 'post' : 'posts'}`;
|
||||
}
|
||||
if (pagesStatesSubplebbitAddresses.size) {
|
||||
if (pagesStatesCommunityAddresses.size) {
|
||||
if (states['fetching-ipns'] || states['fetching-ipfs']) {
|
||||
stateString += ', ';
|
||||
}
|
||||
stateString += `${pagesStatesSubplebbitAddresses.size} ${pagesStatesSubplebbitAddresses.size === 1 ? 'page' : 'pages'}`;
|
||||
stateString += `${pagesStatesCommunityAddresses.size} ${pagesStatesCommunityAddresses.size === 1 ? 'page' : 'pages'}`;
|
||||
}
|
||||
stateString += ` from ${[...clientHosts].join(', ')}`;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import assert from 'assert';
|
||||
import { useEffect } from 'react';
|
||||
import { useLocation, useParams, Params } from 'react-router-dom';
|
||||
import { isSubplebbitView, isAllView, isModView, isHomeView, isDomainView } from '../lib/utils/view-utils';
|
||||
import { isCommunityView, isAllView, isModView, isHomeView, isDomainView } from '../lib/utils/view-utils';
|
||||
|
||||
// the timestamp the last time the user visited
|
||||
const lastVisitTimestamp = localStorage.getItem('seeditLastVisitTimestamp');
|
||||
@@ -85,7 +85,7 @@ const getSessionKeyForView = (pathname: string, params: Readonly<Params<string>>
|
||||
if (isAllView(pathname)) return 'sessionTimeFilter-all';
|
||||
if (isModView(pathname)) return 'sessionTimeFilter-mod';
|
||||
if (isDomainView(pathname)) return `sessionTimeFilter-domain-${params.domain}`;
|
||||
if (isSubplebbitView(pathname, params)) return `sessionTimeFilter-subplebbit-${params.subplebbitAddress}`;
|
||||
if (isCommunityView(pathname, params)) return `sessionTimeFilter-community-${params.communityAddress}`;
|
||||
return null;
|
||||
};
|
||||
|
||||
@@ -130,7 +130,7 @@ export const isValidTimeFilterName = (name: string | undefined | null): boolean
|
||||
const useTimeFilter = () => {
|
||||
const params = useParams();
|
||||
const location = useLocation();
|
||||
const isInSubplebbitView = isSubplebbitView(location.pathname, params);
|
||||
const isInCommunityView = isCommunityView(location.pathname, params);
|
||||
const isInDomainView = Boolean(params.domain);
|
||||
const sessionKey = getSessionKeyForView(location.pathname, params);
|
||||
|
||||
@@ -152,7 +152,7 @@ const useTimeFilter = () => {
|
||||
// let the redirect logic in the component handle it.
|
||||
// Just use it for calculating initial timeFilterSeconds if needed below.
|
||||
} else {
|
||||
if (isInSubplebbitView) {
|
||||
if (isInCommunityView) {
|
||||
timeFilterName = 'all';
|
||||
} else if (isInDomainView) {
|
||||
timeFilterName = '1y';
|
||||
|
||||
@@ -1,283 +0,0 @@
|
||||
import { useMemo } from 'react';
|
||||
import {
|
||||
deleteCommunity as deleteCommunityBase,
|
||||
setAccount as setAccountBase,
|
||||
useAccountComment as useAccountCommentBase,
|
||||
useAccountCommunities as useAccountCommunitiesBase,
|
||||
useCommunities as useCommunitiesBase,
|
||||
useCommunitiesStates as useCommunitiesStatesBase,
|
||||
useCommunity as useCommunityBase,
|
||||
useCommunityStats as useCommunityStatsBase,
|
||||
useCreateCommunity as useCreateCommunityBase,
|
||||
useFeed as useFeedBase,
|
||||
usePublishCommunityEdit as usePublishCommunityEditBase,
|
||||
useSubscribe as useSubscribeBase,
|
||||
} from '@bitsocial/bitsocial-react-hooks/dist/index.js';
|
||||
import type {
|
||||
Account,
|
||||
AccountCommunity,
|
||||
Community,
|
||||
PublishCommunityEditOptions,
|
||||
UseAccountCommentOptions as BaseUseAccountCommentOptions,
|
||||
UseAccountCommentResult as BaseUseAccountCommentResult,
|
||||
UseAccountCommunitiesOptions,
|
||||
UseAccountCommunitiesResult,
|
||||
UseCommunitiesOptions,
|
||||
UseCommunitiesResult,
|
||||
UseCommunitiesStatesOptions,
|
||||
UseCommunitiesStatesResult,
|
||||
UseCommunityOptions,
|
||||
UseCommunityResult,
|
||||
UseCommunityStatsOptions,
|
||||
UseCommunityStatsResult,
|
||||
UseCreateCommunityOptions,
|
||||
UseCreateCommunityResult,
|
||||
UseFeedOptions as BaseUseFeedOptions,
|
||||
UseFeedResult as BaseUseFeedResult,
|
||||
UsePublishCommunityEditOptions,
|
||||
UsePublishCommunityEditResult,
|
||||
UseSubscribeOptions as BaseUseSubscribeOptions,
|
||||
} from '@bitsocial/bitsocial-react-hooks/dist/index.js';
|
||||
import accountsStore from '@bitsocial/bitsocial-react-hooks/dist/stores/accounts/index.js';
|
||||
|
||||
export * from '@bitsocial/bitsocial-react-hooks/dist/index.js';
|
||||
|
||||
type AliasAddresses<T extends { address?: string; subplebbitAddress?: string } | undefined> = T;
|
||||
|
||||
const withSubplebbitAddress = <T extends { address?: string; subplebbitAddress?: string } | undefined>(value: T): AliasAddresses<T> => {
|
||||
if (!value || value.subplebbitAddress || !value.address) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return { ...value, subplebbitAddress: value.address } as AliasAddresses<T>;
|
||||
};
|
||||
|
||||
export type Subplebbit = Community;
|
||||
export type AccountSubplebbit = AccountCommunity & Partial<Community>;
|
||||
export type PublishSubplebbitEditOptions = PublishCommunityEditOptions;
|
||||
|
||||
export interface UseSubplebbitOptions extends Omit<UseCommunityOptions, 'communityAddress'> {
|
||||
subplebbitAddress?: string;
|
||||
}
|
||||
|
||||
export interface UseSubplebbitsOptions extends Omit<UseCommunitiesOptions, 'communityAddresses'> {
|
||||
subplebbitAddresses?: string[];
|
||||
}
|
||||
|
||||
export interface UseSubplebbitStatsOptions extends Omit<UseCommunityStatsOptions, 'communityAddress'> {
|
||||
subplebbitAddress?: string;
|
||||
}
|
||||
|
||||
export interface UseAccountSubplebbitsResult extends Omit<UseAccountCommunitiesResult, 'accountCommunities'> {
|
||||
accountSubplebbits: UseAccountCommunitiesResult['accountCommunities'];
|
||||
}
|
||||
|
||||
export interface UseFeedOptions extends Omit<BaseUseFeedOptions, 'communityAddresses'> {
|
||||
communityAddresses?: string[];
|
||||
subplebbitAddresses?: string[];
|
||||
}
|
||||
|
||||
export interface UseFeedResult extends BaseUseFeedResult {
|
||||
subplebbitAddressesWithNewerPosts: string[];
|
||||
}
|
||||
|
||||
export interface UseSubscribeOptions extends Omit<BaseUseSubscribeOptions, 'communityAddress'> {
|
||||
communityAddress?: string;
|
||||
subplebbitAddress?: string;
|
||||
}
|
||||
|
||||
export interface UseSubplebbitsStatesOptions extends Omit<UseCommunitiesStatesOptions, 'communityAddresses'> {
|
||||
communityAddresses?: string[];
|
||||
subplebbitAddresses?: string[];
|
||||
}
|
||||
|
||||
export interface UseSubplebbitsStatesResult extends Omit<UseCommunitiesStatesResult, 'states'> {
|
||||
states: {
|
||||
[state: string]: {
|
||||
subplebbitAddresses: string[];
|
||||
clientUrls: string[];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export interface UsePublishSubplebbitEditOptions extends Omit<UsePublishCommunityEditOptions, 'communityAddress'> {
|
||||
communityAddress?: string;
|
||||
subplebbitAddress?: string;
|
||||
}
|
||||
|
||||
export interface UsePublishSubplebbitEditResult extends Omit<UsePublishCommunityEditResult, 'publishCommunityEdit'> {
|
||||
publishSubplebbitEdit(): Promise<void>;
|
||||
}
|
||||
|
||||
export type UseCreateSubplebbitOptions = UseCreateCommunityOptions;
|
||||
|
||||
export interface UseCreateSubplebbitResult extends Omit<UseCreateCommunityResult, 'createdCommunity' | 'createCommunity'> {
|
||||
createdSubplebbit: UseCreateCommunityResult['createdCommunity'];
|
||||
createSubplebbit(): Promise<void>;
|
||||
}
|
||||
|
||||
export interface UseAccountCommentOptions extends BaseUseAccountCommentOptions {}
|
||||
|
||||
export interface UseAccountCommentResult extends BaseUseAccountCommentResult {
|
||||
refresh(): Promise<void>;
|
||||
}
|
||||
|
||||
const normalizeAccountForSet = (account: Account): Account => {
|
||||
const storedAccount = account?.id ? accountsStore.getState().accounts[account.id] : undefined;
|
||||
|
||||
if (!storedAccount) {
|
||||
return account;
|
||||
}
|
||||
|
||||
return {
|
||||
...storedAccount,
|
||||
...account,
|
||||
author: account.author ? { ...storedAccount.author, ...account.author } : storedAccount.author,
|
||||
subscriptions: account.subscriptions ?? storedAccount.subscriptions,
|
||||
blockedAddresses: account.blockedAddresses ?? storedAccount.blockedAddresses,
|
||||
blockedCids: account.blockedCids ?? storedAccount.blockedCids,
|
||||
communities: account.communities ?? storedAccount.communities,
|
||||
plebbitOptions: account.plebbitOptions ?? storedAccount.plebbitOptions,
|
||||
mediaIpfsGatewayUrl: account.mediaIpfsGatewayUrl ?? storedAccount.mediaIpfsGatewayUrl,
|
||||
};
|
||||
};
|
||||
|
||||
export const useSubplebbit = (options?: UseSubplebbitOptions): UseCommunityResult => {
|
||||
const { subplebbitAddress, ...rest } = options || {};
|
||||
const community = useCommunityBase({ communityAddress: subplebbitAddress, ...rest });
|
||||
return useMemo(() => withSubplebbitAddress(community as any) as UseCommunityResult, [community]);
|
||||
};
|
||||
|
||||
export const useSubplebbits = (options?: UseSubplebbitsOptions): UseCommunitiesResult & { subplebbits: UseCommunitiesResult['communities'] } => {
|
||||
const { subplebbitAddresses, ...rest } = options || {};
|
||||
const result = useCommunitiesBase({ communityAddresses: subplebbitAddresses, ...rest });
|
||||
|
||||
return useMemo(
|
||||
() => ({
|
||||
...result,
|
||||
communities: result.communities.map((community) => withSubplebbitAddress(community)),
|
||||
subplebbits: result.communities.map((community) => withSubplebbitAddress(community)),
|
||||
}),
|
||||
[result],
|
||||
);
|
||||
};
|
||||
|
||||
export const useSubplebbitStats = (options?: UseSubplebbitStatsOptions): UseCommunityStatsResult => {
|
||||
const { subplebbitAddress, ...rest } = options || {};
|
||||
return useCommunityStatsBase({ communityAddress: subplebbitAddress, ...rest });
|
||||
};
|
||||
|
||||
export const useAccountSubplebbits = (options?: UseAccountCommunitiesOptions): UseAccountSubplebbitsResult => {
|
||||
const result = useAccountCommunitiesBase(options);
|
||||
|
||||
return useMemo(
|
||||
() => ({
|
||||
...result,
|
||||
accountSubplebbits: result.accountCommunities,
|
||||
}),
|
||||
[result],
|
||||
);
|
||||
};
|
||||
|
||||
export const useFeed = (options: UseFeedOptions): UseFeedResult => {
|
||||
const { subplebbitAddresses, communityAddresses, ...rest } = options;
|
||||
const result = useFeedBase({
|
||||
communityAddresses: communityAddresses || subplebbitAddresses || [],
|
||||
...rest,
|
||||
});
|
||||
|
||||
return useMemo(
|
||||
() => ({
|
||||
...result,
|
||||
subplebbitAddressesWithNewerPosts: result.communityAddressesWithNewerPosts,
|
||||
}),
|
||||
[result],
|
||||
);
|
||||
};
|
||||
|
||||
export const useSubscribe = (options?: UseSubscribeOptions) => {
|
||||
const { subplebbitAddress, communityAddress, ...rest } = options || {};
|
||||
return useSubscribeBase({ communityAddress: communityAddress || subplebbitAddress, ...rest });
|
||||
};
|
||||
|
||||
export const useSubplebbitsStates = (options?: UseSubplebbitsStatesOptions): UseSubplebbitsStatesResult => {
|
||||
const { subplebbitAddresses, communityAddresses, ...rest } = options || {};
|
||||
const result = useCommunitiesStatesBase({
|
||||
communityAddresses: communityAddresses || subplebbitAddresses,
|
||||
...rest,
|
||||
});
|
||||
|
||||
return useMemo(
|
||||
() => ({
|
||||
...result,
|
||||
states: Object.fromEntries(
|
||||
Object.entries(result.states).map(([state, value]) => [
|
||||
state,
|
||||
{
|
||||
subplebbitAddresses: value.communityAddresses,
|
||||
clientUrls: value.clientUrls,
|
||||
},
|
||||
]),
|
||||
),
|
||||
}),
|
||||
[result],
|
||||
);
|
||||
};
|
||||
|
||||
export const useCreateSubplebbit = (options?: UseCreateSubplebbitOptions): UseCreateSubplebbitResult => {
|
||||
const result = useCreateCommunityBase(options);
|
||||
|
||||
return useMemo(
|
||||
() => ({
|
||||
...result,
|
||||
createdSubplebbit: withSubplebbitAddress(result.createdCommunity),
|
||||
createSubplebbit: result.createCommunity,
|
||||
}),
|
||||
[result],
|
||||
);
|
||||
};
|
||||
|
||||
export const usePublishSubplebbitEdit = (options?: UsePublishSubplebbitEditOptions): UsePublishSubplebbitEditResult => {
|
||||
const { subplebbitAddress, communityAddress, ...rest } = options || {};
|
||||
const result = usePublishCommunityEditBase({
|
||||
communityAddress: communityAddress || subplebbitAddress,
|
||||
...rest,
|
||||
});
|
||||
|
||||
return useMemo(
|
||||
() => ({
|
||||
...result,
|
||||
publishSubplebbitEdit: result.publishCommunityEdit,
|
||||
}),
|
||||
[result],
|
||||
);
|
||||
};
|
||||
|
||||
export const deleteSubplebbit = deleteCommunityBase;
|
||||
|
||||
export const setAccount = async (account: Account): Promise<void> => {
|
||||
await setAccountBase(normalizeAccountForSet(account));
|
||||
};
|
||||
|
||||
export const useAccountComment = (options?: UseAccountCommentOptions): UseAccountCommentResult => {
|
||||
if (options?.commentIndex === undefined && options?.commentCid === undefined) {
|
||||
return {
|
||||
accountId: '',
|
||||
index: -1,
|
||||
state: 'initializing',
|
||||
error: undefined,
|
||||
errors: [],
|
||||
refresh: async () => {},
|
||||
};
|
||||
}
|
||||
|
||||
const result = useAccountCommentBase(options);
|
||||
|
||||
return useMemo(
|
||||
() => ({
|
||||
...result,
|
||||
refresh: async () => {},
|
||||
}),
|
||||
[result],
|
||||
);
|
||||
};
|
||||
13
src/lib/utils/address-utils.ts
Normal file
13
src/lib/utils/address-utils.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Returns a short display-safe version of an address.
|
||||
* If the address contains a dot (e.g. "my-community.eth"), it is returned as-is.
|
||||
* Otherwise the middle bytes (characters 8-20) are returned as the shortened form.
|
||||
*/
|
||||
const getShortAddress = (address: string): string => {
|
||||
if (!address) return '';
|
||||
if (address.includes('.')) return address;
|
||||
if (address.length < 20) return '';
|
||||
return address.slice(8, 20);
|
||||
};
|
||||
|
||||
export default getShortAddress;
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Comment, useSubplebbit } from '@bitsocial/bitsocial-react-hooks';
|
||||
import { Comment, useCommunity } from '@bitsocial/bitsocial-react-hooks';
|
||||
import { getCommunityIdentifier } from '../../hooks/use-community-identifier';
|
||||
import React, { ReactNode, Fragment } from 'react';
|
||||
|
||||
/**
|
||||
@@ -265,10 +266,8 @@ export const commentMatchesPattern = (comment: Comment, pattern: string, subpleb
|
||||
* @returns True if the comment matches the pattern, false otherwise
|
||||
*/
|
||||
export const useCommentMatchesPattern = (comment: Comment, pattern: string): boolean => {
|
||||
const subplebbit = useSubplebbit({
|
||||
subplebbitAddress: comment?.subplebbitAddress,
|
||||
onlyIfCached: true,
|
||||
});
|
||||
const communityIdentifier = getCommunityIdentifier(comment?.subplebbitAddress);
|
||||
const subplebbit = useCommunity(communityIdentifier ? { community: communityIdentifier, onlyIfCached: true } : undefined);
|
||||
|
||||
return commentMatchesPattern(comment, pattern, subplebbit?.roles);
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Role, Subplebbit, Comment } from '@bitsocial/bitsocial-react-hooks';
|
||||
import { Role, Community, Comment } from '@bitsocial/bitsocial-react-hooks';
|
||||
|
||||
export type Roles = { [address: string]: Role };
|
||||
|
||||
@@ -26,7 +26,7 @@ export const findSubplebbitCreator = (roles: Roles | undefined): string => {
|
||||
return 'anonymous';
|
||||
};
|
||||
|
||||
export const findAuthorSubplebbits = (authorAddress: string | undefined, subplebbits: (Subplebbit | undefined)[]): string[] => {
|
||||
export const findAuthorSubplebbits = (authorAddress: string | undefined, subplebbits: (Community | undefined)[]): string[] => {
|
||||
let authorSubplebbits: string[] = [];
|
||||
|
||||
if (!authorAddress || !subplebbits) {
|
||||
|
||||
@@ -2,22 +2,22 @@ export type ParamsType = {
|
||||
accountCommentIndex?: string;
|
||||
authorAddress?: string;
|
||||
commentCid?: string;
|
||||
subplebbitAddress?: string;
|
||||
communityAddress?: string;
|
||||
timeFilterName?: string;
|
||||
};
|
||||
|
||||
export type ViewType = 'home' | 'pending' | 'post' | 'submit' | 'subplebbit' | 'subplebbit/submit';
|
||||
export type ViewType = 'home' | 'pending' | 'post' | 'submit' | 'community' | 'community/submit';
|
||||
|
||||
const sortTypes = ['/hot', '/new', '/active', '/topAll'];
|
||||
|
||||
export const getAboutLink = (pathname: string, params: ParamsType): string => {
|
||||
// some subs might use emojis in their address, so we need to decode the pathname
|
||||
// some communities might use emojis in their address, so we need to decode the pathname
|
||||
const decodedPathname = decodeURIComponent(pathname);
|
||||
|
||||
if (decodedPathname.startsWith(`/s/${params.subplebbitAddress}/c/${params.commentCid}`)) {
|
||||
return `/s/${params.subplebbitAddress}/c/${params.commentCid}/about`;
|
||||
} else if (decodedPathname.startsWith(`/s/${params.subplebbitAddress}`)) {
|
||||
return `/s/${params.subplebbitAddress}/about`;
|
||||
if (decodedPathname.startsWith(`/s/${params.communityAddress}/c/${params.commentCid}`)) {
|
||||
return `/s/${params.communityAddress}/c/${params.commentCid}/about`;
|
||||
} else if (decodedPathname.startsWith(`/s/${params.communityAddress}`)) {
|
||||
return `/s/${params.communityAddress}/about`;
|
||||
} else if (decodedPathname.startsWith('/profile')) {
|
||||
return '/profile/about';
|
||||
} else if (decodedPathname.startsWith('/u/')) {
|
||||
@@ -49,7 +49,7 @@ export const isAuthorSubmittedView = (pathname: string, params: ParamsType): boo
|
||||
return pathname === `/u/${params.authorAddress}/c/${params.commentCid}/submitted`;
|
||||
};
|
||||
|
||||
export const isCreateSubplebbitView = (pathname: string): boolean => {
|
||||
export const isCreateCommunityView = (pathname: string): boolean => {
|
||||
return pathname === '/communities/create';
|
||||
};
|
||||
|
||||
@@ -98,20 +98,20 @@ export const isPendingPostView = (pathname: string, params: ParamsType): boolean
|
||||
};
|
||||
|
||||
export const isPostPageView = (pathname: string, params: ParamsType): boolean => {
|
||||
// some subs might use emojis in their address, so we need to decode the pathname
|
||||
// some communities might use emojis in their address, so we need to decode the pathname
|
||||
const decodedPathname = decodeURIComponent(pathname);
|
||||
return params.subplebbitAddress && params.commentCid ? decodedPathname.startsWith(`/s/${params.subplebbitAddress}/c/${params.commentCid}`) : false;
|
||||
return params.communityAddress && params.commentCid ? decodedPathname.startsWith(`/s/${params.communityAddress}/c/${params.commentCid}`) : false;
|
||||
};
|
||||
|
||||
export const isPostPageAboutView = (pathname: string, params: ParamsType): boolean => {
|
||||
return params.subplebbitAddress && params.commentCid ? pathname.startsWith(`/s/${params.subplebbitAddress}/c/${params.commentCid}/about`) : false;
|
||||
return params.communityAddress && params.commentCid ? pathname.startsWith(`/s/${params.communityAddress}/c/${params.commentCid}/about`) : false;
|
||||
};
|
||||
|
||||
export const isPostContextView = (pathname: string, params: ParamsType, search: string): boolean => {
|
||||
if (!params.subplebbitAddress || !params.commentCid) return false;
|
||||
if (!params.communityAddress || !params.commentCid) return false;
|
||||
|
||||
const decodedPathname = decodeURIComponent(pathname);
|
||||
const expectedPathBase = `/s/${params.subplebbitAddress}/c/${params.commentCid}`;
|
||||
const expectedPathBase = `/s/${params.communityAddress}/c/${params.commentCid}`;
|
||||
|
||||
if (!decodedPathname.startsWith(expectedPathBase)) return false;
|
||||
|
||||
@@ -165,52 +165,52 @@ export const isSubmitView = (pathname: string): boolean => {
|
||||
return pathname.endsWith('/submit');
|
||||
};
|
||||
|
||||
export const isSubplebbitView = (pathname: string, params: ParamsType): boolean => {
|
||||
// some subs might use emojis in their address, so we need to decode the pathname
|
||||
export const isCommunityView = (pathname: string, params: ParamsType): boolean => {
|
||||
// some communities might use emojis in their address, so we need to decode the pathname
|
||||
const decodedPathname = decodeURIComponent(pathname);
|
||||
return params.subplebbitAddress ? decodedPathname.startsWith(`/s/${params.subplebbitAddress}`) : false;
|
||||
return params.communityAddress ? decodedPathname.startsWith(`/s/${params.communityAddress}`) : false;
|
||||
};
|
||||
|
||||
export const isSubplebbitAboutView = (pathname: string, params: ParamsType): boolean => {
|
||||
return params.subplebbitAddress ? pathname.startsWith(`/s/${params.subplebbitAddress}/about`) : false;
|
||||
export const isCommunityAboutView = (pathname: string, params: ParamsType): boolean => {
|
||||
return params.communityAddress ? pathname.startsWith(`/s/${params.communityAddress}/about`) : false;
|
||||
};
|
||||
|
||||
export const isSubplebbitSettingsView = (pathname: string, params: ParamsType): boolean => {
|
||||
return params.subplebbitAddress ? pathname === `/s/${params.subplebbitAddress}/settings` || pathname === `/s/${params.subplebbitAddress}/settings/editor` : false;
|
||||
export const isCommunitySettingsView = (pathname: string, params: ParamsType): boolean => {
|
||||
return params.communityAddress ? pathname === `/s/${params.communityAddress}/settings` || pathname === `/s/${params.communityAddress}/settings/editor` : false;
|
||||
};
|
||||
|
||||
export const isSubplebbitSubmitView = (pathname: string, params: ParamsType): boolean => {
|
||||
return params.subplebbitAddress ? pathname === `/s/${params.subplebbitAddress}/submit` : false;
|
||||
export const isCommunitySubmitView = (pathname: string, params: ParamsType): boolean => {
|
||||
return params.communityAddress ? pathname === `/s/${params.communityAddress}/submit` : false;
|
||||
};
|
||||
|
||||
export const isSubplebbitsView = (pathname: string): boolean => {
|
||||
export const isCommunitiesView = (pathname: string): boolean => {
|
||||
return pathname.startsWith('/communities');
|
||||
};
|
||||
|
||||
export const isSubplebbitsSubscriberView = (pathname: string): boolean => {
|
||||
export const isCommunitiesSubscriberView = (pathname: string): boolean => {
|
||||
return pathname === '/communities/subscriber';
|
||||
};
|
||||
|
||||
export const isSubplebbitsModeratorView = (pathname: string): boolean => {
|
||||
export const isCommunitiesModeratorView = (pathname: string): boolean => {
|
||||
return pathname === '/communities/moderator';
|
||||
};
|
||||
|
||||
export const isSubplebbitsAdminView = (pathname: string): boolean => {
|
||||
export const isCommunitiesAdminView = (pathname: string): boolean => {
|
||||
return pathname === '/communities/admin';
|
||||
};
|
||||
|
||||
export const isSubplebbitsOwnerView = (pathname: string): boolean => {
|
||||
export const isCommunitiesOwnerView = (pathname: string): boolean => {
|
||||
return pathname === '/communities/owner';
|
||||
};
|
||||
|
||||
export const isSubplebbitsVoteView = (pathname: string): boolean => {
|
||||
export const isCommunitiesVoteView = (pathname: string): boolean => {
|
||||
return pathname.startsWith('/communities/vote');
|
||||
};
|
||||
|
||||
export const isSubplebbitsVotePassingView = (pathname: string): boolean => {
|
||||
export const isCommunitiesVotePassingView = (pathname: string): boolean => {
|
||||
return pathname === '/communities/vote/passing';
|
||||
};
|
||||
|
||||
export const isSubplebbitsVoteRejectingView = (pathname: string): boolean => {
|
||||
export const isCommunitiesVoteRejectingView = (pathname: string): boolean => {
|
||||
return pathname === '/communities/vote/rejecting';
|
||||
};
|
||||
|
||||
42
src/stores/use-communities-loading-start-timestamps-store.ts
Normal file
42
src/stores/use-communities-loading-start-timestamps-store.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
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 default useCommunitiesLoadingStartTimestamps;
|
||||
51
src/stores/use-community-offline-store.ts
Normal file
51
src/stores/use-community-offline-store.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
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,
|
||||
},
|
||||
},
|
||||
}));
|
||||
}, 30000);
|
||||
},
|
||||
}));
|
||||
|
||||
export default useCommunityOfflineStore;
|
||||
@@ -1,8 +1,8 @@
|
||||
import { PublishSubplebbitEditOptions } from '@bitsocial/bitsocial-react-hooks';
|
||||
import { PublishCommunityEditOptions } from '@bitsocial/bitsocial-react-hooks';
|
||||
import { Roles } from '../lib/utils/user-utils';
|
||||
import { create } from 'zustand';
|
||||
|
||||
export type SubplebbitSettingsState = {
|
||||
export type CommunitySettingsState = {
|
||||
challenges: any[] | undefined;
|
||||
title: string | undefined;
|
||||
description: string | undefined;
|
||||
@@ -11,13 +11,13 @@ export type SubplebbitSettingsState = {
|
||||
rules: string[] | undefined;
|
||||
roles: Roles | undefined;
|
||||
settings: any | undefined;
|
||||
subplebbitAddress: string | undefined;
|
||||
publishSubplebbitEditOptions: PublishSubplebbitEditOptions;
|
||||
setSubplebbitSettingsStore: (data: Partial<SubplebbitSettingsState>) => void;
|
||||
resetSubplebbitSettingsStore: () => void;
|
||||
communityAddress: string | undefined;
|
||||
publishCommunityEditOptions: PublishCommunityEditOptions;
|
||||
setCommunitySettingsStore: (data: Partial<CommunitySettingsState>) => void;
|
||||
resetCommunitySettingsStore: () => void;
|
||||
};
|
||||
|
||||
const useSubplebbitSettingsStore = create<SubplebbitSettingsState>((set) => ({
|
||||
const useCommunitySettingsStore = create<CommunitySettingsState>((set) => ({
|
||||
challenges: undefined,
|
||||
title: undefined,
|
||||
description: undefined,
|
||||
@@ -26,9 +26,9 @@ const useSubplebbitSettingsStore = create<SubplebbitSettingsState>((set) => ({
|
||||
rules: undefined,
|
||||
roles: undefined,
|
||||
settings: undefined,
|
||||
subplebbitAddress: undefined,
|
||||
publishSubplebbitEditOptions: {},
|
||||
setSubplebbitSettingsStore: (props) =>
|
||||
communityAddress: undefined,
|
||||
publishCommunityEditOptions: {},
|
||||
setCommunitySettingsStore: (props) =>
|
||||
set((state) => {
|
||||
const nextState = { ...state };
|
||||
Object.entries(props).forEach(([key, value]) => {
|
||||
@@ -36,7 +36,7 @@ const useSubplebbitSettingsStore = create<SubplebbitSettingsState>((set) => ({
|
||||
(nextState as any)[key] = value;
|
||||
}
|
||||
});
|
||||
const editOptions: Partial<SubplebbitSettingsState> = {};
|
||||
const editOptions: Partial<CommunitySettingsState> = {};
|
||||
if (nextState.title !== undefined) editOptions.title = nextState.title?.trim() === '' ? undefined : nextState.title;
|
||||
if (nextState.description !== undefined) editOptions.description = nextState.description?.trim() === '' ? undefined : nextState.description;
|
||||
if (nextState.address !== undefined) editOptions.address = nextState.address?.trim() === '' ? undefined : nextState.address;
|
||||
@@ -44,11 +44,11 @@ const useSubplebbitSettingsStore = create<SubplebbitSettingsState>((set) => ({
|
||||
if (nextState.rules !== undefined) editOptions.rules = nextState.rules;
|
||||
if (nextState.roles !== undefined) editOptions.roles = nextState.roles;
|
||||
if (nextState.settings !== undefined) editOptions.settings = nextState.settings;
|
||||
if (nextState.subplebbitAddress !== undefined) editOptions.subplebbitAddress = nextState.subplebbitAddress?.trim() === '' ? undefined : nextState.subplebbitAddress;
|
||||
nextState.publishSubplebbitEditOptions = editOptions;
|
||||
if (nextState.communityAddress !== undefined) editOptions.communityAddress = nextState.communityAddress?.trim() === '' ? undefined : nextState.communityAddress;
|
||||
nextState.publishCommunityEditOptions = editOptions;
|
||||
return nextState;
|
||||
}),
|
||||
resetSubplebbitSettingsStore: () =>
|
||||
resetCommunitySettingsStore: () =>
|
||||
set(() => {
|
||||
return {
|
||||
challenges: undefined,
|
||||
@@ -59,10 +59,10 @@ const useSubplebbitSettingsStore = create<SubplebbitSettingsState>((set) => ({
|
||||
rules: undefined,
|
||||
roles: undefined,
|
||||
settings: undefined,
|
||||
subplebbitAddress: undefined,
|
||||
publishSubplebbitEditOptions: {},
|
||||
communityAddress: undefined,
|
||||
publishCommunityEditOptions: {},
|
||||
};
|
||||
}),
|
||||
}));
|
||||
|
||||
export default useSubplebbitSettingsStore;
|
||||
export default useCommunitySettingsStore;
|
||||
@@ -1,51 +0,0 @@
|
||||
import { create } from 'zustand';
|
||||
|
||||
interface SubplebbitOfflineState {
|
||||
state?: string;
|
||||
updatedAt?: number;
|
||||
updatingState?: string;
|
||||
initialLoad: boolean;
|
||||
}
|
||||
|
||||
interface SubplebbitOfflineStore {
|
||||
subplebbitOfflineState: Record<string, SubplebbitOfflineState>;
|
||||
setSubplebbitOfflineState: (address: string, state: Partial<SubplebbitOfflineState>) => 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);
|
||||
},
|
||||
}));
|
||||
|
||||
export default useSubplebbitOfflineStore;
|
||||
@@ -1,42 +0,0 @@
|
||||
import { useEffect, useMemo } from 'react';
|
||||
import { create } from 'zustand';
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
export default useSubplebbitsLoadingStartTimestamps;
|
||||
@@ -3,7 +3,7 @@ import { HashLink } from 'react-router-hash-link';
|
||||
import useIsMobile from '../../hooks/use-is-mobile';
|
||||
import Sidebar, { Footer } from '../../components/sidebar';
|
||||
import styles from './about.module.css';
|
||||
import { useAccount, useComment, useSubplebbit } from '@bitsocial/bitsocial-react-hooks';
|
||||
import { useAccount, useComment, useCommunity } from '@bitsocial/bitsocial-react-hooks';
|
||||
import { Capacitor } from '@capacitor/core';
|
||||
import { isHomeAboutView } from '../../lib/utils/view-utils';
|
||||
import { useEffect } from 'react';
|
||||
@@ -156,9 +156,9 @@ const About = () => {
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
const isInHomeAboutView = isHomeAboutView(location.pathname);
|
||||
const { commentCid, subplebbitAddress } = useParams();
|
||||
const { commentCid, communityAddress: subplebbitAddress } = useParams();
|
||||
|
||||
const subplebbit = useSubplebbit({ subplebbitAddress });
|
||||
const subplebbit = useCommunity(subplebbitAddress ? { community: { name: subplebbitAddress } } : undefined);
|
||||
const comment = useComment({ commentCid: commentCid as string, onlyIfCached: true });
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -8,6 +8,7 @@ import useFeedFiltersStore from '../../stores/use-feed-filters-store';
|
||||
import { useDefaultSubplebbitAddresses } from '../../hooks/use-default-subplebbits';
|
||||
import useTimeFilter, { isValidTimeFilterName } from '../../hooks/use-time-filter';
|
||||
import FeedFooter from '../../components/feed-footer';
|
||||
import { getCommunityIdentifiers } from '../../hooks/use-community-identifier';
|
||||
import LoadingEllipsis from '../../components/loading-ellipsis';
|
||||
import Post from '../../components/post';
|
||||
import Sidebar from '../../components/sidebar';
|
||||
@@ -54,7 +55,7 @@ const All = () => {
|
||||
const options: any = {
|
||||
newerThan: searchQuery ? 0 : timeFilterSeconds,
|
||||
sortType,
|
||||
subplebbitAddresses,
|
||||
communities: getCommunityIdentifiers(subplebbitAddresses),
|
||||
};
|
||||
|
||||
if (searchQuery) {
|
||||
@@ -70,7 +71,7 @@ const All = () => {
|
||||
return options;
|
||||
}, [subplebbitAddresses, sortType, timeFilterSeconds, searchQuery]);
|
||||
|
||||
const { feed, hasMore, loadMore, reset, subplebbitAddressesWithNewerPosts } = useFeed(feedOptions);
|
||||
const { feed, hasMore, loadMore, reset, communityKeysWithNewerPosts: subplebbitAddressesWithNewerPosts } = useFeed(feedOptions);
|
||||
|
||||
// Reset no results state when search query changes
|
||||
useEffect(() => {
|
||||
@@ -105,7 +106,7 @@ const All = () => {
|
||||
hasMore: hasMoreWeekly,
|
||||
loadMore: loadMoreWeekly,
|
||||
} = useFeed({
|
||||
subplebbitAddresses,
|
||||
communities: getCommunityIdentifiers(subplebbitAddresses),
|
||||
sortType,
|
||||
newerThan: 60 * 60 * 24 * 7,
|
||||
});
|
||||
@@ -114,7 +115,7 @@ const All = () => {
|
||||
hasMore: hasMoreMonthly,
|
||||
loadMore: loadMoreMonthly,
|
||||
} = useFeed({
|
||||
subplebbitAddresses,
|
||||
communities: getCommunityIdentifiers(subplebbitAddresses),
|
||||
sortType,
|
||||
newerThan: 60 * 60 * 24 * 30,
|
||||
});
|
||||
@@ -123,7 +124,7 @@ const All = () => {
|
||||
hasMore: hasMoreYearly,
|
||||
loadMore: loadMoreYearly,
|
||||
} = useFeed({
|
||||
subplebbitAddresses,
|
||||
communities: getCommunityIdentifiers(subplebbitAddresses),
|
||||
sortType,
|
||||
newerThan: 60 * 60 * 24 * 365,
|
||||
});
|
||||
|
||||
@@ -1,24 +1,25 @@
|
||||
import { Fragment, useEffect, useMemo, useState, useCallback } from 'react';
|
||||
import { Link, useLocation } from 'react-router-dom';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
import { Subplebbit as SubplebbitType, useAccount, useAccountSubplebbits, useSubplebbits, useSubplebbitStats } from '@bitsocial/bitsocial-react-hooks';
|
||||
import styles from './subplebbits.module.css';
|
||||
import { Community as CommunityType, useAccount, useAccountCommunities, useCommunities, useCommunityStats } from '@bitsocial/bitsocial-react-hooks';
|
||||
import styles from './communities.module.css';
|
||||
import { getFormattedTimeDuration } from '../../lib/utils/time-utils';
|
||||
import {
|
||||
isSubplebbitsView,
|
||||
isSubplebbitsSubscriberView,
|
||||
isSubplebbitsModeratorView,
|
||||
isSubplebbitsAdminView,
|
||||
isSubplebbitsOwnerView,
|
||||
isSubplebbitsVoteView,
|
||||
isSubplebbitsVotePassingView,
|
||||
isSubplebbitsVoteRejectingView,
|
||||
isCommunitiesView,
|
||||
isCommunitiesSubscriberView,
|
||||
isCommunitiesModeratorView,
|
||||
isCommunitiesAdminView,
|
||||
isCommunitiesOwnerView,
|
||||
isCommunitiesVoteView,
|
||||
isCommunitiesVotePassingView,
|
||||
isCommunitiesVoteRejectingView,
|
||||
} 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 useDisplayedSubscriptions from '../../hooks/use-displayed-subscriptions';
|
||||
import useIsMobile from '../../hooks/use-is-mobile';
|
||||
import useIsSubplebbitOffline from '../../hooks/use-is-subplebbit-offline';
|
||||
import useIsCommunityOffline from '../../hooks/use-is-community-offline';
|
||||
import ErrorDisplay from '../../components/error-display';
|
||||
import Markdown from '../../components/markdown';
|
||||
import Label from '../../components/post/label';
|
||||
@@ -29,7 +30,7 @@ import _ from 'lodash';
|
||||
|
||||
interface SubplebbitProps {
|
||||
index?: number;
|
||||
subplebbit: SubplebbitType;
|
||||
subplebbit: CommunityType;
|
||||
tags?: string[];
|
||||
isUnsubscribed?: boolean;
|
||||
onUnsubscribe?: (address: string) => void;
|
||||
@@ -43,32 +44,32 @@ const NoCommunitiesMessage = () => {
|
||||
const MyCommunitiesTabs = () => {
|
||||
const { t } = useTranslation();
|
||||
const location = useLocation();
|
||||
const isInSubplebbitsSubscriberView = isSubplebbitsSubscriberView(location.pathname);
|
||||
const isInSubplebbitsModeratorView = isSubplebbitsModeratorView(location.pathname);
|
||||
const isInSubplebbitsAdminView = isSubplebbitsAdminView(location.pathname);
|
||||
const isInSubplebbitsOwnerView = isSubplebbitsOwnerView(location.pathname);
|
||||
const isInSubplebbitsView =
|
||||
isSubplebbitsView(location.pathname) && !isInSubplebbitsSubscriberView && !isInSubplebbitsModeratorView && !isInSubplebbitsAdminView && !isInSubplebbitsOwnerView;
|
||||
const isInCommunitiesSubscriberView = isCommunitiesSubscriberView(location.pathname);
|
||||
const isInCommunitiesModeratorView = isCommunitiesModeratorView(location.pathname);
|
||||
const isInCommunitiesAdminView = isCommunitiesAdminView(location.pathname);
|
||||
const isInCommunitiesOwnerView = isCommunitiesOwnerView(location.pathname);
|
||||
const isInCommunitiesView =
|
||||
isCommunitiesView(location.pathname) && !isInCommunitiesSubscriberView && !isInCommunitiesModeratorView && !isInCommunitiesAdminView && !isInCommunitiesOwnerView;
|
||||
|
||||
return (
|
||||
<div className={styles.subplebbitsTabs}>
|
||||
<Link to='/communities' className={isInSubplebbitsView ? styles.selected : styles.choice}>
|
||||
<Link to='/communities' className={isInCommunitiesView ? styles.selected : styles.choice}>
|
||||
{t('all')}
|
||||
</Link>
|
||||
<span className={styles.separator}>|</span>
|
||||
<Link to='/communities/subscriber' className={isInSubplebbitsSubscriberView ? styles.selected : styles.choice}>
|
||||
<Link to='/communities/subscriber' className={isInCommunitiesSubscriberView ? styles.selected : styles.choice}>
|
||||
{t('subscriber')}
|
||||
</Link>
|
||||
<span className={styles.separator}>|</span>
|
||||
<Link to='/communities/moderator' className={isInSubplebbitsModeratorView ? styles.selected : styles.choice}>
|
||||
<Link to='/communities/moderator' className={isInCommunitiesModeratorView ? styles.selected : styles.choice}>
|
||||
{t('moderator')}
|
||||
</Link>
|
||||
<span className={styles.separator}>|</span>
|
||||
<Link to='/communities/admin' className={isInSubplebbitsAdminView ? styles.selected : styles.choice}>
|
||||
<Link to='/communities/admin' className={isInCommunitiesAdminView ? styles.selected : styles.choice}>
|
||||
{t('admin')}
|
||||
</Link>
|
||||
<span className={styles.separator}>|</span>
|
||||
<Link to='/communities/owner' className={isInSubplebbitsOwnerView ? styles.selected : styles.choice}>
|
||||
<Link to='/communities/owner' className={isInCommunitiesOwnerView ? styles.selected : styles.choice}>
|
||||
{t('owner')}
|
||||
</Link>
|
||||
</div>
|
||||
@@ -78,19 +79,19 @@ const MyCommunitiesTabs = () => {
|
||||
const VoteTabs = () => {
|
||||
const { t } = useTranslation();
|
||||
const location = useLocation();
|
||||
const isInSubplebbitsVoteView = isSubplebbitsVoteView(location.pathname);
|
||||
const isInSubplebbitsVotePassingView = isSubplebbitsVotePassingView(location.pathname);
|
||||
const isInSubplebbitsVoteRejectingView = isSubplebbitsVoteRejectingView(location.pathname);
|
||||
const isInCommunitiesVoteView = isCommunitiesVoteView(location.pathname);
|
||||
const isInCommunitiesVotePassingView = isCommunitiesVotePassingView(location.pathname);
|
||||
const isInCommunitiesVoteRejectingView = isCommunitiesVoteRejectingView(location.pathname);
|
||||
|
||||
return (
|
||||
<div className={styles.subplebbitsTabs}>
|
||||
<Link to='/communities/vote' className={isInSubplebbitsVoteView ? styles.selected : styles.choice}>
|
||||
<Link to='/communities/vote' className={isInCommunitiesVoteView ? styles.selected : styles.choice}>
|
||||
{t('all')}
|
||||
</Link>
|
||||
<span className={styles.separator}>|</span>
|
||||
<Link
|
||||
to='/communities/vote/passing'
|
||||
className={isInSubplebbitsVotePassingView ? styles.selected : styles.choice}
|
||||
className={isInCommunitiesVotePassingView ? styles.selected : styles.choice}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
alert('This feature is not available yet.');
|
||||
@@ -102,7 +103,7 @@ const VoteTabs = () => {
|
||||
<span className={styles.separator}>|</span>
|
||||
<Link
|
||||
to='/communities/vote/rejecting'
|
||||
className={isInSubplebbitsVoteRejectingView ? styles.selected : styles.choice}
|
||||
className={isInCommunitiesVoteRejectingView ? styles.selected : styles.choice}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
alert('This feature is not available yet.');
|
||||
@@ -117,21 +118,21 @@ const VoteTabs = () => {
|
||||
|
||||
const Infobar = () => {
|
||||
const account = useAccount();
|
||||
const { accountSubplebbits, error: accountSubplebbitsError } = useAccountSubplebbits();
|
||||
const { accountCommunities: accountSubplebbits, error: accountCommunitiesError } = useAccountCommunities();
|
||||
const { setError } = useErrorStore();
|
||||
|
||||
useEffect(() => {
|
||||
setError('Infobar_useAccountSubplebbits', accountSubplebbitsError);
|
||||
}, [accountSubplebbitsError, setError]);
|
||||
setError('Infobar_useAccountSubplebbits', accountCommunitiesError);
|
||||
}, [accountCommunitiesError, setError]);
|
||||
|
||||
const subscriptions = account?.subscriptions || [];
|
||||
const { t } = useTranslation();
|
||||
const location = useLocation();
|
||||
|
||||
const isInSubplebbitsSubscriberView = isSubplebbitsSubscriberView(location.pathname);
|
||||
const isInSubplebbitsModeratorView = isSubplebbitsModeratorView(location.pathname);
|
||||
const isInSubplebbitsAdminView = isSubplebbitsAdminView(location.pathname);
|
||||
const isInSubplebbitsOwnerView = isSubplebbitsOwnerView(location.pathname);
|
||||
const isInCommunitiesSubscriberView = isCommunitiesSubscriberView(location.pathname);
|
||||
const isInCommunitiesModeratorView = isCommunitiesModeratorView(location.pathname);
|
||||
const isInCommunitiesAdminView = isCommunitiesAdminView(location.pathname);
|
||||
const isInCommunitiesOwnerView = isCommunitiesOwnerView(location.pathname);
|
||||
|
||||
// Check if we're filtering by any tag
|
||||
const urlParams = new URLSearchParams(location.search);
|
||||
@@ -141,9 +142,9 @@ const Infobar = () => {
|
||||
const basePath = location.pathname;
|
||||
|
||||
let mainInfobarText;
|
||||
if (isInSubplebbitsSubscriberView) {
|
||||
if (isInCommunitiesSubscriberView) {
|
||||
mainInfobarText = subscriptions.length === 0 ? t('not_subscribed') : t('below_subscribed');
|
||||
} else if (isInSubplebbitsModeratorView || isInSubplebbitsAdminView || isInSubplebbitsOwnerView) {
|
||||
} else if (isInCommunitiesModeratorView || isInCommunitiesAdminView || isInCommunitiesOwnerView) {
|
||||
mainInfobarText = Object.keys(accountSubplebbits).length > 0 ? t('below_moderator_access') : t('not_moderator');
|
||||
} else if (subscriptions.length === 0 && Object.keys(accountSubplebbits).length === 0) {
|
||||
mainInfobarText = t('not_subscriber_nor_moderator');
|
||||
@@ -170,7 +171,7 @@ const Infobar = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const Subplebbit = ({ subplebbit, tags, index, isUnsubscribed, onUnsubscribe }: SubplebbitProps) => {
|
||||
const CommunityItem = ({ subplebbit, tags, index, isUnsubscribed, onUnsubscribe }: SubplebbitProps) => {
|
||||
const { t } = useTranslation();
|
||||
const { address, createdAt, description, roles, shortAddress, settings, suggested, title } = subplebbit || {};
|
||||
const [avatarLoadFailed, setAvatarLoadFailed] = useState(false);
|
||||
@@ -198,8 +199,8 @@ const Subplebbit = ({ subplebbit, tags, index, isUnsubscribed, onUnsubscribe }:
|
||||
const downvoteCount = 0;
|
||||
|
||||
const postScore = upvoteCount === 0 && downvoteCount === 0 ? '•' : upvoteCount - downvoteCount || '•';
|
||||
const { allActiveUserCount } = useSubplebbitStats({ subplebbitAddress: address });
|
||||
const { isOffline, isOnlineStatusLoading, offlineTitle } = useIsSubplebbitOffline(subplebbit);
|
||||
const { allActiveUserCount } = useCommunityStats(address ? { community: getCommunityIdentifier(address) } : undefined);
|
||||
const { isOffline, isOnlineStatusLoading, offlineTitle } = useIsCommunityOffline(subplebbit);
|
||||
|
||||
const isNsfw = tags?.some((tag) => nsfwTags.includes(tag));
|
||||
|
||||
@@ -310,14 +311,14 @@ const Subplebbit = ({ subplebbit, tags, index, isUnsubscribed, onUnsubscribe }:
|
||||
|
||||
const AccountSubplebbits = ({ viewRole }: { viewRole: string }) => {
|
||||
const account = useAccount();
|
||||
const { accountSubplebbits, error: accountSubplebbitsError } = useAccountSubplebbits();
|
||||
const { accountCommunities: accountSubplebbits, error: accountCommunitiesError } = useAccountCommunities();
|
||||
const { setError } = useErrorStore();
|
||||
const location = useLocation();
|
||||
const defaultSubplebbits = useDefaultSubplebbits();
|
||||
|
||||
useEffect(() => {
|
||||
setError('AccountSubplebbits_useAccountSubplebbits', accountSubplebbitsError);
|
||||
}, [accountSubplebbitsError, setError, viewRole]);
|
||||
setError('AccountSubplebbits_useAccountSubplebbits', accountCommunitiesError);
|
||||
}, [accountCommunitiesError, setError, viewRole]);
|
||||
|
||||
const urlParams = new URLSearchParams(location.search);
|
||||
const currentTag = urlParams.get('tag');
|
||||
@@ -342,7 +343,7 @@ const AccountSubplebbits = ({ viewRole }: { viewRole: string }) => {
|
||||
})
|
||||
.map((subplebbitData, index) => {
|
||||
const tags = defaultSubplebbits.find((defaultSub) => defaultSub.address === (subplebbitData as any).address)?.tags;
|
||||
return <Subplebbit key={index} subplebbit={subplebbitData} tags={tags} index={index} />;
|
||||
return <CommunityItem key={index} subplebbit={subplebbitData} tags={tags} index={index} />;
|
||||
});
|
||||
|
||||
if (subplebbitElements.length === 0) {
|
||||
@@ -373,14 +374,14 @@ const SubscriberSubplebbits = () => {
|
||||
[account?.author?.address], // Reset dependencies
|
||||
);
|
||||
|
||||
const { subplebbits, error: subplebbitsError } = useSubplebbits({ subplebbitAddresses: displayedSubscriptions });
|
||||
const { communities: subplebbits, error: subplebbitsError } = useCommunities({ communities: getCommunityIdentifiers(displayedSubscriptions) });
|
||||
|
||||
useEffect(() => {
|
||||
setError('SubscriberSubplebbits_useSubplebbits', subplebbitsError);
|
||||
}, [subplebbitsError, setError]);
|
||||
|
||||
const subplebbitElements = Object.values(subplebbits ?? {})
|
||||
.filter((subplebbit): subplebbit is SubplebbitType => Boolean(subplebbit))
|
||||
.filter((subplebbit): subplebbit is CommunityType => Boolean(subplebbit))
|
||||
.filter((subplebbitData) => {
|
||||
if (currentTag) {
|
||||
const tags = defaultSubplebbits.find((defaultSub) => defaultSub.address === (subplebbitData as any).address)?.tags;
|
||||
@@ -396,7 +397,7 @@ const SubscriberSubplebbits = () => {
|
||||
.map((subplebbitData, index) => {
|
||||
const tags = defaultSubplebbits.find((defaultSub) => defaultSub.address === (subplebbitData as any).address)?.tags;
|
||||
return subplebbitData ? (
|
||||
<Subplebbit
|
||||
<CommunityItem
|
||||
key={subplebbitData.address || index}
|
||||
subplebbit={subplebbitData}
|
||||
tags={tags}
|
||||
@@ -422,7 +423,7 @@ const AllDefaultSubplebbits = () => {
|
||||
const urlParams = new URLSearchParams(location.search);
|
||||
const currentTag = urlParams.get('tag');
|
||||
|
||||
const { subplebbits, error: subplebbitsError } = useSubplebbits({ subplebbitAddresses });
|
||||
const { communities: subplebbits, error: subplebbitsError } = useCommunities({ communities: getCommunityIdentifiers(subplebbitAddresses) });
|
||||
const { setError } = useErrorStore();
|
||||
|
||||
useEffect(() => {
|
||||
@@ -430,7 +431,7 @@ const AllDefaultSubplebbits = () => {
|
||||
}, [subplebbitsError, setError]);
|
||||
|
||||
const subplebbitElements = Object.values(subplebbits ?? {})
|
||||
.filter((subplebbit): subplebbit is SubplebbitType => Boolean(subplebbit)) // Type guard
|
||||
.filter((subplebbit): subplebbit is CommunityType => Boolean(subplebbit)) // Type guard
|
||||
.filter((subplebbitData) => {
|
||||
if (currentTag) {
|
||||
const tags = defaultSubplebbitsList.find((defaultSub) => defaultSub.address === (subplebbitData as any).address)?.tags;
|
||||
@@ -445,7 +446,7 @@ const AllDefaultSubplebbits = () => {
|
||||
})
|
||||
.map((subplebbitData, index) => {
|
||||
const tags = defaultSubplebbitsList.find((defaultSub) => defaultSub.address === (subplebbitData as any).address)?.tags;
|
||||
return <Subplebbit key={subplebbitData.address || index} subplebbit={subplebbitData} tags={tags} index={index} />;
|
||||
return <CommunityItem key={subplebbitData.address || index} subplebbit={subplebbitData} tags={tags} index={index} />;
|
||||
});
|
||||
|
||||
if (subplebbitElements.length === 0) {
|
||||
@@ -456,14 +457,14 @@ const AllDefaultSubplebbits = () => {
|
||||
|
||||
const AllAccountSubplebbits = () => {
|
||||
const account = useAccount();
|
||||
const { accountSubplebbits, error: accountSubplebbitsError } = useAccountSubplebbits();
|
||||
const { accountCommunities: accountSubplebbits, error: accountCommunitiesError } = useAccountCommunities();
|
||||
const { setError } = useErrorStore();
|
||||
const location = useLocation();
|
||||
const defaultSubplebbits = useDefaultSubplebbits();
|
||||
|
||||
useEffect(() => {
|
||||
setError('AllAccountSubplebbits_useAccountSubplebbits', accountSubplebbitsError);
|
||||
}, [accountSubplebbitsError, setError]);
|
||||
setError('AllAccountSubplebbits_useAccountSubplebbits', accountCommunitiesError);
|
||||
}, [accountCommunitiesError, setError]);
|
||||
|
||||
const urlParams = new URLSearchParams(location.search);
|
||||
const currentTag = urlParams.get('tag');
|
||||
@@ -476,14 +477,14 @@ const AllAccountSubplebbits = () => {
|
||||
|
||||
const { list: displayedAddresses, isUnsubscribed, handleUnsubscribe } = useDisplayedSubscriptions(getAllAccountRelatedAddresses, [account?.author?.address]);
|
||||
|
||||
const { subplebbits, error: subplebbitsError } = useSubplebbits({ subplebbitAddresses: displayedAddresses });
|
||||
const { communities: subplebbits, error: subplebbitsError } = useCommunities({ communities: getCommunityIdentifiers(displayedAddresses) });
|
||||
|
||||
useEffect(() => {
|
||||
setError('AllAccountSubplebbits_useSubplebbits', subplebbitsError);
|
||||
}, [subplebbitsError, setError]);
|
||||
|
||||
const subplebbitElements = Object.values(subplebbits ?? {})
|
||||
.filter((subplebbit): subplebbit is SubplebbitType => Boolean(subplebbit))
|
||||
.filter((subplebbit): subplebbit is CommunityType => Boolean(subplebbit))
|
||||
.filter((subplebbitData) => {
|
||||
if (currentTag) {
|
||||
const tags = defaultSubplebbits.find((defaultSub) => defaultSub.address === (subplebbitData as any).address)?.tags;
|
||||
@@ -499,7 +500,7 @@ const AllAccountSubplebbits = () => {
|
||||
.map((subplebbitData, index) => {
|
||||
const tags = defaultSubplebbits.find((defaultSub) => defaultSub.address === (subplebbitData as any).address)?.tags;
|
||||
return subplebbitData ? (
|
||||
<Subplebbit
|
||||
<CommunityItem
|
||||
key={subplebbitData.address || index}
|
||||
subplebbit={subplebbitData}
|
||||
tags={tags}
|
||||
@@ -517,7 +518,7 @@ const AllAccountSubplebbits = () => {
|
||||
return <>{subplebbitElements}</>;
|
||||
};
|
||||
|
||||
const Subplebbits = () => {
|
||||
const Communities = () => {
|
||||
const { t } = useTranslation();
|
||||
const location = useLocation();
|
||||
const { errors, clearAllErrors } = useErrorStore();
|
||||
@@ -536,45 +537,45 @@ const Subplebbits = () => {
|
||||
});
|
||||
}, [errors]);
|
||||
|
||||
const isInSubplebbitsSubscriberView = isSubplebbitsSubscriberView(location.pathname);
|
||||
const isInSubplebbitsModeratorView = isSubplebbitsModeratorView(location.pathname);
|
||||
const isInSubplebbitsAdminView = isSubplebbitsAdminView(location.pathname);
|
||||
const isInSubplebbitsOwnerView = isSubplebbitsOwnerView(location.pathname);
|
||||
const isInSubplebbitsVoteView = isSubplebbitsVoteView(location.pathname);
|
||||
const isInSubplebbitsView =
|
||||
isSubplebbitsView(location.pathname) &&
|
||||
!isInSubplebbitsSubscriberView &&
|
||||
!isInSubplebbitsModeratorView &&
|
||||
!isInSubplebbitsAdminView &&
|
||||
!isInSubplebbitsOwnerView &&
|
||||
!isInSubplebbitsVoteView;
|
||||
const isInCommunitiesSubscriberView = isCommunitiesSubscriberView(location.pathname);
|
||||
const isInCommunitiesModeratorView = isCommunitiesModeratorView(location.pathname);
|
||||
const isInCommunitiesAdminView = isCommunitiesAdminView(location.pathname);
|
||||
const isInCommunitiesOwnerView = isCommunitiesOwnerView(location.pathname);
|
||||
const isInCommunitiesVoteView = isCommunitiesVoteView(location.pathname);
|
||||
const isInCommunitiesView =
|
||||
isCommunitiesView(location.pathname) &&
|
||||
!isInCommunitiesSubscriberView &&
|
||||
!isInCommunitiesModeratorView &&
|
||||
!isInCommunitiesAdminView &&
|
||||
!isInCommunitiesOwnerView &&
|
||||
!isInCommunitiesVoteView;
|
||||
|
||||
let viewRole = 'subscriber';
|
||||
if (isInSubplebbitsModeratorView) {
|
||||
if (isInCommunitiesModeratorView) {
|
||||
viewRole = 'moderator';
|
||||
} else if (isInSubplebbitsAdminView) {
|
||||
} else if (isInCommunitiesAdminView) {
|
||||
viewRole = 'admin';
|
||||
} else if (isInSubplebbitsOwnerView) {
|
||||
} else if (isInCommunitiesOwnerView) {
|
||||
viewRole = 'owner';
|
||||
}
|
||||
|
||||
const documentTitle = useMemo(() => {
|
||||
let title = t('communities').charAt(0).toUpperCase() + t('communities').slice(1);
|
||||
if (isInSubplebbitsVoteView) {
|
||||
if (isInCommunitiesVoteView) {
|
||||
title += ` - ${_.startCase(t('vote'))}`;
|
||||
} else if (isInSubplebbitsSubscriberView) {
|
||||
} else if (isInCommunitiesSubscriberView) {
|
||||
title += ` - ${_.startCase(t('subscriber'))}`;
|
||||
} else if (isInSubplebbitsModeratorView) {
|
||||
} else if (isInCommunitiesModeratorView) {
|
||||
title += ` - ${_.startCase(t('moderator'))}`;
|
||||
} else if (isInSubplebbitsAdminView) {
|
||||
} else if (isInCommunitiesAdminView) {
|
||||
title += ` - ${_.startCase(t('admin'))}`;
|
||||
} else if (isInSubplebbitsOwnerView) {
|
||||
} else if (isInCommunitiesOwnerView) {
|
||||
title += ` - ${_.startCase(t('owner'))}`;
|
||||
} else if (isInSubplebbitsView) {
|
||||
} else if (isInCommunitiesView) {
|
||||
title += ` - ${_.startCase(t('all'))}`;
|
||||
}
|
||||
return `${title} - Seedit`;
|
||||
}, [isInSubplebbitsSubscriberView, isInSubplebbitsModeratorView, isInSubplebbitsAdminView, isInSubplebbitsOwnerView, isInSubplebbitsView, isInSubplebbitsVoteView, t]);
|
||||
}, [isInCommunitiesSubscriberView, isInCommunitiesModeratorView, isInCommunitiesAdminView, isInCommunitiesOwnerView, isInCommunitiesView, isInCommunitiesVoteView, t]);
|
||||
|
||||
useEffect(() => {
|
||||
document.title = documentTitle;
|
||||
@@ -587,18 +588,18 @@ const Subplebbits = () => {
|
||||
|
||||
if (
|
||||
source === 'Infobar_useAccountSubplebbits' &&
|
||||
(isInSubplebbitsView || isInSubplebbitsSubscriberView || isInSubplebbitsModeratorView || isInSubplebbitsAdminView || isInSubplebbitsOwnerView)
|
||||
(isInCommunitiesView || isInCommunitiesSubscriberView || isInCommunitiesModeratorView || isInCommunitiesAdminView || isInCommunitiesOwnerView)
|
||||
) {
|
||||
errorsToDisplay.push(<ErrorDisplay key={source} error={errorObj} />);
|
||||
} else if (source === 'AccountSubplebbits_useAccountSubplebbits' && (isInSubplebbitsModeratorView || isInSubplebbitsAdminView || isInSubplebbitsOwnerView)) {
|
||||
} else if (source === 'AccountSubplebbits_useAccountSubplebbits' && (isInCommunitiesModeratorView || isInCommunitiesAdminView || isInCommunitiesOwnerView)) {
|
||||
errorsToDisplay.push(<ErrorDisplay key={source} error={errorObj} />);
|
||||
} else if (source === 'SubscriberSubplebbits_useSubplebbits' && isInSubplebbitsSubscriberView) {
|
||||
} else if (source === 'SubscriberSubplebbits_useSubplebbits' && isInCommunitiesSubscriberView) {
|
||||
errorsToDisplay.push(<ErrorDisplay key={source} error={errorObj} />);
|
||||
} else if (source === 'AllDefaultSubplebbits_useSubplebbits' && isInSubplebbitsVoteView) {
|
||||
} else if (source === 'AllDefaultSubplebbits_useSubplebbits' && isInCommunitiesVoteView) {
|
||||
errorsToDisplay.push(<ErrorDisplay key={source} error={errorObj} />);
|
||||
} else if (source === 'AllAccountSubplebbits_useAccountSubplebbits' && isInSubplebbitsView) {
|
||||
} else if (source === 'AllAccountSubplebbits_useAccountSubplebbits' && isInCommunitiesView) {
|
||||
errorsToDisplay.push(<ErrorDisplay key={source} error={errorObj} />);
|
||||
} else if (source === 'AllAccountSubplebbits_useSubplebbits' && isInSubplebbitsView) {
|
||||
} else if (source === 'AllAccountSubplebbits_useSubplebbits' && isInCommunitiesView) {
|
||||
// Avoid duplicate key if both errors from AllAccountSubplebbits are present
|
||||
errorsToDisplay.push(<ErrorDisplay key={`${source}_subplebbits`} error={errorObj} />);
|
||||
}
|
||||
@@ -611,19 +612,19 @@ const Subplebbits = () => {
|
||||
<div className={styles.sidebar}>
|
||||
<Sidebar />
|
||||
</div>
|
||||
{isInSubplebbitsSubscriberView || isInSubplebbitsModeratorView || isInSubplebbitsAdminView || isInSubplebbitsOwnerView || isInSubplebbitsView ? (
|
||||
{isInCommunitiesSubscriberView || isInCommunitiesModeratorView || isInCommunitiesAdminView || isInCommunitiesOwnerView || isInCommunitiesView ? (
|
||||
<MyCommunitiesTabs />
|
||||
) : (
|
||||
<VoteTabs />
|
||||
)}
|
||||
<Infobar />
|
||||
<div className={styles.error}>{renderErrors()}</div>
|
||||
{isInSubplebbitsVoteView && <AllDefaultSubplebbits />}
|
||||
{(isInSubplebbitsModeratorView || isInSubplebbitsAdminView || isInSubplebbitsOwnerView) && <AccountSubplebbits viewRole={viewRole} />}
|
||||
{isInSubplebbitsSubscriberView && <SubscriberSubplebbits />}
|
||||
{isInSubplebbitsView && <AllAccountSubplebbits />}
|
||||
{isInCommunitiesVoteView && <AllDefaultSubplebbits />}
|
||||
{(isInCommunitiesModeratorView || isInCommunitiesAdminView || isInCommunitiesOwnerView) && <AccountSubplebbits viewRole={viewRole} />}
|
||||
{isInCommunitiesSubscriberView && <SubscriberSubplebbits />}
|
||||
{isInCommunitiesView && <AllAccountSubplebbits />}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Subplebbits;
|
||||
export default Communities;
|
||||
1
src/views/communities/index.ts
Normal file
1
src/views/communities/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { default } from './communities';
|
||||
@@ -1,16 +1,16 @@
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { isCreateSubplebbitView } from '../../../lib/utils/view-utils';
|
||||
import useSubplebbitSettingsStore, { SubplebbitSettingsState } from '../../../stores/use-subplebbit-settings-store';
|
||||
import { isCreateCommunityView } from '../../../lib/utils/view-utils';
|
||||
import useCommunitySettingsStore, { CommunitySettingsState } from '../../../stores/use-community-settings-store';
|
||||
import useChallengesOptions from '../../../hooks/use-challenges-options';
|
||||
import styles from '../subplebbit-settings.module.css';
|
||||
import styles from '../community-settings.module.css';
|
||||
|
||||
interface ChallengeSettingsProps {
|
||||
challenge: any;
|
||||
index: number;
|
||||
isReadOnly: boolean;
|
||||
setSubplebbitSettingsStore: (data: Partial<SubplebbitSettingsState>) => void;
|
||||
setCommunitySettingsStore: (data: Partial<CommunitySettingsState>) => void;
|
||||
settings: any;
|
||||
showSettings: boolean;
|
||||
challengesSettings: any;
|
||||
@@ -72,7 +72,7 @@ const ExcludeAddressesFromChallengeInput = ({
|
||||
);
|
||||
};
|
||||
|
||||
const ChallengeSettings = ({ challenge, challengesSettings, index, isReadOnly, setSubplebbitSettingsStore, settings, showSettings }: ChallengeSettingsProps) => {
|
||||
const ChallengeSettings = ({ challenge, challengesSettings, index, isReadOnly, setCommunitySettingsStore, settings, showSettings }: ChallengeSettingsProps) => {
|
||||
const { name, options } = challenge || {};
|
||||
const challengeSettings = challengesSettings[name];
|
||||
const readOnlyFallback = isReadOnly && Object.keys(challengeSettings || {}).length === 0 && challenge;
|
||||
@@ -82,18 +82,18 @@ const ChallengeSettings = ({ challenge, challengesSettings, index, isReadOnly, s
|
||||
const handleOptionChange = (optionName: string, newValue: string) => {
|
||||
const updatedOptions = { ...options, [optionName]: newValue };
|
||||
const updatedChallenges = settings.challenges?.map((ch: any, idx: number) => (idx === index ? { ...ch, options: updatedOptions } : ch));
|
||||
setSubplebbitSettingsStore({ settings: { ...settings, challenges: updatedChallenges } });
|
||||
setCommunitySettingsStore({ settings: { ...settings, challenges: updatedChallenges } });
|
||||
};
|
||||
|
||||
const addExcludeGroup = () => {
|
||||
const newExclude = { role: [], post: false, reply: false, vote: false };
|
||||
if (challenge?.exclude) {
|
||||
const updatedChallenges = settings?.challenges?.map((ch: any, idx: number) => (idx === index ? { ...ch, exclude: [...ch.exclude, newExclude] } : ch));
|
||||
setSubplebbitSettingsStore({ settings: { ...settings, challenges: updatedChallenges } });
|
||||
setCommunitySettingsStore({ settings: { ...settings, challenges: updatedChallenges } });
|
||||
setShowExcludeSettings((oldShowExcludeSettings) => [...oldShowExcludeSettings, true]);
|
||||
} else {
|
||||
const updatedChallenges = settings?.challenges?.map((ch: any, idx: number) => (idx === index ? { ...ch, exclude: [newExclude] } : ch));
|
||||
setSubplebbitSettingsStore({ settings: { ...settings, challenges: updatedChallenges } });
|
||||
setCommunitySettingsStore({ settings: { ...settings, challenges: updatedChallenges } });
|
||||
setShowExcludeSettings([true]);
|
||||
}
|
||||
};
|
||||
@@ -102,7 +102,7 @@ const ChallengeSettings = ({ challenge, challengesSettings, index, isReadOnly, s
|
||||
const updatedChallenges = [...settings.challenges];
|
||||
const currentChallenge = updatedChallenges[index];
|
||||
currentChallenge.exclude.splice(excludeIndex, 1);
|
||||
setSubplebbitSettingsStore({ settings: { ...settings, challenges: updatedChallenges } });
|
||||
setCommunitySettingsStore({ settings: { ...settings, challenges: updatedChallenges } });
|
||||
};
|
||||
|
||||
const [showExcludeSettings, setShowExcludeSettings] = useState<boolean[]>([]);
|
||||
@@ -153,7 +153,7 @@ const ChallengeSettings = ({ challenge, challengesSettings, index, isReadOnly, s
|
||||
return ch;
|
||||
});
|
||||
|
||||
setSubplebbitSettingsStore({ settings: { ...settings, challenges: updatedChallenges } });
|
||||
setCommunitySettingsStore({ settings: { ...settings, challenges: updatedChallenges } });
|
||||
};
|
||||
|
||||
const handleExcludeAddress = (excludeIndex: number, value: string) => {
|
||||
@@ -206,7 +206,7 @@ const ChallengeSettings = ({ challenge, challengesSettings, index, isReadOnly, s
|
||||
{!isReadOnly && <span className={styles.deleteButton} onClick={() => deleteExcludeGroup(excludeIndex)} title='delete group' />}
|
||||
{!isReadOnly && (
|
||||
<button className={styles.hideCombo} onClick={() => toggleExcludeSettings(excludeIndex)} disabled={isReadOnly}>
|
||||
{showExcludeSettings?.[excludeIndex] ?? false ? 'Hide' : 'Show'} Group Settings
|
||||
{(showExcludeSettings?.[excludeIndex] ?? false) ? 'Hide' : 'Show'} Group Settings
|
||||
</button>
|
||||
)}
|
||||
{showExcludeSettings[excludeIndex] && (
|
||||
@@ -426,29 +426,29 @@ const Challenges = ({
|
||||
challengesSettings: any;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const { settings, setSubplebbitSettingsStore } = useSubplebbitSettingsStore();
|
||||
const { settings, setCommunitySettingsStore } = useCommunitySettingsStore();
|
||||
const location = useLocation();
|
||||
const isInCreateSubplebbitView = isCreateSubplebbitView(location.pathname);
|
||||
const isInCreateCommunityView = isCreateCommunityView(location.pathname);
|
||||
const challenges = settings?.challenges || readOnlyChallenges || [];
|
||||
const [showSettings, setShowSettings] = useState<boolean[]>(challenges?.map(() => false));
|
||||
const challengeOptions = useChallengesOptions();
|
||||
|
||||
const hasSetDefaultChallenge = useRef(false);
|
||||
const valuesRef = useRef({ settings, setSubplebbitSettingsStore });
|
||||
const valuesRef = useRef({ settings, setCommunitySettingsStore });
|
||||
|
||||
useEffect(() => {
|
||||
valuesRef.current = { settings, setSubplebbitSettingsStore };
|
||||
valuesRef.current = { settings, setCommunitySettingsStore };
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (isInCreateSubplebbitView && !hasSetDefaultChallenge.current && challengeOptions && challengesSettings && !valuesRef.current.settings?.challenges?.length) {
|
||||
if (isInCreateCommunityView && !hasSetDefaultChallenge.current && challengeOptions && challengesSettings && !valuesRef.current.settings?.challenges?.length) {
|
||||
const defaultChallengeName = challengesSettings?.['captcha-canvas-v3'] ? 'captcha-canvas-v3' : challengeNames?.[0] || Object.keys(challengeOptions)[0];
|
||||
const defaultChallenge = {
|
||||
name: defaultChallengeName,
|
||||
options: challengeOptions[defaultChallengeName] || {},
|
||||
};
|
||||
|
||||
valuesRef.current.setSubplebbitSettingsStore({
|
||||
valuesRef.current.setCommunitySettingsStore({
|
||||
settings: {
|
||||
...valuesRef.current.settings,
|
||||
challenges: [defaultChallenge],
|
||||
@@ -457,7 +457,7 @@ const Challenges = ({
|
||||
|
||||
hasSetDefaultChallenge.current = true;
|
||||
}
|
||||
}, [isInCreateSubplebbitView, challengeOptions, challengesSettings, challengeNames]);
|
||||
}, [isInCreateCommunityView, challengeOptions, challengesSettings, challengeNames]);
|
||||
|
||||
const toggleSettings = (index: number) => {
|
||||
const newShowSettings = [...showSettings];
|
||||
@@ -472,13 +472,13 @@ const Challenges = ({
|
||||
options: defaultOptions,
|
||||
};
|
||||
const updatedChallenges = [...(settings?.challenges || []), newChallenge];
|
||||
setSubplebbitSettingsStore({ settings: { ...settings, challenges: updatedChallenges } });
|
||||
setCommunitySettingsStore({ settings: { ...settings, challenges: updatedChallenges } });
|
||||
setShowSettings((oldShowSettings) => [...oldShowSettings, true]);
|
||||
};
|
||||
|
||||
const handleDeleteChallenge = (index: number) => {
|
||||
const updatedChallenges = settings?.challenges?.filter((_: any, idx: number) => idx !== index);
|
||||
setSubplebbitSettingsStore({ settings: { ...settings, challenges: updatedChallenges } });
|
||||
setCommunitySettingsStore({ settings: { ...settings, challenges: updatedChallenges } });
|
||||
setShowSettings((oldShowSettings) => oldShowSettings.filter((_, idx) => idx !== index));
|
||||
};
|
||||
|
||||
@@ -488,7 +488,7 @@ const Challenges = ({
|
||||
const updatedChallenges = [...currentChallenges];
|
||||
updatedChallenges[index] = { ...updatedChallenges[index], name: newType, options };
|
||||
|
||||
setSubplebbitSettingsStore({
|
||||
setCommunitySettingsStore({
|
||||
settings: {
|
||||
...settings,
|
||||
challenges: updatedChallenges,
|
||||
@@ -506,7 +506,7 @@ const Challenges = ({
|
||||
{t('add_a_challenge')}
|
||||
</button>
|
||||
)}
|
||||
{challenges.length === 0 && !isInCreateSubplebbitView && <span className={styles.noChallengeWarning}>{t('warning_spam')}</span>}
|
||||
{challenges.length === 0 && !isInCreateCommunityView && <span className={styles.noChallengeWarning}>{t('warning_spam')}</span>}
|
||||
{challenges?.map((challenge: any, index: number) => (
|
||||
<div key={index} className={styles.challenge}>
|
||||
Challenge #{index + 1}
|
||||
@@ -533,7 +533,7 @@ const Challenges = ({
|
||||
challengesSettings={challengesSettings || {}}
|
||||
index={index}
|
||||
isReadOnly={isReadOnly}
|
||||
setSubplebbitSettingsStore={setSubplebbitSettingsStore}
|
||||
setCommunitySettingsStore={setCommunitySettingsStore}
|
||||
settings={settings}
|
||||
showSettings={showSettings[index]}
|
||||
/>
|
||||
@@ -1,11 +1,11 @@
|
||||
import React, { useEffect, useMemo, useState, useRef, lazy, Suspense, Component } from 'react';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
import { usePublishSubplebbitEdit, useSubplebbit } from '@bitsocial/bitsocial-react-hooks';
|
||||
import { usePublishCommunityEdit, useCommunity } from '@bitsocial/bitsocial-react-hooks';
|
||||
import useTheme from '../../../stores/use-theme-store';
|
||||
import styles from '../../settings/account-data-editor/account-data-editor.module.css';
|
||||
import useIsMobile from '../../../hooks/use-is-mobile';
|
||||
import LoadingEllipsis from '../../../components/loading-ellipsis';
|
||||
import useSubplebbitSettingsStore from '../../../stores/use-subplebbit-settings-store';
|
||||
import useCommunitySettingsStore from '../../../stores/use-community-settings-store';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
import ErrorDisplay from '../../../components/error-display';
|
||||
import useStateString from '../../../hooks/use-state-string';
|
||||
@@ -51,22 +51,22 @@ const FallbackEditor = ({ value, onChange, height, disabled }: { value: string;
|
||||
);
|
||||
};
|
||||
|
||||
const SubplebbitDataEditor = () => {
|
||||
const CommunityDataEditor = () => {
|
||||
const { t } = useTranslation();
|
||||
const isMobile = useIsMobile();
|
||||
const navigate = useNavigate();
|
||||
const theme = useTheme((state) => state.theme);
|
||||
const [text, setText] = useState('');
|
||||
|
||||
const { subplebbitAddress } = useParams<{ subplebbitAddress: string }>();
|
||||
const subplebbit = useSubplebbit({ subplebbitAddress });
|
||||
const { communityAddress: subplebbitAddress } = useParams<{ communityAddress: string }>();
|
||||
const subplebbit = useCommunity(subplebbitAddress ? { community: { name: subplebbitAddress } } : undefined);
|
||||
const { address, createdAt, description, error, rules, settings, suggested, roles, title } = subplebbit || {};
|
||||
const hasLoaded = !!createdAt;
|
||||
|
||||
const {
|
||||
publishSubplebbitEditOptions,
|
||||
setSubplebbitSettingsStore,
|
||||
resetSubplebbitSettingsStore,
|
||||
publishCommunityEditOptions,
|
||||
setCommunitySettingsStore,
|
||||
resetCommunitySettingsStore,
|
||||
title: storeTitle,
|
||||
description: storeDescription,
|
||||
address: storeAddress,
|
||||
@@ -74,14 +74,14 @@ const SubplebbitDataEditor = () => {
|
||||
rules: storeRules,
|
||||
roles: storeRoles,
|
||||
settings: storeSettings,
|
||||
subplebbitAddress: storeSubplebbitAddress,
|
||||
} = useSubplebbitSettingsStore();
|
||||
communityAddress: storeCommunityAddress,
|
||||
} = useCommunitySettingsStore();
|
||||
|
||||
const { error: publishSubplebbitEditError, publishSubplebbitEdit } = usePublishSubplebbitEdit(publishSubplebbitEditOptions);
|
||||
const { error: publishCommunityEditError, publishCommunityEdit: publishSubplebbitEdit } = usePublishCommunityEdit(publishCommunityEditOptions);
|
||||
|
||||
// Use store state if available, otherwise fall back to original subplebbit data
|
||||
const currentSettings = useMemo(() => {
|
||||
const { subplebbitAddress: storeAddr } = useSubplebbitSettingsStore.getState();
|
||||
const { communityAddress: storeAddr } = useCommunitySettingsStore.getState();
|
||||
const hasStoreData = storeAddr === subplebbitAddress;
|
||||
|
||||
return {
|
||||
@@ -92,7 +92,7 @@ const SubplebbitDataEditor = () => {
|
||||
rules: hasStoreData ? storeRules : rules,
|
||||
roles: hasStoreData ? storeRoles : roles,
|
||||
settings: hasStoreData ? storeSettings : settings,
|
||||
subplebbitAddress: hasStoreData ? storeSubplebbitAddress : subplebbitAddress,
|
||||
communityAddress: hasStoreData ? storeCommunityAddress : subplebbitAddress,
|
||||
};
|
||||
}, [
|
||||
storeTitle,
|
||||
@@ -102,7 +102,7 @@ const SubplebbitDataEditor = () => {
|
||||
storeRules,
|
||||
storeRoles,
|
||||
storeSettings,
|
||||
storeSubplebbitAddress,
|
||||
storeCommunityAddress,
|
||||
title,
|
||||
description,
|
||||
address,
|
||||
@@ -142,7 +142,7 @@ const SubplebbitDataEditor = () => {
|
||||
// Try to sync immediately if JSON is valid
|
||||
try {
|
||||
const parsedSettings = JSON.parse(newText);
|
||||
setSubplebbitSettingsStore({
|
||||
setCommunitySettingsStore({
|
||||
title: parsedSettings.title ?? '',
|
||||
description: parsedSettings.description ?? '',
|
||||
address: parsedSettings.address,
|
||||
@@ -150,7 +150,7 @@ const SubplebbitDataEditor = () => {
|
||||
rules: parsedSettings.rules ?? [],
|
||||
roles: parsedSettings.roles ?? {},
|
||||
settings: parsedSettings.settings ?? {},
|
||||
subplebbitAddress: parsedSettings.subplebbitAddress,
|
||||
communityAddress: parsedSettings.communityAddress,
|
||||
});
|
||||
} catch {
|
||||
// Invalid JSON - don't spam console during active typing
|
||||
@@ -167,14 +167,14 @@ const SubplebbitDataEditor = () => {
|
||||
if (triggerSave) {
|
||||
const performSave = async () => {
|
||||
try {
|
||||
console.log('Performing save with options:', publishSubplebbitEditOptions);
|
||||
console.log('Performing save with options:', publishCommunityEditOptions);
|
||||
await publishSubplebbitEdit();
|
||||
setShowSaving(false);
|
||||
setTriggerSave(false);
|
||||
|
||||
if (publishSubplebbitEditError) {
|
||||
setCurrentError(publishSubplebbitEditError);
|
||||
alert(publishSubplebbitEditError.message || 'Error: ' + publishSubplebbitEditError);
|
||||
if (publishCommunityEditError) {
|
||||
setCurrentError(publishCommunityEditError);
|
||||
alert(publishCommunityEditError.message || 'Error: ' + publishCommunityEditError);
|
||||
} else {
|
||||
alert(t('settings_saved', { subplebbitAddress }));
|
||||
}
|
||||
@@ -192,11 +192,11 @@ const SubplebbitDataEditor = () => {
|
||||
};
|
||||
performSave();
|
||||
}
|
||||
// Intentionally only depend on triggerSave to prevent multiple executions when publishSubplebbitEditOptions changes during save
|
||||
// Intentionally only depend on triggerSave to prevent multiple executions when publishCommunityEditOptions changes during save
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [triggerSave]);
|
||||
|
||||
const saveSubplebbitSettings = () => {
|
||||
const saveCommunitySettings = () => {
|
||||
try {
|
||||
setShowSaving(true);
|
||||
setCurrentError(undefined);
|
||||
@@ -231,12 +231,12 @@ const SubplebbitDataEditor = () => {
|
||||
useEffect(() => {
|
||||
if (hasLoaded) {
|
||||
// Only reset if we're switching to a different subplebbit or if store is uninitialized
|
||||
const { subplebbitAddress: storeSubplebbitAddress } = useSubplebbitSettingsStore.getState();
|
||||
const shouldReset = !storeSubplebbitAddress || storeSubplebbitAddress !== subplebbitAddress;
|
||||
const { communityAddress: storeCommunityAddress } = useCommunitySettingsStore.getState();
|
||||
const shouldReset = !storeCommunityAddress || storeCommunityAddress !== subplebbitAddress;
|
||||
|
||||
if (shouldReset) {
|
||||
resetSubplebbitSettingsStore();
|
||||
setSubplebbitSettingsStore({
|
||||
resetCommunitySettingsStore();
|
||||
setCommunitySettingsStore({
|
||||
title: title ?? '',
|
||||
description: description ?? '',
|
||||
address,
|
||||
@@ -244,11 +244,11 @@ const SubplebbitDataEditor = () => {
|
||||
rules: rules ?? [],
|
||||
roles: roles ?? {},
|
||||
settings: settings ?? {},
|
||||
subplebbitAddress,
|
||||
communityAddress: subplebbitAddress,
|
||||
});
|
||||
}
|
||||
}
|
||||
}, [hasLoaded, resetSubplebbitSettingsStore, setSubplebbitSettingsStore, title, description, address, suggested, rules, roles, settings, subplebbitAddress]);
|
||||
}, [hasLoaded, resetCommunitySettingsStore, setCommunitySettingsStore, title, description, address, suggested, rules, roles, settings, subplebbitAddress]);
|
||||
|
||||
const loadingStateString = useStateString(subplebbit);
|
||||
|
||||
@@ -319,7 +319,7 @@ const SubplebbitDataEditor = () => {
|
||||
<Trans
|
||||
i18nKey='save_reset_changes'
|
||||
components={{
|
||||
1: <button key='saveSubplebbitSettingsButton' onClick={saveSubplebbitSettings} />,
|
||||
1: <button key='saveCommunitySettingsButton' onClick={saveCommunitySettings} />,
|
||||
2: <button key='resetSubplebbitSettingsButton' onClick={() => setText(subplebbitSettings)} />,
|
||||
}}
|
||||
/>
|
||||
@@ -333,4 +333,4 @@ const SubplebbitDataEditor = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default SubplebbitDataEditor;
|
||||
export default CommunityDataEditor;
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from './community-data-editor';
|
||||
@@ -2,20 +2,20 @@ import { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useLocation, useNavigate, useParams } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
deleteSubplebbit,
|
||||
deleteCommunity,
|
||||
Role,
|
||||
useAccount,
|
||||
useCreateSubplebbit,
|
||||
usePlebbitRpcSettings,
|
||||
usePublishSubplebbitEdit,
|
||||
useSubplebbit,
|
||||
useCreateCommunity,
|
||||
usePkcRpcSettings,
|
||||
usePublishCommunityEdit,
|
||||
useCommunity,
|
||||
useSubscribe,
|
||||
} from '@bitsocial/bitsocial-react-hooks';
|
||||
import { isUserOwnerOrAdmin, Roles } from '../../lib/utils/user-utils';
|
||||
import { isValidURL } from '../../lib/utils/url-utils';
|
||||
import { isCreateSubplebbitView, isSubplebbitSettingsView } from '../../lib/utils/view-utils';
|
||||
import useSubplebbitSettingsStore from '../../stores/use-subplebbit-settings-store';
|
||||
import useIsSubplebbitOffline from '../../hooks/use-is-subplebbit-offline';
|
||||
import { isCreateCommunityView, isCommunitySettingsView } from '../../lib/utils/view-utils';
|
||||
import useCommunitySettingsStore from '../../stores/use-community-settings-store';
|
||||
import useIsCommunityOffline from '../../hooks/use-is-community-offline';
|
||||
import useStateString from '../../hooks/use-state-string';
|
||||
import ErrorDisplay from '../../components/error-display';
|
||||
import LoadingEllipsis from '../../components/loading-ellipsis';
|
||||
@@ -23,19 +23,19 @@ import Markdown from '../../components/markdown';
|
||||
import Sidebar from '../../components/sidebar';
|
||||
import Challenges from './challenge-settings';
|
||||
import { FormattingHelpTable } from '../../components/reply-form';
|
||||
import styles from './subplebbit-settings.module.css';
|
||||
import styles from './community-settings.module.css';
|
||||
import _ from 'lodash';
|
||||
|
||||
const Title = ({ isReadOnly = false }: { isReadOnly?: boolean }) => {
|
||||
const { t } = useTranslation();
|
||||
const { title, setSubplebbitSettingsStore } = useSubplebbitSettingsStore();
|
||||
const { title, setCommunitySettingsStore } = useCommunitySettingsStore();
|
||||
|
||||
return (
|
||||
<div className={`${styles.box} ${isReadOnly && !title ? styles.hidden : styles.visible}`}>
|
||||
<div className={styles.boxTitle}>{t('title')}</div>
|
||||
<div className={styles.boxSubtitle}>{t('a_short_title')}</div>
|
||||
<div className={styles.boxInput}>
|
||||
{isReadOnly ? <span>{title}</span> : <input type='text' value={title ?? ''} onChange={(e) => setSubplebbitSettingsStore({ title: e.target.value })} />}
|
||||
{isReadOnly ? <span>{title}</span> : <input type='text' value={title ?? ''} onChange={(e) => setCommunitySettingsStore({ title: e.target.value })} />}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -43,7 +43,7 @@ const Title = ({ isReadOnly = false }: { isReadOnly?: boolean }) => {
|
||||
|
||||
const Description = ({ isReadOnly = false }: { isReadOnly?: boolean }) => {
|
||||
const { t } = useTranslation();
|
||||
const { description, setSubplebbitSettingsStore } = useSubplebbitSettingsStore();
|
||||
const { description, setCommunitySettingsStore } = useCommunitySettingsStore();
|
||||
const [showFormattingHelp, setShowFormattingHelp] = useState(false);
|
||||
const [showPreview, setShowPreview] = useState(false);
|
||||
|
||||
@@ -57,7 +57,7 @@ const Description = ({ isReadOnly = false }: { isReadOnly?: boolean }) => {
|
||||
) : (
|
||||
<>
|
||||
{!showPreview ? (
|
||||
<textarea value={description ?? ''} onChange={(e) => setSubplebbitSettingsStore({ description: e.target.value })} />
|
||||
<textarea value={description ?? ''} onChange={(e) => setCommunitySettingsStore({ description: e.target.value })} />
|
||||
) : (
|
||||
<div className={styles.preview}>
|
||||
<Markdown content={description ?? ''} />
|
||||
@@ -96,7 +96,7 @@ const Description = ({ isReadOnly = false }: { isReadOnly?: boolean }) => {
|
||||
|
||||
const Address = ({ isReadOnly = false }: { isReadOnly?: boolean }) => {
|
||||
const { t } = useTranslation();
|
||||
const { address, setSubplebbitSettingsStore } = useSubplebbitSettingsStore();
|
||||
const { address, setCommunitySettingsStore } = useCommunitySettingsStore();
|
||||
|
||||
const alertCryptoAddressInfo = () => {
|
||||
alert(`steps to set a .eth community address:\n1. go to app.ens.domains and search the address\n2. once you own the address, go to its page, click on "records", then "edit records"\n3. add a new text record with name "subplebbit-address" and value: ${address}\n\n steps to set a .sol community address:\n1. go to v1.sns.id and search the address\n2. once you own the address, go to your profile, click the address menu "...", then "create subdomain"\n3. enter subdomain "subplebbit-address" and create\n4. go to subdomain, "content", change content to: ${address}
|
||||
@@ -114,7 +114,7 @@ const Address = ({ isReadOnly = false }: { isReadOnly?: boolean }) => {
|
||||
{isReadOnly ? (
|
||||
<span className={styles.readOnlyAddress}>{address}</span>
|
||||
) : (
|
||||
<input type='text' value={address ?? ''} onChange={(e) => setSubplebbitSettingsStore({ address: e.target.value })} />
|
||||
<input type='text' value={address ?? ''} onChange={(e) => setCommunitySettingsStore({ address: e.target.value })} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
@@ -123,7 +123,7 @@ const Address = ({ isReadOnly = false }: { isReadOnly?: boolean }) => {
|
||||
|
||||
const Logo = ({ isReadOnly = false }: { isReadOnly?: boolean }) => {
|
||||
const { t } = useTranslation();
|
||||
const { suggested, setSubplebbitSettingsStore } = useSubplebbitSettingsStore();
|
||||
const { suggested, setCommunitySettingsStore } = useCommunitySettingsStore();
|
||||
|
||||
const [logoUrl, setLogoUrl] = useState(suggested?.avatarUrl);
|
||||
const [imageError, setImageError] = useState(false);
|
||||
@@ -147,7 +147,7 @@ const Logo = ({ isReadOnly = false }: { isReadOnly?: boolean }) => {
|
||||
onChange={(e) => {
|
||||
setLogoUrl(e.target.value.trim());
|
||||
setImageError(false);
|
||||
setSubplebbitSettingsStore({ suggested: { ...suggested, avatarUrl: e.target.value.trim() || undefined } });
|
||||
setCommunitySettingsStore({ suggested: { ...suggested, avatarUrl: e.target.value.trim() || undefined } });
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
@@ -164,20 +164,20 @@ const Logo = ({ isReadOnly = false }: { isReadOnly?: boolean }) => {
|
||||
|
||||
const Rules = ({ isReadOnly = false }: { isReadOnly?: boolean }) => {
|
||||
const { t } = useTranslation();
|
||||
const { rules, setSubplebbitSettingsStore } = useSubplebbitSettingsStore();
|
||||
const { rules, setCommunitySettingsStore } = useCommunitySettingsStore();
|
||||
const lastRuleRef = useRef(null);
|
||||
|
||||
const handleRuleChange = (index: number, newRule: string) => {
|
||||
if (!rules) return;
|
||||
const updatedRules = [...(rules ?? [])];
|
||||
updatedRules[index] = newRule;
|
||||
setSubplebbitSettingsStore({ rules: updatedRules });
|
||||
setCommunitySettingsStore({ rules: updatedRules });
|
||||
};
|
||||
|
||||
const addedRuleRef = useRef(false);
|
||||
const addRule = () => {
|
||||
const newRules = rules ? [...rules, ''] : [''];
|
||||
setSubplebbitSettingsStore({ rules: newRules });
|
||||
setCommunitySettingsStore({ rules: newRules });
|
||||
addedRuleRef.current = true;
|
||||
};
|
||||
|
||||
@@ -191,7 +191,7 @@ const Rules = ({ isReadOnly = false }: { isReadOnly?: boolean }) => {
|
||||
const deleteRule = (index: number) => {
|
||||
if (rules) {
|
||||
const filteredRules = rules.filter((_, i) => i !== index);
|
||||
setSubplebbitSettingsStore({ rules: filteredRules });
|
||||
setCommunitySettingsStore({ rules: filteredRules });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -224,17 +224,17 @@ const Rules = ({ isReadOnly = false }: { isReadOnly?: boolean }) => {
|
||||
|
||||
const Moderators = ({ isReadOnly = false }: { isReadOnly?: boolean }) => {
|
||||
const { t } = useTranslation();
|
||||
const { roles, setSubplebbitSettingsStore } = useSubplebbitSettingsStore();
|
||||
const { roles, setCommunitySettingsStore } = useCommunitySettingsStore();
|
||||
const lastModeratorRef = useRef(null);
|
||||
|
||||
const addedModeratorRef = useRef(false);
|
||||
const handleAddModerator = () => {
|
||||
if (roles) {
|
||||
const newRoles: Roles = { ...roles, '': { role: 'moderator' } };
|
||||
setSubplebbitSettingsStore({ roles: newRoles });
|
||||
setCommunitySettingsStore({ roles: newRoles });
|
||||
addedModeratorRef.current = true;
|
||||
} else {
|
||||
setSubplebbitSettingsStore({ roles: { '': { role: 'moderator' } } });
|
||||
setCommunitySettingsStore({ roles: { '': { role: 'moderator' } } });
|
||||
addedModeratorRef.current = true;
|
||||
}
|
||||
};
|
||||
@@ -250,14 +250,14 @@ const Moderators = ({ isReadOnly = false }: { isReadOnly?: boolean }) => {
|
||||
if (roles) {
|
||||
const updatedRole: Role = { role: newRole };
|
||||
const updatedRoles: Roles = { ...roles, [address]: updatedRole };
|
||||
setSubplebbitSettingsStore({ roles: updatedRoles });
|
||||
setCommunitySettingsStore({ roles: updatedRoles });
|
||||
}
|
||||
};
|
||||
|
||||
const handleDeleteModerator = (address: string) => {
|
||||
if (roles) {
|
||||
const { [address]: _, ...remainingRoles } = roles;
|
||||
setSubplebbitSettingsStore({ roles: remainingRoles });
|
||||
setCommunitySettingsStore({ roles: remainingRoles });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -265,7 +265,7 @@ const Moderators = ({ isReadOnly = false }: { isReadOnly?: boolean }) => {
|
||||
const rolesArray = Object.entries(roles || {});
|
||||
rolesArray[index] = [newAddress, rolesArray[index][1]];
|
||||
const updatedRoles = Object.fromEntries(rolesArray);
|
||||
setSubplebbitSettingsStore({ roles: updatedRoles });
|
||||
setCommunitySettingsStore({ roles: updatedRoles });
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -325,7 +325,7 @@ const Moderators = ({ isReadOnly = false }: { isReadOnly?: boolean }) => {
|
||||
const JSONSettings = ({ isReadOnly: _isReadOnly = false }: { isReadOnly?: boolean }) => {
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
const { subplebbitAddress } = useParams<{ subplebbitAddress: string }>();
|
||||
const { communityAddress: subplebbitAddress } = useParams<{ communityAddress: string }>();
|
||||
|
||||
return (
|
||||
<div className={`${styles.box}`}>
|
||||
@@ -338,63 +338,63 @@ const JSONSettings = ({ isReadOnly: _isReadOnly = false }: { isReadOnly?: boolea
|
||||
);
|
||||
};
|
||||
|
||||
const SubplebbitSettings = () => {
|
||||
const CommunitySettings = () => {
|
||||
const { t } = useTranslation();
|
||||
const { subplebbitAddress } = useParams<{ subplebbitAddress: string }>();
|
||||
const subplebbit = useSubplebbit({ subplebbitAddress });
|
||||
const { communityAddress: subplebbitAddress } = useParams<{ communityAddress: string }>();
|
||||
const subplebbit = useCommunity(subplebbitAddress ? { community: { name: subplebbitAddress } } : undefined);
|
||||
const { address, challenges, createdAt, description, error, rules, shortAddress, settings, suggested, roles, title } = subplebbit || {};
|
||||
const hasLoaded = !!createdAt;
|
||||
|
||||
const { challenges: rpcChallenges } = usePlebbitRpcSettings().plebbitRpcSettings || {};
|
||||
const { challenges: rpcChallenges } = usePkcRpcSettings().pkcRpcSettings || {};
|
||||
const challengeNames = Object.keys(rpcChallenges || {});
|
||||
|
||||
const account = useAccount();
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
const params = useParams();
|
||||
const isInCreateSubplebbitView = isCreateSubplebbitView(location.pathname);
|
||||
const isInSubplebbitSettingsView = isSubplebbitSettingsView(location.pathname, params);
|
||||
const isConnectedToRpc = usePlebbitRpcSettings()?.state === 'connected';
|
||||
const isInCreateCommunityView = isCreateCommunityView(location.pathname);
|
||||
const isInCommunitySettingsView = isCommunitySettingsView(location.pathname, params);
|
||||
const isConnectedToRpc = usePkcRpcSettings()?.state === 'connected';
|
||||
|
||||
if (isInCreateSubplebbitView && !isConnectedToRpc) {
|
||||
if (isInCreateCommunityView && !isConnectedToRpc) {
|
||||
navigate('/', { replace: true });
|
||||
}
|
||||
|
||||
const userAddress = account?.author?.address;
|
||||
const userIsOwnerOrAdmin = isUserOwnerOrAdmin(roles, userAddress);
|
||||
|
||||
const { isOffline, offlineTitle } = useIsSubplebbitOffline(subplebbit || {});
|
||||
const { isOffline, offlineTitle } = useIsCommunityOffline(subplebbit || {});
|
||||
|
||||
// General fields can be edited by owners/admins even without RPC connection
|
||||
const isReadOnly = (!settings && isInSubplebbitSettingsView && !userIsOwnerOrAdmin) || (!isConnectedToRpc && isInCreateSubplebbitView && !userIsOwnerOrAdmin);
|
||||
const isReadOnly = (!settings && isInCommunitySettingsView && !userIsOwnerOrAdmin) || (!isConnectedToRpc && isInCreateCommunityView && !userIsOwnerOrAdmin);
|
||||
|
||||
// Challenges are always read-only when not connected to RPC
|
||||
const isChallengesReadOnly = (!isConnectedToRpc || !settings) && !isInCreateSubplebbitView;
|
||||
const isChallengesReadOnly = (!isConnectedToRpc || !settings) && !isInCreateCommunityView;
|
||||
|
||||
const { publishSubplebbitEditOptions, resetSubplebbitSettingsStore, setSubplebbitSettingsStore, title: storeTitle } = useSubplebbitSettingsStore();
|
||||
const { error: publishSubplebbitEditError, publishSubplebbitEdit } = usePublishSubplebbitEdit(publishSubplebbitEditOptions);
|
||||
const { error: createSubplebbitError, createdSubplebbit, createSubplebbit } = useCreateSubplebbit(publishSubplebbitEditOptions);
|
||||
const { publishCommunityEditOptions, resetCommunitySettingsStore, setCommunitySettingsStore, title: storeTitle } = useCommunitySettingsStore();
|
||||
const { error: publishCommunityEditError, publishCommunityEdit: publishSubplebbitEdit } = usePublishCommunityEdit(publishCommunityEditOptions);
|
||||
const { error: createCommunityError, createdCommunity, createCommunity: createSubplebbit } = useCreateCommunity(publishCommunityEditOptions);
|
||||
|
||||
const [showSaving, setShowSaving] = useState(false);
|
||||
const [currentError, setCurrentError] = useState<Error | undefined>(undefined);
|
||||
|
||||
useEffect(() => {
|
||||
if (publishSubplebbitEditError || createSubplebbitError) {
|
||||
setCurrentError(publishSubplebbitEditError || createSubplebbitError);
|
||||
if (publishCommunityEditError || createCommunityError) {
|
||||
setCurrentError(publishCommunityEditError || createCommunityError);
|
||||
}
|
||||
}, [publishSubplebbitEditError, createSubplebbitError]);
|
||||
}, [publishCommunityEditError, createCommunityError]);
|
||||
|
||||
const saveSubplebbit = async () => {
|
||||
try {
|
||||
setShowSaving(true);
|
||||
setCurrentError(undefined);
|
||||
console.log('Saving subplebbit with options:', publishSubplebbitEditOptions);
|
||||
console.log('Saving subplebbit with options:', publishCommunityEditOptions);
|
||||
await publishSubplebbitEdit();
|
||||
setShowSaving(false);
|
||||
|
||||
if (publishSubplebbitEditError) {
|
||||
setCurrentError(publishSubplebbitEditError);
|
||||
alert(publishSubplebbitEditError.message || 'Error: ' + publishSubplebbitEditError);
|
||||
if (publishCommunityEditError) {
|
||||
setCurrentError(publishCommunityEditError);
|
||||
alert(publishCommunityEditError.message || 'Error: ' + publishCommunityEditError);
|
||||
} else {
|
||||
alert(t('settings_saved', { subplebbitAddress }));
|
||||
}
|
||||
@@ -411,12 +411,12 @@ const SubplebbitSettings = () => {
|
||||
};
|
||||
|
||||
const [showDeleting, setShowDeleting] = useState(false);
|
||||
const _deleteSubplebbit = async () => {
|
||||
const _deleteCommunity = async () => {
|
||||
if (subplebbitAddress && window.confirm(t('delete_confirm', { value: `s/${shortAddress}`, interpolation: { escapeValue: false } }))) {
|
||||
if (window.confirm(t('double_confirm'))) {
|
||||
try {
|
||||
setShowDeleting(true);
|
||||
await deleteSubplebbit(subplebbitAddress);
|
||||
await deleteCommunity(subplebbitAddress);
|
||||
setShowDeleting(false);
|
||||
alert(t('community_deleted'));
|
||||
navigate('/', { replace: true });
|
||||
@@ -432,17 +432,17 @@ const SubplebbitSettings = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const _createSubplebbit = async () => {
|
||||
const _createCommunity = async () => {
|
||||
try {
|
||||
setShowSaving(true);
|
||||
setCurrentError(undefined);
|
||||
console.log('Creating subplebbit with settings:', publishSubplebbitEditOptions);
|
||||
console.log('Creating subplebbit with settings:', publishCommunityEditOptions);
|
||||
await createSubplebbit();
|
||||
setShowSaving(false);
|
||||
|
||||
if (createSubplebbitError) {
|
||||
setCurrentError(createSubplebbitError);
|
||||
alert(createSubplebbitError.message || 'Error: ' + createSubplebbitError);
|
||||
if (createCommunityError) {
|
||||
setCurrentError(createCommunityError);
|
||||
alert(createCommunityError.message || 'Error: ' + createCommunityError);
|
||||
}
|
||||
} catch (e) {
|
||||
setShowSaving(false);
|
||||
@@ -456,30 +456,30 @@ const SubplebbitSettings = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const { subscribe } = useSubscribe({ subplebbitAddress: createdSubplebbit?.address });
|
||||
const { subscribe } = useSubscribe({ communityAddress: createdCommunity?.address });
|
||||
|
||||
useEffect(() => {
|
||||
if (createdSubplebbit) {
|
||||
console.log('createdSubplebbit', createdSubplebbit);
|
||||
alert(`community created, address: ${createdSubplebbit?.address}`);
|
||||
if (createdCommunity) {
|
||||
console.log('createdCommunity', createdCommunity);
|
||||
alert(`community created, address: ${createdCommunity?.address}`);
|
||||
|
||||
if (account && createdSubplebbit.address) {
|
||||
if (account && createdCommunity.address) {
|
||||
subscribe();
|
||||
}
|
||||
|
||||
resetSubplebbitSettingsStore();
|
||||
navigate(`/s/${createdSubplebbit?.address}/`);
|
||||
resetCommunitySettingsStore();
|
||||
navigate(`/s/${createdCommunity?.address}/`);
|
||||
}
|
||||
}, [createdSubplebbit, navigate, resetSubplebbitSettingsStore, account, subscribe]);
|
||||
}, [createdCommunity, navigate, resetCommunitySettingsStore, account, subscribe]);
|
||||
|
||||
const lastViewType = useRef<'create' | 'settings' | 'other' | undefined>(undefined);
|
||||
|
||||
// Initialize store for create view only on first entry or when switching from settings view
|
||||
useEffect(() => {
|
||||
if (isInCreateSubplebbitView && lastViewType.current === 'settings') {
|
||||
resetSubplebbitSettingsStore();
|
||||
if (isInCreateCommunityView && lastViewType.current === 'settings') {
|
||||
resetCommunitySettingsStore();
|
||||
const initialRoles: Roles = account?.author?.address ? { [account.author.address]: { role: 'owner' as const } } : {};
|
||||
setSubplebbitSettingsStore({
|
||||
setCommunitySettingsStore({
|
||||
title: '',
|
||||
description: '',
|
||||
address: undefined,
|
||||
@@ -488,28 +488,28 @@ const SubplebbitSettings = () => {
|
||||
roles: initialRoles,
|
||||
settings: {},
|
||||
challenges: [],
|
||||
subplebbitAddress: undefined,
|
||||
communityAddress: undefined,
|
||||
});
|
||||
}
|
||||
if (isInCreateSubplebbitView) {
|
||||
if (isInCreateCommunityView) {
|
||||
lastViewType.current = 'create';
|
||||
} else if (isInSubplebbitSettingsView) {
|
||||
} else if (isInCommunitySettingsView) {
|
||||
lastViewType.current = 'settings';
|
||||
} else {
|
||||
lastViewType.current = 'other';
|
||||
}
|
||||
}, [isInCreateSubplebbitView, storeTitle, resetSubplebbitSettingsStore, setSubplebbitSettingsStore, account, isInSubplebbitSettingsView]);
|
||||
}, [isInCreateCommunityView, storeTitle, resetCommunitySettingsStore, setCommunitySettingsStore, account, isInCommunitySettingsView]);
|
||||
|
||||
// Set store for loaded subplebbit settings when editing
|
||||
useEffect(() => {
|
||||
if (!isInCreateSubplebbitView && hasLoaded) {
|
||||
if (!isInCreateCommunityView && hasLoaded) {
|
||||
// Only reset if we're switching to a different subplebbit or if store is uninitialized
|
||||
const { subplebbitAddress: storeSubplebbitAddress } = useSubplebbitSettingsStore.getState();
|
||||
const shouldReset = !storeSubplebbitAddress || storeSubplebbitAddress !== subplebbitAddress;
|
||||
const { communityAddress: storeCommunityAddress } = useCommunitySettingsStore.getState();
|
||||
const shouldReset = !storeCommunityAddress || storeCommunityAddress !== subplebbitAddress;
|
||||
|
||||
if (shouldReset) {
|
||||
resetSubplebbitSettingsStore();
|
||||
setSubplebbitSettingsStore({
|
||||
resetCommunitySettingsStore();
|
||||
setCommunitySettingsStore({
|
||||
title: title ?? '',
|
||||
description: description ?? '',
|
||||
address,
|
||||
@@ -518,15 +518,15 @@ const SubplebbitSettings = () => {
|
||||
roles: roles ?? {},
|
||||
settings: settings ?? {},
|
||||
challenges: challenges ?? [],
|
||||
subplebbitAddress,
|
||||
communityAddress: subplebbitAddress,
|
||||
});
|
||||
}
|
||||
}
|
||||
}, [
|
||||
isInCreateSubplebbitView,
|
||||
isInCreateCommunityView,
|
||||
hasLoaded,
|
||||
resetSubplebbitSettingsStore,
|
||||
setSubplebbitSettingsStore,
|
||||
resetCommunitySettingsStore,
|
||||
setCommunitySettingsStore,
|
||||
title,
|
||||
description,
|
||||
address,
|
||||
@@ -540,13 +540,13 @@ const SubplebbitSettings = () => {
|
||||
|
||||
const documentTitle = useMemo(() => {
|
||||
let title;
|
||||
if (isInSubplebbitSettingsView) {
|
||||
if (isInCommunitySettingsView) {
|
||||
title = _.startCase(t('community_settings', { interpolation: { escapeValue: false } }));
|
||||
} else if (isInCreateSubplebbitView) {
|
||||
} else if (isInCreateCommunityView) {
|
||||
title = _.startCase(t('create_community', { interpolation: { escapeValue: false } }));
|
||||
}
|
||||
return `${title} - Seedit`;
|
||||
}, [isInCreateSubplebbitView, isInSubplebbitSettingsView, t]);
|
||||
}, [isInCreateCommunityView, isInCommunitySettingsView, t]);
|
||||
|
||||
useEffect(() => {
|
||||
document.title = documentTitle;
|
||||
@@ -558,7 +558,7 @@ const SubplebbitSettings = () => {
|
||||
|
||||
const loadingStateString = useStateString(subplebbit);
|
||||
|
||||
if (!hasLoaded && !isInCreateSubplebbitView) {
|
||||
if (!hasLoaded && !isInCreateCommunityView) {
|
||||
return (
|
||||
<>
|
||||
{error?.message && (
|
||||
@@ -575,7 +575,7 @@ const SubplebbitSettings = () => {
|
||||
|
||||
return (
|
||||
<div className={styles.content}>
|
||||
{!isInCreateSubplebbitView && (
|
||||
{!isInCreateCommunityView && (
|
||||
<div className={styles.sidebar}>
|
||||
<Sidebar subplebbit={subplebbit} />
|
||||
</div>
|
||||
@@ -585,20 +585,20 @@ const SubplebbitSettings = () => {
|
||||
{isChallengesReadOnly && <div className={styles.infobar}>cannot read or write challenges, community node isn't reachable.</div>}
|
||||
<Title isReadOnly={isReadOnly} />
|
||||
<Description isReadOnly={isReadOnly} />
|
||||
{!isInCreateSubplebbitView && <Address isReadOnly={isReadOnly} />}
|
||||
{!isInCreateCommunityView && <Address isReadOnly={isReadOnly} />}
|
||||
<Logo isReadOnly={isReadOnly} />
|
||||
<Rules isReadOnly={isReadOnly} />
|
||||
<Moderators isReadOnly={isReadOnly} />
|
||||
<Challenges isReadOnly={isChallengesReadOnly} readOnlyChallenges={subplebbit?.challenges} challengeNames={challengeNames} challengesSettings={rpcChallenges} />
|
||||
{!isInCreateSubplebbitView && <JSONSettings isReadOnly={isReadOnly} />}
|
||||
{!isInCreateCommunityView && <JSONSettings isReadOnly={isReadOnly} />}
|
||||
<div className={styles.saveOptions}>
|
||||
{!isInCreateSubplebbitView && !isReadOnly && (
|
||||
{!isInCreateCommunityView && !isReadOnly && (
|
||||
<div className={`${styles.box} ${styles.deleteCommunity}`}>
|
||||
<div className={styles.boxTitle}>{t('delete_community')}</div>
|
||||
<div className={styles.boxSubtitle}>{t('delete_community_description')}</div>
|
||||
<div className={styles.boxInput}>
|
||||
<div className={styles.deleteSubplebbit}>
|
||||
<button onClick={_deleteSubplebbit} disabled={showDeleting || showSaving}>
|
||||
<button onClick={_deleteCommunity} disabled={showDeleting || showSaving}>
|
||||
{t('delete')}
|
||||
</button>
|
||||
<span className={styles.deletingString}>{showDeleting && <LoadingEllipsis string={t('deleting')} />}</span>
|
||||
@@ -607,8 +607,8 @@ const SubplebbitSettings = () => {
|
||||
</div>
|
||||
)}
|
||||
{!isReadOnly && (
|
||||
<button onClick={() => (isInCreateSubplebbitView ? _createSubplebbit() : saveSubplebbit())} disabled={showSaving || showDeleting}>
|
||||
{isInCreateSubplebbitView ? t('create_community') : t('save_options')}
|
||||
<button onClick={() => (isInCreateCommunityView ? _createCommunity() : saveSubplebbit())} disabled={showSaving || showDeleting}>
|
||||
{isInCreateCommunityView ? t('create_community') : t('save_options')}
|
||||
</button>
|
||||
)}
|
||||
{showSaving && <LoadingEllipsis string={t('saving')} />}
|
||||
@@ -622,4 +622,4 @@ const SubplebbitSettings = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default SubplebbitSettings;
|
||||
export default CommunitySettings;
|
||||
1
src/views/community-settings/index.ts
Normal file
1
src/views/community-settings/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { default } from './community-settings';
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { Link, useParams, useNavigate, useSearchParams } from 'react-router-dom';
|
||||
import { useAccountComments, useBlock, useFeed, useSubplebbit, type Comment } from '@bitsocial/bitsocial-react-hooks';
|
||||
import { useAccountComments, useBlock, useFeed, useCommunity, type Comment } from '@bitsocial/bitsocial-react-hooks';
|
||||
import { Virtuoso, VirtuosoHandle, StateSnapshot } from 'react-virtuoso';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
import styles from '../home/home.module.css';
|
||||
@@ -12,8 +12,9 @@ import useFeedFiltersStore from '../../stores/use-feed-filters-store';
|
||||
import useFeedResetStore from '../../stores/use-feed-reset-store';
|
||||
import { usePinnedPostsStore } from '../../stores/use-pinned-posts-store';
|
||||
import { useIsBroadlyNsfwSubplebbit } from '../../hooks/use-is-broadly-nsfw-subplebbit';
|
||||
import useIsSubplebbitOffline from '../../hooks/use-is-subplebbit-offline';
|
||||
import useIsCommunityOffline from '../../hooks/use-is-community-offline';
|
||||
import useTimeFilter, { isValidTimeFilterName } from '../../hooks/use-time-filter';
|
||||
import { getCommunityIdentifiers } from '../../hooks/use-community-identifier';
|
||||
import ErrorDisplay from '../../components/error-display';
|
||||
import LoadingEllipsis from '../../components/loading-ellipsis';
|
||||
import Over18Warning from '../../components/over-18-warning';
|
||||
@@ -213,16 +214,16 @@ const Footer = ({
|
||||
);
|
||||
};
|
||||
|
||||
const Subplebbit = () => {
|
||||
const CommunityView = () => {
|
||||
const params = useParams();
|
||||
const navigate = useNavigate();
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
const searchQuery = searchParams.get('q') || '';
|
||||
|
||||
const subplebbitAddress = params?.subplebbitAddress || '';
|
||||
const subplebbit = useSubplebbit({ subplebbitAddress });
|
||||
const subplebbitAddress = params?.communityAddress || '';
|
||||
const subplebbit = useCommunity(subplebbitAddress ? { community: { name: subplebbitAddress } } : undefined);
|
||||
const { createdAt, error, shortAddress, started, title, updatedAt, settings } = subplebbit || {};
|
||||
const { isOffline } = useIsSubplebbitOffline(subplebbit || {});
|
||||
const { isOffline } = useIsCommunityOffline(subplebbit || {});
|
||||
const isOnline = !isOffline;
|
||||
const isSubCreatedButNotYetPublished = typeof createdAt === 'number' && !updatedAt;
|
||||
|
||||
@@ -248,7 +249,7 @@ const Subplebbit = () => {
|
||||
|
||||
const feedOptions = useMemo(() => {
|
||||
const options: any = {
|
||||
subplebbitAddresses,
|
||||
communities: getCommunityIdentifiers(subplebbitAddresses),
|
||||
sortType,
|
||||
newerThan: searchQuery ? 0 : timeFilterSeconds,
|
||||
};
|
||||
@@ -392,4 +393,4 @@ const Subplebbit = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default Subplebbit;
|
||||
export default CommunityView;
|
||||
1
src/views/community/index.ts
Normal file
1
src/views/community/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { default } from './community';
|
||||
@@ -7,6 +7,7 @@ import useFeedFiltersStore from '../../stores/use-feed-filters-store';
|
||||
import { useDefaultSubplebbitAddresses } from '../../hooks/use-default-subplebbits';
|
||||
import useTimeFilter, { isValidTimeFilterName } from '../../hooks/use-time-filter';
|
||||
import FeedFooter from '../../components/feed-footer';
|
||||
import { getCommunityIdentifiers } from '../../hooks/use-community-identifier';
|
||||
import LoadingEllipsis from '../../components/loading-ellipsis';
|
||||
import Post from '../../components/post';
|
||||
import Sidebar from '../../components/sidebar';
|
||||
@@ -67,19 +68,19 @@ const Domain = () => {
|
||||
const options: {
|
||||
newerThan: number;
|
||||
sortType: string;
|
||||
subplebbitAddresses: string[];
|
||||
communities: ReturnType<typeof getCommunityIdentifiers>;
|
||||
filter: CommentsFilter;
|
||||
} = {
|
||||
newerThan: searchQuery ? 0 : (timeFilterSeconds ?? 0),
|
||||
sortType,
|
||||
subplebbitAddresses,
|
||||
communities: getCommunityIdentifiers(subplebbitAddresses),
|
||||
filter: { filter: filterFunc, key: filterKey },
|
||||
};
|
||||
|
||||
return options;
|
||||
}, [subplebbitAddresses, sortType, timeFilterSeconds, searchQuery, matchesDomain, domain]);
|
||||
|
||||
const { feed, hasMore, loadMore, reset, subplebbitAddressesWithNewerPosts } = useFeed(feedOptions);
|
||||
const { feed, hasMore, loadMore, reset, communityKeysWithNewerPosts: subplebbitAddressesWithNewerPosts } = useFeed(feedOptions);
|
||||
|
||||
useEffect(() => {
|
||||
if (isSearching) {
|
||||
@@ -108,21 +109,21 @@ const Domain = () => {
|
||||
|
||||
// suggest the user to change time filter if there aren't enough posts
|
||||
const { feed: weeklyFeed } = useFeed({
|
||||
subplebbitAddresses,
|
||||
communities: getCommunityIdentifiers(subplebbitAddresses),
|
||||
sortType,
|
||||
newerThan: 60 * 60 * 24 * 7,
|
||||
filter: { filter: matchesDomain, key: `domain-filter-weekly-${domain}` },
|
||||
});
|
||||
|
||||
const { feed: monthlyFeed } = useFeed({
|
||||
subplebbitAddresses,
|
||||
communities: getCommunityIdentifiers(subplebbitAddresses),
|
||||
sortType,
|
||||
newerThan: 60 * 60 * 24 * 30,
|
||||
filter: { filter: matchesDomain, key: `domain-filter-monthly-${domain}` },
|
||||
});
|
||||
|
||||
const { feed: yearlyFeed } = useFeed({
|
||||
subplebbitAddresses,
|
||||
communities: getCommunityIdentifiers(subplebbitAddresses),
|
||||
sortType,
|
||||
newerThan: 60 * 60 * 24 * 365,
|
||||
filter: { filter: matchesDomain, key: `domain-filter-yearly-${domain}` },
|
||||
|
||||
@@ -8,6 +8,7 @@ import useFeedFiltersStore from '../../stores/use-feed-filters-store';
|
||||
import { useAutoSubscribeStore } from '../../stores/use-auto-subscribe-store';
|
||||
import useTimeFilter, { isValidTimeFilterName } from '../../hooks/use-time-filter';
|
||||
import useRedirectToDefaultSort from '../../hooks/use-redirect-to-default-sort';
|
||||
import { getCommunityIdentifiers } from '../../hooks/use-community-identifier';
|
||||
import FeedFooter from '../../components/feed-footer';
|
||||
import LoadingEllipsis from '../../components/loading-ellipsis';
|
||||
import Post from '../../components/post';
|
||||
@@ -75,7 +76,7 @@ const Home = () => {
|
||||
newerThan: searchQuery ? 0 : timeFilterSeconds,
|
||||
postsPerPage: 10,
|
||||
sortType,
|
||||
subplebbitAddresses,
|
||||
communities: getCommunityIdentifiers(subplebbitAddresses),
|
||||
};
|
||||
|
||||
if (searchQuery) {
|
||||
@@ -88,7 +89,7 @@ const Home = () => {
|
||||
return options;
|
||||
}, [subplebbitAddresses, sortType, timeFilterSeconds, searchQuery, commentFilter]);
|
||||
|
||||
const { feed, hasMore, loadMore, reset, subplebbitAddressesWithNewerPosts } = useFeed(feedOptions);
|
||||
const { feed, hasMore, loadMore, reset, communityKeysWithNewerPosts: subplebbitAddressesWithNewerPosts } = useFeed(feedOptions);
|
||||
|
||||
useEffect(() => {
|
||||
startTransition(() => {
|
||||
@@ -126,7 +127,7 @@ const Home = () => {
|
||||
hasMore: hasMoreWeekly,
|
||||
loadMore: loadMoreWeekly,
|
||||
} = useFeed({
|
||||
subplebbitAddresses: shouldLoadAdditionalFeeds ? subplebbitAddresses : [],
|
||||
communities: getCommunityIdentifiers(shouldLoadAdditionalFeeds ? subplebbitAddresses : []),
|
||||
sortType,
|
||||
newerThan: 60 * 60 * 24 * 7,
|
||||
});
|
||||
@@ -135,7 +136,7 @@ const Home = () => {
|
||||
hasMore: hasMoreMonthly,
|
||||
loadMore: loadMoreMonthly,
|
||||
} = useFeed({
|
||||
subplebbitAddresses: shouldLoadAdditionalFeeds ? subplebbitAddresses : [],
|
||||
communities: getCommunityIdentifiers(shouldLoadAdditionalFeeds ? subplebbitAddresses : []),
|
||||
sortType,
|
||||
newerThan: 60 * 60 * 24 * 30,
|
||||
});
|
||||
@@ -144,7 +145,7 @@ const Home = () => {
|
||||
hasMore: hasMoreYearly,
|
||||
loadMore: loadMoreYearly,
|
||||
} = useFeed({
|
||||
subplebbitAddresses: shouldLoadAdditionalFeeds ? subplebbitAddresses : [],
|
||||
communities: getCommunityIdentifiers(shouldLoadAdditionalFeeds ? subplebbitAddresses : []),
|
||||
sortType,
|
||||
newerThan: 60 * 60 * 24 * 365,
|
||||
});
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import { useEffect, useRef, useState, useMemo } from 'react';
|
||||
import { useParams, useSearchParams, useNavigate, useLocation } from 'react-router-dom';
|
||||
import { Virtuoso, VirtuosoHandle, StateSnapshot } from 'react-virtuoso';
|
||||
import { useAccountSubplebbits, useFeed } from '@bitsocial/bitsocial-react-hooks';
|
||||
import { useAccountCommunities, useFeed } from '@bitsocial/bitsocial-react-hooks';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { commentMatchesPattern } from '../../lib/utils/pattern-utils';
|
||||
import useFeedFiltersStore from '../../stores/use-feed-filters-store';
|
||||
import useTimeFilter, { isValidTimeFilterName } from '../../hooks/use-time-filter';
|
||||
import FeedFooter from '../../components/feed-footer';
|
||||
import { getCommunityIdentifiers } from '../../hooks/use-community-identifier';
|
||||
import LoadingEllipsis from '../../components/loading-ellipsis';
|
||||
import Post from '../../components/post';
|
||||
import Sidebar from '../../components/sidebar';
|
||||
@@ -16,7 +17,7 @@ import styles from '../home/home.module.css';
|
||||
const lastVirtuosoStates: { [key: string]: StateSnapshot } = {};
|
||||
|
||||
const Mod = () => {
|
||||
const { accountSubplebbits } = useAccountSubplebbits();
|
||||
const { accountCommunities: accountSubplebbits } = useAccountCommunities();
|
||||
const subplebbitAddresses = Object.keys(accountSubplebbits);
|
||||
const params = useParams<{ sortType?: string; timeFilterName?: string }>();
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
@@ -45,7 +46,7 @@ const Mod = () => {
|
||||
const options: any = {
|
||||
newerThan: searchQuery ? 0 : timeFilterSeconds,
|
||||
sortType,
|
||||
subplebbitAddresses,
|
||||
communities: getCommunityIdentifiers(subplebbitAddresses),
|
||||
};
|
||||
|
||||
if (searchQuery) {
|
||||
@@ -61,7 +62,7 @@ const Mod = () => {
|
||||
return options;
|
||||
}, [subplebbitAddresses, sortType, timeFilterSeconds, searchQuery]);
|
||||
|
||||
const { feed, hasMore, loadMore, reset, subplebbitAddressesWithNewerPosts } = useFeed(feedOptions);
|
||||
const { feed, hasMore, loadMore, reset, communityKeysWithNewerPosts: subplebbitAddressesWithNewerPosts } = useFeed(feedOptions);
|
||||
|
||||
// suggest the user to change time filter if there aren't enough posts
|
||||
const {
|
||||
@@ -69,7 +70,7 @@ const Mod = () => {
|
||||
hasMore: hasMoreWeekly,
|
||||
loadMore: loadMoreWeekly,
|
||||
} = useFeed({
|
||||
subplebbitAddresses,
|
||||
communities: getCommunityIdentifiers(subplebbitAddresses),
|
||||
sortType,
|
||||
newerThan: 60 * 60 * 24 * 7,
|
||||
});
|
||||
@@ -78,7 +79,7 @@ const Mod = () => {
|
||||
hasMore: hasMoreMonthly,
|
||||
loadMore: loadMoreMonthly,
|
||||
} = useFeed({
|
||||
subplebbitAddresses,
|
||||
communities: getCommunityIdentifiers(subplebbitAddresses),
|
||||
sortType,
|
||||
newerThan: 60 * 60 * 24 * 30,
|
||||
});
|
||||
@@ -87,7 +88,7 @@ const Mod = () => {
|
||||
hasMore: hasMoreYearly,
|
||||
loadMore: loadMoreYearly,
|
||||
} = useFeed({
|
||||
subplebbitAddresses,
|
||||
communities: getCommunityIdentifiers(subplebbitAddresses),
|
||||
sortType,
|
||||
newerThan: 60 * 60 * 24 * 365,
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useEffect, useState, useRef, useCallback, useMemo } from 'react';
|
||||
import { Link, useLocation, useNavigate, useParams } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Comment, useAccount, useAccountComment, useAccountComments, useComment, useSubplebbit } from '@bitsocial/bitsocial-react-hooks';
|
||||
import { Comment, useAccount, useAccountComment, useAccountComments, useComment, useCommunity } from '@bitsocial/bitsocial-react-hooks';
|
||||
import findTopParentCidOfReply from '../../lib/utils/cid-utils';
|
||||
import { sortRepliesByBest } from '../../lib/utils/post-utils';
|
||||
import { isPendingPostView, isPostContextView } from '../../lib/utils/view-utils';
|
||||
@@ -274,12 +274,13 @@ const PostPage = () => {
|
||||
}
|
||||
}, [pendingPost?.cid, pendingPost?.subplebbitAddress, navigate, resetFeed]);
|
||||
|
||||
const { commentCid, subplebbitAddress } = params;
|
||||
let post = useComment({ commentCid });
|
||||
const { commentCid, communityAddress: subplebbitAddress } = params;
|
||||
let post = useComment({ commentCid }) as any;
|
||||
if (isInPendingPostView) {
|
||||
post = pendingPost;
|
||||
}
|
||||
const subplebbit = useSubplebbit({ subplebbitAddress: isInPendingPostView ? pendingPost?.subplebbitAddress : subplebbitAddress });
|
||||
const _communityAddr = isInPendingPostView ? pendingPost?.subplebbitAddress : subplebbitAddress;
|
||||
const subplebbit = useCommunity(_communityAddr ? { community: { name: _communityAddr } } : undefined);
|
||||
|
||||
// over 18 warning for subplebbit with nsfw tag in multisub default list
|
||||
const { hasAcceptedWarning } = useContentOptionsStore();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { RefObject, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { setAccount, useAccount, usePlebbitRpcSettings } from '@bitsocial/bitsocial-react-hooks';
|
||||
import { setAccount, useAccount, usePkcRpcSettings } from '@bitsocial/bitsocial-react-hooks';
|
||||
import styles from './plebbit-options.module.css';
|
||||
|
||||
interface SettingsProps {
|
||||
@@ -159,10 +159,10 @@ const PlebbitRPCSettings = ({ plebbitRpcRef }: SettingsProps) => {
|
||||
};
|
||||
|
||||
const PlebbitDataPathSettings = ({ plebbitDataPathRef }: SettingsProps) => {
|
||||
const plebbitRpc = usePlebbitRpcSettings();
|
||||
const { plebbitRpcSettings } = plebbitRpc || {};
|
||||
const plebbitRpc = usePkcRpcSettings();
|
||||
const { pkcRpcSettings } = plebbitRpc || {};
|
||||
const isConnectedToRpc = plebbitRpc?.state === 'connected';
|
||||
const path = plebbitRpcSettings?.plebbitOptions?.dataPath || '';
|
||||
const path = pkcRpcSettings?.plebbitOptions?.dataPath || '';
|
||||
|
||||
return (
|
||||
<div className={styles.plebbitDataPathSettings}>
|
||||
|
||||
@@ -2,15 +2,15 @@ import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useDropzone } from 'react-dropzone';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
import { Link, useNavigate, useParams } from 'react-router-dom';
|
||||
import { useAccount, usePublishComment, useSubplebbit } from '@bitsocial/bitsocial-react-hooks';
|
||||
import Plebbit from '@plebbit/plebbit-js';
|
||||
import { useAccount, usePublishComment, useCommunity } from '@bitsocial/bitsocial-react-hooks';
|
||||
import { Capacitor } from '@capacitor/core';
|
||||
import FileUploader from '../../plugins/file-uploader';
|
||||
import { getLinkMediaInfo } from '../../lib/utils/media-utils';
|
||||
import getShortAddress from '../../lib/utils/address-utils';
|
||||
import { isValidURL } from '../../lib/utils/url-utils';
|
||||
import usePublishPostStore from '../../stores/use-publish-post-store';
|
||||
import { useDefaultSubplebbitAddresses } from '../../hooks/use-default-subplebbits';
|
||||
import useIsSubplebbitOffline from '../../hooks/use-is-subplebbit-offline';
|
||||
import useIsCommunityOffline from '../../hooks/use-is-community-offline';
|
||||
import LoadingEllipsis from '../../components/loading-ellipsis';
|
||||
import Markdown from '../../components/markdown';
|
||||
import Embed from '../../components/post/embed';
|
||||
@@ -405,7 +405,7 @@ const SubplebbitAddressField = () => {
|
||||
setPublishPostStore({ subplebbitAddress: subscription });
|
||||
}}
|
||||
>
|
||||
{Plebbit.getShortAddress({ address: subscription })}
|
||||
{getShortAddress(subscription)}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
@@ -470,13 +470,13 @@ const SubmitPage = () => {
|
||||
const { link, title, subplebbitAddress, publishCommentOptions, setPublishPostStore, resetPublishPostStore } = usePublishPostStore();
|
||||
|
||||
useEffect(() => {
|
||||
setPublishPostStore({ subplebbitAddress: params.subplebbitAddress || '' });
|
||||
}, [params.subplebbitAddress, setPublishPostStore]);
|
||||
setPublishPostStore({ subplebbitAddress: params.communityAddress || '' });
|
||||
}, [params.communityAddress, setPublishPostStore]);
|
||||
|
||||
const selectedSubplebbitData = useSubplebbit({ subplebbitAddress });
|
||||
const selectedSubplebbitData = useCommunity(subplebbitAddress ? { community: { name: subplebbitAddress } } : undefined);
|
||||
const { rules, title: subplebbitTitle } = selectedSubplebbitData;
|
||||
const shortAddress = subplebbitAddress && Plebbit.getShortAddress({ address: subplebbitAddress });
|
||||
const { isOffline, offlineTitle } = useIsSubplebbitOffline(selectedSubplebbitData);
|
||||
const shortAddress = subplebbitAddress && getShortAddress(subplebbitAddress);
|
||||
const { isOffline, offlineTitle } = useIsCommunityOffline(selectedSubplebbitData);
|
||||
|
||||
const { index, publishComment } = usePublishComment(publishCommentOptions);
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export { default } from './subplebbit-settings';
|
||||
@@ -1 +0,0 @@
|
||||
export { default } from './subplebbit-data-editor';
|
||||
@@ -1 +0,0 @@
|
||||
export { default } from './subplebbit';
|
||||
@@ -1 +0,0 @@
|
||||
export { default } from './subplebbits';
|
||||
Reference in New Issue
Block a user