diff --git a/package.json b/package.json index 2aaf5ebe..1645bfee 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "dependencies": { "@capacitor/app": "1.1.1", "@floating-ui/react": "0.26.1", - "@plebbit/plebbit-react-hooks": "https://github.com/plebbit/plebbit-react-hooks.git#f0ae8cd285f282d82eafd290e3b73525faa8ec6b", + "@plebbit/plebbit-react-hooks": "https://github.com/plebbit/plebbit-react-hooks.git#a80ef4b155abf119e66c019576cbc1b338390e00", "@testing-library/jest-dom": "5.14.1", "@testing-library/react": "13.0.0", "@testing-library/user-event": "13.2.1", diff --git a/src/app.tsx b/src/app.tsx index ee561a73..8b1ea752 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -1,8 +1,6 @@ -import { useEffect } from 'react'; import { Outlet, Route, Routes, useLocation, useParams } from 'react-router-dom'; -import { isAllView, isHomeView, isSubscriptionsView } from './lib/utils/view-utils'; +import { isAllView, isSubscriptionsView } from './lib/utils/view-utils'; import useIsMobile from './hooks/use-is-mobile'; -import useTheme from './hooks/use-theme'; import styles from './app.module.css'; import Board from './views/board'; import Catalog from './views/catalog'; @@ -16,17 +14,19 @@ import ChallengeModal from './components/challenge-modal'; import PostForm from './components/post-form'; import SubplebbitStats from './components/subplebbit-stats'; import TopBar from './components/topbar'; +import { timeFilterNames } from './hooks/use-time-filter'; +import useTheme from './hooks/use-theme'; const BoardLayout = () => { - const { accountCommentIndex, subplebbitAddress } = useParams(); + const { accountCommentIndex, subplebbitAddress, timeFilterName } = useParams(); const location = useLocation(); const isMobile = useIsMobile(); - const isInAllView = isAllView(location.pathname); - const isInSubscriptionsView = isSubscriptionsView(location.pathname); + const isInAllView = isAllView(location.pathname, useParams()); + const isInSubscriptionsView = isSubscriptionsView(location.pathname, useParams()); const isValidAccountCommentIndex = !accountCommentIndex || (!isNaN(parseInt(accountCommentIndex)) && parseInt(accountCommentIndex) >= 0); - if (!isValidAccountCommentIndex) { + if (!isValidAccountCommentIndex || (timeFilterName && !timeFilterNames.includes(timeFilterName))) { return ; } @@ -56,28 +56,22 @@ const BoardLayout = () => { ); }; -const App = () => { - const location = useLocation(); - const isInHomeView = isHomeView(location.pathname); - const [theme] = useTheme(); +const GlobalLayout = () => { + useTheme(); - useEffect(() => { - document.body.classList.forEach((className) => document.body.classList.remove(className)); - const classToAdd = isInHomeView ? 'yotsuba' : theme; - document.body.classList.add(classToAdd); - }, [theme, isInHomeView]); - - const globalLayout = ( + return ( <> ); +}; +const App = () => { return (
- + }> } /> }> } /> diff --git a/src/components/board-buttons/board-buttons.tsx b/src/components/board-buttons/board-buttons.tsx index 73d9eb2d..3a83ccb9 100644 --- a/src/components/board-buttons/board-buttons.tsx +++ b/src/components/board-buttons/board-buttons.tsx @@ -144,11 +144,11 @@ export const TimeFilter = ({ isInAllView, isInCatalogView, isInSubscriptionsView export const MobileBoardButtons = () => { const params = useParams(); const location = useLocation(); - const isInAllView = isAllView(location.pathname); + const isInAllView = isAllView(location.pathname, params); const isInCatalogView = isCatalogView(location.pathname, params); const isInPendingPostPage = isPendingPostView(location.pathname, params); const isInPostView = isPostPageView(location.pathname, params); - const isInSubscriptionsView = isSubscriptionsView(location.pathname); + const isInSubscriptionsView = isSubscriptionsView(location.pathname, useParams()); const accountComment = useAccountComment({ commentIndex: params?.accountCommentIndex as any }); const subplebbitAddress = params?.subplebbitAddress || accountComment?.subplebbitAddress; @@ -190,10 +190,10 @@ export const DesktopBoardButtons = () => { const accountComment = useAccountComment({ commentIndex: params?.accountCommentIndex as any }); const subplebbitAddress = params?.subplebbitAddress || accountComment?.subplebbitAddress; const isInCatalogView = isCatalogView(location.pathname, params); - const isInAllView = isAllView(location.pathname); + const isInAllView = isAllView(location.pathname, params); const isInPendingPostPage = isPendingPostView(location.pathname, params); const isInPostView = isPostPageView(location.pathname, params); - const isInSubscriptionsView = isSubscriptionsView(location.pathname); + const isInSubscriptionsView = isSubscriptionsView(location.pathname, useParams()); return ( <> diff --git a/src/components/board-header/board-header.tsx b/src/components/board-header/board-header.tsx index 879a56ba..0227ac26 100644 --- a/src/components/board-header/board-header.tsx +++ b/src/components/board-header/board-header.tsx @@ -20,8 +20,8 @@ const BoardHeader = () => { const location = useLocation(); const params = useParams(); - const isInAllView = isAllView(location.pathname); - const isInSubscriptionsView = isSubscriptionsView(location.pathname); + const isInAllView = isAllView(location.pathname, params); + const isInSubscriptionsView = isSubscriptionsView(location.pathname, useParams()); const accountComment = useAccountComment({ commentIndex: params?.accountCommentIndex as any }); const subplebbitAddress = params?.subplebbitAddress || accountComment?.subplebbitAddress; diff --git a/src/components/catalog-row/catalog-row.tsx b/src/components/catalog-row/catalog-row.tsx index 4a00693c..5dacf149 100644 --- a/src/components/catalog-row/catalog-row.tsx +++ b/src/components/catalog-row/catalog-row.tsx @@ -1,7 +1,7 @@ import { useEffect, useRef, useState } from 'react'; import { createPortal } from 'react-dom'; import { useTranslation } from 'react-i18next'; -import { Link, useLocation } from 'react-router-dom'; +import { Link, useLocation, useParams } from 'react-router-dom'; import { Comment, useComment } from '@plebbit/plebbit-react-hooks'; import { useFloating, offset, shift, size, autoUpdate, Placement } from '@floating-ui/react'; import { getCommentMediaInfo, getHasThumbnail } from '../../lib/utils/media-utils'; @@ -106,7 +106,7 @@ const CatalogPost = ({ post }: { post: Comment }) => { const { hidden } = useHide({ cid }); const location = useLocation(); - const isInAllView = isAllView(location.pathname); + const isInAllView = isAllView(location.pathname, useParams()); const postLink = isInAllView && isDescription ? `/p/all/description` : `/p/${subplebbitAddress}/${isDescription ? 'description' : isRules ? 'rules' : `c/${cid}`}`; diff --git a/src/components/edit-menu/edit-menu.tsx b/src/components/edit-menu/edit-menu.tsx index df1fe233..d1b092b9 100644 --- a/src/components/edit-menu/edit-menu.tsx +++ b/src/components/edit-menu/edit-menu.tsx @@ -112,7 +112,6 @@ const EditMenu = ({ commentCid, isAccountMod, isAccountCommentAuthor, isCommentA const headingId = useId(); const _publishCommentEdit = async () => { - console.log('publishCommentEditOptions', publishCommentEditOptions); try { await publishCommentEdit(); } catch (error) { diff --git a/src/components/markdown/markdown.tsx b/src/components/markdown/markdown.tsx index 7bac056a..72b9fdcf 100644 --- a/src/components/markdown/markdown.tsx +++ b/src/components/markdown/markdown.tsx @@ -128,7 +128,7 @@ interface MarkdownProps { title?: string; } -const Markdown = ({ content, spoiler, title }: MarkdownProps) => { +const Markdown = ({ content, title }: MarkdownProps) => { const remarkPlugins: any[] = [[supersub]]; if (content && content.length <= MAX_LENGTH_FOR_GFM) { @@ -164,7 +164,7 @@ const Markdown = ({ content, spoiler, title }: MarkdownProps) => { remarkPlugins={remarkPlugins} rehypePlugins={[[rehypeSanitize, customSchema]]} components={{ - p: ({ children }) =>

{spoiler ? {children} : children}

, + p: ({ children }) =>

{children}

, img: ({ src }) => {src}, video: ({ src }) => {src}, iframe: ({ src }) => {src}, diff --git a/src/components/post-desktop/post-desktop.tsx b/src/components/post-desktop/post-desktop.tsx index 09b3071e..97c4fcc8 100644 --- a/src/components/post-desktop/post-desktop.tsx +++ b/src/components/post-desktop/post-desktop.tsx @@ -34,9 +34,9 @@ const PostInfo = ({ openReplyModal, post, roles, isHidden }: PostProps) => { const params = useParams(); const location = useLocation(); - const isInAllView = isAllView(location.pathname); + const isInAllView = isAllView(location.pathname, params); const isInPostView = isPostPageView(location.pathname, params); - const isInSubscriptionsView = isSubscriptionsView(location.pathname); + const isInSubscriptionsView = isSubscriptionsView(location.pathname, useParams()); const shortDisplayName = displayName?.trim().length > 20 ? displayName?.trim().slice(0, 20).trim() + '...' : displayName?.trim(); const authorRole = roles?.[address]?.role; diff --git a/src/components/post-desktop/post-menu-desktop/post-menu-desktop.tsx b/src/components/post-desktop/post-menu-desktop/post-menu-desktop.tsx index 80313368..e867d882 100644 --- a/src/components/post-desktop/post-menu-desktop/post-menu-desktop.tsx +++ b/src/components/post-desktop/post-menu-desktop/post-menu-desktop.tsx @@ -134,10 +134,10 @@ const PostMenuDesktop = ({ post }: { post: Comment }) => { const location = useLocation(); const params = useParams(); - const isInAllView = isAllView(location.pathname); + const isInAllView = isAllView(location.pathname, params); const isInCatalogView = isCatalogView(location.pathname, params); const isInPostPageView = isPostPageView(location.pathname, params); - const isInSubscriptionsView = isSubscriptionsView(location.pathname); + const isInSubscriptionsView = isSubscriptionsView(location.pathname, useParams()); const { refs, floatingStyles, context } = useFloating({ placement: 'bottom-start', diff --git a/src/components/post-form/post-form.tsx b/src/components/post-form/post-form.tsx index f9718be4..a66cb6f1 100644 --- a/src/components/post-form/post-form.tsx +++ b/src/components/post-form/post-form.tsx @@ -77,8 +77,8 @@ const PostFormTable = ({ closeForm }: { closeForm: () => void }) => { const subjectRef = useRef(null); const location = useLocation(); - const isInAllView = isAllView(location.pathname); - const isInSubscriptionsView = isSubscriptionsView(location.pathname); + const isInAllView = isAllView(location.pathname, useParams()); + const isInSubscriptionsView = isSubscriptionsView(location.pathname, useParams()); const subscriptions = account?.subscriptions || []; const defaultSubplebbitAddresses = useDefaultSubplebbitAddresses(); @@ -262,8 +262,8 @@ const PostForm = () => { const isInDescriptionView = isDescriptionView(location.pathname, params); const isInPostView = isPostPageView(location.pathname, params); const isInRulesView = isRulesView(location.pathname, params); - const isInAllView = isAllView(location.pathname); - const isInSubscriptionsView = isSubscriptionsView(location.pathname); + const isInAllView = isAllView(location.pathname, params); + const isInSubscriptionsView = isSubscriptionsView(location.pathname, useParams()); const comment = useComment({ commentCid: useParams().commentCid }); const { deleted, locked, removed } = comment || {}; diff --git a/src/components/post-mobile/post-mobile.tsx b/src/components/post-mobile/post-mobile.tsx index fd1d956e..3805e299 100644 --- a/src/components/post-mobile/post-mobile.tsx +++ b/src/components/post-mobile/post-mobile.tsx @@ -26,8 +26,8 @@ const PostInfoAndMedia = ({ openReplyModal, post, roles }: PostProps) => { const { address, displayName, shortAddress } = author || {}; const location = useLocation(); - const isInAllView = isAllView(location.pathname); - const isInSubscriptionsView = isSubscriptionsView(location.pathname); + const isInAllView = isAllView(location.pathname, useParams()); + const isInSubscriptionsView = isSubscriptionsView(location.pathname, useParams()); const authorRole = roles?.[address]?.role; const shortDisplayName = displayName?.trim().length > 20 ? displayName?.trim().slice(0, 20).trim() + '...' : displayName?.trim(); @@ -196,7 +196,7 @@ const PostMobile = ({ openReplyModal, post, roles, showAllReplies, showReplies = const { isDescription, isRules } = post || {}; // custom properties, not from api const params = useParams(); const location = useLocation(); - const isInAllView = isAllView(location.pathname); + const isInAllView = isAllView(location.pathname, params); const isInPendingPostView = isPendingPostView(location.pathname, params); const isInPostView = isPostPageView(location.pathname, params); const linksCount = useCountLinksInReplies(post); diff --git a/src/components/reply-modal/reply-modal.tsx b/src/components/reply-modal/reply-modal.tsx index b53a38bc..77a28ced 100644 --- a/src/components/reply-modal/reply-modal.tsx +++ b/src/components/reply-modal/reply-modal.tsx @@ -2,7 +2,7 @@ import { useEffect, useRef, useState } from 'react'; import { useLocation, useParams } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import Draggable from 'react-draggable'; -import { setAccount, useAccount, useSubplebbit } from '@plebbit/plebbit-react-hooks'; +import { setAccount, useAccount, useAuthorAddress, useSubplebbit } from '@plebbit/plebbit-react-hooks'; import Plebbit from '@plebbit/plebbit-js/dist/browser/index.js'; import { getFormattedTimeAgo } from '../../lib/utils/time-utils'; import { isValidURL } from '../../lib/utils/url-utils'; @@ -78,8 +78,8 @@ const ReplyModal = ({ closeModal, parentCid, scrollY }: ReplyModalProps) => { }, [parentCid]); const location = useLocation(); - const isInAllView = isAllView(location.pathname); - const isInSubscriptionsView = isSubscriptionsView(location.pathname); + const isInAllView = isAllView(location.pathname, useParams()); + const isInSubscriptionsView = isSubscriptionsView(location.pathname, useParams()); const subplebbit = useSubplebbit({ subplebbitAddress }); const { updatedAt } = subplebbit || {}; const isBoardOffline = subplebbit?.updatedAt && subplebbit.updatedAt < Date.now() / 1000 - 60 * 60; diff --git a/src/components/settings-modal/interface-settings/interface-settings.tsx b/src/components/settings-modal/interface-settings/interface-settings.tsx index 70502659..cf9494eb 100644 --- a/src/components/settings-modal/interface-settings/interface-settings.tsx +++ b/src/components/settings-modal/interface-settings/interface-settings.tsx @@ -65,8 +65,12 @@ const CheckForUpdates = () => { const Style = () => { const [theme, setTheme] = useTheme(); + const handleThemeChange = (e: React.ChangeEvent) => { + setTheme(e.target.value); + }; + return ( - diff --git a/src/components/subplebbit-description/subplebbit-description.tsx b/src/components/subplebbit-description/subplebbit-description.tsx index 4c3c8015..654cc4a3 100644 --- a/src/components/subplebbit-description/subplebbit-description.tsx +++ b/src/components/subplebbit-description/subplebbit-description.tsx @@ -2,7 +2,7 @@ import { Post } from '../../views/post'; import { useTranslation } from 'react-i18next'; import { isAllView } from '../../lib/utils/view-utils'; import { useMultisubMetadata } from '../../hooks/use-default-subplebbits'; -import { useLocation } from 'react-router-dom'; +import { useLocation, useParams } from 'react-router-dom'; interface DescriptionPostProps { avatarUrl?: string; @@ -16,7 +16,7 @@ interface DescriptionPostProps { const SubplebbitDescription = ({ avatarUrl, createdAt, description, shortAddress, subplebbitAddress, title }: DescriptionPostProps) => { const { t } = useTranslation(); const location = useLocation(); - const isInAllView = isAllView(location.pathname); + const isInAllView = isAllView(location.pathname, useParams()); const multisubMetadata = useMultisubMetadata(); const post = { diff --git a/src/components/topbar/topbar.tsx b/src/components/topbar/topbar.tsx index 1baf147d..bc611e16 100644 --- a/src/components/topbar/topbar.tsx +++ b/src/components/topbar/topbar.tsx @@ -104,9 +104,9 @@ const TopBarMobile = ({ subplebbitAddress }: { subplebbitAddress: string }) => { const location = useLocation(); const params = useParams(); - const isInAllView = isAllView(location.pathname); + const isInAllView = isAllView(location.pathname, params); const isInCatalogView = isCatalogView(location.pathname, params); - const isInSubscriptionsView = isSubscriptionsView(location.pathname); + const isInSubscriptionsView = isSubscriptionsView(location.pathname, useParams()); const selectValue = isInAllView ? 'all' : isInSubscriptionsView ? 'subscriptions' : subplebbitAddress; const boardSelect = ( diff --git a/src/hooks/use-theme.ts b/src/hooks/use-theme.ts index afe3047e..b900c67d 100644 --- a/src/hooks/use-theme.ts +++ b/src/hooks/use-theme.ts @@ -1,8 +1,63 @@ +import { useState, useMemo } from 'react'; +import { useLocation, useParams } from 'react-router-dom'; import useThemeStore from '../stores/use-theme-store'; +import useDefaultSubplebbits from './use-default-subplebbits'; +import { isAllView, isHomeView, isNotFoundView, isSubscriptionsView } from '../lib/utils/view-utils'; +import { nsfwTags } from '../views/home/home'; const useTheme = (): [string, (theme: string) => void] => { - const { theme, setTheme } = useThemeStore(); - return [theme, setTheme]; + const location = useLocation(); + const { subplebbitAddress } = useParams<{ subplebbitAddress: string }>(); + const getTheme = useThemeStore((state) => state.getTheme); + const setThemeStore = useThemeStore((state) => state.setTheme); + const subplebbits = useDefaultSubplebbits(); + const params = useParams(); + const isInHomeView = isHomeView(location.pathname); + const isInNotFoundView = isNotFoundView(location.pathname, params); + const isInAllView = isAllView(location.pathname, params); + const isInSubscriptionsView = isSubscriptionsView(location.pathname, params); + + const initialTheme = useMemo(() => { + if (isInAllView || isInSubscriptionsView) { + const userTheme = getTheme(isInAllView ? 'all' : 'subscriptions'); + return userTheme || 'yotsuba-b'; + } else if (isInHomeView || isInNotFoundView) { + return 'yotsuba'; + } else if (subplebbitAddress) { + const userTheme = getTheme(subplebbitAddress); + if (userTheme) { + return userTheme; + } + const subplebbit = subplebbits.find((s) => s.address === subplebbitAddress); + if (subplebbit && subplebbit.tags && subplebbit.tags.some((tag) => nsfwTags.includes(tag))) { + return 'yotsuba'; + } + return 'yotsuba-b'; + } + return 'yotsuba'; + }, [location.pathname, subplebbitAddress, subplebbits, getTheme]); + + const [theme, setLocalTheme] = useState(initialTheme); + + useMemo(() => { + document.body.classList.remove('yotsuba', 'yotsuba-b', 'futaba', 'burichan', 'tomorrow', 'photon'); + document.body.classList.add(initialTheme); + }, [initialTheme]); + + const setSubplebbitTheme = (newTheme: string) => { + if (subplebbitAddress) { + setThemeStore(subplebbitAddress, newTheme); + } else if (isInAllView) { + setThemeStore('all', newTheme); + } else if (isInSubscriptionsView) { + setThemeStore('subscriptions', newTheme); + } + setLocalTheme(newTheme); + document.body.classList.remove('yotsuba', 'yotsuba-b', 'futaba', 'burichan', 'tomorrow', 'photon'); + document.body.classList.add(newTheme); + }; + + return [theme, setSubplebbitTheme]; }; export default useTheme; diff --git a/src/hooks/use-time-filter.js b/src/hooks/use-time-filter.js index 7ff81fba..62b0a82f 100644 --- a/src/hooks/use-time-filter.js +++ b/src/hooks/use-time-filter.js @@ -40,7 +40,7 @@ if (secondsSinceLastVisit > 30 * day) { timeFilterNamesToSeconds[lastVisitTimeFilterName] = timeFilterNamesToSeconds['24h']; } -const timeFilterNames = [lastVisitTimeFilterName, '1h', '12h', '24h', '48h', 'week', 'month', 'year', 'all']; +export const timeFilterNames = [lastVisitTimeFilterName, '1h', '12h', '24h', '48h', 'week', 'month', 'year', 'all']; const useTimeFilter = () => { const params = useParams(); diff --git a/src/lib/utils/view-utils.ts b/src/lib/utils/view-utils.ts index cd580663..1954f339 100644 --- a/src/lib/utils/view-utils.ts +++ b/src/lib/utils/view-utils.ts @@ -1,3 +1,5 @@ +import { timeFilterNames } from '../../hooks/use-time-filter'; + export type ParamsType = { accountCommentIndex?: string; commentCid?: string; @@ -5,8 +7,25 @@ export type ParamsType = { timeFilterName?: string; }; -export const isAllView = (pathname: string): boolean => { - return pathname.startsWith('/p/all'); +export const isAllView = (pathname: string, params: ParamsType): boolean => { + const { timeFilterName } = params; + + if (timeFilterName && !timeFilterNames.includes(timeFilterName)) { + return false; + } + + return ( + pathname === '/p/all' || + pathname === '/p/all/settings' || + pathname === `/p/all/${timeFilterName}` || + pathname === `/p/all/${timeFilterName}/settings` || + pathname === '/p/all/catalog' || + pathname === '/p/all/catalog/settings' || + pathname === `/p/all/catalog/${timeFilterName}` || + pathname === `/p/all/catalog/${timeFilterName}/settings` || + pathname === '/p/all/description' || + pathname === '/p/all/description/settings' + ); }; export const isBoardView = (pathname: string, params: ParamsType): boolean => { @@ -68,19 +87,31 @@ export const isSettingsView = (pathname: string, params: ParamsType): boolean => ); }; -export const isSubscriptionsView = (pathname: string): boolean => { - return pathname.startsWith('/p/subscriptions'); +export const isSubscriptionsView = (pathname: string, params: ParamsType): boolean => { + const { timeFilterName } = params; + return ( + pathname === '/p/subscriptions' || + pathname === '/p/subscriptions/settings' || + pathname === `/p/subscriptions/${timeFilterName}` || + pathname === `/p/subscriptions/${timeFilterName}/settings` || + pathname === '/p/subscriptions/catalog' || + pathname === '/p/subscriptions/catalog/settings' || + pathname === `/p/subscriptions/catalog/${timeFilterName}` || + pathname === `/p/subscriptions/catalog/${timeFilterName}/settings` + ); }; export const isNotFoundView = (pathname: string, params: ParamsType): boolean => { return ( - !isAllView(pathname) && + !isAllView(pathname, params) && !isBoardView(pathname, params) && !isCatalogView(pathname, params) && !isDescriptionView(pathname, params) && !isHomeView(pathname) && !isPendingPostView(pathname, params) && !isPostPageView(pathname, params) && - !isRulesView(pathname, params) + !isRulesView(pathname, params) && + !isSettingsView(pathname, params) && + !isSubscriptionsView(pathname, params) ); }; diff --git a/src/stores/use-theme-store.ts b/src/stores/use-theme-store.ts index b3e416cf..d20d9609 100644 --- a/src/stores/use-theme-store.ts +++ b/src/stores/use-theme-store.ts @@ -1,16 +1,40 @@ import { create, StoreApi } from 'zustand'; +import localForageLru from '@plebbit/plebbit-react-hooks/dist/lib/localforage-lru/index.js'; interface ThemeState { - theme: string; - setTheme: (theme: string) => void; + themes: Record; + setTheme: (subplebbitAddress: string, theme: string) => void; + getTheme: (subplebbitAddress: string) => string | null; + loadThemes: () => void; } -const useThemeStore = create((set: StoreApi['setState']) => ({ - theme: localStorage.getItem('theme') || 'yotsuba', - setTheme: (theme: string) => { - localStorage.setItem('theme', theme); - set({ theme }); +const themeStore = localForageLru.createInstance({ + name: 'themeStore', + size: 1000, +}); + +const useThemeStore = create((set: StoreApi['setState'], get: StoreApi['getState']) => ({ + themes: {}, + setTheme: async (subplebbitAddress: string, theme: string) => { + const currentThemes = get().themes; + const updatedThemes = { ...currentThemes, [subplebbitAddress]: theme }; + await themeStore.setItem(subplebbitAddress, theme); + set({ themes: updatedThemes }); + }, + getTheme: (subplebbitAddress: string) => { + const currentThemes = get().themes; + return currentThemes[subplebbitAddress] || null; + }, + loadThemes: async () => { + const entries: [string, string][] = await themeStore.entries(); + const themes: Record = {}; + entries.forEach(([key, value]) => { + themes[key] = value; + }); + set({ themes }); }, })); +useThemeStore.getState().loadThemes(); + export default useThemeStore; diff --git a/src/views/board/board.tsx b/src/views/board/board.tsx index f5e77894..12f356db 100644 --- a/src/views/board/board.tsx +++ b/src/views/board/board.tsx @@ -25,12 +25,12 @@ const Board = () => { const location = useLocation(); const { subplebbitAddress } = useParams<{ subplebbitAddress: string }>(); - const isInAllView = isAllView(location.pathname); + const isInAllView = isAllView(location.pathname, useParams()); const defaultSubplebbitAddresses = useDefaultSubplebbitAddresses(); const account = useAccount(); const subscriptions = account?.subscriptions; - const isInSubscriptionsView = isSubscriptionsView(location.pathname); + const isInSubscriptionsView = isSubscriptionsView(location.pathname, useParams()); const subplebbitAddresses = useMemo(() => { if (isInAllView) { diff --git a/src/views/catalog/catalog-filters/catalog-filters.tsx b/src/views/catalog/catalog-filters/catalog-filters.tsx index 10e30005..0bd6da96 100644 --- a/src/views/catalog/catalog-filters/catalog-filters.tsx +++ b/src/views/catalog/catalog-filters/catalog-filters.tsx @@ -9,8 +9,9 @@ const FiltersModal = ({ closeModal }: { closeModal: () => void }) => { const { t } = useTranslation(); const { showAdultBoards, setShowAdultBoards, showGoreBoards, setShowGoreBoards, showTextOnlyThreads, setShowTextOnlyThreads } = useCatalogFiltersStore(); const location = useLocation(); - const isInCatalogView = isCatalogView(location.pathname, useParams()); - const isInAllView = isAllView(location.pathname); + const params = useParams(); + const isInCatalogView = isCatalogView(location.pathname, params); + const isInAllView = isAllView(location.pathname, params); return ( <> diff --git a/src/views/catalog/catalog.tsx b/src/views/catalog/catalog.tsx index 11da68b4..818a98ae 100644 --- a/src/views/catalog/catalog.tsx +++ b/src/views/catalog/catalog.tsx @@ -27,7 +27,7 @@ const useFeedRows = (columnCount: number, feed: any, isFeedLoaded: boolean, subp const { avatarUrl } = suggested || {}; const location = useLocation(); - const isInAllView = isAllView(location.pathname); + const isInAllView = isAllView(location.pathname, useParams()); const multisub = useMultisubMetadata(); const feedWithDescriptionAndRules = useMemo(() => { @@ -90,13 +90,13 @@ const Catalog = () => { const location = useLocation(); const { subplebbitAddress } = useParams<{ subplebbitAddress: string }>(); - const isInAllView = isAllView(location.pathname); + const isInAllView = isAllView(location.pathname, useParams()); const defaultSubplebbits = useDefaultSubplebbits(); const { showAdultBoards, showGoreBoards } = useCatalogFiltersStore(); const account = useAccount(); const subscriptions = account?.subscriptions; - const isInSubscriptionsView = isSubscriptionsView(location.pathname); + const isInSubscriptionsView = isSubscriptionsView(location.pathname, useParams()); const subplebbitAddresses = useMemo(() => { const filteredDefaultSubplebbits = defaultSubplebbits @@ -121,10 +121,6 @@ const Catalog = () => { return [subplebbitAddress]; }, [isInAllView, isInSubscriptionsView, subplebbitAddress, defaultSubplebbits, subscriptions, showAdultBoards, showGoreBoards]); - useEffect(() => { - console.log(showAdultBoards, showGoreBoards); - }, [showAdultBoards, showGoreBoards]); - const columnCount = Math.floor(useWindowWidth() / columnWidth); // postPerPage based on columnCount for optimized feed, dont change value after first render // eslint-disable-next-line diff --git a/src/views/not-found/not-found.tsx b/src/views/not-found/not-found.tsx index 7e206fe8..df52dfcd 100644 --- a/src/views/not-found/not-found.tsx +++ b/src/views/not-found/not-found.tsx @@ -1,9 +1,8 @@ -import { useEffect, useState, useRef } from 'react'; +import { useState } from 'react'; import { Link, useParams } from 'react-router-dom'; import { HomeLogo } from '../home'; import styles from './not-found.module.css'; import Plebbit from '@plebbit/plebbit-js/dist/browser/index.js'; -import useTheme from '../../hooks/use-theme'; const totalNotFoundImages = 2; @@ -20,22 +19,6 @@ const NotFound = () => { const { subplebbitAddress } = useParams(); const isValidSubplebbitAddress = !subplebbitAddress || subplebbitAddress.includes('.') || /^12D3K[a-zA-Z0-9]{44}$/.test(subplebbitAddress); - const [theme, setTheme] = useTheme(); - const previousThemeRef = useRef(theme); - - useEffect(() => { - if (theme !== 'yotsuba') { - previousThemeRef.current = theme; - setTheme('yotsuba'); - } - - return () => { - if (theme === 'yotsuba') { - setTheme(previousThemeRef.current); - } - }; - }, [theme, setTheme]); - return (
diff --git a/yarn.lock b/yarn.lock index 06c38a28..7d346e41 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3319,6 +3319,68 @@ uuid "9.0.1" viem "1.5.2" +"@plebbit/plebbit-js@https://github.com/plebbit/plebbit-js.git#e44773dc4bb20b5d886699e229c0efc997842d79": + version "0.0.3" + resolved "https://github.com/plebbit/plebbit-js.git#e44773dc4bb20b5d886699e229c0efc997842d79" + dependencies: + "@bonfida/spl-name-service" "2.4.2" + "@chainsafe/libp2p-gossipsub" "12.0.0" + "@chainsafe/libp2p-noise" "15.0.0" + "@chainsafe/libp2p-yamux" "6.0.2" + "@keyv/sqlite" "3.6.7" + "@libp2p/autonat" "1.0.12" + "@libp2p/bootstrap" "10.0.15" + "@libp2p/circuit-relay-v2" "^1.0.15" + "@libp2p/identify" "1.0.14" + "@libp2p/kad-dht" "12.0.7" + "@libp2p/mplex" "10.0.15" + "@libp2p/peer-id-factory" "4.0.6" + "@libp2p/webrtc" "4.0.19" + "@libp2p/webtransport" "4.0.19" + "@plebbit/plebbit-logger" "github:plebbit/plebbit-logger#355a96d7659ed820047980049dfa627d30d83a69" + "@plebbit/proper-lockfile" "github:plebbit/node-proper-lockfile#7fd6332117340c1d3d98dd0afee2d31cc06f72b8" + "@types/proper-lockfile" "4.1.2" + "@types/uuid" "8.3.4" + assert "2.1.0" + better-sqlite3 "9.3.0" + buffer "6.0.3" + captcha-canvas "3.2.1" + cbor "9.0.1" + debounce "1.2.1" + err-code "3.0.1" + ethers "6.10.0" + ext-name "5.0.0" + file-type "16.5.4" + hpagent "1.2.0" + jose "4.11.0" + js-sha256 "0.9.0" + js-sha512 "0.9.0" + keyv "4.5.4" + knex "3.1.0" + kubo-rpc-client "4.1.1" + libp2p "1.2.1" + libp2p-crypto "0.21.2" + limiter-es6-compat "2.1.2" + localforage "1.10.0" + lru-cache "10.1.0" + open-graph-scraper "6.3.3" + p-limit "4.0.0" + p-timeout "6.1.2" + peer-id "0.16.0" + probe-image-size "7.2.3" + remeda "1.57.0" + retry "0.13.1" + rpc-websockets "7.10.0" + safe-stable-stringify "2.4.3" + sha1-uint8array "0.10.7" + skia-canvas "1.0.0" + tiny-typed-emitter "2.1.0" + tinycache "1.1.2" + ts-custom-error "3.3.1" + typestub-ipfs-only-hash "4.0.0" + uuid "9.0.1" + viem "1.5.2" + "@plebbit/plebbit-logger@github:plebbit/plebbit-logger#355a96d7659ed820047980049dfa627d30d83a69": version "0.0.1" uid "355a96d7659ed820047980049dfa627d30d83a69" @@ -3332,11 +3394,11 @@ dependencies: debug "4.3.4" -"@plebbit/plebbit-react-hooks@https://github.com/plebbit/plebbit-react-hooks.git#d7fa27920f8ec21c9fa08bc216054083e1d59fc0": +"@plebbit/plebbit-react-hooks@https://github.com/plebbit/plebbit-react-hooks.git#a80ef4b155abf119e66c019576cbc1b338390e00": version "0.0.1" - resolved "https://github.com/plebbit/plebbit-react-hooks.git#d7fa27920f8ec21c9fa08bc216054083e1d59fc0" + resolved "https://github.com/plebbit/plebbit-react-hooks.git#a80ef4b155abf119e66c019576cbc1b338390e00" dependencies: - "@plebbit/plebbit-js" "https://github.com/plebbit/plebbit-js.git#b6f43c4b639b57622318c46a2e46792ae5fb01c3" + "@plebbit/plebbit-js" "https://github.com/plebbit/plebbit-js.git#e44773dc4bb20b5d886699e229c0efc997842d79" "@plebbit/plebbit-logger" "https://github.com/plebbit/plebbit-logger.git" assert "2.0.0" ethers "5.6.9"