From afb79a27fba87d43e62ea06c3a64267ac3d7f4e4 Mon Sep 17 00:00:00 2001 From: DIYgod Date: Fri, 27 Sep 2024 00:53:56 +0800 Subject: [PATCH] feat: context menu of adding feeds to lists --- .../renderer/src/hooks/biz/useFeedActions.tsx | 107 +++++++++++------- .../src/modules/feed-column/category.tsx | 47 +++++--- apps/renderer/src/store/feed/hooks.ts | 13 +-- locales/app/en.json | 3 +- packages/shared/src/hono.ts | 5 +- 5 files changed, 111 insertions(+), 64 deletions(-) diff --git a/apps/renderer/src/hooks/biz/useFeedActions.tsx b/apps/renderer/src/hooks/biz/useFeedActions.tsx index 3b6c6b8a49..5153f66365 100644 --- a/apps/renderer/src/hooks/biz/useFeedActions.tsx +++ b/apps/renderer/src/hooks/biz/useFeedActions.tsx @@ -7,9 +7,11 @@ import { useModalStack } from "~/components/ui/modal" import type { NativeMenuItem } from "~/lib/native-menu" import { useFeedClaimModal } from "~/modules/claim" import { FeedForm } from "~/modules/discover/feed-form" -import { getFeedById, useFeedById } from "~/store/feed" +import { Queries } from "~/queries" +import { getFeedById, useAddFeedToFeedList, useFeedById } from "~/store/feed" import { subscriptionActions, useSubscriptionByFeedId } from "~/store/subscription" +import { useAuthQuery } from "../common" import { useNavigateEntry } from "./useNavigateEntry" import { getRouteParams } from "./useRouteParams" import { useDeleteSubscription } from "./useSubscriptionActions" @@ -36,50 +38,13 @@ export const useFeedActions = ({ const navigateEntry = useNavigateEntry() const isEntryList = type === "entryList" + const listList = useAuthQuery(Queries.lists.list()) + const addMutation = useAddFeedToFeedList() + const items = useMemo(() => { if (!feed) return [] const isList = feed?.type === "list" const items: NativeMenuItem[] = [ - { - type: "text" as const, - label: isEntryList ? t("sidebar.feed_actions.edit_feed") : t("sidebar.feed_actions.edit"), - shortcut: "E", - click: () => { - present({ - title: isList - ? t("sidebar.feed_actions.edit_list") - : t("sidebar.feed_actions.edit_feed"), - content: ({ dismiss }) => ( - - ), - }) - }, - }, - { - type: "text" as const, - label: isEntryList - ? t("sidebar.feed_actions.unfollow_feed") - : t("sidebar.feed_actions.unfollow"), - shortcut: "Meta+Backspace", - click: () => deleteSubscription.mutate(subscription), - }, - { - type: "text" as const, - label: t( - isList - ? "sidebar.feed_actions.navigate_to_list" - : "sidebar.feed_actions.navigate_to_feed", - ), - shortcut: "Meta+G", - disabled: !isEntryList || getRouteParams().feedId === feedId, - click: () => { - navigateEntry({ feedId }) - }, - }, - { - type: "separator" as const, - disabled: isEntryList, - }, ...(!isList ? [ { @@ -121,6 +86,66 @@ export const useFeedActions = ({ type: "separator" as const, disabled: isEntryList, }, + { + type: "text" as const, + label: t("sidebar.feed_column.context_menu.add_feeds_to_list"), + enabled: !!listList.data?.length, + submenu: listList.data?.map((list) => ({ + label: list.title || "", + type: "text", + icon: list.image, + click() { + return addMutation.mutate({ + feedId, + listId: list.id, + }) + }, + })), + }, + { + type: "separator" as const, + disabled: isEntryList, + }, + { + type: "text" as const, + label: isEntryList ? t("sidebar.feed_actions.edit_feed") : t("sidebar.feed_actions.edit"), + shortcut: "E", + click: () => { + present({ + title: isList + ? t("sidebar.feed_actions.edit_list") + : t("sidebar.feed_actions.edit_feed"), + content: ({ dismiss }) => ( + + ), + }) + }, + }, + { + type: "text" as const, + label: isEntryList + ? t("sidebar.feed_actions.unfollow_feed") + : t("sidebar.feed_actions.unfollow"), + shortcut: "Meta+Backspace", + click: () => deleteSubscription.mutate(subscription), + }, + { + type: "text" as const, + label: t( + isList + ? "sidebar.feed_actions.navigate_to_list" + : "sidebar.feed_actions.navigate_to_feed", + ), + shortcut: "Meta+G", + disabled: !isEntryList || getRouteParams().feedId === feedId, + click: () => { + navigateEntry({ feedId }) + }, + }, + { + type: "separator" as const, + disabled: isEntryList, + }, { type: "text" as const, label: t( diff --git a/apps/renderer/src/modules/feed-column/category.tsx b/apps/renderer/src/modules/feed-column/category.tsx index 596736dc22..506e2f135b 100644 --- a/apps/renderer/src/modules/feed-column/category.tsx +++ b/apps/renderer/src/modules/feed-column/category.tsx @@ -10,12 +10,13 @@ import { LoadingCircle } from "~/components/ui/loading" import { ROUTE_FEED_IN_FOLDER, views } from "~/constants" import { useNavigateEntry } from "~/hooks/biz/useNavigateEntry" import { getRouteParams, useRouteParamsSelector } from "~/hooks/biz/useRouteParams" -import { useAnyPointDown, useInputComposition } from "~/hooks/common" +import { useAnyPointDown, useAuthQuery, useInputComposition } from "~/hooks/common" import { stopPropagation } from "~/lib/dom" import type { FeedViewType } from "~/lib/enum" import { showNativeMenu } from "~/lib/native-menu" import { cn, sortByAlphabet } from "~/lib/utils" -import { getPreferredTitle, useFeedStore } from "~/store/feed" +import { Queries } from "~/queries" +import { getPreferredTitle, useAddFeedToFeedList, useFeedStore } from "~/store/feed" import { subscriptionActions, useSubscriptionByFeedId } from "~/store/subscription" import { useFeedUnreadStore } from "~/store/unread" @@ -115,6 +116,9 @@ function FeedCategoryImpl({ }) const isCategoryIsWaiting = isChangePending + const listList = useAuthQuery(Queries.lists.list()) + const addMutation = useAddFeedToFeedList() + return (
{!!showCollapse && ( @@ -133,6 +137,33 @@ function FeedCategoryImpl({ setIsContextMenuOpen(true) showNativeMenu( [ + { + type: "text", + label: t("sidebar.feed_column.context_menu.mark_as_read"), + click: () => { + subscriptionActions.markReadByFeedIds({ + feedIds: ids, + }) + }, + }, + { type: "separator" }, + { + type: "text", + label: t("sidebar.feed_column.context_menu.add_feeds_to_list"), + enabled: !!listList.data?.length, + submenu: listList.data?.map((list) => ({ + label: list.title || "", + type: "text", + icon: list.image, + click() { + return addMutation.mutate({ + feedIds: ids, + listId: list.id, + }) + }, + })), + }, + { type: "separator" }, { type: "text", enabled: !!(folderName && typeof view === "number"), @@ -140,9 +171,7 @@ function FeedCategoryImpl({ submenu: views .filter((v) => v.view !== view) .map((v) => ({ - // TODO: fix this type error label: t(v.name), - enabled: true, type: "text", shortcut: (v.view + 1).toString(), icon: v.icon, @@ -151,16 +180,6 @@ function FeedCategoryImpl({ }, })), }, - { - type: "text", - label: t("sidebar.feed_column.context_menu.mark_as_read"), - click: () => { - subscriptionActions.markReadByFeedIds({ - feedIds: ids, - }) - }, - }, - { type: "separator" }, { type: "text", label: t("sidebar.feed_column.context_menu.rename_category"), diff --git a/apps/renderer/src/store/feed/hooks.ts b/apps/renderer/src/store/feed/hooks.ts index e0352b6a03..726c58975f 100644 --- a/apps/renderer/src/store/feed/hooks.ts +++ b/apps/renderer/src/store/feed/hooks.ts @@ -65,15 +65,14 @@ export const useFeedHeaderTitle = () => { export const useAddFeedToFeedList = (options?: { onSuccess: () => void; onError: () => void }) => { const { t } = useTranslation("settings") return useMutation({ - mutationFn: async (payload: { feedId: string; listId: string }) => { - const feed = await apiClient.lists.feeds.$post({ - json: { - listId: payload.listId, - feedId: payload.feedId, - }, + mutationFn: async ( + payload: { feedId: string; listId: string } | { feedIds: string[]; listId: string }, + ) => { + const feeds = await apiClient.lists.feeds.$post({ + json: payload, }) - feedActions.addFeedToFeedList(payload.listId, feed.data) + feeds.data.forEach((feed) => feedActions.addFeedToFeedList(payload.listId, feed)) }, onSuccess: () => { toast.success(t("lists.feeds.add.success")) diff --git a/locales/app/en.json b/locales/app/en.json index 56ede2fbe0..d6e1b0a677 100644 --- a/locales/app/en.json +++ b/locales/app/en.json @@ -182,7 +182,8 @@ "sidebar.feed_actions.open_site_in_browser": "Open site in browser", "sidebar.feed_actions.unfollow": "Unfollow", "sidebar.feed_actions.unfollow_feed": "Unfollow feed", - "sidebar.feed_column.context_menu.change_to_other_view": "Change to other view", + "sidebar.feed_column.context_menu.add_feeds_to_list": "Add feeds to list", + "sidebar.feed_column.context_menu.change_to_other_view": "Switch to another view", "sidebar.feed_column.context_menu.delete_category": "Delete category", "sidebar.feed_column.context_menu.delete_category_confirmation": "Delete category {{folderName}}?", "sidebar.feed_column.context_menu.mark_as_read": "Mark as read", diff --git a/packages/shared/src/hono.ts b/packages/shared/src/hono.ts index 2c5fa3dcc3..e244ccef7e 100644 --- a/packages/shared/src/hono.ts +++ b/packages/shared/src/hono.ts @@ -3440,6 +3440,9 @@ declare const _routes: hono_hono_base.HonoBase