@opendaw/lib-box 0.0.63 → 0.0.65
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/editing.d.ts +4 -1
- package/dist/editing.d.ts.map +1 -1
- package/dist/editing.js +42 -13
- package/package.json +4 -4
package/dist/editing.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BoxGraph } from "./graph";
|
|
2
|
-
import { Editing, Maybe, Option, SyncProvider } from "@opendaw/lib-std";
|
|
2
|
+
import { Editing, Maybe, Observer, Option, Subscription, SyncProvider } from "@opendaw/lib-std";
|
|
3
3
|
export interface ModificationProcess {
|
|
4
4
|
approve(): void;
|
|
5
5
|
revert(): void;
|
|
@@ -8,12 +8,15 @@ export declare class BoxEditing implements Editing {
|
|
|
8
8
|
#private;
|
|
9
9
|
constructor(graph: BoxGraph);
|
|
10
10
|
get graph(): BoxGraph;
|
|
11
|
+
subscribe(observer: Observer<void>): Subscription;
|
|
11
12
|
markSaved(): void;
|
|
12
13
|
hasUnsavedChanges(): boolean;
|
|
13
14
|
isEmpty(): boolean;
|
|
14
15
|
clear(): void;
|
|
15
16
|
undo(): boolean;
|
|
16
17
|
redo(): boolean;
|
|
18
|
+
canUndo(): boolean;
|
|
19
|
+
canRedo(): boolean;
|
|
17
20
|
mustModify(): boolean;
|
|
18
21
|
modify<R>(modifier: SyncProvider<Maybe<R>>, mark?: boolean): Option<R>;
|
|
19
22
|
beginModification(): ModificationProcess;
|
package/dist/editing.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editing.d.ts","sourceRoot":"","sources":["../src/editing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,SAAS,CAAA;AAChC,OAAO,
|
|
1
|
+
{"version":3,"file":"editing.d.ts","sourceRoot":"","sources":["../src/editing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,SAAS,CAAA;AAChC,OAAO,EAGH,OAAO,EAEP,KAAK,EAEL,QAAQ,EACR,MAAM,EACN,YAAY,EACZ,YAAY,EACf,MAAM,kBAAkB,CAAA;AAqBzB,MAAM,WAAW,mBAAmB;IAChC,OAAO,IAAI,IAAI,CAAA;IACf,MAAM,IAAI,IAAI,CAAA;CACjB;AAED,qBAAa,UAAW,YAAW,OAAO;;gBAY1B,KAAK,EAAE,QAAQ;IAM3B,IAAI,KAAK,IAAI,QAAQ,CAAqB;IAE1C,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,YAAY;IAIjD,SAAS,IAAI,IAAI;IAKjB,iBAAiB,IAAI,OAAO;IAM5B,OAAO,IAAI,OAAO;IAElB,KAAK,IAAI,IAAI;IASb,IAAI,IAAI,OAAO;IAWf,IAAI,IAAI,OAAO;IASf,OAAO,IAAI,OAAO;IAKlB,OAAO,IAAI,OAAO;IAkBlB,UAAU,IAAI,OAAO;IAErB,MAAM,CAAC,CAAC,EAAE,QAAQ,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,GAAE,OAAc,GAAG,MAAM,CAAC,CAAC,CAAC;IA2B5E,iBAAiB,IAAI,mBAAmB;IAmCxC,IAAI,IAAI,IAAI;IAYZ,YAAY,IAAI,IAAI;IAOpB,OAAO,IAAI,IAAI;CAGlB"}
|
package/dist/editing.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Arrays, assert, Option } from "@opendaw/lib-std";
|
|
1
|
+
import { Arrays, assert, Notifier, Option } from "@opendaw/lib-std";
|
|
2
2
|
class Modification {
|
|
3
3
|
#updates;
|
|
4
4
|
constructor(updates) { this.#updates = updates; }
|
|
@@ -17,6 +17,7 @@ export class BoxEditing {
|
|
|
17
17
|
#graph;
|
|
18
18
|
#pending = [];
|
|
19
19
|
#marked = [];
|
|
20
|
+
#notifier;
|
|
20
21
|
#modifying = false;
|
|
21
22
|
#inProcess = false;
|
|
22
23
|
#disabled = false;
|
|
@@ -24,8 +25,12 @@ export class BoxEditing {
|
|
|
24
25
|
#savedHistoryIndex = 0; // -1 = saved state was spliced away, >= 0 = valid saved position
|
|
25
26
|
constructor(graph) {
|
|
26
27
|
this.#graph = graph;
|
|
28
|
+
this.#notifier = new Notifier();
|
|
27
29
|
}
|
|
28
30
|
get graph() { return this.#graph; }
|
|
31
|
+
subscribe(observer) {
|
|
32
|
+
return this.#notifier.subscribe(observer);
|
|
33
|
+
}
|
|
29
34
|
markSaved() {
|
|
30
35
|
if (this.#pending.length > 0) {
|
|
31
36
|
this.mark();
|
|
@@ -48,44 +53,65 @@ export class BoxEditing {
|
|
|
48
53
|
Arrays.clear(this.#marked);
|
|
49
54
|
this.#historyIndex = 0;
|
|
50
55
|
this.#savedHistoryIndex = 0;
|
|
56
|
+
this.#notifier.notify();
|
|
51
57
|
}
|
|
52
58
|
undo() {
|
|
53
|
-
if (this
|
|
59
|
+
if (!this.canUndo()) {
|
|
54
60
|
return false;
|
|
55
61
|
}
|
|
56
62
|
if (this.#pending.length > 0) {
|
|
57
63
|
this.mark();
|
|
58
64
|
}
|
|
59
|
-
|
|
60
|
-
return false;
|
|
61
|
-
}
|
|
65
|
+
console.debug("undo");
|
|
62
66
|
const modifications = this.#marked[--this.#historyIndex];
|
|
63
67
|
modifications.toReversed().forEach(step => step.inverse(this.#graph));
|
|
64
68
|
this.#graph.edges().validateRequirements();
|
|
69
|
+
this.#notifier.notify();
|
|
65
70
|
return true;
|
|
66
71
|
}
|
|
67
72
|
redo() {
|
|
73
|
+
if (!this.canRedo()) {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
console.debug("redo");
|
|
77
|
+
this.#marked[this.#historyIndex++].forEach(step => step.forward(this.#graph));
|
|
78
|
+
this.#graph.edges().validateRequirements();
|
|
79
|
+
this.#notifier.notify();
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
canUndo() {
|
|
68
83
|
if (this.#disabled) {
|
|
69
84
|
return false;
|
|
70
85
|
}
|
|
71
|
-
|
|
86
|
+
return this.#historyIndex !== 0 || this.#pending.length > 0;
|
|
87
|
+
}
|
|
88
|
+
canRedo() {
|
|
89
|
+
if (this.#disabled) {
|
|
72
90
|
return false;
|
|
73
91
|
}
|
|
74
|
-
if (this.#
|
|
75
|
-
console.warn("redo while having pending updates?");
|
|
92
|
+
if (this.#historyIndex === this.#marked.length) {
|
|
76
93
|
return false;
|
|
77
94
|
}
|
|
78
|
-
this.#
|
|
79
|
-
this.#graph.edges().validateRequirements();
|
|
80
|
-
return true;
|
|
95
|
+
return this.#pending.length <= 0;
|
|
81
96
|
}
|
|
82
|
-
// TODO This
|
|
83
|
-
//
|
|
97
|
+
// TODO This method exists to handle bidirectional sync between UI state and Box state.
|
|
98
|
+
// Problem: When a Box field changes (e.g., during undo/redo), reactive subscriptions may fire
|
|
99
|
+
// and attempt to call modify() to sync the UI state back to the Box. But since undo/redo
|
|
100
|
+
// already has a transaction open (via Modification.inverse/forward calling beginTransaction
|
|
101
|
+
// directly), calling modify() would fail with "Transaction already in progress".
|
|
102
|
+
// Current workaround: Callers check mustModify() before calling modify(). If false (transaction
|
|
103
|
+
// already open), they either skip the call or call setValue directly without recording history.
|
|
104
|
+
// See: EditWrapper.forValue, EditWrapper.forAutomatableParameter, TransportGroup loop sync.
|
|
105
|
+
// Better solution: Consider having Modification.inverse/forward use the same #modifying flag
|
|
106
|
+
// as modify(), or introduce a unified "modification context" that both undo/redo and user
|
|
107
|
+
// actions share. This would allow modify() to detect it's being called reactively during
|
|
108
|
+
// undo/redo and handle it internally, rather than requiring all callers to guard with mustModify().
|
|
84
109
|
mustModify() { return !this.#graph.inTransaction(); }
|
|
85
110
|
modify(modifier, mark = true) {
|
|
86
111
|
assert(!this.#inProcess, "Cannot call modify while a modification process is running");
|
|
87
112
|
if (this.#modifying) {
|
|
88
113
|
// Nested modify call - just execute without separate recording
|
|
114
|
+
this.#notifier.notify();
|
|
89
115
|
return Option.wrap(modifier());
|
|
90
116
|
}
|
|
91
117
|
if (mark && this.#pending.length > 0) {
|
|
@@ -108,6 +134,7 @@ export class BoxEditing {
|
|
|
108
134
|
if (mark) {
|
|
109
135
|
this.mark();
|
|
110
136
|
}
|
|
137
|
+
this.#notifier.notify();
|
|
111
138
|
return Option.wrap(result);
|
|
112
139
|
}
|
|
113
140
|
beginModification() {
|
|
@@ -130,6 +157,7 @@ export class BoxEditing {
|
|
|
130
157
|
this.#inProcess = false;
|
|
131
158
|
this.#graph.edges().validateRequirements();
|
|
132
159
|
this.mark();
|
|
160
|
+
this.#notifier.notify();
|
|
133
161
|
},
|
|
134
162
|
revert: () => {
|
|
135
163
|
this.#graph.endTransaction();
|
|
@@ -162,6 +190,7 @@ export class BoxEditing {
|
|
|
162
190
|
}
|
|
163
191
|
this.#pending.reverse().forEach(modification => modification.inverse(this.#graph));
|
|
164
192
|
this.#pending.length = 0;
|
|
193
|
+
this.#notifier.notify();
|
|
165
194
|
}
|
|
166
195
|
disable() {
|
|
167
196
|
this.#disabled = true;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opendaw/lib-box",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.65",
|
|
4
4
|
"sideEffects": false,
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -23,12 +23,12 @@
|
|
|
23
23
|
"test": "vitest run"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@opendaw/lib-runtime": "^0.0.
|
|
27
|
-
"@opendaw/lib-std": "^0.0.
|
|
26
|
+
"@opendaw/lib-runtime": "^0.0.64",
|
|
27
|
+
"@opendaw/lib-std": "^0.0.64"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@opendaw/eslint-config": "^0.0.27",
|
|
31
31
|
"@opendaw/typescript-config": "^0.0.28"
|
|
32
32
|
},
|
|
33
|
-
"gitHead": "
|
|
33
|
+
"gitHead": "043469788d823f2ae6ca0f5c9f1483c06edf8659"
|
|
34
34
|
}
|