From 007451b239d15d373ddedad85fc637dc78763322 Mon Sep 17 00:00:00 2001 From: ridemountainpig Date: Sat, 18 Jan 2025 12:18:40 +0800 Subject: [PATCH] Update safari extension --- extensions/safari/CHANGELOG.md | 4 + .../src/components/BookmarkListItem.tsx | 31 +++++-- .../src/components/BookmarkListSection.tsx | 14 ++- .../src/components/BookmarkTagColorForm.tsx | 88 +++++++++++++++++++ extensions/safari/src/search-bookmarks.tsx | 17 +++- 5 files changed, 145 insertions(+), 9 deletions(-) create mode 100644 extensions/safari/src/components/BookmarkTagColorForm.tsx diff --git a/extensions/safari/CHANGELOG.md b/extensions/safari/CHANGELOG.md index 0a744687f7b..ede41c554ec 100644 --- a/extensions/safari/CHANGELOG.md +++ b/extensions/safari/CHANGELOG.md @@ -1,5 +1,9 @@ # Safari Changelog +## [Update] - {PR_MERGE_DATE} + +- Add an action to set the color of a bookmark tag. + ## [Chore: Moved contributor to past contributors list] - 2025-01-15 ## [Update] - 2025-01-12 diff --git a/extensions/safari/src/components/BookmarkListItem.tsx b/extensions/safari/src/components/BookmarkListItem.tsx index 9b7344e092a..bcd5324fcaf 100644 --- a/extensions/safari/src/components/BookmarkListItem.tsx +++ b/extensions/safari/src/components/BookmarkListItem.tsx @@ -1,4 +1,4 @@ -import { Action, ActionPanel, List } from "@raycast/api"; +import { Action, ActionPanel, List, Color, Icon } from "@raycast/api"; import { getFavicon } from "@raycast/utils"; import { GeneralBookmark, ReadingListBookmark } from "../types"; import { formatDate } from "../utils"; @@ -6,8 +6,9 @@ import CopyMarkdownLinkAction from "./CopyMarkdownLinkAction"; import CopyTitleAction from "./CopyTitleAction"; import CopyUrlAction from "./CopyUrlAction"; import OpenNewWindowAction from "./OpenNewWindowAction"; +import BookmarkTagColorForm from "./BookmarkTagColorForm"; -const Actions = (props: { bookmark: ReadingListBookmark | GeneralBookmark }) => ( +const Actions = (props: { bookmark: ReadingListBookmark | GeneralBookmark; fetchTagColor?: () => void }) => ( @@ -24,16 +25,30 @@ const Actions = (props: { bookmark: ReadingListBookmark | GeneralBookmark }) => shortcut={{ modifiers: ["cmd"], key: "s" }} /> + {!("dateAdded" in props.bookmark) && ( + + } + onPop={props.fetchTagColor} + /> + + )} ); -export default function BookmarkListItem(props: { bookmark: ReadingListBookmark | GeneralBookmark }) { +export default function BookmarkListItem(props: { + bookmark: ReadingListBookmark | GeneralBookmark; + tagColor?: { [key: string]: string }; + fetchTagColor?: () => void; +}) { return ( } + actions={} accessories={ "dateAdded" in props.bookmark ? [ @@ -43,7 +58,13 @@ export default function BookmarkListItem(props: { bookmark: ReadingListBookmark ] : [ { - tag: props.bookmark.folder, + tag: { + value: props.bookmark.folder, + color: + props.tagColor && props.tagColor[props.bookmark.folder] + ? Color[props.tagColor[props.bookmark.folder] as keyof typeof Color] + : undefined, + }, }, ] } diff --git a/extensions/safari/src/components/BookmarkListSection.tsx b/extensions/safari/src/components/BookmarkListSection.tsx index 3354e1ee0f4..b0d8023a1b4 100644 --- a/extensions/safari/src/components/BookmarkListSection.tsx +++ b/extensions/safari/src/components/BookmarkListSection.tsx @@ -4,11 +4,21 @@ import { GeneralBookmark } from "../types"; import { plural } from "../utils"; import BookmarkListItem from "./BookmarkListItem"; -export default function BookmarkListSection(props: { title: string; filteredBookmarks: GeneralBookmark[] }) { +export default function BookmarkListSection(props: { + title: string; + filteredBookmarks: GeneralBookmark[]; + tagColor: { [key: string]: string }; + fetchTagColor: () => void; +}) { return ( {props.filteredBookmarks.map((bookmark) => ( - + ))} ); diff --git a/extensions/safari/src/components/BookmarkTagColorForm.tsx b/extensions/safari/src/components/BookmarkTagColorForm.tsx new file mode 100644 index 00000000000..dad3eafd7cf --- /dev/null +++ b/extensions/safari/src/components/BookmarkTagColorForm.tsx @@ -0,0 +1,88 @@ +import { ActionPanel, Form, Action, Color, Icon, LocalStorage, showToast, Toast, useNavigation } from "@raycast/api"; +import { useEffect, useState } from "react"; + +export default function BookmarkTagColorForm(props: { tagName: string }) { + const { pop } = useNavigation(); + const [isLoading, setIsLoading] = useState(true); + const [tagColor, setTagColor] = useState(""); + + useEffect(() => { + const fetchTagColor = async () => { + const tagColorLocalStorage = await LocalStorage.getItem("bookmarkTagColor"); + const tagColorObject = tagColorLocalStorage ? JSON.parse(tagColorLocalStorage as string) : {}; + setTagColor(tagColorObject[props.tagName] || "Default"); + setIsLoading(false); + }; + fetchTagColor(); + }, []); + + const saveTagColor = async (tagColor: string) => { + try { + const tagColorLocalStorage = await LocalStorage.getItem("bookmarkTagColor"); + const tagColorObject = tagColorLocalStorage ? JSON.parse(tagColorLocalStorage as string) : {}; + tagColorObject[props.tagName] = tagColor; + await LocalStorage.setItem("bookmarkTagColor", JSON.stringify(tagColorObject)); + await showToast({ + style: Toast.Style.Success, + title: "Successfully saved tag color", + }); + } catch (error) { + await showToast({ + style: Toast.Style.Failure, + title: "Failed to save tag color", + message: error instanceof Error ? error.message : undefined, + }); + } + pop(); + }; + + if (isLoading || !tagColor) { + return
; + } + + return ( + + saveTagColor(values.tagColor)} /> + + } + > + + + + + + + + + + + + + ); +} diff --git a/extensions/safari/src/search-bookmarks.tsx b/extensions/safari/src/search-bookmarks.tsx index 411a377aa47..ffea6c1e0f8 100644 --- a/extensions/safari/src/search-bookmarks.tsx +++ b/extensions/safari/src/search-bookmarks.tsx @@ -1,6 +1,6 @@ -import { List } from "@raycast/api"; +import { List, LocalStorage } from "@raycast/api"; import _ from "lodash"; -import { useState } from "react"; +import { useEffect, useState } from "react"; import { BookmarkListSection, PermissionError } from "./components"; import BookmarksDropdown from "./components/BookmarksDropdown"; import { useBookmarks } from "./hooks"; @@ -10,8 +10,19 @@ import { search } from "./utils"; export default function Command() { const [searchText, setSearchText] = useState(""); const [selectedFolder, setSelectedFolder] = useState("All Bookmarks"); + const [tagColor, setTagColor] = useState<{ [key: string]: string }>({}); const { bookmarks, hasPermission } = useBookmarks(false); + const fetchTagColor = async () => { + const tagColorLocalStorage = await LocalStorage.getItem("bookmarkTagColor"); + const tagColorObject = tagColorLocalStorage ? JSON.parse(tagColorLocalStorage as string) : {}; + setTagColor(tagColorObject); + }; + + useEffect(() => { + fetchTagColor(); + }, []); + if (!hasPermission) { return ; } @@ -53,6 +64,8 @@ export default function Command() { key={key} title={key.toString() || "Top Level Bookmarks"} filteredBookmarks={filteredBookmarks} + tagColor={tagColor} + fetchTagColor={fetchTagColor} /> ); })}