Skip to content

Commit bac31f5

Browse files
committed
migrate to the new store
1 parent 2d6f10f commit bac31f5

21 files changed

Lines changed: 227 additions & 114 deletions

src/App.js

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useState, useEffect, useContext } from 'react'
1+
import React, { useState, useEffect } from 'react'
22
import './App.css'
33
import { Footer } from 'src/components/Layout'
44
import Header from 'src/components/Header'
@@ -7,30 +7,27 @@ import { MarketingBanner } from 'src/components/Elements/MarketingBanner'
77
import ScrollCardsNavigator from './components/ScrollCardsNavigator'
88
import AppContentLayout from './components/AppContentLayout'
99
import 'react-contexify/dist/ReactContexify.css'
10-
import PreferencesContext from './preferences/PreferencesContext'
1110
import { setupAnalytics, trackPageView, setupIdentification } from 'src/lib/analytics'
1211
import { useRemoteConfigStore } from 'src/features/remoteConfig'
1312

1413
function App() {
1514
const [showSideBar, setShowSideBar] = useState(false)
1615
const [showSettings, setShowSettings] = useState(false)
17-
const { dispatcher, ...state } = useContext(PreferencesContext)
16+
1817
const {
1918
remoteConfig: { marketingBannerConfig },
2019
} = useRemoteConfigStore()
2120

2221
useEffect(() => {
2322
setupAnalytics()
24-
setupIdentification(state)
23+
setupIdentification()
2524
trackPageView('home')
2625
}, [])
2726

2827
return (
2928
<div className="App">
3029
<Header
3130
setShowSideBar={setShowSideBar}
32-
state={state}
33-
dispatcher={dispatcher}
3431
showSideBar={showSideBar}
3532
showSettings={showSettings}
3633
setShowSettings={setShowSettings}

src/components/AppContentLayout.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import React, { useContext, useState } from 'react'
1+
import React, { useState } from 'react'
22
import { SUPPORTED_CARDS } from '../Constants'
3-
import PreferencesContext from '../preferences/PreferencesContext'
43
import BottomNavigation from './BottomNavigation'
54
import { isDesktop } from 'react-device-detect'
5+
import { useUserPreferences } from 'src/stores/preferences'
66

77
function MobileCards({ selectedCard }) {
88
const currentCard = SUPPORTED_CARDS.find((c) => c.value === selectedCard.name)
@@ -31,7 +31,7 @@ function DesktopCards({ cards }) {
3131
}
3232

3333
function AppContentLayout({ setShowSettings }) {
34-
const { cards } = useContext(PreferencesContext)
34+
const { cards } = useUserPreferences()
3535
const [selectedCard, setSelectedCard] = useState(cards[0])
3636

3737
return (

src/components/BottomNavigation.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import React, { useContext } from 'react'
1+
import React from 'react'
22
import { SUPPORTED_CARDS } from '../Constants'
3-
import PreferencesContext from '../preferences/PreferencesContext'
3+
import { useUserPreferences } from 'src/stores/preferences'
44
import { AiOutlineMenu } from 'react-icons/ai'
55

66
function BottomNavigation({ selectedCard, setSelectedCard, setShowSettings }) {
7-
const { cards } = useContext(PreferencesContext)
7+
const { cards } = useUserPreferences()
88

99
return (
1010
<div className="bottomNavigation">

src/components/CardItemWithActions.js

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,25 @@
1-
import React, { useState, useContext, useEffect } from 'react'
2-
import PreferencesContext from '../preferences/PreferencesContext'
1+
import React, { useState, useEffect } from 'react'
2+
import { useBookmarks } from 'src/stores/bookmarks'
33
import { BiBookmarkPlus } from 'react-icons/bi'
44
import { BiBookmarkMinus } from 'react-icons/bi'
55
import { trackLinkBookmark, trackLinkUnBookmark, Attributes } from 'src/lib/analytics'
66

77
export default function CardItemWithActions({ cardItem, item, index, source }) {
8-
const { dispatcher, userBookmarks } = useContext(PreferencesContext)
8+
const { bookmarkPost, unbookmarkPost, userBookmarks } = useBookmarks()
99
const [isBookmarked, setIsBookmarked] = useState(
10-
userBookmarks.some((bm) => bm.source == source && bm.url == item.url)
10+
userBookmarks.some((bm) => bm.source === source && bm.url === item.url)
1111
)
1212
const onBookmarkClick = () => {
13-
dispatcher({
14-
type: isBookmarked ? 'unBookmarkItem' : 'bookmarkItem',
15-
value: {
16-
title: item.title,
17-
url: item.url,
18-
source,
19-
},
20-
})
13+
const itemToBookmark = {
14+
title: item.title,
15+
url: item.url,
16+
source,
17+
}
18+
if (isBookmarked) {
19+
unbookmarkPost(itemToBookmark)
20+
} else {
21+
bookmarkPost(itemToBookmark)
22+
}
2123
setIsBookmarked(!isBookmarked)
2224
const analyticsAttrs = {
2325
[Attributes.TRIGERED_FROM]: 'card',
@@ -32,7 +34,7 @@ export default function CardItemWithActions({ cardItem, item, index, source }) {
3234
}
3335
}
3436
useEffect(() => {
35-
setIsBookmarked(userBookmarks.some((bm) => bm.source == source && bm.url == item.url))
37+
setIsBookmarked(userBookmarks.some((bm) => bm.source === source && bm.url === item.url))
3638
}, [userBookmarks])
3739

3840
return (
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import React, { useEffect, useRef } from 'react'
2+
import { trackSearchEngineUse } from 'src/lib/analytics'
3+
import { GoSearch } from 'react-icons/go'
4+
import { SUPPORTED_SEARCH_ENGINES } from 'src/Constants'
5+
import { useUserPreferences } from 'src/stores/preferences'
6+
import { SearchEngine } from 'src/types'
7+
8+
export const SearchBar = () => {
9+
const { searchEngine } = useUserPreferences()
10+
11+
const keywordsInputRef = useRef<HTMLInputElement | null>(null)
12+
const usedSearchEngine: SearchEngine =
13+
SUPPORTED_SEARCH_ENGINES.find((engine) => engine.label === searchEngine) ||
14+
SUPPORTED_SEARCH_ENGINES[0]
15+
16+
const handleSubmit = (e: React.FormEvent) => {
17+
e.preventDefault()
18+
const target = e.target as typeof e.target & {
19+
keyword: { value: string }
20+
}
21+
22+
trackSearchEngineUse(usedSearchEngine.label)
23+
window.open(`${usedSearchEngine.url}${target.keyword}`, '_self')
24+
}
25+
26+
useEffect(() => {
27+
keywordsInputRef.current?.focus()
28+
}, [])
29+
30+
return (
31+
<form className="searchBar" onSubmit={handleSubmit}>
32+
<GoSearch className="searchBarIcon" size={20} />
33+
<input
34+
ref={keywordsInputRef}
35+
type="text"
36+
className="searchBarInput"
37+
placeholder={`Search on ${usedSearchEngine.label}`}
38+
/>
39+
</form>
40+
)
41+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from "./SearchBar"

src/components/Header.js

Lines changed: 24 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -4,49 +4,23 @@ import { CgTab } from 'react-icons/cg'
44
import { BsFillBookmarksFill } from 'react-icons/bs'
55
import { ReactComponent as HackertabLogo } from 'src/assets/logo.svg'
66
import UserTags from './UserTags'
7-
import { SUPPORTED_SEARCH_ENGINES } from '../Constants'
87
import { SettingsModal } from 'src/features/settings'
98
import { BsMoon } from 'react-icons/bs'
109
import { IoMdSunny } from 'react-icons/io'
11-
import { trackSearchEngineUse } from 'src/lib/analytics'
12-
import {Changelog} from 'src/features/changelog'
13-
import { GoSearch } from 'react-icons/go'
10+
import { Changelog } from 'src/features/changelog'
11+
import { SearchBar } from 'src/components/Elements/SearchBar'
12+
import { useUserPreferences } from 'src/stores/preferences'
13+
import { useBookmarks } from 'src/stores/bookmarks'
1414

15-
function SearchBar({ state }) {
16-
const keywordsInputRef = React.useRef(null)
17-
const userSearchEngine = SUPPORTED_SEARCH_ENGINES.find(
18-
(engine) => engine.label === state.searchEngine
19-
)
20-
21-
const handleSubmit = (e) => {
22-
e.preventDefault()
23-
const keywords = e.target.children[1].value
24-
trackSearchEngineUse(userSearchEngine.label)
25-
window.open(`${userSearchEngine.url}${keywords}`, '_self')
26-
}
27-
28-
useEffect(() => {
29-
keywordsInputRef.current.focus()
30-
}, [])
31-
32-
return (
33-
<form className="searchBar" onSubmit={handleSubmit}>
34-
<GoSearch className="searchBarIcon" size={20} />
35-
<input
36-
ref={keywordsInputRef}
37-
type="text"
38-
className="searchBarInput"
39-
placeholder={`Search on ${userSearchEngine.label}`}
40-
/>
41-
</form>
42-
)
43-
}
44-
function Header({ state, dispatcher, showSideBar, setShowSideBar, showSettings, setShowSettings }) {
15+
function Header({ showSideBar, setShowSideBar, showSettings, setShowSettings }) {
4516
const [themeIcon, setThemeIcon] = useState(<BsMoon />)
4617
const isFirstRun = useRef(true)
18+
const { theme, setTheme } = useUserPreferences()
19+
const { userBookmarks } = useBookmarks()
4720

4821
useEffect(() => {
49-
document.documentElement.classList.add(state.theme)
22+
document.documentElement.classList.add(theme)
23+
// eslint-disable-next-line react-hooks/exhaustive-deps
5024
}, [])
5125

5226
useEffect(() => {
@@ -58,27 +32,31 @@ function Header({ state, dispatcher, showSideBar, setShowSideBar, showSettings,
5832
}
5933
}
6034

61-
if (state.theme === 'light') {
62-
document.documentElement.classList.replace('dark', state.theme)
35+
if (theme === 'light') {
36+
document.documentElement.classList.replace('dark', theme)
6337
setThemeIcon(<BsMoon />)
64-
} else if (state.theme === 'dark') {
65-
document.documentElement.classList.replace('light', state.theme)
38+
} else if (theme === 'dark') {
39+
document.documentElement.classList.replace('light', theme)
6640
setThemeIcon(<IoMdSunny />)
6741
}
68-
}, [state?.theme])
42+
}, [theme])
6943

7044
const onThemeChange = () => {
71-
dispatcher({ type: 'toggleTheme' })
45+
if (theme === 'dark') {
46+
setTheme('light')
47+
} else {
48+
setTheme('dark')
49+
}
7250
}
7351

7452
const onSettingsClick = () => {
7553
setShowSettings(true)
7654
}
7755

7856
const BookmarksBadgeCount = () => {
79-
return state.userBookmarks.length > 0 ? (
80-
state.userBookmarks.length < 10 ? (
81-
<span className="badgeCount">{state.userBookmarks.length}</span>
57+
return userBookmarks.length > 0 ? (
58+
userBookmarks.length < 10 ? (
59+
<span className="badgeCount">{userBookmarks.length}</span>
8260
) : (
8361
<span className="badgeCount">+9</span>
8462
)
@@ -97,7 +75,7 @@ function Header({ state, dispatcher, showSideBar, setShowSideBar, showSettings,
9775
<HackertabLogo className="logoText" />
9876
<Changelog />
9977
</span>
100-
<SearchBar state={state} />
78+
<SearchBar />
10179
<div className="extras">
10280
<button className="extraBtn" onClick={onSettingsClick}>
10381
<BsFillGearFill />
@@ -111,7 +89,7 @@ function Header({ state, dispatcher, showSideBar, setShowSideBar, showSettings,
11189
</button>
11290
</div>
11391
<div className="break"></div>
114-
<UserTags userSelectedTags={state.userSelectedTags} onAddClicked={onSettingsClick} />
92+
<UserTags onAddClicked={onSettingsClick} />
11593
</header>
11694
</>
11795
)

src/components/ScrollCardsNavigator.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import React, { useState, useEffect, useContext, useLayoutEffect, useRef } from 'react'
1+
import React, { useState, useEffect, useLayoutEffect, useRef } from 'react'
22
import { FiChevronLeft, FiChevronRight } from 'react-icons/fi'
33
import { APP } from '../Constants'
4-
import PreferencesContext from '../preferences/PreferencesContext'
4+
import { useUserPreferences } from 'src/stores/preferences'
55
import { trackPageScroll } from 'src/lib/analytics'
66

77
function ScrollCardsNavigator() {
8-
const { cards } = useContext(PreferencesContext)
8+
const { cards } = useUserPreferences()
99
const [leftButtonVisible, setLeftButtonVisible] = useState(true)
1010
const [rightButtonVisible, setRightButtonVisible] = useState(true)
1111
const scrollBarContainer = useRef(null)

src/components/SelectableCard.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import React, { useContext, useLayoutEffect } from 'react'
1+
import React, { useLayoutEffect } from 'react'
22
import DropDownMenu from './DropDownMenu'
33
import { GLOBAL_TAG, MY_LANGUAGES_TAG } from '../Constants'
4-
import PreferencesContext from '../preferences/PreferencesContext'
4+
import { useUserPreferences } from 'src/stores/preferences'
55

66
function SelectableCard({
77
tagId,
@@ -13,8 +13,7 @@ function SelectableCard({
1313
trackEvent,
1414
isLanguage = false,
1515
}) {
16-
const preferences = useContext(PreferencesContext)
17-
const { userSelectedTags } = preferences
16+
const { userSelectedTags } = useUserPreferences()
1817

1918
let mergedTags = data
2019
if (isLanguage) {

src/components/UserTags.js

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,21 @@
11
import React from 'react'
22
import { TiPlus } from 'react-icons/ti';
3+
import { useUserPreferences } from 'src/stores/preferences'
4+
import { enhanceTags } from 'src/utils/DataEnhancement'
35

4-
function UserTags({ userSelectedTags, onAddClicked }) {
6+
function UserTags({ onAddClicked }) {
7+
const { userSelectedTags } = useUserPreferences()
58

69
return (
710
<nav className="tags">
8-
{userSelectedTags.map((tag, index) => <span key={index} className="tag">{tag.value}</span>)}
9-
<span className="tag tagHoverable" onClick={onAddClicked}><TiPlus className="tagIcon" /></span>
11+
{enhanceTags(userSelectedTags).map((tag, index) => (
12+
<span key={index} className="tag">
13+
{tag.value}
14+
</span>
15+
))}
16+
<span className="tag tagHoverable" onClick={onAddClicked}>
17+
<TiPlus className="tagIcon" />
18+
</span>
1019
</nav>
1120
)
1221
}

0 commit comments

Comments
 (0)