estreui 1.2.6 → 1.4.0
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/index.html +21 -0
- package/managedOverlay.html +3 -2
- package/overwatchPanel.html +27 -0
- package/package.json +1 -1
- package/scripts/estreUi-dialog.js +1 -4
- package/scripts/estreUi-main.js +326 -0
- package/scripts/estreUi-notification.js +539 -0
- package/scripts/estreUi-pageModel.js +190 -2
- package/serviceWorker.js +4 -2
- package/styles/estreUi.css +1 -1
- package/styles/estreUiCore.css +90 -1
- package/styles/estreUiCore2.css +25 -1
- package/styles/estreUiInitialize.css +5 -1
- package/styles/estreUiRoot.css +139 -2
package/index.html
CHANGED
|
@@ -64,6 +64,7 @@
|
|
|
64
64
|
<script defer type="text/javascript" src="./scripts/estreUi-core.js"></script>
|
|
65
65
|
<script defer type="text/javascript" src="./scripts/estreUi-dialog.js"></script>
|
|
66
66
|
<script defer type="text/javascript" src="./scripts/estreUi-notation.js"></script>
|
|
67
|
+
<script defer type="text/javascript" src="./scripts/estreUi-notification.js"></script>
|
|
67
68
|
<script defer type="text/javascript" src="./scripts/estreUi-pageModel.js"></script>
|
|
68
69
|
<script defer type="text/javascript" src="./scripts/estreUi-pageManager.js"></script>
|
|
69
70
|
<script defer type="text/javascript" src="./scripts/estreUi-handles.js"></script>
|
|
@@ -81,6 +82,7 @@
|
|
|
81
82
|
<link rel="preload" as="fetch" type="text/html" href="./staticDoc.html" crossOrigin="anonymous" />
|
|
82
83
|
<link rel="preload" as="fetch" type="text/html" href="./instantDoc.html" crossOrigin="anonymous" />
|
|
83
84
|
<link rel="preload" as="fetch" type="text/html" href="./mainMenu.html" crossOrigin="anonymous" />
|
|
85
|
+
<link rel="preload" as="fetch" type="text/html" href="./overwatchPanel.html" crossOrigin="anonymous" />
|
|
84
86
|
<link rel="preload" as="fetch" type="text/html" href="./stockHandlePrototypes.html" crossOrigin="anonymous" />
|
|
85
87
|
<link rel="preload" as="fetch" type="text/html" href="./customHandlePrototypes.html" crossOrigin="anonymous" />
|
|
86
88
|
|
|
@@ -97,6 +99,22 @@
|
|
|
97
99
|
</head>
|
|
98
100
|
|
|
99
101
|
<body class="vfv_scroll">
|
|
102
|
+
<!--
|
|
103
|
+
Dark mode pre-paint coupling (opt-in): uncomment to write
|
|
104
|
+
body[data-dark-mode] before the splash paints, avoiding FOLM
|
|
105
|
+
(flash of light mode) on dark-locked sessions. Adjust the
|
|
106
|
+
storage key and auto-mode policy to match your project.
|
|
107
|
+
-->
|
|
108
|
+
<!--
|
|
109
|
+
<script>
|
|
110
|
+
(function () {
|
|
111
|
+
const stored = localStorage.getItem("estreUi.darkMode");
|
|
112
|
+
const dark = stored === "1"
|
|
113
|
+
|| (stored == null && window.matchMedia && matchMedia("(prefers-color-scheme: dark)").matches);
|
|
114
|
+
if (dark) document.body.dataset.darkMode = "1";
|
|
115
|
+
})();
|
|
116
|
+
</script>
|
|
117
|
+
-->
|
|
100
118
|
<main id="splashRoot" style="z-index: 500; ">
|
|
101
119
|
<section id="splash" data-on-top="0">
|
|
102
120
|
<div class="container" data-container-id="root">
|
|
@@ -113,6 +131,9 @@
|
|
|
113
131
|
</header>
|
|
114
132
|
<nav id="mainMenu" class="right" data-exported="1" data-opened="">
|
|
115
133
|
</nav>
|
|
134
|
+
<nav id="overwatchPanel" data-exported="1" data-opened="">
|
|
135
|
+
</nav>
|
|
136
|
+
<section id="panelTrigger" data-static="1"></section>
|
|
116
137
|
|
|
117
138
|
<div id="ptr"><div>
|
|
118
139
|
<!-- Commented out. This is not implemented currently. <dotlottie-player src="./lotties/ptr_indic.json" background="transparent" speed="1" direction="1" mode="normal"></dotlottie-player> -->
|
package/managedOverlay.html
CHANGED
|
@@ -199,12 +199,13 @@
|
|
|
199
199
|
<div class="container top" data-container-id="noti" data-static="1" data-on-top="1">
|
|
200
200
|
<article class="" data-article-id="noti" data-static="" data-multi-instance="1" data-instance-origin="">
|
|
201
201
|
<div class="h_icon_set post_block" data-bind-attr="interactive@data-interactive" data-bind-style="bgColor@--bg-color">
|
|
202
|
-
<div class="icon_place"><img data-bind-attr="
|
|
202
|
+
<div class="icon_place"><img data-bind-attr="largeIconSrc@src" /></div>
|
|
203
203
|
<div class="content_place">
|
|
204
204
|
<div class="title_line"><span data-bind="contentTitle"></span></div>
|
|
205
|
+
<div class="subtitle_line"><span data-bind="subtitle"></span></div>
|
|
205
206
|
<div class="h_icon_Set content_area">
|
|
206
207
|
<div class="content_place" data-bind="content" data-bind-style="textColor@--color textSize@--size textWeight@--weight"></div>
|
|
207
|
-
<div class="icon_place"><img data-bind-attr="
|
|
208
|
+
<div class="icon_place"><img data-bind-attr="iconSrc@src" /></div>
|
|
208
209
|
</div>
|
|
209
210
|
</div>
|
|
210
211
|
</div>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<header id="panelHeader" data-static="1">
|
|
2
|
+
<!-- Common top header. Clock / date populated by setOverwatchPanelClock in a later commit. -->
|
|
3
|
+
<span id="panelClock"></span>
|
|
4
|
+
<span id="panelDate"></span>
|
|
5
|
+
</header>
|
|
6
|
+
<div class="dynamic_section_host" data-static="1">
|
|
7
|
+
<div class="host_item" data-id="timeline"><span>Timeline</span></div>
|
|
8
|
+
<div class="host_item" data-id="quickPanel"><span>Quick</span></div>
|
|
9
|
+
</div>
|
|
10
|
+
<div class="dynamic_section_block full_screen" data-static="1">
|
|
11
|
+
<section class="block_item" id="timeline" data-id="timeline" data-static="1">
|
|
12
|
+
<!-- Timeline slot: markup reserved in roadmap #008. Implementation scheduled separately. -->
|
|
13
|
+
</section>
|
|
14
|
+
<section class="block_item" id="quickPanel" data-id="quickPanel" data-static="1">
|
|
15
|
+
<div class="container" data-container-id="root" data-static="1">
|
|
16
|
+
<article data-article-id="main" data-static="1">
|
|
17
|
+
<div class="quick_tiles">
|
|
18
|
+
<button id="darkModeToggle" class="quick_tile" type="button" data-dark-mode-state="auto" onclick="estreUi.cycleDarkMode();">
|
|
19
|
+
<span class="tile_icon" aria-hidden="true">🌓</span>
|
|
20
|
+
<span class="tile_label">Auto</span>
|
|
21
|
+
</button>
|
|
22
|
+
</div>
|
|
23
|
+
</article>
|
|
24
|
+
</div>
|
|
25
|
+
</section>
|
|
26
|
+
</div>
|
|
27
|
+
<section id="panelGrabArea" data-static="1"><div class="handle"></div><div class="pad"></div></section>
|
package/package.json
CHANGED
|
@@ -502,10 +502,7 @@ const arrived = function (instanceOrigin) {
|
|
|
502
502
|
}
|
|
503
503
|
|
|
504
504
|
|
|
505
|
-
|
|
506
|
-
const noti = function (title, htmlContent, onTakeInteraction = (intent) => {}, mainIconSrc, subIconSrc) {
|
|
507
|
-
//<= To do implement
|
|
508
|
-
}
|
|
505
|
+
// noti() moved to estreUi-notification.js (roadmap #009).
|
|
509
506
|
|
|
510
507
|
|
|
511
508
|
// ======================================================================
|
package/scripts/estreUi-main.js
CHANGED
|
@@ -31,6 +31,11 @@ const estreUi = {
|
|
|
31
31
|
menuSectionList: [],
|
|
32
32
|
get menuArea() { return this.menuSections["menuArea"]; },
|
|
33
33
|
|
|
34
|
+
panelSections: {},
|
|
35
|
+
panelSectionList: [],
|
|
36
|
+
get quickPanel() { return this.panelSections["quickPanel"]; },
|
|
37
|
+
get timeline() { return this.panelSections["timeline"]; },
|
|
38
|
+
|
|
34
39
|
headerSections: {},
|
|
35
40
|
headerSectionList: [],
|
|
36
41
|
get appbar() { return this.headerSections["appbar"]; },
|
|
@@ -41,6 +46,7 @@ const estreUi = {
|
|
|
41
46
|
blindedCurrentOnTop: null,
|
|
42
47
|
mainCurrentOnTop: null,
|
|
43
48
|
menuCurrentOnTop: null,
|
|
49
|
+
panelCurrentOnTop: null,
|
|
44
50
|
headerCurrentOnTop: null,
|
|
45
51
|
|
|
46
52
|
//static getter
|
|
@@ -102,6 +108,16 @@ const estreUi = {
|
|
|
102
108
|
$menuArea: null,
|
|
103
109
|
$grabArea: null,
|
|
104
110
|
|
|
111
|
+
$overwatchPanel: null,
|
|
112
|
+
get $panelSections() { return this.$panelBlock?.find(c.c + se + uis.blockItem) ?? $(); },
|
|
113
|
+
$panelHeader: null,
|
|
114
|
+
$panelHost: null,
|
|
115
|
+
$panelBlock: null,
|
|
116
|
+
$panelClock: null,
|
|
117
|
+
$panelDate: null,
|
|
118
|
+
$panelGrabArea: null,
|
|
119
|
+
$panelTrigger: null,
|
|
120
|
+
|
|
105
121
|
$fixedTop: null,
|
|
106
122
|
get $headerSections() { return this.$fixedTop.find(c.c + se); },
|
|
107
123
|
$appbar: null,
|
|
@@ -121,6 +137,11 @@ const estreUi = {
|
|
|
121
137
|
|
|
122
138
|
//handles
|
|
123
139
|
menuSwipeHandler: null,
|
|
140
|
+
panelOpenSwipeHandler: null,
|
|
141
|
+
panelCloseSwipeHandler: null,
|
|
142
|
+
panelClockTimeoutId: null,
|
|
143
|
+
panelClockIntervalId: null,
|
|
144
|
+
darkModeMql: null,
|
|
124
145
|
|
|
125
146
|
//properties
|
|
126
147
|
euiState: "exit",
|
|
@@ -166,6 +187,16 @@ const estreUi = {
|
|
|
166
187
|
//getter and setter
|
|
167
188
|
get isOpenMainMenu() { return this.$mainMenu.attr(eds.opened) == t1; },
|
|
168
189
|
|
|
190
|
+
get isOpenOverwatchPanel() { return this.$overwatchPanel.attr(eds.opened) == t1; },
|
|
191
|
+
|
|
192
|
+
get darkMode() {
|
|
193
|
+
const stored = localStorage.getItem("estreUi.darkMode");
|
|
194
|
+
if (stored == "1") return true;
|
|
195
|
+
if (stored == "0") return false;
|
|
196
|
+
return null;
|
|
197
|
+
},
|
|
198
|
+
get isDarkMode() { return document.body.dataset.darkMode == t1; },
|
|
199
|
+
|
|
169
200
|
|
|
170
201
|
|
|
171
202
|
//links (object redirection)
|
|
@@ -187,6 +218,9 @@ const estreUi = {
|
|
|
187
218
|
|
|
188
219
|
this.$mainMenu = $("nav#mainMenu");
|
|
189
220
|
|
|
221
|
+
this.$overwatchPanel = $("nav#overwatchPanel");
|
|
222
|
+
this.$panelTrigger = $("section#panelTrigger");
|
|
223
|
+
|
|
190
224
|
this.$fixedTop = $("header#fixedTop");
|
|
191
225
|
|
|
192
226
|
this.$fixedBottom = $("#fixedBottom");
|
|
@@ -198,6 +232,7 @@ const estreUi = {
|
|
|
198
232
|
this.setReload();
|
|
199
233
|
this.setBackNavigation();
|
|
200
234
|
this.setMenuSwipeHandler();
|
|
235
|
+
this.setupDarkMode();
|
|
201
236
|
|
|
202
237
|
|
|
203
238
|
const onLoadedFixedBottom = async _ => {
|
|
@@ -236,6 +271,23 @@ const estreUi = {
|
|
|
236
271
|
return this.initStaticMenus(subTerm);
|
|
237
272
|
}
|
|
238
273
|
|
|
274
|
+
const onLoadedOverwatchPanel = subTerm => {
|
|
275
|
+
this.$panelHeader = this.$overwatchPanel.find("header#panelHeader");
|
|
276
|
+
this.$panelHost = this.$overwatchPanel.find(uis.dynamicSectionHost);
|
|
277
|
+
this.$panelBlock = this.$overwatchPanel.find(uis.dynamicSectionBlock);
|
|
278
|
+
this.$panelClock = this.$panelHeader.find("#panelClock");
|
|
279
|
+
this.$panelDate = this.$panelHeader.find("#panelDate");
|
|
280
|
+
this.$panelGrabArea = this.$overwatchPanel.find("section#panelGrabArea");
|
|
281
|
+
|
|
282
|
+
this.$panelGrabArea.click(this.overwatchPanelGrabAreaOnclick);
|
|
283
|
+
this.setPanelSwipeHandler();
|
|
284
|
+
this.scheduleOverwatchPanelClock();
|
|
285
|
+
this.initOverwatchPanelHandles();
|
|
286
|
+
this.initOverwatchPanelTimeline();
|
|
287
|
+
this.updateDarkModeToggleWidgets();
|
|
288
|
+
return this.initStaticPanels(subTerm);
|
|
289
|
+
}
|
|
290
|
+
|
|
239
291
|
|
|
240
292
|
const loadExported = url => fetch(url).then(response => {
|
|
241
293
|
if (!response.ok) throw new Error('Network response was not ok');
|
|
@@ -315,6 +367,18 @@ const estreUi = {
|
|
|
315
367
|
.then(() => loadExportedMainMenu(subTerm, attempt + 1));
|
|
316
368
|
});
|
|
317
369
|
|
|
370
|
+
let loadExportedOverwatchPanel;
|
|
371
|
+
loadExportedOverwatchPanel = (subTerm, attempt = 0) => loadExported("overwatchPanel.html").then(htmlContent => {
|
|
372
|
+
this.$overwatchPanel.prepend(htmlContent);
|
|
373
|
+
return onLoadedOverwatchPanel(subTerm);
|
|
374
|
+
}).catch(error => {
|
|
375
|
+
const delay = Math.min(1000 * Math.pow(2, attempt), 30000);
|
|
376
|
+
console.error("There has been a problem with your fetch operation for overwatchPanel: ", error);
|
|
377
|
+
console.log(`Retrying to load overwatchPanel in ${delay}ms...`);
|
|
378
|
+
return postPromise(resolve => setTimeout(resolve, delay))
|
|
379
|
+
.then(() => loadExportedOverwatchPanel(subTerm, attempt + 1));
|
|
380
|
+
});
|
|
381
|
+
|
|
318
382
|
let loadExportedStockHandlePrototypes;
|
|
319
383
|
loadExportedStockHandlePrototypes = (_, attempt = 0) => loadExported("stockHandlePrototypes.html").then(htmlContent => {
|
|
320
384
|
this.$handlePrototypes.prepend(htmlContent);
|
|
@@ -372,6 +436,7 @@ const estreUi = {
|
|
|
372
436
|
await Promise.all(mainLoader);
|
|
373
437
|
|
|
374
438
|
await (this.$mainMenu.attr(eds.exported) == t1 ? loadExportedMainMenu(subTerm) : onLoadedMainMenu(subTerm));
|
|
439
|
+
await (this.$overwatchPanel.attr(eds.exported) == t1 ? loadExportedOverwatchPanel(subTerm) : onLoadedOverwatchPanel(subTerm));
|
|
375
440
|
|
|
376
441
|
this.initSessionManager();
|
|
377
442
|
|
|
@@ -512,6 +577,95 @@ const estreUi = {
|
|
|
512
577
|
},
|
|
513
578
|
|
|
514
579
|
|
|
580
|
+
//dark mode
|
|
581
|
+
setupDarkMode() {
|
|
582
|
+
if (window.matchMedia) {
|
|
583
|
+
this.darkModeMql = window.matchMedia("(prefers-color-scheme: dark)");
|
|
584
|
+
const onChange = _ => { if (this.darkMode == null) this.applyDarkMode(); };
|
|
585
|
+
if (this.darkModeMql.addEventListener) this.darkModeMql.addEventListener("change", onChange);
|
|
586
|
+
else this.darkModeMql.addListener(onChange);
|
|
587
|
+
}
|
|
588
|
+
this.applyDarkMode();
|
|
589
|
+
},
|
|
590
|
+
|
|
591
|
+
setDarkMode(value) {
|
|
592
|
+
let pref;
|
|
593
|
+
if (value == null) pref = null;
|
|
594
|
+
else if (value === false || value === 0 || value === "0") pref = false;
|
|
595
|
+
else pref = true;
|
|
596
|
+
|
|
597
|
+
if (pref == null) localStorage.removeItem("estreUi.darkMode");
|
|
598
|
+
else localStorage.setItem("estreUi.darkMode", pref ? "1" : "0");
|
|
599
|
+
|
|
600
|
+
this.applyDarkMode();
|
|
601
|
+
return this.isDarkMode;
|
|
602
|
+
},
|
|
603
|
+
|
|
604
|
+
applyDarkMode() {
|
|
605
|
+
const pref = this.darkMode;
|
|
606
|
+
const active = (pref == null) ? (this.darkModeMql?.matches ?? false) : pref;
|
|
607
|
+
if (active) document.body.dataset.darkMode = "1";
|
|
608
|
+
else delete document.body.dataset.darkMode;
|
|
609
|
+
this.updateDarkModeToggleWidgets();
|
|
610
|
+
},
|
|
611
|
+
|
|
612
|
+
// Cycle auto -> light -> dark -> auto (single-button 3-state control)
|
|
613
|
+
cycleDarkMode() {
|
|
614
|
+
const pref = this.darkMode;
|
|
615
|
+
if (pref == null) this.setDarkMode(false);
|
|
616
|
+
else if (pref === false) this.setDarkMode(true);
|
|
617
|
+
else this.setDarkMode(null);
|
|
618
|
+
return this.darkMode;
|
|
619
|
+
},
|
|
620
|
+
|
|
621
|
+
/**
|
|
622
|
+
* Register a tile in the quickPanel section of overwatchPanel.
|
|
623
|
+
* Host projects call this after estreUi.init to append custom toggles/shortcuts.
|
|
624
|
+
*
|
|
625
|
+
* @param {Object} config
|
|
626
|
+
* @param {string} config.id unique DOM id for the tile
|
|
627
|
+
* @param {string} [config.icon] short glyph or emoji shown in the .tile_icon span
|
|
628
|
+
* @param {string} [config.label] text label shown in the .tile_label span
|
|
629
|
+
* @param {Function} [config.onClick] click handler; receives the jQuery event
|
|
630
|
+
* @returns {HTMLElement|null} the tile element, or null if quickPanel is not ready / id collides
|
|
631
|
+
*/
|
|
632
|
+
registerOverwatchPanelTile(config) {
|
|
633
|
+
if (config == null || config.id == null) return null;
|
|
634
|
+
const $tiles = this.$overwatchPanel?.find("#quickPanel .quick_tiles");
|
|
635
|
+
if ($tiles == null || $tiles.length < 1) return null;
|
|
636
|
+
if ($tiles.find("#" + config.id).length > 0) return null;
|
|
637
|
+
const $tile = $("<button>").addClass("quick_tile").attr("type", "button").attr("id", config.id);
|
|
638
|
+
$tile.append($("<span>").addClass("tile_icon").attr("aria-hidden", "true").text(config.icon ?? ""));
|
|
639
|
+
$tile.append($("<span>").addClass("tile_label").text(config.label ?? ""));
|
|
640
|
+
if (typeof config.onClick == "function") $tile.on("click", config.onClick);
|
|
641
|
+
$tiles.append($tile);
|
|
642
|
+
return $tile[0];
|
|
643
|
+
},
|
|
644
|
+
|
|
645
|
+
unregisterOverwatchPanelTile(id) {
|
|
646
|
+
if (id == null) return false;
|
|
647
|
+
const $tile = this.$overwatchPanel?.find("#quickPanel .quick_tiles #" + id);
|
|
648
|
+
if ($tile == null || $tile.length < 1) return false;
|
|
649
|
+
$tile.off("click").remove();
|
|
650
|
+
return true;
|
|
651
|
+
},
|
|
652
|
+
|
|
653
|
+
updateDarkModeToggleWidgets() {
|
|
654
|
+
const $widgets = $("#darkModeToggle");
|
|
655
|
+
if ($widgets.length < 1) return;
|
|
656
|
+
const pref = this.darkMode;
|
|
657
|
+
const state = (pref == null) ? "auto" : (pref ? "dark" : "light");
|
|
658
|
+
const icon = state == "light" ? "\u2600\uFE0F" : (state == "dark" ? "\u263D" : "\u{1F313}");
|
|
659
|
+
const label = state.charAt(0).toUpperCase() + state.slice(1);
|
|
660
|
+
$widgets.each(function() {
|
|
661
|
+
const $w = $(this);
|
|
662
|
+
$w.attr("data-dark-mode-state", state);
|
|
663
|
+
$w.find(".tile_icon").text(icon);
|
|
664
|
+
$w.find(".tile_label").text(label);
|
|
665
|
+
});
|
|
666
|
+
},
|
|
667
|
+
|
|
668
|
+
|
|
515
669
|
//mainMenu
|
|
516
670
|
setMenuSwipeHandler() {
|
|
517
671
|
if (this.$mainMenu.length > 0) {
|
|
@@ -534,6 +688,88 @@ const estreUi = {
|
|
|
534
688
|
if (this.menuSwipeHandler != null) this.menuSwipeHandler.release();
|
|
535
689
|
},
|
|
536
690
|
|
|
691
|
+
|
|
692
|
+
//overwatchPanel
|
|
693
|
+
setPanelSwipeHandler() {
|
|
694
|
+
if (this.$overwatchPanel.length < 1) return;
|
|
695
|
+
this.releasePanelSwipeHandler();
|
|
696
|
+
const ui = this;
|
|
697
|
+
if (this.$panelTrigger.length > 0) {
|
|
698
|
+
this.panelOpenSwipeHandler = new EstreSwipeHandler(this.$panelTrigger[0]).unuseX()
|
|
699
|
+
.setResponseBound(this.$overwatchPanel)
|
|
700
|
+
.setOnUp(function(grabX, grabY, handled, canceled, directed) {
|
|
701
|
+
if (handled && grabY > 0 && !ui.isOpenOverwatchPanel) {
|
|
702
|
+
setTimeout(_ => ui.openOverwatchPanel(), 0);
|
|
703
|
+
}
|
|
704
|
+
});
|
|
705
|
+
}
|
|
706
|
+
if (this.$panelGrabArea.length > 0) {
|
|
707
|
+
this.panelCloseSwipeHandler = new EstreSwipeHandler(this.$panelGrabArea[0]).unuseX()
|
|
708
|
+
.setResponseBound(this.$overwatchPanel)
|
|
709
|
+
.setOnUp(function(grabX, grabY, handled, canceled, directed) {
|
|
710
|
+
if (handled && grabY < 0 && ui.isOpenOverwatchPanel) {
|
|
711
|
+
setTimeout(_ => ui.closeOverwatchPanel(), 0);
|
|
712
|
+
}
|
|
713
|
+
});
|
|
714
|
+
}
|
|
715
|
+
},
|
|
716
|
+
|
|
717
|
+
releasePanelSwipeHandler() {
|
|
718
|
+
if (this.panelOpenSwipeHandler != null) { this.panelOpenSwipeHandler.release(); this.panelOpenSwipeHandler = null; }
|
|
719
|
+
if (this.panelCloseSwipeHandler != null) { this.panelCloseSwipeHandler.release(); this.panelCloseSwipeHandler = null; }
|
|
720
|
+
},
|
|
721
|
+
|
|
722
|
+
// The .dynamic_section_block inside overwatchPanel lives outside any <article>,
|
|
723
|
+
// so the standard article-scoped handle init never reaches it. Attach the handle
|
|
724
|
+
// here with the panel itself acting as a minimal host.
|
|
725
|
+
initOverwatchPanelHandles() {
|
|
726
|
+
if (this.$overwatchPanel.length < 1) return;
|
|
727
|
+
const $block = this.$panelBlock;
|
|
728
|
+
if ($block == null || $block.length < 1) return;
|
|
729
|
+
const host = { $host: this.$overwatchPanel };
|
|
730
|
+
new EstreDynamicSectionBlockHandle($block[0], host).init();
|
|
731
|
+
},
|
|
732
|
+
|
|
733
|
+
// Mounts EstreTimelineView onto overwatchPanel #timeline slot (roadmap #010).
|
|
734
|
+
// Timeline persists entries left by checkOut()ed noti banners.
|
|
735
|
+
initOverwatchPanelTimeline() {
|
|
736
|
+
if (typeof EstreTimelineView === "undefined") return;
|
|
737
|
+
if (this.$overwatchPanel == null || this.$overwatchPanel.length < 1) return;
|
|
738
|
+
const $timeline = this.$overwatchPanel.find("#timeline");
|
|
739
|
+
if ($timeline.length < 1) return;
|
|
740
|
+
this.timelineView = new EstreTimelineView($timeline);
|
|
741
|
+
},
|
|
742
|
+
|
|
743
|
+
setOverwatchPanelClock() {
|
|
744
|
+
if (this.$panelClock == null) return;
|
|
745
|
+
const now = new Date();
|
|
746
|
+
if (this.$panelClock.length > 0) {
|
|
747
|
+
const hh = String(now.getHours()).padStart(2, "0");
|
|
748
|
+
const mm = String(now.getMinutes()).padStart(2, "0");
|
|
749
|
+
this.$panelClock.text(hh + ":" + mm);
|
|
750
|
+
}
|
|
751
|
+
if (this.$panelDate.length > 0) {
|
|
752
|
+
const fmt = new Intl.DateTimeFormat(undefined, { weekday: "short", month: "short", day: "numeric" });
|
|
753
|
+
this.$panelDate.text(fmt.format(now));
|
|
754
|
+
}
|
|
755
|
+
},
|
|
756
|
+
|
|
757
|
+
scheduleOverwatchPanelClock() {
|
|
758
|
+
this.releaseOverwatchPanelClock();
|
|
759
|
+
this.setOverwatchPanelClock();
|
|
760
|
+
const now = new Date();
|
|
761
|
+
const msToNext = 60000 - (now.getSeconds() * 1000 + now.getMilliseconds());
|
|
762
|
+
this.panelClockTimeoutId = setTimeout(_ => {
|
|
763
|
+
this.setOverwatchPanelClock();
|
|
764
|
+
this.panelClockIntervalId = setInterval(_ => this.setOverwatchPanelClock(), 60000);
|
|
765
|
+
}, msToNext);
|
|
766
|
+
},
|
|
767
|
+
|
|
768
|
+
releaseOverwatchPanelClock() {
|
|
769
|
+
if (this.panelClockTimeoutId != null) { clearTimeout(this.panelClockTimeoutId); this.panelClockTimeoutId = null; }
|
|
770
|
+
if (this.panelClockIntervalId != null) { clearInterval(this.panelClockIntervalId); this.panelClockIntervalId = null; }
|
|
771
|
+
},
|
|
772
|
+
|
|
537
773
|
mainMenuBtnOnClick(e) {
|
|
538
774
|
estreUi.toggleMainMenuButton();
|
|
539
775
|
},
|
|
@@ -542,6 +778,10 @@ const estreUi = {
|
|
|
542
778
|
estreUi.closeMainMenu();
|
|
543
779
|
},
|
|
544
780
|
|
|
781
|
+
overwatchPanelGrabAreaOnclick(e) {
|
|
782
|
+
estreUi.closeOverwatchPanel();
|
|
783
|
+
},
|
|
784
|
+
|
|
545
785
|
toggleMainMenuButton() {
|
|
546
786
|
if (this.isOpenMainMenu) return this.closeMainMenu();
|
|
547
787
|
else return this.openMainMenu();
|
|
@@ -590,6 +830,53 @@ const estreUi = {
|
|
|
590
830
|
},
|
|
591
831
|
|
|
592
832
|
|
|
833
|
+
//overwatchPanel
|
|
834
|
+
toggleOverwatchPanel(sectionId) {
|
|
835
|
+
if (this.isOpenOverwatchPanel) return this.closeOverwatchPanel();
|
|
836
|
+
else return this.openOverwatchPanel(sectionId);
|
|
837
|
+
},
|
|
838
|
+
|
|
839
|
+
openOverwatchPanel(sectionId) {
|
|
840
|
+
if (!this.isOpenOverwatchPanel) {
|
|
841
|
+
this.$overwatchPanel.attr(eds.opened, t1);
|
|
842
|
+
if (sectionId != null) this.showOverwatchPanelSection(sectionId);
|
|
843
|
+
else {
|
|
844
|
+
const $top = this.$panelSections.filter(asv(eds.onTop, t1));
|
|
845
|
+
const panelCurrentTop = $top[$top.length - 1]?.pageHandle;
|
|
846
|
+
if (panelCurrentTop != null) {
|
|
847
|
+
this.panelCurrentOnTop = panelCurrentTop;
|
|
848
|
+
panelCurrentTop.show(false);
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
return true;
|
|
852
|
+
} else if (sectionId != null) {
|
|
853
|
+
this.showOverwatchPanelSection(sectionId);
|
|
854
|
+
return true;
|
|
855
|
+
} else return false;
|
|
856
|
+
},
|
|
857
|
+
|
|
858
|
+
closeOverwatchPanel() {
|
|
859
|
+
if (this.isOpenOverwatchPanel) {
|
|
860
|
+
this.$overwatchPanel.attr(eds.opened, "");
|
|
861
|
+
this.panelCurrentOnTop?.onHide();
|
|
862
|
+
return true;
|
|
863
|
+
} else return false;
|
|
864
|
+
},
|
|
865
|
+
|
|
866
|
+
showOverwatchPanelSection(id) {
|
|
867
|
+
const $target = this.$panelSections.filter(eid + id);
|
|
868
|
+
if ($target.length < 1) return false;
|
|
869
|
+
const targetEl = $target[$target.length - 1];
|
|
870
|
+
targetEl.scrollIntoView({ behavior: "smooth", block: "start", inline: "start" });
|
|
871
|
+
const targetComponent = targetEl.pageHandle;
|
|
872
|
+
if (targetComponent != null) {
|
|
873
|
+
targetComponent.show(false);
|
|
874
|
+
this.panelCurrentOnTop = targetComponent;
|
|
875
|
+
}
|
|
876
|
+
return true;
|
|
877
|
+
},
|
|
878
|
+
|
|
879
|
+
|
|
593
880
|
//rootbar
|
|
594
881
|
initRootbar() {
|
|
595
882
|
this.$rootTabs = this.$tabsbar.find(c.c + btn);
|
|
@@ -1393,6 +1680,45 @@ const estreUi = {
|
|
|
1393
1680
|
return component;
|
|
1394
1681
|
},
|
|
1395
1682
|
|
|
1683
|
+
async initStaticPanels(term = 0) {
|
|
1684
|
+
const $pss = this.$panelSections;
|
|
1685
|
+
|
|
1686
|
+
const delayer = (delay = term) => postPromise(resolve => setTimeout(resolve, delay));
|
|
1687
|
+
for (var i=0; i<$pss.length; i++) {
|
|
1688
|
+
this.initStaticPanel($pss[i], null, u, true);
|
|
1689
|
+
await delayer();
|
|
1690
|
+
}
|
|
1691
|
+
|
|
1692
|
+
let $top = this.$panelSections.filter(asv(eds.onTop, t1));
|
|
1693
|
+
if ($top.length < 1) $top = this.$panelSections.filter(eid + "quickPanel");
|
|
1694
|
+
if ($top.length < 1) $top = this.$panelSections;
|
|
1695
|
+
if ($top.length > 0) {
|
|
1696
|
+
const targetComponent = $top[$top.length - 1].pageHandle;
|
|
1697
|
+
targetComponent?.show(false);
|
|
1698
|
+
this.panelCurrentOnTop = targetComponent;
|
|
1699
|
+
}
|
|
1700
|
+
},
|
|
1701
|
+
|
|
1702
|
+
releaseStaticPanel(component) {
|
|
1703
|
+
if (component == null) return;
|
|
1704
|
+
const instanceId = component.instanceId;
|
|
1705
|
+
component.release(component.isStatic ? null : true);
|
|
1706
|
+
if (this.panelSections[instanceId] != null) delete this.panelSections[instanceId];
|
|
1707
|
+
const index = this.panelSectionList.indexOf(component);
|
|
1708
|
+
if (index > -1) this.panelSectionList.splice(index, 1);
|
|
1709
|
+
},
|
|
1710
|
+
|
|
1711
|
+
initStaticPanel(bound, intent = null, instanceOrigin, init = false) {
|
|
1712
|
+
this.releaseStaticPanel(bound.pageHandle);
|
|
1713
|
+
const component = new EstrePanelComponent(bound, instanceOrigin);
|
|
1714
|
+
if (!init || component.isStatic) {
|
|
1715
|
+
this.panelSections[component.instanceId] = component;
|
|
1716
|
+
this.panelSectionList.push(component);
|
|
1717
|
+
}
|
|
1718
|
+
component.init(intent);
|
|
1719
|
+
return component;
|
|
1720
|
+
},
|
|
1721
|
+
|
|
1396
1722
|
async initHeaderBars(term = 0) {
|
|
1397
1723
|
const $hss = this.$headerSections;
|
|
1398
1724
|
|