authorgravatar for jakeleventhal@me.comJake Leventhal <jakeleventhal@me.com> 2026-09-18 01:24:56-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-09-18 02:24:56-03:00
log7a2cce826852c3a3255d7c7aa1e9c148287eba2c
treeb4d9c48f68c88834f6981e2fb323ba98fbcaab6e
parent818add08fcd73942f1f05edacc23f4019c146eeb
signature Signed by PGP key B5690EEEBB952194

feat(mobile): add copy thread ID to thread list actions (#12228)


2 files changed, 10 insertions(+), 0 deletions(-)

apps/mobile/src/features/threads/thread-list-items.tsx+5
...@@ -18,6 +18,7 @@ import { ControlPillMenu } from "../../components/ControlPill";...@@ -18,6 +18,7 @@ import { ControlPillMenu } from "../../components/ControlPill";
18import { EnvironmentMachineSymbol } from "../../components/EnvironmentMachineSymbol";18import { EnvironmentMachineSymbol } from "../../components/EnvironmentMachineSymbol";
19import { ProjectFavicon } from "../../components/ProjectFavicon";19import { ProjectFavicon } from "../../components/ProjectFavicon";
20import { cn } from "../../lib/cn";20import { cn } from "../../lib/cn";
21import { copyTextWithHaptic } from "../../lib/copyTextWithHaptic";
21import { HOME_HORIZONTAL_INSET } from "../../lib/layoutMetrics";22import { HOME_HORIZONTAL_INSET } from "../../lib/layoutMetrics";
22import { relativeTime } from "../../lib/time";23import { relativeTime } from "../../lib/time";
23import { useUniwindTheme } from "../../lib/useUniwindTheme";24import { useUniwindTheme } from "../../lib/useUniwindTheme";
...@@ -547,6 +548,7 @@ export const ThreadListRow = memo(function ThreadListRow(props: {...@@ -547,6 +548,7 @@ export const ThreadListRow = memo(function ThreadListRow(props: {
547 : []),548 : []),
548 THREAD_ROW_MENU_ACTIONS[0]!,549 THREAD_ROW_MENU_ACTIONS[0]!,
549 THREAD_ROW_MENU_ACTIONS[1]!,550 THREAD_ROW_MENU_ACTIONS[1]!,
551 { id: "copy-thread-id", title: "Copy thread ID", image: "doc.on.doc" },
550 ...buildThreadTitleRegenerationMenuItems({552 ...buildThreadTitleRegenerationMenuItems({
551 supported: props.titleRegenerationSupported,553 supported: props.titleRegenerationSupported,
552 isRegenerating: thread.titleRegeneration != null,554 isRegenerating: thread.titleRegeneration != null,
...@@ -569,6 +571,9 @@ export const ThreadListRow = memo(function ThreadListRow(props: {...@@ -569,6 +571,9 @@ export const ThreadListRow = memo(function ThreadListRow(props: {
569 if (nativeEvent.event === "new-thread-on-branch") onNewThreadOnBranch(thread);571 if (nativeEvent.event === "new-thread-on-branch") onNewThreadOnBranch(thread);
570 if (nativeEvent.event === "archive") handleArchive();572 if (nativeEvent.event === "archive") handleArchive();
571 if (nativeEvent.event === "rename") handleRename();573 if (nativeEvent.event === "rename") handleRename();
574 if (nativeEvent.event === "copy-thread-id") {
575 copyTextWithHaptic(thread.id, { target: "thread-id" });
576 }
572 if (nativeEvent.event === "regenerate-title") handleRegenerateTitle();577 if (nativeEvent.event === "regenerate-title") handleRegenerateTitle();
573 if (nativeEvent.event === "delete") handleDelete();578 if (nativeEvent.event === "delete") handleDelete();
574 },579 },
apps/mobile/src/features/threads/thread-list-v2-items.tsx+5
...@@ -24,6 +24,7 @@ import { ProjectFavicon } from "../../components/ProjectFavicon";...@@ -24,6 +24,7 @@ import { ProjectFavicon } from "../../components/ProjectFavicon";
24import { ProviderInstanceIcon } from "../../components/ProviderIcon";24import { ProviderInstanceIcon } from "../../components/ProviderIcon";
25import type { ThreadRowProviderInstance } from "./thread-provider-instance";25import type { ThreadRowProviderInstance } from "./thread-provider-instance";
26import { cn } from "../../lib/cn";26import { cn } from "../../lib/cn";
27import { copyTextWithHaptic } from "../../lib/copyTextWithHaptic";
27import { relativeTime } from "../../lib/time";28import { relativeTime } from "../../lib/time";
28import { useUniwindTheme } from "../../lib/useUniwindTheme";29import { useUniwindTheme } from "../../lib/useUniwindTheme";
29import type { PendingNewTask } from "../../state/use-pending-new-tasks";30import type { PendingNewTask } from "../../state/use-pending-new-tasks";
...@@ -670,6 +671,9 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: {...@@ -670,6 +671,9 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: {
670 if (nativeEvent.event === "archive") handleArchive();671 if (nativeEvent.event === "archive") handleArchive();
671 if (nativeEvent.event === "rename") handleRename();672 if (nativeEvent.event === "rename") handleRename();
672 if (nativeEvent.event === "regenerate-title") handleRegenerateTitle();673 if (nativeEvent.event === "regenerate-title") handleRegenerateTitle();
674 if (nativeEvent.event === "copy-thread-id") {
675 copyTextWithHaptic(thread.id, { target: "thread-id" });
676 }
673 if (nativeEvent.event === "delete") handleDelete();677 if (nativeEvent.event === "delete") handleDelete();
674 if (nativeEvent.event === "snooze:custom") {678 if (nativeEvent.event === "snooze:custom") {
675 setCustomSnoozeOpen(true);679 setCustomSnoozeOpen(true);
...@@ -1165,6 +1169,7 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: {...@@ -1165,6 +1169,7 @@ export const ThreadListV2Row = memo(function ThreadListV2Row(props: {
1165 },1169 },
1166 ]1170 ]
1167 : []),1171 : []),
1172 { id: "copy-thread-id", title: "Copy thread ID", image: "doc.on.doc" },
1168 ...(snoozedRow1173 ...(snoozedRow
1169 ? snoozedMenuActions1174 ? snoozedMenuActions
1170 : !props.settlementSupported1175 : !props.settlementSupported