Passed
Push — master ( f3902d...24613b )
by EMP
04:19
created

modern/main.js   F

Complexity

Total Complexity 364
Complexity/F 2.46

Size

Lines of Code 1787
Function Count 148

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1216
dl 0
loc 1787
rs 0.8
c 0
b 0
f 0
wmc 364
mnd 216
bc 216
fnc 148
bpm 1.4594
cpm 2.4594
noi 13

32 Functions

Rating   Name   Duplication   Size   Complexity  
A main.js ➔ MsgInfo 0 5 1
B main.js ➔ TabState 0 6 8
A main.js ➔ getCountryFlag 0 6 2
A main.js ➔ clearDisplay 0 10 3
A main.js ➔ getClockIcon 0 17 5
C main.js ➔ errorDialog 0 33 11
A main.js ➔ updateAddressCounts 0 11 3
A main.js ➔ updateLimits 0 16 3
F main.js ➔ displayExport 0 19 14
F main.js ➔ displayMsg 0 193 46
F main.js ➔ showFiles 0 134 32
A main.js ➔ writeVerify 0 27 4
F main.js ➔ deleteAddress 0 44 14
B main.js ➔ addOwnAccount 0 51 8
D main.js ➔ setTab 0 78 12
F main.js ➔ showInbox 0 56 16
A main.js ➔ clearWrite 0 12 2
A main.js ➔ adjustLevel 0 14 3
A main.js ➔ addContact 0 30 2
B main.js ➔ addAddress 0 64 5
A main.js ➔ updateAddressButtons 0 5 1
A main.js ➔ refreshContactList 0 17 3
B main.js ➔ addAccountToTable 0 40 7
C main.js ➔ showDrbox 0 56 11
A main.js ➔ reloadAccount 0 10 1
B main.js ➔ addressCreate 0 24 8
A main.js ➔ addContacts 0 11 2
A main.js ➔ addAddresses 0 5 2
A main.js ➔ setRowsPerPage 0 8 1
F main.js ➔ displayFile 0 124 16
B main.js ➔ displayOutMsg 0 52 5
C main.js ➔ addMsg 0 42 9

How to fix   Complexity   

Complexity

