Skip to content

Commit

Permalink
Update safari extension
Browse files Browse the repository at this point in the history
  • Loading branch information
ridemountainpig committed Jan 18, 2025
1 parent f236409 commit 007451b
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 9 deletions.
4 changes: 4 additions & 0 deletions extensions/safari/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
31 changes: 26 additions & 5 deletions extensions/safari/src/components/BookmarkListItem.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
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";
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 }) => (
<ActionPanel>
<ActionPanel.Section>
<Action.OpenInBrowser url={props.bookmark.url} />
Expand All @@ -24,16 +25,30 @@ const Actions = (props: { bookmark: ReadingListBookmark | GeneralBookmark }) =>
shortcut={{ modifiers: ["cmd"], key: "s" }}
/>
</ActionPanel.Section>
{!("dateAdded" in props.bookmark) && (
<ActionPanel.Section>
<Action.Push
title="Setting Tag Color"
icon={Icon.Tag}
target={<BookmarkTagColorForm tagName={props.bookmark.folder} />}
onPop={props.fetchTagColor}
/>
</ActionPanel.Section>
)}
</ActionPanel>
);

export default function BookmarkListItem(props: { bookmark: ReadingListBookmark | GeneralBookmark }) {
export default function BookmarkListItem(props: {
bookmark: ReadingListBookmark | GeneralBookmark;
tagColor?: { [key: string]: string };
fetchTagColor?: () => void;
}) {
return (
<List.Item
title={props.bookmark.title}
subtitle={props.bookmark.domain}
icon={getFavicon(props.bookmark.url)}
actions={<Actions bookmark={props.bookmark} />}
actions={<Actions bookmark={props.bookmark} fetchTagColor={props.fetchTagColor} />}
accessories={
"dateAdded" in props.bookmark
? [
Expand All @@ -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,
},
},
]
}
Expand Down
14 changes: 12 additions & 2 deletions extensions/safari/src/components/BookmarkListSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
<List.Section title={_.startCase(props.title)} subtitle={plural(props.filteredBookmarks.length, "bookmark")}>
{props.filteredBookmarks.map((bookmark) => (
<BookmarkListItem key={bookmark.uuid} bookmark={bookmark} />
<BookmarkListItem
key={bookmark.uuid}
bookmark={bookmark}
tagColor={props.tagColor}
fetchTagColor={props.fetchTagColor}
/>
))}
</List.Section>
);
Expand Down
88 changes: 88 additions & 0 deletions extensions/safari/src/components/BookmarkTagColorForm.tsx
Original file line number Diff line number Diff line change
@@ -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<boolean>(true);
const [tagColor, setTagColor] = useState<string>("");

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 <Form isLoading />;
}

return (
<Form
actions={
<ActionPanel>
<Action.SubmitForm title="Save Tag Color" onSubmit={(values) => saveTagColor(values.tagColor)} />
</ActionPanel>
}
>
<Form.Dropdown id="tagColor" title="Tag Color" value={tagColor} onChange={setTagColor}>
<Form.Dropdown.Item value="Default" title="Default Color" />
<Form.Dropdown.Item value="Green" title="Green" icon={{ source: Icon.CircleFilled, tintColor: Color.Green }} />
<Form.Dropdown.Item
value="Magenta"
title="Magenta"
icon={{ source: Icon.CircleFilled, tintColor: Color.Magenta }}
/>
<Form.Dropdown.Item
value="Orange"
title="Orange"
icon={{ source: Icon.CircleFilled, tintColor: Color.Orange }}
/>
<Form.Dropdown.Item
value="Purple"
title="Purple"
icon={{ source: Icon.CircleFilled, tintColor: Color.Purple }}
/>
<Form.Dropdown.Item value="Red" title="Red" icon={{ source: Icon.CircleFilled, tintColor: Color.Red }} />
<Form.Dropdown.Item
value="Yellow"
title="Yellow"
icon={{ source: Icon.CircleFilled, tintColor: Color.Yellow }}
/>
<Form.Dropdown.Item
value="PrimaryText"
title="PrimaryText"
icon={{ source: Icon.CircleFilled, tintColor: Color.PrimaryText }}
/>
<Form.Dropdown.Item
value="SecondaryText"
title="SecondaryText"
icon={{ source: Icon.CircleFilled, tintColor: Color.SecondaryText }}
/>
</Form.Dropdown>
</Form>
);
}
17 changes: 15 additions & 2 deletions extensions/safari/src/search-bookmarks.tsx
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -10,8 +10,19 @@ import { search } from "./utils";
export default function Command() {
const [searchText, setSearchText] = useState<string>("");
const [selectedFolder, setSelectedFolder] = useState<string>("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 <PermissionError />;
}
Expand Down Expand Up @@ -53,6 +64,8 @@ export default function Command() {
key={key}
title={key.toString() || "Top Level Bookmarks"}
filteredBookmarks={filteredBookmarks}
tagColor={tagColor}
fetchTagColor={fetchTagColor}
/>
);
})}
Expand Down

0 comments on commit 007451b

Please sign in to comment.