Switch to double quotes and reformat codebase with Biome

This commit is contained in:
Mohamed Boudra
2026-03-21 20:22:15 +07:00
parent ab40786882
commit f6579dbeb4
805 changed files with 38132 additions and 40175 deletions
+142 -143
View File
@@ -6,107 +6,107 @@ import {
RefreshControl,
FlatList,
type ListRenderItem,
} from 'react-native'
import { useSafeAreaInsets } from 'react-native-safe-area-context'
import { useCallback, useMemo, useState, type ReactElement } from 'react'
import { router } from 'expo-router'
import { StyleSheet, UnistylesRuntime, useUnistyles } from 'react-native-unistyles'
import { formatTimeAgo } from '@/utils/time'
import { shortenPath } from '@/utils/shorten-path'
import { type AggregatedAgent } from '@/hooks/use-aggregated-agents'
import { useSessionStore } from '@/stores/session-store'
import { Archive } from 'lucide-react-native'
import { prepareWorkspaceTab } from '@/utils/workspace-navigation'
} from "react-native";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { useCallback, useMemo, useState, type ReactElement } from "react";
import { router } from "expo-router";
import { StyleSheet, UnistylesRuntime, useUnistyles } from "react-native-unistyles";
import { formatTimeAgo } from "@/utils/time";
import { shortenPath } from "@/utils/shorten-path";
import { type AggregatedAgent } from "@/hooks/use-aggregated-agents";
import { useSessionStore } from "@/stores/session-store";
import { Archive } from "lucide-react-native";
import { prepareWorkspaceTab } from "@/utils/workspace-navigation";
interface AgentListProps {
agents: AggregatedAgent[]
showCheckoutInfo?: boolean
isRefreshing?: boolean
onRefresh?: () => void
selectedAgentId?: string
onAgentSelect?: () => void
listFooterComponent?: ReactElement | null
showAttentionIndicator?: boolean
agents: AggregatedAgent[];
showCheckoutInfo?: boolean;
isRefreshing?: boolean;
onRefresh?: () => void;
selectedAgentId?: string;
onAgentSelect?: () => void;
listFooterComponent?: ReactElement | null;
showAttentionIndicator?: boolean;
}
type FlatListItem =
| { type: 'header'; key: string; title: string }
| { type: 'agent'; key: string; agent: AggregatedAgent }
| { type: "header"; key: string; title: string }
| { type: "agent"; key: string; agent: AggregatedAgent };
function deriveDateSectionLabel(lastActivityAt: Date): string {
const now = new Date()
const todayStart = new Date(now.getFullYear(), now.getMonth(), now.getDate())
const yesterdayStart = new Date(todayStart.getTime() - 24 * 60 * 60 * 1000)
const now = new Date();
const todayStart = new Date(now.getFullYear(), now.getMonth(), now.getDate());
const yesterdayStart = new Date(todayStart.getTime() - 24 * 60 * 60 * 1000);
const activityStart = new Date(
lastActivityAt.getFullYear(),
lastActivityAt.getMonth(),
lastActivityAt.getDate()
)
lastActivityAt.getDate(),
);
if (activityStart.getTime() >= todayStart.getTime()) {
return 'Today'
return "Today";
}
if (activityStart.getTime() >= yesterdayStart.getTime()) {
return 'Yesterday'
return "Yesterday";
}
const diffTime = todayStart.getTime() - activityStart.getTime()
const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24))
const diffTime = todayStart.getTime() - activityStart.getTime();
const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24));
if (diffDays <= 7) {
return 'This week'
return "This week";
}
if (diffDays <= 30) {
return 'This month'
return "This month";
}
return 'Older'
return "Older";
}
function formatStatusLabel(status: AggregatedAgent['status']): string {
function formatStatusLabel(status: AggregatedAgent["status"]): string {
switch (status) {
case 'initializing':
return 'Starting'
case 'idle':
return 'Idle'
case 'running':
return 'Running'
case 'error':
return 'Error'
case 'closed':
return 'Closed'
case "initializing":
return "Starting";
case "idle":
return "Idle";
case "running":
return "Running";
case "error":
return "Error";
case "closed":
return "Closed";
default:
return status
return status;
}
}
function SessionBadge({
label,
icon,
tone = 'neutral',
tone = "neutral",
}: {
label: string
icon?: ReactElement
tone?: 'neutral' | 'warning' | 'danger'
label: string;
icon?: ReactElement;
tone?: "neutral" | "warning" | "danger";
}) {
return (
<View
style={[
styles.badge,
tone === 'warning' && styles.badgeWarning,
tone === 'danger' && styles.badgeDanger,
tone === "warning" && styles.badgeWarning,
tone === "danger" && styles.badgeDanger,
]}
>
{icon}
<Text
style={[
styles.badgeText,
tone === 'warning' && styles.badgeTextWarning,
tone === 'danger' && styles.badgeTextDanger,
tone === "warning" && styles.badgeTextWarning,
tone === "danger" && styles.badgeTextDanger,
]}
>
{label}
</Text>
</View>
)
);
}
function SessionRow({
@@ -117,19 +117,19 @@ function SessionRow({
onPress,
onLongPress,
}: {
agent: AggregatedAgent
isMobile: boolean
selectedAgentId?: string
showAttentionIndicator: boolean
onPress: (agent: AggregatedAgent) => void
onLongPress: (agent: AggregatedAgent) => void
agent: AggregatedAgent;
isMobile: boolean;
selectedAgentId?: string;
showAttentionIndicator: boolean;
onPress: (agent: AggregatedAgent) => void;
onLongPress: (agent: AggregatedAgent) => void;
}) {
const { theme } = useUnistyles()
const timeAgo = formatTimeAgo(agent.lastActivityAt)
const agentKey = `${agent.serverId}:${agent.id}`
const isSelected = selectedAgentId === agentKey
const statusLabel = formatStatusLabel(agent.status)
const projectPath = shortenPath(agent.cwd)
const { theme } = useUnistyles();
const timeAgo = formatTimeAgo(agent.lastActivityAt);
const agentKey = `${agent.serverId}:${agent.id}`;
const isSelected = selectedAgentId === agentKey;
const statusLabel = formatStatusLabel(agent.status);
const projectPath = shortenPath(agent.cwd);
return (
<Pressable
@@ -149,7 +149,7 @@ function SessionRow({
style={[styles.sessionTitle, isSelected && styles.sessionTitleHighlighted]}
numberOfLines={1}
>
{agent.title || 'New session'}
{agent.title || "New session"}
</Text>
{agent.archivedAt ? (
<SessionBadge
@@ -199,10 +199,9 @@ function SessionRow({
</View>
) : null}
</Pressable>
)
);
}
export function AgentList({
agents,
isRefreshing = false,
@@ -212,88 +211,88 @@ export function AgentList({
listFooterComponent,
showAttentionIndicator = true,
}: AgentListProps) {
const { theme } = useUnistyles()
const insets = useSafeAreaInsets()
const [actionAgent, setActionAgent] = useState<AggregatedAgent | null>(null)
const isMobile = UnistylesRuntime.breakpoint === 'xs' || UnistylesRuntime.breakpoint === 'sm'
const { theme } = useUnistyles();
const insets = useSafeAreaInsets();
const [actionAgent, setActionAgent] = useState<AggregatedAgent | null>(null);
const isMobile = UnistylesRuntime.breakpoint === "xs" || UnistylesRuntime.breakpoint === "sm";
const actionClient = useSessionStore((state) =>
actionAgent?.serverId ? (state.sessions[actionAgent.serverId]?.client ?? null) : null
)
actionAgent?.serverId ? (state.sessions[actionAgent.serverId]?.client ?? null) : null,
);
const isActionSheetVisible = actionAgent !== null
const isActionDaemonUnavailable = Boolean(actionAgent?.serverId && !actionClient)
const isActionSheetVisible = actionAgent !== null;
const isActionDaemonUnavailable = Boolean(actionAgent?.serverId && !actionClient);
const handleAgentPress = useCallback(
(agent: AggregatedAgent) => {
if (isActionSheetVisible) {
return
return;
}
const serverId = agent.serverId
const agentId = agent.id
const serverId = agent.serverId;
const agentId = agent.id;
onAgentSelect?.()
onAgentSelect?.();
const route = prepareWorkspaceTab({
serverId,
workspaceId: agent.cwd,
target: { kind: 'agent', agentId },
target: { kind: "agent", agentId },
pin: Boolean(agent.archivedAt),
})
router.navigate(route as any)
});
router.navigate(route as any);
},
[isActionSheetVisible, onAgentSelect]
)
[isActionSheetVisible, onAgentSelect],
);
const handleAgentLongPress = useCallback((agent: AggregatedAgent) => {
setActionAgent(agent)
}, [])
setActionAgent(agent);
}, []);
const handleCloseActionSheet = useCallback(() => {
setActionAgent(null)
}, [])
setActionAgent(null);
}, []);
const handleArchiveAgent = useCallback(() => {
if (!actionAgent || !actionClient) {
return
return;
}
void actionClient.archiveAgent(actionAgent.id)
setActionAgent(null)
}, [actionAgent, actionClient])
void actionClient.archiveAgent(actionAgent.id);
setActionAgent(null);
}, [actionAgent, actionClient]);
const flatItems = useMemo((): FlatListItem[] => {
const order = ['Today', 'Yesterday', 'This week', 'This month', 'Older'] as const
const buckets = new Map<string, AggregatedAgent[]>()
const order = ["Today", "Yesterday", "This week", "This month", "Older"] as const;
const buckets = new Map<string, AggregatedAgent[]>();
for (const agent of agents) {
const label = deriveDateSectionLabel(agent.lastActivityAt)
const existing = buckets.get(label) ?? []
existing.push(agent)
buckets.set(label, existing)
const label = deriveDateSectionLabel(agent.lastActivityAt);
const existing = buckets.get(label) ?? [];
existing.push(agent);
buckets.set(label, existing);
}
const result: FlatListItem[] = []
const result: FlatListItem[] = [];
for (const label of order) {
const data = buckets.get(label)
const data = buckets.get(label);
if (!data || data.length === 0) {
continue
continue;
}
result.push({ type: 'header', key: `header:${label}`, title: label })
result.push({ type: "header", key: `header:${label}`, title: label });
for (const agent of data) {
result.push({ type: 'agent', key: `${agent.serverId}:${agent.id}`, agent })
result.push({ type: "agent", key: `${agent.serverId}:${agent.id}`, agent });
}
}
return result
}, [agents])
return result;
}, [agents]);
const renderItem: ListRenderItem<FlatListItem> = useCallback(
({ item }) => {
if (item.type === 'header') {
if (item.type === "header") {
return (
<View style={styles.sectionHeading}>
<Text style={styles.sectionTitle}>{item.title}</Text>
</View>
)
);
}
return (
<SessionRow
@@ -304,12 +303,12 @@ export function AgentList({
onPress={handleAgentPress}
onLongPress={handleAgentLongPress}
/>
)
);
},
[handleAgentLongPress, handleAgentPress, isMobile, selectedAgentId, showAttentionIndicator]
)
[handleAgentLongPress, handleAgentPress, isMobile, selectedAgentId, showAttentionIndicator],
);
const keyExtractor = useCallback((item: FlatListItem) => item.key, [])
const keyExtractor = useCallback((item: FlatListItem) => item.key, []);
return (
<>
@@ -350,7 +349,7 @@ export function AgentList({
>
<View style={styles.sheetHandle} />
<Text style={styles.sheetTitle}>
{isActionDaemonUnavailable ? 'Host offline' : 'Archive this session?'}
{isActionDaemonUnavailable ? "Host offline" : "Archive this session?"}
</Text>
<View style={styles.sheetButtonRow}>
<Pressable
@@ -380,7 +379,7 @@ export function AgentList({
</View>
</Modal>
</>
)
);
}
const styles = StyleSheet.create((theme) => ({
@@ -399,8 +398,8 @@ const styles = StyleSheet.create((theme) => ({
},
sectionHeading: {
marginTop: theme.spacing[2],
flexDirection: 'row',
alignItems: 'center',
flexDirection: "row",
alignItems: "center",
gap: theme.spacing[3],
paddingHorizontal: theme.spacing[3],
marginBottom: theme.spacing[2],
@@ -411,8 +410,8 @@ const styles = StyleSheet.create((theme) => ({
color: theme.colors.foregroundMuted,
},
row: {
flexDirection: 'row',
alignItems: 'center',
flexDirection: "row",
alignItems: "center",
paddingVertical: theme.spacing[2],
paddingHorizontal: theme.spacing[3],
borderRadius: {
@@ -429,15 +428,15 @@ const styles = StyleSheet.create((theme) => ({
minWidth: 0,
},
rowTitleRow: {
flexDirection: 'row',
alignItems: 'center',
flexWrap: 'wrap',
flexDirection: "row",
alignItems: "center",
flexWrap: "wrap",
gap: theme.spacing[2],
},
rowMetaRow: {
flexDirection: 'row',
alignItems: 'center',
flexWrap: 'wrap',
flexDirection: "row",
alignItems: "center",
flexWrap: "wrap",
gap: theme.spacing[1],
marginTop: 2,
},
@@ -456,7 +455,7 @@ const styles = StyleSheet.create((theme) => ({
sessionTitle: {
flexShrink: 1,
fontSize: theme.fontSize.sm,
fontWeight: '400',
fontWeight: "400",
color: theme.colors.foreground,
opacity: 0.86,
},
@@ -464,7 +463,7 @@ const styles = StyleSheet.create((theme) => ({
opacity: 1,
},
sessionMetaText: {
maxWidth: '100%',
maxWidth: "100%",
fontSize: theme.fontSize.sm,
color: theme.colors.foregroundMuted,
},
@@ -486,11 +485,11 @@ const styles = StyleSheet.create((theme) => ({
color: theme.colors.foregroundMuted,
flexShrink: 0,
width: 72,
textAlign: 'right' as const,
textAlign: "right" as const,
},
badge: {
flexDirection: 'row',
alignItems: 'center',
flexDirection: "row",
alignItems: "center",
gap: theme.spacing[1],
paddingHorizontal: theme.spacing[2],
paddingVertical: theme.spacing[1],
@@ -498,10 +497,10 @@ const styles = StyleSheet.create((theme) => ({
backgroundColor: theme.colors.surface2,
},
badgeWarning: {
backgroundColor: 'rgba(245, 158, 11, 0.12)',
backgroundColor: "rgba(245, 158, 11, 0.12)",
},
badgeDanger: {
backgroundColor: 'rgba(239, 68, 68, 0.14)',
backgroundColor: "rgba(239, 68, 68, 0.14)",
},
badgeText: {
fontSize: theme.fontSize.xs,
@@ -516,26 +515,26 @@ const styles = StyleSheet.create((theme) => ({
},
sheetOverlay: {
flex: 1,
justifyContent: 'flex-end',
justifyContent: "flex-end",
},
sheetBackdrop: {
position: 'absolute',
position: "absolute",
top: 0,
right: 0,
bottom: 0,
left: 0,
backgroundColor: 'rgba(0,0,0,0.35)',
backgroundColor: "rgba(0,0,0,0.35)",
},
sheetContainer: {
backgroundColor: theme.colors.surface2,
borderTopLeftRadius: theme.borderRadius['2xl'],
borderTopRightRadius: theme.borderRadius['2xl'],
borderTopLeftRadius: theme.borderRadius["2xl"],
borderTopRightRadius: theme.borderRadius["2xl"],
paddingHorizontal: theme.spacing[6],
paddingTop: theme.spacing[4],
gap: theme.spacing[4],
},
sheetHandle: {
alignSelf: 'center',
alignSelf: "center",
width: 40,
height: 4,
borderRadius: theme.borderRadius.full,
@@ -546,18 +545,18 @@ const styles = StyleSheet.create((theme) => ({
fontSize: theme.fontSize.lg,
fontWeight: theme.fontWeight.semibold,
color: theme.colors.foreground,
textAlign: 'center',
textAlign: "center",
},
sheetButtonRow: {
flexDirection: 'row',
flexDirection: "row",
gap: theme.spacing[3],
},
sheetButton: {
flex: 1,
borderRadius: theme.borderRadius.lg,
paddingVertical: theme.spacing[4],
alignItems: 'center',
justifyContent: 'center',
alignItems: "center",
justifyContent: "center",
},
sheetArchiveButton: {
backgroundColor: theme.colors.primary,
@@ -578,4 +577,4 @@ const styles = StyleSheet.create((theme) => ({
fontWeight: theme.fontWeight.semibold,
fontSize: theme.fontSize.base,
},
}))
}));