feat(design): a channel's and a Plex playlist's one action list (C1) — the row's "…", Delete + undo, an action toast's 8 s floor (E28 S3e2)
- Channels: the row's full-history, hide and unsubscribe buttons become its "…" at the row end (useChannelActions: open, pin, YouTube, copy name / link, full history or the admin reset, hide with an undo toast, unsubscribe behind its danger confirm); the card layout docks the "…" beside the name (ChannelLayoutGrid moreKey). The admin reset's confirm now names the reset. - Plex playlist page: a title, a show group and a season each open the page's one row menu (a title's is its usePlexCardActions list plus the removal); no X at rest; removals take an undo toast whose Undo puts every row back at its own index in one request (bulk add `positions`); j/k walk the visible rows, Delete removes the walked one; rename and delete in the header's "…". - notify: a toast with an action lives at least 8 s (the owner's call), whatever the toast setting.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import type { ComponentProps } from "react";
|
||||
import type { ComponentProps, ReactNode } from "react";
|
||||
import type { TFunction } from "i18next";
|
||||
import { NO_TAG_SENTINEL, type ManagedChannel } from "../lib/api";
|
||||
import { formatCountOrDash, formatTotalHours, relativeTime } from "../lib/format";
|
||||
@@ -7,7 +7,7 @@ import { PriorityStepper } from "./ui/PriorityStepper";
|
||||
import ChannelLink from "./ChannelLink";
|
||||
import AboutCell from "./AboutCell";
|
||||
import { ChannelTagsControl, type SuggestedTag } from "./ChannelTags";
|
||||
import { ActionsCell, StoredCell } from "./channelCells";
|
||||
import { StoredCell } from "./channelCells";
|
||||
import { isFullySynced } from "./channelSync";
|
||||
|
||||
/** The shared "subscribers" DataTable column (right-aligned, sortable, em-dash for null) — identical
|
||||
@@ -49,16 +49,12 @@ export function tagsColumnTest(c: ManagedChannel, values: string[]): boolean {
|
||||
* column block lives outside the page component (its cell components are in channelCells). */
|
||||
export interface ChannelColumnDeps {
|
||||
t: TFunction;
|
||||
isAdmin: boolean;
|
||||
canWrite: boolean;
|
||||
prioOptions: { value: string; label: string }[];
|
||||
userTags: ComponentProps<typeof ChannelTagsControl>["userTags"];
|
||||
bumpPriority: (id: string, delta: number) => void;
|
||||
setPriority: (id: string, value: number) => void;
|
||||
onHide: (c: ManagedChannel) => void;
|
||||
onDeep: (c: ManagedChannel) => void;
|
||||
onReset: (c: ManagedChannel) => void;
|
||||
onUnsub: (c: ManagedChannel) => void;
|
||||
/** The row's "…" — the door to the channel's one action list (`useChannelActions`). */
|
||||
more: (c: ManagedChannel) => ReactNode;
|
||||
onView: (c: ManagedChannel) => void;
|
||||
toggleTag: (channelId: string, tagId: number, hasTag: boolean) => void;
|
||||
createAndAttachTag: (channelId: string, name: string) => void;
|
||||
@@ -72,16 +68,11 @@ export interface ChannelColumnDeps {
|
||||
export function buildChannelColumns(deps: ChannelColumnDeps): Column<ManagedChannel>[] {
|
||||
const {
|
||||
t,
|
||||
isAdmin,
|
||||
canWrite,
|
||||
prioOptions,
|
||||
userTags,
|
||||
bumpPriority,
|
||||
setPriority,
|
||||
onHide,
|
||||
onDeep,
|
||||
onReset,
|
||||
onUnsub,
|
||||
more,
|
||||
onView,
|
||||
toggleTag,
|
||||
createAndAttachTag,
|
||||
@@ -109,25 +100,6 @@ export function buildChannelColumns(deps: ChannelColumnDeps): Column<ManagedChan
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "actions",
|
||||
header: t("channels.cols.actions"),
|
||||
align: "left",
|
||||
nowrap: true,
|
||||
width: "5.5rem",
|
||||
cardLabel: false,
|
||||
render: (c) => (
|
||||
<ActionsCell
|
||||
c={c}
|
||||
isAdmin={isAdmin}
|
||||
canWrite={canWrite}
|
||||
onHide={() => onHide(c)}
|
||||
onDeep={() => onDeep(c)}
|
||||
onReset={() => onReset(c)}
|
||||
onUnsubscribe={() => onUnsub(c)}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "channel",
|
||||
header: t("channels.cols.channel"),
|
||||
@@ -217,5 +189,17 @@ export function buildChannelColumns(deps: ChannelColumnDeps): Column<ManagedChan
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "actions",
|
||||
header: "",
|
||||
align: "right",
|
||||
// Room for the "…" at 44px on touch (`.touch-target`), not just its 28px under a mouse.
|
||||
width: "3.25rem",
|
||||
nowrap: true,
|
||||
cardLabel: false,
|
||||
// The row's full-history, hide and unsubscribe buttons went into the menu (E28 C1): the row
|
||||
// keeps what is read or tuned all the time — priority, tags, the ✓ — and ends in its "…".
|
||||
render: more,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user