From 1f4f68530f854361d96a5fc5451f9122eb59b344 Mon Sep 17 00:00:00 2001 From: Hongbo Wu Date: Wed, 3 Apr 2024 16:59:50 +0800 Subject: [PATCH 1/4] add tests for filters --- .../api/test/services/library_item.test.ts | 140 ++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 packages/api/test/services/library_item.test.ts diff --git a/packages/api/test/services/library_item.test.ts b/packages/api/test/services/library_item.test.ts new file mode 100644 index 000000000..c567db29d --- /dev/null +++ b/packages/api/test/services/library_item.test.ts @@ -0,0 +1,140 @@ +import { expect } from 'chai' +import 'mocha' +import { filterItemEvents } from '../../src/services/library_item' +import { parseSearchQuery } from '../../src/utils/search' + +describe('filterItemEvents', () => { + it('returns events if there are quotation marks in the subscription name', () => { + const query = 'subscription:"Best \\\"Omnivore\\\""' + const ast = parseSearchQuery(query) + const events = [ + { + subscription: 'Best "Omnivore"', + }, + ] + const result = filterItemEvents(ast, events) + expect(result).to.eql(events) + }) + + it('returns events if subscription name equals ignore case', () => { + const query = 'subscription:substack' + const ast = parseSearchQuery(query) + const events = [ + { + subscription: 'Substack', + }, + ] + const result = filterItemEvents(ast, events) + expect(result).to.eql(events) + }) + + it('returns events if site name equals ignore case', () => { + const query = 'site:youtube' + const ast = parseSearchQuery(query) + const events = [ + { + siteName: 'YouTube', + }, + ] + const result = filterItemEvents(ast, events) + expect(result).to.eql(events) + }) + + it('returns events if site name contains the search query', () => { + const query = 'site:standard' + const ast = parseSearchQuery(query) + const events = [ + { + siteName: 'Der Standard', + }, + ] + const result = filterItemEvents(ast, events) + expect(result).to.eql(events) + }) + + it('returns events if domain name contains the search query', () => { + const query = 'site:stackoverflow.com' + const ast = parseSearchQuery(query) + const events = [ + { + siteName: 'Stack Overflow', + originalUrl: 'https://stackoverflow.com/questions/123', + }, + ] + const result = filterItemEvents(ast, events) + expect(result).to.eql(events) + }) + + it('returns events if top level domain matches', () => { + const query = 'site:".com"' + const ast = parseSearchQuery(query) + const events = [ + { + siteName: 'Stack Overflow', + originalUrl: 'https://stackoverflow.com/questions/123', + }, + ] + const result = filterItemEvents(ast, events) + expect(result).to.eql(events) + }) + + it('returns events if labels match the search query', () => { + const query = 'label:foo' + const ast = parseSearchQuery(query) + const events = [ + { + labelNames: ['foo'], + }, + ] + const result = filterItemEvents(ast, events) + expect(result).to.eql(events) + }) + + it('returns events if labels contain quotation marks', () => { + const query = 'label:"foo \\\"bar\\\""' + const ast = parseSearchQuery(query) + const events = [ + { + labelNames: ['foo "bar"'], + }, + ] + const result = filterItemEvents(ast, events) + expect(result).to.eql(events) + }) + + it('returns events if labels contain space', () => { + const query = 'label:"foo bar"' + const ast = parseSearchQuery(query) + const events = [ + { + labelNames: ['foo bar'], + }, + ] + const result = filterItemEvents(ast, events) + expect(result).to.eql(events) + }) + + it('returns events if labels match the search query ignore case', () => { + const query = 'label:Foo' + const ast = parseSearchQuery(query) + const events = [ + { + labelNames: ['foo'], + }, + ] + const result = filterItemEvents(ast, events) + expect(result).to.eql(events) + }) + + it('returns events if labels match the search query with multiple labels', () => { + const query = 'label:foo,bar' + const ast = parseSearchQuery(query) + const events = [ + { + labelNames: ['foo', 'bar'], + }, + ] + const result = filterItemEvents(ast, events) + expect(result).to.eql(events) + }) +}) From 95556f659708fa65fe29fd0575ff75be219d4312 Mon Sep 17 00:00:00 2001 From: Hongbo Wu Date: Wed, 3 Apr 2024 17:00:21 +0800 Subject: [PATCH 2/4] escape quotes for subscription search on Web --- .../templates/navMenu/LibraryLegacyMenu.tsx | 33 ++++++----- .../templates/navMenu/LibraryMenu.tsx | 57 ++++++++++--------- packages/web/pages/settings/shortcuts.tsx | 44 ++++++-------- packages/web/utils/helper.ts | 1 + 4 files changed, 67 insertions(+), 68 deletions(-) create mode 100644 packages/web/utils/helper.ts diff --git a/packages/web/components/templates/navMenu/LibraryLegacyMenu.tsx b/packages/web/components/templates/navMenu/LibraryLegacyMenu.tsx index 7fa8dcf8a..20a31c0be 100644 --- a/packages/web/components/templates/navMenu/LibraryLegacyMenu.tsx +++ b/packages/web/components/templates/navMenu/LibraryLegacyMenu.tsx @@ -1,24 +1,25 @@ +import { useRegisterActions } from 'kbar' +import Link from 'next/link' +import { Circle, X } from 'phosphor-react' import { ReactNode, useEffect, useMemo, useRef } from 'react' -import { StyledText } from '../../elements/StyledText' -import { Box, HStack, SpanBox, VStack } from '../../elements/LayoutPrimitives' -import { Button } from '../../elements/Button' -import { Circle, NewspaperClipping, X } from 'phosphor-react' +import { usePersistedState } from '../../../lib/hooks/usePersistedState' +import { Label } from '../../../lib/networking/fragments/labelFragment' +import { SavedSearch } from '../../../lib/networking/fragments/savedSearchFragment' +import { useGetLabelsQuery } from '../../../lib/networking/queries/useGetLabelsQuery' +import { useGetSavedSearchQuery } from '../../../lib/networking/queries/useGetSavedSearchQuery' import { Subscription, SubscriptionType, useGetSubscriptionsQuery, } from '../../../lib/networking/queries/useGetSubscriptionsQuery' -import { useGetLabelsQuery } from '../../../lib/networking/queries/useGetLabelsQuery' -import { Label } from '../../../lib/networking/fragments/labelFragment' -import { theme } from '../../tokens/stitches.config' -import { useRegisterActions } from 'kbar' -import { LogoBox } from '../../elements/LogoBox' -import { usePersistedState } from '../../../lib/hooks/usePersistedState' -import { useGetSavedSearchQuery } from '../../../lib/networking/queries/useGetSavedSearchQuery' -import { SavedSearch } from '../../../lib/networking/fragments/savedSearchFragment' +import { escapeQuotes } from '../../../utils/helper' +import { Button } from '../../elements/Button' import { ToggleCaretDownIcon } from '../../elements/icons/ToggleCaretDownIcon' -import Link from 'next/link' import { ToggleCaretRightIcon } from '../../elements/icons/ToggleCaretRightIcon' +import { Box, HStack, SpanBox, VStack } from '../../elements/LayoutPrimitives' +import { LogoBox } from '../../elements/LogoBox' +import { StyledText } from '../../elements/StyledText' +import { theme } from '../../tokens/stitches.config' import { NavMenuFooter } from './Footer' export const LIBRARY_LEFT_MENU_WIDTH = '275px' @@ -255,7 +256,7 @@ function Subscriptions( name: name, keywords: '*' + name, perform: () => { - props.applySearchQuery(`subscription:\"${name}\"`) + props.applySearchQuery(`subscription:\"${escapeQuotes(name)}\"`) }, } }), @@ -291,7 +292,9 @@ function Subscriptions( return ( diff --git a/packages/web/components/templates/navMenu/LibraryMenu.tsx b/packages/web/components/templates/navMenu/LibraryMenu.tsx index 7a48e621b..0da615ab0 100644 --- a/packages/web/components/templates/navMenu/LibraryMenu.tsx +++ b/packages/web/components/templates/navMenu/LibraryMenu.tsx @@ -1,36 +1,37 @@ -import { ReactNode, useEffect, useMemo, useRef, useState } from "react" -import { StyledText } from '../../elements/StyledText' -import { Box, HStack, SpanBox, VStack } from '../../elements/LayoutPrimitives' -import { Button } from '../../elements/Button' +import { useRegisterActions } from 'kbar' +import Link from 'next/link' +import { useRouter } from 'next/router' import { Circle, DotsThree, MagnifyingGlass, X } from 'phosphor-react' +import { ReactNode, useEffect, useMemo, useRef, useState } from 'react' +import { usePersistedState } from '../../../lib/hooks/usePersistedState' +import { Label } from '../../../lib/networking/fragments/labelFragment' +import { SavedSearch } from '../../../lib/networking/fragments/savedSearchFragment' +import { useGetLabelsQuery } from '../../../lib/networking/queries/useGetLabelsQuery' +import { useGetSavedSearchQuery } from '../../../lib/networking/queries/useGetSavedSearchQuery' import { Subscription, SubscriptionType, useGetSubscriptionsQuery, } from '../../../lib/networking/queries/useGetSubscriptionsQuery' -import { useGetLabelsQuery } from '../../../lib/networking/queries/useGetLabelsQuery' -import { Label } from '../../../lib/networking/fragments/labelFragment' -import { theme } from '../../tokens/stitches.config' -import { useRegisterActions } from 'kbar' -import { LogoBox } from '../../elements/LogoBox' -import { usePersistedState } from '../../../lib/hooks/usePersistedState' -import { useGetSavedSearchQuery } from '../../../lib/networking/queries/useGetSavedSearchQuery' -import { SavedSearch } from '../../../lib/networking/fragments/savedSearchFragment' -import { ToggleCaretDownIcon } from '../../elements/icons/ToggleCaretDownIcon' -import Link from 'next/link' -import { ToggleCaretRightIcon } from '../../elements/icons/ToggleCaretRightIcon' -import { NavMenuFooter } from './Footer' +import { Shortcut } from '../../../pages/settings/shortcuts' +import { escapeQuotes } from '../../../utils/helper' +import { Button } from '../../elements/Button' +import { CoverImage } from '../../elements/CoverImage' +import { Dropdown, DropdownOption } from '../../elements/DropdownElements' +import { DiscoverIcon } from '../../elements/icons/DiscoverIcon' import { FollowingIcon } from '../../elements/icons/FollowingIcon' +import { HighlightsIcon } from '../../elements/icons/HighlightsIcon' import { HomeIcon } from '../../elements/icons/HomeIcon' import { LibraryIcon } from '../../elements/icons/LibraryIcon' -import { HighlightsIcon } from '../../elements/icons/HighlightsIcon' -import { CoverImage } from '../../elements/CoverImage' -import { Shortcut } from '../../../pages/settings/shortcuts' -import { OutlinedLabelChip } from '../../elements/OutlinedLabelChip' import { NewsletterIcon } from '../../elements/icons/NewsletterIcon' -import { Dropdown, DropdownOption } from '../../elements/DropdownElements' -import { useRouter } from 'next/router' -import { DiscoverIcon } from "../../elements/icons/DiscoverIcon" +import { ToggleCaretDownIcon } from '../../elements/icons/ToggleCaretDownIcon' +import { ToggleCaretRightIcon } from '../../elements/icons/ToggleCaretRightIcon' +import { Box, HStack, SpanBox, VStack } from '../../elements/LayoutPrimitives' +import { LogoBox } from '../../elements/LogoBox' +import { OutlinedLabelChip } from '../../elements/OutlinedLabelChip' +import { StyledText } from '../../elements/StyledText' +import { theme } from '../../tokens/stitches.config' +import { NavMenuFooter } from './Footer' export const LIBRARY_LEFT_MENU_WIDTH = '275px' @@ -221,7 +222,7 @@ const LibraryNav = (props: LibraryFilterMenuProps): JSX.Element => { } /> @@ -545,7 +546,7 @@ function Subscriptions( name: name, keywords: '*' + name, perform: () => { - props.applySearchQuery(`subscription:\"${name}\"`) + props.applySearchQuery(`subscription:\"${escapeQuotes(name)}\"`) }, } }), @@ -581,7 +582,9 @@ function Subscriptions( return ( @@ -735,7 +738,7 @@ type NavButtonRedirectProps = { } function NavRedirectButton(props: NavButtonRedirectProps): JSX.Element { - const [selected, setSelected] = useState(false); + const [selected, setSelected] = useState(false) const router = useRouter() useEffect(() => { diff --git a/packages/web/pages/settings/shortcuts.tsx b/packages/web/pages/settings/shortcuts.tsx index 1ee7d39f0..7d1879156 100644 --- a/packages/web/pages/settings/shortcuts.tsx +++ b/packages/web/pages/settings/shortcuts.tsx @@ -1,40 +1,32 @@ -import { - ReactNode, - useCallback, - useEffect, - useMemo, - useReducer, - useState, -} from 'react' -import { applyStoredTheme } from '../../lib/themeUpdater' - -import { useGetLabelsQuery } from '../../lib/networking/queries/useGetLabelsQuery' -import { useGetSavedSearchQuery } from '../../lib/networking/queries/useGetSavedSearchQuery' -import { SettingsLayout } from '../../components/templates/SettingsLayout' +import { styled } from '@stitches/react' +import { CheckSquare, Square } from 'phosphor-react' +import { ReactNode, useCallback, useEffect, useMemo, useReducer } from 'react' import { Toaster } from 'react-hot-toast' +import { Button } from '../../components/elements/Button' +import { CoverImage } from '../../components/elements/CoverImage' +import { DragIcon } from '../../components/elements/icons/DragIcon' +import { LabelChip } from '../../components/elements/LabelChip' import { Box, - VStack, HStack, - SpanBox, Separator, + SpanBox, + VStack, } from '../../components/elements/LayoutPrimitives' -import { LabelChip } from '../../components/elements/LabelChip' import { StyledText } from '../../components/elements/StyledText' +import { SettingsLayout } from '../../components/templates/SettingsLayout' +import { usePersistedState } from '../../lib/hooks/usePersistedState' +import { Label } from '../../lib/networking/fragments/labelFragment' +import { SavedSearch } from '../../lib/networking/fragments/savedSearchFragment' +import { useGetLabelsQuery } from '../../lib/networking/queries/useGetLabelsQuery' +import { useGetSavedSearchQuery } from '../../lib/networking/queries/useGetSavedSearchQuery' import { Subscription, SubscriptionType, useGetSubscriptionsQuery, } from '../../lib/networking/queries/useGetSubscriptionsQuery' -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-react' -import { Button } from '../../components/elements/Button' -import { styled } from '@stitches/react' -import { SavedSearch } from '../../lib/networking/fragments/savedSearchFragment' - +import { applyStoredTheme } from '../../lib/themeUpdater' +import { escapeQuotes } from '../../utils/helper' type ListAction = 'RESET' | 'ADD_ITEM' | 'REMOVE_ITEM' const SHORTCUTS_KEY = 'library-shortcuts' @@ -416,7 +408,7 @@ const AvailableItems = (props: ListProps): JSX.Element => { : 'feed', filter: subscription.type == SubscriptionType.NEWSLETTER - ? `subscription:\"${subscription.name}\"` + ? `subscription:\"${escapeQuotes(subscription.name)}\"` : `rss:\"${subscription.url}\"`, } props.dispatchList({ diff --git a/packages/web/utils/helper.ts b/packages/web/utils/helper.ts new file mode 100644 index 000000000..831148eed --- /dev/null +++ b/packages/web/utils/helper.ts @@ -0,0 +1 @@ +export const escapeQuotes = (str: string) => str.replace(/"/g, '\\"') From e9a587bfdb9c8879e9b0e8461fbcae6ab72bf474 Mon Sep 17 00:00:00 2001 From: Hongbo Wu Date: Wed, 3 Apr 2024 17:07:36 +0800 Subject: [PATCH 3/4] escape quotes for label search on Web --- .../templates/navMenu/LibraryLegacyMenu.tsx | 12 +++++------- .../web/components/templates/navMenu/LibraryMenu.tsx | 9 +++++---- packages/web/pages/settings/pinned-searches.tsx | 3 ++- packages/web/pages/settings/shortcuts.tsx | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/packages/web/components/templates/navMenu/LibraryLegacyMenu.tsx b/packages/web/components/templates/navMenu/LibraryLegacyMenu.tsx index 20a31c0be..58bf59f03 100644 --- a/packages/web/components/templates/navMenu/LibraryLegacyMenu.tsx +++ b/packages/web/components/templates/navMenu/LibraryLegacyMenu.tsx @@ -510,7 +510,7 @@ function LabelButton(props: LabelButtonProps): JSX.Element { const checkboxRef = useRef(null) const state = useMemo(() => { const term = props.searchTerm ?? '' - if (term.indexOf(`label:\"${props.label.name}\"`) >= 0) { + if (term.indexOf(`label:\"${escapeQuotes(props.label.name)}\"`) >= 0) { return 'on' } return 'off' @@ -560,7 +560,7 @@ function LabelButton(props: LabelButtonProps): JSX.Element { props.applySearchQuery(query.trim()) } else { props.applySearchQuery( - `${query.trim()} label:\"${props.label.name}\"` + `${query.trim()} label:\"${escapeQuotes(props.label.name)}\"` ) } }} @@ -579,16 +579,14 @@ function LabelButton(props: LabelButtonProps): JSX.Element { type="checkbox" checked={state === 'on'} onChange={(e) => { + const escapedName = escapeQuotes(props.label.name) if (e.target.checked) { props.applySearchQuery( - `${props.searchTerm ?? ''} label:\"${props.label.name}\"` + `${props.searchTerm ?? ''} label:\"${escapedName}\"` ) } else { const query = - props.searchTerm?.replace( - `label:\"${props.label.name}\"`, - '' - ) ?? '' + props.searchTerm?.replace(`label:\"${escapedName}\"`, '') ?? '' props.applySearchQuery(query) } }} diff --git a/packages/web/components/templates/navMenu/LibraryMenu.tsx b/packages/web/components/templates/navMenu/LibraryMenu.tsx index 0da615ab0..165a257ad 100644 --- a/packages/web/components/templates/navMenu/LibraryMenu.tsx +++ b/packages/web/components/templates/navMenu/LibraryMenu.tsx @@ -935,7 +935,7 @@ function LabelButton(props: LabelButtonProps): JSX.Element { const checkboxRef = useRef(null) const state = useMemo(() => { const term = props.searchTerm ?? '' - if (term.indexOf(`label:\"${props.label.name}\"`) >= 0) { + if (term.indexOf(`label:\"${escapeQuotes(props.label.name)}\"`) >= 0) { return 'on' } return 'off' @@ -985,7 +985,7 @@ function LabelButton(props: LabelButtonProps): JSX.Element { props.applySearchQuery(query.trim()) } else { props.applySearchQuery( - `${query.trim()} label:\"${props.label.name}\"` + `${query.trim()} label:\"${escapeQuotes(props.label.name)}\"` ) } }} @@ -1004,14 +1004,15 @@ function LabelButton(props: LabelButtonProps): JSX.Element { type="checkbox" checked={state === 'on'} onChange={(e) => { + const escapedLabelName = escapeQuotes(props.label.name) if (e.target.checked) { props.applySearchQuery( - `${props.searchTerm ?? ''} label:\"${props.label.name}\"` + `${props.searchTerm ?? ''} label:\"${escapedLabelName}\"` ) } else { const query = props.searchTerm?.replace( - `label:\"${props.label.name}\"`, + `label:\"${escapedLabelName}\"`, '' ) ?? '' props.applySearchQuery(query) diff --git a/packages/web/pages/settings/pinned-searches.tsx b/packages/web/pages/settings/pinned-searches.tsx index b06f8cce9..784062d14 100644 --- a/packages/web/pages/settings/pinned-searches.tsx +++ b/packages/web/pages/settings/pinned-searches.tsx @@ -21,6 +21,7 @@ import { Label } from '../../lib/networking/fragments/labelFragment' import { CheckSquare, Circle, Square } from 'phosphor-react' import { SavedSearch } from '../../lib/networking/fragments/savedSearchFragment' import { usePersistedState } from '../../lib/hooks/usePersistedState' +import { escapeQuotes } from '../../utils/helper' export type PinnedSearch = { type: 'saved-search' | 'label' @@ -282,7 +283,7 @@ function LabelButton(props: LabelButtonProps): JSX.Element { type: 'label', itemId: props.label.id, name: props.label.name, - search: `label:\"${props.label.name}\"`, + search: `label:\"${escapeQuotes(props.label.name)}\"`, }} listAction={props.listAction} > diff --git a/packages/web/pages/settings/shortcuts.tsx b/packages/web/pages/settings/shortcuts.tsx index 7d1879156..09355ee2b 100644 --- a/packages/web/pages/settings/shortcuts.tsx +++ b/packages/web/pages/settings/shortcuts.tsx @@ -357,7 +357,7 @@ const AvailableItems = (props: ListProps): JSX.Element => { type: 'label', label: label, name: label.name, - filter: `label:\"${label.name}\"`, + filter: `label:\"${escapeQuotes(label.name)}\"`, } props.dispatchList({ item, From dcfc9517974c8db41143221c9955ff7e621394fc Mon Sep 17 00:00:00 2001 From: Hongbo Wu Date: Wed, 3 Apr 2024 17:16:37 +0800 Subject: [PATCH 4/4] revert import order change --- .../templates/navMenu/LibraryLegacyMenu.tsx | 30 ++++++------ .../templates/navMenu/LibraryMenu.tsx | 48 +++++++++---------- packages/web/pages/settings/shortcuts.tsx | 48 +++++++++++-------- 3 files changed, 67 insertions(+), 59 deletions(-) diff --git a/packages/web/components/templates/navMenu/LibraryLegacyMenu.tsx b/packages/web/components/templates/navMenu/LibraryLegacyMenu.tsx index 58bf59f03..8590c3578 100644 --- a/packages/web/components/templates/navMenu/LibraryLegacyMenu.tsx +++ b/packages/web/components/templates/navMenu/LibraryLegacyMenu.tsx @@ -1,26 +1,26 @@ -import { useRegisterActions } from 'kbar' -import Link from 'next/link' -import { Circle, X } from 'phosphor-react' import { ReactNode, useEffect, useMemo, useRef } from 'react' -import { usePersistedState } from '../../../lib/hooks/usePersistedState' -import { Label } from '../../../lib/networking/fragments/labelFragment' -import { SavedSearch } from '../../../lib/networking/fragments/savedSearchFragment' -import { useGetLabelsQuery } from '../../../lib/networking/queries/useGetLabelsQuery' -import { useGetSavedSearchQuery } from '../../../lib/networking/queries/useGetSavedSearchQuery' +import { StyledText } from '../../elements/StyledText' +import { Box, HStack, SpanBox, VStack } from '../../elements/LayoutPrimitives' +import { Button } from '../../elements/Button' +import { Circle, NewspaperClipping, X } from 'phosphor-react' import { Subscription, SubscriptionType, useGetSubscriptionsQuery, } from '../../../lib/networking/queries/useGetSubscriptionsQuery' -import { escapeQuotes } from '../../../utils/helper' -import { Button } from '../../elements/Button' -import { ToggleCaretDownIcon } from '../../elements/icons/ToggleCaretDownIcon' -import { ToggleCaretRightIcon } from '../../elements/icons/ToggleCaretRightIcon' -import { Box, HStack, SpanBox, VStack } from '../../elements/LayoutPrimitives' -import { LogoBox } from '../../elements/LogoBox' -import { StyledText } from '../../elements/StyledText' +import { useGetLabelsQuery } from '../../../lib/networking/queries/useGetLabelsQuery' +import { Label } from '../../../lib/networking/fragments/labelFragment' import { theme } from '../../tokens/stitches.config' +import { useRegisterActions } from 'kbar' +import { LogoBox } from '../../elements/LogoBox' +import { usePersistedState } from '../../../lib/hooks/usePersistedState' +import { useGetSavedSearchQuery } from '../../../lib/networking/queries/useGetSavedSearchQuery' +import { SavedSearch } from '../../../lib/networking/fragments/savedSearchFragment' +import { ToggleCaretDownIcon } from '../../elements/icons/ToggleCaretDownIcon' +import Link from 'next/link' +import { ToggleCaretRightIcon } from '../../elements/icons/ToggleCaretRightIcon' import { NavMenuFooter } from './Footer' +import { escapeQuotes } from '../../../utils/helper' export const LIBRARY_LEFT_MENU_WIDTH = '275px' diff --git a/packages/web/components/templates/navMenu/LibraryMenu.tsx b/packages/web/components/templates/navMenu/LibraryMenu.tsx index 165a257ad..a2c5cbb05 100644 --- a/packages/web/components/templates/navMenu/LibraryMenu.tsx +++ b/packages/web/components/templates/navMenu/LibraryMenu.tsx @@ -1,37 +1,37 @@ -import { useRegisterActions } from 'kbar' -import Link from 'next/link' -import { useRouter } from 'next/router' +import { ReactNode, useEffect, useMemo, useRef, useState } from "react" +import { StyledText } from '../../elements/StyledText' +import { Box, HStack, SpanBox, VStack } from '../../elements/LayoutPrimitives' +import { Button } from '../../elements/Button' import { Circle, DotsThree, MagnifyingGlass, X } from 'phosphor-react' -import { ReactNode, useEffect, useMemo, useRef, useState } from 'react' -import { usePersistedState } from '../../../lib/hooks/usePersistedState' -import { Label } from '../../../lib/networking/fragments/labelFragment' -import { SavedSearch } from '../../../lib/networking/fragments/savedSearchFragment' -import { useGetLabelsQuery } from '../../../lib/networking/queries/useGetLabelsQuery' -import { useGetSavedSearchQuery } from '../../../lib/networking/queries/useGetSavedSearchQuery' import { Subscription, SubscriptionType, useGetSubscriptionsQuery, } from '../../../lib/networking/queries/useGetSubscriptionsQuery' -import { Shortcut } from '../../../pages/settings/shortcuts' -import { escapeQuotes } from '../../../utils/helper' -import { Button } from '../../elements/Button' -import { CoverImage } from '../../elements/CoverImage' -import { Dropdown, DropdownOption } from '../../elements/DropdownElements' -import { DiscoverIcon } from '../../elements/icons/DiscoverIcon' +import { useGetLabelsQuery } from '../../../lib/networking/queries/useGetLabelsQuery' +import { Label } from '../../../lib/networking/fragments/labelFragment' +import { theme } from '../../tokens/stitches.config' +import { useRegisterActions } from 'kbar' +import { LogoBox } from '../../elements/LogoBox' +import { usePersistedState } from '../../../lib/hooks/usePersistedState' +import { useGetSavedSearchQuery } from '../../../lib/networking/queries/useGetSavedSearchQuery' +import { SavedSearch } from '../../../lib/networking/fragments/savedSearchFragment' +import { ToggleCaretDownIcon } from '../../elements/icons/ToggleCaretDownIcon' +import Link from 'next/link' +import { ToggleCaretRightIcon } from '../../elements/icons/ToggleCaretRightIcon' +import { NavMenuFooter } from './Footer' import { FollowingIcon } from '../../elements/icons/FollowingIcon' -import { HighlightsIcon } from '../../elements/icons/HighlightsIcon' import { HomeIcon } from '../../elements/icons/HomeIcon' import { LibraryIcon } from '../../elements/icons/LibraryIcon' -import { NewsletterIcon } from '../../elements/icons/NewsletterIcon' -import { ToggleCaretDownIcon } from '../../elements/icons/ToggleCaretDownIcon' -import { ToggleCaretRightIcon } from '../../elements/icons/ToggleCaretRightIcon' -import { Box, HStack, SpanBox, VStack } from '../../elements/LayoutPrimitives' -import { LogoBox } from '../../elements/LogoBox' +import { HighlightsIcon } from '../../elements/icons/HighlightsIcon' +import { CoverImage } from '../../elements/CoverImage' +import { Shortcut } from '../../../pages/settings/shortcuts' import { OutlinedLabelChip } from '../../elements/OutlinedLabelChip' -import { StyledText } from '../../elements/StyledText' -import { theme } from '../../tokens/stitches.config' -import { NavMenuFooter } from './Footer' +import { NewsletterIcon } from '../../elements/icons/NewsletterIcon' +import { Dropdown, DropdownOption } from '../../elements/DropdownElements' +import { useRouter } from 'next/router' +import { DiscoverIcon } from "../../elements/icons/DiscoverIcon" +import { escapeQuotes } from "../../../utils/helper" export const LIBRARY_LEFT_MENU_WIDTH = '275px' diff --git a/packages/web/pages/settings/shortcuts.tsx b/packages/web/pages/settings/shortcuts.tsx index 09355ee2b..f9fddfec2 100644 --- a/packages/web/pages/settings/shortcuts.tsx +++ b/packages/web/pages/settings/shortcuts.tsx @@ -1,31 +1,39 @@ -import { styled } from '@stitches/react' -import { CheckSquare, Square } from 'phosphor-react' -import { ReactNode, useCallback, useEffect, useMemo, useReducer } from 'react' -import { Toaster } from 'react-hot-toast' -import { Button } from '../../components/elements/Button' -import { CoverImage } from '../../components/elements/CoverImage' -import { DragIcon } from '../../components/elements/icons/DragIcon' -import { LabelChip } from '../../components/elements/LabelChip' import { - Box, - HStack, - Separator, - SpanBox, - VStack, -} from '../../components/elements/LayoutPrimitives' -import { StyledText } from '../../components/elements/StyledText' -import { SettingsLayout } from '../../components/templates/SettingsLayout' -import { usePersistedState } from '../../lib/hooks/usePersistedState' -import { Label } from '../../lib/networking/fragments/labelFragment' -import { SavedSearch } from '../../lib/networking/fragments/savedSearchFragment' + ReactNode, + useCallback, + useEffect, + useMemo, + useReducer, + useState, +} from 'react' +import { applyStoredTheme } from '../../lib/themeUpdater' + import { useGetLabelsQuery } from '../../lib/networking/queries/useGetLabelsQuery' import { useGetSavedSearchQuery } from '../../lib/networking/queries/useGetSavedSearchQuery' +import { SettingsLayout } from '../../components/templates/SettingsLayout' +import { Toaster } from 'react-hot-toast' +import { + Box, + VStack, + HStack, + SpanBox, + Separator, +} from '../../components/elements/LayoutPrimitives' +import { LabelChip } from '../../components/elements/LabelChip' +import { StyledText } from '../../components/elements/StyledText' import { Subscription, SubscriptionType, useGetSubscriptionsQuery, } from '../../lib/networking/queries/useGetSubscriptionsQuery' -import { applyStoredTheme } from '../../lib/themeUpdater' +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-react' +import { Button } from '../../components/elements/Button' +import { styled } from '@stitches/react' +import { SavedSearch } from '../../lib/networking/fragments/savedSearchFragment' import { escapeQuotes } from '../../utils/helper' type ListAction = 'RESET' | 'ADD_ITEM' | 'REMOVE_ITEM'