diff --git a/.vscode/settings.json b/.vscode/settings.json
index 7a73a41b..4090ed0e 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,2 +1,6 @@
{
+ "editor.formatOnSave": true,
+ "editor.codeActionsOnSave": {
+ "source.organizeImports": true
+ }
}
\ No newline at end of file
diff --git a/public/base.manifest.json b/public/base.manifest.json
index 5c8e6760..bd28af6d 100644
--- a/public/base.manifest.json
+++ b/public/base.manifest.json
@@ -4,5 +4,11 @@
"version": "1.15.10",
"chrome_url_overrides": {
"newtab": "index.html"
+ },
+ "icons": {
+ "16": "/logos/logo16.png",
+ "32": "/logos/logo32.png",
+ "48": "/logos/logo48.png",
+ "128": "/logos/logo128.png"
}
}
diff --git a/src/App.js b/src/App.js
index 7f78a20c..b078d64d 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,16 +1,35 @@
-import { useState, useEffect } from 'react'
+import React, { Suspense, useEffect, useLayoutEffect, useState } from 'react'
+import 'react-contexify/dist/ReactContexify.css'
import 'src/assets/App.css'
import { Footer, Header } from 'src/components/Layout'
import { BookmarksSidebar } from 'src/features/bookmarks'
import { MarketingBanner } from 'src/features/MarketingBanner'
-import { ScrollCardsNavigator } from './components/Layout'
-import { AppContentLayout } from './components/Layout'
-import 'react-contexify/dist/ReactContexify.css'
-import { setupAnalytics, trackPageView, setupIdentification } from 'src/lib/analytics'
+import { setupAnalytics, setupIdentification, trackPageView } from 'src/lib/analytics'
+import { useUserPreferences } from 'src/stores/preferences'
+import { diffBetweenTwoDatesInDays } from 'src/utils/DateUtils'
+import { AppContentLayout, ScrollCardsNavigator } from './components/Layout'
+import { isWebOrExtensionVersion } from './utils/Environment'
+import { getAppVersion } from './utils/Os'
+
+const OnboardingModal = React.lazy(() =>
+ import('src/features/onboarding').then((module) => ({ default: module.OnboardingModal }))
+)
function App() {
const [showSideBar, setShowSideBar] = useState(false)
const [showSettings, setShowSettings] = useState(false)
+ const [showOnboarding, setShowOnboarding] = useState(true)
+ const { onboardingCompleted, firstSeenDate, markOnboardingAsCompleted } = useUserPreferences()
+
+ useLayoutEffect(() => {
+ if (!onboardingCompleted && getAppVersion() <= '1.15.9') {
+ const usageDays = diffBetweenTwoDatesInDays(firstSeenDate, Date.now())
+ if (usageDays > 0) {
+ markOnboardingAsCompleted(null)
+ }
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [onboardingCompleted, firstSeenDate])
useEffect(() => {
setupAnalytics()
@@ -21,7 +40,16 @@ function App() {
return (
<>
+
+ {!onboardingCompleted && isWebOrExtensionVersion() === 'extension' && (
+
+
+
+ )}
{
return (
diff --git a/src/components/Elements/ChipsSet/ChipsSet.tsx b/src/components/Elements/ChipsSet/ChipsSet.tsx
index 7efe7973..0e5e9d12 100644
--- a/src/components/Elements/ChipsSet/ChipsSet.tsx
+++ b/src/components/Elements/ChipsSet/ChipsSet.tsx
@@ -1,5 +1,6 @@
-import { Option } from 'src/types'
import { useState } from 'react'
+import { Option } from 'src/types'
+import './chipset.css'
type ChipProps = {
option: Option
@@ -10,30 +11,66 @@ type ChipProps = {
const Chip = ({ option, onSelect, active = false }: ChipProps) => {
return (
)
}
-
+type ChangeAction = 'ADD' | 'REMOVE'
type ChipsSetProps = {
options: Option[]
- defaultValue: Option
- onChange: (option: Option) => void
+ defaultValues?: string[]
+ canSelectMultiple?: boolean
+ onChange?: (action: ChangeAction, options: Option[]) => void
}
-export const ChipsSet = ({ options, onChange, defaultValue }: ChipsSetProps) => {
- const [selectedChip, setSelectedChip] = useState