editable todo summary field
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
import { makeAutoObservable, runInAction } from "mobx";
|
||||
import type { RuntimeTodo, Todo } from "../types";
|
||||
import { buildTodoTree, filterTodoTree } from "../utils/todoTree";
|
||||
import { store } from "./RootStore";
|
||||
|
||||
export class RuntimeTodoStore {
|
||||
items: RuntimeTodo[] = [];
|
||||
dirty: boolean = false;
|
||||
private saveTimer: number | undefined;
|
||||
|
||||
constructor() {
|
||||
makeAutoObservable(this);
|
||||
}
|
||||
|
||||
public setFromServer(items: Todo[]) {
|
||||
this.items = buildTodoTree(items);
|
||||
}
|
||||
|
||||
public modifyTodo(item: RuntimeTodo, mutation: Partial<Todo>) {
|
||||
runInAction(() => {
|
||||
Object.assign(item, mutation);
|
||||
|
||||
const serverItem = store.server.getItemByUid(item.uid);
|
||||
const keys = Object.keys(mutation) as (keyof Todo)[];
|
||||
item.dirty = !serverItem || keys.some((key) => item[key] !== serverItem[key]);
|
||||
|
||||
this.setDirty();
|
||||
});
|
||||
}
|
||||
|
||||
private setDirty(value: boolean = true) {
|
||||
this.dirty = value;
|
||||
|
||||
if (this.saveTimer)
|
||||
clearTimeout(this.saveTimer);
|
||||
|
||||
this.saveTimer = setTimeout(this.saveToServer.bind(this), 3000);
|
||||
}
|
||||
|
||||
public async saveToServer(): Promise<void> {
|
||||
if (this.saveTimer)
|
||||
clearTimeout(this.saveTimer);
|
||||
|
||||
const dirtyItems = Array.from(filterTodoTree(this.items, (item) => item.dirty));
|
||||
if (dirtyItems.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Snapshot what we're about to send: if a todo gets edited again
|
||||
// while its save is in flight, the response no longer reflects its
|
||||
// current state, so it must stay dirty (setDirty() already queued a
|
||||
// fresh save for it).
|
||||
const summarySnapshot = new Map(dirtyItems.map((item) => [item.uid, item.summary]));
|
||||
const savedUids = new Set(await store.server.save(dirtyItems));
|
||||
|
||||
runInAction(() => {
|
||||
for (const item of dirtyItems) {
|
||||
if (savedUids.has(item.uid) && item.summary === summarySnapshot.get(item.uid)) {
|
||||
item.dirty = false;
|
||||
}
|
||||
}
|
||||
this.dirty = Array.from(filterTodoTree(this.items, (item) => item.dirty)).length > 0;
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user