@yuneta/gobj-ui 7.25.5 → 7.25.7
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/README.md +35 -0
- package/dist/gobj-ui.cjs.js +243 -21
- package/dist/gobj-ui.es.js +243 -21
- package/package.json +1 -1
- package/src/c_yui_schema_editor.js +274 -23
- package/src/schema_editor_transport.wiring.test.js +457 -0
- package/src/shell_modals.js +32 -4
- package/src/shell_toast_once.test.js +64 -0
|
@@ -70,6 +70,12 @@
|
|
|
70
70
|
* `update-node` / `delete-node` on the treedb service, and it may
|
|
71
71
|
* be a routing adapter two hops away (the agent console's
|
|
72
72
|
* C_AGENT_TREEDB_LINK) — this view cannot tell, and must not.
|
|
73
|
+
* A DROP of it (the host's EV_TRANSPORT_STATE, or a failure that
|
|
74
|
+
* arrives while the transport is out of session) ends the load or
|
|
75
|
+
* the write it cut, and the model is asked again when the session
|
|
76
|
+
* is back. Every request carries its round (`round` for a load,
|
|
77
|
+
* `write` for a write) in `__md_command__`, so an answer of what
|
|
78
|
+
* was cut is ignored instead of counted in the next one.
|
|
73
79
|
*
|
|
74
80
|
* Copyright (c) 2026, ArtGins.
|
|
75
81
|
* All Rights Reserved.
|
|
@@ -108,6 +114,7 @@ import {
|
|
|
108
114
|
clean_name,
|
|
109
115
|
msg_iev_get_stack,
|
|
110
116
|
kw_get_str,
|
|
117
|
+
kw_get_int,
|
|
111
118
|
kw_get_dict,
|
|
112
119
|
is_object,
|
|
113
120
|
is_array,
|
|
@@ -198,6 +205,7 @@ let PRIVATE_DATA = {
|
|
|
198
205
|
model: null, /* build_schema_model() of the above */
|
|
199
206
|
pending: 0, /* `nodes` requests still in flight */
|
|
200
207
|
load_error: "",
|
|
208
|
+
load_round: 0, /* which load an answer belongs to: echoed as `round` */
|
|
201
209
|
|
|
202
210
|
/* Where the operator is. The url carries it; these mirror it. */
|
|
203
211
|
treedb_id: "",
|
|
@@ -220,9 +228,14 @@ let PRIVATE_DATA = {
|
|
|
220
228
|
save_queue: null,
|
|
221
229
|
save_return: "",
|
|
222
230
|
save_wrote: false,
|
|
231
|
+
write_tag: 0, /* which write an answer belongs to: echoed as `write` */
|
|
223
232
|
connected: false,
|
|
233
|
+
reload_on_open: false, /* a drop cut a load or a write: ask the model again */
|
|
234
|
+
dropped_round: 0, /* the load a drop ended: its failures are the drop, said once */
|
|
235
|
+
dropped_write: 0, /* the same for the write a drop ended */
|
|
236
|
+
reload_after_write: false, /* a write given up turned out DONE while another was in flight */
|
|
224
237
|
|
|
225
|
-
/* A position that arrived while a write was in flight */
|
|
238
|
+
/* A position that arrived while a load or a write was in flight */
|
|
226
239
|
pending_seg: null,
|
|
227
240
|
|
|
228
241
|
/* The import dialog's plan and the two nodes it draws into */
|
|
@@ -458,6 +471,7 @@ function request_model(gobj)
|
|
|
458
471
|
priv.records = {treedbs: [], topics: [], cols: []};
|
|
459
472
|
priv.load_error = "";
|
|
460
473
|
priv.pending = 0;
|
|
474
|
+
priv.load_round++;
|
|
461
475
|
gobj_change_state(gobj, "ST_LOADING");
|
|
462
476
|
show_notice(gobj, "loading the schemas");
|
|
463
477
|
|
|
@@ -465,7 +479,7 @@ function request_model(gobj)
|
|
|
465
479
|
if(remote_command(gobj, "nodes", {
|
|
466
480
|
topic_name: topic_name,
|
|
467
481
|
options: {list_dict: true}
|
|
468
|
-
}) === 0) {
|
|
482
|
+
}, {round: priv.load_round}) === 0) {
|
|
469
483
|
priv.pending++;
|
|
470
484
|
}
|
|
471
485
|
}
|
|
@@ -487,7 +501,7 @@ function request_model(gobj)
|
|
|
487
501
|
* answer says which topic it is about, since the command is
|
|
488
502
|
* `nodes` for all three.
|
|
489
503
|
***************************************************************/
|
|
490
|
-
function remote_command(gobj, command, kw)
|
|
504
|
+
function remote_command(gobj, command, kw, tag)
|
|
491
505
|
{
|
|
492
506
|
let remote = gobj_read_pointer_attr(gobj, "gobj_remote_yuno");
|
|
493
507
|
let treedb_name = gobj_read_str_attr(gobj, "treedb_name");
|
|
@@ -512,11 +526,11 @@ function remote_command(gobj, command, kw)
|
|
|
512
526
|
* whichever one is under this view — and `record_id` is here and
|
|
513
527
|
* NOT at the top level because a delete answers with nothing, and a
|
|
514
528
|
* parameter the treedb does not know has no business travelling. */
|
|
515
|
-
full_kw.__md_command__ = {
|
|
529
|
+
full_kw.__md_command__ = Object.assign({
|
|
516
530
|
purpose: PURPOSE,
|
|
517
531
|
topic_name: (kw && kw.topic_name) || "",
|
|
518
532
|
record_id: (kw && kw.record_id) || ""
|
|
519
|
-
};
|
|
533
|
+
}, tag || {});
|
|
520
534
|
delete full_kw.record_id;
|
|
521
535
|
|
|
522
536
|
let ret = gobj_command(remote, command, full_kw, gobj);
|
|
@@ -2362,17 +2376,121 @@ function run_next_write(gobj)
|
|
|
2362
2376
|
let command = write_command(write.op);
|
|
2363
2377
|
let options = write_options(write.op);
|
|
2364
2378
|
|
|
2379
|
+
priv.write_tag++;
|
|
2365
2380
|
if(remote_command(gobj, command, {
|
|
2366
2381
|
topic_name: write.topic_name,
|
|
2367
2382
|
record: write.record,
|
|
2368
2383
|
options: options,
|
|
2369
2384
|
record_id: write.record.id || ""
|
|
2370
|
-
}) < 0) {
|
|
2385
|
+
}, {write: priv.write_tag}) < 0) {
|
|
2371
2386
|
return end_writes(gobj, t("cannot reach the treedb"));
|
|
2372
2387
|
}
|
|
2373
2388
|
return 0;
|
|
2374
2389
|
}
|
|
2375
2390
|
|
|
2391
|
+
/***************************************************************
|
|
2392
|
+
* Does the transport say it is in session? The state the library
|
|
2393
|
+
* reads off every transport (C_IEVENT_CLI and the routing adapters
|
|
2394
|
+
* name it the same).
|
|
2395
|
+
***************************************************************/
|
|
2396
|
+
function transport_in_session(gobj)
|
|
2397
|
+
{
|
|
2398
|
+
let remote = gobj_read_pointer_attr(gobj, "gobj_remote_yuno");
|
|
2399
|
+
|
|
2400
|
+
return !!remote && gobj_current_state(remote) === "ST_SESSION";
|
|
2401
|
+
}
|
|
2402
|
+
|
|
2403
|
+
/***************************************************************
|
|
2404
|
+
* Is this answer of the load in flight, or of the write in
|
|
2405
|
+
* flight? Each request carries its round in `__md_command__`, and
|
|
2406
|
+
* one the drop abandoned (or a deadline settled) can still come
|
|
2407
|
+
* back: counted, it ended the next load with the old data or
|
|
2408
|
+
* moved the next write's queue.
|
|
2409
|
+
*
|
|
2410
|
+
* The state is part of the question, and that is only true
|
|
2411
|
+
* because NOTHING moves the editor out of ST_LOADING or ST_SAVING
|
|
2412
|
+
* but the end of what is in flight: a position the host sends
|
|
2413
|
+
* meanwhile waits in `pending_seg` (ac_show()). 7.25.6 let EV_SHOW
|
|
2414
|
+
* move a RELOAD out of ST_LOADING, and every answer of it was then
|
|
2415
|
+
* "for a load that is over": the records it had emptied stayed
|
|
2416
|
+
* empty, and the next write patched them into a model with no
|
|
2417
|
+
* treedb at all.
|
|
2418
|
+
***************************************************************/
|
|
2419
|
+
function is_current_load(gobj, md)
|
|
2420
|
+
{
|
|
2421
|
+
return gobj_current_state(gobj) === "ST_LOADING" &&
|
|
2422
|
+
kw_get_int(gobj, md, "round", 0, 0) === gobj.priv.load_round;
|
|
2423
|
+
}
|
|
2424
|
+
|
|
2425
|
+
function is_current_write(gobj, md)
|
|
2426
|
+
{
|
|
2427
|
+
return gobj_current_state(gobj) === "ST_SAVING" &&
|
|
2428
|
+
kw_get_int(gobj, md, "write", 0, 0) === gobj.priv.write_tag;
|
|
2429
|
+
}
|
|
2430
|
+
|
|
2431
|
+
/***************************************************************
|
|
2432
|
+
* The transport dropped under a load or a write: its answers
|
|
2433
|
+
* will never come. The load goes back to the screen it replaced
|
|
2434
|
+
* (or to "not connected" when there was none), the write ends
|
|
2435
|
+
* with the drop said -- whether it landed is unknown -- and both
|
|
2436
|
+
* mark the model to be asked again when the session is back.
|
|
2437
|
+
* Bumping the round makes an answer of what was cut stale.
|
|
2438
|
+
***************************************************************/
|
|
2439
|
+
function transport_dropped(gobj)
|
|
2440
|
+
{
|
|
2441
|
+
let priv = gobj.priv;
|
|
2442
|
+
let state = gobj_current_state(gobj);
|
|
2443
|
+
|
|
2444
|
+
priv.reload_on_open = true;
|
|
2445
|
+
if(state === "ST_SAVING") {
|
|
2446
|
+
log_warning(`${gobj_short_name(gobj)}: the transport dropped during a write: ` +
|
|
2447
|
+
`the model is read again on the reconnect`);
|
|
2448
|
+
priv.dropped_write = priv.write_tag;
|
|
2449
|
+
priv.write_tag++;
|
|
2450
|
+
return end_writes(gobj, "the connection dropped during the write");
|
|
2451
|
+
}
|
|
2452
|
+
if(state === "ST_LOADING") {
|
|
2453
|
+
/* Said HERE, once: the transport settles every request the drop
|
|
2454
|
+
* cut, and those failures are this one event (see
|
|
2455
|
+
* ac_mt_command_answer()). */
|
|
2456
|
+
log_warning(`${gobj_short_name(gobj)}: the transport dropped during the load: ` +
|
|
2457
|
+
`the model is read again on the reconnect`);
|
|
2458
|
+
priv.dropped_round = priv.load_round;
|
|
2459
|
+
priv.load_round++;
|
|
2460
|
+
priv.pending = 0;
|
|
2461
|
+
priv.load_error = "";
|
|
2462
|
+
return end_load(gobj);
|
|
2463
|
+
}
|
|
2464
|
+
return 0;
|
|
2465
|
+
}
|
|
2466
|
+
|
|
2467
|
+
/***************************************************************
|
|
2468
|
+
* A load is over -- landed, failed or cut -- and the editor goes
|
|
2469
|
+
* where the operator is: the position the host sent while it was
|
|
2470
|
+
* in flight (ac_show() kept it), or the one it had. Without a
|
|
2471
|
+
* model there is no screen to go to: the position is kept for the
|
|
2472
|
+
* next load, and the editor says why it is empty.
|
|
2473
|
+
***************************************************************/
|
|
2474
|
+
function end_load(gobj)
|
|
2475
|
+
{
|
|
2476
|
+
let priv = gobj.priv;
|
|
2477
|
+
let seg = priv.pending_seg;
|
|
2478
|
+
|
|
2479
|
+
priv.pending_seg = null;
|
|
2480
|
+
if(priv.model) {
|
|
2481
|
+
if(seg !== null) {
|
|
2482
|
+
return apply_seg(gobj, seg);
|
|
2483
|
+
}
|
|
2484
|
+
return go(gobj, priv.treedb_id, priv.topic_name, priv.diagram, false);
|
|
2485
|
+
}
|
|
2486
|
+
if(seg !== null) {
|
|
2487
|
+
adopt_seg(gobj, seg);
|
|
2488
|
+
}
|
|
2489
|
+
gobj_change_state(gobj, "ST_IDLE");
|
|
2490
|
+
render(gobj);
|
|
2491
|
+
return 0;
|
|
2492
|
+
}
|
|
2493
|
+
|
|
2376
2494
|
/***************************************************************
|
|
2377
2495
|
* The queue is done, or gave up. Either way the model is what
|
|
2378
2496
|
* the answers made it, so the screen is redrawn from it and the
|
|
@@ -2402,7 +2520,7 @@ function end_writes(gobj, error)
|
|
|
2402
2520
|
});
|
|
2403
2521
|
}
|
|
2404
2522
|
priv.save_wrote = false;
|
|
2405
|
-
return
|
|
2523
|
+
return reload_if_owed(gobj);
|
|
2406
2524
|
}
|
|
2407
2525
|
}
|
|
2408
2526
|
|
|
@@ -2417,9 +2535,30 @@ function end_writes(gobj, error)
|
|
|
2417
2535
|
priv.save_wrote = false;
|
|
2418
2536
|
render(gobj);
|
|
2419
2537
|
publish_check(gobj);
|
|
2538
|
+
reload_if_owed(gobj);
|
|
2420
2539
|
return error ? -1 : 0;
|
|
2421
2540
|
}
|
|
2422
2541
|
|
|
2542
|
+
/***************************************************************
|
|
2543
|
+
* A write given up earlier turned out DONE while another one was
|
|
2544
|
+
* in flight (see ac_mt_command_answer()): the model is read again
|
|
2545
|
+
* now that nothing is.
|
|
2546
|
+
***************************************************************/
|
|
2547
|
+
function reload_if_owed(gobj)
|
|
2548
|
+
{
|
|
2549
|
+
let priv = gobj.priv;
|
|
2550
|
+
|
|
2551
|
+
if(!priv.reload_after_write) {
|
|
2552
|
+
return 0;
|
|
2553
|
+
}
|
|
2554
|
+
priv.reload_after_write = false;
|
|
2555
|
+
if(!transport_in_session(gobj)) {
|
|
2556
|
+
priv.reload_on_open = true;
|
|
2557
|
+
return 0;
|
|
2558
|
+
}
|
|
2559
|
+
return request_model(gobj);
|
|
2560
|
+
}
|
|
2561
|
+
|
|
2423
2562
|
/***************************************************************
|
|
2424
2563
|
* The record a column form produces.
|
|
2425
2564
|
*
|
|
@@ -2525,9 +2664,13 @@ function go(gobj, treedb_id, topic_name, diagram, mirror)
|
|
|
2525
2664
|
priv.topic_name = topic_name || "";
|
|
2526
2665
|
priv.diagram = !!diagram;
|
|
2527
2666
|
|
|
2667
|
+
/* No model and no load (a load in flight never gets here: ac_show()
|
|
2668
|
+
* keeps the position for it): nothing to draw, and ST_LOADING would
|
|
2669
|
+
* claim a load that nobody asked for -- the reconnect skipped the one
|
|
2670
|
+
* it owed BECAUSE the state said a load was running. */
|
|
2528
2671
|
let state = "ST_TREEDBS";
|
|
2529
2672
|
if(!priv.model) {
|
|
2530
|
-
state = "
|
|
2673
|
+
state = "ST_IDLE";
|
|
2531
2674
|
} else if(priv.model.treedbs.length === 0) {
|
|
2532
2675
|
state = "ST_EMPTY";
|
|
2533
2676
|
} else if(priv.treedb_id && priv.diagram) {
|
|
@@ -2573,18 +2716,39 @@ function position_seg(gobj)
|
|
|
2573
2716
|
* empty screen: a shared link outlives the schema it points at.
|
|
2574
2717
|
***************************************************************/
|
|
2575
2718
|
function apply_seg(gobj, seg)
|
|
2719
|
+
{
|
|
2720
|
+
let pos = seg_position(seg);
|
|
2721
|
+
|
|
2722
|
+
return go(gobj, pos.treedb_id, pos.topic_name, pos.diagram, false);
|
|
2723
|
+
}
|
|
2724
|
+
|
|
2725
|
+
function seg_position(seg)
|
|
2576
2726
|
{
|
|
2577
2727
|
let parts = String(seg || "").split("/").filter(x => x.length > 0);
|
|
2578
2728
|
let treedb_id = parts[0] || "";
|
|
2579
2729
|
let tail = parts[1] || "";
|
|
2580
2730
|
|
|
2581
2731
|
if(!treedb_id) {
|
|
2582
|
-
return
|
|
2732
|
+
return {treedb_id: "", topic_name: "", diagram: false};
|
|
2583
2733
|
}
|
|
2584
2734
|
if(tail === DIAGRAM_SEG) {
|
|
2585
|
-
return
|
|
2735
|
+
return {treedb_id: treedb_id, topic_name: "", diagram: true};
|
|
2586
2736
|
}
|
|
2587
|
-
return
|
|
2737
|
+
return {treedb_id: treedb_id, topic_name: tail, diagram: false};
|
|
2738
|
+
}
|
|
2739
|
+
|
|
2740
|
+
/***************************************************************
|
|
2741
|
+
* Where the operator is, taken WITHOUT a screen: there is no model
|
|
2742
|
+
* to draw it on yet, and the load that brings one goes there.
|
|
2743
|
+
***************************************************************/
|
|
2744
|
+
function adopt_seg(gobj, seg)
|
|
2745
|
+
{
|
|
2746
|
+
let priv = gobj.priv;
|
|
2747
|
+
let pos = seg_position(seg);
|
|
2748
|
+
|
|
2749
|
+
priv.treedb_id = pos.treedb_id;
|
|
2750
|
+
priv.topic_name = pos.topic_name;
|
|
2751
|
+
priv.diagram = pos.diagram;
|
|
2588
2752
|
}
|
|
2589
2753
|
|
|
2590
2754
|
|
|
@@ -2627,8 +2791,31 @@ function ac_mt_command_answer(gobj, event, kw, src)
|
|
|
2627
2791
|
return 0; /* another panel's answer on a shared transport */
|
|
2628
2792
|
}
|
|
2629
2793
|
|
|
2794
|
+
/* A failure while the transport is not in session is the DROP, not a
|
|
2795
|
+
* refusal: a routing adapter settles what it had in flight when its
|
|
2796
|
+
* session closes, and that can arrive before the host's
|
|
2797
|
+
* EV_TRANSPORT_STATE. Read as a refusal, the write it ended looked
|
|
2798
|
+
* refused, and the reconnect did not reload a model it may have
|
|
2799
|
+
* changed. */
|
|
2800
|
+
if(result < 0 && !transport_in_session(gobj) &&
|
|
2801
|
+
(gobj_current_state(gobj) === "ST_LOADING" ||
|
|
2802
|
+
gobj_current_state(gobj) === "ST_SAVING")) {
|
|
2803
|
+
if((command === "nodes" && is_current_load(gobj, md)) ||
|
|
2804
|
+
(command !== "nodes" && is_current_write(gobj, md))) {
|
|
2805
|
+
return transport_dropped(gobj);
|
|
2806
|
+
}
|
|
2807
|
+
}
|
|
2808
|
+
|
|
2630
2809
|
if(command === "nodes") {
|
|
2631
2810
|
let topic_name = kw_get_str(gobj, md, "topic_name", "", 0);
|
|
2811
|
+
if(!is_current_load(gobj, md)) {
|
|
2812
|
+
if(result < 0 && kw_get_int(gobj, md, "round", 0, 0) === priv.dropped_round) {
|
|
2813
|
+
return 0; /* the drop that ended this load failed it: said once, in transport_dropped() */
|
|
2814
|
+
}
|
|
2815
|
+
log_warning(`${gobj_short_name(gobj)}: 'nodes' of '${topic_name}' answered ` +
|
|
2816
|
+
`for a load that is over: ignored`);
|
|
2817
|
+
return 0;
|
|
2818
|
+
}
|
|
2632
2819
|
priv.pending--;
|
|
2633
2820
|
if(result < 0) {
|
|
2634
2821
|
priv.load_error = comment || t("cannot load the schemas");
|
|
@@ -2640,9 +2827,7 @@ function ac_mt_command_answer(gobj, event, kw, src)
|
|
|
2640
2827
|
}
|
|
2641
2828
|
if(priv.load_error) {
|
|
2642
2829
|
priv.model = null;
|
|
2643
|
-
|
|
2644
|
-
render(gobj);
|
|
2645
|
-
return 0;
|
|
2830
|
+
return end_load(gobj);
|
|
2646
2831
|
}
|
|
2647
2832
|
/* Records straight from the store: what an undo would name is the
|
|
2648
2833
|
* order that was ON SCREEN, and this is the stored one arriving.
|
|
@@ -2655,13 +2840,25 @@ function ac_mt_command_answer(gobj, event, kw, src)
|
|
|
2655
2840
|
* against. Taken on the write patches instead, it measured every
|
|
2656
2841
|
* version against itself. */
|
|
2657
2842
|
start_measuring(gobj);
|
|
2658
|
-
/* Back to where the operator was
|
|
2659
|
-
* the answer to a deep link that
|
|
2660
|
-
|
|
2843
|
+
/* Back to where the operator was, or went while it loaded: the
|
|
2844
|
+
* load may be a refresh, or the answer to a deep link that
|
|
2845
|
+
* arrived before the model. */
|
|
2846
|
+
return end_load(gobj);
|
|
2661
2847
|
}
|
|
2662
2848
|
|
|
2663
2849
|
if(command === "update-node" || command === "delete-node") {
|
|
2664
2850
|
let topic_name = kw_get_str(gobj, md, "topic_name", "", 0);
|
|
2851
|
+
if(!is_current_write(gobj, md)) {
|
|
2852
|
+
if(result < 0 && kw_get_int(gobj, md, "write", 0, 0) === priv.dropped_write) {
|
|
2853
|
+
return 0; /* the drop that ended this write failed it: said once, in transport_dropped() */
|
|
2854
|
+
}
|
|
2855
|
+
if(result < 0) {
|
|
2856
|
+
log_warning(`${gobj_short_name(gobj)}: '${command}' of '${topic_name}' answered ` +
|
|
2857
|
+
`for a write that is over (result ${result}): ignored`);
|
|
2858
|
+
return 0;
|
|
2859
|
+
}
|
|
2860
|
+
return late_write_done(gobj, command, topic_name);
|
|
2861
|
+
}
|
|
2665
2862
|
if(result < 0) {
|
|
2666
2863
|
return end_writes(gobj, comment || t("the treedb refused the write"));
|
|
2667
2864
|
}
|
|
@@ -2697,6 +2894,41 @@ function ac_mt_command_answer(gobj, event, kw, src)
|
|
|
2697
2894
|
return 0;
|
|
2698
2895
|
}
|
|
2699
2896
|
|
|
2897
|
+
/***************************************************************
|
|
2898
|
+
* A write this view gave up on (a drop, a deadline) answers that
|
|
2899
|
+
* it was DONE: the store holds a change the model does not show.
|
|
2900
|
+
* The model is read again -- now, or when what is in flight ends,
|
|
2901
|
+
* or on the reconnect. A load in flight needs nothing: it was
|
|
2902
|
+
* asked after the write, on the same transport, and reads it.
|
|
2903
|
+
*
|
|
2904
|
+
* Only when the answer reaches this view. A routing adapter that
|
|
2905
|
+
* settled the write on its own deadline (gui_agent's
|
|
2906
|
+
* C_AGENT_TREEDB_LINK) does not deliver its late answer again --
|
|
2907
|
+
* the view was answered once, as failed -- and echoes the node
|
|
2908
|
+
* event instead, which this view does not hear: there, Refresh is
|
|
2909
|
+
* what reads the store.
|
|
2910
|
+
***************************************************************/
|
|
2911
|
+
function late_write_done(gobj, command, topic_name)
|
|
2912
|
+
{
|
|
2913
|
+
let priv = gobj.priv;
|
|
2914
|
+
let state = gobj_current_state(gobj);
|
|
2915
|
+
|
|
2916
|
+
log_warning(`${gobj_short_name(gobj)}: '${command}' of '${topic_name}' was given up, ` +
|
|
2917
|
+
`and it was DONE: the model is read again`);
|
|
2918
|
+
if(state === "ST_LOADING") {
|
|
2919
|
+
return 0;
|
|
2920
|
+
}
|
|
2921
|
+
if(state === "ST_SAVING") {
|
|
2922
|
+
priv.reload_after_write = true;
|
|
2923
|
+
return 0;
|
|
2924
|
+
}
|
|
2925
|
+
if(!transport_in_session(gobj)) {
|
|
2926
|
+
priv.reload_on_open = true;
|
|
2927
|
+
return 0;
|
|
2928
|
+
}
|
|
2929
|
+
return request_model(gobj);
|
|
2930
|
+
}
|
|
2931
|
+
|
|
2700
2932
|
/***************************************************************
|
|
2701
2933
|
* Remember which topic this write belongs to, which is what
|
|
2702
2934
|
* "its version still has to move" is asked about.
|
|
@@ -2723,10 +2955,14 @@ function ac_show(gobj, event, kw, src)
|
|
|
2723
2955
|
{
|
|
2724
2956
|
let priv = gobj.priv;
|
|
2725
2957
|
let seg = (kw && kw.subpath) || "";
|
|
2958
|
+
let state = gobj_current_state(gobj);
|
|
2726
2959
|
|
|
2727
|
-
|
|
2960
|
+
/* Nothing but the end of what is in flight moves the editor out of
|
|
2961
|
+
* these two (see is_current_load()): the position waits, and the
|
|
2962
|
+
* last one sent wins. */
|
|
2963
|
+
if(state === "ST_SAVING" || state === "ST_LOADING") {
|
|
2728
2964
|
priv.pending_seg = seg;
|
|
2729
|
-
return 0; /* applied when the write lands (end_writes) */
|
|
2965
|
+
return 0; /* applied when the write lands (end_writes) or the load (end_load) */
|
|
2730
2966
|
}
|
|
2731
2967
|
return apply_seg(gobj, seg);
|
|
2732
2968
|
}
|
|
@@ -2743,16 +2979,31 @@ function ac_hide(gobj, event, kw, src)
|
|
|
2743
2979
|
}
|
|
2744
2980
|
|
|
2745
2981
|
/***************************************************************
|
|
2746
|
-
* The session came up or went down. The model stays
|
|
2747
|
-
*
|
|
2748
|
-
*
|
|
2982
|
+
* The session came up or went down. The model stays -- a schema
|
|
2983
|
+
* does not change under you -- unless the drop cut a load or a
|
|
2984
|
+
* write (transport_dropped()): then it is asked again on the way
|
|
2985
|
+
* back, as it is when a first load had no transport to run on.
|
|
2986
|
+
*
|
|
2987
|
+
* Nothing else ends a load or a write the drop cut: their answers
|
|
2988
|
+
* will never come, and waiting in ST_LOADING skipped the reload
|
|
2989
|
+
* itself (M-1 of the independent review of 7.25.4).
|
|
2749
2990
|
***************************************************************/
|
|
2750
2991
|
function ac_transport_state(gobj, event, kw, src)
|
|
2751
2992
|
{
|
|
2752
2993
|
let priv = gobj.priv;
|
|
2994
|
+
let state = gobj_current_state(gobj);
|
|
2753
2995
|
|
|
2754
2996
|
priv.connected = !!(kw && kw.connected);
|
|
2755
|
-
if(priv.connected
|
|
2997
|
+
if(!priv.connected) {
|
|
2998
|
+
if(state === "ST_LOADING" || state === "ST_SAVING") {
|
|
2999
|
+
return transport_dropped(gobj);
|
|
3000
|
+
}
|
|
3001
|
+
render_toolbar(gobj);
|
|
3002
|
+
return 0;
|
|
3003
|
+
}
|
|
3004
|
+
if((!priv.model || priv.reload_on_open) &&
|
|
3005
|
+
state !== "ST_LOADING" && state !== "ST_SAVING") {
|
|
3006
|
+
priv.reload_on_open = false;
|
|
2756
3007
|
return request_model(gobj);
|
|
2757
3008
|
}
|
|
2758
3009
|
render_toolbar(gobj);
|