mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-07-17 02:01:26 +02:00
Duplicate models from the DB instead of frontend snapshots (#505)
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { getCurrentWebviewWindow } from "@tauri-apps/api/webviewWindow";
|
||||
import { resolvedModelName } from "@yaakapp/yaak-client/lib/resolvedModelName";
|
||||
import { AnyModel, ModelPayload } from "../bindings/gen_models";
|
||||
import { modelStoreDataAtom } from "./atoms";
|
||||
import { ExtractModel, JotaiStore, ModelStoreData } from "./types";
|
||||
@@ -156,44 +155,22 @@ export async function deleteModel<M extends AnyModel["model"], T extends Extract
|
||||
await trackModelWrite(invoke<string>("models_delete", { model }));
|
||||
}
|
||||
|
||||
export function duplicateModel<M extends AnyModel["model"], T extends ExtractModel<AnyModel, M>>(
|
||||
model: T | null,
|
||||
) {
|
||||
export async function duplicateModel<
|
||||
M extends AnyModel["model"],
|
||||
T extends ExtractModel<AnyModel, M>,
|
||||
>(model: T | null): Promise<string> {
|
||||
if (model == null) {
|
||||
throw new Error("Failed to duplicate null model");
|
||||
}
|
||||
|
||||
// If the model has an explicit (non-empty) name, try to duplicate it with a name that doesn't conflict.
|
||||
// When the name is empty, keep it empty so the display falls back to the URL.
|
||||
let name = "name" in model ? model.name : undefined;
|
||||
if (name) {
|
||||
const existingModels = listModels(model.model);
|
||||
for (let i = 0; i < 100; i++) {
|
||||
const hasConflict = existingModels.some((m) => {
|
||||
if ("folderId" in m && "folderId" in model && model.folderId !== m.folderId) {
|
||||
return false;
|
||||
} else if (resolvedModelName(m) !== name) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
if (!hasConflict) {
|
||||
break;
|
||||
}
|
||||
// Flush pending writes first, since the backend duplicates from the DB (the passed-in
|
||||
// model may be a stale snapshot, eg. from the memoized sidebar tree). Conflict-free
|
||||
// naming ("Foo Copy 2") is also handled by the backend.
|
||||
await flushAllModelWrites();
|
||||
|
||||
// Name conflict. Try another one
|
||||
const m: RegExpMatchArray | null = name.match(/ Copy( (?<n>\d+))?$/);
|
||||
if (m != null && m.groups?.n == null) {
|
||||
name = name.substring(0, m.index) + " Copy 2";
|
||||
} else if (m != null && m.groups?.n != null) {
|
||||
name = name.substring(0, m.index) + ` Copy ${parseInt(m.groups.n) + 1}`;
|
||||
} else {
|
||||
name = `${name} Copy`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return trackModelWrite(invoke<string>("models_duplicate", { model: { ...model, name } }));
|
||||
return trackModelWrite(
|
||||
invoke<string>("models_duplicate", { modelType: model.model, modelId: model.id }),
|
||||
);
|
||||
}
|
||||
|
||||
export async function createGlobalModel<T extends Exclude<AnyModel, { workspaceId: string }>>(
|
||||
|
||||
Reference in New Issue
Block a user