Skip to content

Commit

Permalink
chore: refactor actions
Browse files Browse the repository at this point in the history
  • Loading branch information
jedwards1230 committed Apr 23, 2024
1 parent 5cbf5dd commit 485bd03
Show file tree
Hide file tree
Showing 21 changed files with 245 additions and 158 deletions.
38 changes: 19 additions & 19 deletions client/src/components/CommandTray/CommandTray.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,32 @@
import { View } from "react-native";

import { Text } from "@/components/ui/Text";
import { ActionList } from "@/hooks/useAction";
import { ActionList } from "@/hooks/actions";

export function CommandTray({ input }: { input: string }) {
if (!input.startsWith("/")) return null;
return (
<View className="flex flex-row items-center justify-between w-full py-2 pl-2 pr-2 web:pr-10">
<CommandList input={input} />
</View>
);
if (!input.startsWith("/")) return null;
return (
<View className="flex flex-row items-center justify-between w-full py-2 pl-2 pr-2 web:pr-10">
<CommandList input={input} />
</View>
);
}

function CommandList({ input }: { input: string }) {
const command = input.slice(1);
const possibleCommands = command
? ActionList.filter((c) => c.startsWith(command))
: ActionList;
const command = input.slice(1);
const possibleCommands = command
? ActionList.filter((c) => c.startsWith(command))
: ActionList;

return (
<View>
{possibleCommands.map((command) => (
<CommandItem key={command} command={command} />
))}
</View>
);
return (
<View>
{possibleCommands.map((command) => (
<CommandItem key={command} command={command} />
))}
</View>
);
}

function CommandItem({ command }: { command: string }) {
return <Text>{command}</Text>;
return <Text>{command}</Text>;
}
14 changes: 11 additions & 3 deletions client/src/components/Dialogs/Command.web.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
} from "@/components/ui/Command";
import { Icon } from "@/components/ui/Icon";
import { useConfigStore } from "@/hooks/stores/configStore";
import { useAction } from "@/hooks/useAction";
import { useDeleteActiveThread, useDeleteAllThreads, useResetDb } from "@/hooks/actions";

