@hydranium/glsp-client-theia 1.0.0-next.202 → 1.0.0-next.204
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 +9 -2
- package/lib/browser/diagram-widget.d.ts +11 -0
- package/lib/browser/diagram-widget.d.ts.map +1 -1
- package/lib/browser/diagram-widget.js +24 -0
- package/lib/browser/diagram-widget.js.map +1 -1
- package/lib/browser/glsp-diagram-manager.d.ts +19 -2
- package/lib/browser/glsp-diagram-manager.d.ts.map +1 -1
- package/lib/browser/glsp-diagram-manager.js +28 -1
- package/lib/browser/glsp-diagram-manager.js.map +1 -1
- package/lib/browser/glsp-theia-frontend-module.d.ts.map +1 -1
- package/lib/browser/glsp-theia-frontend-module.js +2 -0
- package/lib/browser/glsp-theia-frontend-module.js.map +1 -1
- package/lib/browser/index.d.ts +1 -0
- package/lib/browser/index.d.ts.map +1 -1
- package/lib/browser/index.js +1 -0
- package/lib/browser/index.js.map +1 -1
- package/lib/browser/window-session.d.ts +57 -0
- package/lib/browser/window-session.d.ts.map +1 -0
- package/lib/browser/window-session.js +102 -0
- package/lib/browser/window-session.js.map +1 -0
- package/package.json +7 -7
- package/src/browser/diagram-widget.ts +23 -2
- package/src/browser/glsp-diagram-manager.ts +30 -4
- package/src/browser/glsp-theia-frontend-module.ts +2 -0
- package/src/browser/index.ts +1 -0
- package/src/browser/window-session.ts +114 -0
package/README.md
CHANGED
|
@@ -48,11 +48,18 @@ if you are mounting a hydranium GLSP diagram in a Theia application.
|
|
|
48
48
|
LSP already publishes the same diagnostics, and the per-diagram container binds
|
|
49
49
|
`NoOpExternalMarkerManager` instead: markers still decorate the diagram, but
|
|
50
50
|
Theia's Problems view stops double-listing them.
|
|
51
|
-
|
|
51
|
+
- **`AbstractHydraniumGlspDiagramManager`** derives the language-correlated
|
|
52
52
|
getters from one descriptor plus a label, and `reopen` replaces a diagram
|
|
53
53
|
with a fresh widget in the same tab position, as the Retry of a failed load
|
|
54
54
|
does. It reopens every diagram when their client is lost, and a failed one
|
|
55
|
-
when a client starts.
|
|
55
|
+
when a client starts. A diagram's client id is the same for the same widget
|
|
56
|
+
in the same window, so a diagram reopened after its client is lost, or
|
|
57
|
+
reloaded with its page, takes its old session over with the window's resume
|
|
58
|
+
token and keeps its unsaved text.
|
|
59
|
+
- **`WindowSessionService`** — the window's id and resume token, claimed as
|
|
60
|
+
the frontend starts. The default keeps them in `sessionStorage` and hands
|
|
61
|
+
them on only as the page leaves, so a reload resumes and a duplicated tab
|
|
62
|
+
draws its own. Rebind it for a different notion of a window.
|
|
56
63
|
- **`HydraniumGlspClientContribution`** — for a server that starts late: it
|
|
57
64
|
defers `start` until a workspace is open, fails a start that takes longer than
|
|
58
65
|
`startupTimeoutMs` (30 s by default), and starts a fresh client after a failed
|
|
@@ -6,11 +6,13 @@
|
|
|
6
6
|
*
|
|
7
7
|
* SPDX-License-Identifier: MIT
|
|
8
8
|
********************************************************************************/
|
|
9
|
+
import { type Args } from '@eclipse-glsp/client';
|
|
9
10
|
import { GLSPDiagramWidget, type GLSPDiagramWidgetOptions } from '@eclipse-glsp/theia-integration';
|
|
10
11
|
import { type Message } from '@theia/core/lib/browser';
|
|
11
12
|
import { Emitter, type Event } from '@theia/core';
|
|
12
13
|
import { type Container } from '@theia/core/shared/inversify';
|
|
13
14
|
import { type DiagramLoadOutcome, HydraniumDiagramLoader } from './diagram-loader';
|
|
15
|
+
import { WindowSessionService } from './window-session';
|
|
14
16
|
import '../../style/diagram-loading.css';
|
|
15
17
|
/** Class on the overlay root. Adopters style / override via this contract. */
|
|
16
18
|
export declare const DIAGRAM_LOADING_CLASS = "hydranium-diagram-loading";
|
|
@@ -42,6 +44,7 @@ export declare const DIAGRAM_LOADING_FAILED_CLASS = "hydranium-diagram-loading-f
|
|
|
42
44
|
* dirty, so Theia's exit check still counts it; see {@link createSaveable}.
|
|
43
45
|
*/
|
|
44
46
|
export declare class HydraniumGlspDiagramWidget extends GLSPDiagramWidget {
|
|
47
|
+
protected readonly windowSessions: WindowSessionService;
|
|
45
48
|
protected loadingOverlay?: HTMLElement;
|
|
46
49
|
protected readonly reopenRequestEmitter: Emitter<void>;
|
|
47
50
|
/** Fires when this diagram asks to be replaced by a fresh widget, as its
|
|
@@ -57,8 +60,16 @@ export declare class HydraniumGlspDiagramWidget extends GLSPDiagramWidget {
|
|
|
57
60
|
configure(options: GLSPDiagramWidgetOptions, diContainer: Container): void;
|
|
58
61
|
/** The widget's saveable. Override to change how saves and dirty state behave. */
|
|
59
62
|
protected createSaveable(): GLSPDiagramWidget['saveable'];
|
|
63
|
+
/** Adds the window's resume token, so a reload or reconnect takes this diagram's session over. */
|
|
64
|
+
protected getRequestModelOptions(): Args;
|
|
60
65
|
protected onAfterAttach(msg: Message): void;
|
|
61
66
|
dispose(): void;
|
|
67
|
+
/**
|
|
68
|
+
* GLSP's restore with `animate: false`; compare the two on a GLSP upgrade.
|
|
69
|
+
* An animated restore holds back every later command, so a Delete right
|
|
70
|
+
* after a select-all typed as the diagram opens finds nothing selected.
|
|
71
|
+
*/
|
|
72
|
+
protected setViewportData(viewportData: Parameters<GLSPDiagramWidget['setViewportData']>[0]): Promise<void>;
|
|
62
73
|
/**
|
|
63
74
|
* Cover the canvas until the load settles.
|
|
64
75
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diagram-widget.d.ts","sourceRoot":"","sources":["../../src/browser/diagram-widget.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;
|
|
1
|
+
{"version":3,"file":"diagram-widget.d.ts","sourceRoot":"","sources":["../../src/browser/diagram-widget.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EAAE,KAAK,IAAI,EAAgF,MAAM,sBAAsB,CAAC;AAE/H,OAAO,EAAE,iBAAiB,EAAE,KAAK,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAGnG,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,KAAK,KAAK,EAAO,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,KAAK,SAAS,EAAsB,MAAM,8BAA8B,CAAC;AAClF,OAAO,EAAE,KAAK,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAEnF,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAIxD,OAAO,iCAAiC,CAAC;AAEzC,8EAA8E;AAC9E,eAAO,MAAM,qBAAqB,8BAA8B,CAAC;AAEjE;kFACkF;AAClF,eAAO,MAAM,4BAA4B,qCAAoC,CAAC;AAE9E;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBACa,0BAA2B,SAAQ,iBAAiB;IAChC,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAG,oBAAoB,CAAC;IACvF,SAAS,CAAC,cAAc,CAAC,EAAE,WAAW,CAAC;IACvC,SAAS,CAAC,QAAQ,CAAC,oBAAoB,gBAAuB;IAE9D;;;yBAGqB;IACrB,QAAQ,CAAC,kBAAkB,EAAE,KAAK,CAAC,IAAI,CAAC,CAAmC;IAE3E;;;;OAIG;IACM,SAAS,CAAC,OAAO,EAAE,wBAAwB,EAAE,WAAW,EAAE,SAAS,GAAG,IAAI,CAMlF;IAED,kFAAkF;IAClF,SAAS,CAAC,cAAc,IAAI,iBAAiB,CAAC,UAAU,CAAC,CAExD;IAED,kGAAkG;IAClG,UAAmB,sBAAsB,IAAI,IAAI,CAEhD;IAED,UAAmB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAKnD;IAEQ,OAAO,IAAI,IAAI,CAGvB;IAED;;;;OAIG;IACH,UAAyB,eAAe,CAAC,YAAY,EAAE,UAAU,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAMzH;IAED;;;;;;;OAOG;IACH,SAAS,CAAC,kBAAkB,IAAI,IAAI,CAiBnC;IAED,iEAAiE;IACjE,SAAS,CAAC,aAAa,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI,CAMzD;IAED;;;;;;;;;OASG;IACH,SAAS,CAAC,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAY9C;IAED,mDAAmD;IACnD,SAAS,CAAC,SAAS,IAAI,IAAI,CAI1B;IAED,+EAA+E;IAC/E,SAAS,CAAC,iBAAiB,IAAI,WAAW,CAMzC;IAED,SAAS,CAAC,kBAAkB,IAAI,IAAI,CAGnC;IAED;;oFAEgF;IAChF,SAAS,CAAC,oBAAoB,IAAI,WAAW,CAW5C;IAED;sEACkE;IAClE,SAAS,KAAK,YAAY,IAAI,MAAM,CAEnC;IAED;;;;;OAKG;IACH,SAAS,KAAK,sBAAsB,IAAI,sBAAsB,GAAG,SAAS,CAGzE;CACH"}
|
|
@@ -13,14 +13,19 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
13
13
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
14
14
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
15
15
|
};
|
|
16
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
17
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
18
|
+
};
|
|
16
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
20
|
exports.HydraniumGlspDiagramWidget = exports.DIAGRAM_LOADING_FAILED_CLASS = exports.DIAGRAM_LOADING_CLASS = void 0;
|
|
18
21
|
const client_1 = require("@eclipse-glsp/client");
|
|
22
|
+
const protocol_1 = require("@hydranium/protocol");
|
|
19
23
|
const theia_integration_1 = require("@eclipse-glsp/theia-integration");
|
|
20
24
|
const core_1 = require("@theia/core");
|
|
21
25
|
const inversify_1 = require("@theia/core/shared/inversify");
|
|
22
26
|
const diagram_loader_1 = require("./diagram-loader");
|
|
23
27
|
const glsp_saveable_1 = require("./glsp-saveable");
|
|
28
|
+
const window_session_1 = require("./window-session");
|
|
24
29
|
// Shipped by this package rather than left to adopters: an overlay whose
|
|
25
30
|
// stylesheet was forgotten is an unstyled div in normal flow, which is a silent
|
|
26
31
|
// failure. Adopters override individual rules from their own stylesheet.
|
|
@@ -55,6 +60,7 @@ exports.DIAGRAM_LOADING_FAILED_CLASS = `${exports.DIAGRAM_LOADING_CLASS}-failed`
|
|
|
55
60
|
* dirty, so Theia's exit check still counts it; see {@link createSaveable}.
|
|
56
61
|
*/
|
|
57
62
|
let HydraniumGlspDiagramWidget = class HydraniumGlspDiagramWidget extends theia_integration_1.GLSPDiagramWidget {
|
|
63
|
+
windowSessions;
|
|
58
64
|
loadingOverlay;
|
|
59
65
|
reopenRequestEmitter = new core_1.Emitter();
|
|
60
66
|
/** Fires when this diagram asks to be replaced by a fresh widget, as its
|
|
@@ -78,6 +84,10 @@ let HydraniumGlspDiagramWidget = class HydraniumGlspDiagramWidget extends theia_
|
|
|
78
84
|
createSaveable() {
|
|
79
85
|
return new glsp_saveable_1.HydraniumGlspSaveable(this.actionDispatcher, this.diContainer.get(client_1.EditorContextService));
|
|
80
86
|
}
|
|
87
|
+
/** Adds the window's resume token, so a reload or reconnect takes this diagram's session over. */
|
|
88
|
+
getRequestModelOptions() {
|
|
89
|
+
return { ...super.getRequestModelOptions(), [protocol_1.RESUME_TOKEN_ARG]: this.windowSessions.current().resumeToken };
|
|
90
|
+
}
|
|
81
91
|
onAfterAttach(msg) {
|
|
82
92
|
// Before `super`, which is what starts the load on first attach — so the
|
|
83
93
|
// overlay is already up when the round trip begins.
|
|
@@ -88,6 +98,16 @@ let HydraniumGlspDiagramWidget = class HydraniumGlspDiagramWidget extends theia_
|
|
|
88
98
|
this.hideLoadingOverlay();
|
|
89
99
|
super.dispose();
|
|
90
100
|
}
|
|
101
|
+
/**
|
|
102
|
+
* GLSP's restore with `animate: false`; compare the two on a GLSP upgrade.
|
|
103
|
+
* An animated restore holds back every later command, so a Delete right
|
|
104
|
+
* after a select-all typed as the diagram opens finds nothing selected.
|
|
105
|
+
*/
|
|
106
|
+
async setViewportData(viewportData) {
|
|
107
|
+
if (this.actionDispatcher instanceof client_1.GLSPActionDispatcher) {
|
|
108
|
+
this.actionDispatcher.dispatchOnceModelInitialized(client_1.SetViewportAction.create(viewportData.elementId, viewportData.viewportData, { animate: false }));
|
|
109
|
+
}
|
|
110
|
+
}
|
|
91
111
|
/**
|
|
92
112
|
* Cover the canvas until the load settles.
|
|
93
113
|
*
|
|
@@ -192,6 +212,10 @@ let HydraniumGlspDiagramWidget = class HydraniumGlspDiagramWidget extends theia_
|
|
|
192
212
|
}
|
|
193
213
|
};
|
|
194
214
|
exports.HydraniumGlspDiagramWidget = HydraniumGlspDiagramWidget;
|
|
215
|
+
__decorate([
|
|
216
|
+
(0, inversify_1.inject)(window_session_1.WindowSessionService),
|
|
217
|
+
__metadata("design:type", Object)
|
|
218
|
+
], HydraniumGlspDiagramWidget.prototype, "windowSessions", void 0);
|
|
195
219
|
exports.HydraniumGlspDiagramWidget = HydraniumGlspDiagramWidget = __decorate([
|
|
196
220
|
(0, inversify_1.injectable)()
|
|
197
221
|
], HydraniumGlspDiagramWidget);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diagram-widget.js","sourceRoot":"","sources":["../../src/browser/diagram-widget.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF
|
|
1
|
+
{"version":3,"file":"diagram-widget.js","sourceRoot":"","sources":["../../src/browser/diagram-widget.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,11 +6,13 @@
|
|
|
6
6
|
*
|
|
7
7
|
* SPDX-License-Identifier: MIT
|
|
8
8
|
********************************************************************************/
|
|
9
|
+
import { type IDiagramOptions } from '@eclipse-glsp/client';
|
|
9
10
|
import { GLSPDiagramManager } from '@eclipse-glsp/theia-integration';
|
|
10
11
|
import { type GLSPDiagramLanguage } from '@eclipse-glsp/theia-integration/lib/common';
|
|
11
|
-
import { type GLSPDiagramWidget } from '@eclipse-glsp/theia-integration/lib/browser';
|
|
12
|
+
import { type GLSPDiagramWidget, type GLSPDiagramWidgetOptions } from '@eclipse-glsp/theia-integration/lib/browser';
|
|
12
13
|
import { type WidgetOpenerOptions } from '@theia/core/lib/browser';
|
|
13
14
|
import { type Disposable } from '@theia/core';
|
|
15
|
+
import { WindowSessionService } from './window-session';
|
|
14
16
|
/**
|
|
15
17
|
* `GLSPDiagramManager` subclass that derives the language-correlated getters
|
|
16
18
|
* (`fileExtensions`, `diagramType`, `contributionId`, `iconClass`) from a
|
|
@@ -40,6 +42,7 @@ export declare abstract class AbstractHydraniumGlspDiagramManager extends GLSPDi
|
|
|
40
42
|
protected abstract readonly managerLabel: string;
|
|
41
43
|
/** Optional icon-class override; takes precedence over the language's `iconClass`. */
|
|
42
44
|
protected readonly customIconClass?: string;
|
|
45
|
+
protected readonly windowSessions: WindowSessionService;
|
|
43
46
|
protected clientListeners?: Disposable;
|
|
44
47
|
/** The reopens asked for so far, which run one at a time. */
|
|
45
48
|
protected reopening: Promise<void>;
|
|
@@ -49,6 +52,19 @@ export declare abstract class AbstractHydraniumGlspDiagramManager extends GLSPDi
|
|
|
49
52
|
get iconClass(): string;
|
|
50
53
|
get label(): string;
|
|
51
54
|
createWidget(options?: unknown): Promise<GLSPDiagramWidget>;
|
|
55
|
+
/**
|
|
56
|
+
* The same client id for the same diagram in this window, across a reload
|
|
57
|
+
* and a reopen after a lost client, so its load takes over the session the
|
|
58
|
+
* old connection left and keeps its unsaved text. A diagram closed by the
|
|
59
|
+
* user ends its session, and opening it again starts afresh.
|
|
60
|
+
*
|
|
61
|
+
* The widget options enter as a hash: GLSP makes the id an element id and
|
|
62
|
+
* finds it with an `#id` selector, which a URI's `:` and `/` break. The
|
|
63
|
+
* options identify the widget, so two widgets of one document, in two edit
|
|
64
|
+
* modes or set apart by an option an adopter adds, do not take each other's
|
|
65
|
+
* session over.
|
|
66
|
+
*/
|
|
67
|
+
protected createDiagramOptions(options: GLSPDiagramWidgetOptions): IDiagramOptions;
|
|
52
68
|
/**
|
|
53
69
|
* Reopen every diagram once its client is lost, since none of them has a
|
|
54
70
|
* server behind it any more, and a failed one once a client starts.
|
|
@@ -58,7 +74,8 @@ export declare abstract class AbstractHydraniumGlspDiagramManager extends GLSPDi
|
|
|
58
74
|
protected loadFailed(widget: GLSPDiagramWidget): boolean;
|
|
59
75
|
/**
|
|
60
76
|
* Replace `widget` with a fresh one for the same diagram, in the same tab
|
|
61
|
-
* position and with its viewport: a new container
|
|
77
|
+
* position and with its viewport: a new container and load under the same
|
|
78
|
+
* client id, which takes over the session the old connection left.
|
|
62
79
|
* Reopens run one at a time, since each places its replacement next to a
|
|
63
80
|
* neighbour that a reopen running alongside could take out of the layout.
|
|
64
81
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"glsp-diagram-manager.d.ts","sourceRoot":"","sources":["../../src/browser/glsp-diagram-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;
|
|
1
|
+
{"version":3,"file":"glsp-diagram-manager.d.ts","sourceRoot":"","sources":["../../src/browser/glsp-diagram-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EAAmC,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC7F,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,4CAA4C,CAAC;AACtF,OAAO,EACJ,KAAK,iBAAiB,EACtB,KAAK,wBAAwB,EAE/B,MAAM,6CAA6C,CAAC;AACrD,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,KAAK,UAAU,EAAwB,MAAM,aAAa,CAAC;AAMpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAExD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,8BACsB,mCAAoC,SAAQ,kBAAkB;IACjF,8EAA8E;IAC9E,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,eAAe,EAAE,mBAAmB,CAAC;IAEjE,wEAAwE;IACxE,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAEjD,sFAAsF;IACtF,SAAS,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAEd,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAG,oBAAoB,CAAC;IAEvF,SAAS,CAAC,eAAe,CAAC,EAAE,UAAU,CAAC;IACvC,6DAA6D;IAC7D,SAAS,CAAC,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,CAAqB;IAEvD,IAAa,cAAc,IAAI,MAAM,EAAE,CAEtC;IAED,IAAa,WAAW,IAAI,MAAM,CAEjC;IAED,IAAa,cAAc,IAAI,MAAM,CAEpC;IAED,IAAa,SAAS,IAAI,MAAM,CAE/B;IAED,IAAI,KAAK,IAAI,MAAM,CAElB;IAEc,YAAY,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAOzE;IAED;;;;;;;;;;;OAWG;IACH,UAAmB,oBAAoB,CAAC,OAAO,EAAE,wBAAwB,GAAG,eAAe,CAG1F;IAED;;;OAGG;IACH,SAAS,CAAC,cAAc,IAAI,IAAI,CAY/B;IAED,SAAS,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,iBAAiB,KAAK,OAAO,GAAG,IAAI,CAIvE;IAED,SAAS,CAAC,UAAU,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAGvD;IAED;;;;;;OAMG;IACH,MAAM,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAI/C;IAED;+DAC2D;IAC3D,UAAgB,aAAa,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAqBtE;IAED;;;;;;;;;;;;;;;;;;OAkBG;IACH,UAAmB,iBAAiB,CAAC,MAAM,EAAE,iBAAiB,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAMtG;CACH"}
|
|
@@ -13,15 +13,20 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
13
13
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
14
14
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
15
15
|
};
|
|
16
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
17
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
18
|
+
};
|
|
16
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
20
|
exports.AbstractHydraniumGlspDiagramManager = void 0;
|
|
18
21
|
const client_1 = require("@eclipse-glsp/client");
|
|
19
22
|
const theia_integration_1 = require("@eclipse-glsp/theia-integration");
|
|
20
23
|
const core_1 = require("@theia/core");
|
|
21
24
|
const inversify_1 = require("@theia/core/shared/inversify");
|
|
25
|
+
const protocol_1 = require("@hydranium/protocol");
|
|
22
26
|
const client_contribution_1 = require("./client-contribution");
|
|
23
27
|
const diagram_loader_1 = require("./diagram-loader");
|
|
24
28
|
const diagram_widget_1 = require("./diagram-widget");
|
|
29
|
+
const window_session_1 = require("./window-session");
|
|
25
30
|
/**
|
|
26
31
|
* `GLSPDiagramManager` subclass that derives the language-correlated getters
|
|
27
32
|
* (`fileExtensions`, `diagramType`, `contributionId`, `iconClass`) from a
|
|
@@ -47,6 +52,7 @@ const diagram_widget_1 = require("./diagram-widget");
|
|
|
47
52
|
let AbstractHydraniumGlspDiagramManager = class AbstractHydraniumGlspDiagramManager extends theia_integration_1.GLSPDiagramManager {
|
|
48
53
|
/** Optional icon-class override; takes precedence over the language's `iconClass`. */
|
|
49
54
|
customIconClass;
|
|
55
|
+
windowSessions;
|
|
50
56
|
clientListeners;
|
|
51
57
|
/** The reopens asked for so far, which run one at a time. */
|
|
52
58
|
reopening = Promise.resolve();
|
|
@@ -73,6 +79,22 @@ let AbstractHydraniumGlspDiagramManager = class AbstractHydraniumGlspDiagramMana
|
|
|
73
79
|
}
|
|
74
80
|
return widget;
|
|
75
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* The same client id for the same diagram in this window, across a reload
|
|
84
|
+
* and a reopen after a lost client, so its load takes over the session the
|
|
85
|
+
* old connection left and keeps its unsaved text. A diagram closed by the
|
|
86
|
+
* user ends its session, and opening it again starts afresh.
|
|
87
|
+
*
|
|
88
|
+
* The widget options enter as a hash: GLSP makes the id an element id and
|
|
89
|
+
* finds it with an `#id` selector, which a URI's `:` and `/` break. The
|
|
90
|
+
* options identify the widget, so two widgets of one document, in two edit
|
|
91
|
+
* modes or set apart by an option an adopter adds, do not take each other's
|
|
92
|
+
* session over.
|
|
93
|
+
*/
|
|
94
|
+
createDiagramOptions(options) {
|
|
95
|
+
const clientId = `${this.diagramType}_${this.windowSessions.current().id}_${(0, protocol_1.textHash)(JSON.stringify(options))}`;
|
|
96
|
+
return { ...super.createDiagramOptions(options), clientId };
|
|
97
|
+
}
|
|
76
98
|
/**
|
|
77
99
|
* Reopen every diagram once its client is lost, since none of them has a
|
|
78
100
|
* server behind it any more, and a failed one once a client starts.
|
|
@@ -98,7 +120,8 @@ let AbstractHydraniumGlspDiagramManager = class AbstractHydraniumGlspDiagramMana
|
|
|
98
120
|
}
|
|
99
121
|
/**
|
|
100
122
|
* Replace `widget` with a fresh one for the same diagram, in the same tab
|
|
101
|
-
* position and with its viewport: a new container
|
|
123
|
+
* position and with its viewport: a new container and load under the same
|
|
124
|
+
* client id, which takes over the session the old connection left.
|
|
102
125
|
* Reopens run one at a time, since each places its replacement next to a
|
|
103
126
|
* neighbour that a reopen running alongside could take out of the layout.
|
|
104
127
|
*/
|
|
@@ -159,6 +182,10 @@ let AbstractHydraniumGlspDiagramManager = class AbstractHydraniumGlspDiagramMana
|
|
|
159
182
|
}
|
|
160
183
|
};
|
|
161
184
|
exports.AbstractHydraniumGlspDiagramManager = AbstractHydraniumGlspDiagramManager;
|
|
185
|
+
__decorate([
|
|
186
|
+
(0, inversify_1.inject)(window_session_1.WindowSessionService),
|
|
187
|
+
__metadata("design:type", Object)
|
|
188
|
+
], AbstractHydraniumGlspDiagramManager.prototype, "windowSessions", void 0);
|
|
162
189
|
exports.AbstractHydraniumGlspDiagramManager = AbstractHydraniumGlspDiagramManager = __decorate([
|
|
163
190
|
(0, inversify_1.injectable)()
|
|
164
191
|
], AbstractHydraniumGlspDiagramManager);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"glsp-diagram-manager.js","sourceRoot":"","sources":["../../src/browser/glsp-diagram-manager.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF
|
|
1
|
+
{"version":3,"file":"glsp-diagram-manager.js","sourceRoot":"","sources":["../../src/browser/glsp-diagram-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"glsp-theia-frontend-module.d.ts","sourceRoot":"","sources":["../../src/browser/glsp-theia-frontend-module.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EACJ,KAAK,gBAAgB,EACrB,oBAAoB,EACpB,sBAAsB,EACtB,KAAK,kBAAkB,EAEvB,uBAAuB,EAEzB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,4CAA4C,CAAC;AAEtF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"glsp-theia-frontend-module.d.ts","sourceRoot":"","sources":["../../src/browser/glsp-theia-frontend-module.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EACJ,KAAK,gBAAgB,EACrB,oBAAoB,EACpB,sBAAsB,EACtB,KAAK,kBAAkB,EAEvB,uBAAuB,EAEzB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,4CAA4C,CAAC;AAEtF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAI/D;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB,eAAoE,CAAC;AACxG,MAAM,MAAM,sBAAsB,GAAG,OAAO,sBAAsB,CAAC;AAEnE;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,8BAAsB,wCAAyC,SAAQ,uBAAuB;IAC3F,qEAAqE;IACrE,kBAA2B,eAAe,EAAE,mBAAmB,CAAC;IAEhE,oFAAoF;IACpF,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,oBAAoB,EAAE,UAAU,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAE3F,8FAA8F;IAC9F,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,cAAc,EAAE,UAAU,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAEnF;;;;;;;;;;OAUG;IACH,SAAS,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAE/C;;;;;;;;;OASG;IACH,SAAS,CAAC,sBAAsB,IAAI,UAAU,CAAC,OAAO,CAAC,sBAAsB,CAAC,GAAG,sBAAsB,GAAG,SAAS,CAElH;IAED;;;;;;;OAOG;IACM,UAAU,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAOnD;IAEQ,wBAAwB,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAEjE;IAEQ,0BAA0B,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAWnE;IAEQ,uBAAuB,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAGhE;IAED;;;;;;;;;;;;;;;;OAgBG;IACM,wBAAwB,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAGjE;CACH"}
|
|
@@ -12,6 +12,7 @@ exports.AbstractHydraniumGlspTheiaFrontendModule = exports.SkipClientContributio
|
|
|
12
12
|
const theia_integration_1 = require("@eclipse-glsp/theia-integration");
|
|
13
13
|
const browser_1 = require("@hydranium/client-theia/lib/browser");
|
|
14
14
|
const diagram_widget_1 = require("./diagram-widget");
|
|
15
|
+
const window_session_1 = require("./window-session");
|
|
15
16
|
/**
|
|
16
17
|
* Sentinel returned from {@link AbstractHydraniumGlspTheiaFrontendModule.bindClientContribution}
|
|
17
18
|
* to mean "this module deliberately does not bind a GLSPClientContribution"
|
|
@@ -85,6 +86,7 @@ class AbstractHydraniumGlspTheiaFrontendModule extends theia_integration_1.GLSPT
|
|
|
85
86
|
initialize(context) {
|
|
86
87
|
super.initialize(context);
|
|
87
88
|
(0, browser_1.bindConnectionReporter)(context.bind, context.isBound);
|
|
89
|
+
(0, window_session_1.bindWindowSessionService)(context.bind, context.isBound);
|
|
88
90
|
if (this.logLevelPreference) {
|
|
89
91
|
(0, browser_1.bindLogLevelPreference)(context.bind, this.logLevelPreference);
|
|
90
92
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"glsp-theia-frontend-module.js","sourceRoot":"","sources":["../../src/browser/glsp-theia-frontend-module.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;AAElF,uEAQyC;AAEzC,iEAAqG;AAErG,qDAA8D;
|
|
1
|
+
{"version":3,"file":"glsp-theia-frontend-module.js","sourceRoot":"","sources":["../../src/browser/glsp-theia-frontend-module.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;AAElF,uEAQyC;AAEzC,iEAAqG;AAErG,qDAA8D;AAC9D,qDAA4D;AAE5D;;;;;;GAMG;AACU,QAAA,sBAAsB,GAAG,MAAM,CAAC,GAAG,CAAC,qDAAqD,CAAC,CAAC;AAGxG;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,8CAA+D,SAAQ,2CAAuB;IAU3F;;;;;;;;;;OAUG;IACgB,kBAAkB,CAAU;IAE/C;;;;;;;;;OASG;IACO,sBAAsB;QAC7B,OAAO,SAAS,CAAC;IACpB,CAAC;IAED;;;;;;;OAOG;IACM,UAAU,CAAC,OAAyB;QAC1C,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QAC1B,IAAA,gCAAsB,EAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;QACtD,IAAA,yCAAwB,EAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;QACxD,IAAI,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC3B,IAAA,gCAAsB,EAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,kBAAkB,CAAC,CAAC;QACjE,CAAC;IACJ,CAAC;IAEQ,wBAAwB,CAAC,OAAyB;QACxD,OAAO,CAAC,IAAI,CAAC,wCAAoB,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IACpE,CAAC;IAEQ,0BAA0B,CAAC,OAAyB;QAC1D,MAAM,YAAY,GAAG,IAAI,CAAC,sBAAsB,EAAE,CAAC;QACnD,IAAI,YAAY,KAAK,QAAA,sBAAsB,EAAE,CAAC;YAC3C,OAAO;QACV,CAAC;QACD,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;YAC9B,KAAK,CAAC,0BAA0B,CAAC,OAAO,CAAC,CAAC;YAC1C,OAAO;QACV,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,MAAM,EAAE,CAAC,gBAAgB,EAAE,CAAC;QACvD,OAAO,CAAC,IAAI,CAAC,0CAAsB,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;IAChE,CAAC;IAEQ,uBAAuB,CAAC,OAAyB;QACvD,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,MAAM,EAAE,CAAC,gBAAgB,EAAE,CAAC;QAC9D,IAAA,0CAAsB,EAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IACpE,CAAC;IAED;;;;;;;;;;;;;;;;OAgBG;IACM,wBAAwB,CAAC,OAAyB;QACxD,KAAK,CAAC,wBAAwB,CAAC,OAAO,CAAC,CAAC;QACxC,OAAO,CAAC,MAAM,CAAC,qCAAiB,CAAC,CAAC,EAAE,CAAC,2CAA0B,CAAC,CAAC;IACpE,CAAC;CACH"}
|
package/lib/browser/index.d.ts
CHANGED
|
@@ -20,5 +20,6 @@ export * from './glsp-theia-frontend-module';
|
|
|
20
20
|
export * from './hidden-bounds-updater';
|
|
21
21
|
export * from './hydranium-glsp-diagram-configuration';
|
|
22
22
|
export * from './status-overlay';
|
|
23
|
+
export * from './window-session';
|
|
23
24
|
export type { GLSPDiagramLanguage } from '@eclipse-glsp/theia-integration/lib/common';
|
|
24
25
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/browser/index.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAIlF,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,kBAAkB,CAAC;AACjC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,4BAA4B,CAAC;AAC3C,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,iBAAiB,CAAC;AAChC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,yBAAyB,CAAC;AACxC,cAAc,wCAAwC,CAAC;AACvD,cAAc,kBAAkB,CAAC;AAKjC,YAAY,EAAE,mBAAmB,EAAE,MAAM,4CAA4C,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/browser/index.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAIlF,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,kBAAkB,CAAC;AACjC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,4BAA4B,CAAC;AAC3C,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,iBAAiB,CAAC;AAChC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,yBAAyB,CAAC;AACxC,cAAc,wCAAwC,CAAC;AACvD,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AAKjC,YAAY,EAAE,mBAAmB,EAAE,MAAM,4CAA4C,CAAC"}
|
package/lib/browser/index.js
CHANGED
|
@@ -38,4 +38,5 @@ __exportStar(require("./glsp-theia-frontend-module"), exports);
|
|
|
38
38
|
__exportStar(require("./hidden-bounds-updater"), exports);
|
|
39
39
|
__exportStar(require("./hydranium-glsp-diagram-configuration"), exports);
|
|
40
40
|
__exportStar(require("./status-overlay"), exports);
|
|
41
|
+
__exportStar(require("./window-session"), exports);
|
|
41
42
|
//# sourceMappingURL=index.js.map
|
package/lib/browser/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/browser/index.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;;;;;;;;;;;;;;AAElF,gEAAgE;AAChE,mFAAmF;AACnF,sDAAoC;AACpC,wDAAsC;AACtC,mDAAiC;AACjC,gEAA8C;AAC9C,mDAAiC;AACjC,gDAA8B;AAC9B,6DAA2C;AAC3C,yDAAuC;AACvC,yDAAuC;AACvC,kDAAgC;AAChC,+DAA6C;AAC7C,0DAAwC;AACxC,yEAAuD;AACvD,mDAAiC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/browser/index.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;;;;;;;;;;;;;;AAElF,gEAAgE;AAChE,mFAAmF;AACnF,sDAAoC;AACpC,wDAAsC;AACtC,mDAAiC;AACjC,gEAA8C;AAC9C,mDAAiC;AACjC,gDAA8B;AAC9B,6DAA2C;AAC3C,yDAAuC;AACvC,yDAAuC;AACvC,kDAAgC;AAChC,+DAA6C;AAC7C,0DAAwC;AACxC,yEAAuD;AACvD,mDAAiC;AACjC,mDAAiC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made available under the
|
|
5
|
+
* terms of the MIT License which is available in the project root.
|
|
6
|
+
*
|
|
7
|
+
* SPDX-License-Identifier: MIT
|
|
8
|
+
********************************************************************************/
|
|
9
|
+
import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application-contribution';
|
|
10
|
+
import { type interfaces } from '@theia/core/shared/inversify';
|
|
11
|
+
/** The `sessionStorage` key of the window's {@link WindowSession}. */
|
|
12
|
+
export declare const WINDOW_SESSION_KEY = "hydranium.glsp.windowSession";
|
|
13
|
+
/** Holds the id of the window session the last page in the tab left, for the next page to take up. */
|
|
14
|
+
export declare const RELEASED_WINDOW_SESSION_KEY = "hydranium.glsp.releasedWindowSession";
|
|
15
|
+
/** The window's part of every diagram client id it opens, and the token its diagrams resume with. */
|
|
16
|
+
export interface WindowSession {
|
|
17
|
+
readonly id: string;
|
|
18
|
+
readonly resumeToken: string;
|
|
19
|
+
}
|
|
20
|
+
export declare function isWindowSession(value: unknown): value is WindowSession;
|
|
21
|
+
export declare const WindowSessionService: unique symbol;
|
|
22
|
+
/**
|
|
23
|
+
* The page's window session: the one the last page in this tab left, so a
|
|
24
|
+
* reload resumes its diagrams, and a new one otherwise.
|
|
25
|
+
*
|
|
26
|
+
* A reload only has a session to resume on a server that outlives the page; a
|
|
27
|
+
* server started per frontend, as a Theia plugin host's is, is new after one.
|
|
28
|
+
*/
|
|
29
|
+
export interface WindowSessionService {
|
|
30
|
+
current(): WindowSession;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Keeps the window session in `sessionStorage` and hands it on only as the page
|
|
34
|
+
* leaves. A duplicated tab copies `sessionStorage` while the original page is
|
|
35
|
+
* still live, so the copy finds no released session and draws its own; taking
|
|
36
|
+
* the original's would end the original's diagram sessions. Where
|
|
37
|
+
* `sessionStorage` is unavailable the session lasts for the page, and a reload
|
|
38
|
+
* resumes nothing.
|
|
39
|
+
*
|
|
40
|
+
* Claimed as the frontend starts, not with the first diagram: until then the
|
|
41
|
+
* released mark stays, and a tab duplicated meanwhile would take it too. A page
|
|
42
|
+
* restored from the back-forward cache takes the mark back, since Theia
|
|
43
|
+
* before 1.75 leaves it live without a reload.
|
|
44
|
+
*/
|
|
45
|
+
export declare class DefaultWindowSessionService implements WindowSessionService, FrontendApplicationContribution {
|
|
46
|
+
protected session?: WindowSession;
|
|
47
|
+
initialize(): void;
|
|
48
|
+
current(): WindowSession;
|
|
49
|
+
protected claim(): WindowSession;
|
|
50
|
+
protected parse(text: string | null): WindowSession | undefined;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Bind {@link WindowSessionService} once per container, and claim it as the
|
|
54
|
+
* frontend starts. An adopter rebinds {@link WindowSessionService}.
|
|
55
|
+
*/
|
|
56
|
+
export declare function bindWindowSessionService(bind: interfaces.Bind, isBound: interfaces.IsBound): void;
|
|
57
|
+
//# sourceMappingURL=window-session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"window-session.d.ts","sourceRoot":"","sources":["../../src/browser/window-session.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAIlF,OAAO,EAAE,+BAA+B,EAAE,MAAM,2DAA2D,CAAC;AAC5G,OAAO,EAAc,KAAK,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAE3E,sEAAsE;AACtE,eAAO,MAAM,kBAAkB,iCAAiC,CAAC;AACjE,sGAAsG;AACtG,eAAO,MAAM,2BAA2B,yCAAyC,CAAC;AAElF,qGAAqG;AACrG,MAAM,WAAW,aAAa;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC/B;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,aAAa,CAOtE;AAED,eAAO,MAAM,oBAAoB,eAAiC,CAAC;AAEnE;;;;;;GAMG;AACH,MAAM,WAAW,oBAAoB;IAClC,OAAO,IAAI,aAAa,CAAC;CAC3B;AAED;;;;;;;;;;;;GAYG;AACH,qBACa,2BAA4B,YAAW,oBAAoB,EAAE,+BAA+B;IACtG,SAAS,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC;IAElC,UAAU,IAAI,IAAI,CAEjB;IAED,OAAO,IAAI,aAAa,CAGvB;IAED,SAAS,CAAC,KAAK,IAAI,aAAa,CAkB/B;IAED,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,aAAa,GAAG,SAAS,CAO9D;CACH;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,UAAU,CAAC,OAAO,GAAG,IAAI,CAMjG"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/********************************************************************************
|
|
3
|
+
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
4
|
+
*
|
|
5
|
+
* This program and the accompanying materials are made available under the
|
|
6
|
+
* terms of the MIT License which is available in the project root.
|
|
7
|
+
*
|
|
8
|
+
* SPDX-License-Identifier: MIT
|
|
9
|
+
********************************************************************************/
|
|
10
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
11
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
12
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
13
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
14
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.DefaultWindowSessionService = exports.WindowSessionService = exports.RELEASED_WINDOW_SESSION_KEY = exports.WINDOW_SESSION_KEY = void 0;
|
|
18
|
+
exports.isWindowSession = isWindowSession;
|
|
19
|
+
exports.bindWindowSessionService = bindWindowSessionService;
|
|
20
|
+
const protocol_1 = require("@hydranium/protocol");
|
|
21
|
+
// Not the `@theia/core/lib/browser` barrel, which touches DOM globals at load.
|
|
22
|
+
const frontend_application_contribution_1 = require("@theia/core/lib/browser/frontend-application-contribution");
|
|
23
|
+
const inversify_1 = require("@theia/core/shared/inversify");
|
|
24
|
+
/** The `sessionStorage` key of the window's {@link WindowSession}. */
|
|
25
|
+
exports.WINDOW_SESSION_KEY = 'hydranium.glsp.windowSession';
|
|
26
|
+
/** Holds the id of the window session the last page in the tab left, for the next page to take up. */
|
|
27
|
+
exports.RELEASED_WINDOW_SESSION_KEY = 'hydranium.glsp.releasedWindowSession';
|
|
28
|
+
function isWindowSession(value) {
|
|
29
|
+
return (typeof value === 'object' &&
|
|
30
|
+
value !== null &&
|
|
31
|
+
typeof value.id === 'string' &&
|
|
32
|
+
typeof value.resumeToken === 'string');
|
|
33
|
+
}
|
|
34
|
+
exports.WindowSessionService = Symbol('WindowSessionService');
|
|
35
|
+
/**
|
|
36
|
+
* Keeps the window session in `sessionStorage` and hands it on only as the page
|
|
37
|
+
* leaves. A duplicated tab copies `sessionStorage` while the original page is
|
|
38
|
+
* still live, so the copy finds no released session and draws its own; taking
|
|
39
|
+
* the original's would end the original's diagram sessions. Where
|
|
40
|
+
* `sessionStorage` is unavailable the session lasts for the page, and a reload
|
|
41
|
+
* resumes nothing.
|
|
42
|
+
*
|
|
43
|
+
* Claimed as the frontend starts, not with the first diagram: until then the
|
|
44
|
+
* released mark stays, and a tab duplicated meanwhile would take it too. A page
|
|
45
|
+
* restored from the back-forward cache takes the mark back, since Theia
|
|
46
|
+
* before 1.75 leaves it live without a reload.
|
|
47
|
+
*/
|
|
48
|
+
let DefaultWindowSessionService = class DefaultWindowSessionService {
|
|
49
|
+
session;
|
|
50
|
+
initialize() {
|
|
51
|
+
this.current();
|
|
52
|
+
}
|
|
53
|
+
current() {
|
|
54
|
+
this.session ??= this.claim();
|
|
55
|
+
return this.session;
|
|
56
|
+
}
|
|
57
|
+
claim() {
|
|
58
|
+
const created = { id: (0, protocol_1.randomUuid)(), resumeToken: (0, protocol_1.randomUuid)() };
|
|
59
|
+
try {
|
|
60
|
+
const storage = globalThis.sessionStorage;
|
|
61
|
+
const stored = this.parse(storage.getItem(exports.WINDOW_SESSION_KEY));
|
|
62
|
+
const session = stored && storage.getItem(exports.RELEASED_WINDOW_SESSION_KEY) === stored.id ? stored : created;
|
|
63
|
+
storage.setItem(exports.WINDOW_SESSION_KEY, JSON.stringify(session));
|
|
64
|
+
storage.removeItem(exports.RELEASED_WINDOW_SESSION_KEY);
|
|
65
|
+
globalThis.addEventListener?.('pagehide', () => storage.setItem(exports.RELEASED_WINDOW_SESSION_KEY, session.id));
|
|
66
|
+
globalThis.addEventListener?.('pageshow', event => {
|
|
67
|
+
if (event.persisted) {
|
|
68
|
+
storage.removeItem(exports.RELEASED_WINDOW_SESSION_KEY);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
return session;
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return created;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
parse(text) {
|
|
78
|
+
try {
|
|
79
|
+
const value = text ? JSON.parse(text) : undefined;
|
|
80
|
+
return isWindowSession(value) ? value : undefined;
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
exports.DefaultWindowSessionService = DefaultWindowSessionService;
|
|
88
|
+
exports.DefaultWindowSessionService = DefaultWindowSessionService = __decorate([
|
|
89
|
+
(0, inversify_1.injectable)()
|
|
90
|
+
], DefaultWindowSessionService);
|
|
91
|
+
/**
|
|
92
|
+
* Bind {@link WindowSessionService} once per container, and claim it as the
|
|
93
|
+
* frontend starts. An adopter rebinds {@link WindowSessionService}.
|
|
94
|
+
*/
|
|
95
|
+
function bindWindowSessionService(bind, isBound) {
|
|
96
|
+
if (!isBound(exports.WindowSessionService)) {
|
|
97
|
+
bind(DefaultWindowSessionService).toSelf().inSingletonScope();
|
|
98
|
+
bind(exports.WindowSessionService).toService(DefaultWindowSessionService);
|
|
99
|
+
bind(frontend_application_contribution_1.FrontendApplicationContribution).toService(exports.WindowSessionService);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=window-session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"window-session.js","sourceRoot":"","sources":["../../src/browser/window-session.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hydranium/glsp-client-theia",
|
|
3
|
-
"version": "1.0.0-next.
|
|
3
|
+
"version": "1.0.0-next.204",
|
|
4
4
|
"description": "Theia-coupled client primitives for GLSP heads built on @hydranium/glsp-server. Provides the action dispatcher, channel logger, and connection-handler bases that Theia-based adopters extend; companion of @hydranium/glsp-server.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"diagram",
|
|
@@ -82,10 +82,10 @@
|
|
|
82
82
|
"@eclipse-glsp/client": "2.7.0",
|
|
83
83
|
"@eclipse-glsp/server": "2.7.0",
|
|
84
84
|
"@eclipse-glsp/theia-integration": "2.7.0",
|
|
85
|
-
"@hydranium/client-theia": "1.0.0-next.
|
|
86
|
-
"@hydranium/core": "1.0.0-next.
|
|
87
|
-
"@hydranium/glsp-server": "1.0.0-next.
|
|
88
|
-
"@hydranium/protocol": "1.0.0-next.
|
|
85
|
+
"@hydranium/client-theia": "1.0.0-next.204",
|
|
86
|
+
"@hydranium/core": "1.0.0-next.204",
|
|
87
|
+
"@hydranium/glsp-server": "1.0.0-next.204",
|
|
88
|
+
"@hydranium/protocol": "1.0.0-next.204",
|
|
89
89
|
"@theia/core": "^1.70.0",
|
|
90
90
|
"@theia/process": "^1.70.0",
|
|
91
91
|
"@theia/workspace": "^1.70.0",
|
|
@@ -99,8 +99,8 @@
|
|
|
99
99
|
"peerDependencies": {
|
|
100
100
|
"@eclipse-glsp/client": "^2.6.0",
|
|
101
101
|
"@eclipse-glsp/theia-integration": "^2.6.0",
|
|
102
|
-
"@hydranium/client-theia": "1.0.0-next.
|
|
103
|
-
"@hydranium/protocol": "1.0.0-next.
|
|
102
|
+
"@hydranium/client-theia": "1.0.0-next.204",
|
|
103
|
+
"@hydranium/protocol": "1.0.0-next.204",
|
|
104
104
|
"@theia/core": "^1.70.0",
|
|
105
105
|
"@theia/process": "^1.70.0",
|
|
106
106
|
"@theia/workspace": "^1.70.0",
|
|
@@ -7,15 +7,17 @@
|
|
|
7
7
|
* SPDX-License-Identifier: MIT
|
|
8
8
|
********************************************************************************/
|
|
9
9
|
|
|
10
|
-
import { DiagramLoader, EditorContextService } from '@eclipse-glsp/client';
|
|
10
|
+
import { type Args, DiagramLoader, EditorContextService, GLSPActionDispatcher, SetViewportAction } from '@eclipse-glsp/client';
|
|
11
|
+
import { RESUME_TOKEN_ARG } from '@hydranium/protocol';
|
|
11
12
|
import { GLSPDiagramWidget, type GLSPDiagramWidgetOptions } from '@eclipse-glsp/theia-integration';
|
|
12
13
|
// Type-only: the `@theia/core/lib/browser` barrel touches DOM globals at module
|
|
13
14
|
// load, which the node-environment unit tests cannot provide.
|
|
14
15
|
import { type Message } from '@theia/core/lib/browser';
|
|
15
16
|
import { Emitter, type Event, nls } from '@theia/core';
|
|
16
|
-
import { type Container, injectable } from '@theia/core/shared/inversify';
|
|
17
|
+
import { type Container, inject, injectable } from '@theia/core/shared/inversify';
|
|
17
18
|
import { type DiagramLoadOutcome, HydraniumDiagramLoader } from './diagram-loader';
|
|
18
19
|
import { HydraniumGlspSaveable } from './glsp-saveable';
|
|
20
|
+
import { WindowSessionService } from './window-session';
|
|
19
21
|
// Shipped by this package rather than left to adopters: an overlay whose
|
|
20
22
|
// stylesheet was forgotten is an unstyled div in normal flow, which is a silent
|
|
21
23
|
// failure. Adopters override individual rules from their own stylesheet.
|
|
@@ -54,6 +56,7 @@ export const DIAGRAM_LOADING_FAILED_CLASS = `${DIAGRAM_LOADING_CLASS}-failed`;
|
|
|
54
56
|
*/
|
|
55
57
|
@injectable()
|
|
56
58
|
export class HydraniumGlspDiagramWidget extends GLSPDiagramWidget {
|
|
59
|
+
@inject(WindowSessionService) protected readonly windowSessions!: WindowSessionService;
|
|
57
60
|
protected loadingOverlay?: HTMLElement;
|
|
58
61
|
protected readonly reopenRequestEmitter = new Emitter<void>();
|
|
59
62
|
|
|
@@ -81,6 +84,11 @@ export class HydraniumGlspDiagramWidget extends GLSPDiagramWidget {
|
|
|
81
84
|
return new HydraniumGlspSaveable(this.actionDispatcher, this.diContainer.get(EditorContextService));
|
|
82
85
|
}
|
|
83
86
|
|
|
87
|
+
/** Adds the window's resume token, so a reload or reconnect takes this diagram's session over. */
|
|
88
|
+
protected override getRequestModelOptions(): Args {
|
|
89
|
+
return { ...super.getRequestModelOptions(), [RESUME_TOKEN_ARG]: this.windowSessions.current().resumeToken };
|
|
90
|
+
}
|
|
91
|
+
|
|
84
92
|
protected override onAfterAttach(msg: Message): void {
|
|
85
93
|
// Before `super`, which is what starts the load on first attach — so the
|
|
86
94
|
// overlay is already up when the round trip begins.
|
|
@@ -93,6 +101,19 @@ export class HydraniumGlspDiagramWidget extends GLSPDiagramWidget {
|
|
|
93
101
|
super.dispose();
|
|
94
102
|
}
|
|
95
103
|
|
|
104
|
+
/**
|
|
105
|
+
* GLSP's restore with `animate: false`; compare the two on a GLSP upgrade.
|
|
106
|
+
* An animated restore holds back every later command, so a Delete right
|
|
107
|
+
* after a select-all typed as the diagram opens finds nothing selected.
|
|
108
|
+
*/
|
|
109
|
+
protected override async setViewportData(viewportData: Parameters<GLSPDiagramWidget['setViewportData']>[0]): Promise<void> {
|
|
110
|
+
if (this.actionDispatcher instanceof GLSPActionDispatcher) {
|
|
111
|
+
this.actionDispatcher.dispatchOnceModelInitialized(
|
|
112
|
+
SetViewportAction.create(viewportData.elementId, viewportData.viewportData, { animate: false })
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
96
117
|
/**
|
|
97
118
|
* Cover the canvas until the load settles.
|
|
98
119
|
*
|
|
@@ -7,16 +7,22 @@
|
|
|
7
7
|
* SPDX-License-Identifier: MIT
|
|
8
8
|
********************************************************************************/
|
|
9
9
|
|
|
10
|
-
import { codiconCSSString, DiagramLoader } from '@eclipse-glsp/client';
|
|
10
|
+
import { codiconCSSString, DiagramLoader, type IDiagramOptions } from '@eclipse-glsp/client';
|
|
11
11
|
import { GLSPDiagramManager } from '@eclipse-glsp/theia-integration';
|
|
12
12
|
import { type GLSPDiagramLanguage } from '@eclipse-glsp/theia-integration/lib/common';
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
type GLSPDiagramWidget,
|
|
15
|
+
type GLSPDiagramWidgetOptions,
|
|
16
|
+
type GLSPWidgetOpenerOptions
|
|
17
|
+
} from '@eclipse-glsp/theia-integration/lib/browser';
|
|
14
18
|
import { type WidgetOpenerOptions } from '@theia/core/lib/browser';
|
|
15
19
|
import { type Disposable, DisposableCollection } from '@theia/core';
|
|
16
|
-
import { injectable } from '@theia/core/shared/inversify';
|
|
20
|
+
import { inject, injectable } from '@theia/core/shared/inversify';
|
|
21
|
+
import { textHash } from '@hydranium/protocol';
|
|
17
22
|
import { HydraniumGlspClientContribution } from './client-contribution';
|
|
18
23
|
import { HydraniumDiagramLoader } from './diagram-loader';
|
|
19
24
|
import { HydraniumGlspDiagramWidget } from './diagram-widget';
|
|
25
|
+
import { WindowSessionService } from './window-session';
|
|
20
26
|
|
|
21
27
|
/**
|
|
22
28
|
* `GLSPDiagramManager` subclass that derives the language-correlated getters
|
|
@@ -51,6 +57,8 @@ export abstract class AbstractHydraniumGlspDiagramManager extends GLSPDiagramMan
|
|
|
51
57
|
/** Optional icon-class override; takes precedence over the language's `iconClass`. */
|
|
52
58
|
protected readonly customIconClass?: string;
|
|
53
59
|
|
|
60
|
+
@inject(WindowSessionService) protected readonly windowSessions!: WindowSessionService;
|
|
61
|
+
|
|
54
62
|
protected clientListeners?: Disposable;
|
|
55
63
|
/** The reopens asked for so far, which run one at a time. */
|
|
56
64
|
protected reopening: Promise<void> = Promise.resolve();
|
|
@@ -84,6 +92,23 @@ export abstract class AbstractHydraniumGlspDiagramManager extends GLSPDiagramMan
|
|
|
84
92
|
return widget;
|
|
85
93
|
}
|
|
86
94
|
|
|
95
|
+
/**
|
|
96
|
+
* The same client id for the same diagram in this window, across a reload
|
|
97
|
+
* and a reopen after a lost client, so its load takes over the session the
|
|
98
|
+
* old connection left and keeps its unsaved text. A diagram closed by the
|
|
99
|
+
* user ends its session, and opening it again starts afresh.
|
|
100
|
+
*
|
|
101
|
+
* The widget options enter as a hash: GLSP makes the id an element id and
|
|
102
|
+
* finds it with an `#id` selector, which a URI's `:` and `/` break. The
|
|
103
|
+
* options identify the widget, so two widgets of one document, in two edit
|
|
104
|
+
* modes or set apart by an option an adopter adds, do not take each other's
|
|
105
|
+
* session over.
|
|
106
|
+
*/
|
|
107
|
+
protected override createDiagramOptions(options: GLSPDiagramWidgetOptions): IDiagramOptions {
|
|
108
|
+
const clientId = `${this.diagramType}_${this.windowSessions.current().id}_${textHash(JSON.stringify(options))}`;
|
|
109
|
+
return { ...super.createDiagramOptions(options), clientId };
|
|
110
|
+
}
|
|
111
|
+
|
|
87
112
|
/**
|
|
88
113
|
* Reopen every diagram once its client is lost, since none of them has a
|
|
89
114
|
* server behind it any more, and a failed one once a client starts.
|
|
@@ -115,7 +140,8 @@ export abstract class AbstractHydraniumGlspDiagramManager extends GLSPDiagramMan
|
|
|
115
140
|
|
|
116
141
|
/**
|
|
117
142
|
* Replace `widget` with a fresh one for the same diagram, in the same tab
|
|
118
|
-
* position and with its viewport: a new container
|
|
143
|
+
* position and with its viewport: a new container and load under the same
|
|
144
|
+
* client id, which takes over the session the old connection left.
|
|
119
145
|
* Reopens run one at a time, since each places its replacement next to a
|
|
120
146
|
* neighbour that a reopen running alongside could take out of the layout.
|
|
121
147
|
*/
|
|
@@ -20,6 +20,7 @@ import { type GLSPDiagramLanguage } from '@eclipse-glsp/theia-integration/lib/co
|
|
|
20
20
|
import { bindConnectionReporter, bindLogLevelPreference } from '@hydranium/client-theia/lib/browser';
|
|
21
21
|
import type { interfaces } from '@theia/core/shared/inversify';
|
|
22
22
|
import { HydraniumGlspDiagramWidget } from './diagram-widget';
|
|
23
|
+
import { bindWindowSessionService } from './window-session';
|
|
23
24
|
|
|
24
25
|
/**
|
|
25
26
|
* Sentinel returned from {@link AbstractHydraniumGlspTheiaFrontendModule.bindClientContribution}
|
|
@@ -107,6 +108,7 @@ export abstract class AbstractHydraniumGlspTheiaFrontendModule extends GLSPTheia
|
|
|
107
108
|
override initialize(context: ContainerContext): void {
|
|
108
109
|
super.initialize(context);
|
|
109
110
|
bindConnectionReporter(context.bind, context.isBound);
|
|
111
|
+
bindWindowSessionService(context.bind, context.isBound);
|
|
110
112
|
if (this.logLevelPreference) {
|
|
111
113
|
bindLogLevelPreference(context.bind, this.logLevelPreference);
|
|
112
114
|
}
|
package/src/browser/index.ts
CHANGED
|
@@ -23,6 +23,7 @@ export * from './glsp-theia-frontend-module';
|
|
|
23
23
|
export * from './hidden-bounds-updater';
|
|
24
24
|
export * from './hydranium-glsp-diagram-configuration';
|
|
25
25
|
export * from './status-overlay';
|
|
26
|
+
export * from './window-session';
|
|
26
27
|
|
|
27
28
|
// Upstream's root entry is its browser tier and re-exports no `lib/common`, so the
|
|
28
29
|
// type our abstract `diagramLanguage` members are declared with has no bare-specifier
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made available under the
|
|
5
|
+
* terms of the MIT License which is available in the project root.
|
|
6
|
+
*
|
|
7
|
+
* SPDX-License-Identifier: MIT
|
|
8
|
+
********************************************************************************/
|
|
9
|
+
|
|
10
|
+
import { randomUuid } from '@hydranium/protocol';
|
|
11
|
+
// Not the `@theia/core/lib/browser` barrel, which touches DOM globals at load.
|
|
12
|
+
import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application-contribution';
|
|
13
|
+
import { injectable, type interfaces } from '@theia/core/shared/inversify';
|
|
14
|
+
|
|
15
|
+
/** The `sessionStorage` key of the window's {@link WindowSession}. */
|
|
16
|
+
export const WINDOW_SESSION_KEY = 'hydranium.glsp.windowSession';
|
|
17
|
+
/** Holds the id of the window session the last page in the tab left, for the next page to take up. */
|
|
18
|
+
export const RELEASED_WINDOW_SESSION_KEY = 'hydranium.glsp.releasedWindowSession';
|
|
19
|
+
|
|
20
|
+
/** The window's part of every diagram client id it opens, and the token its diagrams resume with. */
|
|
21
|
+
export interface WindowSession {
|
|
22
|
+
readonly id: string;
|
|
23
|
+
readonly resumeToken: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function isWindowSession(value: unknown): value is WindowSession {
|
|
27
|
+
return (
|
|
28
|
+
typeof value === 'object' &&
|
|
29
|
+
value !== null &&
|
|
30
|
+
typeof (value as WindowSession).id === 'string' &&
|
|
31
|
+
typeof (value as WindowSession).resumeToken === 'string'
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export const WindowSessionService = Symbol('WindowSessionService');
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* The page's window session: the one the last page in this tab left, so a
|
|
39
|
+
* reload resumes its diagrams, and a new one otherwise.
|
|
40
|
+
*
|
|
41
|
+
* A reload only has a session to resume on a server that outlives the page; a
|
|
42
|
+
* server started per frontend, as a Theia plugin host's is, is new after one.
|
|
43
|
+
*/
|
|
44
|
+
export interface WindowSessionService {
|
|
45
|
+
current(): WindowSession;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Keeps the window session in `sessionStorage` and hands it on only as the page
|
|
50
|
+
* leaves. A duplicated tab copies `sessionStorage` while the original page is
|
|
51
|
+
* still live, so the copy finds no released session and draws its own; taking
|
|
52
|
+
* the original's would end the original's diagram sessions. Where
|
|
53
|
+
* `sessionStorage` is unavailable the session lasts for the page, and a reload
|
|
54
|
+
* resumes nothing.
|
|
55
|
+
*
|
|
56
|
+
* Claimed as the frontend starts, not with the first diagram: until then the
|
|
57
|
+
* released mark stays, and a tab duplicated meanwhile would take it too. A page
|
|
58
|
+
* restored from the back-forward cache takes the mark back, since Theia
|
|
59
|
+
* before 1.75 leaves it live without a reload.
|
|
60
|
+
*/
|
|
61
|
+
@injectable()
|
|
62
|
+
export class DefaultWindowSessionService implements WindowSessionService, FrontendApplicationContribution {
|
|
63
|
+
protected session?: WindowSession;
|
|
64
|
+
|
|
65
|
+
initialize(): void {
|
|
66
|
+
this.current();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
current(): WindowSession {
|
|
70
|
+
this.session ??= this.claim();
|
|
71
|
+
return this.session;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
protected claim(): WindowSession {
|
|
75
|
+
const created: WindowSession = { id: randomUuid(), resumeToken: randomUuid() };
|
|
76
|
+
try {
|
|
77
|
+
const storage = globalThis.sessionStorage;
|
|
78
|
+
const stored = this.parse(storage.getItem(WINDOW_SESSION_KEY));
|
|
79
|
+
const session = stored && storage.getItem(RELEASED_WINDOW_SESSION_KEY) === stored.id ? stored : created;
|
|
80
|
+
storage.setItem(WINDOW_SESSION_KEY, JSON.stringify(session));
|
|
81
|
+
storage.removeItem(RELEASED_WINDOW_SESSION_KEY);
|
|
82
|
+
globalThis.addEventListener?.('pagehide', () => storage.setItem(RELEASED_WINDOW_SESSION_KEY, session.id));
|
|
83
|
+
globalThis.addEventListener?.('pageshow', event => {
|
|
84
|
+
if ((event as PageTransitionEvent).persisted) {
|
|
85
|
+
storage.removeItem(RELEASED_WINDOW_SESSION_KEY);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
return session;
|
|
89
|
+
} catch {
|
|
90
|
+
return created;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
protected parse(text: string | null): WindowSession | undefined {
|
|
95
|
+
try {
|
|
96
|
+
const value: unknown = text ? JSON.parse(text) : undefined;
|
|
97
|
+
return isWindowSession(value) ? value : undefined;
|
|
98
|
+
} catch {
|
|
99
|
+
return undefined;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Bind {@link WindowSessionService} once per container, and claim it as the
|
|
106
|
+
* frontend starts. An adopter rebinds {@link WindowSessionService}.
|
|
107
|
+
*/
|
|
108
|
+
export function bindWindowSessionService(bind: interfaces.Bind, isBound: interfaces.IsBound): void {
|
|
109
|
+
if (!isBound(WindowSessionService)) {
|
|
110
|
+
bind(DefaultWindowSessionService).toSelf().inSingletonScope();
|
|
111
|
+
bind(WindowSessionService).toService(DefaultWindowSessionService);
|
|
112
|
+
bind(FrontendApplicationContribution).toService(WindowSessionService);
|
|
113
|
+
}
|
|
114
|
+
}
|