refactor: move zustand stores to their own directory

This commit is contained in:
Tom (plebeius.eth)
2024-10-08 17:10:30 +02:00
parent 9b701a559f
commit 564756ce8b
20 changed files with 263 additions and 220 deletions

View File

@@ -2,7 +2,7 @@ import { useState } from 'react';
import { FloatingFocusManager, useClick, useDismiss, useFloating, useId, useInteractions, useRole } from '@floating-ui/react';
import { Challenge as ChallengeType, useComment } from '@plebbit/plebbit-react-hooks';
import { useTranslation } from 'react-i18next';
import useChallenges from '../../hooks/use-challenges';
import useChallenges from '../../stores/use-challenges-store';
import styles from './challenge-modal.module.css';
import { getPublicationPreview, getPublicationType, getVotePreview } from '../../lib/utils/challenge-utils';

View File

@@ -4,7 +4,7 @@ import { PublishCommentEditOptions, useComment, useEditedComment, usePublishComm
import { FormattingHelpTable } from '../reply-form';
import styles from '../reply-form/reply-form.module.css';
import { alertChallengeVerificationFailed } from '../../lib/utils/challenge-utils';
import challengesStore from '../../hooks/use-challenges';
import challengesStore from '../../stores/use-challenges-store';
const { addChallenge } = challengesStore.getState();

View File

@@ -37,9 +37,9 @@ import {
isProfileUpvotedView,
isSettingsPlebbitOptionsView,
} from '../../lib/utils/view-utils';
import useNotFoundStore from '../../stores/use-not-found-store';
import useTheme from '../../hooks/use-theme';
import useWindowWidth from '../../hooks/use-window-width';
import { useNotFoundStore } from '../../views/not-found';
import styles from './header.module.css';
import SubscribeButton from '../subscribe-button';

View File

@@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next';
import { PublishCommentEditOptions, useComment, useEditedComment, usePublishCommentEdit } from '@plebbit/plebbit-react-hooks';
import styles from './edit-menu.module.css';
import { alertChallengeVerificationFailed } from '../../../../lib/utils/challenge-utils';
import challengesStore from '../../../../hooks/use-challenges';
import challengesStore from '../../../../stores/use-challenges-store';
const { addChallenge } = challengesStore.getState();

View File

@@ -4,7 +4,7 @@ import { Trans, useTranslation } from 'react-i18next';
import { PublishCommentEditOptions, useComment, useEditedComment, usePublishCommentEdit } from '@plebbit/plebbit-react-hooks';
import styles from './mod-menu.module.css';
import { alertChallengeVerificationFailed } from '../../../../lib/utils/challenge-utils';
import challengesStore from '../../../../hooks/use-challenges';
import challengesStore from '../../../../stores/use-challenges-store';
const { addChallenge } = challengesStore.getState();

View File

@@ -1,7 +1,7 @@
import { useMemo } from 'react';
import { ChallengeVerification, Comment, usePublishVote, useAccountVote } from '@plebbit/plebbit-react-hooks';
import { alertChallengeVerificationFailed } from '../lib/utils/challenge-utils';
import useChallengesStore from './use-challenges';
import useChallengesStore from '../stores/use-challenges-store';
const useDownvote = (comment: Comment): [boolean, () => void] => {
const { addChallenge } = useChallengesStore();

View File

@@ -1,67 +1,6 @@
import { useMemo } from 'react';
import { ChallengeVerification, Comment, PublishCommentOptions, usePublishComment } from '@plebbit/plebbit-react-hooks';
import { create } from 'zustand';
import useChallengesStore from './use-challenges';
import { alertChallengeVerificationFailed } from '../lib/utils/challenge-utils';
type SetReplyStoreData = {
subplebbitAddress: string;
parentCid: string;
content: string | undefined;
link: string | undefined;
spoiler: boolean;
};
type ReplyState = {
content: { [parentCid: string]: string | undefined };
link: { [parentCid: string]: string | undefined };
spoiler: { [parentCid: string]: boolean | undefined };
publishCommentOptions: PublishCommentOptions;
setReplyStore: (data: SetReplyStoreData) => void;
resetReplyStore: (parentCid: string) => void;
};
const { addChallenge } = useChallengesStore.getState();
const useReplyStore = create<ReplyState>((set) => ({
content: {},
link: {},
spoiler: {},
publishCommentOptions: {},
setReplyStore: (data: SetReplyStoreData) =>
set((state) => {
const { subplebbitAddress, parentCid, content, link, spoiler } = data;
const publishCommentOptions = {
subplebbitAddress,
parentCid,
content,
link,
spoiler,
onChallenge: (...args: any) => addChallenge(args),
onChallengeVerification: (challengeVerification: ChallengeVerification, comment: Comment) => {
alertChallengeVerificationFailed(challengeVerification, comment);
},
onError: (error: Error) => {
console.error(error);
alert(error.message);
},
};
return {
content: { ...state.content, [parentCid]: content },
link: { ...state.link, [parentCid]: link },
spoiler: { ...state.spoiler, [parentCid]: spoiler },
publishCommentOptions: { ...state.publishCommentOptions, [parentCid]: publishCommentOptions },
};
}),
resetReplyStore: (parentCid) =>
set((state) => ({
content: { ...state.content, [parentCid]: undefined },
link: { ...state.link, [parentCid]: undefined },
spoiler: { ...state.spoiler, [parentCid]: undefined },
publishCommentOptions: { ...state.publishCommentOptions, [parentCid]: undefined },
})),
}));
import { usePublishComment } from '@plebbit/plebbit-react-hooks';
import useReplyStore from '../stores/use-reply-store';
const useReply = ({ cid, subplebbitAddress }: { cid: string; subplebbitAddress: string }) => {
const parentCid = cid;

View File

@@ -1,17 +1,4 @@
import { create, StoreApi } from 'zustand';
interface ThemeState {
theme: string;
setTheme: (theme: string) => void;
}
const useThemeStore = create<ThemeState>((set: StoreApi<ThemeState>['setState']) => ({
theme: localStorage.getItem('theme') || 'light',
setTheme: (theme: string) => {
localStorage.setItem('theme', theme);
set({ theme });
},
}));
import useThemeStore from '../stores/use-theme-store';
const useTheme = (): [string, (theme: string) => void] => {
const { theme, setTheme } = useThemeStore();

View File

@@ -1,6 +1,6 @@
import { useMemo } from 'react';
import { ChallengeVerification, Comment, usePublishVote, useAccountVote } from '@plebbit/plebbit-react-hooks';
import useChallengesStore from './use-challenges';
import useChallengesStore from '../stores/use-challenges-store';
import { alertChallengeVerificationFailed } from '../lib/utils/challenge-utils';
const useUpvote = (comment: Comment): [boolean, () => void] => {

View File

@@ -0,0 +1,13 @@
import { create } from 'zustand';
interface NotFoundState {
isNotFound: boolean;
setNotFound: (isNotFound: boolean) => void;
}
export const useNotFoundStore = create<NotFoundState>((set) => ({
isNotFound: false,
setNotFound: (isNotFound: boolean) => set({ isNotFound }),
}));
export default useNotFoundStore;

View File

@@ -0,0 +1,66 @@
import { PublishCommentOptions } from '@plebbit/plebbit-react-hooks';
import { ChallengeVerification, Comment } from '@plebbit/plebbit-react-hooks';
import { create } from 'zustand';
import useChallengesStore from './use-challenges-store';
import { alertChallengeVerificationFailed } from '../lib/utils/challenge-utils';
type SetReplyStoreData = {
subplebbitAddress: string;
parentCid: string;
content: string | undefined;
link: string | undefined;
spoiler: boolean;
};
type ReplyState = {
content: { [parentCid: string]: string | undefined };
link: { [parentCid: string]: string | undefined };
spoiler: { [parentCid: string]: boolean | undefined };
publishCommentOptions: PublishCommentOptions;
setReplyStore: (data: SetReplyStoreData) => void;
resetReplyStore: (parentCid: string) => void;
};
const { addChallenge } = useChallengesStore.getState();
const useReplyStore = create<ReplyState>((set) => ({
content: {},
link: {},
spoiler: {},
publishCommentOptions: {},
setReplyStore: (data: SetReplyStoreData) =>
set((state) => {
const { subplebbitAddress, parentCid, content, link, spoiler } = data;
const publishCommentOptions = {
subplebbitAddress,
parentCid,
content,
link,
spoiler,
onChallenge: (...args: any) => addChallenge(args),
onChallengeVerification: (challengeVerification: ChallengeVerification, comment: Comment) => {
alertChallengeVerificationFailed(challengeVerification, comment);
},
onError: (error: Error) => {
console.error(error);
alert(error.message);
},
};
return {
content: { ...state.content, [parentCid]: content },
link: { ...state.link, [parentCid]: link },
spoiler: { ...state.spoiler, [parentCid]: spoiler },
publishCommentOptions: { ...state.publishCommentOptions, [parentCid]: publishCommentOptions },
};
}),
resetReplyStore: (parentCid) =>
set((state) => ({
content: { ...state.content, [parentCid]: undefined },
link: { ...state.link, [parentCid]: undefined },
spoiler: { ...state.spoiler, [parentCid]: undefined },
publishCommentOptions: { ...state.publishCommentOptions, [parentCid]: undefined },
})),
}));
export default useReplyStore;

View File

@@ -0,0 +1,50 @@
import { create } from 'zustand';
import challengesStore from './use-challenges-store';
import { PublishCommentOptions } from '@plebbit/plebbit-react-hooks';
import { alertChallengeVerificationFailed } from '../lib/utils/challenge-utils';
type SubmitState = {
subplebbitAddress: string | undefined;
title: string | undefined;
content: string | undefined;
link: string | undefined;
publishCommentOptions: PublishCommentOptions;
spoiler: boolean | undefined;
setSubmitStore: (data: Partial<SubmitState>) => void;
resetSubmitStore: () => void;
};
const { addChallenge } = challengesStore.getState();
const useSubmitStore = create<SubmitState>((set) => ({
subplebbitAddress: undefined,
title: undefined,
content: undefined,
link: undefined,
spoiler: undefined,
publishCommentOptions: {},
setSubmitStore: ({ subplebbitAddress, title, content, link, spoiler }) =>
set((state) => {
const nextState = { ...state };
if (subplebbitAddress !== undefined) nextState.subplebbitAddress = subplebbitAddress;
if (title !== undefined) nextState.title = title || undefined;
if (content !== undefined) nextState.content = content || undefined;
if (link !== undefined) nextState.link = link || undefined;
if (spoiler !== undefined) nextState.spoiler = spoiler || undefined;
nextState.publishCommentOptions = {
...nextState,
onChallenge: (...args: any) => addChallenge(args),
onChallengeVerification: alertChallengeVerificationFailed,
onError: (error: Error) => {
console.error(error);
let errorMessage = error.message;
alert(errorMessage);
},
};
return nextState;
}),
resetSubmitStore: () => set({ subplebbitAddress: undefined, title: undefined, content: undefined, link: undefined, spoiler: undefined, publishCommentOptions: {} }),
}));
export default useSubmitStore;

View File

@@ -0,0 +1,68 @@
import { PublishSubplebbitEditOptions } from '@plebbit/plebbit-react-hooks';
import { Roles } from '../lib/utils/user-utils';
import { create } from 'zustand';
export type SubplebbitSettingsState = {
challenges: any[] | undefined;
title: string | undefined;
description: string | undefined;
address: string | undefined;
suggested: any | undefined;
rules: string[] | undefined;
roles: Roles | undefined;
settings: any | undefined;
subplebbitAddress: string | undefined;
publishSubplebbitEditOptions: PublishSubplebbitEditOptions;
setSubplebbitSettingsStore: (data: Partial<SubplebbitSettingsState>) => void;
resetSubplebbitSettingsStore: () => void;
};
const useSubplebbitSettingsStore = create<SubplebbitSettingsState>((set) => ({
challenges: undefined,
title: undefined,
description: undefined,
address: undefined,
suggested: undefined,
rules: undefined,
roles: undefined,
settings: undefined,
subplebbitAddress: undefined,
publishSubplebbitEditOptions: {},
setSubplebbitSettingsStore: (props) =>
set((state) => {
const nextState = { ...state };
Object.entries(props).forEach(([key, value]) => {
if (value !== undefined) {
(nextState as any)[key] = value;
}
});
const editOptions: Partial<SubplebbitSettingsState> = {};
if (nextState.title !== undefined) editOptions.title = nextState.title;
if (nextState.description !== undefined) editOptions.description = nextState.description;
if (nextState.address !== undefined) editOptions.address = nextState.address;
if (nextState.suggested !== undefined) editOptions.suggested = nextState.suggested;
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;
nextState.publishSubplebbitEditOptions = editOptions;
return nextState;
}),
resetSubplebbitSettingsStore: () =>
set(() => {
return {
challenges: undefined,
title: undefined,
description: undefined,
address: undefined,
suggested: undefined,
rules: undefined,
roles: undefined,
settings: undefined,
subplebbitAddress: undefined,
publishSubplebbitEditOptions: {},
};
}),
}));
export default useSubplebbitSettingsStore;

View File

@@ -0,0 +1,16 @@
import { create, StoreApi } from 'zustand';
interface ThemeState {
theme: string;
setTheme: (theme: string) => void;
}
const useThemeStore = create<ThemeState>((set: StoreApi<ThemeState>['setState']) => ({
theme: localStorage.getItem('theme') || 'light',
setTheme: (theme: string) => {
localStorage.setItem('theme', theme);
set({ theme });
},
}));
export default useThemeStore;

View File

@@ -1 +1 @@
export { default, useNotFoundStore } from './not-found';
export { default } from './not-found';

View File

@@ -1,6 +1,6 @@
import { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { create } from 'zustand';
import useNotFoundStore from '../../stores/use-not-found-store';
import styles from './not-found.module.css';
const totalNotFoundImages = 2;
@@ -14,16 +14,6 @@ const NotFoundImage = () => {
return <img src={imagePath} alt='' />;
};
interface NotFoundState {
isNotFound: boolean;
setNotFound: (isNotFound: boolean) => void;
}
export const useNotFoundStore = create<NotFoundState>((set) => ({
isNotFound: false,
setNotFound: (isNotFound: boolean) => set({ isNotFound }),
}));
const NotFound = () => {
const { t } = useTranslation();
const setNotFound = useNotFoundStore((state) => state.setNotFound);

View File

@@ -3,6 +3,19 @@
color: var(--text);
}
.infobar {
box-sizing: border-box;
background-color: var(--background-orange);
border-color: var(--border-orange);
border-style: solid;
border-width: 1px;
margin: 0px 5px 5px 0px;
padding: 6px 10px 6px 10px;
color: var(--text);
word-wrap: break-word;
font-size: 14px;
}
h1 {
font-size: 18px;
font-weight: normal;

View File

@@ -1,62 +1,16 @@
import { ChangeEvent, useCallback, useEffect, useState } from 'react';
import { Link, useLocation, useNavigate, useParams } from 'react-router-dom';
import { PublishCommentOptions, useAccount, usePublishComment, useSubplebbit } from '@plebbit/plebbit-react-hooks';
import Plebbit from '@plebbit/plebbit-js/dist/browser/index.js';
import { Trans, useTranslation } from 'react-i18next';
import { create } from 'zustand';
import Plebbit from '@plebbit/plebbit-js/dist/browser/index.js';
import { useAccount, usePublishComment, useSubplebbit } from '@plebbit/plebbit-react-hooks';
import useSubmitStore from '../../stores/use-submit-store';
import { useDefaultSubplebbitAddresses } from '../../hooks/use-default-subplebbits';
import { alertChallengeVerificationFailed } from '../../lib/utils/challenge-utils';
import { getLinkMediaInfo } from '../../lib/utils/media-utils';
import { isValidURL } from '../../lib/utils/url-utils';
import { isSubmitView } from '../../lib/utils/view-utils';
import styles from './submit-page.module.css';
import challengesStore from '../../hooks/use-challenges';
import Embed from '../../components/post/embed';
import Markdown from '../../components/markdown';
type SubmitState = {
subplebbitAddress: string | undefined;
title: string | undefined;
content: string | undefined;
link: string | undefined;
publishCommentOptions: PublishCommentOptions;
spoiler: boolean | undefined;
setSubmitStore: (data: Partial<SubmitState>) => void;
resetSubmitStore: () => void;
};
const { addChallenge } = challengesStore.getState();
const useSubmitStore = create<SubmitState>((set) => ({
subplebbitAddress: undefined,
title: undefined,
content: undefined,
link: undefined,
spoiler: undefined,
publishCommentOptions: {},
setSubmitStore: ({ subplebbitAddress, title, content, link, spoiler }) =>
set((state) => {
const nextState = { ...state };
if (subplebbitAddress !== undefined) nextState.subplebbitAddress = subplebbitAddress;
if (title !== undefined) nextState.title = title || undefined;
if (content !== undefined) nextState.content = content || undefined;
if (link !== undefined) nextState.link = link || undefined;
if (spoiler !== undefined) nextState.spoiler = spoiler || undefined;
nextState.publishCommentOptions = {
...nextState,
onChallenge: (...args: any) => addChallenge(args),
onChallengeVerification: alertChallengeVerificationFailed,
onError: (error: Error) => {
console.error(error);
let errorMessage = error.message;
alert(errorMessage);
},
};
return nextState;
}),
resetSubmitStore: () => set({ subplebbitAddress: undefined, title: undefined, content: undefined, link: undefined, spoiler: undefined, publishCommentOptions: {} }),
}));
import styles from './submit-page.module.css';
const UrlField = () => {
const { t } = useTranslation();
@@ -133,6 +87,24 @@ const Submit = () => {
const { subscriptions } = account || {};
const defaultSubplebbitAddresses = useDefaultSubplebbitAddresses();
const [isOffline, setIsOffline] = useState(false);
useEffect(() => {
const checkOfflineStatus = () => {
if (subplebbit?.updatedAt !== undefined) {
setIsOffline(subplebbit.updatedAt < Date.now() / 1000 - 60 * 60);
} else {
setTimeout(() => {
setIsOffline(subplebbit?.updatedAt === undefined || subplebbit.updatedAt < Date.now() / 1000 - 60 * 60);
}, 5000);
}
};
if (subplebbitAddress) {
checkOfflineStatus();
}
}, [subplebbit?.updatedAt, subplebbitAddress]);
const onPublish = () => {
if (!title) {
alert(`Missing title`);
@@ -260,6 +232,7 @@ const Submit = () => {
return (
<div className={styles.content}>
{isOffline && <div className={styles.infobar}>test</div>}
<h1>
<Trans
i18nKey='submit_to'

View File

@@ -1,90 +1,18 @@
import { useEffect, useMemo, useRef, useState } from 'react';
import { useLocation, useNavigate, useParams } from 'react-router-dom';
import {
deleteSubplebbit,
PublishSubplebbitEditOptions,
Role,
useAccount,
useCreateSubplebbit,
useSubplebbit,
usePublishSubplebbitEdit,
} from '@plebbit/plebbit-react-hooks';
import { deleteSubplebbit, Role, useAccount, useCreateSubplebbit, useSubplebbit, usePublishSubplebbitEdit } from '@plebbit/plebbit-react-hooks';
import { Roles } from '../../lib/utils/user-utils';
import { useTranslation } from 'react-i18next';
import { create } from 'zustand';
import styles from './subplebbit-settings.module.css';
import { isValidURL } from '../../lib/utils/url-utils';
import { isCreateSubplebbitView, isSubplebbitSettingsView } from '../../lib/utils/view-utils';
import useSubplebbitSettingsStore, { SubplebbitSettingsState } from '../../stores/use-subplebbit-settings-store';
import useChallengesOptions from '../../hooks/use-challenges-options';
import useChallengeSettings from '../../hooks/use-challenge-settings';
import LoadingEllipsis from '../../components/loading-ellipsis';
import Markdown from '../../components/markdown';
import Sidebar from '../../components/sidebar';
import _ from 'lodash';
type SubplebbitSettingsState = {
challenges: any[] | undefined;
title: string | undefined;
description: string | undefined;
address: string | undefined;
suggested: any | undefined;
rules: string[] | undefined;
roles: Roles | undefined;
settings: any | undefined;
subplebbitAddress: string | undefined;
publishSubplebbitEditOptions: PublishSubplebbitEditOptions;
setSubplebbitSettingsStore: (data: Partial<SubplebbitSettingsState>) => void;
resetSubplebbitSettingsStore: () => void;
};
const useSubplebbitSettingsStore = create<SubplebbitSettingsState>((set) => ({
challenges: undefined,
title: undefined,
description: undefined,
address: undefined,
suggested: undefined,
rules: undefined,
roles: undefined,
settings: undefined,
subplebbitAddress: undefined,
publishSubplebbitEditOptions: {},
setSubplebbitSettingsStore: (props) =>
set((state) => {
const nextState = { ...state };
Object.entries(props).forEach(([key, value]) => {
if (value !== undefined) {
(nextState as any)[key] = value;
}
});
const editOptions: Partial<SubplebbitSettingsState> = {};
if (nextState.title !== undefined) editOptions.title = nextState.title;
if (nextState.description !== undefined) editOptions.description = nextState.description;
if (nextState.address !== undefined) editOptions.address = nextState.address;
if (nextState.suggested !== undefined) editOptions.suggested = nextState.suggested;
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;
nextState.publishSubplebbitEditOptions = editOptions;
return nextState;
}),
resetSubplebbitSettingsStore: () =>
set(() => {
return {
challenges: undefined,
title: undefined,
description: undefined,
address: undefined,
suggested: undefined,
rules: undefined,
roles: undefined,
settings: undefined,
subplebbitAddress: undefined,
publishSubplebbitEditOptions: {},
};
}),
}));
const Title = ({ isReadOnly = false }: { isReadOnly?: boolean }) => {
const { t } = useTranslation();
const { title, setSubplebbitSettingsStore } = useSubplebbitSettingsStore();