Skip to content
Draft
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
33 changes: 31 additions & 2 deletions apps/mobile/app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,23 @@ const dmSansFonts = {
bold: "@expo-google-fonts/dm-sans/700Bold/DMSans_700Bold.ttf",
} as const;

// OpenUI app cards draw each app in its own typeface (Google Sans, Inter Tight, Mona Sans; all OFL).
const appCardFonts = [
["GoogleSans-Regular", "google-sans/400Regular/GoogleSans_400Regular.ttf", 400],
["GoogleSans-Medium", "google-sans/500Medium/GoogleSans_500Medium.ttf", 500],
["GoogleSans-Bold", "google-sans/700Bold/GoogleSans_700Bold.ttf", 700],
["InterTight-Regular", "inter-tight/400Regular/InterTight_400Regular.ttf", 400],
["InterTight-SemiBold", "inter-tight/600SemiBold/InterTight_600SemiBold.ttf", 600],
["InterTight-Bold", "inter-tight/700Bold/InterTight_700Bold.ttf", 700],
["MonaSans-Regular", "mona-sans/400Regular/MonaSans_400Regular.ttf", 400],
["MonaSans-SemiBold", "mona-sans/600SemiBold/MonaSans_600SemiBold.ttf", 600],
["MonaSans-Bold", "mona-sans/700Bold/MonaSans_700Bold.ttf", 700],
].map(([fontFamily, file, weight]) => ({
fontFamily: fontFamily as string,
path: `@expo-google-fonts/${file as string}`,
weight: weight as number,
}));