export function CommandDialog({
open,
Expand All @@ -22,8 +22,9 @@ export function CommandDialog({
setOpen: React.Dispatch<React.SetStateAction<boolean>>;
}) {
const { threadId } = useConfigStore();
const deleteThread = useAction("deleteThread")();
const resetDb = useAction("resetDb")();
const deleteThread = useDeleteActiveThread();
const deleteAllThreads = useDeleteAllThreads();
const resetDb = useResetDb();

const items = [
{
Expand All @@ -34,6 +35,13 @@ export function CommandDialog({
onClick: () => deleteThread.action(threadId!),
hidden: !threadId,
},
{
label: "Delete All Threads",
Icon: Icon,
type: "FontAwesome" as const,
iconName: "trash" as const,
onClick: deleteAllThreads.action,
},
{
label: "Reset DB",
Icon: Icon,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import { Pressable, View } from "react-native";
import { useRouter } from "expo-router";

import type { Thread } from "@/types";
import { useAction } from "@/hooks/useAction";
import { Text } from "@/components/ui/Text";
import ChatHistory from "@/components/ChatHistory";
import { useHoverHelper } from "@/hooks/useHoverHelper";
import { cn } from "@/lib/utils";
import { useDeleteActiveThread } from "@/hooks/actions";

const menuConfig: MenuConfig = {
menuTitle: "",
Expand All @@ -21,7 +21,7 @@ const menuConfig: MenuConfig = {

export function ThreadButton({ thread }: { thread: Thread }) {
const { isHover, ...helpers } = useHoverHelper();
const deleteThread = useAction("deleteThread")();
const deleteThread = useDeleteActiveThread();
const router = useRouter();

const goToThread = () =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ import { useSafeAreaInsets } from "react-native-safe-area-context";

import type { Thread } from "@/types";
import { useUserData } from "@/hooks/stores/useUserData";
import { useAction } from "@/hooks/useAction";
import { useDeleteActiveThread } from "@/hooks/actions";
import { Icon } from "@/components/ui/Icon";
import { Text } from "@/components/ui/Text";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/Popover";
import { Button } from "@/components/ui/Button";

export function ThreadButtonPopover({ thread }: { thread: Thread }) {
const session = useUserData((s) => s.session);
const deleteThread = useAction("deleteThread")();
const deleteThread = useDeleteActiveThread();

const insets = useSafeAreaInsets();
const contentInsets = {
Expand Down
1 change: 1 addition & 0 deletions client/src/components/ui/Icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
} from "@expo/vector-icons";
import { IconProps as baseProps } from "@expo/vector-icons/build/createIconSet";
import { useContext } from "react";

import { TextClassContext } from "./Text";
import { cn } from "@/lib/utils";

Expand Down
31 changes: 31 additions & 0 deletions client/src/hooks/actions/actions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { useQueryClient } from "@tanstack/react-query";

import { fetcher } from "@/lib/fetcher";
import { useUserData } from "../stores/useUserData";
import { useDeleteThreadMutation } from "../fetchers/Thread/useDeleteThreadMutation";
import { useDeleteAllThreadsMutation } from "../fetchers/Thread/useDeleteAllThreadsMutation";

export function useDeleteActiveThread() {
const { mutateAsync } = useDeleteThreadMutation();
const action = async (threadId: string) => mutateAsync(threadId);
return { action };
}

export function useDeleteAllThreads() {
const { mutateAsync } = useDeleteAllThreadsMutation();
const action = async () => mutateAsync();
return { action };
}

/** Reset the Server DB to empty. */
export function useResetDb() {
const queryClient = useQueryClient();
const apiKey = useUserData((s) => s.apiKey);

const action = async () => {
await fetcher("/reset", { apiKey });
queryClient.invalidateQueries();
};

return { action };
}
10 changes: 10 additions & 0 deletions client/src/hooks/actions/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import * as actionFunctions from "./actions";
export * from "./actions";

const Actions = actionFunctions;

export type ActionMap = typeof Actions;
export type Command = keyof ActionMap;
export type UIAction = ReturnType<ActionMap[keyof ActionMap]>;

export const ActionList: Command[] = Object.keys(Actions) as Command[];
5 changes: 0 additions & 5 deletions client/src/hooks/fetchers/Message/useMessagesQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,3 @@ export const useMessagesQuery = (threadId: string | null) => {
const apiKey = useUserData((s) => s.apiKey);
return useQuery(messagesQueryOptions(apiKey, threadId));
};

export const useMessagesQueryOptions = (threadId: string | null) => {
const apiKey = useUserData((s) => s.apiKey);
return messagesQueryOptions(apiKey, threadId);
};
42 changes: 42 additions & 0 deletions client/src/hooks/fetchers/Thread/useDeleteAllThreadsMutation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { useMutation, useQueryClient } from "@tanstack/react-query";

import { fetcher } from "@/lib/fetcher";
import { threadListQueryOptions } from "./useThreadListQuery";
import { useUserData } from "../../stores/useUserData";
import { useConfigStore } from "@/hooks/stores/configStore";

const deleteThread = (apiKey: string) =>
fetcher(`/threads/`, {
apiKey,
method: "DELETE",
stream: true,
});

export function useDeleteAllThreadsMutation() {
const apiKey = useUserData.use.apiKey();
const setThreadId = useConfigStore.use.setThreadId();
const queryClient = useQueryClient();

return useMutation({
mutationKey: ["deleteAllThreads"],
mutationFn: () => deleteThread(apiKey),
onMutate: async () => {
const listQuery = threadListQueryOptions(apiKey);
setThreadId(null);
await queryClient.cancelQueries();
const cached = queryClient.getQueryData(listQuery.queryKey);

queryClient.setQueryData(listQuery.queryKey, []);
return { cached };
},
onSuccess: async () => queryClient.invalidateQueries(),
onError: async (error, _, ctx) => {
console.error("Failed to delete threads: " + error);
queryClient.setQueryData(
threadListQueryOptions(apiKey).queryKey,
ctx?.cached
);
await queryClient.invalidateQueries();
},
});
}
44 changes: 0 additions & 44 deletions client/src/hooks/useAction/actions.tsx

This file was deleted.

1 change: 0 additions & 1 deletion client/src/hooks/useAction/index.ts

This file was deleted.

76 changes: 38 additions & 38 deletions client/src/hooks/useChat/useChat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,42 +6,42 @@ import { useThreadManager } from "./useThreadManager";
export type FormSubmission = (input: string) => Promise<void>;

export function useChat(initialThreadId: string | null) {
const [isRunning, setIsRunning] = useState(false);
const [error, setError] = useState<string | null>(null);

const threadManager = useThreadManager(initialThreadId);
const chatResponseManager = useChatResponse();

const reset = (threadId?: string | null) => {
setIsRunning(false);
threadManager.reset(threadId);
};

const abort = () => {
reset();
chatResponseManager.abort();
};

const handleSubmit: FormSubmission = async (input) => {
setIsRunning(true);
try {
const { threadId } = await threadManager.onSubmit(initialThreadId, input);
chatResponseManager.requestChat(threadId);
reset(threadId);
} catch (error) {
setError("Failed to send message");
reset();
console.error(error);
} finally {
setIsRunning(false);
}
};

return {
error,
loading:
threadManager.isMutating || chatResponseManager.isResponding || isRunning,
handleSubmit,
abort,
};
const [isRunning, setIsRunning] = useState(false);
const [error, setError] = useState<string | null>(null);

const threadManager = useThreadManager(initialThreadId);
const chatResponseManager = useChatResponse();

const reset = (threadId?: string | null) => {
setIsRunning(false);
threadManager.reset(threadId);
};

const abort = () => {
reset();
chatResponseManager.abort();
};

const handleSubmit: FormSubmission = async (input) => {
setIsRunning(true);
try {
const { threadId } = await threadManager.onSubmit(initialThreadId, input);
chatResponseManager.requestChat(threadId);
reset(threadId);
} catch (error) {
setError("Failed to send message");
reset();
console.error(error);
} finally {
setIsRunning(false);
}
};

return {
error,
loading:
threadManager.isMutating || chatResponseManager.isResponding || isRunning,
handleSubmit,
abort,
};
}
9 changes: 5 additions & 4 deletions client/src/hooks/useChat/useThreadManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,18 @@ export const useThreadManager = (initialThreadId: string | null) => {
const router = useRouter();
const [error, setError] = useState<string | null>(null);
const [activeThreadId, setActiveThreadId] = useState<string | null>(initialThreadId);
useEffect(() => {
if (initialThreadId !== activeThreadId) return;
setActiveThreadId(initialThreadId);
}, [initialThreadId]);

const fileList = useFileStore.use.fileList();
const messagesQuery = useMessagesQuery(activeThreadId);
const createThreadMut = useThreadPost();
const addMessageMut = useMessagePost();
const addMessageFileMut = useMessageFilePost();

useEffect(() => {
if (initialThreadId !== activeThreadId) return;
setActiveThreadId(initialThreadId);
}, [initialThreadId]);

const isMutating =
addMessageMut.isPending ||
createThreadMut.isPending ||
Expand Down
4 changes: 2 additions & 2 deletions client/src/views/chat/ChatHeader/CenterButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ import { useConfigStore } from "@/hooks/stores/configStore";
import { useAgentQuery } from "@/hooks/fetchers/Agent/useAgentQuery";
import { useMessagesQuery } from "@/hooks/fetchers/Message/useMessagesQuery";
import { useTokenCount } from "@/hooks/useTokenCount";
import { useAction } from "@/hooks/useAction";
import { useDeleteActiveThread } from "@/hooks/actions";

export function CenterButton({ threadId }: { threadId: string | null }) {
const router = useRouter();
const { defaultAgent } = useConfigStore();

const { data: messages } = useMessagesQuery(threadId);
const { data: agent } = useAgentQuery(defaultAgent.id);
const deleteThread = useAction("deleteThread")();
const deleteThread = useDeleteActiveThread();

const tokenInput = messages?.map((m) => m.content).join(" ") || "";
const tokens = useTokenCount(tokenInput);
Expand Down
Loading

0 comments on commit 485bd03

Please sign in to comment.