Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 33 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,44 @@ Please do not hesitate to ask a question, report a bug or add a suggestion. or s

## Development

Please use the develop branch. Create an .env file with the necessary env variables
Please use the develop branch. Create an `.env` file in the root directory with the following variables:

```bash
$ git clone --branch develop git@github.com:medyo/hackertab.dev.git
VITE_API_URL=https://api.hackertab.dev/
VITE_BUILD_TARGET=web # or extension
VITE_BUILD_PLATFORM=chrome # optional, used for extension builds (chrome or firefox)
VITE_FIREBASE_API_KEY= # optional for local dev, required for auth features
VITE_AMPLITUDE_URL= # optional
VITE_AMPLITUDE_KEY= # optional
VITE_SENTRY_DSN= # optional
```

### Setup

Make sure you are using Node.js version 18.

```bash
$ git clone https://github.com/medyo/hackertab.dev.git
$ cd hackertab.dev
$ yarn
$ yarn start
$ # Then visit http://localhost:3000
```

Then visit [http://localhost:5173](http://localhost:5173) (or the port shown in your terminal).

## 🚀 Build

To build the project for different targets:

```bash
# Web build
$ yarn build:web

# Chrome extension
$ yarn build:chrome

# Firefox extension
$ yarn build:firefox
```

## Maintainers
Expand Down
9 changes: 0 additions & 9 deletions src/components/Elements/Button/Button.css
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,4 @@
color: var(--button-hover-text-color);
}
}

