ai #1

Merged
ssa merged 17 commits from ai into main 2026-02-18 22:44:42 +03:00
2 changed files with 47 additions and 61 deletions
Showing only changes of commit 6565223b96 - Show all commits

View File

@@ -11,78 +11,55 @@ import logo from './assets/cgg.png'
class AppState { class AppState {
private constructor( private constructor(
public config: Config = new Config(), public config: Config = new Config(),
public envs: Env[] = [
],
) { } ) { }
static readonly Instance = new AppState(); static readonly Instance = new AppState();
public loadConfig(cfg: Config) { public loadConfig(cfg: Config) {
this.config = cfg; this.config = cfg;
this.envs = cfg.envs; // Reference the same array as config
}
public addEnv(env: Env): number {
this.envs.push(env);
// Also update config.envs since they reference the same array
this.config.envs = this.envs;
return this.envs.length - 1;
} }
public async saveEnv(env: Env): Promise<number> { public async saveEnv(env: Env): Promise<number> {
// Create a promise that resolves after 1 second // Simulate async save with 1 second delay
return await new Promise<number>((resolve) => { return await new Promise<number>((resolve) => {
setTimeout(() => { setTimeout(() => {
let idx = this.envs.findIndex(x => x.id === env.id); console.log("Saved env:", env.name);
if (idx > -1) { resolve(0);
this.envs[idx] = env;
console.log("UPDATED envs", this.envs);
}
resolve(idx); // Resolve the promise after updating
}, 1000); }, 1000);
}); });
} }
public removeEnv(envId: number) {
const idx = this.envs.findIndex(x => x.id === envId);
if (idx > -1) {
this.envs.splice(idx, 1);
// Also update config.envs since they reference the same array
this.config.envs = this.envs;
}
}
// Update the internal envs reference to match React state
public syncEnvs(newEnvs: Env[]) {
this.envs = newEnvs;
this.config.envs = newEnvs;
}
} }
function App() { function App() {
const [envs, setEnvs] = useState(AppState.Instance.envs); const [config, setConfig] = useState(() => AppState.Instance.config);
const [envs, setEnvs] = useState(() => AppState.Instance.config.envs);
const [selectedEnv, setSelectedEnv] = useState(0); const [selectedEnv, setSelectedEnv] = useState(0);
const [config, setConfig] = useState(AppState.Instance.config);
// Ensure selectedEnv is always valid // Ensure selectedEnv is always valid
const validSelectedEnv = Math.min(selectedEnv, Math.max(0, envs.length - 1)); const validSelectedEnv = Math.min(selectedEnv, Math.max(0, envs.length - 1));
const currentEnv = envs[validSelectedEnv]; const currentEnv = envs[validSelectedEnv];
async function handleEnvChanged(env: Env) { async function handleEnvChanged(env: Env) {
// Synchronously update the env in the array // Optimistic update - update React state immediately
let idx = AppState.Instance.envs.findIndex(x => x.id === env.id); setEnvs(prevEnvs => {
if (idx > -1) { const newEnvs = [...prevEnvs];
AppState.Instance.envs[idx] = env; const idx = newEnvs.findIndex(x => x.id === env.id);
// Also update config.envs since they reference the same array if (idx > -1) {
AppState.Instance.config.envs = AppState.Instance.envs; newEnvs[idx] = env;
const newEnvs = [...AppState.Instance.envs]; }
setEnvs(newEnvs); return newEnvs;
AppState.Instance.syncEnvs(newEnvs); // Keep AppState in sync with React state });
setConfig(AppState.Instance.config); // Trigger re-render for config
} // Also update config.envs to keep it in sync
setConfig(prevConfig => {
const newConfig = new Config();
newConfig.envs = prevConfig.envs.map(e => e.id === env.id ? env : e);
newConfig.template = prevConfig.template;
return newConfig;
});
// Then do the async save (for consistency with existing behavior) // Fire off async save in background (no need to wait)
await AppState.Instance.saveEnv(env); AppState.Instance.saveEnv(env);
} }
function handleEnvSelected(idx: number) { function handleEnvSelected(idx: number) {
@@ -90,20 +67,25 @@ function App() {
} }
function handleEnvAdded(env: Env): number { function handleEnvAdded(env: Env): number {
const idx = AppState.Instance.addEnv(env); const newIdx = envs.length;
const newEnvs = [...AppState.Instance.envs]; setEnvs(prevEnvs => [...prevEnvs, env]);
setEnvs(newEnvs); setConfig(prevConfig => {
AppState.Instance.syncEnvs(newEnvs); // Keep AppState in sync with React state const newConfig = new Config();
setConfig(AppState.Instance.config); // Trigger re-render for config newConfig.envs = [...prevConfig.envs, env];
return idx; newConfig.template = prevConfig.template;
return newConfig;
});
return newIdx;
} }
function handleEnvRemoved(envId: number) { function handleEnvRemoved(envId: number) {
AppState.Instance.removeEnv(envId); setEnvs(prevEnvs => prevEnvs.filter(e => e.id !== envId));
const newEnvs = [...AppState.Instance.envs]; setConfig(prevConfig => {
setEnvs(newEnvs); const newConfig = new Config();
AppState.Instance.syncEnvs(newEnvs); // Keep AppState in sync with React state newConfig.envs = prevConfig.envs.filter(e => e.id !== envId);
setConfig(AppState.Instance.config); // Trigger re-render for config newConfig.template = prevConfig.template;
return newConfig;
});
} }
return ( return (
@@ -112,8 +94,8 @@ function App() {
<div className="row mb-2"> <div className="row mb-2">
<FileChooser onSelected={x => { <FileChooser onSelected={x => {
AppState.Instance.loadConfig(x); AppState.Instance.loadConfig(x);
setEnvs(AppState.Instance.envs); setEnvs(x.envs);
setConfig(AppState.Instance.config); setConfig(x);
}} /> }} />
</div> </div>
{envs.length > 0 ? {envs.length > 0 ?

View File

@@ -44,8 +44,12 @@ export function Environment(props: { envs: Env[], onChanged: (env: Env) => void,
const name = prompt("Enter new environment name:"); const name = prompt("Enter new environment name:");
if (!name || name.trim() === "") return; if (!name || name.trim() === "") return;
// Calculate next integer ID based on max existing ID
const maxId = props.envs.reduce((max, e) => Math.max(max, e.id ?? 0), -1);
const newId = maxId + 1;
const newEnv = new Env( const newEnv = new Env(
Math.random() * 10000, newId,
name.trim(), name.trim(),
[...currEnv.params] [...currEnv.params]
); );