diff --git a/packages/web/components/elements/StyledText.tsx b/packages/web/components/elements/StyledText.tsx
index 50ad458fa..6c2fd86cb 100644
--- a/packages/web/components/elements/StyledText.tsx
+++ b/packages/web/components/elements/StyledText.tsx
@@ -39,11 +39,10 @@ const textVariants = {
},
settingsSection: {
fontWeight: '600',
- fontSize: '17px',
+ fontSize: '22px',
fontFamily: '$inter',
color: '$grayText',
m: '0px',
- my: '15px',
marginBlockStart: '0px',
marginBlockEnd: '0px',
},
diff --git a/packages/web/lib/navigations.ts b/packages/web/lib/navigations.ts
index 97d275d17..5953e9b9b 100644
--- a/packages/web/lib/navigations.ts
+++ b/packages/web/lib/navigations.ts
@@ -1 +1 @@
-export const DEFAULT_HOME_PATH = `/l/home`
+export const DEFAULT_HOME_PATH = `/home`
diff --git a/packages/web/pages/settings/shortcuts.tsx b/packages/web/pages/settings/shortcuts.tsx
index 06f7a6d96..da3dde540 100644
--- a/packages/web/pages/settings/shortcuts.tsx
+++ b/packages/web/pages/settings/shortcuts.tsx
@@ -31,7 +31,7 @@ import { DragIcon } from '../../components/elements/icons/DragIcon'
import { CoverImage } from '../../components/elements/CoverImage'
import { Label } from '../../lib/networking/fragments/labelFragment'
import { usePersistedState } from '../../lib/hooks/usePersistedState'
-import { CheckSquare, Square } from '@phosphor-icons/react'
+import { CheckSquare, Square, Tag } from '@phosphor-icons/react'
import { Button } from '../../components/elements/Button'
import { styled } from '@stitches/react'
import { SavedSearch } from '../../lib/networking/fragments/savedSearchFragment'
@@ -42,7 +42,13 @@ import {
Shortcut,
useGetShortcuts,
useResetShortcuts,
+ useSetShortcuts,
} from '../../lib/networking/shortcuts/useShortcuts'
+import * as Switch from '@radix-ui/react-switch'
+import { useGetSubscriptions } from '../../lib/networking/subscriptions/useGetSubscriptions'
+import { NewsletterIcon } from '../../components/elements/icons/NewsletterIcon'
+import { FollowingIcon } from '../../components/elements/icons/FollowingIcon'
+import { LIBRARY_LEFT_MENU_WIDTH } from '../../components/templates/navMenu/NavigationMenu'
function flattenShortcuts(shortcuts: Shortcut[]): string[] {
let result: string[] = []
@@ -59,20 +65,106 @@ function flattenShortcuts(shortcuts: Shortcut[]): string[] {
return result
}
+function removeShortcutById(
+ shortcuts: Shortcut[] | undefined,
+ targetId: string
+): Shortcut[] | undefined {
+ if (!shortcuts) {
+ return undefined
+ }
+ return shortcuts
+ .filter((shortcut) => shortcut.id !== targetId)
+ .map((shortcut) => ({
+ ...shortcut,
+ children: removeShortcutById(shortcut.children, targetId),
+ }))
+}
+
+type ListAction = 'RESET' | 'ADD_ITEM' | 'REMOVE_ITEM'
+
export default function Shortcuts(): JSX.Element {
- const { data: shortcuts, isLoading } = useGetShortcuts()
+ const { data, isLoading } = useGetShortcuts()
+ const setShortcuts = useSetShortcuts()
+
+ const listReducer = (
+ state: { state: string; items: Shortcut[] },
+ action: {
+ type: ListAction
+ item?: Shortcut
+ items?: Shortcut[]
+ }
+ ) => {
+ switch (action.type) {
+ case 'RESET': {
+ return { state: 'CURRENT', items: action.items ?? [] }
+ }
+ case 'ADD_ITEM': {
+ const item = action.item
+ if (!item) {
+ return state
+ }
+ const existing = state.items.find(
+ (existing) => existing.type == item.type && existing.id == item.id
+ )
+ if (existing) {
+ return state
+ }
+ state.items.push(item)
+ setShortcuts.mutate({
+ shortcuts: [...state.items],
+ })
+ return { state: 'CURRENT', items: [...state.items] }
+ }
+ case 'REMOVE_ITEM': {
+ const item = action.item
+ console.log('removing item: ', item)
+ if (!item) {
+ return state
+ }
+ const updated = removeShortcutById(state.items, item.id) ?? []
+ setShortcuts.mutate({
+ shortcuts: [...updated],
+ })
+ return { state: 'CURRENT', items: [...updated] }
+ }
+ default:
+ throw new Error('unknown action')
+ }
+ }
+
+ const [shortcuts, dispatchList] = useReducer(listReducer, {
+ state: 'INITIAL',
+ items: [],
+ })
+
const shortcutIds = useMemo(() => {
- if (shortcuts) {
- return flattenShortcuts(shortcuts)
+ if (shortcuts.items) {
+ return flattenShortcuts(shortcuts.items)
}
return []
- }, [shortcuts])
+ }, [shortcuts.items])
- console.log('shortcutIds: ', shortcutIds)
+ useEffect(() => {
+ if (!isLoading) {
+ console.log('data: ', data)
+ dispatchList({ type: 'RESET', items: data })
+ }
+ }, [data])
return (
-
+
+
+
+
+
)
}
@@ -85,187 +177,7 @@ export const SectionSeparator = styled(Separator, {
type ListProps = {
shortcutIds: string[]
- // dispatchList: (arg: { type: ListAction; item?: Shortcut | undefined }) => void
-}
-
-const AvailableItems = (props: ListProps): JSX.Element => {
- const { data: labels } = useGetLabels()
- const { data: savedSearches } = useGetSavedSearches()
- const { subscriptions } = useGetSubscriptionsQuery()
-
- const sortedLabels = useMemo(() => {
- if (!labels) {
- return []
- }
- return labels.sort((a, b) =>
- a.name.toLocaleLowerCase().localeCompare(b.name.toLocaleLowerCase())
- )
- }, [labels])
-
- const sortedSubscriptions = useMemo(() => {
- if (!subscriptions) {
- return []
- }
- return subscriptions.sort((a, b) =>
- a.name.toLocaleLowerCase().localeCompare(b.name.toLocaleLowerCase())
- )
- }, [subscriptions])
-
- const sortedsavedSearches = useMemo(() => {
- if (!savedSearches) {
- return []
- }
- return savedSearches.sort((a, b) =>
- a.name.toLocaleLowerCase().localeCompare(b.name.toLocaleLowerCase())
- )
- }, [savedSearches])
-
- const searchSelected = useCallback(
- (search: SavedSearch) => {
- return !!props.shortcutIds.find((shortcutId) => shortcutId == search.id)
- },
- [props]
- )
-
- const labelSelected = useCallback(
- (label: Label) => {
- return !!props.shortcutIds.find((shortcutId) => shortcutId == label.id)
- },
- [props]
- )
-
- const subscriptionSelected = useCallback(
- (subscription: Subscription) => {
- return !!props.shortcutIds.find(
- (shortcutId) => shortcutId == subscription.id
- )
- },
- [props]
- )
-
- console.log('sortedsavedSearchesL: ', sortedsavedSearches)
-
- return (
-
- {/* Available items */}
-
-
- {/*
- Labels
- {sortedLabels.map((label) => {
- console.log('label: ', label)
- return (
-
- )
- })}
-
-
- Subscriptions
- {sortedSubscriptions.map((subscription) => {
- console.log('subscription: ', subscription)
- return (
-
- )
- })} */}
-
- )
+ dispatchList: (arg: { type: ListAction; item?: Shortcut | undefined }) => void
}
const SavedSearches = (props: ListProps) => {
@@ -275,23 +187,266 @@ const SavedSearches = (props: ListProps) => {
if (!savedSearches) {
return []
}
- return savedSearches.sort((a, b) =>
- a.name.toLocaleLowerCase().localeCompare(b.name.toLocaleLowerCase())
+ return (
+ savedSearches
+ // .filter((search) => props.shortcutIds.indexOf(search.id) === -1)
+ .sort((a, b) =>
+ a.name.toLocaleLowerCase().localeCompare(b.name.toLocaleLowerCase())
+ )
)
- }, [savedSearches])
+ }, [props, savedSearches])
+
+ const isChecked = useCallback(
+ (shortcutId: string) => {
+ return props.shortcutIds.indexOf(shortcutId) !== -1
+ },
+ [props.shortcutIds]
+ )
+
return (
- <>
- {/* Saved Searches */}
- {/* */}
- {!isLoading &&
- (savedSearches ?? []).map((search) => {
- return (
-
- {search.name}
-
- )
- })}
- {/* */}
- >
+
+ Saved Searches
+
+ {!isLoading &&
+ (sortedsavedSearches ?? []).map((search) => {
+ return (
+
+ {search.name}
+
+ {
+ if (checked) {
+ props.dispatchList({
+ type: 'ADD_ITEM',
+ item: {
+ id: search.id,
+ type: 'search',
+ name: search.name,
+ section: 'library',
+ filter: search.filter,
+ },
+ })
+ } else {
+ props.dispatchList({
+ type: 'REMOVE_ITEM',
+ item: {
+ type: 'search',
+ section: 'library',
+ ...search,
+ },
+ })
+ }
+ }}
+ />
+
+
+ )
+ })}
+
+
)
}
+
+const Subscriptions = (props: ListProps) => {
+ const { data: subscriptions, isLoading } = useGetSubscriptions({})
+
+ const sortedSubscriptions = useMemo(() => {
+ if (!subscriptions) {
+ return []
+ }
+ return subscriptions.sort((a, b) =>
+ a.name.toLocaleLowerCase().localeCompare(b.name.toLocaleLowerCase())
+ )
+ }, [props, subscriptions])
+
+ const isChecked = useCallback(
+ (shortcutId: string) => {
+ return props.shortcutIds.indexOf(shortcutId) !== -1
+ },
+ [props.shortcutIds]
+ )
+
+ return (
+
+ Subscriptions
+
+ {!isLoading &&
+ (sortedSubscriptions ?? []).map((subscription) => {
+ return (
+
+ {subscription.icon ? (
+
+ ) : subscription.type == SubscriptionType.NEWSLETTER ? (
+
+ ) : (
+
+ )}
+ {subscription.name}
+
+ {
+ const item: Shortcut = {
+ id: subscription.id,
+ section: 'subscriptions',
+ name: subscription.name,
+ icon: subscription.icon,
+ type:
+ subscription.type == SubscriptionType.NEWSLETTER
+ ? 'newsletter'
+ : 'feed',
+ filter:
+ subscription.type == SubscriptionType.NEWSLETTER
+ ? `subscription:\"${escapeQuotes(
+ subscription.name
+ )}\"`
+ : `rss:\"${subscription.url}\"`,
+ }
+ if (checked) {
+ props.dispatchList({
+ type: 'ADD_ITEM',
+ item,
+ })
+ } else {
+ props.dispatchList({
+ type: 'REMOVE_ITEM',
+ item,
+ })
+ }
+ }}
+ />
+
+
+ )
+ })}
+
+
+ )
+}
+
+const Labels = (props: ListProps) => {
+ const { data: labels, isLoading } = useGetLabels()
+
+ const sortedLabels = useMemo(() => {
+ if (!labels) {
+ return []
+ }
+ return labels.sort((a, b) =>
+ a.name.toLocaleLowerCase().localeCompare(b.name.toLocaleLowerCase())
+ )
+ }, [props, labels])
+
+ const isChecked = useCallback(
+ (shortcutId: string) => {
+ return props.shortcutIds.indexOf(shortcutId) !== -1
+ },
+ [props.shortcutIds]
+ )
+
+ return (
+
+ Labels
+
+ {!isLoading &&
+ (sortedLabels ?? []).map((label) => {
+ return (
+
+
+
+ {label.name}
+
+
+ {
+ const item: Shortcut = {
+ id: label.id,
+ type: 'label',
+ label: label,
+ section: 'library',
+ name: label.name,
+ filter: `label:\"${escapeQuotes(label.name)}\"`,
+ }
+ if (checked) {
+ props.dispatchList({
+ type: 'ADD_ITEM',
+ item,
+ })
+ } else {
+ props.dispatchList({
+ type: 'REMOVE_ITEM',
+ item,
+ })
+ }
+ }}
+ />
+
+
+ )
+ })}
+
+
+ )
+}
+
+type SwitchBoxProps = {
+ checked: boolean
+ setChecked: (checked: boolean) => void
+}
+const SwitchBox = (props: SwitchBoxProps) => {
+ return (
+ {
+ props.setChecked(checked)
+ }}
+ >
+
+
+ )
+}
+
+const SwitchRoot = styled(Switch.Root, {
+ all: 'unset',
+ width: 42,
+ height: 25,
+ backgroundColor: '$thBorderColor',
+ borderRadius: '9999px',
+ position: 'relative',
+ WebkitTapHighlightColor: 'rgba(0, 0, 0, 0)',
+ '&:focus': { boxShadow: `0 0 0 2px $thBorderColor` },
+ '&[data-state="checked"]': { backgroundColor: '#4BB543' },
+})
+
+const SwitchThumb = styled(Switch.Thumb, {
+ display: 'block',
+ width: 21,
+ height: 21,
+ backgroundColor: '$thTextContrast2',
+ borderRadius: '9999px',
+ transition: 'transform 100ms',
+ transform: 'translateX(2px)',
+ willChange: 'transform',
+ '&[data-state="checked"]': { transform: 'translateX(19px)' },
+})