Fix mobile dropdown close and draft thinking persistence
Closes #150 Closes #151
This commit is contained in:
@@ -13,6 +13,7 @@ import { useHosts } from "@/runtime/host-runtime";
|
||||
import { useHostRuntimeClient, useHostRuntimeIsConnected } from "@/runtime/host-runtime";
|
||||
import {
|
||||
useFormPreferences,
|
||||
mergeProviderPreferences,
|
||||
type FormPreferences,
|
||||
type ProviderPreferences,
|
||||
} from "./use-form-preferences";
|
||||
@@ -693,26 +694,23 @@ export function useAgentFormState(options: UseAgentFormStateOptions = {}): UseAg
|
||||
const persistFormPreferences = useCallback(async () => {
|
||||
const resolvedModel = resolveEffectiveModel(availableModels, formState.model);
|
||||
const modelId = resolvedModel?.id ?? formState.model;
|
||||
const existingProviderPrefs = preferences?.providerPreferences?.[formState.provider];
|
||||
|
||||
const nextProviderPrefs: ProviderPreferences = {
|
||||
model: modelId || undefined,
|
||||
mode: formState.modeId || undefined,
|
||||
thinkingByModel: {
|
||||
...existingProviderPrefs?.thinkingByModel,
|
||||
...(modelId && formState.thinkingOptionId
|
||||
? { [modelId]: formState.thinkingOptionId }
|
||||
: {}),
|
||||
},
|
||||
};
|
||||
|
||||
await updatePreferences({
|
||||
const nextPreferences = mergeProviderPreferences({
|
||||
preferences: preferences ?? {},
|
||||
provider: formState.provider,
|
||||
providerPreferences: {
|
||||
...preferences?.providerPreferences,
|
||||
[formState.provider]: nextProviderPrefs,
|
||||
},
|
||||
updates: {
|
||||
model: modelId || undefined,
|
||||
mode: formState.modeId || undefined,
|
||||
...(modelId && formState.thinkingOptionId
|
||||
? {
|
||||
thinkingByModel: {
|
||||
[modelId]: formState.thinkingOptionId,
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
} satisfies Partial<ProviderPreferences>,
|
||||
});
|
||||
|
||||
await updatePreferences(nextPreferences);
|
||||
}, [
|
||||
availableModels,
|
||||
formState.model,
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { mergeProviderPreferences } from "./use-form-preferences";
|
||||
|
||||
describe("mergeProviderPreferences", () => {
|
||||
it("stores the selected model for a provider", () => {
|
||||
expect(
|
||||
mergeProviderPreferences({
|
||||
preferences: {},
|
||||
provider: "claude",
|
||||
updates: { model: "claude-opus-4-6" },
|
||||
}),
|
||||
).toEqual({
|
||||
provider: "claude",
|
||||
providerPreferences: {
|
||||
claude: {
|
||||
model: "claude-opus-4-6",
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("merges thinking preferences by model without dropping existing entries", () => {
|
||||
expect(
|
||||
mergeProviderPreferences({
|
||||
preferences: {
|
||||
provider: "claude",
|
||||
providerPreferences: {
|
||||
claude: {
|
||||
model: "claude-sonnet-4-6",
|
||||
thinkingByModel: {
|
||||
"claude-sonnet-4-6": "medium",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
provider: "claude",
|
||||
updates: {
|
||||
thinkingByModel: {
|
||||
"claude-opus-4-6": "high",
|
||||
},
|
||||
},
|
||||
}),
|
||||
).toEqual({
|
||||
provider: "claude",
|
||||
providerPreferences: {
|
||||
claude: {
|
||||
model: "claude-sonnet-4-6",
|
||||
thinkingByModel: {
|
||||
"claude-sonnet-4-6": "medium",
|
||||
"claude-opus-4-6": "high",
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -2,6 +2,7 @@ import { useCallback } from "react";
|
||||
import AsyncStorage from "@react-native-async-storage/async-storage";
|
||||
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { z } from "zod";
|
||||
import type { AgentProvider } from "@server/server/agent/agent-sdk-types";
|
||||
|
||||
const FORM_PREFERENCES_STORAGE_KEY = "@paseo:create-agent-preferences";
|
||||
const FORM_PREFERENCES_QUERY_KEY = ["form-preferences"];
|
||||
@@ -35,6 +36,36 @@ export interface UseFormPreferencesReturn {
|
||||
updatePreferences: (updates: Partial<FormPreferences>) => Promise<void>;
|
||||
}
|
||||
|
||||
export function mergeProviderPreferences(args: {
|
||||
preferences: FormPreferences;
|
||||
provider: AgentProvider;
|
||||
updates: Partial<ProviderPreferences>;
|
||||
}): FormPreferences {
|
||||
const { preferences, provider, updates } = args;
|
||||
const existingProviderPreferences = preferences.providerPreferences ?? {};
|
||||
const existing = existingProviderPreferences[provider] ?? {};
|
||||
const nextThinkingByModel =
|
||||
updates.thinkingByModel === undefined
|
||||
? existing.thinkingByModel
|
||||
: {
|
||||
...existing.thinkingByModel,
|
||||
...updates.thinkingByModel,
|
||||
};
|
||||
|
||||
return {
|
||||
...preferences,
|
||||
provider,
|
||||
providerPreferences: {
|
||||
...existingProviderPreferences,
|
||||
[provider]: {
|
||||
...existing,
|
||||
...updates,
|
||||
...(nextThinkingByModel ? { thinkingByModel: nextThinkingByModel } : {}),
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function useFormPreferences(): UseFormPreferencesReturn {
|
||||
const queryClient = useQueryClient();
|
||||
const { data, isPending } = useQuery({
|
||||
|
||||
Reference in New Issue
Block a user