diff --git a/apps/mobile/src/features/connection/CloudEnvironmentRows.tsx b/apps/mobile/src/features/connection/CloudEnvironmentRows.tsx
index dbb1dca068d45625caf356a6dc71850186b501d3..cccc6425ec1314d6ede19cc2c6c91d41c6a6b4f0 100644
--- a/apps/mobile/src/features/connection/CloudEnvironmentRows.tsx
+++ b/apps/mobile/src/features/connection/CloudEnvironmentRows.tsx
@@ -1,3 +1,4 @@
+import { ConnectionTraceId } from "./ConnectionTraceId";
import { useAuth } from "@clerk/expo";
import { SymbolView } from "../../components/AppSymbol";
import {
@@ -405,23 +406,15 @@ function CloudEnvironmentRowShell(props: {
>
{statusText}
{errorTraceId ? (
- <>
- {" Trace ID: "}
- {
- event.stopPropagation();
- copyTextWithHaptic(errorTraceId, { target: "connection-trace-id" });
- }}
- onPress={(event) => {
- event.stopPropagation();
- }}
- >
- {errorTraceId}
-
- >
+
) : null}
{errorCanExpand ? (
diff --git a/apps/mobile/src/features/connection/ConnectionEnvironmentRow.tsx b/apps/mobile/src/features/connection/ConnectionEnvironmentRow.tsx
index a42db147c17d6f9aab92f9cfc3a00d39377acae4..b4e32a06f55b68360c1d419ba25b45d04224de3b 100644
--- a/apps/mobile/src/features/connection/ConnectionEnvironmentRow.tsx
+++ b/apps/mobile/src/features/connection/ConnectionEnvironmentRow.tsx
@@ -1,3 +1,4 @@
+import { ConnectionTraceId } from "./ConnectionTraceId";
import { SymbolView } from "../../components/AppSymbol";
import { connectionStatusText } from "@t3tools/client-runtime/connection";
import type { AtomCommandResult } from "@t3tools/client-runtime/state/runtime";
@@ -15,7 +16,6 @@ import { MaterialButton } from "../../components/MaterialButton";
import { MaterialIconButton } from "../../components/MaterialIconButton";
import { ThemedSwitch } from "../../components/ThemedSwitch";
import { cn } from "../../lib/cn";
-import { copyTextWithHaptic } from "../../lib/copyTextWithHaptic";
import type { ConnectedEnvironmentSummary } from "../../state/remote-runtime-types";
import { serverEnvironment } from "../../state/server";
import { ConnectionStatusDot } from "./ConnectionStatusDot";
@@ -114,23 +114,11 @@ export function ConnectionEnvironmentRow(props: {
>
{statusLabel}
{statusTraceId ? (
- <>
- {" Trace ID: "}
- {
- event.stopPropagation();
- copyTextWithHaptic(statusTraceId, { target: "connection-trace-id" });
- }}
- onPress={(event) => {
- event.stopPropagation();
- }}
- >
- {statusTraceId}
-
- >
+
) : null}
) : null}
diff --git a/apps/mobile/src/features/connection/ConnectionTraceId.tsx b/apps/mobile/src/features/connection/ConnectionTraceId.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..a92bd109e4c6d44f9fae33a7358a9454e266d5c5
--- /dev/null
+++ b/apps/mobile/src/features/connection/ConnectionTraceId.tsx
@@ -0,0 +1,51 @@
+import { AppText as Text } from "../../components/AppText";
+import { cn } from "../../lib/cn";
+import { copyTextWithHaptic } from "../../lib/copyTextWithHaptic";
+
+/** Inline trace control; disclosure rows reserve ordinary taps for their own navigation. */
+export function ConnectionTraceId({
+ traceId,
+ tone = "muted",
+ activation = "press",
+}: {
+ readonly traceId: string;
+ readonly tone?: "muted" | "danger";
+ readonly activation?: "press" | "longPress";
+}) {
+ const copy = () => copyTextWithHaptic(traceId, { target: "connection-trace-id" });
+ return (
+ <>
+ {" Trace ID: "}
+ {
+ event.stopPropagation();
+ if (event.nativeEvent.actionName === "activate") copy();
+ }}
+ className={cn(
+ "underline decoration-dotted",
+ tone === "danger" ? "text-danger-foreground" : "text-foreground-muted",
+ )}
+ onLongPress={
+ activation === "longPress"
+ ? (event) => {
+ event.stopPropagation();
+ copy();
+ }
+ : undefined
+ }
+ onPress={(event) => {
+ event.stopPropagation();
+ if (activation === "press") copy();
+ }}
+ >
+ {traceId}
+
+ >
+ );
+}
diff --git a/apps/mobile/src/features/connection/EnvironmentConnectionNotice.tsx b/apps/mobile/src/features/connection/EnvironmentConnectionNotice.tsx
index ca799a0c8192015b12c0977bc915c62c4e577889..bb829673688c91062607a0596f6aca347110725e 100644
--- a/apps/mobile/src/features/connection/EnvironmentConnectionNotice.tsx
+++ b/apps/mobile/src/features/connection/EnvironmentConnectionNotice.tsx
@@ -1,3 +1,4 @@
+import { ConnectionTraceId } from "./ConnectionTraceId";
import {
type EnvironmentConnectionPhase,
type EnvironmentConnectionPresentation,
@@ -6,7 +7,6 @@ import { SymbolView } from "../../components/AppSymbol";
import { ActivityIndicator, Pressable, View } from "react-native";
import { AppText as Text } from "../../components/AppText";
-import { copyTextWithHaptic } from "../../lib/copyTextWithHaptic";
function noticeTitle(phase: EnvironmentConnectionPhase, environmentLabel: string): string {
switch (phase) {
@@ -81,21 +81,7 @@ export function EnvironmentConnectionNotice(props: {
{noticeDetail(props.connection.phase, props.resourceName, props.connection.error)}
{props.connection.traceId ? (
- <>
- {" Trace ID: "}
-
- copyTextWithHaptic(props.connection.traceId!, {
- target: "connection-trace-id",
- })
- }
- >
- {props.connection.traceId}
-
- >
+
) : null}