Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions apps/mobile/generated-uniwind-themes.css
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@
--color-adaptive-emerald-500-a12-a16: oklch(69.6% 0.17 162.48 / 12%);
--color-adaptive-emerald-600-400: oklch(59.6% 0.145 163.225);
--color-adaptive-emerald-700-300: oklch(50.8% 0.118 165.612);
--color-adaptive-fuchsia-500-a50-300-a40: oklch(66.7% 0.295 322.15 / 50%);
--color-adaptive-fuchsia-600-300: oklch(59.1% 0.293 322.896);
--color-adaptive-indigo-500-a12-a16: oklch(58.5% 0.233 277.117 / 12%);
--color-adaptive-indigo-600-300: oklch(51.1% 0.262 276.966);
--color-adaptive-indigo-700-300: oklch(45.7% 0.24 277.023);
Expand Down Expand Up @@ -271,6 +273,8 @@
--color-adaptive-emerald-500-a12-a16: oklch(69.6% 0.17 162.48 / 16%);
--color-adaptive-emerald-600-400: oklch(76.5% 0.177 163.223);
--color-adaptive-emerald-700-300: oklch(84.5% 0.143 164.978);
--color-adaptive-fuchsia-500-a50-300-a40: oklch(83.3% 0.145 321.434 / 40%);
--color-adaptive-fuchsia-600-300: oklch(83.3% 0.145 321.434);
--color-adaptive-indigo-500-a12-a16: oklch(58.5% 0.233 277.117 / 16%);
--color-adaptive-indigo-600-300: oklch(78.5% 0.115 274.713);
--color-adaptive-indigo-700-300: oklch(78.5% 0.115 274.713);
Expand Down Expand Up @@ -432,6 +436,8 @@
--color-adaptive-emerald-500-a12-a16: oklch(69.6% 0.17 162.48 / 12%);
--color-adaptive-emerald-600-400: oklch(59.6% 0.145 163.225);
--color-adaptive-emerald-700-300: oklch(50.8% 0.118 165.612);
--color-adaptive-fuchsia-500-a50-300-a40: oklch(66.7% 0.295 322.15 / 50%);
--color-adaptive-fuchsia-600-300: oklch(59.1% 0.293 322.896);
--color-adaptive-indigo-500-a12-a16: oklch(58.5% 0.233 277.117 / 12%);
--color-adaptive-indigo-600-300: oklch(51.1% 0.262 276.966);
--color-adaptive-indigo-700-300: oklch(45.7% 0.24 277.023);
Expand Down Expand Up @@ -593,6 +599,8 @@
--color-adaptive-emerald-500-a12-a16: oklch(69.6% 0.17 162.48 / 16%);
--color-adaptive-emerald-600-400: oklch(76.5% 0.177 163.223);
--color-adaptive-emerald-700-300: oklch(84.5% 0.143 164.978);
--color-adaptive-fuchsia-500-a50-300-a40: oklch(83.3% 0.145 321.434 / 40%);
--color-adaptive-fuchsia-600-300: oklch(83.3% 0.145 321.434);
--color-adaptive-indigo-500-a12-a16: oklch(58.5% 0.233 277.117 / 16%);
--color-adaptive-indigo-600-300: oklch(78.5% 0.115 274.713);
--color-adaptive-indigo-700-300: oklch(78.5% 0.115 274.713);
Expand Down Expand Up @@ -754,6 +762,8 @@
--color-adaptive-emerald-500-a12-a16: oklch(69.6% 0.17 162.48 / 12%);
--color-adaptive-emerald-600-400: oklch(59.6% 0.145 163.225);
--color-adaptive-emerald-700-300: oklch(50.8% 0.118 165.612);
--color-adaptive-fuchsia-500-a50-300-a40: oklch(66.7% 0.295 322.15 / 50%);
--color-adaptive-fuchsia-600-300: oklch(59.1% 0.293 322.896);
--color-adaptive-indigo-500-a12-a16: oklch(58.5% 0.233 277.117 / 12%);
--color-adaptive-indigo-600-300: oklch(51.1% 0.262 276.966);
--color-adaptive-indigo-700-300: oklch(45.7% 0.24 277.023);
Expand Down Expand Up @@ -915,6 +925,8 @@
--color-adaptive-emerald-500-a12-a16: oklch(69.6% 0.17 162.48 / 16%);
--color-adaptive-emerald-600-400: oklch(76.5% 0.177 163.223);
--color-adaptive-emerald-700-300: oklch(84.5% 0.143 164.978);
--color-adaptive-fuchsia-500-a50-300-a40: oklch(83.3% 0.145 321.434 / 40%);
--color-adaptive-fuchsia-600-300: oklch(83.3% 0.145 321.434);
--color-adaptive-indigo-500-a12-a16: oklch(58.5% 0.233 277.117 / 16%);
--color-adaptive-indigo-600-300: oklch(78.5% 0.115 274.713);
--color-adaptive-indigo-700-300: oklch(78.5% 0.115 274.713);
Expand Down Expand Up @@ -1076,6 +1088,8 @@
--color-adaptive-emerald-500-a12-a16: oklch(69.6% 0.17 162.48 / 12%);
--color-adaptive-emerald-600-400: oklch(59.6% 0.145 163.225);
--color-adaptive-emerald-700-300: oklch(50.8% 0.118 165.612);
--color-adaptive-fuchsia-500-a50-300-a40: oklch(66.7% 0.295 322.15 / 50%);
--color-adaptive-fuchsia-600-300: oklch(59.1% 0.293 322.896);
--color-adaptive-indigo-500-a12-a16: oklch(58.5% 0.233 277.117 / 12%);
--color-adaptive-indigo-600-300: oklch(51.1% 0.262 276.966);
--color-adaptive-indigo-700-300: oklch(45.7% 0.24 277.023);
Expand Down Expand Up @@ -1237,6 +1251,8 @@
--color-adaptive-emerald-500-a12-a16: oklch(69.6% 0.17 162.48 / 16%);
--color-adaptive-emerald-600-400: oklch(76.5% 0.177 163.223);
--color-adaptive-emerald-700-300: oklch(84.5% 0.143 164.978);
--color-adaptive-fuchsia-500-a50-300-a40: oklch(83.3% 0.145 321.434 / 40%);
--color-adaptive-fuchsia-600-300: oklch(83.3% 0.145 321.434);
--color-adaptive-indigo-500-a12-a16: oklch(58.5% 0.233 277.117 / 16%);
--color-adaptive-indigo-600-300: oklch(78.5% 0.115 274.713);
--color-adaptive-indigo-700-300: oklch(78.5% 0.115 274.713);
Expand Down Expand Up @@ -1398,6 +1414,8 @@
--color-adaptive-emerald-500-a12-a16: oklch(69.6% 0.17 162.48 / 12%);
--color-adaptive-emerald-600-400: oklch(59.6% 0.145 163.225);
--color-adaptive-emerald-700-300: oklch(50.8% 0.118 165.612);
--color-adaptive-fuchsia-500-a50-300-a40: oklch(66.7% 0.295 322.15 / 50%);
--color-adaptive-fuchsia-600-300: oklch(59.1% 0.293 322.896);
--color-adaptive-indigo-500-a12-a16: oklch(58.5% 0.233 277.117 / 12%);
--color-adaptive-indigo-600-300: oklch(51.1% 0.262 276.966);
--color-adaptive-indigo-700-300: oklch(45.7% 0.24 277.023);
Expand Down Expand Up @@ -1559,6 +1577,8 @@
--color-adaptive-emerald-500-a12-a16: oklch(69.6% 0.17 162.48 / 16%);
--color-adaptive-emerald-600-400: oklch(76.5% 0.177 163.223);
--color-adaptive-emerald-700-300: oklch(84.5% 0.143 164.978);
--color-adaptive-fuchsia-500-a50-300-a40: oklch(83.3% 0.145 321.434 / 40%);
--color-adaptive-fuchsia-600-300: oklch(83.3% 0.145 321.434);
--color-adaptive-indigo-500-a12-a16: oklch(58.5% 0.233 277.117 / 16%);
--color-adaptive-indigo-600-300: oklch(78.5% 0.115 274.713);
--color-adaptive-indigo-700-300: oklch(78.5% 0.115 274.713);
Expand Down Expand Up @@ -1720,6 +1740,8 @@
--color-adaptive-emerald-500-a12-a16: oklch(69.6% 0.17 162.48 / 12%);
--color-adaptive-emerald-600-400: oklch(59.6% 0.145 163.225);
--color-adaptive-emerald-700-300: oklch(50.8% 0.118 165.612);
--color-adaptive-fuchsia-500-a50-300-a40: oklch(66.7% 0.295 322.15 / 50%);
--color-adaptive-fuchsia-600-300: oklch(59.1% 0.293 322.896);
--color-adaptive-indigo-500-a12-a16: oklch(58.5% 0.233 277.117 / 12%);
--color-adaptive-indigo-600-300: oklch(51.1% 0.262 276.966);
--color-adaptive-indigo-700-300: oklch(45.7% 0.24 277.023);
Expand Down Expand Up @@ -1881,6 +1903,8 @@
--color-adaptive-emerald-500-a12-a16: oklch(69.6% 0.17 162.48 / 16%);
--color-adaptive-emerald-600-400: oklch(76.5% 0.177 163.223);
--color-adaptive-emerald-700-300: oklch(84.5% 0.143 164.978);
--color-adaptive-fuchsia-500-a50-300-a40: oklch(83.3% 0.145 321.434 / 40%);
--color-adaptive-fuchsia-600-300: oklch(83.3% 0.145 321.434);
--color-adaptive-indigo-500-a12-a16: oklch(58.5% 0.233 277.117 / 16%);
--color-adaptive-indigo-600-300: oklch(78.5% 0.115 274.713);
--color-adaptive-indigo-700-300: oklch(78.5% 0.115 274.713);
Expand Down
5 changes: 5 additions & 0 deletions apps/mobile/scripts/generate-uniwind-themes.mts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ const ADAPTIVE_COLORS: Readonly<Record<string, readonly [light: string, dark: st
],
"--color-adaptive-emerald-600-400": [color("emerald", 600), color("emerald", 400)],
"--color-adaptive-emerald-700-300": [color("emerald", 700), color("emerald", 300)],
"--color-adaptive-fuchsia-500-a50-300-a40": [
color("fuchsia", 500, 0.5),
color("fuchsia", 300, 0.4),
],
"--color-adaptive-fuchsia-600-300": [color("fuchsia", 600), color("fuchsia", 300)],
"--color-adaptive-indigo-500-a12-a16": [color("indigo", 500, 0.12), color("indigo", 500, 0.16)],
"--color-adaptive-indigo-600-300": [color("indigo", 600), color("indigo", 300)],
"--color-adaptive-indigo-700-300": [color("indigo", 700), color("indigo", 300)],
Expand Down
5 changes: 5 additions & 0 deletions apps/mobile/src/features/threads/ThreadDetailScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ import { ThreadFeed, type ThreadFeedHistoryControls } from "./ThreadFeed";
import { useThreadTurnSubagents } from "./ThreadAgentsSheet";
import { ComposerQueuedEditBanner } from "./ComposerQueuedEdit";
import { useThreadQueuedCount } from "./ThreadQueueControl";
import { ThreadGuestShareBar } from "./ThreadGuestShareBar";
import type { ThreadContentPresentation } from "./threadContentPresentation";
import { resolveThreadFeedSubmissionAnchor } from "./thread-feed-live-follow";
import { useOpenLinkedThread } from "./useOpenLinkedThread";
Expand Down Expand Up @@ -1632,6 +1633,10 @@ export const ThreadDetailScreen = function ThreadDetailScreen(props: ThreadDetai
key={`chatgpt-limit:${props.selectedThread.latestRun?.runId}`}
thread={props.selectedThread}
/>
<ThreadGuestShareBar
threadRef={props.selectedThreadDetailRef}
canOperateThread={props.canOperateThread}
/>
{props.feedbackSubmissions.map((submission) => (
<ComposerFeedback
key={submission.id}
Expand Down
111 changes: 81 additions & 30 deletions apps/mobile/src/features/threads/ThreadFeed.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import {
} from "../../lib/enrichedLinkPresentation";
import { ThreadContextDivider } from "./thread-context-divider";
import { ThreadHandoffDivider, ThreadHandoffRow } from "./thread-handoff-row";
import { GuestBubbleTint, GuestMessageName } from "./guestMessageStyle";
import { ThreadGuestPendingMessage, useThreadGuestShare } from "./ThreadGuestShareBar";
import { SecretRequestCard } from "./SecretRequestCard";
import { AppActivityIndicator } from "../../components/ui/AppActivityIndicator";
import {
Expand Down Expand Up @@ -229,9 +231,11 @@ import {
WORK_GROUP_TOGGLE_HEIGHT,
} from "./thread-work-log";
import {
appendGuestPendingMessages,
appendPendingThreadMessages,
isCompactionCommandFeedEntry,
type PendingThreadFeedEntry,
type ThreadFeedRow,
} from "./pending-thread-feed";
import type { QueuedThreadMessage } from "../../state/thread-outbox-model";
import { resolveThreadFeedFixedItemSize } from "./thread-feed-item-size";
Expand Down Expand Up @@ -760,6 +764,38 @@ function MessageAttachmentFile(props: {
);
}

/** A message's files as its bubble shows them; a guest's waiting message uses it too. */
function MessageAttachmentList(props: {
readonly attachments: ReadonlyArray<ChatAttachment>;
readonly environmentId: EnvironmentId;
readonly onPressPreview: (source: FilePreviewSource) => void;
readonly onPressVideo: (attachment: ChatFileAttachment, sourceIdentifier: string) => void;
}) {
return props.attachments.map((attachment) =>
isImageAttachment(attachment) ? (
<MessageAttachmentImage
key={attachment.id}
environmentId={props.environmentId}
attachmentId={attachment.id}
name={attachment.name}
mimeType={attachment.mimeType}
className="mt-1.5 aspect-[1.3] w-full rounded-[18px] bg-subtle-strong"
onPressPreview={props.onPressPreview}
/>
) : isFileAttachment(attachment) ? (
<MessageAttachmentFile
key={attachment.id}
environmentId={props.environmentId}
attachment={attachment}
onPressPreview={props.onPressPreview}
onPressVideo={props.onPressVideo}
/>
) : (
<MessageAttachmentUnknown key={attachment.id} name={attachment.name} />
),
);
}

function MessageAttachmentUnknown(props: { readonly name: string }) {
return (
<View className="flex-row items-center gap-2 py-1">
Expand Down Expand Up @@ -1203,7 +1239,7 @@ function compactionLabel(label: string, title: string | undefined) {
}

function renderFeedEntry(
info: { item: PendingThreadFeedEntry; index: number },
info: { item: ThreadFeedRow; index: number },
props: Pick<
ThreadFeedProps,
| "environmentId"
Expand Down Expand Up @@ -1251,6 +1287,25 @@ function renderFeedEntry(
const entry = info.item;
const { markdownStyles, iconSubtleColor, userBubbleColor } = props;

if (entry.type === "guest-pending") {
return (
<ThreadGuestPendingMessage
threadRef={scopeThreadRef(props.environmentId, props.threadId)}
guestName={entry.guestName}
message={entry.message}
bubbleMaxWidth={props.duoColumns ? "85%" : props.userBubbleMaxWidth}
renderAttachments={(attachments) => (
<MessageAttachmentList
attachments={attachments}
environmentId={props.environmentId}
onPressPreview={props.onPressPreview}
onPressVideo={props.onPressVideo}
/>
)}
/>
);
}

if (entry.type === "run-fold") {
return (
<View className="mb-1 flex-row items-center border-b border-border-subtle px-2">
Expand Down Expand Up @@ -1504,6 +1559,9 @@ function renderFeedEntry(
Sent by T3 Code
</Text>
) : null}
{presentation.guestName !== undefined ? (
<GuestMessageName name={presentation.guestName} />
) : null}
<View
className="min-w-0 rounded-[20px]"
style={{
Expand All @@ -1518,6 +1576,7 @@ function renderFeedEntry(
: null),
}}
>
{presentation.attribution === "guest" ? <GuestBubbleTint /> : null}
{foldRowId !== null ? (
<AgentMessageFoldHeader
environmentId={props.environmentId}
Expand Down Expand Up @@ -1676,7 +1735,7 @@ function renderFeedEntry(
<UserMessageCopyButton
text={presentation.text}
onCopy={
message.context
message.context && presentation.attribution !== "guest"
? () =>
writeComposerContextClipboard(message.text, {
version: 1,
Expand Down Expand Up @@ -1722,29 +1781,12 @@ function renderFeedEntry(
/>
</MarkdownImageAvailableWidthContext>
) : null}
{attachments.map((attachment) => {
return isImageAttachment(attachment) ? (
<MessageAttachmentImage
key={attachment.id}
environmentId={props.environmentId}
attachmentId={attachment.id}
name={attachment.name}
mimeType={attachment.mimeType}
className="mt-1.5 aspect-[1.3] w-full rounded-[18px] bg-subtle-strong"
onPressPreview={props.onPressPreview}
/>
) : isFileAttachment(attachment) ? (
<MessageAttachmentFile
key={attachment.id}
environmentId={props.environmentId}
attachment={attachment}
onPressPreview={props.onPressPreview}
onPressVideo={props.onPressVideo}
/>
) : (
<MessageAttachmentUnknown key={attachment.id} name={attachment.name} />
);
})}
<MessageAttachmentList
attachments={attachments}
environmentId={props.environmentId}
onPressPreview={props.onPressPreview}
onPressVideo={props.onPressVideo}
/>
{showAssistantMeta && message.checkpointSummary ? (
<TurnDiffStat
checkpoint={message.checkpointSummary}
Expand Down Expand Up @@ -2067,6 +2109,11 @@ function useThreadFeedPresentation(
export const ThreadFeed = memo(function ThreadFeed(props: ThreadFeedProps) {
const { listRef, onEndFollowEnabledChange, onHeaderMaterialVisibilityChange } = props;
const workflowOpening = useWorkflowOpening(props.environmentId, props.threadId);
const guestThreadRef = useMemo(
() => scopeThreadRef(props.environmentId, props.threadId),
[props.environmentId, props.threadId],
);
const guestShare = useThreadGuestShare(guestThreadRef);
const deviceType = useDeviceType();
const duoColumns = useNativeWorkspaceColumnsSupported() && isDuoDevice(deviceType);
const openPullRequest = useOpenPullRequest();
Expand Down Expand Up @@ -2662,7 +2709,10 @@ export const ThreadFeed = memo(function ThreadFeed(props: ThreadFeedProps) {
reportHeaderMaterialVisibility(false);
}, [feedThreadKey, reportHeaderMaterialVisibility]);

const presentedFeed = useThreadFeedPresentation(props, expandedTurnIds, expandedWorkGroups);
const presentedFeed = appendGuestPendingMessages(
useThreadFeedPresentation(props, expandedTurnIds, expandedWorkGroups),
guestShare,
);
const setupAnchorIndex = presentedFeed.findIndex(
(entry) => entry.type === "message" && entry.message.role === "user",
);
Expand Down Expand Up @@ -2880,7 +2930,7 @@ export const ThreadFeed = memo(function ThreadFeed(props: ThreadFeedProps) {
}
};

const shouldRestoreVisibleContentPosition = (entry: ThreadFeedEntry) => {
const shouldRestoreVisibleContentPosition = (entry: ThreadFeedRow) => {
const disclosureAnchorKey = disclosureAnchorKeyRef.current;
return disclosureAnchorKey === null || entry.id === disclosureAnchorKey;
};
Expand Down Expand Up @@ -2964,7 +3014,8 @@ export const ThreadFeed = memo(function ThreadFeed(props: ThreadFeedProps) {
// Without this, every row above the viewport is assumed to be
// estimatedItemSize tall, and scrolling up through unmeasured content
// corrects each row's height as it mounts — the feed visibly jumps.
const getFixedItemSize = (entry: ThreadFeedEntry) => {
const getFixedItemSize = (entry: ThreadFeedRow) => {
if (entry.type === "guest-pending") return undefined;
if (entry.type === "html-render") {
return htmlRenderRowHeight(htmlRenderFrameHeight(entry.render, contentWidth));
}
Expand Down Expand Up @@ -3010,7 +3061,7 @@ export const ThreadFeed = memo(function ThreadFeed(props: ThreadFeedProps) {
if (hasHtmlRenders) listRef.current?.clearCaches({ mode: "sizes" });
}, [beginReflow, contentWidth, hasHtmlRenders, listRef]);

const renderItem = (info: { item: PendingThreadFeedEntry; index: number }) => (
const renderItem = (info: { item: ThreadFeedRow; index: number }) => (
<Animated.View
key={info.item.id}
entering={disclosureToggleSettling ? THREAD_FEED_DISCLOSURE_ENTER_TRANSITION : undefined}
Expand Down Expand Up @@ -3301,7 +3352,7 @@ function ThreadFeedLoadEarlierControl(props: ThreadFeedHistoryControls) {
}

function MessageImageGalleryScope(props: {
entry: PendingThreadFeedEntry;
entry: ThreadFeedRow;
environmentId: EnvironmentId;
threadId: ThreadId;
workspaceRoot: string | null | undefined;
Expand Down
Loading
Loading