Skip to content
Open
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
15 changes: 0 additions & 15 deletions apps/mobile/src/agent-ui.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -164,21 +164,6 @@ export function TaskCard({
</Pressable>
);
}
export function ChatWork() {
const { data } = useAgentWorkspace();
const tasks = [...(data?.tasks || [])]
.filter(activeTask)
.sort((a, b) => b.createdAt.localeCompare(a.createdAt))
.slice(0, 2);
if (!tasks.length) return null;
return (
<View style={{ gap: 10 }}>
{tasks.map((task) => (
<TaskCard task={task} key={task.id} compact />
))}
</View>
);
}
export function AgentActivityScreen() {
const { data } = useAgentWorkspace();
const [filter, setFilter] = useState("All");
Expand Down
5 changes: 2 additions & 3 deletions apps/mobile/src/chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ export function WorkspaceTools() {
name: "use_desktop",
description: "Show the agent working on the computer's desktop",
parameters: displayParameters,
render: ({ toolCallId, result, status }) => (
<DesktopToolCard toolCallId={toolCallId} result={result} loading={status !== "complete"} />
render: ({ result, status }) => (
<DesktopToolCard result={result} loading={status !== "complete"} />
),
});
useRenderTool({
Expand Down Expand Up @@ -653,7 +653,6 @@ export function ChatScreen({
{!!latestDesktop && (
<DesktopToolCard
live
toolCallId={latestDesktop}
result={
messages.find(
(message) => message.role === "tool" && message.toolCallId === latestDesktop,
Expand Down
1 change: 0 additions & 1 deletion apps/mobile/src/desktop-tool-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ export function DesktopToolCard({
live = false,
loading,
}: {
toolCallId: string;
live?: boolean;
result: unknown;
loading: boolean;
Expand Down
319 changes: 0 additions & 319 deletions apps/mobile/src/screens.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {
ArrowDownToLine,
ArrowUpRight,
CalendarDays,
Check,
CheckCheck,
ChevronLeft,
ChevronRight,
Expand All @@ -29,7 +28,6 @@ import {
Pressable,
Text,
TextInput,
useWindowDimensions,
View,
} from "react-native";
import type {
Expand All @@ -51,7 +49,6 @@ import {
ErrorNotice,
IconButton,
LinkRow,
Mascot,
relativeDate,
resultSummary,
SectionHeading,
Expand All @@ -68,322 +65,6 @@ function todayDate() {
function eventDate(event: CalendarEvent) {
return event.allDay ? event.start : localDateTime(event.start, event.timeZone).date;
}
export function TodayScreen() {
const { workspace: w, navigate, open, ask } = useWorkspace();
const wide = useWindowDimensions().width > 1180;
const pending = w.actions.filter((a) => a.status === "awaiting_review");
const unread = w.mail.filter((m) => m.unread);
const today = todayDate();
const events = w.events
.filter((e) => eventDate(e) === today)
.sort((a, b) => a.start.localeCompare(b.start));
return (
<View style={{ gap: 25 }}>
<View
style={[
{
backgroundColor: "#E8F2F8",
borderRadius: 24,
padding: 32,
minHeight: 228,
overflow: "hidden",
},
s.row,
]}
>
<View style={{ flex: 1, gap: 15, zIndex: 1 }}>
<View style={[s.row, { gap: 7 }]}>
<Sparkles size={13} color={colors.blueDark} />
<Text style={[s.label, { color: colors.blueDark }]}>A little clarity, every day</Text>
</View>
<Text
style={{
fontSize: wide ? 39 : 29,
lineHeight: wide ? 45 : 36,
letterSpacing: -1.7,
fontWeight: "500",
color: colors.text,
}}
>
Your day, with a little{"\n"}more room to breathe.
</Text>
<Text style={[s.muted, { maxWidth: 420, color: "#617680" }]}>
{events.length ? `${events.length} things on your calendar` : "Your calendar has room"}
{unread.length ? `, ${unread.length} unread emails` : ""}.{"\n"}Let’s make space for
what matters.
</Text>
<Button
onPress={() => ask("Help me plan my day")}
icon={Sparkles}
primary
style={{ alignSelf: "flex-start", marginTop: 5 }}
>
Plan my day
</Button>
</View>
{wide && (
<View style={{ width: 220, height: 210, alignItems: "center", justifyContent: "center" }}>
<View
style={{
position: "absolute",
width: 190,
height: 190,
borderRadius: 100,
backgroundColor: "#DAEAF2",
}}
/>
<View
style={{
position: "absolute",
width: 145,
height: 145,
borderRadius: 80,
borderWidth: 1,
borderColor: "#C8DBE6",
}}
/>
<Mascot size={94} />
<View
style={[
s.row,
{
position: "absolute",
top: 17,
left: -19,
padding: 11,
gap: 7,
backgroundColor: "#FFF",
borderRadius: 13,
transform: [{ rotate: "-7deg" }],
},
]}
>
<Check size={14} color="#739174" />
<Text style={s.small}>A lighter day</Text>
</View>
<View
style={[
s.row,
{
position: "absolute",
bottom: 18,
right: -8,
padding: 12,
gap: 8,
backgroundColor: "#FFF",
borderRadius: 13,
transform: [{ rotate: "5deg" }],
},
]}
>
<CalendarDays size={17} color={colors.blueDark} />
<Text style={s.small}>Everything, together</Text>
</View>
</View>
)}
</View>
<View style={{ flexDirection: "row", gap: 13, flexWrap: "wrap" }}>
{[
{
label: "UNREAD EMAILS",
value: unread.length,
note: "A fresh look at your inbox",
icon: Mail,
section: "mail" as const,
tint: colors.sky,
},
{
label: "ON THE CALENDAR",
value: events.length,
note: "Make room for your priorities",
icon: CalendarDays,
section: "calendar" as const,
tint: colors.green,
},
{
label: "WAITING FOR YOU",
value: pending.length,
note: "Your review keeps things moving",
icon: ShieldCheck,
section: "activity" as const,
tint: colors.lavender,
},
].map((item) => (
<Pressable
key={item.label}
accessibilityRole="button"
onPress={() => navigate(item.section)}
style={{ flex: 1, minWidth: 180 }}
>
<Card style={{ padding: 21, height: 126 }}>
<View style={s.between}>
<Text style={[s.label, { fontSize: 9, letterSpacing: 1 }]}>{item.label}</Text>
<View
style={[
s.iconBox,
{ width: 31, height: 31, borderRadius: 10, backgroundColor: item.tint },
]}
>
<item.icon size={15} color={colors.text} />
</View>
</View>
<Text style={{ fontSize: 29, color: colors.text, letterSpacing: -1, marginTop: -2 }}>
{String(item.value).padStart(2, "0")}
</Text>
<Text style={[s.small, { fontSize: 10, marginTop: 3 }]}>{item.note}</Text>
</Card>
</Pressable>
))}
</View>
<View style={{ flexDirection: wide ? "row" : "column", gap: 22 }}>
<Card style={{ flex: 1 }}>
<SectionHeading
title="On your calendar"
action="Full calendar"
onPress={() => navigate("calendar")}
/>
{events.length ? (
events.slice(0, 3).map((e, i) => <AgendaRow key={e.id} event={e} index={i} />)
) : (
<Empty
icon={CalendarDays}
title="Some breathing room"
detail="No events scheduled today."
/>
)}
<Pressable
onPress={() => open({ type: "event" })}
style={[
s.row,
{
gap: 8,
paddingTop: 15,
marginTop: 9,
borderTopWidth: 1,
borderTopColor: colors.line,
},
]}
>
<Plus size={15} color={colors.muted} />
<Text style={s.small}>Make time for something</Text>
</Pressable>
</Card>
<Card style={{ flex: 1 }}>
<SectionHeading
title="From your inbox"
action="Open mail"
onPress={() => navigate("mail")}
/>
{w.mail.length ? (
w.mail.slice(0, 3).map((m, i) => (
<Pressable
key={m.id}
onPress={() => open({ type: "mail", mail: m })}
style={[
s.row,
{
gap: 12,
paddingVertical: 13,
borderTopWidth: i ? 1 : 0,
borderTopColor: colors.line,
},
]}
>
<Avatar name={m.sender} index={i} />
<View style={{ flex: 1, gap: 3 }}>
<View style={s.between}>
<Text style={[s.text, { fontSize: 12, fontWeight: "600" }]}>{m.sender}</Text>
<Text style={[s.small, { fontSize: 10 }]}>{timeLabel(m.date)}</Text>
</View>
<Text numberOfLines={1} style={[s.text, { fontSize: 12, lineHeight: 18 }]}>
{m.subject}
</Text>
<Text numberOfLines={1} style={[s.small, { fontSize: 11 }]}>
{m.body.replace(/\n/g, " ")}
</Text>
</View>
{m.unread && (
<View
style={{ width: 5, height: 5, borderRadius: 4, backgroundColor: "#78ABD0" }}
/>
)}
</Pressable>
))
) : (
<Empty
icon={Inbox}
title="Inbox is quiet"
detail="Connect Google to bring your messages here."
/>
)}
</Card>
</View>
<View style={{ flexDirection: wide ? "row" : "column", gap: 22 }}>
<Card style={{ flex: 1, backgroundColor: "#F0F0E7" }}>
<SectionHeading title="A hand with the little things" />
<Text style={[s.muted, { marginBottom: 15 }]}>
Start with a thought. We’ll take it from there.
</Text>
{[
"What needs my attention today?",
"Help me catch up on my inbox",
"Show my recent documents",
].map((prompt) => (
<Pressable
key={prompt}
onPress={() => ask(prompt)}
style={[
s.between,
{ borderTopWidth: 1, borderTopColor: "#E1E2D9", paddingVertical: 13 },
]}
>
<Text style={[s.text, { fontSize: 12 }]}>{prompt}</Text>
<ArrowUpRight size={15} color={colors.muted} />
</Pressable>
))}
</Card>
<Card style={{ flex: 1 }}>
<SectionHeading
title={pending.length ? "Ready for your review" : "Recent activity"}
action="View all"
onPress={() => navigate("activity")}
/>
{pending.length
? pending
.slice(0, 3)
.map((a) => (
<LinkRow
key={a.id}
title={a.title}
detail="Prepared · waiting for your approval"
onPress={() => open({ type: "review", action: a })}
icon={ShieldCheck}
tint={colors.lavender}
/>
))
: w.activity.slice(0, 3).map((a) => (
<View key={a.id} style={[s.row, { gap: 13, paddingVertical: 12 }]}>
<View
style={[s.iconBox, { width: 32, height: 32, backgroundColor: colors.green }]}
>
<Check size={14} color={colors.text} />
</View>
<View style={{ flex: 1 }}>
<Text style={[s.text, { fontSize: 12 }]}>{a.title}</Text>
<Text style={s.small}>{relativeDate(a.date)}</Text>
</View>
</View>
))}
{!pending.length && !w.activity.length && (
<Text style={s.muted}>
Your workspace is ready. Things you do here will appear in your activity.
</Text>
)}
</Card>
</View>
</View>
);
}
function Avatar({ name, index = 0 }: { name: string; index?: number }) {
return (
<View
Expand Down
Loading
Loading