1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
|
import { invoke } from "@tauri-apps/api/core";
import { toast } from "sonner";
import { create } from "zustand";
import type { Instance } from "../types/bindings/instance";
interface InstancesState {
// State
instances: Instance[];
activeInstanceId: string | null;
// Computed property
activeInstance: Instance | null;
// Actions
loadInstances: () => Promise<void>;
createInstance: (name: string) => Promise<Instance | null>;
deleteInstance: (id: string) => Promise<void>;
updateInstance: (instance: Instance) => Promise<void>;
setActiveInstance: (id: string) => Promise<void>;
duplicateInstance: (id: string, newName: string) => Promise<Instance | null>;
getInstance: (id: string) => Promise<Instance | null>;
setInstances: (instances: Instance[]) => void;
setActiveInstanceId: (id: string | null) => void;
}
export const useInstancesStore = create<InstancesState>((set, get) => ({
// Initial state
instances: [],
activeInstanceId: null,
// Computed property
get activeInstance() {
const { instances, activeInstanceId } = get();
if (!activeInstanceId) return null;
return instances.find((i) => i.id === activeInstanceId) || null;
},
// Actions
loadInstances: async () => {
try {
const instances = await invoke<Instance[]>("list_instances");
const active = await invoke<Instance | null>("get_active_instance");
let newActiveInstanceId = null;
if (active) {
newActiveInstanceId = active.id;
} else if (instances.length > 0) {
// If no active instance but instances exist, set the first one as active
await get().setActiveInstance(instances[0].id);
newActiveInstanceId = instances[0].id;
}
set({ instances, activeInstanceId: newActiveInstanceId });
} catch (e) {
console.error("Failed to load instances:", e);
toast.error("Error loading instances: " + String(e));
}
},
createInstance: async (name) => {
try {
const instance = await invoke<Instance>("create_instance", { name });
await get().loadInstances();
toast.success(`Instance "${name}" created successfully`);
return instance;
} catch (e) {
console.error("Failed to create instance:", e);
toast.error("Error creating instance: " + String(e));
return null;
}
},
deleteInstance: async (id) => {
try {
await invoke("delete_instance", { instanceId: id });
await get().loadInstances();
// If deleted instance was active, set another as active
const { instances, activeInstanceId } = get();
if (activeInstanceId === id) {
if (instances.length > 0) {
await get().setActiveInstance(instances[0].id);
} else {
set({ activeInstanceId: null });
}
}
toast.success("Instance deleted successfully");
} catch (e) {
console.error("Failed to delete instance:", e);
toast.error("Error deleting instance: " + String(e));
}
},
updateInstance: async (instance) => {
try {
await invoke("update_instance", { instance });
await get().loadInstances();
toast.success("Instance updated successfully");
} catch (e) {
console.error("Failed to update instance:", e);
toast.error("Error updating instance: " + String(e));
}
},
setActiveInstance: async (id) => {
try {
await invoke("set_active_instance", { instanceId: id });
set({ activeInstanceId: id });
toast.success("Active instance changed");
} catch (e) {
console.error("Failed to set active instance:", e);
toast.error("Error setting active instance: " + String(e));
}
},
duplicateInstance: async (id, newName) => {
try {
const instance = await invoke<Instance>("duplicate_instance", {
instanceId: id,
newName,
});
await get().loadInstances();
toast.success(`Instance duplicated as "${newName}"`);
return instance;
} catch (e) {
console.error("Failed to duplicate instance:", e);
toast.error("Error duplicating instance: " + String(e));
return null;
}
},
getInstance: async (id) => {
try {
return await invoke<Instance>("get_instance", { instanceId: id });
} catch (e) {
console.error("Failed to get instance:", e);
return null;
}
},
setInstances: (instances) => {
set({ instances });
},
setActiveInstanceId: (id) => {
set({ activeInstanceId: id });
},
}));
|