/ src / hooks / use-theme.ts
use-theme.ts
 1  import { useState, useEffect, useCallback } from 'react';
 2  import { useLocation, useParams } from 'react-router-dom';
 3  import { isAllView, isSubscriptionsView } from '../lib/utils/view-utils';
 4  import useThemeStore from '../stores/use-theme-store';
 5  import useDefaultSubplebbits from './use-default-subplebbits';
 6  import useInitialTheme from './use-initial-theme';
 7  import { nsfwTags } from '../views/home/home';
 8  import { useAccountComment } from '@plebbit/plebbit-react-hooks';
 9  
10  const themeClasses = ['yotsuba', 'yotsuba-b', 'futaba', 'burichan', 'tomorrow', 'photon'];
11  
12  const updateThemeClass = (newTheme: string) => {
13    document.body.classList.remove(...themeClasses);
14    if (newTheme) {
15      document.body.classList.add(newTheme);
16    }
17  };
18  
19  const useTheme = (): [string, (theme: string) => void] => {
20    const location = useLocation();
21    const params = useParams<{ subplebbitAddress: string }>();
22    const pendingPostParams = useParams<{ accountCommentIndex?: string }>();
23    const pendingPostCommentIndex = pendingPostParams?.accountCommentIndex ? parseInt(pendingPostParams.accountCommentIndex) : undefined;
24    const pendingPost = useAccountComment({ commentIndex: pendingPostCommentIndex });
25    const pendingPostSubplebbitAddress = pendingPost?.subplebbitAddress;
26  
27    const setThemeStore = useThemeStore((state) => state.setTheme);
28    const getTheme = useThemeStore((state) => state.getTheme);
29    const loadThemes = useThemeStore((state) => state.loadThemes);
30    const subplebbits = useDefaultSubplebbits();
31  
32    const initialTheme = useInitialTheme(pendingPostSubplebbitAddress);
33    const [currentTheme, setCurrentTheme] = useState(initialTheme);
34  
35    const getCurrentTheme = useCallback(() => {
36      const subplebbitAddress = params?.subplebbitAddress || pendingPostSubplebbitAddress;
37      const isInAllView = isAllView(location.pathname, params);
38      const isInSubscriptionsView = isSubscriptionsView(location.pathname, params);
39  
40      let storedTheme = null;
41      if (isInAllView || isInSubscriptionsView) {
42        storedTheme = getTheme('sfw', false);
43      } else if (subplebbitAddress) {
44        const subplebbit = subplebbits.find((s) => s.address === subplebbitAddress);
45        if (subplebbit && subplebbit.tags && subplebbit.tags.some((tag) => nsfwTags.includes(tag))) {
46          storedTheme = getTheme('nsfw', false);
47        } else {
48          storedTheme = getTheme('sfw', false);
49        }
50      }
51  
52      return storedTheme || initialTheme;
53    }, [location.pathname, params, getTheme, subplebbits, initialTheme, pendingPostSubplebbitAddress]);
54  
55    useEffect(() => {
56      const newTheme = getCurrentTheme();
57      if (newTheme !== currentTheme) {
58        setCurrentTheme(newTheme);
59        updateThemeClass(newTheme);
60      }
61    }, [getCurrentTheme, currentTheme]);
62  
63    useEffect(() => {
64      loadThemes();
65    }, [loadThemes]);
66  
67    const setSubplebbitTheme = useCallback(
68      async (newTheme: string) => {
69        const subplebbitAddress = params?.subplebbitAddress || pendingPostSubplebbitAddress;
70        const isInAllView = isAllView(location.pathname, params);
71        const isInSubscriptionsView = isSubscriptionsView(location.pathname, params);
72  
73        if (isInAllView || isInSubscriptionsView) {
74          await setThemeStore('sfw', newTheme);
75        } else if (subplebbitAddress) {
76          const subplebbit = subplebbits.find((s) => s.address === subplebbitAddress);
77          if (subplebbit && subplebbit.tags && subplebbit.tags.some((tag) => nsfwTags.includes(tag))) {
78            await setThemeStore('nsfw', newTheme);
79          } else {
80            await setThemeStore('sfw', newTheme);
81          }
82        }
83  
84        setCurrentTheme(newTheme);
85        updateThemeClass(newTheme);
86      },
87      [location.pathname, params, setThemeStore, subplebbits, pendingPostSubplebbitAddress],
88    );
89  
90    return [currentTheme, setSubplebbitTheme];
91  };
92  
93  export default useTheme;