Update files
This commit is contained in:
@@ -4,9 +4,9 @@ import {
|
|||||||
Pressable,
|
Pressable,
|
||||||
Modal,
|
Modal,
|
||||||
RefreshControl,
|
RefreshControl,
|
||||||
FlatList,
|
SectionList,
|
||||||
type ViewToken,
|
type ViewToken,
|
||||||
type ListRenderItem,
|
type SectionListRenderItem,
|
||||||
} from "react-native";
|
} from "react-native";
|
||||||
import { useCallback, useMemo, useRef, useState, type ReactElement } from "react";
|
import { useCallback, useMemo, useRef, useState, type ReactElement } from "react";
|
||||||
import { router, usePathname } from "expo-router";
|
import { router, usePathname } from "expo-router";
|
||||||
@@ -36,6 +36,40 @@ interface AgentListProps {
|
|||||||
listFooterComponent?: ReactElement | null;
|
listFooterComponent?: ReactElement | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface AgentListSection {
|
||||||
|
key: string;
|
||||||
|
title: string;
|
||||||
|
data: 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 activityStart = new Date(
|
||||||
|
lastActivityAt.getFullYear(),
|
||||||
|
lastActivityAt.getMonth(),
|
||||||
|
lastActivityAt.getDate()
|
||||||
|
);
|
||||||
|
|
||||||
|
if (activityStart.getTime() >= todayStart.getTime()) {
|
||||||
|
return "Today";
|
||||||
|
}
|
||||||
|
if (activityStart.getTime() >= yesterdayStart.getTime()) {
|
||||||
|
return "Yesterday";
|
||||||
|
}
|
||||||
|
|
||||||
|
const diffTime = todayStart.getTime() - activityStart.getTime();
|
||||||
|
const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24));
|
||||||
|
if (diffDays <= 7) {
|
||||||
|
return "This week";
|
||||||
|
}
|
||||||
|
if (diffDays <= 30) {
|
||||||
|
return "This month";
|
||||||
|
}
|
||||||
|
return "Older";
|
||||||
|
}
|
||||||
|
|
||||||
export function AgentList({
|
export function AgentList({
|
||||||
agents,
|
agents,
|
||||||
isRefreshing = false,
|
isRefreshing = false,
|
||||||
@@ -213,9 +247,37 @@ export function AgentList({
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
const renderAgentItem = useCallback<ListRenderItem<AggregatedAgent>>(
|
const sections = useMemo((): AgentListSection[] => {
|
||||||
({ item: agent }) => <AgentListRow agent={agent} />,
|
const order = ["Today", "Yesterday", "This week", "This month", "Older"] as const;
|
||||||
[AgentListRow]
|
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 result: AgentListSection[] = [];
|
||||||
|
for (const label of order) {
|
||||||
|
const data = buckets.get(label);
|
||||||
|
if (!data || data.length === 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
result.push({ key: `date:${label}`, title: label, data });
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}, [agents]);
|
||||||
|
|
||||||
|
const renderAgentItem: SectionListRenderItem<AggregatedAgent, AgentListSection> =
|
||||||
|
useCallback(({ item: agent }) => <AgentListRow agent={agent} />, [AgentListRow]);
|
||||||
|
|
||||||
|
const renderSectionHeader = useCallback(
|
||||||
|
({ section }: { section: AgentListSection }) => (
|
||||||
|
<View style={styles.sectionHeader}>
|
||||||
|
<Text style={styles.sectionTitle}>{section.title}</Text>
|
||||||
|
</View>
|
||||||
|
),
|
||||||
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
const keyExtractor = useCallback(
|
const keyExtractor = useCallback(
|
||||||
@@ -225,12 +287,14 @@ export function AgentList({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<FlatList
|
<SectionList
|
||||||
data={agents}
|
sections={sections}
|
||||||
style={styles.list}
|
style={styles.list}
|
||||||
contentContainerStyle={styles.listContent}
|
contentContainerStyle={styles.listContent}
|
||||||
keyExtractor={keyExtractor}
|
keyExtractor={keyExtractor}
|
||||||
renderItem={renderAgentItem}
|
renderItem={renderAgentItem}
|
||||||
|
renderSectionHeader={renderSectionHeader}
|
||||||
|
stickySectionHeadersEnabled={false}
|
||||||
extraData={selectedAgentId}
|
extraData={selectedAgentId}
|
||||||
showsVerticalScrollIndicator={false}
|
showsVerticalScrollIndicator={false}
|
||||||
keyboardShouldPersistTaps="handled"
|
keyboardShouldPersistTaps="handled"
|
||||||
@@ -315,6 +379,16 @@ const styles = StyleSheet.create((theme) => ({
|
|||||||
paddingTop: theme.spacing[2],
|
paddingTop: theme.spacing[2],
|
||||||
paddingBottom: theme.spacing[4],
|
paddingBottom: theme.spacing[4],
|
||||||
},
|
},
|
||||||
|
sectionHeader: {
|
||||||
|
paddingVertical: theme.spacing[2],
|
||||||
|
marginTop: theme.spacing[2],
|
||||||
|
},
|
||||||
|
sectionTitle: {
|
||||||
|
fontSize: theme.fontSize.sm,
|
||||||
|
fontWeight: "500",
|
||||||
|
color: theme.colors.foregroundMuted,
|
||||||
|
textAlign: "left",
|
||||||
|
},
|
||||||
agentItem: {
|
agentItem: {
|
||||||
paddingVertical: theme.spacing[2],
|
paddingVertical: theme.spacing[2],
|
||||||
paddingHorizontal: theme.spacing[3],
|
paddingHorizontal: theme.spacing[3],
|
||||||
|
|||||||
@@ -20,13 +20,11 @@ import { StyleSheet, useUnistyles } from "react-native-unistyles";
|
|||||||
import { useQueries, useQueryClient, type UseQueryOptions } from "@tanstack/react-query";
|
import { useQueries, useQueryClient, type UseQueryOptions } from "@tanstack/react-query";
|
||||||
import { ChevronDown, ChevronRight } from "lucide-react-native";
|
import { ChevronDown, ChevronRight } from "lucide-react-native";
|
||||||
import { formatTimeAgo } from "@/utils/time";
|
import { formatTimeAgo } from "@/utils/time";
|
||||||
import { shortenPath } from "@/utils/shorten-path";
|
|
||||||
import { deriveBranchLabel, deriveProjectPath } from "@/utils/agent-display-info";
|
|
||||||
import {
|
import {
|
||||||
groupAgents,
|
groupAgents,
|
||||||
|
parseRepoNameFromRemoteUrl,
|
||||||
parseRepoShortNameFromRemoteUrl,
|
parseRepoShortNameFromRemoteUrl,
|
||||||
type ProjectGroup,
|
type ProjectGroup,
|
||||||
type DateGroup,
|
|
||||||
} from "@/utils/agent-grouping";
|
} from "@/utils/agent-grouping";
|
||||||
import { type AggregatedAgent } from "@/hooks/use-aggregated-agents";
|
import { type AggregatedAgent } from "@/hooks/use-aggregated-agents";
|
||||||
import { useSessionStore } from "@/stores/session-store";
|
import { useSessionStore } from "@/stores/session-store";
|
||||||
@@ -42,13 +40,12 @@ import {
|
|||||||
} from "@/utils/navigation-timing";
|
} from "@/utils/navigation-timing";
|
||||||
|
|
||||||
type SectionType =
|
type SectionType =
|
||||||
| { type: "project"; data: ProjectGroup }
|
| { type: "project"; data: ProjectGroup };
|
||||||
| { type: "date"; data: DateGroup };
|
|
||||||
|
|
||||||
interface SectionData {
|
interface SectionData {
|
||||||
key: string;
|
key: string;
|
||||||
title: string;
|
title: string;
|
||||||
type: "project" | "date";
|
type: "project";
|
||||||
data: AggregatedAgent[];
|
data: AggregatedAgent[];
|
||||||
/** For project sections, the first agent's serverId (to lookup checkout status) */
|
/** For project sections, the first agent's serverId (to lookup checkout status) */
|
||||||
firstAgentServerId?: string;
|
firstAgentServerId?: string;
|
||||||
@@ -68,14 +65,12 @@ interface GroupedAgentListProps {
|
|||||||
interface SectionHeaderProps {
|
interface SectionHeaderProps {
|
||||||
section: SectionData;
|
section: SectionData;
|
||||||
isCollapsed: boolean;
|
isCollapsed: boolean;
|
||||||
agentCount: number;
|
|
||||||
onToggle: () => void;
|
onToggle: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
function SectionHeader({
|
function SectionHeader({
|
||||||
section,
|
section,
|
||||||
isCollapsed,
|
isCollapsed,
|
||||||
agentCount,
|
|
||||||
onToggle,
|
onToggle,
|
||||||
}: SectionHeaderProps) {
|
}: SectionHeaderProps) {
|
||||||
const { theme } = useUnistyles();
|
const { theme } = useUnistyles();
|
||||||
@@ -90,7 +85,14 @@ function SectionHeader({
|
|||||||
// Derive display title: prefer repo name from remote URL, fallback to path-based name
|
// Derive display title: prefer repo name from remote URL, fallback to path-based name
|
||||||
let displayTitle = section.title;
|
let displayTitle = section.title;
|
||||||
if (section.type === "project" && checkout?.isGit && checkout.remoteUrl) {
|
if (section.type === "project" && checkout?.isGit && checkout.remoteUrl) {
|
||||||
const repoName = parseRepoShortNameFromRemoteUrl(checkout.remoteUrl);
|
const isGitHubRemote =
|
||||||
|
checkout.remoteUrl.includes("github.com") ||
|
||||||
|
checkout.remoteUrl.includes("git@github.com:");
|
||||||
|
|
||||||
|
const repoName = isGitHubRemote
|
||||||
|
? parseRepoNameFromRemoteUrl(checkout.remoteUrl)
|
||||||
|
: parseRepoShortNameFromRemoteUrl(checkout.remoteUrl);
|
||||||
|
|
||||||
if (repoName) {
|
if (repoName) {
|
||||||
displayTitle = repoName;
|
displayTitle = repoName;
|
||||||
}
|
}
|
||||||
@@ -105,24 +107,17 @@ function SectionHeader({
|
|||||||
onPress={onToggle}
|
onPress={onToggle}
|
||||||
>
|
>
|
||||||
<View style={styles.sectionHeaderLeft}>
|
<View style={styles.sectionHeaderLeft}>
|
||||||
{isCollapsed ? (
|
|
||||||
<ChevronRight
|
|
||||||
size={14}
|
|
||||||
color={theme.colors.foregroundMuted}
|
|
||||||
style={styles.chevron}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<ChevronDown
|
|
||||||
size={14}
|
|
||||||
color={theme.colors.foregroundMuted}
|
|
||||||
style={styles.chevron}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<Text style={styles.sectionTitle} numberOfLines={1}>
|
<Text style={styles.sectionTitle} numberOfLines={1}>
|
||||||
{displayTitle}
|
{displayTitle}
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<Text style={styles.sectionCount}>{agentCount}</Text>
|
<View style={styles.sectionHeaderRight}>
|
||||||
|
{isCollapsed ? (
|
||||||
|
<ChevronRight size={14} color={theme.colors.foregroundMuted} />
|
||||||
|
) : (
|
||||||
|
<ChevronDown size={14} color={theme.colors.foregroundMuted} />
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -241,7 +236,7 @@ export function GroupedAgentList({
|
|||||||
}, [agents, checkoutCacheQueries]);
|
}, [agents, checkoutCacheQueries]);
|
||||||
|
|
||||||
// Group agents
|
// Group agents
|
||||||
const { activeGroups, inactiveGroups } = useMemo(
|
const { activeGroups } = useMemo(
|
||||||
() =>
|
() =>
|
||||||
groupAgents(agents, {
|
groupAgents(agents, {
|
||||||
getRemoteUrl: (agent) =>
|
getRemoteUrl: (agent) =>
|
||||||
@@ -268,19 +263,8 @@ export function GroupedAgentList({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const group of inactiveGroups) {
|
|
||||||
const sectionKey = `date:${group.label}`;
|
|
||||||
const isCollapsed = collapsedSections.has(sectionKey);
|
|
||||||
result.push({
|
|
||||||
key: sectionKey,
|
|
||||||
title: group.label,
|
|
||||||
type: "date",
|
|
||||||
data: isCollapsed ? [] : group.agents,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}, [activeGroups, inactiveGroups, collapsedSections]);
|
}, [activeGroups, collapsedSections]);
|
||||||
|
|
||||||
const viewabilityConfig = useMemo(
|
const viewabilityConfig = useMemo(
|
||||||
() => ({ itemVisiblePercentThreshold: 30 }),
|
() => ({ itemVisiblePercentThreshold: 30 }),
|
||||||
@@ -338,8 +322,9 @@ export function GroupedAgentList({
|
|||||||
agentId: agent.id,
|
agentId: agent.id,
|
||||||
});
|
});
|
||||||
const checkout = checkoutQuery.data ?? null;
|
const checkout = checkoutQuery.data ?? null;
|
||||||
const projectPath = deriveProjectPath(agent.cwd, checkout);
|
const activeBranchLabel = checkout?.isGit
|
||||||
const branchLabel = deriveBranchLabel(checkout);
|
? (checkout.currentBranch ?? checkout.baseRef ?? "git")
|
||||||
|
: null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Pressable
|
<Pressable
|
||||||
@@ -373,8 +358,7 @@ export function GroupedAgentList({
|
|||||||
</View>
|
</View>
|
||||||
|
|
||||||
<Text style={styles.secondaryRow} numberOfLines={1}>
|
<Text style={styles.secondaryRow} numberOfLines={1}>
|
||||||
{shortenPath(projectPath)}
|
{activeBranchLabel ? `${activeBranchLabel} · ${timeAgo}` : timeAgo}
|
||||||
{branchLabel ? ` · ${branchLabel}` : ""} · {timeAgo}
|
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
@@ -391,31 +375,21 @@ export function GroupedAgentList({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const renderItem: SectionListRenderItem<AggregatedAgent, SectionData> =
|
const renderItem: SectionListRenderItem<AggregatedAgent, SectionData> =
|
||||||
useCallback(
|
useCallback(({ item: agent }) => <AgentListRow agent={agent} />, [AgentListRow]);
|
||||||
({ item: agent }) => <AgentListRow agent={agent} />,
|
|
||||||
[AgentListRow]
|
|
||||||
);
|
|
||||||
|
|
||||||
const renderSectionHeader = useCallback(
|
const renderSectionHeader = useCallback(
|
||||||
({ section }: { section: SectionData }) => {
|
({ section }: { section: SectionData }) => {
|
||||||
const isCollapsed = collapsedSections.has(section.key);
|
const isCollapsed = collapsedSections.has(section.key);
|
||||||
const agentCount =
|
|
||||||
section.type === "project"
|
|
||||||
? activeGroups.find((g) => `project:${g.projectKey}` === section.key)
|
|
||||||
?.agents.length ?? 0
|
|
||||||
: inactiveGroups.find((g) => `date:${g.label}` === section.key)
|
|
||||||
?.agents.length ?? 0;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SectionHeader
|
<SectionHeader
|
||||||
section={section}
|
section={section}
|
||||||
isCollapsed={isCollapsed}
|
isCollapsed={isCollapsed}
|
||||||
agentCount={agentCount}
|
|
||||||
onToggle={() => toggleSection(section.key)}
|
onToggle={() => toggleSection(section.key)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
[collapsedSections, activeGroups, inactiveGroups, toggleSection]
|
[collapsedSections, toggleSection]
|
||||||
);
|
);
|
||||||
|
|
||||||
const keyExtractor = useCallback(
|
const keyExtractor = useCallback(
|
||||||
@@ -521,7 +495,8 @@ const styles = StyleSheet.create((theme) => ({
|
|||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
justifyContent: "space-between",
|
justifyContent: "space-between",
|
||||||
paddingVertical: theme.spacing[2],
|
paddingVertical: theme.spacing[2],
|
||||||
paddingHorizontal: theme.spacing[2],
|
paddingHorizontal: theme.spacing[4] + theme.spacing[2],
|
||||||
|
marginHorizontal: -theme.spacing[4],
|
||||||
marginTop: theme.spacing[2],
|
marginTop: theme.spacing[2],
|
||||||
borderRadius: theme.borderRadius.md,
|
borderRadius: theme.borderRadius.md,
|
||||||
},
|
},
|
||||||
@@ -531,22 +506,21 @@ const styles = StyleSheet.create((theme) => ({
|
|||||||
sectionHeaderLeft: {
|
sectionHeaderLeft: {
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
|
justifyContent: "flex-start",
|
||||||
flex: 1,
|
flex: 1,
|
||||||
minWidth: 0,
|
minWidth: 0,
|
||||||
},
|
},
|
||||||
chevron: {
|
sectionHeaderRight: {
|
||||||
marginRight: theme.spacing[1],
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
marginLeft: theme.spacing[2],
|
||||||
},
|
},
|
||||||
sectionTitle: {
|
sectionTitle: {
|
||||||
fontSize: theme.fontSize.sm,
|
fontSize: theme.fontSize.sm,
|
||||||
fontWeight: theme.fontWeight.medium,
|
fontWeight: "500",
|
||||||
color: theme.colors.foregroundMuted,
|
color: theme.colors.foregroundMuted,
|
||||||
flex: 1,
|
flex: 1,
|
||||||
},
|
textAlign: "left",
|
||||||
sectionCount: {
|
|
||||||
fontSize: theme.fontSize.xs,
|
|
||||||
color: theme.colors.foregroundMuted,
|
|
||||||
marginLeft: theme.spacing[2],
|
|
||||||
},
|
},
|
||||||
agentItem: {
|
agentItem: {
|
||||||
paddingVertical: theme.spacing[2],
|
paddingVertical: theme.spacing[2],
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import Animated, {
|
|||||||
} from "react-native-reanimated";
|
} from "react-native-reanimated";
|
||||||
import { Gesture, GestureDetector } from "react-native-gesture-handler";
|
import { Gesture, GestureDetector } from "react-native-gesture-handler";
|
||||||
import { StyleSheet, UnistylesRuntime, useUnistyles } from "react-native-unistyles";
|
import { StyleSheet, UnistylesRuntime, useUnistyles } from "react-native-unistyles";
|
||||||
import { Plus, Settings } from "lucide-react-native";
|
import { ChevronRight, Plus, Settings } from "lucide-react-native";
|
||||||
import { router } from "expo-router";
|
import { router } from "expo-router";
|
||||||
import { usePanelStore } from "@/stores/panel-store";
|
import { usePanelStore } from "@/stores/panel-store";
|
||||||
import { GroupedAgentList } from "./grouped-agent-list";
|
import { GroupedAgentList } from "./grouped-agent-list";
|
||||||
@@ -75,7 +75,6 @@ export function SlidingSidebar({ selectedAgentId }: SlidingSidebarProps) {
|
|||||||
() => sortedAgents.slice(0, SIDEBAR_AGENT_LIMIT),
|
() => sortedAgents.slice(0, SIDEBAR_AGENT_LIMIT),
|
||||||
[sortedAgents]
|
[sortedAgents]
|
||||||
);
|
);
|
||||||
const hasMore = agents.length > SIDEBAR_AGENT_LIMIT;
|
|
||||||
|
|
||||||
const handleClose = useCallback(() => {
|
const handleClose = useCallback(() => {
|
||||||
closeToAgent();
|
closeToAgent();
|
||||||
@@ -171,20 +170,20 @@ export function SlidingSidebar({ selectedAgentId }: SlidingSidebarProps) {
|
|||||||
pointerEvents: backdropOpacity.value > 0.01 ? "auto" : "none",
|
pointerEvents: backdropOpacity.value > 0.01 ? "auto" : "none",
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const viewMoreButton = hasMore ? (
|
const viewMoreButton = (
|
||||||
<View style={styles.viewMoreContainer}>
|
<View style={styles.viewMoreContainer}>
|
||||||
<Pressable
|
<Pressable
|
||||||
style={({ hovered }) => [
|
style={({ hovered, pressed }) => [
|
||||||
styles.newAgentButton,
|
|
||||||
styles.viewMoreButton,
|
styles.viewMoreButton,
|
||||||
hovered && styles.newAgentButtonHovered,
|
(hovered || pressed) && styles.viewMoreButtonHovered,
|
||||||
]}
|
]}
|
||||||
onPress={handleViewMore}
|
onPress={handleViewMore}
|
||||||
>
|
>
|
||||||
<Text style={styles.viewMoreButtonText}>View More</Text>
|
<Text style={styles.viewMoreButtonText}>All agents</Text>
|
||||||
|
<ChevronRight size={16} color={theme.colors.foregroundMuted} />
|
||||||
</Pressable>
|
</Pressable>
|
||||||
</View>
|
</View>
|
||||||
) : null;
|
);
|
||||||
|
|
||||||
// Render mobile sidebar
|
// Render mobile sidebar
|
||||||
// On web, use "auto" instead of "box-none" because web's pointer-events: none blocks scroll
|
// On web, use "auto" instead of "box-none" because web's pointer-events: none blocks scroll
|
||||||
@@ -354,12 +353,25 @@ const styles = StyleSheet.create((theme) => ({
|
|||||||
paddingTop: theme.spacing[2],
|
paddingTop: theme.spacing[2],
|
||||||
},
|
},
|
||||||
viewMoreButton: {
|
viewMoreButton: {
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "flex-start",
|
||||||
|
gap: theme.spacing[1],
|
||||||
paddingVertical: theme.spacing[2],
|
paddingVertical: theme.spacing[2],
|
||||||
|
paddingHorizontal: 0,
|
||||||
|
borderWidth: 0,
|
||||||
|
backgroundColor: "transparent",
|
||||||
|
alignSelf: "flex-start",
|
||||||
|
transitionProperty: "opacity",
|
||||||
|
transitionDuration: "150ms",
|
||||||
|
},
|
||||||
|
viewMoreButtonHovered: {
|
||||||
|
opacity: 0.8,
|
||||||
},
|
},
|
||||||
viewMoreButtonText: {
|
viewMoreButtonText: {
|
||||||
fontSize: theme.fontSize.base,
|
fontSize: theme.fontSize.base,
|
||||||
fontWeight: theme.fontWeight.normal,
|
fontWeight: theme.fontWeight.normal,
|
||||||
color: theme.colors.foreground,
|
color: theme.colors.foregroundMuted,
|
||||||
},
|
},
|
||||||
sidebarFooter: {
|
sidebarFooter: {
|
||||||
paddingHorizontal: theme.spacing[4],
|
paddingHorizontal: theme.spacing[4],
|
||||||
|
|||||||
@@ -204,7 +204,7 @@ export interface GroupedAgents {
|
|||||||
inactiveGroups: DateGroup[];
|
inactiveGroups: DateGroup[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const ACTIVE_GRACE_PERIOD_MS = 5 * 60 * 1000; // 5 minutes
|
const ACTIVE_GRACE_PERIOD_MS = 15 * 60 * 1000; // 15 minutes
|
||||||
|
|
||||||
interface GroupAgentsOptions {
|
interface GroupAgentsOptions {
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user