fix: env ID generation and React state synchronization
This commit is contained in:
102
src/App.tsx
102
src/App.tsx
@@ -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 ?
|
||||||
|
|||||||
6
src/componets/env/Environment.tsx
vendored
6
src/componets/env/Environment.tsx
vendored
@@ -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]
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user