@@ -25,146 +25,176 @@ import { FooterGroup } from './components/FooterGroup'
2525import { FooterLink } from './components/FooterLink'
2626import { LinkList } from './components/LinkList'
2727import { Search } from './components/Search'
28- import { links } from './links'
29- import {
30- getThemeStateSetting ,
31- setThemeStateSetting
32- } from './services/localStorageService'
3328import {
3429 AppMode ,
35- setMode ,
36- toggleMode ,
37- useCurrentMode
38- } from './stores/currentModeStore'
39- import { HiddenLinks , useHiddenLinks } from './stores/hiddenLinksStore'
30+ CurrentModeContext ,
31+ CurrentModeContextValue ,
32+ useCurrentModeContextValue
33+ } from './contexts/currentModeContext'
34+ import {
35+ HiddenLinksContext ,
36+ useHiddenLinksContextValue
37+ } from './contexts/hiddenLinksContext'
38+ import { links } from './links'
39+ import {
40+ loadThemeSetting ,
41+ saveThemeSetting
42+ } from './services/localStorage/values/themeSetting'
4043
4144export const WebdevHome : FC = ( ) => {
42- const { mode } = useCurrentMode ( )
43- const { handleCustomizeAction, hiddenLinks } = useCustomizeMode ( )
44- const { handleSearchAction, searchTerm, setSearchTerm } = useSearchMode ( )
45- const { themeSwitcherIcon, handleThemeSwitcherAction } = useThemeSwitcher ( )
45+ const currentModeContextValue = useCurrentModeContextValue ( )
46+ const hiddenLinksContextValue = useHiddenLinksContextValue ( )
47+
48+ const customizeMode = useCustomizeMode ( { currentModeContextValue } )
49+ const searchMode = useSearchMode ( { currentModeContextValue } )
50+ const themeSwitcher = useThemeSwitcher ( )
51+
52+ const { isCurrentMode } = currentModeContextValue
53+ const { hiddenLinks } = hiddenLinksContextValue
4654
4755 return (
48- < div className = "app" >
49- < AppHeader />
50-
51- < AppActions >
52- < AppAction
53- icon = { mdiMagnify }
54- action = { handleSearchAction }
55- active = { mode === AppMode . search }
56- />
57- < AppAction
58- icon = { themeSwitcherIcon }
59- action = { handleThemeSwitcherAction }
60- active = { false }
61- />
62- < AppAction
63- icon = { mdiFormatListChecks }
64- action = { handleCustomizeAction }
65- active = { mode === AppMode . customize }
66- />
67- </ AppActions >
68-
69- { mode === AppMode . default || mode === AppMode . customize ? (
70- < AppContent >
71- < LinkList links = { links . items } hiddenLinks = { hiddenLinks . links } />
72- </ AppContent >
73- ) : (
74- < Search searchTerm = { searchTerm } setSearchTerm = { setSearchTerm } />
75- ) }
76-
77- < AppFooter >
78- < FooterGroup title = { 'WebdevHome v' + version } >
79- < FooterLink
80- text = "Changelog"
81- url = "https://github.com/webdevhome/webdevhome.github.io/releases"
82- />
83- < FooterLink
84- text = "GitHub"
85- url = "https://github.com/webdevhome/webdevhome.github.io"
86- />
87- </ FooterGroup >
88-
89- < FooterDivider />
90-
91- < FooterGroup title = "Icons" >
92- < FooterLink
93- text = "Material Design Icons"
94- url = "https://materialdesignicons.com"
95- />
96- < FooterLink text = "Simple Icons" url = "https://simpleicons.org/" />
97- </ FooterGroup >
98- </ AppFooter >
99- </ div >
56+ < CurrentModeContext . Provider value = { currentModeContextValue } >
57+ < HiddenLinksContext . Provider value = { hiddenLinksContextValue } >
58+ < div className = "app" >
59+ < AppHeader />
60+
61+ < AppActions >
62+ < AppAction
63+ icon = { mdiMagnify }
64+ action = { searchMode . handleSearchAction }
65+ active = { isCurrentMode ( AppMode . search ) }
66+ />
67+ < AppAction
68+ icon = { themeSwitcher . icon }
69+ action = { themeSwitcher . switchTheme }
70+ active = { false }
71+ />
72+ < AppAction
73+ icon = { mdiFormatListChecks }
74+ action = { customizeMode . handleCustomizeAction }
75+ active = { isCurrentMode ( AppMode . customize ) }
76+ />
77+ </ AppActions >
78+
79+ { isCurrentMode ( AppMode . default , AppMode . customize ) ? (
80+ < AppContent >
81+ < LinkList links = { links . items } hiddenLinks = { hiddenLinks } />
82+ </ AppContent >
83+ ) : (
84+ < Search
85+ searchTerm = { searchMode . searchTerm }
86+ setSearchTerm = { searchMode . setSearchTerm }
87+ />
88+ ) }
89+
90+ < AppFooter >
91+ < FooterGroup title = { 'WebdevHome v' + version } >
92+ < FooterLink
93+ text = "Changelog"
94+ url = "https://github.com/webdevhome/webdevhome.github.io/releases"
95+ />
96+ < FooterLink
97+ text = "GitHub"
98+ url = "https://github.com/webdevhome/webdevhome.github.io"
99+ />
100+ </ FooterGroup >
101+
102+ < FooterDivider />
103+
104+ < FooterGroup title = "Icons" >
105+ < FooterLink
106+ text = "Material Design Icons"
107+ url = "https://materialdesignicons.com"
108+ />
109+ < FooterLink text = "Simple Icons" url = "https://simpleicons.org/" />
110+ </ FooterGroup >
111+ </ AppFooter >
112+ </ div >
113+ </ HiddenLinksContext . Provider >
114+ </ CurrentModeContext . Provider >
100115 )
101116}
102117
103118// #region customize feature
119+ interface UseCustomizeModeParams {
120+ currentModeContextValue : CurrentModeContextValue
121+ }
122+
104123interface UseCustomizeModeReturn {
105- hiddenLinks : HiddenLinks
106124 handleCustomizeAction : ( ) => void
107125}
108126
109- function useCustomizeMode ( ) : UseCustomizeModeReturn {
110- const hiddenLinks = useHiddenLinks ( )
111- const { mode } = useCurrentMode ( )
127+ function useCustomizeMode ( {
128+ currentModeContextValue,
129+ } : UseCustomizeModeParams ) : UseCustomizeModeReturn {
130+ const { isCurrentMode, setCurrentMode, toggleMode } = currentModeContextValue
112131
113132 useEffect ( ( ) => {
114133 document . addEventListener ( 'keydown' , handleGlobalKeydown )
115134
116135 function handleGlobalKeydown ( event : KeyboardEvent ) : void {
117- if ( event . key === 'Escape' && mode === AppMode . customize ) {
118- setMode ( AppMode . default )
136+ if ( event . key === 'Escape' && isCurrentMode ( AppMode . customize ) ) {
137+ setCurrentMode ( AppMode . default )
119138 }
120139 }
121140
122141 return ( ) => {
123142 document . removeEventListener ( 'keydown' , handleGlobalKeydown )
124143 }
125- } , [ mode ] )
144+ } , [ isCurrentMode , setCurrentMode ] )
126145
127146 const handleCustomizeAction = useCallback ( ( ) : void => {
128147 toggleMode ( AppMode . customize )
129- } , [ ] )
148+ } , [ toggleMode ] )
130149
131- return { hiddenLinks , handleCustomizeAction }
150+ return { handleCustomizeAction }
132151}
133152// #endregion customize feature
134153
135154// #region search feature
155+ interface UseSearchModeParams {
156+ currentModeContextValue : CurrentModeContextValue
157+ }
158+
136159interface UseSearchModeReturn {
137160 handleSearchAction : ( ) => void
138161 searchTerm : string
139162 setSearchTerm : Dispatch < SetStateAction < string > >
140163}
141164
142- function useSearchMode ( ) : UseSearchModeReturn {
165+ function useSearchMode ( {
166+ currentModeContextValue,
167+ } : UseSearchModeParams ) : UseSearchModeReturn {
143168 const [ searchTerm , setSearchTerm ] = useState < string > ( '' )
144- const { mode } = useCurrentMode ( )
145169
146- useEffect ( ( ) => {
147- window . addEventListener ( 'keypress' , handleGlobalKeypress )
170+ const { isCurrentMode, setCurrentMode, toggleMode } = currentModeContextValue
148171
149- function handleGlobalKeypress ( event : KeyboardEvent ) : void {
150- if ( mode === AppMode . default ) {
172+ const handleGlobalKeypress = useCallback (
173+ ( event : KeyboardEvent ) => {
174+ if ( isCurrentMode ( AppMode . default ) ) {
151175 if ( event . key === '\n' ) {
152176 return
153177 }
154-
155- setMode ( AppMode . search )
178+
179+ setSearchTerm ( event . key )
180+ setCurrentMode ( AppMode . search )
156181 }
157- }
182+ } ,
183+ [ isCurrentMode , setCurrentMode ]
184+ )
158185
159- return ( ) : void => {
186+ useEffect ( ( ) => {
187+ window . addEventListener ( 'keypress' , handleGlobalKeypress )
188+
189+ return ( ) => {
160190 window . removeEventListener ( 'keypress' , handleGlobalKeypress )
161191 }
162- } , [ mode ] )
192+ } , [ handleGlobalKeypress , isCurrentMode , setCurrentMode ] )
163193
164194 const handleSearchAction = useCallback ( ( ) : void => {
165195 setSearchTerm ( '' )
166196 toggleMode ( AppMode . search )
167- } , [ ] )
197+ } , [ toggleMode ] )
168198
169199 return { handleSearchAction, searchTerm, setSearchTerm }
170200}
@@ -175,26 +205,24 @@ export const themeStates = ['auto', 'light', 'dark'] as const
175205export type ThemeState = typeof themeStates [ number ]
176206
177207interface UseThemeSwitcherReturn {
178- themeSwitcherIcon : string
179- handleThemeSwitcherAction : ( ) => void
208+ icon : string
209+ switchTheme : ( ) => void
180210}
181211
182212function useThemeSwitcher ( ) : UseThemeSwitcherReturn {
183- const [ themeState , setThemeState ] = useState < ThemeState > (
184- getThemeStateSetting ( )
185- )
213+ const [ themeState , setThemeState ] = useState < ThemeState > ( loadThemeSetting ( ) )
186214
187215 const bodyElement = useMemo (
188216 ( ) => globalThis . document . getElementsByTagName ( 'body' ) [ 0 ] ,
189217 [ ]
190218 )
191219
192220 useEffect ( ( ) => {
193- setThemeStateSetting ( themeState )
221+ saveThemeSetting ( themeState )
194222 bodyElement . className = `${ themeState } -theme`
195223 } , [ bodyElement . className , themeState ] )
196224
197- const themeSwitcherIcon = useMemo ( ( ) : string => {
225+ const icon = useMemo ( ( ) : string => {
198226 if ( themeState === 'light' ) {
199227 return mdiWeatherSunny
200228 }
@@ -204,7 +232,7 @@ function useThemeSwitcher(): UseThemeSwitcherReturn {
204232 return mdiThemeLightDark
205233 } , [ themeState ] )
206234
207- const handleThemeSwitcherAction = useCallback ( ( ) : void => {
235+ const switchTheme = useCallback ( ( ) : void => {
208236 switch ( themeState ) {
209237 case 'light' :
210238 setThemeState ( 'dark' )
@@ -218,6 +246,6 @@ function useThemeSwitcher(): UseThemeSwitcherReturn {
218246 }
219247 } , [ themeState ] )
220248
221- return { themeSwitcherIcon , handleThemeSwitcherAction }
249+ return { icon , switchTheme }
222250}
223251// #endregion theme switcher
0 commit comments