Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
89 commits
Select commit Hold shift + click to select a range
372c057
refactor: remove unused article fetching APIs for various sources
medyo Oct 4, 2025
ee57371
refactor: remove unused API files for Hacker News and Indie Hackers a…
medyo Oct 5, 2025
011639e
refactor: remove unused imports and functions from DataEnhancement ut…
medyo Oct 12, 2025
9332f2e
refactor: clean up Tag type by removing unused values and update Arti…
medyo Oct 12, 2025
dcfb5a1
fix: update badge to link in SUPPORTED_CARDS for improved navigation
medyo Oct 12, 2025
21c2aba
feat: enhance ListComponent with sorting functionality and add ListCo…
medyo Oct 12, 2025
df0e803
feat: add @szhsin/react-menu dependency and import styles in index.tsx
medyo Oct 19, 2025
47158ef
refactor: remove LanguagesTab and SourcesTab components to streamline…
medyo Nov 1, 2025
46512af
fix: add useEffect to reset selected chips when defaultValues change
medyo Nov 1, 2025
f7cbe6b
refactor: simplify onboarding process by removing unused components a…
medyo Nov 1, 2025
461f2c0
refactor: clean up GLOBAL_TAG and remove unused MY_LANGUAGES_TAG
medyo Nov 1, 2025
368f3ac
feat: implement SearchEngineBar component and update SearchBarWithLog…
medyo Nov 1, 2025
d5d3563
feat: replace SearchBar with SearchEngineBar in Header component
medyo Nov 1, 2025
ae2d11c
refactor: simplify RemoteConfigStore by removing unused properties an…
medyo Nov 1, 2025
cd269f4
refactor the data source logic and add better filters
medyo Nov 1, 2025
cd2c390
feat: enhance ConferencesItem and ConferencesCard components with imp…
medyo Nov 1, 2025
2309f4a
feat: add providerId handling and last connection indicator in AuthModal
medyo Nov 2, 2025
77ec1c1
feat: conditionally render OnboardingModal based on onboarding comple…
medyo Nov 3, 2025
63f933e
feat: integrate Sentry for session expiration tracking and enhance us…
medyo Nov 3, 2025
73168a0
feat: implement CardHeader component and refactor card components to …
medyo Nov 5, 2025
ea26e14
feat: add MY_LANGUAGES_OPTION configuration for language selection
medyo Nov 6, 2025
e0a5b05
feat: add connectedAt property to User type for tracking connection time
medyo Nov 6, 2025
3f00234
refactor: remove CardHeader component from GithubCard and simplify ti…
medyo Nov 6, 2025
89afad0
fix: adjust tag order in userTagsMemo and ensure MenuDivider appears …
medyo Nov 6, 2025
a0450a7
refactor: update ConferencesCard and ConferenceItem components for im…
medyo Nov 6, 2025
a07c37f
refactor: remove FloatingFilter component and its index file
medyo Nov 6, 2025
d3c9588
refactor: remove unused useRemoteConfigStore import from DesktopCards…
medyo Nov 6, 2025
0bc199d
refactor: add loading attribute to images in ArticleItem and FeedItem…
medyo Nov 6, 2025
aa61021
refactor: remove unused index prop from multiple ArticleItem and Feed…
medyo Nov 6, 2025
85c2b4e
refactor: remove unused initState function from useUserPreferences
medyo Nov 8, 2025
3351dfb
refactor: change div to span for subTitle in ArticleItem component
medyo Nov 9, 2025
51819a0
refactor: enhance styling for menu items and block headers in App.css
medyo Nov 9, 2025
449b680
refactor: remove unused index prop from CardItemWithActions component
medyo Nov 9, 2025
eafcfef
refactor: update Feed component to use feedLoading class for loading …
medyo Nov 9, 2025
34224aa
refactor: simplify ArticleItem component by removing PostFlair rendering
medyo Nov 9, 2025
9a6e2bb
refactor: remove FloatingFilter export from index.ts
medyo Nov 9, 2025
d2d3505
refactor: update Card component to improve settings component renderi…
medyo Nov 9, 2025
cb597db
refactor: update FreecodecampCard component to improve tag handling a…
medyo Nov 9, 2025
1104191
refactor: optimize DevtoCard component by removing unused imports and…
medyo Nov 9, 2025
62e86ac
refactor: optimize CardHeader and CardSettings components for improve…
medyo Nov 9, 2025
4e95853
refactor: add value properties to occupations in HelloTab component f…
medyo Nov 9, 2025
383dc67
refactor: optimize ListComponent by improving memoization and error h…
medyo Nov 9, 2025
d58d4d1
refactor: enhance UserTags component by improving tag handling and in…
medyo Nov 9, 2025
b44f786
feat: implement lazy loading for cards using IntersectionObserver and…
medyo Nov 9, 2025
a05af28
refactor: update streak handling in AppLayout and useAuth for improve…
medyo Nov 16, 2025
bb3f5d8
refactor: update button labels in AuthModal to clarify last used prov…
medyo Nov 16, 2025
f82ccc0
refactor: improve ArticleItem component by utilizing user preferences…
medyo Nov 16, 2025
f805f0e
refactor: center align tabFooter buttons for improved layout consistency
medyo Nov 16, 2025
5971020
refactor: remove duplicate 'value' property from Occupation type defi…
medyo Nov 16, 2025
f6f831f
refactor: remove unused key prop from CardItemWithActions in ArticleI…
medyo Nov 16, 2025
166ca1b
refactor: simplify loading state handling in ListComponent
medyo Nov 16, 2025
21e1133
refactor: optimize useSelectedTags hook by consolidating user prefere…
medyo Nov 16, 2025
a19477e
refactor: update RemoteConfig type by removing unused properties and …
medyo Nov 16, 2025
868546e
refactor: enhance sortOptions in HashnodeCard with reactions and comm…
medyo Nov 16, 2025
62def59
refactor: enhance Header component with layout toggle functionality a…
medyo Nov 18, 2025
701cb26
refactor: streamline Article and Product types by reorganizing proper…
medyo Nov 18, 2025
6a23f7b
refactor: update CardItemWithActionsProps type to define item structu…
medyo Nov 18, 2025
dfe822b
refactor: replace useQueries with useQuery in getConferences and getG…
medyo Nov 18, 2025
9f450f1
fix: update getRemoteConfig to fetch from the correct config file path
medyo Nov 18, 2025
2b8251f
fix: adjust title display in ConferencesItem to improve layout
medyo Nov 18, 2025
1680297
refactor: simplify cardSettings destructuring in GithubCard component
medyo Nov 18, 2025
79c268e
fix: update ArticleItem component to use Product type instead of Arti…
medyo Nov 18, 2025
75ddc98
fix: update ProductHuntCard to use Product type instead of Article type
medyo Nov 18, 2025
3c336ee
fix: migrate userSelectedTags to enhance tag compatibility and update…
medyo Nov 18, 2025
91bee9b
fix: enhance TopicSettings component with improved tag handling and s…
medyo Nov 18, 2025
7f6d34a
fix: add styles for category titles, subtitle buttons, and expand but…
medyo Nov 18, 2025
cdc2a18
fix: update Vite configuration to include additional dependencies and…
medyo Nov 19, 2025
8d650bb
fix: rename shouldCountStreak to shouldIcrementStreak and update date…
medyo Nov 19, 2025
a3490f8
Merge pull request #252 from medyo/refactor-data-source
medyo Nov 19, 2025
0bf827e
fix: handle potential null value for cardSettings in GithubCard compo…
medyo Nov 19, 2025
fba2a51
fix: update build command to use development mode and adjust Sentry c…
medyo Nov 19, 2025
788498c
fix: set NODE_ENV to development during project build in GitHub Actio…
medyo Nov 19, 2025
8a3c49d
fix: remove NODE_ENV setting from GitHub Actions build step and updat…
medyo Nov 19, 2025
0309c97
chore: remove unused dependencies from package.json and yarn.lock
medyo Nov 19, 2025
1898d26
redo spinners dependency
medyo Nov 19, 2025
94a3cb5
fix: remove unused 'react-spring-bottom-sheet' dependency from Vite c…
medyo Nov 19, 2025
10498ab
fix: update migration function to include version parameter and log m…
medyo Nov 19, 2025
60afc6f
fix: enhance migration logging and update onboardingCompleted state d…
medyo Nov 20, 2025
53f53e0
fix: update query keys to include version suffix for conferences, Git…
medyo Nov 20, 2025
adc4681
fix: add occupation field to user preferences state and initialize fr…
medyo Nov 20, 2025
a37b1d3
fix: add Hackernews and Lobsters sources to FeedItemSource and update…
medyo Nov 22, 2025
13fa875
fix: remove unused PostFlair component and its associated types from …
medyo Nov 22, 2025
d6c16c1
fix: update GLOBAL_TAG value to an empty string in HashnodeCard and R…
medyo Nov 22, 2025
7e908eb
fix: update GLOBAL_TAG value to an empty string in FreecodecampCard c…
medyo Nov 22, 2025
7cb791c
feat: add HackernoonCard component and associated ArticleItem with icon
medyo Nov 22, 2025
603fb48
fix: add error handling to source article fetching in multiple card c…
medyo Nov 23, 2025
05944a6
feat: add bodyClassName prop to SettingsContentLayout and apply topic…
medyo Nov 23, 2025
530796d
fix: update sources for Devops, Data, Security, and ML Engineer occup…
medyo Nov 23, 2025
6d91884
fix: update occupation tags and improve card settings handling in Hel…
medyo Nov 23, 2025
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
2 changes: 1 addition & 1 deletion .github/workflows/develop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
run: yarn