const widgetsPlugin: NonNullable<ExpoConfig["plugins"]>[number] = [
"expo-widgets",
{
Expand Down Expand Up @@ -284,7 +301,10 @@ const config: ExpoConfig = {
},
android: {
icon: variant.assets.appIcon,
package: process.env.T3_OPENUI_LAB_BUILD === "1" ? "com.t3tools.t3code.openui" : variant.androidPackage,
package:
process.env.T3_OPENUI_LAB_BUILD === "1"
? "com.t3tools.t3code.openui"
: variant.androidPackage,
...(repoEnv.T3CODE_ANDROID_GOOGLE_SERVICES_FILE
? { googleServicesFile: repoEnv.T3CODE_ANDROID_GOOGLE_SERVICES_FILE }
: {}),
Expand All @@ -311,7 +331,12 @@ const config: ExpoConfig = {
"expo-font",
{
ios: {
fonts: [dmSansFonts.regular, dmSansFonts.medium, dmSansFonts.bold],
fonts: [
dmSansFonts.regular,
dmSansFonts.medium,
dmSansFonts.bold,
...appCardFonts.map((font) => font.path),
],
},
android: {
fonts: [
Expand All @@ -327,6 +352,10 @@ const config: ExpoConfig = {
fontFamily: "DMSans-Bold",
fontDefinitions: [{ path: dmSansFonts.bold, weight: 700 }],
},
...appCardFonts.map(({ fontFamily, path, weight }) => ({
fontFamily,
fontDefinitions: [{ path, weight }],
})),
],
},
},
Expand Down
Binary file added apps/mobile/assets/app-cards/car-black.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/mobile/assets/app-cards/car-comfort.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/mobile/assets/app-cards/car-x.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/mobile/assets/app-cards/car-xl.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 5 additions & 2 deletions apps/mobile/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,16 @@
"@clerk/expo-native-components": "0.4.0",
"@effect/atom-react": "catalog:",
"@expo-google-fonts/dm-sans": "^0.4.2",
"@expo-google-fonts/google-sans": "^0.4.4",
"@expo-google-fonts/inter-tight": "^0.4.2",
"@expo-google-fonts/mona-sans": "^0.4.1",
"@expo/metro-runtime": "~58.0.14",
"@expo/ui": "58.0.20",
"@legendapp/list": "catalog:",
"@material/material-color-utilities": "0.3.0",
"@noble/curves": "catalog:",
"@openuidev/lang-core": "1.0.2",
"@openuidev/react-lang": "1.0.2",
"zod": "^4.6.5",
"@pierre/diffs": "catalog:",
"@pierre/highlights": "catalog:",
"@react-native-ai/apple": "0.12.0",
Expand Down Expand Up @@ -140,7 +142,8 @@
"remark-parse": "catalog:",
"tailwind-merge": "^3.5.0",
"unified": "catalog:",
"uniwind": "1.13.0"
"uniwind": "1.13.0",
"zod": "^4.6.5"
},
"devDependencies": {
"@babel/core": "^7.29.7",
Expand Down
34 changes: 30 additions & 4 deletions apps/mobile/src/features/threads/thread-work-log.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,13 @@ import {
shouldFollowThreadWorkGroupAppend,
type ThreadWorkGroupScrollPosition,
} from "./thread-feed-live-follow";
import type { AppBrand } from "@t3tools/client-runtime/app-connectors";
import {
resolveWorkEntryAppActivity,
resolveWorkEntryToolPresentation,
toolGroupAction,
type ToolGroupSummaryKind,
workEntryAppActivityLabel,
workEntryViewedImagePath,
} from "@t3tools/client-runtime/work-log/presentation";
import { resolveWorkGroupScrollAnchor } from "@t3tools/client-runtime/work-log/scroll-anchor";
Expand Down Expand Up @@ -200,6 +203,24 @@ export function ThreadDisclosureChevron(props: {
);
}

/** Brand monogram for tools from a known app (Gmail, Uber, Maps, ...); no logos are bundled. */
function AppActivityMark({ brand }: { readonly brand: AppBrand }) {
return (
<View
accessible={false}
className="h-4 w-4 items-center justify-center rounded-[4px]"
style={{ backgroundColor: brand.color }}
>
<Text
className="font-t3-bold"
style={{ color: brand.onColor, fontSize: brand.mark.length > 1 ? 7 : 10, lineHeight: 12 }}
>
{brand.mark}
</Text>
</View>
);
}

function ShimmerWorkContent(props: {
readonly textClassName?: string;
readonly compact?: boolean;
Expand Down Expand Up @@ -1007,12 +1028,15 @@ const ThreadWorkLogRow = function ThreadWorkLogRow(
</Text>
);
const toolPresentation = resolveWorkEntryToolPresentation(row.workEntry);
const previewText = row.groupStandIn?.label ?? workEntryRowLabel(row.workEntry);
const appActivity = row.groupStandIn ? null : resolveWorkEntryAppActivity(row.workEntry);
const appLabel = appActivity ? workEntryAppActivityLabel(row.workEntry) : null;
const previewText = row.groupStandIn?.label ?? appLabel ?? workEntryRowLabel(row.workEntry);
const answerPreview = row.workEntry.questionAnswer
? getQuestionAnswerPreview(row.workEntry.questionAnswer)
: null;
const accessiblePreview = [previewText, answerPreview].filter(Boolean).join(": ");
const displayText = row.groupStandIn?.label ?? workEntryRowLabel(row.workEntry, expanded);
const displayText =
row.groupStandIn?.label ?? appLabel ?? workEntryRowLabel(row.workEntry, expanded);
const isSystemNotice = row.projectedItem.item.type === "system_notice";
const isUsageLimit =
row.projectedItem.item.type === "error" &&
Expand Down Expand Up @@ -1058,7 +1082,7 @@ const ThreadWorkLogRow = function ThreadWorkLogRow(
}}
onLongPress={() => props.onCopyRow(row.id, row.getCopyText())}
>
{row.live && !expanded ? (
{row.live && !expanded && !appActivity ? (
<ShimmeringWorkContent
environmentId={props.environmentId}
icon={icon}
Expand All @@ -1071,7 +1095,9 @@ const ThreadWorkLogRow = function ThreadWorkLogRow(
) : (
<>
<WorkLogIconSlot>
{toolIcon ? (
{appActivity ? (
<AppActivityMark brand={appActivity.brand} />
) : toolIcon ? (
<ToolActivityIconView
environmentId={props.environmentId}
icon={toolIcon}
Expand Down
10 changes: 10 additions & 0 deletions apps/mobile/src/lib/threadActivity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
liveActivityToolStatus,
toolGroupAction,
resolveWorkEntryToolPresentation,
workEntryAppActivityLabel,
summarizeToolGroup,
toolGroupSummaryKind,
type ToolGroupSummaryKind,
Expand Down Expand Up @@ -256,6 +257,8 @@ export function workEntryRowLabel(entry: WorkLogPresentationEntry, expanded = fa
if (entry.itemType === "fork") return entry.label;
if (expanded && entry.itemType === "reasoning")
return entry.toolLifecycleStatus === "inProgress" ? "Thinking" : "Thought";
const appLabel = workEntryAppActivityLabel(entry);
if (appLabel) return appLabel;
const presentation = resolveWorkEntryToolPresentation(entry);
if (presentation) return presentation.displayName;
if (entry.command?.trim()) return compactWorkEntryText(commandDisplayText(entry.command));
Expand Down Expand Up @@ -856,6 +859,11 @@ function singleToolCallLabel(activity: ThreadFeedActivity, expanded: boolean): s
return expanded
? "Thought"
: compactWorkEntryText(activity.workEntry.detail ?? "") || "Thought";
const appLabel = workEntryAppActivityLabel(
activity.workEntry,
activity.workEntry.toolLifecycleStatus ?? "completed",
);
if (appLabel) return appLabel;
const presentation = resolveWorkEntryToolPresentation(activity.workEntry, "completed");
if (presentation) return presentation.displayName;
const command = activity.workEntry.command?.trim();
Expand Down Expand Up @@ -1877,6 +1885,8 @@ function liveToolActivitySummary(activity: ThreadFeedActivity, presentTense: boo
(status === "inProgress" ? "Thinking" : "Thought")
);
}
const appLabel = workEntryAppActivityLabel(activity.workEntry, status);
if (appLabel) return appLabel;
const presentation = resolveWorkEntryToolPresentation({
...activity.workEntry,
toolLifecycleStatus: status,
Expand Down
Loading
Loading