From 4f3b258363ded1a340bd1a7702da7cfd6415b954 Mon Sep 17 00:00:00 2001 From: Mo Date: Thu, 20 Oct 2022 09:28:35 -0500 Subject: [PATCH] feat: ability to favorite tags (#1852) --- .../src/javascripts/Components/Icon/Icon.tsx | 1 + .../Components/Tags/SmartViewsListItem.tsx | 2 +- .../Components/Tags/TagContextMenu.tsx | 11 +++++ .../javascripts/Components/Tags/TagsList.tsx | 20 +++++---- .../Components/Tags/TagsListItem.tsx | 17 ++++++- .../Components/Tags/TagsSection.tsx | 45 ++++++++++++------- .../Navigation/NavigationController.ts | 12 ++++- 7 files changed, 81 insertions(+), 27 deletions(-) diff --git a/packages/web/src/javascripts/Components/Icon/Icon.tsx b/packages/web/src/javascripts/Components/Icon/Icon.tsx index 48bc7e557..9fdf63366 100644 --- a/packages/web/src/javascripts/Components/Icon/Icon.tsx +++ b/packages/web/src/javascripts/Components/Icon/Icon.tsx @@ -68,6 +68,7 @@ export const ICONS = { eye: icons.EyeIcon, file: icons.FileIcon, folder: icons.FolderIcon, + fullscreen: icons.FullscreenIcon, hashtag: icons.HashtagIcon, help: icons.HelpIcon, history: icons.HistoryIcon, diff --git a/packages/web/src/javascripts/Components/Tags/SmartViewsListItem.tsx b/packages/web/src/javascripts/Components/Tags/SmartViewsListItem.tsx index cc5005e1a..6ff8cda17 100644 --- a/packages/web/src/javascripts/Components/Tags/SmartViewsListItem.tsx +++ b/packages/web/src/javascripts/Components/Tags/SmartViewsListItem.tsx @@ -37,7 +37,7 @@ const smartViewIconType = (view: SmartView, isSelected: boolean): IconType => { [SystemViewId.StarredNotes]: 'star-filled', } - return mapping[view.uuid as SystemViewId] || 'hashtag' + return mapping[view.uuid as SystemViewId] || 'window' } const getIconClass = (view: SmartView, isSelected: boolean): string => { diff --git a/packages/web/src/javascripts/Components/Tags/TagContextMenu.tsx b/packages/web/src/javascripts/Components/Tags/TagContextMenu.tsx index 5775663cd..edc04e633 100644 --- a/packages/web/src/javascripts/Components/Tags/TagContextMenu.tsx +++ b/packages/web/src/javascripts/Components/Tags/TagContextMenu.tsx @@ -46,6 +46,11 @@ const TagContextMenu = ({ navigationController, isEntitledToFolders, selectedTag navigationController.remove(selectedTag, true).catch(console.error) }, [navigationController, selectedTag]) + const onClickStar = useCallback(() => { + navigationController.setFavorite(selectedTag, !selectedTag.starred).catch(console.error) + navigationController.setContextMenuOpen(false) + }, [navigationController, selectedTag]) + const tagLastModified = useMemo( () => formatDateForContextMenu(selectedTag.userModifiedDate), [selectedTag.userModifiedDate], @@ -62,6 +67,12 @@ const TagContextMenu = ({ navigationController, isEntitledToFolders, selectedTag >
+ +
+ + {selectedTag.starred ? 'Unfavorite' : 'Favorite'} +
+
diff --git a/packages/web/src/javascripts/Components/Tags/TagsList.tsx b/packages/web/src/javascripts/Components/Tags/TagsList.tsx index 8012f7305..ce2173b10 100644 --- a/packages/web/src/javascripts/Components/Tags/TagsList.tsx +++ b/packages/web/src/javascripts/Components/Tags/TagsList.tsx @@ -9,11 +9,12 @@ import { TagsListItem } from './TagsListItem' type Props = { viewControllerManager: ViewControllerManager + type: 'all' | 'favorites' } -const TagsList: FunctionComponent = ({ viewControllerManager }: Props) => { - const tagsState = viewControllerManager.navigationController - const allTags = tagsState.allLocalRootTags +const TagsList: FunctionComponent = ({ viewControllerManager, type }: Props) => { + const navigationController = viewControllerManager.navigationController + const allTags = type === 'all' ? navigationController.allLocalRootTags : navigationController.starredTags const backend = HTML5Backend @@ -49,17 +50,20 @@ const TagsList: FunctionComponent = ({ viewControllerManager }: Props) => level={0} key={tag.uuid} tag={tag} - tagsState={tagsState} + type={type} + tagsState={navigationController} features={viewControllerManager.featuresController} linkingController={viewControllerManager.linkingController} onContextMenu={onContextMenu} /> ) })} - + {type === 'all' && ( + + )} )} diff --git a/packages/web/src/javascripts/Components/Tags/TagsListItem.tsx b/packages/web/src/javascripts/Components/Tags/TagsListItem.tsx index 249e5df0d..9bc147dc7 100644 --- a/packages/web/src/javascripts/Components/Tags/TagsListItem.tsx +++ b/packages/web/src/javascripts/Components/Tags/TagsListItem.tsx @@ -29,6 +29,7 @@ import { LinkingController } from '@/Controllers/LinkingController' type Props = { tag: SNTag + type: 'all' | 'favorites' tagsState: NavigationController features: FeaturesController linkingController: LinkingController @@ -40,7 +41,7 @@ const PADDING_BASE_PX = 14 const PADDING_PER_LEVEL_PX = 21 export const TagsListItem: FunctionComponent = observer( - ({ tag, features, tagsState, level, onContextMenu, linkingController }) => { + ({ tag, type, features, tagsState, level, onContextMenu, linkingController }) => { const { toggleAppPane } = useResponsiveAppPane() const [title, setTitle] = useState(tag.title || '') @@ -263,7 +264,18 @@ export const TagsListItem: FunctionComponent = observer(
)}
- +
{isEditing ? ( = observer( level={level + 1} key={tag.uuid} tag={tag} + type={type} tagsState={tagsState} features={features} linkingController={linkingController} diff --git a/packages/web/src/javascripts/Components/Tags/TagsSection.tsx b/packages/web/src/javascripts/Components/Tags/TagsSection.tsx index c2b30b405..0ff4abdda 100644 --- a/packages/web/src/javascripts/Components/Tags/TagsSection.tsx +++ b/packages/web/src/javascripts/Components/Tags/TagsSection.tsx @@ -52,22 +52,37 @@ const TagsSection: FunctionComponent = ({ viewControllerManager }) => { }, [viewControllerManager, checkIfMigrationNeeded]) return ( -
-
-
- - + <> + {viewControllerManager.navigationController.starredTags.length > 0 && ( +
+
+
+
+ Favorites +
+
+
+ +
+ )} + +
+
+
+ + +
-
- -
+ + + ) } diff --git a/packages/web/src/javascripts/Controllers/Navigation/NavigationController.ts b/packages/web/src/javascripts/Controllers/Navigation/NavigationController.ts index 18fe088e9..ef1d88490 100644 --- a/packages/web/src/javascripts/Controllers/Navigation/NavigationController.ts +++ b/packages/web/src/javascripts/Controllers/Navigation/NavigationController.ts @@ -35,6 +35,7 @@ export class NavigationController { tags: SNTag[] = [] smartViews: SmartView[] = [] + starredTags: SNTag[] = [] allNotesCount_ = 0 selectedUuid: AnyTag['uuid'] | undefined = undefined selected_: AnyTag | undefined @@ -66,6 +67,7 @@ export class NavigationController makeObservable(this, { tags: observable, + starredTags: observable, smartViews: observable.ref, hasAtLeastOneFolder: computed, allNotesCount_: observable, @@ -111,7 +113,7 @@ export class NavigationController this.application.streamItems([ContentType.Tag, ContentType.SmartView], ({ changed, removed }) => { runInAction(() => { this.tags = this.application.items.getDisplayableTags() - + this.starredTags = this.tags.filter((tag) => tag.starred) this.smartViews = this.application.items.getSmartViews() const currentSelectedTag = this.selected_ @@ -476,6 +478,14 @@ export class NavigationController .catch(console.error) } + public async setFavorite(tag: SNTag, favorite: boolean) { + return this.application.mutator + .changeAndSaveItem(tag, (mutator) => { + mutator.starred = favorite + }) + .catch(console.error) + } + public get editingTag(): SNTag | SmartView | undefined { return this.editing_ }