&.dark-focus {
background-color: var(--dark-mode-background-color);
color: var(--dark-mode-text-color);

&:hover {
opacity: 0.9;
}
}
}
1 change: 0 additions & 1 deletion src/components/Elements/Button/CircleButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ const sizes = {

const variants = {
primary: 'primary',
darkfocus: 'dark-focus',
}

type CircleButtonProps = {
Expand Down
49 changes: 18 additions & 31 deletions src/components/Layout/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { clsx } from 'clsx'
import { useCallback, useEffect, useState } from 'react'
import { BsFillBookmarksFill, BsFillGearFill, BsMoonFill } from 'react-icons/bs'
import { BsFillBookmarksFill, BsFillGearFill } from 'react-icons/bs'
import { CgTab } from 'react-icons/cg'
import { FaCrown } from 'react-icons/fa'
import { IoMdSunny } from 'react-icons/io'
import { MdDoDisturbOff } from 'react-icons/md'
import { RiDashboardHorizontalFill } from 'react-icons/ri'
import { TfiLayoutColumn4Alt } from 'react-icons/tfi'
Expand All @@ -15,12 +14,7 @@ import { UserTags } from 'src/components/Elements/UserTags'
import { useAuth } from 'src/features/auth'
import { Changelog } from 'src/features/changelog'
import { useRemoteConfigStore } from 'src/features/remoteConfig'
import {
identifyUserTheme,
trackDNDDisable,
trackDisplayTypeChange,
trackThemeSelect,
} from 'src/lib/analytics'
import { trackDNDDisable, trackDisplayTypeChange } from 'src/lib/analytics'
import { useUserPreferences } from 'src/stores/preferences'
import { lazyImport } from 'src/utils/lazyImport'
import { Button, CircleButton } from '../Elements'
Expand All @@ -30,36 +24,32 @@ const { DonateModal } = lazyImport(() => import('src/features/donate'), 'DonateM
export const Header = () => {
const { openAuthModal, user, isConnected, isConnecting } = useAuth()

const [themeIcon, setThemeIcon] = useState(<BsMoonFill />)
const [openDonateModal, setOpenDonateModal] = useState(false)
const { paywall } = useRemoteConfigStore()
const { theme, setTheme, setDNDDuration, isDNDModeActive, layout, setLayout } =
useUserPreferences()
const { theme, setDNDDuration, isDNDModeActive, layout, setLayout } = useUserPreferences()
const navigate = useNavigate()
const location = useLocation()

useEffect(() => {
document.documentElement.classList.add(theme)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
const applyResolvedTheme = (resolved: 'dark' | 'light') => {
document.documentElement.classList.remove('dark', 'light')
document.documentElement.classList.add(resolved)
}

useEffect(() => {
if (theme === 'light') {
document.documentElement.classList.replace('dark', theme)
setThemeIcon(<BsMoonFill />)
} else if (theme === 'dark') {
document.documentElement.classList.replace('light', theme)
setThemeIcon(<IoMdSunny />)
if (theme === 'system') {
const mq = window.matchMedia('(prefers-color-scheme: dark)')
const updateSystemTheme = (matches: boolean) => {
applyResolvedTheme(matches ? 'dark' : 'light')
}
updateSystemTheme(mq.matches)
const handler = (e: MediaQueryListEvent) => updateSystemTheme(e.matches)
mq.addEventListener('change', handler)
return () => mq.removeEventListener('change', handler)
} else {
applyResolvedTheme(theme)
}
}, [theme])

const onThemeChange = useCallback(() => {
const newTheme = theme === 'dark' ? 'light' : 'dark'
setTheme(newTheme)
trackThemeSelect(newTheme)
identifyUserTheme(newTheme)
}, [theme, setTheme])

const onLayoutChange = useCallback(() => {
const newLayout = layout === 'cards' ? 'grid' : 'cards'
trackDisplayTypeChange(newLayout)
Expand Down Expand Up @@ -111,9 +101,6 @@ export const Header = () => {
<CircleButton onClick={onLayoutChange}>
{layout === 'cards' ? <RiDashboardHorizontalFill /> : <TfiLayoutColumn4Alt />}
</CircleButton>
<CircleButton onClick={onThemeChange} variant="darkfocus">
{themeIcon}
</CircleButton>
<CircleButton onClick={() => navigate('/settings/bookmarks')}>
<BsFillBookmarksFill />
</CircleButton>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import React from 'react'
import { BsMoonFill } from 'react-icons/bs'
import { IoMdSunny } from 'react-icons/io'
import { MdMonitor } from 'react-icons/md'
import Toggle from 'react-toggle'
import 'react-toggle/style.css'
import { Footer } from 'src/components/Layout'
Expand All @@ -12,13 +15,20 @@ import {
trackThemeSelect,
} from 'src/lib/analytics'
import { useUserPreferences } from 'src/stores/preferences'
import { Theme } from 'src/types'
import { DeleteAccount } from '../UserSettings/DeleteAccount'
import { UserInfo } from '../UserSettings/UserInfo'
import { CardsNumberSettings } from './CardsNumberSettings'
import { DNDSettings } from './DNDSettings'
import './generalSettings.css'
import { LayoutSettings } from './LayoutSettings'

const themeIcons = {
light: <IoMdSunny />,
dark: <BsMoonFill />,
system: <MdMonitor />,
}

export const GeneralSettings = () => {
const {
openLinksNewTab,
Expand Down Expand Up @@ -47,8 +57,7 @@ export const GeneralSettings = () => {
setListingMode(value)
}

const onDarkModeChange = () => {
const newTheme = theme === 'dark' ? 'light' : 'dark'
const onThemeChange = (newTheme: Theme) => {
setTheme(newTheme)
trackThemeSelect(newTheme)
identifyUserTheme(newTheme)
Expand All @@ -70,9 +79,23 @@ export const GeneralSettings = () => {
<CardsNumberSettings />

<div className="settingRow">
<p className="settingTitle">Dark Mode</p>
<p className="settingTitle">Theme</p>
<div className="settingContent">
<Toggle checked={theme === 'dark'} icons={false} onChange={onDarkModeChange} />
<div className="themeSelector">
{(['light', 'dark', 'system'] as Theme[]).map((option) => (
<label key={option} className={`themeOption${theme === option ? ' active' : ''}`}>
<input
type="radio"
name="theme"
value={option}
checked={theme === option}
onChange={() => onThemeChange(option)}
/>
{themeIcons[option]}
<span>{option.charAt(0).toUpperCase() + option.slice(1)}</span>
</label>
))}
</div>
</div>
</div>

Expand Down
Loading