chore: delete unused files flagged by knip
38 files removed across app and server (verified unreferenced via grep + typecheck). Includes dead components, hooks, stores, utils, POC scripts, an empty orchestrator stub, stale playwright configs, and a duplicate workspace-registry test-helpers module. knip config tightened: added babel.config.js, native platform extensions, and test-stubs/ to app entry patterns.
This commit is contained in:
-1
@@ -1 +0,0 @@
|
||||
export * from "./use-dictation";
|
||||
@@ -1,71 +0,0 @@
|
||||
import { useState, useEffect, useCallback } from "react";
|
||||
import AsyncStorage from "@react-native-async-storage/async-storage";
|
||||
|
||||
const STORAGE_KEY = "@paseo:recent-paths";
|
||||
const MAX_RECENT_PATHS = 3;
|
||||
|
||||
export interface UseRecentPathsReturn {
|
||||
recentPaths: string[];
|
||||
isLoading: boolean;
|
||||
addRecentPath: (path: string) => Promise<void>;
|
||||
clearRecentPaths: () => Promise<void>;
|
||||
}
|
||||
|
||||
export function useRecentPaths(): UseRecentPathsReturn {
|
||||
const [recentPaths, setRecentPaths] = useState<string[]>([]);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
// Load recent paths from AsyncStorage on mount
|
||||
useEffect(() => {
|
||||
loadRecentPaths();
|
||||
}, []);
|
||||
|
||||
async function loadRecentPaths() {
|
||||
try {
|
||||
const stored = await AsyncStorage.getItem(STORAGE_KEY);
|
||||
if (stored) {
|
||||
const parsed = JSON.parse(stored) as string[];
|
||||
setRecentPaths(parsed);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("[RecentPaths] Failed to load recent paths:", error);
|
||||
// Continue with empty array
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
const addRecentPath = useCallback(
|
||||
async (path: string) => {
|
||||
try {
|
||||
// Remove duplicates and add to front
|
||||
const filtered = recentPaths.filter((p) => p !== path);
|
||||
const updated = [path, ...filtered].slice(0, MAX_RECENT_PATHS);
|
||||
|
||||
setRecentPaths(updated);
|
||||
await AsyncStorage.setItem(STORAGE_KEY, JSON.stringify(updated));
|
||||
} catch (error) {
|
||||
console.error("[RecentPaths] Failed to save recent path:", error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
[recentPaths],
|
||||
);
|
||||
|
||||
const clearRecentPaths = useCallback(async () => {
|
||||
try {
|
||||
setRecentPaths([]);
|
||||
await AsyncStorage.removeItem(STORAGE_KEY);
|
||||
} catch (error) {
|
||||
console.error("[RecentPaths] Failed to clear recent paths:", error);
|
||||
throw error;
|
||||
}
|
||||
}, []);
|
||||
|
||||
return {
|
||||
recentPaths,
|
||||
isLoading,
|
||||
addRecentPath,
|
||||
clearRecentPaths,
|
||||
};
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
import { useEffect, useMemo } from "react";
|
||||
import { useQueries } from "@tanstack/react-query";
|
||||
import {
|
||||
checkoutStatusQueryKey,
|
||||
type CheckoutStatusPayload,
|
||||
CHECKOUT_STATUS_STALE_TIME,
|
||||
} from "@/hooks/use-checkout-status-query";
|
||||
import { groupAgents } from "@/utils/agent-grouping";
|
||||
import { useSectionOrderStore, sortProjectsByStoredOrder } from "@/stores/section-order-store";
|
||||
import type { AggregatedAgent } from "@/hooks/use-aggregated-agents";
|
||||
|
||||
export interface SidebarSectionData {
|
||||
key: string;
|
||||
projectKey: string;
|
||||
title: string;
|
||||
agents: AggregatedAgent[];
|
||||
/** For project sections, the first agent's serverId (to lookup checkout status) */
|
||||
firstAgentServerId?: string;
|
||||
/** For project sections, the first agent's id (to lookup checkout status) */
|
||||
firstAgentId?: string;
|
||||
/** Working directory for the project (from first agent) */
|
||||
workingDir?: string;
|
||||
}
|
||||
|
||||
export function useSidebarAgentSections(agents: AggregatedAgent[]): SidebarSectionData[] {
|
||||
// Subscribe to checkout status cache entries for each visible agent so that grouping
|
||||
// can switch from cwd→remote as soon as checkout status is prefetched.
|
||||
//
|
||||
// This avoids a brief UI state where two separate sections can render with the
|
||||
// same icon/title while grouping is still keyed by cwd.
|
||||
const checkoutStatusQueries = useQueries({
|
||||
queries: agents.map((agent) => ({
|
||||
queryKey: checkoutStatusQueryKey(agent.serverId, agent.cwd),
|
||||
queryFn: async (): Promise<CheckoutStatusPayload> => {
|
||||
throw new Error("Checkout status query is disabled in sidebar grouping");
|
||||
},
|
||||
enabled: false,
|
||||
staleTime: CHECKOUT_STATUS_STALE_TIME,
|
||||
})),
|
||||
});
|
||||
|
||||
const remoteUrlByAgentKey = useMemo(() => {
|
||||
const result = new Map<string, string | null>();
|
||||
for (let idx = 0; idx < agents.length; idx++) {
|
||||
const agent = agents[idx];
|
||||
const checkout = checkoutStatusQueries[idx]?.data ?? null;
|
||||
result.set(`${agent.serverId}:${agent.id}`, checkout?.remoteUrl ?? null);
|
||||
}
|
||||
return result;
|
||||
}, [agents, checkoutStatusQueries]);
|
||||
|
||||
const projectOrder = useSectionOrderStore((state) => state.projectOrder);
|
||||
const setProjectOrder = useSectionOrderStore((state) => state.setProjectOrder);
|
||||
|
||||
const { activeGroups } = useMemo(
|
||||
() =>
|
||||
groupAgents(agents, {
|
||||
getRemoteUrl: (agent) => remoteUrlByAgentKey.get(`${agent.serverId}:${agent.id}`) ?? null,
|
||||
}),
|
||||
[agents, remoteUrlByAgentKey],
|
||||
);
|
||||
|
||||
const sortedGroups = useMemo(
|
||||
() => sortProjectsByStoredOrder(activeGroups, projectOrder),
|
||||
[activeGroups, projectOrder],
|
||||
);
|
||||
|
||||
const sections: SidebarSectionData[] = useMemo(() => {
|
||||
const result: SidebarSectionData[] = [];
|
||||
|
||||
for (const group of sortedGroups) {
|
||||
const sectionKey = `project:${group.projectKey}`;
|
||||
const firstAgent = group.agents[0];
|
||||
result.push({
|
||||
key: sectionKey,
|
||||
projectKey: group.projectKey,
|
||||
title: group.projectName,
|
||||
agents: group.agents,
|
||||
firstAgentServerId: firstAgent?.serverId,
|
||||
firstAgentId: firstAgent?.id,
|
||||
workingDir: firstAgent?.cwd,
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}, [sortedGroups]);
|
||||
|
||||
// Sync section order when new projects appear.
|
||||
useEffect(() => {
|
||||
const currentKeys = sections.map((s) => s.projectKey);
|
||||
const storedKeys = new Set(projectOrder);
|
||||
const newKeys = currentKeys.filter((key) => !storedKeys.has(key));
|
||||
|
||||
if (newKeys.length > 0) {
|
||||
setProjectOrder([...projectOrder, ...newKeys]);
|
||||
}
|
||||
}, [projectOrder, sections, setProjectOrder]);
|
||||
|
||||
return sections;
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
/**
|
||||
* Learn more about light and dark modes:
|
||||
* https://docs.expo.dev/guides/color-schemes/
|
||||
*/
|
||||
|
||||
import { Colors } from "@/constants/theme";
|
||||
import { useColorScheme } from "@/hooks/use-color-scheme";
|
||||
|
||||
export function useThemeColor(
|
||||
props: { light?: string; dark?: string },
|
||||
colorName: keyof typeof Colors.light & keyof typeof Colors.dark,
|
||||
) {
|
||||
const theme = useColorScheme() ?? "light";
|
||||
const colorFromProps = props[theme];
|
||||
|
||||
if (colorFromProps) {
|
||||
return colorFromProps;
|
||||
} else {
|
||||
return Colors[theme][colorName];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user