feat(subscription-column): add view tab context menu
This commit is contained in:
parent
75f5c725ac
commit
60dcd42f16
|
|
@ -7,12 +7,16 @@ import type { FC } from "react"
|
|||
import { startTransition, useCallback } from "react"
|
||||
import { useTranslation } from "react-i18next"
|
||||
|
||||
import { useUISettingKey } from "~/atoms/settings/ui"
|
||||
import { MenuItemText, useShowContextMenu } from "~/atoms/context-menu"
|
||||
import { setUISetting, useUISettingKey } from "~/atoms/settings/ui"
|
||||
import { FocusablePresets } from "~/components/common/Focusable"
|
||||
import { useNavigateEntry } from "~/hooks/biz/useNavigateEntry"
|
||||
import { parseView, useRouteParamsSelector } from "~/hooks/biz/useRouteParams"
|
||||
import { useTimelineList } from "~/hooks/biz/useTimelineList"
|
||||
import { useContextMenu } from "~/hooks/common/useContextMenu"
|
||||
|
||||
import { resetSelectedFeedIds } from "./atom"
|
||||
import { useShowTimelineTabsSettingsModal } from "./TimelineTabsSettingsModal"
|
||||
|
||||
export function SubscriptionTabButton({
|
||||
timelineId,
|
||||
|
|
@ -25,35 +29,125 @@ export function SubscriptionTabButton({
|
|||
|
||||
const isActive = activeTimelineId === timelineId
|
||||
const navigate = useNavigateEntry()
|
||||
const navigateToTimeline = useCallback(
|
||||
(nextTimelineId: string) => {
|
||||
navigate({
|
||||
timelineId: nextTimelineId,
|
||||
feedId: null,
|
||||
entryId: null,
|
||||
})
|
||||
resetSelectedFeedIds()
|
||||
},
|
||||
[navigate],
|
||||
)
|
||||
const setActive = useCallback(() => {
|
||||
navigate({
|
||||
timelineId,
|
||||
feedId: null,
|
||||
entryId: null,
|
||||
})
|
||||
resetSelectedFeedIds()
|
||||
}, [navigate, timelineId])
|
||||
navigateToTimeline(timelineId)
|
||||
}, [navigateToTimeline, timelineId])
|
||||
|
||||
const view = parseView(timelineId)
|
||||
|
||||
if (view === FeedViewType.All) {
|
||||
return <ViewAllSwitchButton isActive={isActive} setActive={setActive} shortcut={shortcut} />
|
||||
return (
|
||||
<ViewAllSwitchButton
|
||||
timelineId={timelineId}
|
||||
isActive={isActive}
|
||||
setActive={setActive}
|
||||
shortcut={shortcut}
|
||||
navigateToTimeline={navigateToTimeline}
|
||||
/>
|
||||
)
|
||||
} else if (typeof view === "number") {
|
||||
return (
|
||||
<ViewSwitchButton view={view} isActive={isActive} setActive={setActive} shortcut={shortcut} />
|
||||
<ViewSwitchButton
|
||||
view={view}
|
||||
timelineId={timelineId}
|
||||
isActive={isActive}
|
||||
setActive={setActive}
|
||||
shortcut={shortcut}
|
||||
navigateToTimeline={navigateToTimeline}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const useSubscriptionTabContextMenu = ({
|
||||
timelineId,
|
||||
isActive,
|
||||
navigateToTimeline,
|
||||
}: {
|
||||
timelineId: string
|
||||
isActive: boolean
|
||||
navigateToTimeline: (timelineId: string) => void
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const showContextMenu = useShowContextMenu()
|
||||
const showTimelineTabsSettingsModal = useShowTimelineTabsSettingsModal()
|
||||
const visibleTimelineList = useTimelineList({ withAll: true, visible: true })
|
||||
const hiddenTimelineList = useTimelineList({ withAll: true, hidden: true })
|
||||
|
||||
const canHide = visibleTimelineList.filter((id) => id !== timelineId).length > 0
|
||||
|
||||
const handleHide = useCallback(() => {
|
||||
if (!canHide) return
|
||||
|
||||
const nextVisible = visibleTimelineList.filter((id) => id !== timelineId)
|
||||
const nextHidden = hiddenTimelineList.filter((id) => id !== timelineId).concat(timelineId)
|
||||
setUISetting("timelineTabs", {
|
||||
visible: nextVisible,
|
||||
hidden: nextHidden,
|
||||
})
|
||||
|
||||
if (isActive) {
|
||||
const currentIndex = visibleTimelineList.indexOf(timelineId)
|
||||
const fallbackTimelineId =
|
||||
nextVisible[currentIndex] ?? nextVisible[currentIndex - 1] ?? nextVisible[0]
|
||||
|
||||
if (fallbackTimelineId) {
|
||||
navigateToTimeline(fallbackTimelineId)
|
||||
}
|
||||
}
|
||||
}, [canHide, hiddenTimelineList, isActive, navigateToTimeline, timelineId, visibleTimelineList])
|
||||
|
||||
const contextMenuProps = useContextMenu({
|
||||
onContextMenu: async (event) => {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
await showContextMenu(
|
||||
[
|
||||
new MenuItemText({
|
||||
label: t("sidebar.timeline_tabs.hide_tab"),
|
||||
click: handleHide,
|
||||
disabled: !canHide,
|
||||
}),
|
||||
new MenuItemText({
|
||||
label: t("sidebar.timeline_tabs.customize"),
|
||||
click: showTimelineTabsSettingsModal,
|
||||
}),
|
||||
],
|
||||
event,
|
||||
)
|
||||
},
|
||||
})
|
||||
|
||||
return contextMenuProps
|
||||
}
|
||||
|
||||
const ViewAllSwitchButton: FC<{
|
||||
timelineId: string
|
||||
isActive: boolean
|
||||
setActive: () => void
|
||||
shortcut: string
|
||||
}> = ({ isActive, setActive, shortcut }) => {
|
||||
navigateToTimeline: (timelineId: string) => void
|
||||
}> = ({ timelineId, isActive, setActive, shortcut, navigateToTimeline }) => {
|
||||
const unreadByView = useUnreadByView(FeedViewType.All)
|
||||
const { t } = useTranslation()
|
||||
const showSidebarUnreadCount = useUISettingKey("sidebarShowUnreadCount")
|
||||
const item = getView(FeedViewType.All)
|
||||
const contextMenuProps = useSubscriptionTabContextMenu({
|
||||
timelineId,
|
||||
isActive,
|
||||
navigateToTimeline,
|
||||
})
|
||||
|
||||
return (
|
||||
<ActionButton
|
||||
|
|
@ -66,6 +160,7 @@ const ViewAllSwitchButton: FC<{
|
|||
"flex h-11 w-8 shrink-0 grow flex-col items-center gap-1 text-[1.375rem]",
|
||||
ELECTRON ? "hover:!bg-theme-item-hover" : "",
|
||||
)}
|
||||
{...contextMenuProps}
|
||||
onClick={(e) => {
|
||||
startTransition(() => {
|
||||
setActive()
|
||||
|
|
@ -92,10 +187,12 @@ const ViewAllSwitchButton: FC<{
|
|||
|
||||
const ViewSwitchButton: FC<{
|
||||
view: FeedViewType
|
||||
timelineId: string
|
||||
isActive: boolean
|
||||
setActive: () => void
|
||||
shortcut: string
|
||||
}> = ({ view, isActive, setActive, shortcut }) => {
|
||||
navigateToTimeline: (timelineId: string) => void
|
||||
}> = ({ view, timelineId, isActive, setActive, shortcut, navigateToTimeline }) => {
|
||||
const unreadByView = useUnreadByView(view)
|
||||
const { t } = useTranslation()
|
||||
const showSidebarUnreadCount = useUISettingKey("sidebarShowUnreadCount")
|
||||
|
|
@ -107,6 +204,11 @@ const ViewSwitchButton: FC<{
|
|||
view: item.view,
|
||||
},
|
||||
})
|
||||
const contextMenuProps = useSubscriptionTabContextMenu({
|
||||
timelineId,
|
||||
isActive,
|
||||
navigateToTimeline,
|
||||
})
|
||||
|
||||
return (
|
||||
<ActionButton
|
||||
|
|
@ -121,6 +223,7 @@ const ViewSwitchButton: FC<{
|
|||
ELECTRON ? "hover:!bg-theme-item-hover" : "",
|
||||
isOver && "border-orange-400 bg-orange-400/60",
|
||||
)}
|
||||
{...contextMenuProps}
|
||||
onClick={(e) => {
|
||||
startTransition(() => {
|
||||
setActive()
|
||||
|
|
|
|||
|
|
@ -228,7 +228,7 @@ export const useShowTimelineTabsSettingsModal = () => {
|
|||
return useCallback(() => {
|
||||
present({
|
||||
id: "timeline-tabs-settings",
|
||||
title: "Customize Timeline Tabs",
|
||||
title: "Customize View Tabs",
|
||||
content: () => <TimelineTabsSettings />,
|
||||
overlay: true,
|
||||
clickOutsideToDismiss: true,
|
||||
|
|
|
|||
|
|
@ -392,6 +392,8 @@
|
|||
"sidebar.feed_column.context_menu.rename_category_success": "Category renamed successfully",
|
||||
"sidebar.feed_column.context_menu.title": "Move to New Category",
|
||||
"sidebar.select_sort_method": "Select a sort method",
|
||||
"sidebar.timeline_tabs.customize": "Customize View Tabs...",
|
||||
"sidebar.timeline_tabs.hide_tab": "Hide this view",
|
||||
"signin.continue_with": "Continue with {{provider}}",
|
||||
"signin.sign_in_to": "Sign in to",
|
||||
"signin.sign_up_to": "Sign up to",
|
||||
|
|
|
|||
|
|
@ -387,6 +387,8 @@
|
|||
"sidebar.feed_column.context_menu.rename_category_success": "カテゴリーのリネームに成功しました",
|
||||
"sidebar.feed_column.context_menu.title": "新規カテゴリーに移動する",
|
||||
"sidebar.select_sort_method": "並べ替え方法を選択",
|
||||
"sidebar.timeline_tabs.customize": "ビュータブをカスタマイズ...",
|
||||
"sidebar.timeline_tabs.hide_tab": "このビューを非表示にする",
|
||||
"signin.continue_with": "{{provider}} で続ける",
|
||||
"signin.sign_in_to": "サインイン",
|
||||
"signin.sign_up_to": "サインアップ",
|
||||
|
|
|
|||
|
|
@ -390,6 +390,8 @@
|
|||
"sidebar.feed_column.context_menu.rename_category_success": "分类重命名成功",
|
||||
"sidebar.feed_column.context_menu.title": "移动至新分类",
|
||||
"sidebar.select_sort_method": "选择排序方法",
|
||||
"sidebar.timeline_tabs.customize": "自定义视图标签...",
|
||||
"sidebar.timeline_tabs.hide_tab": "隐藏此视图",
|
||||
"signin.continue_with": "使用 {{provider}} 登录",
|
||||
"signin.sign_in_to": "登录",
|
||||
"signin.sign_up_to": "注册",
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@
|
|||
"appearance.custom_font": "Custom Font",
|
||||
"appearance.customization.title": "Customization",
|
||||
"appearance.customize_sub_tabs.description": "Customize the subscription tabs to your liking.",
|
||||
"appearance.customize_sub_tabs.label": "Customize Subscription Tabs",
|
||||
"appearance.customize_sub_tabs.label": "Customize View Tabs",
|
||||
"appearance.customize_toolbar.description": "Customize the entry content toolbar to your liking.",
|
||||
"appearance.customize_toolbar.label": "Customize Toolbar",
|
||||
"appearance.date_format.description": "Adjust the display date format.",
|
||||
|
|
|
|||
Loading…
Reference in New Issue