Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
54e39c6
initial commit
Chouikane Feb 6, 2023
98db547
add rss from settings modal
Chouikane Feb 7, 2023
8cad7f4
clean code
Chouikane Feb 7, 2023
4a3ac83
fix rss sources bookmarks
Chouikane Feb 7, 2023
c1d6eda
fix query key
Chouikane Feb 8, 2023
c7c6ec5
update rssFeed endpoint
Chouikane Feb 8, 2023
212c465
add rss card icon
Chouikane Feb 9, 2023
af9c57a
remove unavailable card filter
medyo Feb 10, 2023
99d298c
rename the rss key
medyo Feb 10, 2023
baf2ef2
show an orange rss icon if favicon not available
medyo Feb 10, 2023
b646b65
remove rss cards from display card settings
Chouikane Feb 10, 2023
2cffb6e
Merge branch 'feat/add-rss' of github.com:medyo/hackertab.dev into fe…
Chouikane Feb 10, 2023
e8085f6
improve the rss feed setting
medyo Feb 10, 2023
fa8b6cd
improve the displayed card settings hint
medyo Feb 10, 2023
f9c153d
fix an input warning
medyo Feb 10, 2023
04e66bb
improve rss analytics code
medyo Feb 10, 2023
80b0ab4
improve the rss setting ui
medyo Feb 10, 2023
7ca42fb
dynamic ads
Chouikane Feb 10, 2023
df460b0
Merge branch 'feat/add-rss' of github.com:medyo/hackertab.dev into fe…
Chouikane Feb 10, 2023
1feaf71
rm unused vars
Chouikane Feb 10, 2023
fbd8023
reanem customrssCard -> rssCard
medyo Feb 10, 2023
8ba197f
Merge branch 'feat/add-rss' of github.com:medyo/hackertab.dev into fe…
medyo Feb 10, 2023
49f5b7e
rename api file to ts
medyo Feb 10, 2023
93f70e6
remove unused css class
medyo Feb 10, 2023
5ec9fe6
fix zustand warnings
medyo Feb 10, 2023
a3de22d
Merge branch 'develop' into feat/add-rss
medyo Feb 10, 2023
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: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"country-emoji": "^1.5.4",
"dompurify": "^2.2.7",
"eslint-plugin-react": "^7.28.0",
"htmlparser2": "^8.0.1",
"jsonpath": "^1.1.1",
"localforage": "^1.9.0",
"normalize.css": "^8.0.1",
Expand All @@ -35,6 +36,7 @@
"react-spring-bottom-sheet": "^3.4.1",
"react-toggle": "^4.1.1",
"react-tooltip": "^4.2.21",
"rss-to-json": "^2.1.1",
"styled-components": "2",
"timeago.js": "^4.0.2",
"type-fest": "^1.2.0",
Expand Down
4 changes: 3 additions & 1 deletion src/assets/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,9 @@ a {
width: 18px;
height: 18px;
}

