Skip to content

Commit

Permalink
Merge pull request #146 from medyo/develop
Browse files Browse the repository at this point in the history
New version
  • Loading branch information
medyo authored Mar 15, 2023
2 parents 38d2e98 + 25e1ec4 commit 0c90f66
Show file tree
Hide file tree
Showing 9 changed files with 112 additions and 17 deletions.
7 changes: 6 additions & 1 deletion src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ function App() {
const [showSideBar, setShowSideBar] = useState(false)
const [showSettings, setShowSettings] = useState(false)
const [showOnboarding, setShowOnboarding] = useState(true)
const { onboardingCompleted, firstSeenDate, markOnboardingAsCompleted } = useUserPreferences()
const { onboardingCompleted, firstSeenDate, markOnboardingAsCompleted, maxVisibleCards } =
useUserPreferences()

useLayoutEffect(() => {
if (!onboardingCompleted && getAppVersion() <= '1.15.9') {
Expand All @@ -31,6 +32,10 @@ function App() {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [onboardingCompleted, firstSeenDate])

useEffect(() => {
document.documentElement.style.setProperty('--max-visible-cards', maxVisibleCards)
}, [maxVisibleCards])

useEffect(() => {
setupAnalytics()
setupIdentification()
Expand Down
20 changes: 14 additions & 6 deletions src/assets/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -1043,18 +1043,21 @@ Producthunt item
.floatingFilter {
display: block;
}
.block {
width: 100vw;
}
}
/* Small devices (portrait tablets and large phones, 600px and up) */
@media only screen and (min-width: 600px) {
.block {
width: calc(96vw / 2);
width: calc(96vw / min(2, var(--max-visible-cards)));
}
}

/* Medium devices (landscape tablets, 768px and up) */
@media only screen and (min-width: 768px) {
.block {
width: calc(96vw / 3);
width: calc(96vw / min(3, var(--max-visible-cards)));
}
.searchBarInput {
width: 200px;
Expand All @@ -1064,7 +1067,7 @@ Producthunt item
/* Large devices (desktops, 992px and up)*/
@media only screen and (min-width: 992px) {
.block {
width: calc(96vw / 3);
width: calc(96vw / min(3, var(--max-visible-cards)));
}

.searchBarInput {
Expand All @@ -1075,14 +1078,14 @@ Producthunt item
/* X-Large devices (large desktops, 1200px and up)*/
@media only screen and (min-width: 1200px) {
.block {
width: calc(96vw / 4);
width: calc(96vw / min(4, var(--max-visible-cards)));
}
}

/* XX-Large devices (larger desktops, 1400px and up)*/
@media only screen and (min-width: 1400px) {
.block {
width: calc(96vw / 4);
width: calc(95vw / min(4, var(--max-visible-cards)));
}
}

Expand All @@ -1093,7 +1096,9 @@ Producthunt item
padding: 0;
}
.block {
width: calc((1800px - 12px * 4) / 4);
width: calc(
(1800px - 14px * min(5, var(--max-visible-cards))) / min(5, var(--max-visible-cards))
);
}
}

Expand All @@ -1120,3 +1125,6 @@ Producthunt item
position: relative;
vertical-align: middle;
}
.noMargin {
margin: 0 !important;
}
9 changes: 6 additions & 3 deletions src/assets/variables.css
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
src: url('fonts/nunito/nunito-semibold.woff2') format('woff2');
}

html {
--max-visible-cards: 4;
}

html.dark {
--app-name-text-color: #fff;
--background-color: #0d1116;
Expand Down Expand Up @@ -89,7 +93,7 @@ html.dark {
--settings-input-border-color: #3a4553;
--settings-input-border-focus-color: #6b7b90;
--settings-input-placeholder-color: #42474e;
--settings-input-text-color: #fff
--settings-input-text-color: #fff;
}

html.light {
Expand Down Expand Up @@ -171,6 +175,5 @@ html.light {
--settings-input-border-color: #e9ebec;
--settings-input-border-focus-color: #c4d6df;
--settings-input-placeholder-color: #97a6ad;
--settings-input-text-color: #253b53

--settings-input-text-color: #253b53;
}
6 changes: 4 additions & 2 deletions src/components/Elements/ChipsSet/ChipsSet.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import clsx from 'clsx'
import { useState } from 'react'
import { Option } from 'src/types'
import './chipset.css'

type ChipProps = {
option: Option
onSelect: (option: Option) => void
Expand All @@ -19,12 +19,14 @@ const Chip = ({ option, onSelect, active = false }: ChipProps) => {
type ChangeAction = 'ADD' | 'REMOVE'
type ChipsSetProps = {
options: Option[]
className?: string
defaultValues?: string[]
canSelectMultiple?: boolean
onChange?: (action: ChangeAction, options: Option[]) => void
}

export const ChipsSet = ({
className,
options,
canSelectMultiple = false,
onChange,
Expand Down Expand Up @@ -62,7 +64,7 @@ export const ChipsSet = ({
}

return (
<div className="chipsSet">
<div className={clsx('chipsSet', className)}>
{options.map((option) => {
return (
<Chip
Expand Down
8 changes: 8 additions & 0 deletions src/components/Elements/ChipsSet/chipset.css
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,11 @@
background-color: var(--chip-active-background);
color: var(--chip-active-text);
}

.chipsSet.alternative-color .chip {
background-color: var(--card-action-button-background);
}
.chipsSet.alternative-color .chip.active {
background-color: var(--card-active-action-button-background);
color: var(--card-active-action-button-color);
}
2 changes: 1 addition & 1 deletion src/components/Layout/ScrollCardsNavigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export const ScrollCardsNavigator = () => {
}, [])

useLayoutEffect(() => {
setLeftButtonVisible(false)
scrollBarContainer.current = document.querySelector('.Cards')
}, [])

Expand All @@ -48,7 +49,6 @@ export const ScrollCardsNavigator = () => {
}, [handleKeyboardKeys])

useEffect(() => {
setLeftButtonVisible(false)
setRightButtonVisible(cards.length > maxCardsPerRow)
}, [cards])

Expand Down
53 changes: 52 additions & 1 deletion src/features/settings/components/SettingsModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import ReactModal from 'react-modal'
import Select, { ActionMeta, MultiValue, SingleValue } from 'react-select'
import Toggle from 'react-toggle'
import 'react-toggle/style.css'
import { ChipsSet } from 'src/components/Elements'
import { Footer } from 'src/components/Layout'
import { SUPPORTED_CARDS, SUPPORTED_SEARCH_ENGINES, supportLink } from 'src/config'
import { Tag, useRemoteConfigStore } from 'src/features/remoteConfig'
Expand All @@ -12,19 +13,21 @@ import {
identifyUserLanguages,
identifyUserLinksInNewTab,
identifyUserListingMode,
identifyUserMaxVisibleCards,
identifyUserSearchEngine,
identifyUserTheme,
trackLanguageAdd,
trackLanguageRemove,
trackListingModeSelect,
trackMaxVisibleCardsChange,
trackSearchEngineSelect,
trackSourceAdd,
trackSourceRemove,
trackTabTarget,
trackThemeSelect,
} from 'src/lib/analytics'
import { useUserPreferences } from 'src/stores/preferences'
import { SearchEngineType, SelectedCard } from 'src/types'
import { Option, SearchEngineType, SelectedCard } from 'src/types'
import { RssSetting } from './RssSetting'
import './settings.css'

Expand All @@ -48,8 +51,10 @@ export const SettingsModal = ({ showSettings, setShowSettings }: SettingsModalPr
listingMode,
theme,
searchEngine,
maxVisibleCards,
setTheme,
setListingMode,
setMaxVisibleCards,
setSearchEngine,
setOpenLinksNewTab,
setCards,
Expand Down Expand Up @@ -144,6 +149,15 @@ export const SettingsModal = ({ showSettings, setShowSettings }: SettingsModalPr
identifyUserTheme(newTheme)
}

const onMaxVisibleCardsChange = (selectedChips: Option[]) => {
if (selectedChips.length) {
const maxVisibleCards = parseInt(selectedChips[0].value)
setMaxVisibleCards(maxVisibleCards)
identifyUserMaxVisibleCards(maxVisibleCards)
trackMaxVisibleCardsChange(maxVisibleCards)
}
}

return (
<ReactModal
isOpen={showSettings}
Expand Down Expand Up @@ -215,6 +229,43 @@ export const SettingsModal = ({ showSettings, setShowSettings }: SettingsModalPr

<RssSetting setSelectedCards={setSelectedCards} />

<div className="settingRow">
<p className="settingTitle">Max number of cards to display</p>
<div className="settingContent">
<ChipsSet
className={'noMargin alternative-color'}
canSelectMultiple={false}
options={[
{
label: '3 cards',
value: '3',
},
{
label: '4 cards',
value: '4',
},
{
label: '5 cards',
value: '5',
},
{
label: '6 cards',
value: '6',
},
]}
defaultValues={[maxVisibleCards.toString()]}
onChange={(_, selectedChips) => {
onMaxVisibleCardsChange(selectedChips)
}}
/>

<p className="settingHint">
To ensure a seamless experience, we may adjust the selected number to align with the
resolution of your screen.
</p>
</div>
</div>

<div className="settingRow">
<p className="settingTitle">Dark Mode</p>
<div className="settingContent">
Expand Down
20 changes: 17 additions & 3 deletions src/lib/analytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ enum Verbs {
FINISH = 'Finish',
SKIP = 'Skip',
DRAG = 'Drag',
Change = 'Change',
}

export enum Attributes {
Expand All @@ -60,6 +61,7 @@ export enum Attributes {
SOURCE_TAGS = 'Source Tags',
CAMPAIGN_ID = 'Campaign Id',
OCCUPATION = 'Occupation',
MAX_VISIBLE_CARDS = 'Max Visible Cards',
}

const _SEP_ = ' '
Expand All @@ -82,6 +84,7 @@ export const setupIdentification = () => {
listingMode,
openLinksNewTab,
searchEngine,
maxVisibleCards
} = useUserPreferences.getState()

identifyUserProperty(Attributes.RESOLUTION, getScreenResolution())
Expand All @@ -91,6 +94,7 @@ export const setupIdentification = () => {
identifyUserListingMode(listingMode)
identifyUserSearchEngine(searchEngine)
identifyUserLinksInNewTab(openLinksNewTab)
identifyUserMaxVisibleCards(maxVisibleCards)
if (onboardingResult?.title) {
identifyUserOccupation(onboardingResult.title)
}
Expand Down Expand Up @@ -291,6 +295,14 @@ export const trackPageDrag = () => {
})
}

export const trackMaxVisibleCardsChange = (maxVisibleCards: number) => {
trackEvent({
object: Objects.CARD,
verb: Verbs.Change,
attributes: {[Attributes.MAX_VISIBLE_CARDS]: maxVisibleCards}
})
}

// Identification

export const identifyUserLanguages = (languages: string[]) => {
Expand All @@ -317,7 +329,9 @@ export const identifyUserLinksInNewTab = (enabled: boolean) => {
export const identifyUserOccupation = (occupation: string) => {
identifyUserProperty(Attributes.OCCUPATION, occupation)
}

export const identifyUserMaxVisibleCards = (maxVisibleCards: number) => {
identifyUserProperty(Attributes.MAX_VISIBLE_CARDS, maxVisibleCards)
}

// Private functions
type trackEventProps = {
Expand Down Expand Up @@ -365,13 +379,13 @@ const trackEvent = ({ object, verb, attributes }: trackEventProps) => {
}
}

const identifyUserProperty = (attributes: Attributes, value: string | string[]) => {
const identifyUserProperty = (attributes: Attributes, value: string | number | string[]) => {
try {
let formatedValue
if (Array.isArray(value)) {
formatedValue = value.filter(Boolean).map((item) => item.toLowerCase())
} else {
formatedValue = value.toLowerCase()
formatedValue = typeof value === "string" ? value.toLowerCase() : value.toString()
}

if (isDevelopment()) {
Expand Down
4 changes: 4 additions & 0 deletions src/stores/preferences.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export type UserPreferencesState = {
onboardingResult: Omit<Occupation, 'icon'> | null
listingMode: ListingMode
searchEngine: string
maxVisibleCards: number
cards: SelectedCard[]
cardsSettings: Record<string, CardSettingsType>
firstSeenDate: number
Expand All @@ -28,6 +29,7 @@ type UserPreferencesStoreActions = {
setListingMode: (listingMode: ListingMode) => void
setCards: (selectedCards: SelectedCard[]) => void
setTags: (selectedTags: Tag[]) => void
setMaxVisibleCards: (maxVisibleCards: number) => void
setCardSettings: (card: string, settings: CardSettingsType) => void
markOnboardingAsCompleted: (occupation: Omit<Occupation, 'icon'> | null) => void
setUserCustomCards: (cards: SupportedCardType[]) => void
Expand All @@ -39,6 +41,7 @@ export const useUserPreferences = create(
(set) => ({
userSelectedTags: [],
cardsSettings: {},
maxVisibleCards: 4,
theme: 'dark',
onboardingCompleted: false,
onboardingResult: null,
Expand All @@ -59,6 +62,7 @@ export const useUserPreferences = create(
setOpenLinksNewTab: (openLinksNewTab: boolean) => set({ openLinksNewTab: openLinksNewTab }),
setCards: (selectedCards: SelectedCard[]) => set({ cards: selectedCards }),
setTags: (selectedTags: Tag[]) => set({ userSelectedTags: selectedTags }),
setMaxVisibleCards: (maxVisibleCards: number) => set({ maxVisibleCards: maxVisibleCards }),
initState: (newState: UserPreferencesState) =>
set(() => {
return { ...newState }
Expand Down

0 comments on commit 0c90f66

Please sign in to comment.