blob: ab34e4ce76b3aa86ff181bf0fe0ec5906e2bd826 [file] [log] [blame]
gio1bf00802024-08-17 12:31:41 +04001function showTooltip(obj) {
2 obj.style.visibility = 'visible';
3 obj.style.opacity = '1';
4}
5function hideTooltip(obj) {
6 obj.style.visibility = 'hidden';
7 obj.style.opacity = '0';
8}
9
10document.addEventListener("DOMContentLoaded", function () {
11 document.getElementById('appFrame-default').contentDocument.write("Welcome to the dodo: application launcher, think of it as your desktop environment. You can launch applications from left-hand side dock. You should setup VPN clients on your devices, so you can install applications from Application Manager and access your private network. Instructions on how to do that can be viewed by clicking <b>Help</b> button after hovering over <b>Headscale</b> icon in the dock.");
12 document.getElementById('appFrame-default').style.backgroundColor = '#d6d6d6';
13 initDock();
14 setTimeout(reloadDock, 5000);
15});
16
17function copyToClipboard(elem, text) {
18 navigator.clipboard.writeText(text);
19 elem.setAttribute("data-tooltip", "Copied");
20 elem.setAttribute("data-placement", "bottom");
21 setTimeout(() => {
22 elem.removeAttribute("data-tooltip");
23 elem.removeAttribute("data-placement");
24 }, 500);
25};
26
27function reloadDock() {
28 fetch("/")
29 .then((resp) => {
30 if (resp.ok) {
31 return resp.text();
32 } else {
33 return undefined;
34 }
35 })
36 .then((resp) => {
37 if (!resp) {
38 return;
39 }
40 const tmp = document.createElement("div");
41 tmp.innerHTML = resp;
42 const apps = document.querySelector(".app-list");
43 let existing = [...document.querySelectorAll(".app-container")];
44 let current = [...tmp.querySelectorAll(".app-container")];
45 const getId = (e) => e.getAttribute("id");
46 const existingIds = existing.map(getId);
47 const currentIds = current.map(getId);
48 existing.forEach((e) => {
49 const id = getId(e);
50 if (!currentIds.includes(id)) {
51 e.classList.add("fadeout");
52 setTimeout(() => apps.removeChild(e), 1900);
53 }
54 });
55 let prevId = undefined;
56 current.forEach((c) => {
57 const id = getId(c);
58 if (existingIds.includes(id)) {
59 prevId = id;
60 return;
61 }
62 c.classList.add("pulsate");
63 if (prevId) {
64 apps.insertBefore(c, document.getElementById(prevId).nextSibling);
65 } else {
66 apps.insertBefore(c, apps.firstChild);
67 }
68 prevId = id;
69 });
70 initDock();
71 })
72 .finally(() => setTimeout(reloadDock, 5000));
73}
74
75function initDock() {
76 const icons = document.querySelectorAll(".app-icon");
77 const circle = document.querySelector(".user-circle");
78 const tooltipUser = document.querySelector("#tooltip-user");
79 const initial = document.getElementById('user-initial');
80
81 circle.addEventListener('mouseenter', () => {
82 icons.forEach(icon => {
83 const tooltip = icon.nextElementSibling;
84 hideTooltip(tooltip);
85 });
86 showTooltip(tooltipUser);
87 initial.style.color = "#7f9f7f";
88 });
89
90 circle.addEventListener('mouseleave', () => {
91 hideTooltip(tooltipUser);
92 initial.style.color = "#d4888d";
93 });
94
95 let hideTimeout;
96 let activeTooltip;
97
98 icons.forEach(function (icon) {
99 if (activeAppId && icon.getAttribute("data-app-id") === activeAppId) {
100 icon.style.color = "var(--button)";
101 }
102 icon.addEventListener("click", function (event) {
103 event.stopPropagation();
104 const appUrl = this.getAttribute("data-app-url");
105 const appId = this.getAttribute("data-app-id");
106 const modalId = this.getAttribute("data-modal-id");
107
108 if (!appUrl && modalId) {
109 openModal(document.getElementById(modalId));
110 } else {
111 if (!iframes[appId]) {
112 createIframe(appId, appUrl);
113 }
114 activeAppId = appId;
115 showIframe(appId);
116 document.querySelectorAll(".app-icon").forEach((icon) => {
117 icon.style.color = "var(--bodyBg)";
118 });
119 this.style.color = "var(--button)";
120 };
121 });
122
123 const tooltip = icon.nextElementSibling;
124 [
125 ['mouseenter', () => {
126 clearTimeout(hideTimeout);
127 if (activeTooltip && activeTooltip !== tooltip) {
128 hideTooltip(activeTooltip);
129 };
130 const rect = icon.getBoundingClientRect();
131 tooltip.style.top = `${rect.top + 26}px`;
132 showTooltip(tooltip);
133 activeTooltip = tooltip;
134 }],
135 ['mouseleave', () => {
136 hideTimeout = setTimeout(() => {
137 hideTooltip(tooltip);
138 if (activeTooltip === tooltip) {
139 activeTooltip = null;
140 };
141 }, 200);
142 }],
143 ].forEach(([event, listener]) => {
144 icon.addEventListener(event, listener);
145 });
146
147 tooltip.addEventListener('mouseenter', () => {
148 clearTimeout(hideTimeout);
149 });
150
151 tooltip.addEventListener('mouseleave', () => {
152 hideTimeout = setTimeout(() => {
153 hideTooltip(tooltip);
154 if (activeTooltip === tooltip) {
155 activeTooltip = null;
156 };
157 }, 200);
158 });
159 });
160
161 let visibleModal = undefined;
162 const openModal = function (modal) {
163 modal.removeAttribute("close");
164 modal.setAttribute("open", true);
165 visibleModal = modal;
166 };
167
168 const closeModal = function (modal) {
169 modal.removeAttribute("open");
170 modal.setAttribute("close", true);
171 visibleModal = undefined;
172 };
173
174 const helpButtons = document.querySelectorAll('.help-button');
175
176 helpButtons.forEach(function (button) {
177 button.addEventListener('click', function (event) {
178 event.stopPropagation();
179 const buttonId = button.getAttribute('id');
180 const modalId = 'modal-' + buttonId.substring("help-button-".length);
181 const closeHelpId = "close-help-" + buttonId.substring("help-button-".length);
182 const modal = document.getElementById(modalId);
183 openModal(modal);
184 const closeHelpButton = document.getElementById(closeHelpId);
185 closeHelpButton.addEventListener('click', function (event) {
186 event.stopPropagation();
187 closeModal(modal);
188 });
189 });
190 });
191
192 const modalHelpButtons = document.querySelectorAll('.title-menu');
193
194 modalHelpButtons.forEach(function (button) {
195 button.addEventListener('click', function (event) {
196 event.stopPropagation();
197 const helpTitle = button.getAttribute('id');
198 const helpTitleId = helpTitle.substring('title-'.length);
199 const helpContentId = 'help-content-' + helpTitleId;
200 let clDiv = document.getElementById(helpContentId).parentNode;
201 const allContentElements = clDiv.querySelectorAll('.help-content');
202
203 allContentElements.forEach(function (contentElement) {
204 contentElement.style.display = "none";
205 });
206
207 let currentHelpTitle = button;
208 while (currentHelpTitle && !currentHelpTitle.classList.contains('modal-left')) {
209 currentHelpTitle = currentHelpTitle.parentNode;
210 if (currentHelpTitle === document.body) {
211 currentHelpTitle = null;
212 break;
213 }
214 }
215
216 currentHelpTitle.querySelectorAll('.title-menu').forEach(function (button) {
217 button.removeAttribute("aria-current");
218 });
219
220 document.getElementById(helpContentId).style.display = 'block';
221 button.setAttribute("aria-current", "page");
222 });
223 });
224
225 document.addEventListener("keydown", (event) => {
226 if (event.key === "Escape" && visibleModal) {
227 closeModal(visibleModal);
228 }
229 });
230
231 document.addEventListener("click", (event) => {
232 if (visibleModal === null || visibleModal === undefined) return;
233 const modalContent = visibleModal.querySelector("article");
234 const closeButton = visibleModal.querySelector(".close-button");
235 if (!modalContent.contains(event.target) || closeButton.contains(event.target)) {
236 closeModal(visibleModal);
237 }
238 });
239}
240
241let activeAppId = undefined;
242const iframes = {};
243const rightPanel = document.getElementById('right-panel');
244
245function showIframe(appId) {
246 document.querySelectorAll('.appFrame').forEach(iframe => {
247 iframe.style.display = iframe.id === `appFrame-${appId}` ? 'block' : 'none';
248 });
249};
250
251function createIframe(appId, appUrl) {
252 const iframe = document.createElement('iframe');
253 iframe.id = `appFrame-${appId}`;
254 iframe.className = 'appFrame';
255 iframe.src = appUrl;
256 iframe.style.display = 'none';
257 rightPanel.appendChild(iframe);
258 iframes[appId] = iframe;
259};