@jsenv/plugin-toolbar 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/css/document_execution_indicator.css +87 -0
- package/dist/css/globals.css +75 -0
- package/dist/css/server_indicator.css +83 -0
- package/dist/css/theme_light.css +110 -0
- package/dist/css/toolbar.css +7 -683
- package/dist/css/toolbar_menu_overflow.css +59 -0
- package/dist/css/toolbar_settings.css +202 -0
- package/dist/css/tooltips.css +67 -0
- package/dist/js/animation.js +282 -0
- package/dist/js/animation_actions.js +7 -0
- package/dist/js/animation_effects.js +10 -0
- package/dist/js/animation_signals.js +4 -0
- package/dist/js/changes_actions.js +7 -0
- package/dist/js/changes_indicator.js +57 -0
- package/dist/js/changes_signals.js +2 -0
- package/dist/js/document_execution_indicator.js +62 -0
- package/dist/js/document_index_link.js +4 -0
- package/dist/js/dom.js +48 -0
- package/dist/js/execution_actions.js +46 -0
- package/dist/js/execution_effects.js +16 -0
- package/dist/js/execution_signals.js +17 -0
- package/dist/js/hooks.mjs +185 -0
- package/dist/js/iframe_to_parent_href.js +10 -0
- package/dist/js/notification_actions.js +60 -0
- package/dist/js/notification_context.js +1 -0
- package/dist/js/notification_effects.js +9 -0
- package/dist/js/notification_signals.js +5 -0
- package/dist/js/parent_window_actions.js +39 -0
- package/dist/js/parent_window_context.js +6 -0
- package/dist/js/parent_window_effects.js +15 -0
- package/dist/js/parent_window_signals.js +25 -0
- package/dist/js/preact.mjs +316 -0
- package/dist/js/responsive.js +104 -0
- package/dist/js/server_actions.js +7 -0
- package/dist/js/server_effects.js +9 -0
- package/dist/js/server_indicator.js +52 -0
- package/dist/js/server_signals.js +10 -0
- package/dist/js/settings_actions.js +7 -0
- package/dist/js/settings_signals.js +2 -0
- package/dist/js/signals-core.mjs +339 -0
- package/dist/js/signals.mjs +202 -0
- package/dist/js/theme_actions.js +7 -0
- package/dist/js/theme_effects.js +6 -0
- package/dist/js/theme_signals.js +4 -0
- package/dist/js/toolbar_animation_setting.js +21 -0
- package/dist/js/toolbar_autoreload_setting.js +67 -0
- package/dist/js/toolbar_close_button.js +14 -0
- package/dist/js/toolbar_core.js +8 -1792
- package/dist/js/toolbar_injector.js +2 -4
- package/dist/js/toolbar_menu_overflow.js +81 -0
- package/dist/js/toolbar_notification_setting.js +72 -0
- package/dist/js/toolbar_open_actions.js +7 -0
- package/dist/js/toolbar_open_effects.js +4 -0
- package/dist/js/toolbar_open_signals.js +4 -0
- package/dist/js/toolbar_opening.js +65 -0
- package/dist/js/toolbar_overlay.js +69 -0
- package/dist/js/toolbar_settings.js +44 -0
- package/dist/js/toolbar_state_context.js +1 -0
- package/dist/js/toolbar_state_effects.js +8 -0
- package/dist/js/toolbar_state_signals.js +17 -0
- package/dist/js/toolbar_theme_setting.js +13 -0
- package/dist/js/toolbar_ui.js +20 -0
- package/dist/js/tooltip_actions.js +6 -0
- package/dist/js/variant.js +53 -0
- package/dist/jsenv_plugin_toolbar.js +3 -6
- package/package.json +2 -2
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { effect } from "./signals.mjs";
|
|
2
|
+
import { executionSignal, executionTooltipOpenedSignal } from "./execution_signals.js";
|
|
3
|
+
import { closeExecutionTooltip, openExecutionTooltip } from "./execution_actions.js";
|
|
4
|
+
import { removeForceHideElement } from "./dom.js";
|
|
5
|
+
import { enableVariant } from "./variant.js";
|
|
6
|
+
const executionIndicator = document.querySelector("#document_execution_indicator");
|
|
7
|
+
export const renderDocumentExecutionIndicator = async () => {
|
|
8
|
+
removeForceHideElement(document.querySelector("#document_execution_indicator"));
|
|
9
|
+
effect(() => {
|
|
10
|
+
const execution = executionSignal.value;
|
|
11
|
+
updateExecutionIndicator(execution);
|
|
12
|
+
});
|
|
13
|
+
effect(() => {
|
|
14
|
+
const executionTooltipOpened = executionTooltipOpenedSignal.value;
|
|
15
|
+
if (executionTooltipOpened) {
|
|
16
|
+
executionIndicator.setAttribute("data-tooltip-visible", "");
|
|
17
|
+
} else {
|
|
18
|
+
executionIndicator.removeAttribute("data-tooltip-visible");
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
const updateExecutionIndicator = ({
|
|
23
|
+
status,
|
|
24
|
+
startTime,
|
|
25
|
+
endTime
|
|
26
|
+
} = {}) => {
|
|
27
|
+
enableVariant(executionIndicator, {
|
|
28
|
+
execution: status
|
|
29
|
+
});
|
|
30
|
+
const variantNode = executionIndicator.querySelector("[data-when-active]");
|
|
31
|
+
variantNode.querySelector("button").onclick = () => {
|
|
32
|
+
const executionTooltipOpened = executionTooltipOpenedSignal.value;
|
|
33
|
+
if (executionTooltipOpened) {
|
|
34
|
+
closeExecutionTooltip();
|
|
35
|
+
} else {
|
|
36
|
+
openExecutionTooltip();
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
variantNode.querySelector(".tooltip").textContent = computeText({
|
|
40
|
+
status,
|
|
41
|
+
startTime,
|
|
42
|
+
endTime
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// relative time: https://github.com/tc39/proposal-intl-relative-time/issues/118
|
|
47
|
+
const computeText = ({
|
|
48
|
+
status,
|
|
49
|
+
startTime,
|
|
50
|
+
endTime
|
|
51
|
+
}) => {
|
|
52
|
+
if (status === "completed") {
|
|
53
|
+
return `Execution completed in ${endTime - startTime}ms`;
|
|
54
|
+
}
|
|
55
|
+
if (status === "errored") {
|
|
56
|
+
return `Execution failed in ${endTime - startTime}ms`;
|
|
57
|
+
}
|
|
58
|
+
if (status === "running") {
|
|
59
|
+
return "Executing...";
|
|
60
|
+
}
|
|
61
|
+
return "";
|
|
62
|
+
};
|
package/dist/js/dom.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export const getToolbarIframe = () => {
|
|
2
|
+
const iframes = Array.from(window.parent.document.querySelectorAll("iframe"));
|
|
3
|
+
return iframes.find(iframe => iframe.contentWindow === window);
|
|
4
|
+
};
|
|
5
|
+
export const forceHideElement = element => {
|
|
6
|
+
element.setAttribute("data-force-hide", "");
|
|
7
|
+
};
|
|
8
|
+
export const removeForceHideElement = element => {
|
|
9
|
+
element.removeAttribute("data-force-hide");
|
|
10
|
+
};
|
|
11
|
+
export const setStyles = (element, styles) => {
|
|
12
|
+
const elementStyle = element.style;
|
|
13
|
+
const restoreStyles = Object.keys(styles).map(styleName => {
|
|
14
|
+
let restore;
|
|
15
|
+
if (styleName in elementStyle) {
|
|
16
|
+
const currentStyle = elementStyle[styleName];
|
|
17
|
+
restore = () => {
|
|
18
|
+
elementStyle[styleName] = currentStyle;
|
|
19
|
+
};
|
|
20
|
+
} else {
|
|
21
|
+
restore = () => {
|
|
22
|
+
delete elementStyle[styleName];
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
elementStyle[styleName] = styles[styleName];
|
|
26
|
+
return restore;
|
|
27
|
+
});
|
|
28
|
+
return () => {
|
|
29
|
+
restoreStyles.forEach(restore => restore());
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
export const setAttributes = (element, attributes) => {
|
|
33
|
+
Object.keys(attributes).forEach(name => {
|
|
34
|
+
element.setAttribute(name, attributes[name]);
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
export const getDocumentScroll = () => {
|
|
38
|
+
return {
|
|
39
|
+
x: document.documentElement.scrollLeft,
|
|
40
|
+
y: document.documentElement.scrollTop
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
export const activateToolbarSection = element => {
|
|
44
|
+
element.setAttribute("data-active", "");
|
|
45
|
+
};
|
|
46
|
+
export const deactivateToolbarSection = element => {
|
|
47
|
+
element.removeAttribute("data-active");
|
|
48
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { executionTooltipOpenedSignal } from "./execution_signals.js";
|
|
2
|
+
import { notify } from "./notification_actions.js";
|
|
3
|
+
export const openExecutionTooltip = () => {
|
|
4
|
+
executionTooltipOpenedSignal.value = true;
|
|
5
|
+
};
|
|
6
|
+
export const closeExecutionTooltip = () => {
|
|
7
|
+
executionTooltipOpenedSignal.value = false;
|
|
8
|
+
};
|
|
9
|
+
export const notifyExecutionResult = (execution, previousExecution) => {
|
|
10
|
+
const executedFileRelativeUrl = window.location.href;
|
|
11
|
+
const notificationOptions = {
|
|
12
|
+
lang: "en",
|
|
13
|
+
icon: getFaviconHref(),
|
|
14
|
+
clickToFocus: true,
|
|
15
|
+
clickToClose: true
|
|
16
|
+
};
|
|
17
|
+
if (execution.status === "errored") {
|
|
18
|
+
if (previousExecution) {
|
|
19
|
+
if (previousExecution.status === "completed") {
|
|
20
|
+
notify("Broken", {
|
|
21
|
+
...notificationOptions,
|
|
22
|
+
body: `${executedFileRelativeUrl} execution now failing.`
|
|
23
|
+
});
|
|
24
|
+
} else {
|
|
25
|
+
notify("Still failing", {
|
|
26
|
+
...notificationOptions,
|
|
27
|
+
body: `${executedFileRelativeUrl} execution still failing.`
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
} else {
|
|
31
|
+
notify("Failing", {
|
|
32
|
+
...notificationOptions,
|
|
33
|
+
body: `${executedFileRelativeUrl} execution failed.`
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
} else if (previousExecution && previousExecution.status === "errored") {
|
|
37
|
+
notify("Fixed", {
|
|
38
|
+
...notificationOptions,
|
|
39
|
+
body: `${executedFileRelativeUrl} execution fixed.`
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
const getFaviconHref = () => {
|
|
44
|
+
const link = document.querySelector('link[rel="icon"]');
|
|
45
|
+
return link ? link.href : undefined;
|
|
46
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { effect } from "./signals.mjs";
|
|
2
|
+
import { executionSignal, previousExecutionSignal } from "./execution_signals.js";
|
|
3
|
+
import { notifyExecutionResult } from "./execution_actions.js";
|
|
4
|
+
effect(() => {
|
|
5
|
+
const execution = executionSignal.value;
|
|
6
|
+
if (execution) {
|
|
7
|
+
sessionStorage.setItem(window.location.href, JSON.stringify(execution));
|
|
8
|
+
}
|
|
9
|
+
});
|
|
10
|
+
effect(() => {
|
|
11
|
+
const execution = executionSignal.value;
|
|
12
|
+
const previousExecution = previousExecutionSignal.value;
|
|
13
|
+
if (execution) {
|
|
14
|
+
notifyExecutionResult(execution, previousExecution);
|
|
15
|
+
}
|
|
16
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { signal } from "./signals.mjs";
|
|
2
|
+
export const executionTooltipOpenedSignal = signal(false);
|
|
3
|
+
export const executionSignal = signal({
|
|
4
|
+
status: "running"
|
|
5
|
+
});
|
|
6
|
+
export const previousExecutionSignal = signal(sessionStorage.hasOwnProperty(window.location.href) ? JSON.parse(sessionStorage.getItem(window.location.href)) : null);
|
|
7
|
+
window.parent.__supervisor__.getDocumentExecutionResult().then(({
|
|
8
|
+
status,
|
|
9
|
+
startTime,
|
|
10
|
+
endTime
|
|
11
|
+
}) => {
|
|
12
|
+
executionSignal.value = {
|
|
13
|
+
status,
|
|
14
|
+
startTime,
|
|
15
|
+
endTime
|
|
16
|
+
};
|
|
17
|
+
});
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { options as n } from "./preact.mjs";
|
|
2
|
+
var t,
|
|
3
|
+
r,
|
|
4
|
+
u,
|
|
5
|
+
i,
|
|
6
|
+
o = 0,
|
|
7
|
+
f = [],
|
|
8
|
+
c = [],
|
|
9
|
+
e = n.__b,
|
|
10
|
+
a = n.__r,
|
|
11
|
+
v = n.diffed,
|
|
12
|
+
l = n.__c,
|
|
13
|
+
m = n.unmount;
|
|
14
|
+
function d(t, u) {
|
|
15
|
+
n.__h && n.__h(r, t, o || u), o = 0;
|
|
16
|
+
var i = r.__H || (r.__H = {
|
|
17
|
+
__: [],
|
|
18
|
+
__h: []
|
|
19
|
+
});
|
|
20
|
+
return t >= i.__.length && i.__.push({
|
|
21
|
+
__V: c
|
|
22
|
+
}), i.__[t];
|
|
23
|
+
}
|
|
24
|
+
function p(n) {
|
|
25
|
+
return o = 1, y(B, n);
|
|
26
|
+
}
|
|
27
|
+
function y(n, u, i) {
|
|
28
|
+
var o = d(t++, 2);
|
|
29
|
+
if (o.t = n, !o.__c && (o.__ = [i ? i(u) : B(void 0, u), function (n) {
|
|
30
|
+
var t = o.__N ? o.__N[0] : o.__[0],
|
|
31
|
+
r = o.t(t, n);
|
|
32
|
+
t !== r && (o.__N = [r, o.__[1]], o.__c.setState({}));
|
|
33
|
+
}], o.__c = r, !r.u)) {
|
|
34
|
+
r.u = !0;
|
|
35
|
+
var f = r.shouldComponentUpdate;
|
|
36
|
+
r.shouldComponentUpdate = function (n, t, r) {
|
|
37
|
+
if (!o.__c.__H) return !0;
|
|
38
|
+
var u = o.__c.__H.__.filter(function (n) {
|
|
39
|
+
return n.__c;
|
|
40
|
+
});
|
|
41
|
+
if (u.every(function (n) {
|
|
42
|
+
return !n.__N;
|
|
43
|
+
})) return !f || f.call(this, n, t, r);
|
|
44
|
+
var i = !1;
|
|
45
|
+
return u.forEach(function (n) {
|
|
46
|
+
if (n.__N) {
|
|
47
|
+
var t = n.__[0];
|
|
48
|
+
n.__ = n.__N, n.__N = void 0, t !== n.__[0] && (i = !0);
|
|
49
|
+
}
|
|
50
|
+
}), !(!i && o.__c.props === n) && (!f || f.call(this, n, t, r));
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
return o.__N || o.__;
|
|
54
|
+
}
|
|
55
|
+
function h(u, i) {
|
|
56
|
+
var o = d(t++, 3);
|
|
57
|
+
!n.__s && z(o.__H, i) && (o.__ = u, o.i = i, r.__H.__h.push(o));
|
|
58
|
+
}
|
|
59
|
+
function s(u, i) {
|
|
60
|
+
var o = d(t++, 4);
|
|
61
|
+
!n.__s && z(o.__H, i) && (o.__ = u, o.i = i, r.__h.push(o));
|
|
62
|
+
}
|
|
63
|
+
function _(n) {
|
|
64
|
+
return o = 5, F(function () {
|
|
65
|
+
return {
|
|
66
|
+
current: n
|
|
67
|
+
};
|
|
68
|
+
}, []);
|
|
69
|
+
}
|
|
70
|
+
function A(n, t, r) {
|
|
71
|
+
o = 6, s(function () {
|
|
72
|
+
return "function" == typeof n ? (n(t()), function () {
|
|
73
|
+
return n(null);
|
|
74
|
+
}) : n ? (n.current = t(), function () {
|
|
75
|
+
return n.current = null;
|
|
76
|
+
}) : void 0;
|
|
77
|
+
}, null == r ? r : r.concat(n));
|
|
78
|
+
}
|
|
79
|
+
function F(n, r) {
|
|
80
|
+
var u = d(t++, 7);
|
|
81
|
+
return z(u.__H, r) ? (u.__V = n(), u.i = r, u.__h = n, u.__V) : u.__;
|
|
82
|
+
}
|
|
83
|
+
function T(n, t) {
|
|
84
|
+
return o = 8, F(function () {
|
|
85
|
+
return n;
|
|
86
|
+
}, t);
|
|
87
|
+
}
|
|
88
|
+
function q(n) {
|
|
89
|
+
var u = r.context[n.__c],
|
|
90
|
+
i = d(t++, 9);
|
|
91
|
+
return i.c = n, u ? (null == i.__ && (i.__ = !0, u.sub(r)), u.props.value) : n.__;
|
|
92
|
+
}
|
|
93
|
+
function x(t, r) {
|
|
94
|
+
n.useDebugValue && n.useDebugValue(r ? r(t) : t);
|
|
95
|
+
}
|
|
96
|
+
function P(n) {
|
|
97
|
+
var u = d(t++, 10),
|
|
98
|
+
i = p();
|
|
99
|
+
return u.__ = n, r.componentDidCatch || (r.componentDidCatch = function (n, t) {
|
|
100
|
+
u.__ && u.__(n, t), i[1](n);
|
|
101
|
+
}), [i[0], function () {
|
|
102
|
+
i[1](void 0);
|
|
103
|
+
}];
|
|
104
|
+
}
|
|
105
|
+
function V() {
|
|
106
|
+
var n = d(t++, 11);
|
|
107
|
+
if (!n.__) {
|
|
108
|
+
for (var u = r.__v; null !== u && !u.__m && null !== u.__;) u = u.__;
|
|
109
|
+
var i = u.__m || (u.__m = [0, 0]);
|
|
110
|
+
n.__ = "P" + i[0] + "-" + i[1]++;
|
|
111
|
+
}
|
|
112
|
+
return n.__;
|
|
113
|
+
}
|
|
114
|
+
function b() {
|
|
115
|
+
for (var t; t = f.shift();) if (t.__P && t.__H) try {
|
|
116
|
+
t.__H.__h.forEach(k), t.__H.__h.forEach(w), t.__H.__h = [];
|
|
117
|
+
} catch (r) {
|
|
118
|
+
t.__H.__h = [], n.__e(r, t.__v);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
n.__b = function (n) {
|
|
122
|
+
r = null, e && e(n);
|
|
123
|
+
}, n.__r = function (n) {
|
|
124
|
+
a && a(n), t = 0;
|
|
125
|
+
var i = (r = n.__c).__H;
|
|
126
|
+
i && (u === r ? (i.__h = [], r.__h = [], i.__.forEach(function (n) {
|
|
127
|
+
n.__N && (n.__ = n.__N), n.__V = c, n.__N = n.i = void 0;
|
|
128
|
+
})) : (i.__h.forEach(k), i.__h.forEach(w), i.__h = [])), u = r;
|
|
129
|
+
}, n.diffed = function (t) {
|
|
130
|
+
v && v(t);
|
|
131
|
+
var o = t.__c;
|
|
132
|
+
o && o.__H && (o.__H.__h.length && (1 !== f.push(o) && i === n.requestAnimationFrame || ((i = n.requestAnimationFrame) || j)(b)), o.__H.__.forEach(function (n) {
|
|
133
|
+
n.i && (n.__H = n.i), n.__V !== c && (n.__ = n.__V), n.i = void 0, n.__V = c;
|
|
134
|
+
})), u = r = null;
|
|
135
|
+
}, n.__c = function (t, r) {
|
|
136
|
+
r.some(function (t) {
|
|
137
|
+
try {
|
|
138
|
+
t.__h.forEach(k), t.__h = t.__h.filter(function (n) {
|
|
139
|
+
return !n.__ || w(n);
|
|
140
|
+
});
|
|
141
|
+
} catch (u) {
|
|
142
|
+
r.some(function (n) {
|
|
143
|
+
n.__h && (n.__h = []);
|
|
144
|
+
}), r = [], n.__e(u, t.__v);
|
|
145
|
+
}
|
|
146
|
+
}), l && l(t, r);
|
|
147
|
+
}, n.unmount = function (t) {
|
|
148
|
+
m && m(t);
|
|
149
|
+
var r,
|
|
150
|
+
u = t.__c;
|
|
151
|
+
u && u.__H && (u.__H.__.forEach(function (n) {
|
|
152
|
+
try {
|
|
153
|
+
k(n);
|
|
154
|
+
} catch (n) {
|
|
155
|
+
r = n;
|
|
156
|
+
}
|
|
157
|
+
}), u.__H = void 0, r && n.__e(r, u.__v));
|
|
158
|
+
};
|
|
159
|
+
var g = "function" == typeof requestAnimationFrame;
|
|
160
|
+
function j(n) {
|
|
161
|
+
var t,
|
|
162
|
+
r = function () {
|
|
163
|
+
clearTimeout(u), g && cancelAnimationFrame(t), setTimeout(n);
|
|
164
|
+
},
|
|
165
|
+
u = setTimeout(r, 100);
|
|
166
|
+
g && (t = requestAnimationFrame(r));
|
|
167
|
+
}
|
|
168
|
+
function k(n) {
|
|
169
|
+
var t = r,
|
|
170
|
+
u = n.__c;
|
|
171
|
+
"function" == typeof u && (n.__c = void 0, u()), r = t;
|
|
172
|
+
}
|
|
173
|
+
function w(n) {
|
|
174
|
+
var t = r;
|
|
175
|
+
n.__c = n.__(), r = t;
|
|
176
|
+
}
|
|
177
|
+
function z(n, t) {
|
|
178
|
+
return !n || n.length !== t.length || t.some(function (t, r) {
|
|
179
|
+
return t !== n[r];
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
function B(n, t) {
|
|
183
|
+
return "function" == typeof t ? t(n) : t;
|
|
184
|
+
}
|
|
185
|
+
export { T as useCallback, q as useContext, x as useDebugValue, h as useEffect, P as useErrorBoundary, V as useId, A as useImperativeHandle, s as useLayoutEffect, F as useMemo, y as useReducer, _ as useRef, p as useState };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { notificationAPIDetected } from "./notification_context.js";
|
|
2
|
+
import { notificationsEnabledSignal, notificationPermissionSignal } from "./notification_signals.js";
|
|
3
|
+
export const enableNotifications = () => {
|
|
4
|
+
notificationsEnabledSignal.value = true;
|
|
5
|
+
};
|
|
6
|
+
export const disableNotifications = () => {
|
|
7
|
+
notificationsEnabledSignal.value = false;
|
|
8
|
+
};
|
|
9
|
+
const arrayOfOpenedNotifications = [];
|
|
10
|
+
export const notify = notificationAPIDetected ? async (title, {
|
|
11
|
+
clickToFocus = false,
|
|
12
|
+
clickToClose = false,
|
|
13
|
+
...options
|
|
14
|
+
} = {}) => {
|
|
15
|
+
const notificationsEnabled = notificationsEnabledSignal.value;
|
|
16
|
+
if (!notificationsEnabled) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
if (Notification.permission !== "granted") {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
const notification = new Notification(title, options);
|
|
23
|
+
arrayOfOpenedNotifications.push(notification);
|
|
24
|
+
notification.onclick = () => {
|
|
25
|
+
// but if the user navigated inbetween
|
|
26
|
+
// focusing window will show something else
|
|
27
|
+
// in that case it could be great to do something
|
|
28
|
+
// maybe like showing a message saying this execution
|
|
29
|
+
// is no longer visible
|
|
30
|
+
// we could also navigauate to this file execution but
|
|
31
|
+
// there is no guarantee re-executing the file would give same output
|
|
32
|
+
// and it would also trigger an other notification
|
|
33
|
+
if (clickToFocus) window.focus();
|
|
34
|
+
if (clickToClose) notification.close();
|
|
35
|
+
};
|
|
36
|
+
notification.onclose = () => {
|
|
37
|
+
const index = arrayOfOpenedNotifications.indexOf(notification);
|
|
38
|
+
if (index > -1) {
|
|
39
|
+
arrayOfOpenedNotifications.splice(index, 1);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
return notification;
|
|
43
|
+
} : () => {};
|
|
44
|
+
export const closeAllNotifications = () => {
|
|
45
|
+
// slice because arrayOfOpenedNotifications can be mutated while looping
|
|
46
|
+
arrayOfOpenedNotifications.slice().forEach(notification => {
|
|
47
|
+
notification.close();
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
let requestPromise;
|
|
51
|
+
export const requestPermission = notificationAPIDetected ? async () => {
|
|
52
|
+
if (requestPromise) {
|
|
53
|
+
await requestPromise;
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
requestPromise = Notification.requestPermission();
|
|
57
|
+
await requestPromise;
|
|
58
|
+
requestPromise = undefined;
|
|
59
|
+
notificationPermissionSignal.value = Notification.permission;
|
|
60
|
+
} : () => Promise.resolve();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const notificationAPIDetected = typeof window.Notification === "function";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { effect } from "./signals.mjs";
|
|
2
|
+
import { notificationsEnabledSignal } from "./notification_signals.js";
|
|
3
|
+
import { closeAllNotifications } from "./notification_actions.js";
|
|
4
|
+
effect(() => {
|
|
5
|
+
const notificationsEnabled = notificationsEnabledSignal.value;
|
|
6
|
+
if (!notificationsEnabled) {
|
|
7
|
+
closeAllNotifications();
|
|
8
|
+
}
|
|
9
|
+
});
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { signal } from "./signals.mjs";
|
|
2
|
+
import { paramsFromParentWindow } from "./parent_window_context.js";
|
|
3
|
+
import { stateFromLocalStorage } from "./toolbar_state_context.js";
|
|
4
|
+
export const notificationsEnabledSignal = signal(typeof stateFromLocalStorage.notificationsEnabled === "boolean" ? stateFromLocalStorage.notificationsEnabled : typeof paramsFromParentWindow.notificationsEnabled === "boolean" ? paramsFromParentWindow.notificationsEnabled : false);
|
|
5
|
+
export const notificationPermissionSignal = signal(Notification.permission);
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { parentWindowReloader } from "./parent_window_context.js";
|
|
2
|
+
export const sendEventToParent = (name, data) => {
|
|
3
|
+
window.parent.postMessage({
|
|
4
|
+
__jsenv__: {
|
|
5
|
+
event: name,
|
|
6
|
+
data
|
|
7
|
+
}
|
|
8
|
+
}, "*");
|
|
9
|
+
};
|
|
10
|
+
export const addExternalCommandCallback = (command, callback) => {
|
|
11
|
+
const messageEventCallback = messageEvent => {
|
|
12
|
+
const {
|
|
13
|
+
data
|
|
14
|
+
} = messageEvent;
|
|
15
|
+
if (typeof data !== "object") {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const {
|
|
19
|
+
__jsenv__
|
|
20
|
+
} = data;
|
|
21
|
+
if (!__jsenv__) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
if (__jsenv__.command !== command) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
callback(...__jsenv__.args);
|
|
28
|
+
};
|
|
29
|
+
window.addEventListener("message", messageEventCallback);
|
|
30
|
+
return () => {
|
|
31
|
+
window.removeEventListener("message", messageEventCallback);
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
export const enableAutoreload = () => {
|
|
35
|
+
parentWindowReloader.autoreload.enable();
|
|
36
|
+
};
|
|
37
|
+
export const disableAutoreload = () => {
|
|
38
|
+
parentWindowReloader.autoreload.disable();
|
|
39
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export const paramsFromParentWindow = {};
|
|
2
|
+
const searchParams = new URLSearchParams(window.location.search);
|
|
3
|
+
searchParams.forEach((value, key) => {
|
|
4
|
+
paramsFromParentWindow[key] = value === "" ? true : value;
|
|
5
|
+
});
|
|
6
|
+
export const parentWindowReloader = window.parent.__reloader__;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { addExternalCommandCallback, sendEventToParent } from "./parent_window_actions.js";
|
|
2
|
+
import { animationsEnabledSignal } from "./animation_signals.js";
|
|
3
|
+
import { initToolbarUI } from "./toolbar_ui.js";
|
|
4
|
+
addExternalCommandCallback("initToolbar", () => {
|
|
5
|
+
// for the first render, force disable animations
|
|
6
|
+
const animationsEnabled = animationsEnabledSignal.value;
|
|
7
|
+
if (animationsEnabled) {
|
|
8
|
+
animationsEnabledSignal.value = false;
|
|
9
|
+
}
|
|
10
|
+
initToolbarUI();
|
|
11
|
+
if (animationsEnabled) {
|
|
12
|
+
animationsEnabledSignal.value = true;
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
sendEventToParent("toolbar_ready");
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { signal } from "./signals.mjs";
|
|
2
|
+
import { paramsFromParentWindow, parentWindowReloader } from "./parent_window_context.js";
|
|
3
|
+
export const autoreloadEnabledSignal = signal(false);
|
|
4
|
+
export const reloaderStatusSignal = signal("idle");
|
|
5
|
+
export const changesSignal = signal(0);
|
|
6
|
+
if (parentWindowReloader) {
|
|
7
|
+
if (!parentWindowReloader.autoreload.enabled && paramsFromParentWindow.autoreload) {
|
|
8
|
+
autoreloadEnabledSignal.value = true;
|
|
9
|
+
} else {
|
|
10
|
+
autoreloadEnabledSignal.value = parentWindowReloader.autoreload.enabled;
|
|
11
|
+
}
|
|
12
|
+
parentWindowReloader.autoreload.onchange = () => {
|
|
13
|
+
autoreloadEnabledSignal.value = parentWindowReloader.autoreload.enabled;
|
|
14
|
+
};
|
|
15
|
+
reloaderStatusSignal.value = parentWindowReloader.status.value;
|
|
16
|
+
const onchange = parentWindowReloader.status.onchange;
|
|
17
|
+
parentWindowReloader.status.onchange = () => {
|
|
18
|
+
onchange();
|
|
19
|
+
reloaderStatusSignal.value = parentWindowReloader.status.value;
|
|
20
|
+
};
|
|
21
|
+
changesSignal.value = parentWindowReloader.changes.value;
|
|
22
|
+
parentWindowReloader.changes.onchange = () => {
|
|
23
|
+
changesSignal.value = [...parentWindowReloader.changes.value];
|
|
24
|
+
};
|
|
25
|
+
}
|