- name: Build project
run: yarn build:web
run: yarn build:web --mode development

- name: Copy build to remote host
uses: appleboy/[email protected]
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"@dnd-kit/core": "^6.3.1",
"@dnd-kit/sortable": "^10.0.0",
"@sentry/react": "^9.38.0",
"@szhsin/react-menu": "^4.5.0",
"@tanstack/query-async-storage-persister": "^5.8.3",
"@tanstack/react-query": "^4.13.0",
"@tanstack/react-query-persist-client": "^5.8.4",
Expand All @@ -33,7 +34,6 @@
"react-share": "^4.4.1",
"react-simple-toasts": "^6.1.0",
"react-spinners": "^0.10.4",
"react-spring-bottom-sheet": "^3.4.1",
"react-toggle": "^4.1.1",
"react-tooltip": "^4.2.21",
"timeago.js": "^4.0.2",
Expand Down
4 changes: 2 additions & 2 deletions script/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build() {
echo 'Building Hackertab...'
rm -rf dist
tsc
vite build
vite build "$@"
}

build
build "$@"
11 changes: 3 additions & 8 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import clsx from 'clsx'
import { useEffect, useLayoutEffect, useState } from 'react'
import { useEffect, useLayoutEffect } from 'react'
import { DNDLayout } from 'src/components/Layout'
import {
identifyAdvBlocked,
Expand All @@ -10,7 +10,6 @@ import {
import { useUserPreferences } from 'src/stores/preferences'
import { AppContentLayout } from './components/Layout'
import { verifyAdvStatus } from './features/adv/utils/status'
import { isWebOrExtensionVersion } from './utils/Environment'
import { lazyImport } from './utils/lazyImport'
const { OnboardingModal } = lazyImport(() => import('src/features/onboarding'), 'OnboardingModal')

Expand All @@ -25,10 +24,9 @@ const intersectionCallback = (entries: IntersectionObserverEntry[]) => {
}

export const App = () => {
const [showOnboarding, setShowOnboarding] = useState(true)
const {
onboardingCompleted,
maxVisibleCards,
onboardingCompleted,
setAdvStatus,
isDNDModeActive,
layout,
Expand Down Expand Up @@ -78,10 +76,7 @@ export const App = () => {

return (
<>
{!onboardingCompleted && isWebOrExtensionVersion() === 'extension' && (
<OnboardingModal showOnboarding={showOnboarding} setShowOnboarding={setShowOnboarding} />
)}

{!onboardingCompleted && <OnboardingModal />}
<div
className={clsx(
'layoutLayers hideScrollBar',
Expand Down
110 changes: 108 additions & 2 deletions src/assets/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ a {
text-align: center;
margin: auto;
font-size: 16px;
line-height: 24px;
padding: 16px;
}

Expand Down Expand Up @@ -269,16 +270,94 @@ a {
max-width: 180px;
}

.blockHeader:hover .blockHeaderLink {
.blockHeader:hover .blockHeaderLink,
.blockHeader:hover .blockHeaderSettingsButton {
opacity: 1;
}

.menuItem {
font-size: 1em;
display: flex;
flex-direction: row;
font-family: 'nunito';
column-gap: 8px;
svg {
font-size: 1.1em;
}
}

.szh-menu__header {
margin-bottom: 6px;
}
.light {
.menuItem {
color: var(--card-header-text-color);
}
.szh-menu__item--disabled {
color: var(--secondary-text-color);
opacity: 0.6;
cursor: not-allowed;
}
}

.dark {
.szh-menu {
background-color: var(--card-background-color);
border-radius: 12px;
border: 1px solid var(--card-border-color);
box-shadow: 0 0 20px var(--card-border-color);
}
.szh-menu__item {
color: var(--primary-text-color);
}

.szh-menu__divider {
background-color: var(--card-border-color);
}

.szh-menu__item--hover {
background-color: var(--app-name-text-color);
color: var(--background-color);
}
.szh-menu__item--hover {
background-color: var(--app-name-text-color);
}
.szh-menu__submenu {
background-color: var(--card-background-color);

.szh-menu__item--hover {
background-color: var(--app-name-text-color);
color: var(--background-color);
}
}
.szh-menu__item--disabled {
color: var(--secondary-text-color);
opacity: 0.6;
cursor: not-allowed;
}
}

.blockHeaderSettingsButton {
color: #96a2ae;
display: flex;
justify-content: center;
opacity: 0;
font-size: 1.2em;
transition: opacity 0.2s linear;
cursor: pointer;
&:focus {
cursor: pointer;
opacity: 1;
}
}

.blockHeaderLink {
align-items: center;
color: #96a2ae;
display: flex;
justify-content: center;
opacity: 0;
font-size: 1.2em;
transition: opacity 0.2s linear;
}

Expand Down Expand Up @@ -311,7 +390,13 @@ a {
transform: rotate(3deg);
opacity: 0.5;
}

.blockHeaderHighlight {
border-radius: 15px;
padding: 1px 6px;
border: 1px solid var(--chip-border-color);
background-color: var(--chip-background);
font-size: 0.9em;
}
.blockHeaderIcon {
display: flex;
height: 16px;
Expand All @@ -330,6 +415,11 @@ a {
padding: 0 6px;
text-transform: lowercase;
color: white;

&.past {
background-color: #dd5353;
margin-right: 4px;
}
}
.blockHeaderIcon img {
display: block;
Expand Down Expand Up @@ -567,6 +657,10 @@ a {
transition: opacity 0.3s ease-out 0.1s, transform 0.3s ease-out 0.1s,
visibility 0.3s ease-out 0.1s;
width: 100%;

button.tag {
cursor: pointer;
}
}

.tag {
Expand Down Expand Up @@ -921,7 +1015,14 @@ Producthunt item
padding: 0 32px 0 48px;
width: 100%;
background-color: var(--card-header-background-color);

&::placeholder {
color: var(--primary-text-color);
font-size: 0.9em;
opacity: 0.5;
}
}

.searchBarInput:focus {
outline: none;
}
Expand Down Expand Up @@ -1159,6 +1260,11 @@ Producthunt item
right: 16px;
width: 48px;
z-index: 2;

& svg {
color: white;
font-size: 24px;
}
}

.floatingFilterBottomSheet .title {
Expand Down
Binary file added src/assets/icon_hackernoon.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
119 changes: 59 additions & 60 deletions src/components/Elements/Card/Card.tsx
Original file line number Diff line number Diff line change
@@ -1,79 +1,78 @@
import clsx from 'clsx'
import React, { useEffect, useState } from 'react'
import { BsBoxArrowInUpRight } from 'react-icons/bs'
import { ref } from 'src/config'
import { AdvBanner } from 'src/features/adv'
import { useRemoteConfigStore } from 'src/features/remoteConfig'
import { useUserPreferences } from 'src/stores/preferences'
import { DesktopBreakpoint } from 'src/providers/DesktopBreakpoint'
import { MobileBreakpoint } from 'src/providers/MobileBreakpoint'
import { CardPropsType } from 'src/types'

type RootCardProps = CardPropsType & {
children: React.ReactNode
titleComponent?: React.ReactNode
settingsComponent?: React.ReactNode
fullBlock?: boolean
}
export const Card = React.forwardRef<HTMLDivElement, RootCardProps>(
(
{
meta,
titleComponent,
settingsComponent,
className,
withAds = false,
children,
fullBlock = false,
knob,
},
ref
) => {
const { icon, label, badge } = meta
const [canAdsLoad, setCanAdsLoad] = useState(true)

export const Card = ({
meta,
titleComponent,
className,
withAds = false,
children,
fullBlock = false,
knob,
}: RootCardProps) => {
const { openLinksNewTab } = useUserPreferences()
const { link, icon, label, badge } = meta
const [canAdsLoad, setCanAdsLoad] = useState(true)
const { adsConfig } = useRemoteConfigStore()

useEffect(() => {
if (!adsConfig.enabled || !withAds) {
return
}
useEffect(() => {
if (!withAds) {
return
}

const handleClassChange = () => {
if (document.documentElement.classList.contains('dndState')) {
setCanAdsLoad(false)
} else {
setCanAdsLoad(true)
const handleClassChange = () => {
if (document.documentElement.classList.contains('dndState')) {
setCanAdsLoad(false)
} else {
setCanAdsLoad(true)
}
}
}

const observer = new MutationObserver(handleClassChange)
observer.observe(document.documentElement, { attributes: true })
const observer = new MutationObserver(handleClassChange)
observer.observe(document.documentElement, { attributes: true })

return () => {
observer.disconnect()
}
}, [withAds, adsConfig.enabled])
return () => {
observer.disconnect()
}
}, [withAds])

const handleHeaderLinkClick = (e: React.MouseEvent<HTMLAnchorElement>) => {
e.preventDefault()
let url = `${link}?${ref}`
window.open(url, openLinksNewTab ? '_blank' : '_self')
}
return (
<div ref={ref} className={clsx('block', fullBlock && 'fullBlock', className)}>
<MobileBreakpoint>
{settingsComponent && <button className="floatingFilter">{settingsComponent}</button>}
</MobileBreakpoint>
<div className="blockHeader">
{knob}
<span className="blockHeaderIcon">{icon}</span> {titleComponent || label}{' '}
<DesktopBreakpoint>
{settingsComponent && (
<span className="blockHeaderSettingsButton">{settingsComponent}</span>
)}
</DesktopBreakpoint>
{badge && <span className="blockHeaderBadge">{badge}</span>}
</div>

return (
<div className={clsx('block', fullBlock && 'fullBlock', className)}>
<div className="blockHeader">
{knob}
<span className="blockHeaderIcon">{icon}</span> {titleComponent || label}{' '}
{link && (
<a className="blockHeaderLink" href={link} onClick={handleHeaderLinkClick}>
<BsBoxArrowInUpRight />
</a>
{canAdsLoad && withAds && (
<div className="ad-wrapper blockRow">
<AdvBanner />
</div>
)}
{badge && <span className="blockHeaderBadge">{badge}</span>}
</div>

{canAdsLoad && adsConfig.enabled && withAds && (
<div className="ad-wrapper blockRow">
<AdvBanner />
</div>
)}

<div className="blockContent scrollable">{children}</div>
</div>
)
}
<div className="blockContent scrollable">{children}</div>
</div>
)
}
)
Loading