Complex classes like modern/main.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
"use strict";
2
3
sodium.ready.then(function() {
4
5
let isReady = true;
6
7
let vaultPage = -4;
8
const vault = new PostVault(function(ok) {
0 ignored issues
show
Bug introduced by
The variable PostVault seems to be never declared. If this is a global, consider adding a /** global: PostVault */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
9
	if (ok) vaultPage = -3;
10
});
11
12
const ae = new AllEars(function(ok) {
13
	if (!ok) {
14
		document.getElementById("greeting").textContent = "Failed loading All-Ears";
15
		return;
16
	}
17
18
	try {
19
		if (localStorage.greeting) {
20
			document.getElementById("greeting").textContent = localStorage.greeting;
21
			document.getElementById("txt_pg").value = localStorage.greeting;
22
		} else localStorage.greeting = document.getElementById("greeting").textContent;
23
	} catch(e) {
24
		document.getElementById("btn_pg").disabled = true;
25
		document.getElementById("txt_pg").disabled = true;
26
		document.getElementById("txt_pg").className = "ita";
27
		document.getElementById("txt_pg").value = "LocalStorage inaccessible";
28
	}
29
30
	document.getElementById("txt_umk").maxLength = "60";
31
});
32
33
function TabState(cur, max, btnDele, btnUpdt) {
34
	this.cur = cur;
35
	this.max = max;
36
	this.btnDele = btnDele;
37
	this.btnUpdt = btnUpdt;
38
}
39
40
const tabs = [
41
	new TabState(0, 0, false, true), // Inbox
42
	new TabState(0, 0, false, false), // Outbx
43
	new TabState(0, 1, true,  false), // Write
44
	new TabState(0, 2, false, false), // Notes
45
	new TabState(0, 2, false, false) // Tools
46
];
47
48
function MsgInfo(msgId, msgType, msgNum) {
49
	this.id = msgId;
50
	this.type = msgType;
51
	this.num = msgNum;
52
}
53
54
let msgDisplay = new MsgInfo(null, null, null);
55
let showHeaders = false;
56
let rowsPerPage = 0;
57
58
let tab = 0;
59
const TAB_INBOX = 0;
60
const TAB_DRBOX = 1;
61
const TAB_WRITE = 2;
62
const TAB_NOTES = 3;
63
const TAB_TOOLS = 4;
64
65
function errorDialog(err, focusAfter) {
66
	if (typeof(err) !== "number" || err < 1) return;
67
68
	let btnDisable = [];
69
	const buttons = document.querySelectorAll("nav > button");
70
	buttons.forEach(function(btn) {
71
		btnDisable.push(btn.disabled);
72
		btn.disabled = true;
73
	});
74
75
	const errMsg = ae.getErrorMessage(err);
76
77
	const dlg = document.querySelector("dialog");
78
	dlg.children[0].style.height = getComputedStyle(document.querySelector("#main1 > div[class='mid']")).height;
79
	dlg.querySelector("h1").textContent = "ERROR " + ((err >= 400) ? err : ("0x" + err.toString(16).padStart(2, "0").toUpperCase()));
80
	dlg.querySelector("p").textContent = (typeof(errMsg) === "string") ? errMsg : errMsg[1];
81
	dlg.show();
82
83
	document.querySelector("dialog > div").onclick = function() {
84
		buttons.forEach(function(btn, i) {btn.disabled = btnDisable[i];});
85
		dlg.close();
86
		if (focusAfter) focusAfter.focus();
87
	};
88
89
	document.onkeyup = function(event) {
90
		document.onkeyup = null;
91
		event.preventDefault();
92
93
		buttons.forEach(function(btn, i) {btn.disabled = btnDisable[i];});
94
		dlg.close();
95
		if (focusAfter) focusAfter.focus();
96
	};
97
}
98
99
function getCountryFlag(countryCode) {
100
	return (!countryCode || countryCode.length !== 2 || countryCode === "??") ? "❔" : sodium.to_string(new Uint8Array([
101
		240, 159, 135, 166 + countryCode.codePointAt(0) - 65,
102
		240, 159, 135, 166 + countryCode.codePointAt(1) - 65
103
	]));
104
}
105
106
function getClockIcon(d) {
107
	const h24 = d.getUTCHours();
108
	let h12 = (h24 === 0 ? 12 : ((h24 > 12) ? h24 - 12 : h24));
109
110
	const m60 = (d.getUTCMinutes() * 60) + d.getUTCSeconds();
111
	let m30 = 0;
112
	if (m60 <= 900) { // <= 15: round down to this hour
113
		m30 = 0;
114
	} else if (m60 > 900 && m60 < 2700) { // 15..45: round to half-past this hour
115
		m30 = 12;
116
	} else { // >= 45: round up to next hour
117
		h12++;
118
		m30 = 0;
119
	}
120
121
	return String.fromCodePoint((128335 + h12) + m30);
122
}
123
124
function clearDisplay() {
125
	document.getElementById("btn_mnext").disabled = true;
126
	document.getElementById("btn_mprev").disabled = true;
127
	document.getElementById("readmsg_export").hidden = true;
128
129
	const el = document.querySelector("#readmsg_main > img, #readmsg_main > audio, #readmsg_main > video, #readmsg_main > embed, #readmsg_main > iframe");
130
	if (!el) return;
131
	if (el.src) URL.revokeObjectURL(el.src);
132
	el.remove();
133
}
134
135
/*
136
function addMsgFlag(abbr, abbrTitle) {
137
	const parent = document.getElementById("readmsg_flags").children[0];
138
139
	const el = document.createElement("abbr");
140
	el.title = abbrTitle;
141
	el.textContent = abbr;
142
143
	parent.appendChild(document.createTextNode(" "));
144
	parent.appendChild(el);
145
}
146
*/
147
148
function displayFile(isHistory, num, showNext) {
149
	if (num < 0 || num >= ae.getUplMsgCount()) return;
0 ignored issues
show
Comprehensibility Best Practice introduced by
Are you sure this return statement is not missing an argument? If this is intended, consider adding an explicit undefined like return undefined;.
Loading history...
150
151
	const fileType = ae.getUplMsgType(num);
152
	if (!fileType) {
153
		if (isHistory) return;
0 ignored issues
show
Comprehensibility Best Practice introduced by
Are you sure this return statement is not missing an argument? If this is intended, consider adding an explicit undefined like return undefined;.
Loading history...
154
		if (showNext === true) return displayFile(false, num + 1, true);
155
		if (showNext === false) return displayFile(false, num - 1, false);
156
		ae.downloadUplMsg(num); return;
0 ignored issues
show
Comprehensibility Best Practice introduced by
Are you sure this return statement is not missing an argument? If this is intended, consider adding an explicit undefined like return undefined;.
Loading history...
157
	}
158
159
	clearDisplay();
160
	document.querySelector("article").scroll(0, 0);
161
	document.querySelector("article").setAttribute("data-msgid", ae.getUplMsgId(num));
162
163
	document.getElementById("btn_mdele").disabled = false;
164
	document.getElementById("btn_msave").disabled = false;
165
	document.getElementById("btn_reply").disabled = true;
166
167
	document.getElementById("btn_msave").onclick = function() {ae.downloadUplMsg(num);};
168
169
	document.getElementById("readmsg_info").hidden = true;
170
	document.getElementById("readmsg_dkim").hidden = true;
171
	document.querySelector("#readmsg_main > h1").textContent = ae.getUplMsgTitle(num);
172
173
	msgDisplay = new MsgInfo(ae.getUplMsgId(num), "upl", num);
174
	if (!isHistory) history.pushState({tab: tab, page: tabs[tab].cur, msg: msgDisplay}, null);
175
176
	document.getElementById("main2").hidden = false;
177
	document.getElementById("main1").hidden = !window.matchMedia("(min-width: 80em)").matches;
178
179
	document.getElementById("btn_mnext").disabled = (num === ae.getUplMsgCount() - 1);
180
	document.getElementById("btn_mprev").disabled = (num === 0);
181
	document.getElementById("btn_mnext").onclick = function() {displayFile(false, num + 1, true);};
182
	document.getElementById("btn_mprev").onclick = function() {displayFile(false, num - 1, false);};
183
184
	if (fileType === "text") {
185
		document.querySelector("#readmsg_main > pre").hidden = false;
186
		try {
187
			document.querySelector("#readmsg_main > pre").textContent = sodium.to_string(ae.getUplMsgBody(num));
188
		} catch(e) {
189
			document.querySelector("#readmsg_main > pre").textContent = "Failed decoding body: " + e.message;
190
		}
191
		return;
0 ignored issues
show
Comprehensibility Best Practice introduced by
Are you sure this return statement is not missing an argument? If this is intended, consider adding an explicit undefined like return undefined;.
Loading history...
192
	}
193
194
	document.querySelector("#readmsg_main > pre").hidden = true;
195
	let el;
196
197
	switch (fileType) {
198
		case "image": {
199
			el = document.createElement("img");
200
			el.src = URL.createObjectURL(new Blob([ae.getUplMsgBody(num).buffer]));
201
			el.onclick = function() {
202
				if (!document.fullscreen)
203
					this.requestFullscreen();
204
				else
205
					document.exitFullscreen();
206
			};
207
		break;}
208
209
		case "audio":
210
		case "video": {
211
			el = document.createElement(fileType);
212
			el.controls = "controls";
213
			el.src = URL.createObjectURL(new Blob([ae.getUplMsgBody(num).buffer]));
214
		break;}
215
216
		case "pdf": {
217
			el = document.createElement("embed");
218
			el.type = "application/pdf";
219
			el.src = URL.createObjectURL(new Blob([ae.getUplMsgBody(num).buffer], {type: "application/pdf"}));
220
		break;}
221
222
		case "html": {
223
			el = document.createElement("iframe");
224
			el.allow = "vertical-scroll";
225
			el.sandbox = "";
226
			el.referrerPolicy = "no-referrer";
227
228
			try {
229
				const sanBody = document.createElement("body");
230
				sanBody.setHTML(sodium.to_string(ae.getUplMsgBody(num).buffer), {sanitizer: new Sanitizer({
0 ignored issues
show
Bug introduced by
The variable Sanitizer seems to be never declared. If this is a global, consider adding a /** global: Sanitizer */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
231
					"allowElements": [
232
						"a","div","p",
233
						"h1","h2","h3","h4","h5","h6",
234
						"em","strong","b","i","u"
235
					],
236
					"allowAttributes": {
237
						"href": ["*"]
238
					}
239
				})});
240
241
				el.srcdoc =
242
				"<!doctype html><html>" +
243
					"<head>" +
244
						"<style>" +
245
							"html, body {background: #080a08; color: #fff; scrollbar-color: #222 #333;}\n" +
246
							"body {opacity:0.55;}\n" +
247
							"body > *:first-child {margin-top: 0; padding-top: 0;}\n" +
248
							"a {color: #fff;}\n" +
249
							"button, input, select, textarea {background: #000; color: #fff;}\n" +
250
						"</style>" +
251
					"</head>" +
252
					sanBody.outerHTML +
253
				"</html>";
254
			} catch(e) {
255
				el.srcdoc = "<!doctype html><html><head><style>body {background: #080a08; color: #fff; opacity:0.55;} h1 {margin: 0;}</style><body><h1>Error</h1><p>" + e.message + "</p></body></html>";
256
			}
257
		break;}
258
259
		case "svg": {
260
			el = document.createElement("iframe");
261
			el.allow = "";
262
			el.sandbox = "";
263
			el.referrerPolicy = "no-referrer";
264
			el.srcdoc = "<!doctype><html><head><style>body,html,svg {margin: 0; padding: 0; border: 0; height: 100%; width: 100%; display: block; background: #080a08;}</style></head><body>" + sodium.to_string(ae.getUplMsgBody(num).buffer) + "</body></html>";
265
		break;}
266
267
		default: return;
0 ignored issues
show
Comprehensibility Best Practice introduced by
Are you sure this return statement is not missing an argument? If this is intended, consider adding an explicit undefined like return undefined;.
Loading history...
268
	}
269
270
	document.getElementById("readmsg_main").appendChild(el);
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
271
}
272
273
function displayMsg(isHistory, isInt, num) {
274
	clearDisplay();
275
	document.getElementById("btn_mdele").disabled = false;
276
277
	document.querySelector("article").scroll(0, 0);
278
	document.querySelector("article").setAttribute("data-msgid", isInt? ae.getIntMsgId(num) : ae.getExtMsgId(num));
279
280
	document.getElementById("btn_msave").disabled = false;
281
	document.getElementById("btn_msave").onclick = function() {displayExport(false, isInt, num);};
282
283
	const ts = isInt? ae.getIntMsgTime(num) : ae.getExtMsgTime(num);
284
285
	if (!isInt || (ae.getIntMsgFrom(num) !== "public" && ae.getIntMsgFrom(num) !== "system")) {
286
		document.getElementById("btn_reply").disabled = false;
287
288
		document.getElementById("btn_reply").onclick = function() {
289
			document.getElementById("write_recv").value = isInt? ae.getIntMsgFrom(num) : ae.getExtMsgReplyAddress(num);
290
			document.getElementById("write_subj").value = isInt? ae.getIntMsgTitle(num) : ae.getExtMsgTitle(num);
291
			if (!document.getElementById("write_subj").value.startsWith("Re:")) document.getElementById("write_subj").value = "Re: " + document.getElementById("write_subj").value;
292
			document.querySelector("#write2_pkey > input").value = isInt? ae.getIntMsgApk(num) : "";
293
294
			document.getElementById("write_recv").readOnly = !isInt;
295
			document.getElementById("write_subj").readOnly = !isInt;
296
			document.getElementById("write_subj").setAttribute("data-replyid", isInt? "" : ae.getExtMsgHdrId(num));
297
298
			tabs[TAB_WRITE].cur = 0;
299
			document.getElementById("btn_write").disabled = false;
300
			document.getElementById("btn_write").click();
301
			document.getElementById("write_body").focus();
302
303
			for (const opt of document.getElementById("write_from").options) {
304
				if (opt.value === (isInt ? ae.getIntMsgTo(num) : ae.getExtMsgEnvTo(num).split("@")[0].toLowerCase())) {
305
					opt.selected = true;
306
				}
307
			}
308
		};
309
	} else {
310
		document.getElementById("btn_reply").disabled = true;
311
	}
312
313
	document.getElementById("readmsg_info").hidden = false;
314
	document.querySelector("#readmsg_main > pre").hidden = false;
315
316
	document.getElementById("readmsg_envto").textContent = isInt ? "" : ae.getExtMsgEnvTo(num);
317
	document.getElementById("readmsg_hdrto").textContent = isInt ? ae.getIntMsgTo(num) : (ae.getExtMsgHdrTo(num));
318
	if(!isInt && ae.getExtMsgDnTo(num)) {
319
		const span = document.createElement("span");
320
		span.className = "sans";
321
		span.textContent = " • " + ae.getExtMsgDnTo(num);
322
		document.getElementById("readmsg_hdrto").appendChild(span);
323
	}
324
325
	const tzOs = new Date().getTimezoneOffset();
326
	const msgDate = new Date((ts * 1000) + (tzOs * -60000));
327
	document.getElementById("readmsg_date").children[0].textContent = getClockIcon(msgDate);
328
	document.getElementById("readmsg_date").children[1].dateTime = new Date(ts * 1000).toISOString();
329
330
	if (isInt) {
331
		document.getElementById("readmsg_dkim").hidden = true;
332
333
		document.querySelector("#readmsg_main > h1").textContent = ae.getIntMsgTitle(num);
334
		document.querySelector("#readmsg_main > pre").textContent = ae.getIntMsgBody(num);
335
336
		document.getElementById("readmsg_date").children[1].textContent = msgDate.toISOString().slice(0, 19).replace("T", " ");
337
338
		document.getElementById("readmsg_ip").style.visibility = "hidden";
339
		document.getElementById("readmsg_rdns").style.visibility = "hidden";
340
		document.getElementById("readmsg_greet").style.visibility = "hidden";
341
		document.getElementById("readmsg_cert").style.visibility = "hidden";
342
		document.getElementById("readmsg_envfrom").style.visibility = "hidden";
343
		document.getElementById("readmsg_envto").style.visibility = "hidden";
344
345
		if (ae.getIntMsgFrom(num) !== "system" && ae.getIntMsgFrom(num) !== "public") {
346
			document.getElementById("readmsg_tls").style.visibility = "visible";
347
			document.getElementById("readmsg_tls").children[0].textContent = ae.getIntMsgApk(num);
348
		} else document.getElementById("readmsg_tls").style.visibility = "hidden";
349
350
		let symbol = document.createElement("span");
351
		if      (ae.getIntMsgLevel(num) === 3 && ae.getIntMsgFrom(num) === "system") {symbol.title = "System message"; symbol.textContent = "🅢";}
352
		else if (ae.getIntMsgLevel(num) === 3 && ae.getIntMsgFrom(num) === "public") {symbol.title = "Public announcement"; symbol.textContent = "🅟";}
353
		else if (ae.getIntMsgLevel(num) === 3) {symbol.title = "Administrator"; symbol.textContent = "🅐";}
354
		else if (ae.getIntMsgLevel(num) === 2) {symbol.title = "Level 2";  symbol.textContent = "➋";}
355
		else if (ae.getIntMsgLevel(num) === 1) {symbol.title = "Level 1";  symbol.textContent = "➊";}
356
		else if (ae.getIntMsgLevel(num) === 0) {symbol.title = "Level 0";  symbol.textContent = "🄌";}
357
		else {symbol.title = "Invalid level"; symbol.textContent = "⚠";}
358
359
		document.getElementById("readmsg_hdrfrom").replaceChildren(symbol, document.createTextNode(" " + ae.getIntMsgFrom(num)));
360
361
//		if ( ae.getIntMsgFlagE2ee(num)) addMsgFlag("E2EE", "End-to-end encrypted");
362
	} else {
363
		const headers = document.createElement("p");
364
		headers.textContent = ae.getExtMsgHeaders(num);
365
		headers.className = "mono";
366
		headers.hidden = !showHeaders;
367
368
		const body = document.createElement("p");
369
		body.innerHTML = ae.getExtMsgBody(num, false);
370
371
		document.querySelector("#readmsg_main > pre").replaceChildren(headers, body);
372
373
		const h1 = document.querySelector("#readmsg_main > h1");
374
		h1.textContent = ae.getExtMsgTitle(num);
375
		h1.style.cursor = headers.textContent? "pointer" : "";
376
		h1.onclick = function() {
377
			if (!headers.textContent) return;
378
			showHeaders = !showHeaders;
379
			headers.hidden = !showHeaders;
380
		};
381
382
		let hdrSecs = Math.abs(ae.getExtMsgHdrTime(num));
383
		let hdrTime = "";
384
		if (hdrSecs >= 3600) {
385
			const hdrHours = Math.floor(hdrSecs / 3600);
386
			hdrTime += hdrHours.toString() + "h ";
387
			hdrSecs -= hdrHours * 3600;
388
		}
389
		if (hdrSecs >= 60) {
390
			const hdrMins = Math.floor(hdrSecs / 60);
391
			hdrTime += hdrMins.toString() + "m ";
392
			hdrSecs -= hdrMins * 60;
393
		}
394
		hdrTime += hdrSecs + "s";
395
396
		const hdrTz = (ae.getExtMsgHdrTz(num) >= 0 ? "+" : "-") + Math.floor(Math.abs(ae.getExtMsgHdrTz(num)) / 60).toString().padStart(2, "0") + (Math.abs(ae.getExtMsgHdrTz(num)) % 60).toString().padStart(2, "0");
397
398
		let spans = [document.createElement("span"), document.createElement("span"), document.createElement("span")];
399
		spans[0].textContent = msgDate.toISOString().slice(0, 19).replace("T", " ");
400
		spans[1].className = "sans";
401
		spans[1].textContent = " • ";
402
		spans[2].textContent = hdrTz + " " + ((ae.getExtMsgHdrTime(num) >= 0) ? "+" : "-") + hdrTime;
403
		document.getElementById("readmsg_date").children[1].replaceChildren(...spans);
404
405
		document.getElementById("readmsg_ip").style.visibility = "visible";
406
		document.getElementById("readmsg_rdns").style.visibility = "visible";
407
		document.getElementById("readmsg_greet").style.visibility = "visible";
408
		document.getElementById("readmsg_tls").style.visibility = "visible";
409
		document.getElementById("readmsg_cert").style.visibility = "visible";
410
		document.getElementById("readmsg_envfrom").style.visibility = "visible";
411
		document.getElementById("readmsg_envto").style.visibility = "visible";
412
413
		// DKIM
414
		if (ae.getExtMsgDkimCount(num) > 0) {
415
			document.getElementById("readmsg_dkim").hidden = false;
416
417
			document.querySelectorAll("#readmsg_dkim div").forEach(function(d, i) {
418
				if (i >= ae.getExtMsgDkimCount(num)) {
419
					d.textContent = "";
420
					return;
421
				}
422
				d.textContent = (ae.getExtMsgDkimValidSig(num, i) ? "OK" : "❌") + " " + ae.getExtMsgDkimAlgo(num, i) + " " + ae.getExtMsgDkimHeadHash(num, i) + "/" + ae.getExtMsgDkimBodyHash(num, i) + ": "
423
					+ (ae.getExtMsgDkimIdentity(num, i) ? (ae.getExtMsgDkimIdentity(num, i) + "|") : "") + ae.getExtMsgDkimDomain(num, i) + "|" + ae.getExtMsgDkimSelector(num, i)
424
					+ ((ae.getExtMsgDkimTs(num, i) > 0) ? (" @" + ae.getExtMsgDkimTs(num, i)) : "");
425
			});
426
		} else {
427
			document.getElementById("readmsg_dkim").hidden = true;
428
		}
429
430
		// Left side
431
		document.getElementById("readmsg_country").textContent = getCountryFlag(ae.getExtMsgCcode(num));
432
		document.getElementById("readmsg_country").title = ae.getExtMsgCname(num);
433
		document.getElementById("readmsg_ip").children[1].textContent = ae.getExtMsgIp(num) + (ae.getExtMsgFlagIpBl(num) ? " ❗" : "");
434
		document.getElementById("readmsg_ip").children[2].textContent = " • " + ae.getExtMsgAuSys(num);
435
		document.getElementById("readmsg_tls").children[0].textContent = ae.getExtMsgTLS(num);
436
437
		// Right side
438
		document.getElementById("readmsg_greet").children[0].textContent = ae.getExtMsgGreet(num) + (ae.getExtMsgFlagGrDm(num) ? " ✓" : "");
439
		document.getElementById("readmsg_rdns").children[0].textContent = ae.getExtMsgRdns(num) + (ae.getExtMsgGreet(num).toLowerCase() === ae.getExtMsgRdns(num).toLowerCase() ? " ✓" : "");
440
		document.getElementById("readmsg_cert").children[0].textContent = ae.getExtMsgTlsDomain(num) ? (ae.getExtMsgTlsDomain(num) + " ✓") : "";
441
		document.getElementById("readmsg_envfrom").textContent = ae.getExtMsgEnvFrom(num);
442
		document.getElementById("readmsg_hdrfrom").textContent = ae.getExtMsgHdrFrom(num);
443
		if (ae.getExtMsgDnFrom(num)) {
444
			const span = document.createElement("span");
445
			span.className = "sans";
446
			span.textContent = " • " + ae.getExtMsgDnFrom(num);
447
			document.getElementById("readmsg_hdrfrom").appendChild(span);
448
		}
449
450
/*
451
		clearMsgFlags();
452
		if (!ae.getExtMsgFlagPExt(num)) addMsgFlag("SMTP", "The sender did not use the Extended (ESMTP) protocol");
453
		if ( ae.getExtMsgFlagRare(num)) addMsgFlag("RARE", "The sender issued unusual command(s)");
454
		if ( ae.getExtMsgFlagFail(num)) addMsgFlag("FAIL", "The sender issued invalid command(s)");
455
		if ( ae.getExtMsgFlagPErr(num)) addMsgFlag("PROT", "The sender violated the protocol");
456
*/
457
	}
458
459
	document.getElementById("readmsg_main").hidden = false;
460
	document.getElementById("main2").hidden = false;
461
	document.getElementById("main1").hidden = !window.matchMedia("(min-width: 80em)").matches;
462
463
	msgDisplay = new MsgInfo(isInt? ae.getIntMsgId(num) : ae.getExtMsgId(num), isInt? "int" : "ext", num);
464
	if (!isHistory) history.pushState({tab: tab, page: tabs[tab].cur, msg: msgDisplay}, null);
465
}
466
467
function displayExport(isHistory, isInt, num) {
468
	clearDisplay();
469
	document.getElementById("readmsg_main").hidden = true;
470
	document.getElementById("readmsg_export").hidden = false;
471
	document.getElementById("btn_msave").blur();
472
	document.getElementById("btn_msave").disabled = true;
473
	document.getElementById("btn_reply").disabled = true;
474
	document.getElementById("btn_mdele").disabled = true;
475
476
//	document.querySelector("#readmsg_export > div:nth-child(1)").onclick = function() {};
477
	document.querySelector("#readmsg_export > div:nth-child(2)").onclick = function() {if (isInt) {ae.downloadIntMsg(num);} else {ae.downloadExtMsg(num);} displayMsg(false, isInt, num);};
478
	document.querySelector("#readmsg_export > div:nth-child(3)").onclick = function() {if (isInt) {ae.htmlIntMsg(num, true);} else {ae.htmlExtMsg(num, true);} displayMsg(false, isInt, num);};
479
	document.querySelector("#readmsg_export > div:nth-child(4)").onclick = function() {if (isInt) {ae.txtIntMsg(num, true);} else {ae.txtExtMsg(num, true);} displayMsg(false, isInt, num);};
480
	document.querySelector("#readmsg_export > div:nth-child(5)").onclick = function() {if (isInt) {ae.printIntMsg(num);} else {ae.printExtMsg(num);} displayMsg(false, isInt, num);};
481
	document.querySelector("#readmsg_export > div:nth-child(6)").onclick = function() {navigator.clipboard.writeText(isInt? ae.txtIntMsg(num, false) : ae.txtExtMsg(num, false)); displayMsg(false, isInt, num);};
482
483
	msgDisplay = new MsgInfo(isInt? ae.getIntMsgId(num) : ae.getExtMsgId(num), isInt? "int_exp" : "ext_exp", num);
484
	if (!isHistory) history.pushState({tab: tab, page: tabs[tab].cur, msg: msgDisplay}, null);
485
}
486
487
function displayOutMsg(isHistory, num) {
488
	clearDisplay();
489
	document.querySelector("article").scroll(0, 0);
490
	document.querySelector("article").setAttribute("data-msgid", ae.getOutMsgId(num));
491
492
	document.getElementById("btn_mdele").disabled = false;
493
	document.getElementById("btn_msave").disabled = true;
494
	document.getElementById("btn_reply").disabled = true;
495
496
	document.getElementById("readmsg_info").hidden = false;
497
	document.querySelector("#readmsg_main > pre").hidden = false;
498
499
	document.querySelector("#readmsg_main > h1").textContent = ae.getOutMsgSubj(num);
500
	document.querySelector("#readmsg_main > pre").textContent = ae.getOutMsgBody(num);
501
502
	document.getElementById("readmsg_hdrto").style.visibility   = "visible";
503
	document.getElementById("readmsg_hdrfrom").style.visibility = "visible";
504
	document.getElementById("readmsg_envto").style.visibility   = "visible";
505
	document.getElementById("readmsg_envfrom").style.visibility = "hidden";
506
507
	document.getElementById("readmsg_hdrfrom").textContent = ae.getOutMsgFrom(num);
508
509
	document.getElementById("readmsg_envto").textContent = ae.getOutMsgMxDom(num);
510
	document.getElementById("readmsg_hdrto").textContent = ae.getOutMsgTo(num);
511
512
	const ts = ae.getOutMsgTime(num);
513
	const tzOs = new Date().getTimezoneOffset();
514
	document.getElementById("readmsg_date").children[1].textContent = new Date((ts * 1000) + (tzOs * -60000)).toISOString().slice(0, 19).replace("T", " ");
515
516
	const isInt = ae.getOutMsgIsInt(num);
517
	document.getElementById("readmsg_ip").style.visibility    = isInt? "hidden" : "visible";
518
	document.getElementById("readmsg_rdns").style.visibility  = /*isInt?*/ "hidden" /*: "visible"*/; // TODO
519
	document.getElementById("readmsg_tls").style.visibility   = /*isInt?*/ "hidden" /*: "visible"*/; // TODO
520
	document.getElementById("readmsg_cert").style.visibility  = /*isInt?*/ "hidden" /*: "visible"*/; // TODO
521
	document.getElementById("readmsg_greet").style.visibility = isInt? "hidden" : "visible";
522
523
	if (!isInt) {
524
		document.getElementById("readmsg_ip").children[1].textContent = ae.getOutMsgIp(num);
525
		document.getElementById("readmsg_country").textContent = getCountryFlag(ae.getOutMsgCcode(num));
526
		document.getElementById("readmsg_country").title = ae.getOutMsgCname(num);
527
//		document.getElementById("readmsg_tls").children[0].textContent = ae.getOutMsgTLS(num);
528
		document.getElementById("readmsg_greet").children[0].textContent = ae.getOutMsgGreet(num);
529
	}
530
531
//	if ( ae.getOutMsgFlagE2ee(num)) addMsgFlag("E2EE", "End-to-end encrypted");
532
533
	document.getElementById("main2").hidden = false;
534
	document.getElementById("main1").hidden = !window.matchMedia("(min-width: 80em)").matches;
535
536
	msgDisplay = new MsgInfo(ae.getOutMsgId(num), "out", num);
537
	if (!isHistory) history.pushState({tab: tab, page: tabs[tab].cur, msg: msgDisplay}, null);
538
}
539
540
function updateAddressButtons() {
541
	const limitReached = (ae.getAddressCountNormal() + ae.getAddressCountShield() >= 31);
542
	document.getElementById("btn_address_create_normal").disabled = (limitReached || ae.getAddressCountNormal() >= ae.getLimitNormalA(ae.getOwnLevel()));
543
	document.getElementById("btn_address_create_shield").disabled = (limitReached || ae.getAddressCountShield() >= ae.getLimitShieldA(ae.getOwnLevel()));
544
}
545
546
function updateAddressCounts() {
547
	document.querySelector("#tbd_accs > tr > td:nth-child(3)").textContent = ae.getAddressCountNormal();
548
	document.querySelector("#tbd_accs > tr > td:nth-child(4)").textContent = ae.getAddressCountShield();
549
550
	document.getElementById("limit_normal").textContent = (ae.getAddressCountNormal() + "/" + ae.getLimitNormalA(ae.getOwnLevel())).padStart(ae.getLimitNormalA(ae.getOwnLevel()) > 9 ? 5 : 1);
551
	document.getElementById("limit_shield").textContent = (ae.getAddressCountShield() + "/" + ae.getLimitShieldA(ae.getOwnLevel())).padStart(ae.getLimitShieldA(ae.getOwnLevel()) > 9 ? 5 : 1);
552
	document.getElementById("limit_total").textContent = ((ae.getAddressCountNormal() + ae.getAddressCountShield()) + "/" + ae.getAddrPerUser()).padStart(5);
553
554
	updateAddressButtons();
555
//	document.getElementById("getapk_result").textContent = ae.getOwnApk(document.getElementById("getapk_addr").value);
556
}
557
558
function addOwnAccount() {
559
	const row = document.getElementById("tbd_accs").insertRow(-1);
560
561
	let cell;
562
	cell = row.insertCell(-1); cell.textContent = ae.uidToName(ae.getOwnUid());
563
	cell = row.insertCell(-1); cell.textContent = Math.round(ae.getTotalMsgBytes() / 1048576); // MiB
564
	cell = row.insertCell(-1); cell.textContent = ae.getAddressCountNormal();
565
	cell = row.insertCell(-1); cell.textContent = ae.getAddressCountShield();
566
567
	cell = row.insertCell(-1);
568
	let btn = document.createElement("button");
569
	btn.type = "button";
570
	btn.textContent = "+";
571
	btn.disabled = true;
572
	cell.appendChild(btn);
573
574
	cell = row.insertCell(-1); cell.textContent = ae.getOwnLevel();
575
576
	cell = row.insertCell(-1);
577
	btn = document.createElement("button");
578
	btn.type = "button";
579
	btn.textContent = "−";
580
	btn.disabled = true;
581
	btn.id = "btn_lowme";
582
	btn.onclick = function() {
583
		const newLevel = parseInt(row.cells[5].textContent, 10) - 1;
584
		ae.Account_Update(ae.getOwnUid(), newLevel, function(error) {
585
			if (error === 0) {
586
				row.cells[5].textContent = newLevel;
587
				if (newLevel === 0) {document.getElementById("btn_lowme").disabled = true;}
588
			} else errorDialog(error);
589
		});
590
	};
591
	cell.appendChild(btn);
592
593
	cell = row.insertCell(-1);
594
	btn = document.createElement("button");
595
	btn.type = "button";
596
	btn.textContent = "X";
597
	btn.disabled = true;
598
	btn.id = "btn_delme";
599
	btn.onclick = function() {
600
		ae.Account_Delete(ae.getOwnUid(), function(error) {
601
			if (error === 0) {
602
				row.remove();
603
				document.getElementById("fs_users").disabled = true;
604
			} else errorDialog(error);
605
		});
606
	};
607
	cell.appendChild(btn);
608
}
609
610
function adjustLevel(uid, level, c) {
611
	const fs = document.getElementById("tbl_accs");
612
	fs.disabled = true;
613
614
	ae.Account_Update(uid, level, function(error) {
615
		fs.disabled = false;
616
617
		if (error === 0) {
618
			c[4].children[0].disabled = (level === 3);
619
			c[5].textContent = level;
620
			c[6].children[0].disabled = (level === 0);
621
		} else errorDialog(error);
622
	});
623
}
624
625
function addMsg(isInt, i) {
626
	const row = document.getElementById("tbl_inbox").insertRow(-1);
627
	row.setAttribute("data-msgid", isInt? ae.getIntMsgId(i) : ae.getExtMsgId(i));
628
629
	const ts = isInt? ae.getIntMsgTime(i) : ae.getExtMsgTime(i);
630
	const el = document.createElement("time");
631
	el.dateTime = new Date(ts * 1000).toISOString();
632
	el.textContent = new Date((ts * 1000) + (new Date().getTimezoneOffset() * -60000)).toISOString().slice(0, 10);
633
	let cell = row.insertCell(-1);
634
	cell.appendChild(el);
635
636
	cell = row.insertCell(-1);
637
	cell.textContent = isInt? ae.getIntMsgTitle(i) : ae.getExtMsgTitle(i);
638
	if (!cell.textContent) cell.textContent = "(fail)";
639
640
	if (isInt) {
641
		cell = row.insertCell(-1);
642
		cell.textContent = ae.getIntMsgFrom(i);
643
		cell.className = (ae.getIntMsgFrom(i).length === 16) ? "mono" : "";
644
	} else {
645
		let from1 = ae.getExtMsgHdrFrom(i);
646
		if (!from1) from1 = ae.getExtMsgEnvFrom(i);
647
		const from2 = from1.substring(from1.indexOf("@") + 1);
648
		cell = row.insertCell(-1);
649
		cell.textContent = from1.substring(0, from1.indexOf("@"));
650
651
		const flag = document.createElement("abbr");
652
		flag.textContent = getCountryFlag(ae.getExtMsgCcode(i));
653
		flag.title = ae.getExtMsgCname(i);
654
655
		const fromText = document.createElement("span");
656
		fromText.textContent = " " + from2;
657
658
		cell = row.insertCell(-1);
659
		cell.appendChild(flag);
660
		cell.appendChild(fromText);
661
	}
662
663
	row.onclick = function() {
664
		displayMsg(false, isInt, i);
665
	};
666
}
667
668
function setRowsPerPage(tbl) {
669
	tbl.replaceChildren();
670
	const row = tbl.insertRow(-1);
671
	const cell = row.insertCell(-1);
672
	cell.textContent = "0";
673
	rowsPerPage = Math.floor(getComputedStyle(tbl).height.replace("px", "") / getComputedStyle(tbl.getElementsByTagName("tr")[0]).height.replace("px", ""));
674
	tbl.replaceChildren();
675
}
676
677
function showInbox() {
678
	const tbl = document.getElementById("tbl_inbox");
679
	if (!document.getElementById("main1").hidden) setRowsPerPage(tbl);
680
681
	const maxExt = ae.getExtMsgCount();
682
	const maxInt = ae.getIntMsgCount();
683
	const loadMore = ae.getReadyMsgBytes() < ae.getTotalMsgBytes();
684
685
	if (maxExt + maxInt > 0) {
686
		tabs[TAB_INBOX].max = Math.floor((maxExt + maxInt - (loadMore? 0 : 1)) / rowsPerPage);
687
		document.getElementById("btn_rght").disabled = (tabs[TAB_INBOX].cur >= tabs[TAB_INBOX].max);
688
		tbl.replaceChildren();
689
690
		let skipMsgs = rowsPerPage * tabs[TAB_INBOX].cur;
691
		let numExt = 0;
692
		let numInt = 0;
693
		let numAdd = 0;
694
695
		while (numAdd < rowsPerPage) {
696
			const tsInt = (numInt < maxInt) ? ae.getIntMsgTime(numInt) : -1;
697
			const tsExt = (numExt < maxExt) ? ae.getExtMsgTime(numExt) : -1;
698
			if (tsInt === -1 && tsExt === -1) break;
699
700
			if (tsInt !== -1 && (tsExt === -1 || tsInt > tsExt)) {
701
				if (skipMsgs > 0) skipMsgs--; else {addMsg(true, numInt); numAdd++;}
702
				numInt++;
703
			} else if (tsExt !== -1) {
704
				if (skipMsgs > 0) skipMsgs--; else {addMsg(false, numExt); numAdd++;}
705
				numExt++;
706
			}
707
		}
708
	} else {
709
		tabs[TAB_INBOX].max = 0;
710
	}
711
712
	if (loadMore && tabs[TAB_INBOX].cur >= tabs[TAB_INBOX].max) {
713
		const row = tbl.insertRow(-1);
714
		const cell = row.insertCell(-1);
715
		cell.textContent = "Load more (" + Math.round((ae.getTotalMsgBytes() - ae.getReadyMsgBytes()) / 1024) + " KiB left)";
716
717
		row.onclick = function() {
718
			tbl.style.opacity = 0.5;
719
720
			ae.Message_Browse(false, false, function(errorBrowse) {
721
				tbl.style.opacity = 1;
722
723
				if (errorBrowse !== 0) {
724
					errorDialog(errorBrowse);
725
					return;
726
				}
727
728
				showInbox();
729
			});
730
		};
731
	}
732
}
733
734
function showDrbox() {
735
	const tbl = document.getElementById("tbl_drbox");
736
	if (!document.getElementById("main1").hidden) setRowsPerPage(tbl);
737
738
	const drCount = ae.getOutMsgCount();
739
	const loadMore = ae.getReadyMsgBytes() < ae.getTotalMsgBytes();
740
741
	if (drCount > 0) {
742
		tabs[TAB_DRBOX].max = Math.floor((drCount - (loadMore? 0 : 1)) / rowsPerPage);
743
		document.getElementById("btn_rght").disabled = (tabs[TAB_DRBOX].cur >= tabs[TAB_DRBOX].max);
744
		tbl.replaceChildren();
745
746
		let skipMsgs = rowsPerPage * tabs[TAB_DRBOX].cur;
747
		let numAdd = 0;
748
749
		for (let i = 0; numAdd < rowsPerPage && i < drCount; i++) {
750
			if (skipMsgs > 0) {
751
				skipMsgs--;
752
				continue;
753
			}
754
755
			const row = tbl.insertRow(-1);
756
			row.setAttribute("data-msgid", ae.getOutMsgId(i));
757
758
			let cell;
759
			cell = row.insertCell(-1); cell.textContent = new Date(ae.getOutMsgTime(i) * 1000).toISOString().slice(0, 10);
760
			cell = row.insertCell(-1); cell.textContent = ae.getOutMsgSubj(i);
761
			row.onclick = function() {displayOutMsg(false, i);};
762
763
			numAdd++;
764
		}
765
	} else {
766
		tabs[TAB_DRBOX].max = 0;
767
	}
768
769
	if (loadMore && tabs[TAB_DRBOX].cur >= tabs[TAB_DRBOX].max) {
770
		const row = tbl.insertRow(-1);
771
		const cell = row.insertCell(-1);
772
		cell.textContent = "Load more (" + Math.round((ae.getTotalMsgBytes() - ae.getReadyMsgBytes()) / 1024) + " KiB left)";
773
774
		row.onclick = function() {
775
			tbl.style.opacity = 0.5;
776
777
			ae.Message_Browse(false, false, function(errorBrowse) {
778
				tbl.style.opacity = 1;
779
780
				if (errorBrowse !== 0) {
781
					errorDialog(errorBrowse);
782
					return;
783
				}
784
785
				showDrbox();
786
			});
787
		};
788
	}
789
}
790
791
function showFiles() {
792
	const tbl = document.getElementById("tbl_files");
793
	if (!document.getElementById("main1").hidden) setRowsPerPage(tbl);
794
795
	const msgCount = ae.getUplMsgCount() + ((vaultPage >= 0) ? vault.getTotalFiles() : 0);
796
	const loadMore = ae.getReadyMsgBytes() < ae.getTotalMsgBytes();
797
798
	if (msgCount > 0) {
799
		tabs[TAB_NOTES].max = 2 + Math.floor((msgCount - (loadMore? 0 : 1)) / rowsPerPage);
800
		document.getElementById("btn_rght").disabled = (tabs[TAB_NOTES].cur >= tabs[TAB_NOTES].max);
801
		tbl.replaceChildren();
802
803
		let skipMsgs = rowsPerPage * (tabs[TAB_NOTES].cur - 2);
804
		let numAdd = 0;
805
806
		for (let i = 0; numAdd < rowsPerPage && i < ae.getUplMsgCount(); i++) {
807
			if (skipMsgs > 0) {
808
				skipMsgs--;
809
				continue;
810
			}
811
812
			const row = tbl.insertRow(-1);
813
			row.setAttribute("data-msgid", ae.getUplMsgId(i));
814
			row.className = "rowfile";
815
816
			let cell = row.insertCell(-1);
817
			cell.textContent = new Date(ae.getUplMsgTime(i) * 1000).toISOString().slice(0, 10);
818
			cell.onclick = function() {displayFile(false, i, null);};
819
820
			cell = row.insertCell(-1);
821
			cell.textContent = (ae.getUplMsgBytes(i) / 1024).toFixed(0).padStart(4, " ");
822
			cell.onclick = function() {displayFile(false, i, null);};
823
824
			cell = row.insertCell(-1);
825
			const parentNum = ae.getUplMsgParent(i);
826
			if (typeof(parentNum) === "number") {
827
				cell.textContent = ae.getExtMsgTitle(parentNum);
828
				cell.onclick = function() {displayMsg(false, false, parentNum);};
829
			} else if (parentNum === false) {
830
				cell.textContent = "Upload";
831
			} else {
832
				cell.textContent = "Unknown";
833
			}
834
835
			cell = row.insertCell(-1);
836
			cell.textContent = ae.getUplMsgTitle(i);
837
			cell.onclick = function() {displayFile(false, i, null);};
838
839
			cell = row.insertCell(-1);
840
			const btn = document.createElement("button");
841
			btn.setAttribute("data-msgid", ae.getUplMsgId(i));
842
			btn.type = "button";
843
			btn.textContent = "X";
844
			btn.onclick = function() {
845
				ae.Message_Delete(this.getAttribute("data-msgid"), function(error) {
846
					if (error === 0) showFiles();
847
					else errorDialog(error);
848
				});
849
			};
850
			cell.appendChild(btn);
851
852
			numAdd++;
853
		}
854
855
		if (vaultPage >= 0) {
856
			for (let i = 0; numAdd < rowsPerPage && i < 256; i++) {
857
				if (vault.getFileSize(i) < 1) continue;
858
859
				if (skipMsgs > 0) {
860
					skipMsgs--;
861
					continue;
862
				}
863
864
				const row = tbl.insertRow(-1);
865
				row.className = "rowfile";
866
867
				let cell = row.insertCell(-1);
868
				cell.textContent = new Date(vault.getFileTime(i) * 1000).toISOString().slice(0, 10);
869
870
				cell = row.insertCell(-1);
871
				cell.textContent = (vault.getFileSize(i) / 1024).toFixed(0).padStart(4, " ");
872
873
				cell = row.insertCell(-1);
874
				cell.textContent = "Vault";
875
876
				cell = row.insertCell(-1);
877
				cell.textContent = vault.getFilePath(i);
878
				cell.onclick = function() {vault.downloadFile(i, function(m,p){}, function(msg) {
0 ignored issues
show
Unused Code introduced by
The parameter m is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter p is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
879
					if (msg !== "Done") errorDialog(404);
880
				});};
881
882
				cell = row.insertCell(-1);
883
				const btn = document.createElement("button");
884
				btn.type = "button";
885
				btn.textContent = "X";
886
				btn.onclick = function() {
887
					vault.deleteFile(i, function(error) {
888
						if (error === 0) showFiles();
889
						else errorDialog(error);
890
					});
891
				};
892
				cell.appendChild(btn);
893
894
				numAdd++;
895
			}
896
		}
897
	} else tabs[TAB_NOTES].max = 2;
898
899
	if (loadMore && tabs[TAB_NOTES].cur >= tabs[TAB_NOTES].max) {
900
		const row = tbl.insertRow(-1);
901
		row.className = "rowfilex";
902
903
		let cell = row.insertCell(-1);
904
		if (ae.getReadyMsgBytes() < ae.getTotalMsgBytes()) {
905
			cell.textContent = "Load more (" + Math.round((ae.getTotalMsgBytes() - ae.getReadyMsgBytes()) / 1024) + " KiB left)";
906
			cell.onclick = function() {
907
				tbl.style.opacity = 0.5;
908
909
				ae.Message_Browse(false, false, function(errorBrowse) {
910
					tbl.style.opacity = 1;
911
912
					if (errorBrowse !== 0) {
913
						errorDialog(errorBrowse);
914
						return;
915
					}
916
917
					showFiles();
918
				});
919
			};
920
		}
921
922
		cell = row.insertCell(-1);
0 ignored issues
show
Unused Code introduced by
The assignment to variable cell seems to be never used. Consider removing it.
Loading history...
923
	}
924
}
925
926
function addAccountToTable(i) {
927
	if (ae.getOwnUid() === ae.admin_getUserUid(i)) return;
928
929
	const row = document.getElementById("tbd_accs").insertRow(-1);
930
	let cell;
931
	cell = row.insertCell(-1); cell.textContent = ae.uidToName(ae.admin_getUserUid(i));
932
	cell = row.insertCell(-1); cell.textContent = Math.round(ae.admin_getUserKib(i) / 1024);
933
	cell = row.insertCell(-1); cell.textContent = ae.admin_getUserNrm(i);
934
	cell = row.insertCell(-1); cell.textContent = ae.admin_getUserShd(i);
935
936
	cell = row.insertCell(-1);
937
	let btn = document.createElement("button");
938
	btn.type = "button";
939
	btn.textContent = "+";
940
	btn.disabled = (ae.admin_getUserLvl(i) === 3);
941
	btn.onclick = function() {const c = this.parentElement.parentElement.cells; adjustLevel(ae.admin_getUserUid(i), ae.admin_getUserLvl(i) + 1, c);};
942
	cell.appendChild(btn);
943
944
	cell = row.insertCell(-1); cell.textContent = ae.admin_getUserLvl(i);
945
946
	cell = row.insertCell(-1);
947
	btn = document.createElement("button");
948
	btn.type = "button";
949
	btn.textContent = "−";
950
	btn.disabled = (ae.admin_getUserLvl(i) === 0);
951
	btn.onclick = function() {const c = this.parentElement.parentElement.cells; adjustLevel(ae.admin_getUserUid(i), ae.admin_getUserLvl(i) - 1, c);};
952
	cell.appendChild(btn);
953
954
	cell = row.insertCell(-1);
955
	btn = document.createElement("button");
956
	btn.type = "button";
957
	btn.textContent = "X";
958
	btn.onclick = function() {
959
		const tr = this.parentElement.parentElement;
960
		ae.Account_Delete(ae.admin_getUserUid(i), function(error) {
961
			if (error === 0) tr.remove(); else errorDialog(error);
962
		});
963
	};
964
	cell.appendChild(btn);
965
}
966
967
function updateLimits() {
968
	const tbl = document.querySelector("#tbl_limits > tbody");
969
970
	if (ae.isUserAdmin()) {
971
		for (let i = 0; i < 4; i++) {
972
			tbl.rows[i].cells[1].children[0].value = ae.getLimitStorage(i);
973
			tbl.rows[i].cells[2].children[0].value = ae.getLimitNormalA(i);
974
			tbl.rows[i].cells[3].children[0].value = ae.getLimitShieldA(i);
975
		}
976
	} else {
977
		const lvl = ae.getOwnLevel();
978
		tbl.rows[lvl].cells[1].children[0].value = ae.getLimitStorage(lvl);
979
		tbl.rows[lvl].cells[2].children[0].value = ae.getLimitNormalA(lvl);
980
		tbl.rows[lvl].cells[3].children[0].value = ae.getLimitShieldA(lvl);
981
	}
982
}
983
984
function deleteAddress(addr) {
985
	const buttons = document.querySelectorAll("#tbl_addrs button");
986
	buttons.forEach(function(btn) {btn.disabled = true;});
987
988
	let addressToDelete = -1;
989
	for (let i = 0; i < ae.getAddressCount(); i++) {
990
		if (addr === ae.getAddress(i)) {
991
			addressToDelete = i;
992
			break;
993
		}
994
	}
995
996
	if (addressToDelete === -1) return;
997
998
	ae.Address_Delete(addressToDelete, function(error1) {
999
		if (error1 !== 0) {
1000
			buttons.forEach(function(btn) {btn.disabled = false;});
1001
			errorDialog(error1);
1002
			return;
1003
		}
1004
1005
		document.getElementById("tbl_addrs").deleteRow(addressToDelete);
1006
		document.getElementById("write_from").remove(addressToDelete);
1007
1008
		if (ae.getAddressCountNormal() > 0) {
1009
			const apkList = document.getElementById("getapk_addr");
1010
			for (let i = 0; i < apkList.children.length; i++) {
1011
				if (apkList.children[i].value === addr) {
1012
					apkList.remove(i);
1013
					break;
1014
				}
1015
			}
1016
		} else {
1017
			document.getElementById("getapk_addr").replaceChildren();
1018
		}
1019
1020
		updateAddressCounts();
1021
1022
		ae.Private_Update(function(error2) {
1023
			buttons.forEach(function(btn) {btn.disabled = false;});
1024
			if (error2) errorDialog(error2);
1025
		});
1026
	});
1027
}
1028
1029
function setTab(isHistory, tabNum, pageNum) {
1030
	tab = tabNum;
1031
	if (pageNum !== -1) tabs[tab].cur = pageNum;
1032
1033
	document.querySelectorAll("#main1 > nav:first-of-type > button").forEach(function(btn, i) {
1034
		document.querySelectorAll("#main1 > .mid > div")[i].hidden = (tab !== i);
1035
		btn.disabled = (tab === i);
1036
	});
1037
1038
	const bigScreen = window.matchMedia("(min-width: 80em)").matches;
1039
	document.getElementById("main2").hidden = !bigScreen;
1040
	document.getElementById("btn_leave").disabled = bigScreen;
1041
1042
	switch (tab) {
1043
		case TAB_INBOX: showInbox(); break;
1044
		case TAB_DRBOX: showDrbox(); break;
1045
1046
		case TAB_WRITE:
1047
			if (tabs[tab].cur === 0) {
1048
				document.getElementById("div_write_1").hidden = false;
1049
				document.getElementById("div_write_2").hidden = true;
1050
				document.getElementById("write_recv").focus();
1051
			} else if (!writeVerify()) {
1052
				tabs[TAB_WRITE].cur = 0;
1053
				return;
1054
			}
1055
		break;
1056
1057
		case TAB_NOTES:
1058
			if (vaultPage === -2) {
1059
				vaultPage = -1;
1060
1061
				vault.downloadIndex(function(err) {
1062
					if (err === 0) {
1063
						vaultPage = 0;
1064
					}
1065
				});
1066
			}
1067
1068
			switch (tabs[tab].cur) {
1069
				case 0:
1070
					document.getElementById("div_notes").children[0].hidden = false;
1071
					document.getElementById("div_notes").children[1].hidden = true;
1072
					document.getElementById("div_notes").children[2].hidden = true;
1073
				break;
1074
1075
				case 1:
1076
					document.getElementById("div_notes").children[0].hidden = true;
1077
					document.getElementById("div_notes").children[1].hidden = false;
1078
					document.getElementById("div_notes").children[2].hidden = true;
1079
1080
					document.querySelector("#div_notepad meter").value = ae.getPrivateExtraSpace() / ae.getPrivateExtraSpaceMax();
1081
				break;
1082
1083
				case 2:
1084
					document.getElementById("div_notes").children[0].hidden = true;
1085
					document.getElementById("div_notes").children[1].hidden = true;
1086
					document.getElementById("div_notes").children[2].hidden = false;
0 ignored issues
show
introduced by
This node falls through to the next case due to this statement. Please add a comment either directly below this line or between the cases to explain.
Loading history...
1087
1088
				default:
1089
					showFiles();
1090
			}
1091
		break;
1092
1093
		case TAB_TOOLS:
1094
			for (let i = 0; i <= tabs[tab].max; i++) {
1095
				document.getElementById("div_tools").children[i].hidden = (i !== tabs[tab].cur);
1096
			}
1097
		break;
1098
	}
1099
1100
	document.getElementById("btn_dele").disabled = !tabs[tab].btnDele;
1101
	document.getElementById("btn_left").disabled = (tabs[tab].cur === 0);
1102
	document.getElementById("btn_rght").disabled = (tabs[tab].cur === tabs[tab].max);
1103
	document.getElementById("btn_updt").disabled = !tabs[tab].btnUpdt;
1104
1105
	if (!isHistory) history.pushState({tab: tab, page: tabs[tab].cur, msg: msgDisplay}, null);
1106
}
1107
1108
window.onresize = function() {
1109
	setTab(true, tab, tabs[tab].cur);
1110
}
1111
1112
function clearWrite() {
1113
	setTab(false, TAB_WRITE, 0);
1114
1115
	document.querySelector("#write2_pkey > input").value = "";
1116
	document.getElementById("write_body").value = "";
1117
	document.getElementById("write_subj").value = "";
1118
	document.getElementById("write_subj").readOnly = false;
1119
	document.getElementById("write_subj").setAttribute("data-replyid", "");
1120
	document.getElementById("write_recv").value = "";
1121
	document.getElementById("write_recv").readOnly = false;
1122
	document.getElementById("write_recv").focus();
1123
}
1124
1125
function refreshContactList() {
1126
	let opts = [];
1127
1128
	for (let i = 0; i < ae.getContactCount(); i++) {
1129
		const el = document.createElement("option");
1130
		el.value = ae.getContactMail(i);
1131
		opts.push(el);
1132
	}
1133
1134
	if (ae.isUserAdmin()) {
1135
		const el = document.createElement("option");
1136
		el.value = "public";
1137
		opts.push(el);
1138
	}
1139
1140
	document.getElementById("contact_emails").replaceChildren(...opts);
1141
}
1142
1143
function addContact(mail, name, note) {
1144
	const tbl = document.getElementById("tbl_ctact");
1145
	const row = tbl.insertRow(-1);
1146
1147
	let cell = row.insertCell(-1);
1148
	cell.autocapitalize = "off";
1149
	cell.contentEditable = true;
1150
	cell.inputMode = "email";
1151
	cell.spellcheck = false;
1152
	cell.textContent = mail;
1153
1154
	cell = row.insertCell(-1);
1155
	cell.autocapitalize = "words";
1156
	cell.contentEditable = true;
1157
	cell.spellcheck = false;
1158
	cell.textContent = name;
1159
1160
	cell = row.insertCell(-1);
1161
	cell.autocapitalize = "off";
1162
	cell.contentEditable = true;
1163
	cell.spellcheck = false;
1164
	cell.textContent = note;
1165
1166
	cell = row.insertCell(-1);
1167
	const el = document.createElement("button");
1168
	el.type = "button";
1169
	el.textContent = "X";
1170
	el.onclick = function() {row.remove();};
1171
	cell.appendChild(el);
1172
}
1173
1174
function addContacts() {
1175
	for (let i = 0; i < ae.getContactCount(); i++) {
1176
		addContact(
1177
			ae.getContactMail(i),
1178
			ae.getContactName(i),
1179
			ae.getContactNote(i)
1180
		);
1181
	}
1182
1183
	refreshContactList();
1184
}
1185
1186
function addAddress(num) {
1187
	const addrTable = document.getElementById("tbl_addrs");
1188
	const row = addrTable.insertRow(-1);
1189
	const addr = ae.getAddress(num);
1190
1191
	let cell = row.insertCell(-1);
1192
	cell.textContent = addr;
1193
	cell.onclick = function() {navigator.clipboard.writeText(((this.textContent.length === 16) ? ae.shieldMix(this.textContent, 0) : this.textContent) + "@" + ae.getDomainEml());};
1194
1195
	cell = row.insertCell(-1);
1196
	let el = document.createElement("input");
1197
	el.type = "checkbox";
1198
	el.checked = ae.getAddressAccInt(num);
1199
	cell.appendChild(el);
1200
1201
	cell = row.insertCell(-1);
1202
	el = document.createElement("input");
1203
	el.type = "checkbox";
1204
	el.checked = ae.getAddressAccExt(num);
1205
	cell.appendChild(el);
1206
1207
	cell = row.insertCell(-1);
1208
	el = document.createElement("input");
1209
	el.type = "checkbox";
1210
	el.checked = ae.getAddressAllVer(num);
1211
	cell.appendChild(el);
1212
1213
	cell = row.insertCell(-1);
1214
	el = document.createElement("input");
1215
	el.type = "checkbox";
1216
	el.checked = ae.getAddressAttach(num);
1217
	cell.appendChild(el);
1218
1219
	cell = row.insertCell(-1);
1220
	el = document.createElement("input");
1221
	el.type = "checkbox";
1222
	el.checked = ae.getAddressSecure(num);
1223
	cell.appendChild(el);
1224
1225
	cell = row.insertCell(-1);
1226
	el = document.createElement("input");
1227
	el.type = "checkbox";
1228
	el.checked = ae.getAddressOrigin(num);
1229
	cell.appendChild(el);
1230
1231
	cell = row.insertCell(-1);
1232
	el = document.createElement("button");
1233
	el.type = "button";
1234
	el.textContent = "X";
1235
	el.onclick = function() {deleteAddress(addr);};
1236
	cell.appendChild(el);
1237
1238
	el = document.createElement("option");
1239
	el.value = addr;
1240
	el.textContent = addr + "@" + ae.getDomainEml();
1241
	document.getElementById("write_from").appendChild(el);
1242
1243
	if (addr.length !== 16) {
1244
		el = document.createElement("option");
1245
		el.value = addr;
1246
		el.textContent = addr;
1247
		document.getElementById("getapk_addr").appendChild(el);
1248
	}
1249
}
1250
1251
function addAddresses() {
1252
	for (let i = 0; i < ae.getAddressCount(); i++) {
1253
		addAddress(i);
1254
	}
1255
}
1256
1257
function addressCreate(addr) {
1258
	document.getElementById("btn_address_create_normal").disabled = true;
1259
	document.getElementById("btn_address_create_shield").disabled = true;
1260
1261
	ae.Address_Create(addr, function(error1) {
1262
		if (error1 !== 0) {
1263
			updateAddressButtons();
1264
			errorDialog(error1, (addr !== "SHIELD") ? document.getElementById("txt_address_create_normal") : null);
1265
			return;
1266
		}
1267
1268
		ae.Private_Update(function(error2) {
1269
			updateAddressCounts();
1270
1271
			addAddress(ae.getAddressCount() - 1);
1272
			if (addr !== "SHIELD") {
1273
				document.getElementById("txt_address_create_normal").value = "";
1274
				document.getElementById("txt_address_create_normal").focus();
1275
			}
1276
1277
			if (error2 !== 0) errorDialog(error2, (addr !== "SHIELD") ? document.getElementById("txt_address_create_normal") : null);
1278
		});
1279
	});
1280
}
1281
1282
function reloadAccount() {
1283
	updateLimits();
1284
	addOwnAccount();
1285
	addContacts();
1286
	addAddresses();
1287
	updateAddressCounts();
1288
1289
	document.getElementById("fs_admin").disabled = !ae.isUserAdmin();
1290
	document.getElementById("txt_notepad").value = ae.getPrivateExtra();
1291
}
1292
1293
function writeVerify() {
1294
	if (
1295
	   !document.getElementById("write_recv").reportValidity()
1296
	|| !document.getElementById("write_subj").reportValidity()
1297
	|| !document.getElementById("write_body").reportValidity()
1298
	) return false;
1299
1300
	document.getElementById("div_write_1").hidden = true;
1301
	document.getElementById("div_write_2").hidden = false;
1302
1303
	document.getElementById("write2_recv").textContent = document.getElementById("write_recv").value;
1304
	document.getElementById("write2_subj").textContent = document.getElementById("write_subj").value;
1305
	document.getElementById("write2_rply").textContent = document.getElementById("write_subj").getAttribute("data-replyid");
1306
	document.getElementById("write2_body").textContent = document.getElementById("write_body").value;
1307
1308
	if (document.getElementById("write_recv").value.indexOf("@") >= 0) {
1309
		document.getElementById("write2_from").textContent = document.getElementById("write_from").value + "@" + ae.getDomainEml();
1310
		document.getElementById("write2_pkey").hidden = true;
1311
	} else {
1312
		document.getElementById("write2_from").textContent = document.getElementById("write_from").value;
1313
		document.getElementById("write2_pkey").hidden = (document.getElementById("write_recv").value === "public");
1314
	}
1315
1316
	document.querySelector("#write2_send > button").disabled = false;
1317
	document.getElementById("write2_btntxt").textContent = (document.getElementById("write_recv").value === "public") ? "Make" : "Send to";
1318
	return true;
1319
}
1320
1321
// Interface elements
1322
if (window.matchMedia("(prefers-color-scheme: light)").matches) document.querySelector("head > meta[name='theme-color']").content = "#eef";
1323
window.matchMedia("(prefers-color-scheme: light)").onchange = function() {document.querySelector("head > meta[name='theme-color']").content = window.matchMedia("(prefers-color-scheme: light)").matches? "#eef" : "#001";};
1324
1325
window.onpopstate = function(event) {
1326
	if (!isReady || !event.state) return;
1327
	setTab(true, event.state.tab, event.state.page);
1328
	msgDisplay = event.state.msg;
1329
1330
	if (msgDisplay) {
1331
		switch (msgDisplay.type) {
1332
			case "ext": displayMsg(true, false, msgDisplay.num); break;
1333
			case "int": displayMsg(true, true, msgDisplay.num); break;
1334
			case "out": displayOutMsg(true, msgDisplay.num); break;
1335
			case "upl": displayFile(true, msgDisplay.num, null); break;
1336
			case "ext_exp": displayExport(true, false, msgDisplay.num); break;
1337
			case "int_exp": displayExport(true, true, msgDisplay.num); break;
1338
		}
1339
	}
1340
};
1341
1342
document.querySelectorAll("#main1 > nav:first-of-type > button").forEach(function(btn, i) {
1343
	btn.onclick = function() {setTab(false, i, -1);};
1344
});
1345
1346
document.getElementById("btn_left").onclick = function() {
1347
	setTab(false, tab, tabs[tab].cur - 1);
1348
};
1349
1350
document.getElementById("btn_rght").onclick = function() {
1351
	setTab(false, tab, tabs[tab].cur + 1);
1352
};
1353
1354
1355
document.getElementById("btn_dele").onclick = function() {
1356
	this.blur();
1357
1358
	if (tab === TAB_WRITE) clearWrite();
1359
};
1360
1361
document.getElementById("btn_updt").onclick = function() {
1362
	const btn = this;
1363
	btn.disabled = true;
1364
	btn.blur();
1365
1366
	if (tab === TAB_INBOX) {
1367
		document.getElementById("tbl_inbox").style.opacity = 0.5;
1368
1369
		ae.Message_Browse(true, false, function(error) {
1370
			btn.disabled = false;
1371
			document.getElementById("tbl_inbox").style.opacity = 1;
1372
1373
			if (error === 0) {
1374
				showInbox();
1375
			} else {
1376
				errorDialog(error);
1377
			}
1378
		});
1379
	}
1380
};
1381
1382
document.getElementById("btn_mdele").onclick = function() {
1383
	const delId = document.querySelector("article").getAttribute("data-msgid");
1384
	if (!delId) return;
1385
1386
	const btn = this;
1387
	btn.blur();
1388
	btn.disabled = true;
1389
1390
	ae.Message_Delete(delId, function(error) {
1391
		if (error !== 0) {
1392
			btn.disabled = false;
1393
			errorDialog(error);
1394
			return;
1395
		}
1396
1397
		switch (tab) {
1398
			case TAB_INBOX: showInbox(); break;
1399
			case TAB_DRBOX: showDrbox(); break;
1400
			case TAB_NOTES: showFiles(); break;
1401
		}
1402
	});
1403
};
1404
1405
document.getElementById("btn_leave").onclick = function() {
1406
	document.getElementById("main2").hidden = true;
1407
	document.getElementById("main1").hidden = false;
1408
};
1409
1410
document.getElementById("btn_newcontact").onclick = function() {
1411
	addContact("", "", "");
1412
};
1413
1414
document.getElementById("btn_savecontacts").onclick = function() {
1415
	while (ae.getContactCount() > 0) {
1416
		ae.deleteContact(0);
1417
	}
1418
1419
	for (const row of document.getElementById("tbl_ctact").rows) {
1420
		ae.addContact(row.cells[0].textContent, row.cells[1].textContent, row.cells[2].textContent);
1421
	}
1422
1423
	refreshContactList();
1424
1425
	const btn = this;
1426
	btn.disabled = true;
1427
1428
	ae.Private_Update(function(error) {
1429
		btn.disabled = false;
1430
		if (error) errorDialog(error);
1431
	});
1432
};
1433
1434
document.getElementById("btn_address_create_normal").onclick = function() {
1435
	if (ae.getAddressCountNormal() >= ae.getLimitNormalA(ae.getOwnLevel()) || ae.getAddressCountNormal() + ae.getAddressCountShield() >= 31) return;
1436
1437
	const txtNewAddr = document.getElementById("txt_address_create_normal");
1438
	if (!txtNewAddr.reportValidity()) return;
1439
1440
	addressCreate(txtNewAddr.value.toLowerCase());
1441
};
1442
1443
document.getElementById("txt_address_create_normal").onkeyup = function(event) {
1444
	if (event.key !== "Enter") return;
1445
	event.preventDefault();
1446
	document.getElementById("btn_address_create_normal").click();
1447
};
1448
1449
document.getElementById("btn_address_create_shield").onclick = function() {
1450
	if (ae.getAddressCountShield() >= ae.getLimitShieldA(ae.getOwnLevel()) || ae.getAddressCountNormal() + ae.getAddressCountShield() >= 31) return;
1451
1452
	addressCreate("SHIELD");
1453
};
1454
1455
document.getElementById("btn_address_update").onclick = function() {
1456
	const btn = this;
1457
	btn.disabled = true;
1458
1459
	const rows = document.getElementById("tbl_addrs").rows;
1460
1461
	for (let i = 0; i < rows.length; i++) {
1462
		ae.setAddressAccInt(i, rows[i].getElementsByTagName("input")[0].checked);
1463
		ae.setAddressAccExt(i, rows[i].getElementsByTagName("input")[1].checked);
1464
		ae.setAddressAllVer(i, rows[i].getElementsByTagName("input")[2].checked);
1465
		ae.setAddressAttach(i, rows[i].getElementsByTagName("input")[3].checked);
1466
		ae.setAddressSecure(i, rows[i].getElementsByTagName("input")[4].checked);
1467
		ae.setAddressOrigin(i, rows[i].getElementsByTagName("input")[5].checked);
1468
	}
1469
1470
	ae.Address_Update(function(error) {
1471
		btn.disabled = false;
1472
		if (error) errorDialog(error);
1473
	});
1474
};
1475
1476
1477
document.getElementById("txt_sender").onkeyup = function(event) {
1478
	if (event.key !== "Enter") return;
1479
	event.preventDefault();
1480
	document.getElementById("btn_sender").click();
1481
};
1482
1483
document.getElementById("btn_reg").onclick = function() {
1484
	const btn = document.getElementById("btn_reg");
1485
	const uak = document.getElementById("txt_reg_uak");
1486
	const epk = document.getElementById("txt_reg_epk");
1487
1488
	if (!uak.reportValidity() || !epk.reportValidity()) return;
1489
	btn.disabled = true;
1490
	uak.disabled = true;
1491
	epk.disabled = true;
1492
1493
	ae.Account_Create(uak.value, epk.value, function(error) {
1494
		if (error === 0) {
1495
			addAccountToTable(ae.admin_getUserCount() - 1);
1496
			uak.value = "";
1497
			epk.value = "";
1498
		} else errorDialog(error);
1499
1500
		btn.disabled = false;
1501
		uak.disabled = false;
1502
		epk.disabled = false;
1503
	});
1504
};
1505
1506
document.getElementById("chk_dng_usr").onclick = function() {
1507
	document.getElementById("btn_lowme").disabled = !this.checked || (ae.getOwnLevel() === 0);
1508
	document.getElementById("btn_erame").disabled = !this.checked;
1509
	document.getElementById("btn_delme").disabled = !this.checked;
1510
};
1511
1512
document.getElementById("btn_erame").onclick = function() {
1513
	ae.Message_Delete("ALL", function(error) {
1514
		if (error === 0) {
1515
			document.getElementById("chk_dng_usr").checked = false;
1516
			document.getElementById("chk_dng_usr").onclick();
1517
		} else errorDialog(error);
1518
	});
1519
};
1520
1521
document.getElementById("btn_notepad_restore").onclick = function() {
1522
	document.getElementById("txt_notepad").value = ae.getPrivateExtra();
1523
	document.getElementById("btn_notepad_savepad").disabled = true;
1524
	document.getElementById("txt_notepad").oninput = function() {
1525
		this.oninput = null;
1526
		document.getElementById("btn_notepad_savepad").disabled = false;
1527
		document.getElementById("btn_notepad_savepad").textContent = "Save";
1528
	};
1529
};
1530
1531
document.getElementById("txt_notepad").oninput = function() {
1532
	document.getElementById("btn_notepad_savepad").disabled = false;
1533
};
1534
1535
document.getElementById("btn_notepad_savepad").onclick = function() {
1536
	const btn = this;
1537
	btn.disabled = true;
1538
1539
	const error = ae.setPrivateExtra(document.getElementById("txt_notepad").value);
1540
	if (error !== 0) {
1541
		btn.disabled = false;
1542
		errorDialog(error);
1543
		return;
1544
	}
1545
1546
	ae.Private_Update(function(error2) {
1547
		if (error2 !== 0) {
1548
			btn.disabled = false;
1549
			errorDialog(error2);
1550
		} else {
1551
			document.querySelector("#div_notepad meter").value = ae.getPrivateExtraSpace() / ae.getPrivateExtraSpaceMax();
1552
			btn.textContent = "Saved";
1553
			document.getElementById("txt_notepad").oninput = function() {
1554
				this.oninput = null;
1555
				btn.textContent = "Save";
1556
				btn.disabled = false;
1557
			};
1558
		}
1559
	});
1560
};
1561
1562
document.getElementById("btn_notepad_saveupl").onclick = function() {
1563
	const np = document.getElementById("txt_notepad");
1564
	np.disabled = true;
1565
1566
	let fname = prompt("Save as...", "Untitled");
0 ignored issues
show
Debugging Code Best Practice introduced by
The prompt UI element is often considered obtrusive and is generally only used as a temporary measure. Consider replacing it with another UI element.
Loading history...
1567
	if (!fname.endsWith(".txt")) fname += ".txt";
1568
1569
	ae.Message_Upload(fname, np.value, function(error) {
1570
		if (error === 0) {
1571
			np.value = "";
1572
			showFiles();
1573
			document.getElementById("tbd_accs").children[0].children[1].textContent = Math.round(ae.getTotalMsgBytes() / 1024 / 1024);
1574
		} else errorDialog(error);
1575
1576
		np.disabled = false;
1577
	});
1578
};
1579
1580
document.getElementById("btn_upload").onclick = function() {
1581
	const btn = this;
1582
	const fileSelector = document.createElement("input");
1583
	fileSelector.type = "file";
1584
	fileSelector.click();
1585
1586
	fileSelector.onchange = function() {
1587
		btn.disabled = true;
1588
1589
		const reader = new FileReader();
1590
		reader.onload = function() {
1591
			ae.Message_Upload(fileSelector.files[0].name, new Uint8Array(reader.result), function(error) {
1592
				if (error === 0) {
1593
					showFiles();
1594
					document.getElementById("tbd_accs").children[0].children[1].textContent = Math.round(ae.getTotalMsgBytes() / 1024 / 1024);
1595
				} else errorDialog(error);
1596
1597
				btn.disabled = false;
1598
			});
1599
		};
1600
1601
		reader.readAsArrayBuffer(fileSelector.files[0]);
1602
	};
1603
};
1604
1605
document.getElementById("btn_pg").onclick = function() {
1606
//	localStorage.greeting = document.getElementById("txt_pg").value;
1607
};
1608
1609
document.querySelector("#write2_send > button").onclick = function() {
1610
	const btn = this;
1611
	btn.disabled = true;
1612
1613
	// Public announcement
1614
	if (document.getElementById("write2_recv").textContent === "public") {
1615
		ae.Message_Public(document.getElementById("write_subj").value, document.getElementById("write_body").value, function(error) {
1616
			if (error !== 0) {
1617
				document.getElementById("write2_btntxt").textContent = "Retry making";
1618
				btn.disabled = false;
1619
				errorDialog(error);
1620
				return;
1621
			}
1622
1623
			clearWrite();
1624
			displayMsg(false, true, 0);
1625
		});
1626
1627
		return;
1628
	}
1629
1630
	// Email or internal message
1631
	let apk = null;
1632
	if (document.getElementById("write2_recv").textContent.indexOf("@") === -1) {
1633
		const elApk = document.querySelector("#write2_pkey > input");
1634
		if (!elApk.reportValidity()) {
1635
			btn.disabled = false;
1636
			return;
1637
		}
1638
1639
		try {apk = sodium.from_base64(elApk.value, sodium.base64_variants.ORIGINAL_NO_PADDING);}
1640
		catch(e) {
1641
			errorDialog(1); // Invalid input
1642
			btn.disabled = false;
1643
			return;
1644
		}
1645
	}
1646
1647
	document.getElementById("write2_btntxt").textContent = "Sending to";
1648
1649
	ae.Message_Create(
1650
		document.getElementById("write_subj").value,
1651
		document.getElementById("write_body").value,
1652
		document.getElementById("write_from").value,
1653
		document.getElementById("write_recv").value,
1654
		document.getElementById("write_subj").getAttribute("data-replyid"),
1655
		apk,
1656
		function(error) {
1657
			if (error !== 0) {
1658
				errorDialog(error);
1659
				document.getElementById("write2_btntxt").textContent = "Retry sending to";
1660
				btn.disabled = false;
1661
				return;
1662
			}
1663
1664
			showDrbox();
1665
			clearWrite();
1666
			displayOutMsg(false, 0);
1667
		}
1668
	);
1669
};
1670
1671
document.getElementById("btn_sender").onclick = function() {
1672
	ae.Message_Sender(document.getElementById("txt_sender_hash").value, Date.parse(document.getElementById("txt_sender_date").value) / 1000, function(error, result) {
1673
		if (error !== 0) {
1674
			errorDialog(error);
1675
			return;
1676
		}
1677
1678
		document.getElementById("txt_sender_res").value = result;
1679
	});
1680
};
1681
1682
document.getElementById("btn_limits").onclick = function() {
1683
	const btn = this;
1684
	btn.disabled = true;
1685
1686
	const mib = [parseInt(document.getElementById("lim_mib0").value, 10), parseInt(document.getElementById("lim_mib1").value, 10), parseInt(document.getElementById("lim_mib2").value, 10), parseInt(document.getElementById("lim_mib3").value, 10)];
1687
	const nrm = [parseInt(document.getElementById("lim_nrm0").value, 10), parseInt(document.getElementById("lim_nrm1").value, 10), parseInt(document.getElementById("lim_nrm2").value, 10), parseInt(document.getElementById("lim_nrm3").value, 10)];
1688
	const shd = [parseInt(document.getElementById("lim_shd0").value, 10), parseInt(document.getElementById("lim_shd1").value, 10), parseInt(document.getElementById("lim_shd2").value, 10), parseInt(document.getElementById("lim_shd3").value, 10)];
1689
1690
	ae.Setting_Limits(mib, nrm, shd, function(error) {
1691
		btn.disabled = false;
1692
1693
		if (error !== 0) {
1694
			errorDialog(error);
1695
		} else {
1696
			updateAddressCounts();
1697
		}
1698
	});
1699
};
1700
1701
document.getElementById("getapk_addr").onchange = function() {
1702
	document.getElementById("getapk_result").textContent = ae.getOwnApk(document.getElementById("getapk_addr").value);
1703
};
1704
1705
document.getElementById("txt_umk").onfocus = function() {
1706
//	document.getElementById("greeting").textContent = localStorage.greeting;
1707
};
1708
1709
document.getElementById("txt_umk").onkeyup = function(event) {
1710
	if (event.key !== "Enter") return;
1711
	event.preventDefault();
1712
	document.getElementById("btn_enter").click();
1713
};
1714
1715
document.getElementById("btn_enter").onclick = function() {
1716
	const txtUmk = document.getElementById("txt_umk");
1717
1718
	if (txtUmk.value === "") {
1719
		ae.reset();
1720
		document.getElementById("greeting").textContent = "Data cleared";
1721
		return;
1722
	}
1723
1724
	if (!txtUmk.reportValidity()) return;
1725
1726
	const btn = this;
1727
	btn.disabled = true;
1728
1729
	document.getElementById("txt_umk").disabled = true;
1730
1731
	ae.setKeys(txtUmk.value, function(successSetKeys) {
1732
		if (!successSetKeys) {
1733
			document.getElementById("txt_umk").disabled = false;
1734
			txtUmk.focus();
1735
1736
			document.getElementById("greeting").textContent = "SetKeys failed";
1737
			btn.disabled = false;
1738
			return;
1739
		}
1740
1741
		document.body.style.cursor = "wait";
1742
		document.getElementById("greeting").textContent = "Connecting...";
1743
1744
		if (vaultPage === -3) {
1745
			vault.setKeys(txtUmk.value, function(vaultKeysOk) {
1746
				if (vaultKeysOk) vaultPage = -2;
1747
			});
1748
		}
1749
1750
		ae.Message_Browse(true, true, function(errorBrowse) {
1751
			document.body.style.cursor = "";
1752
1753
			if (errorBrowse !== 0 && errorBrowse !== 0x09) {
1754
				let errorMsg = ae.getErrorMessage(errorBrowse);
1755
				if (typeof(errorMsg) == "object") errorMsg = errorMsg[1];
1756
1757
				document.getElementById("greeting").textContent = errorMsg + " ("+ ((errorBrowse >= 400) ? errorBrowse : "0x" + errorBrowse.toString(16).padStart(2, "0").toUpperCase()) + ")";
1758
				document.getElementById("txt_umk").disabled = false;
1759
				btn.disabled = false;
1760
				btn.focus();
1761
				return;
1762
			}
1763
1764
			txtUmk.value = "";
1765
			document.getElementById("div_begin").hidden = true;
1766
			document.getElementById("div_main").hidden = false;
1767
			isReady = true;
1768
			reloadAccount();
1769
			history.replaceState({tab: 0, page: 0, msg: msgDisplay}, null);
1770
			setTab(true, 0, 0);
1771
1772
			if (errorBrowse !== 0) errorDialog(errorBrowse);
1773
			if (!ae.isUserAdmin()) return;
1774
1775
			ae.Account_Browse(function(errorAcc) {
1776
				if (errorAcc === 0) {
1777
					for (let i = 0; i < ae.admin_getUserCount(); i++) {addAccountToTable(i);}
1778
					updateLimits();
1779
				} else {
1780
					errorDialog(errorAcc);
1781
				}
1782
			});
1783
		});
1784
	});
1785
};
1786
1787
});
1788