.blockHeaderIcon .rss {
color:#ee802f;
}
.blockRow {
scroll-snap-align: start;
padding: 8px 16px;
Expand Down
13 changes: 13 additions & 0 deletions src/assets/variables.css
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@ html.dark {
--tab-neutral-button-text: #a2a7ad;
--tab-positive-button-background: #0366d6;
--tab-positive-button-text: white;

--settings-input-background-color: #0d1116;
--settings-input-border-color: #3a4553;
--settings-input-border-focus-color: #6b7b90;
--settings-input-placeholder-color: #42474e;
--settings-input-text-color: #fff
}

html.light {
Expand Down Expand Up @@ -160,4 +166,11 @@ html.light {
--tab-neutral-button-text: #3c5065;
--tab-positive-button-background: #0366d6;
--tab-positive-button-text: white;

--settings-input-background-color: #ffffff;
--settings-input-border-color: #e9ebec;
--settings-input-border-focus-color: #c4d6df;
--settings-input-placeholder-color: #97a6ad;
--settings-input-text-color: #253b53

}
4 changes: 2 additions & 2 deletions src/components/Elements/Card/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import React from 'react'
import { BsBoxArrowInUpRight } from 'react-icons/bs'
import { ref } from 'src/config'
import { useUserPreferences } from 'src/stores/preferences'
import { SupportedCard } from 'src/config'
import { SupportedCardType } from 'src/types'

type CardProps = {
children: React.ReactNode
card: SupportedCard
card: SupportedCardType
titleComponent?: React.ReactNode
fullBlock?: boolean
}
Expand Down
10 changes: 6 additions & 4 deletions src/components/Elements/CardWithActions/CardItemWithActions.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
import React, { useState, useEffect } from 'react'
import React, { useEffect, useState } from 'react'
import { BiBookmarkMinus, BiBookmarkPlus } from 'react-icons/bi'
import { Attributes, trackLinkBookmark, trackLinkUnBookmark } from 'src/lib/analytics'
import { useBookmarks } from 'src/stores/bookmarks'
import { BiBookmarkPlus } from 'react-icons/bi'
import { BiBookmarkMinus } from 'react-icons/bi'
import { trackLinkBookmark, trackLinkUnBookmark, Attributes } from 'src/lib/analytics'
import { BaseEntry } from 'src/types'

type CardItemWithActionsProps = {
item: BaseEntry
index: number
source: string
cardItem: React.ReactNode
sourceType?: 'rss' | 'supported'
}

export const CardItemWithActions = ({
cardItem,
item,
index,
source,
sourceType = 'supported',
}: CardItemWithActionsProps) => {
const { bookmarkPost, unbookmarkPost, userBookmarks } = useBookmarks()
const [isBookmarked, setIsBookmarked] = useState(
Expand All @@ -27,6 +28,7 @@ export const CardItemWithActions = ({
title: item.title,
url: item.url,
source,
sourceType: sourceType ?? 'rss',
}
if (isBookmarked) {
unbookmarkPost(itemToBookmark)
Expand Down
5 changes: 3 additions & 2 deletions src/components/Elements/FloatingFilter/FloatingFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ import { FiFilter } from 'react-icons/fi'
import { BottomSheet } from 'react-spring-bottom-sheet'
import 'react-spring-bottom-sheet/dist/style.css'
import { ChipsSet } from 'src/components/Elements'
import { dateRanges, GLOBAL_TAG, MY_LANGUAGES_TAG, SupportedCard } from 'src/config'
import { dateRanges, GLOBAL_TAG, MY_LANGUAGES_TAG } from 'src/config'
import { trackCardDateRangeSelect, trackCardLanguageSelect } from 'src/lib/analytics'
import { useUserPreferences } from 'src/stores/preferences'
import { SupportedCardType } from 'src/types'

type ListingFilterMobileProps = {
card: SupportedCard
card: SupportedCardType
filters?: ('datesRange' | 'language')[]
}

Expand Down
12 changes: 8 additions & 4 deletions src/components/Layout/AppContentLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
import { useState } from 'react'
import { BottomNavigation } from '../Elements'
import { isDesktop } from 'react-device-detect'
import { useUserPreferences } from 'src/stores/preferences'
import { MobileCards } from './MobileCards'
import { BottomNavigation } from '../Elements'
import { DesktopCards } from './DesktopCards'
import { MobileCards } from './MobileCards'

export const AppContentLayout = ({
setShowSettings,
}: {
setShowSettings: (value: boolean | ((prevVar: boolean) => boolean)) => void
}) => {
const { cards } = useUserPreferences()
const { cards, userCustomCards } = useUserPreferences()
const [selectedCard, setSelectedCard] = useState(cards[0])

return (
<>
<main className="AppContent HorizontalScroll">
{isDesktop ? <DesktopCards cards={cards} /> : <MobileCards selectedCard={selectedCard} />}
{isDesktop ? (
<DesktopCards cards={cards} userCustomCards={userCustomCards} />
) : (
<MobileCards selectedCard={selectedCard} />
)}
</main>

<BottomNavigation
Expand Down
16 changes: 12 additions & 4 deletions src/components/Layout/DesktopCards.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
import React from 'react'
import { SUPPORTED_CARDS } from 'src/config'
import { SelectedCard } from 'src/types'
import { CustomRssCard } from 'src/features/cards'
import { SelectedCard, SupportedCardType } from 'src/types'

export const DesktopCards = ({ cards }: { cards: SelectedCard[] }) => {
export const DesktopCards = ({
cards,
userCustomCards,
}: {
cards: SelectedCard[]
userCustomCards: SupportedCardType[]
}) => {
const AVAILABLE_CARDS = [...SUPPORTED_CARDS, ...userCustomCards]
return (
<>
{cards.map((card, index) => {
const constantCard = SUPPORTED_CARDS.find((c) => c.value === card.name)
const constantCard = AVAILABLE_CARDS.find((c) => c.value === card.name)
if (!constantCard) {
return null
}

return React.createElement(constantCard.component, {
return React.createElement(constantCard?.component || CustomRssCard, {
key: card.name,
meta: constantCard,
withAds: index === 0,
Expand Down
16 changes: 7 additions & 9 deletions src/components/Layout/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
import React, { useEffect, useRef, useState } from 'react'
import { BsFillGearFill } from 'react-icons/bs'
import { useEffect, useRef, useState } from 'react'
import { BsFillBookmarksFill, BsFillGearFill, BsMoon } from 'react-icons/bs'
import { CgTab } from 'react-icons/cg'
import { BsFillBookmarksFill } from 'react-icons/bs'
import { IoMdSunny } from 'react-icons/io'
import { ReactComponent as HackertabLogo } from 'src/assets/logo.svg'
import { SearchBar } from 'src/components/Elements/SearchBar'
import { UserTags } from 'src/components/Elements/UserTags'
import { SettingsModal } from 'src/features/settings'
import { BsMoon } from 'react-icons/bs'
import { IoMdSunny } from 'react-icons/io'
import { Changelog } from 'src/features/changelog'
import { SearchBar } from 'src/components/Elements/SearchBar'
import { useUserPreferences } from 'src/stores/preferences'
import { SettingsModal } from 'src/features/settings'
import { identifyUserTheme, trackThemeSelect } from 'src/lib/analytics'
import { useBookmarks } from 'src/stores/bookmarks'
import { trackThemeSelect, identifyUserTheme } from 'src/lib/analytics'
import { useUserPreferences } from 'src/stores/preferences'

type HeaderProps = {
showSideBar: boolean
Expand Down
3 changes: 2 additions & 1 deletion src/components/Layout/MobileCards.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import React from 'react'
import { SUPPORTED_CARDS } from 'src/config'
import { CustomRssCard } from 'src/features/cards'
import { SelectedCard } from 'src/types'

export const MobileCards = ({ selectedCard }: { selectedCard: SelectedCard }) => {
const currentCard = SUPPORTED_CARDS.find((c) => c.value === selectedCard.name)
return currentCard
? React.createElement(currentCard.component, {
? React.createElement(currentCard?.component || CustomRssCard, {
key: currentCard.value,
meta: currentCard,
withAds: true,
Expand Down
25 changes: 13 additions & 12 deletions src/config/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import React from 'react'
import { CgIndieHackers } from 'react-icons/cg'
import { FaDev, FaFreeCodeCamp, FaMediumM, FaReddit } from 'react-icons/fa'
import { HiTicket } from 'react-icons/hi'
Expand All @@ -18,7 +17,7 @@ import {
ProductHuntCard,
RedditCard,
} from 'src/features/cards'
import { CardPropsType } from 'src/types'
import { SupportedCardType } from 'src/types'

// Keys
export const ANALYTICS_ENDPOINT = process.env.REACT_APP_AMPLITUDE_URL as string
Expand Down Expand Up @@ -67,23 +66,15 @@ export const SUPPORTED_SEARCH_ENGINES = [
url: 'https://www.startpage.com/sp/search?query=',
},
]

export type SupportedCard = {
value: string
icon: React.ReactNode
analyticsTag: string
label: string
link: string
component: React.FunctionComponent<CardPropsType>
}
export const SUPPORTED_CARDS: SupportedCard[] = [
export const SUPPORTED_CARDS: SupportedCardType[] = [
{
value: 'github',
analyticsTag: 'github',
label: 'Github repositories',
component: GithubCard,
icon: <SiGithub className="blockHeaderWhite" />,
link: 'https://github.com/',
type: 'supported',
},
{
value: 'hackernews',
Expand All @@ -92,6 +83,7 @@ export const SUPPORTED_CARDS: SupportedCard[] = [
label: 'Hackernews',
component: HackernewsCard,
link: 'https://news.ycombinator.com/',
type: 'supported',
},
{
value: 'conferences',
Expand All @@ -100,6 +92,7 @@ export const SUPPORTED_CARDS: SupportedCard[] = [
label: 'Upcoming events',
component: ConferencesCard,
link: 'https://confs.tech/',
type: 'supported',
},
{
value: 'devto',
Expand All @@ -108,6 +101,7 @@ export const SUPPORTED_CARDS: SupportedCard[] = [
label: 'DevTo',
component: DevtoCard,
link: 'https://dev.to/',
type: 'supported',
},
{
value: 'producthunt',
Expand All @@ -116,6 +110,7 @@ export const SUPPORTED_CARDS: SupportedCard[] = [
label: 'Product Hunt',
component: ProductHuntCard,
link: 'https://producthunt.com/',
type: 'supported',
},
{
value: 'reddit',
Expand All @@ -124,6 +119,7 @@ export const SUPPORTED_CARDS: SupportedCard[] = [
label: 'Reddit',
component: RedditCard,
link: 'https://reddit.com/',
type: 'supported',
},
{
value: 'lobsters',
Expand All @@ -132,6 +128,7 @@ export const SUPPORTED_CARDS: SupportedCard[] = [
label: 'Lobsters',
component: LobstersCard,
link: 'https://lobste.rs/',
type: 'supported',
},
{
value: 'hashnode',
Expand All @@ -140,6 +137,7 @@ export const SUPPORTED_CARDS: SupportedCard[] = [
label: 'Hashnode',
component: HashnodeCard,
link: 'https://hashnode.com/',
type: 'supported',
},
{
value: 'freecodecamp',
Expand All @@ -148,6 +146,7 @@ export const SUPPORTED_CARDS: SupportedCard[] = [
label: 'FreeCodeCamp',
component: FreecodecampCard,
link: 'https://freecodecamp.com/news',
type: 'supported',
},
{
value: 'indiehackers',
Expand All @@ -156,6 +155,7 @@ export const SUPPORTED_CARDS: SupportedCard[] = [
label: 'IndieHackers',
component: IndiehackersCard,
link: 'https://indiehackers.com/',
type: 'supported',
},
{
value: 'medium',
Expand All @@ -164,6 +164,7 @@ export const SUPPORTED_CARDS: SupportedCard[] = [
label: 'Medium',
component: MediumCard,
link: 'https://medium.com/',
type: 'supported',
},
]

Expand Down
21 changes: 10 additions & 11 deletions src/features/MarketingBanner/components/MarketingBanner.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import DOMPurify from 'dompurify'
import { useMarketingConfigStore } from '../stores/marketingBanner'
import { useUserPreferences } from 'src/stores/preferences'
import { getAppVersion } from 'src/utils/Os'
import { isWebOrExtensionVersion, isProduction, getBrowserName } from 'src/utils/Environment'
import { useMemo, useState, useEffect } from 'react'
import { Campaign, MarketingConfig } from '../types'
import { useGetMarketingConfig } from '../api/getMarketingConfig'
import jsonPath from 'jsonpath'
import { useEffect, useMemo, useState } from 'react'
import { isMobile } from 'react-device-detect'
import {
trackMarketingCampaignClose,
trackMarketingCampaignView,
trackMarketingCampaignOpen,
trackMarketingCampaignView,
} from 'src/lib/analytics'
import { useUserPreferences } from 'src/stores/preferences'
import { diffBetweenTwoDatesInDays } from 'src/utils/DateUtils'
import { isMobile } from 'react-device-detect'
import jsonPath from 'jsonpath'
import { getBrowserName, isProduction, isWebOrExtensionVersion } from 'src/utils/Environment'
import { getAppVersion } from 'src/utils/Os'
import { useGetMarketingConfig } from '../api/getMarketingConfig'
import { useMarketingConfigStore } from '../stores/marketingBanner'
import { Campaign, MarketingConfig } from '../types'

export const MarketingBanner = () => {
const { setCampaignClosed, closedCampaigns } = useMarketingConfigStore()
Expand Down Expand Up @@ -79,7 +79,6 @@ export const MarketingBanner = () => {

return availableCampaigns
} catch (e) {
console.log('getAvailableCampaigns', e)
return []
}
}
Expand Down
5 changes: 3 additions & 2 deletions src/features/MarketingBanner/stores/marketingBanner.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import create from 'zustand';
import { persist } from 'zustand/middleware'
import { create } from 'zustand';

import { persist } from 'zustand/middleware';

type ClosedCampaign = {
id: string;
Expand Down
Loading