Passed
Push — master ( e130ca...a6cfbd )
by EMP
06:52
created

main.js ➔ addNotes   A

Complexity

Conditions 2

Size

Total Lines 13
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 10
dl 0
loc 13
rs 9.9
c 0
b 0
f 0
cc 2
1
"use strict";
2
3
sodium.ready.then(function() {
1 ignored issue
show
Bug introduced by
The variable sodium seems to be never declared. If this is a global, consider adding a /** global: sodium */ 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...
4
5
const ae = new AllEars(function(ok) {
1 ignored issue
show
Bug introduced by
The variable AllEars seems to be never declared. If this is a global, consider adding a /** global: AllEars */ 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...
6
	if (ok) {
7
		document.getElementById("txt_skey").style.background = "#466";
8
		document.getElementById("txt_skey").maxLength = "64";
9
	} else {
10
		console.log("Failed to load All-Ears");
11
	}
12
});
13
14
function TabState(cur, max, btnDele, btnUpdt) {
15
	this.cur = cur;
16
	this.max = max;
17
	this.btnDele = btnDele;
18
	this.btnUpdt = btnUpdt;
19
}
20
21
const tabs = [
22
	new TabState(0, 0, false, true), // Inbox
23
	new TabState(0, 0, false, true), // Outbx
24
	new TabState(0, 2, true, false), // Write
25
	new TabState(0, 3, false, false), // Notes
26
	new TabState(0, 3, false, true) // Admin
27
];
28
29
let tab = 0;
30
const TAB_INBOX = 0;
31
const TAB_OUTBX = 1;
0 ignored issues
show
Unused Code introduced by
The constant TAB_OUTBX seems to be never used. Consider removing it.
Loading history...
32
const TAB_WRITE = 2;
33
const TAB_NOTES = 3;
34
const TAB_ADMIN = 4;
35
36
// Helper functions
37
function getCountryName(countryCode) {
38
	const opts = document.getElementById("gatekeeper_country");
39
40
	for (let i = 0; i < opts.length; i++) {
41
		if (opts[i].value === countryCode) {
42
			return opts[i].textContent;
43
		}
44
	}
45
46
	return "Unknown countrycode: " + countryCode;
47
}
48
49
function getCountryFlag(countryCode) {
50
	return sodium.to_string(new Uint8Array([
1 ignored issue
show
Bug introduced by
The variable sodium seems to be never declared. If this is a global, consider adding a /** global: sodium */ 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...
51
		240, 159, 135, 166 + countryCode.codePointAt(0) - 65,
52
		240, 159, 135, 166 + countryCode.codePointAt(1) - 65
53
	]));
54
}
55
56
function getMsgId(num) {
57
	let i;
58
	if (ae.GetExtMsgHeaders(num).toLowerCase().slice(0, 11) === "message-id:") {
59
		i = 0;
60
	} else {
61
		i = ae.GetExtMsgHeaders(num).toLowerCase().indexOf("\nmessage-id:");
62
		if (i < 1) return "ERR";
63
		i++;
64
	}
65
66
	const x = ae.GetExtMsgHeaders(num).slice(i + 11).trim();
67
	if (x[0] !== "<") return "ERR2";
68
	return x.slice(1, x.indexOf(">"));
69
}
70
71
function displayMsg(isInt, num) {
72
	document.getElementById("midright").scroll(0, 0);
73
74
	const ts = isInt? ae.GetIntMsgTime(num) : ae.GetExtMsgTime(num);
75
76
	document.getElementById("btn_reply").disabled = false;
77
	document.getElementById("btn_reply").onclick = function() {
78
		document.getElementById("write_recv").value = isInt? ae.GetIntMsgFrom(num) : ae.GetExtMsgFrom(num);
79
		document.getElementById("write_subj").value = "Re: " + (isInt ? ae.GetIntMsgTitle(num) : ae.GetExtMsgTitle(num));
80
		document.getElementById("write_rply").textContent = (isInt? "" : getMsgId(num));
81
		document.getElementById("btn_write").click();
82
		document.getElementById("div_write_1").hidden = false;
83
		document.getElementById("div_write_2").hidden = true;
84
		document.getElementById("write_body").focus();
85
		for (const opt of document.getElementById("write_from").options) {
86
			if (opt.value === (isInt ? ae.GetIntMsgTo(num) : ae.GetExtMsgTo(num))) {
87
				opt.selected = true;
88
			}
89
		}
90
	};
91
92
	document.getElementById("msg").hidden = false;
93
	document.getElementById("msg").getElementsByTagName("h1")[0].textContent = isInt ? ae.GetIntMsgTitle(num) : ae.GetExtMsgTitle(num);
94
	document.getElementById("msg").getElementsByTagName("pre")[0].textContent = isInt ? ae.GetIntMsgBody(num) : ae.GetExtMsgBody(num);
95
96
	document.getElementById("readmsg_to").textContent = isInt ? ae.GetIntMsgTo(num) : ae.GetExtMsgTo(num);
97
	document.getElementById("readmsg_date").children[0].textContent = new Date(ts * 1000).toISOString().slice(0, 19).replace("T", " ");
98
99
	if (!isInt) {
100
		document.getElementById("readmsg_ip").hidden = false;
101
		document.getElementById("readmsg_country").hidden = false;
102
		document.getElementById("readmsg_tls").hidden = false;
103
		document.getElementById("readmsg_greet").hidden = false;
104
		document.getElementById("readmsg_timing").hidden = false;
105
		document.getElementById("readmsg_envfrom").hidden = false;
106
107
		const cc = ae.GetExtMsgCountry(num);
108
109
		document.getElementById("readmsg_ip").children[0].textContent = ae.GetExtMsgIp(num);
110
		document.getElementById("readmsg_country").textContent = getCountryFlag(cc) + " " + getCountryName(cc);
111
		document.getElementById("readmsg_tls").children[0].textContent = ae.GetExtMsgTLS(num);
112
		document.getElementById("readmsg_greet").children[0].textContent = ae.GetExtMsgGreet(num);
113
		document.getElementById("readmsg_envfrom").textContent = ae.GetExtMsgFrom(num);
114
115
		let flagText = "";
116
		if (!ae.GetExtMsgFlagVPad(num)) flagText += "<abbr title=\"Invalid padding\">PAD</abbr> ";
117
		if (!ae.GetExtMsgFlagVSig(num)) flagText += "<abbr title=\"Invalid signature\">SIG</abbr> ";
118
		if (!ae.GetExtMsgFlagPExt(num)) flagText += "<abbr title=\"The sender did not use the Extended (ESMTP) protocol\">SMTP</abbr> ";
119
		if (!ae.GetExtMsgFlagQuit(num)) flagText += "<abbr title=\"The sender did not issue the required QUIT command\">QUIT</abbr> ";
120
		if (ae.GetExtMsgFlagRare(num)) flagText += "<abbr title=\"The sender issued unusual command(s)\">RARE</abbr> ";
121
		if (ae.GetExtMsgFlagFail(num)) flagText += "<abbr title=\"The sender issued invalid command(s)\">FAIL</abbr> ";
122
		if (ae.GetExtMsgFlagPErr(num)) flagText += "<abbr title=\"The sender violated the protocol\">PROT</abbr> ";
123
		document.getElementById("readmsg_flags").children[0].innerHTML = flagText.trim();
124
	} else {
125
		document.getElementById("readmsg_ip").hidden = true;
126
		document.getElementById("readmsg_country").hidden = true;
127
		document.getElementById("readmsg_tls").hidden = true;
128
		document.getElementById("readmsg_greet").hidden = true;
129
		document.getElementById("readmsg_timing").hidden = true;
130
		document.getElementById("readmsg_envfrom").hidden = true;
131
132
		let symbol = "<span title=\"Invalid level\">&#x26a0;</span>";
133
		if (ae.GetIntMsgFrom(num) === "system") {if (ae.GetIntMsgLevel(num) === 3) symbol = "<span title=\"System\">&#x1f162;</span>";} // S (System)
134
		else if (ae.GetIntMsgLevel(num) === 0) symbol = "<span title=\"Level 0 User\">&#x1f10c;</span>"; // 0
135
		else if (ae.GetIntMsgLevel(num) === 1) symbol = "<span title=\"Level 1 User\">&#x278a;</span>"; // 1
136
		else if (ae.GetIntMsgLevel(num) === 2) symbol = "<span title=\"Level 2 User\">&#x278b;</span>"; // 2
137
		else if (ae.GetIntMsgLevel(num) === 3) symbol = "<span title=\"Administrator\">&#x1f150;</span>"; // A (Admin)
138
		document.getElementById("readmsg_from").innerHTML = symbol + " " + ae.GetIntMsgFrom(num);
139
140
		let flagText = "";
141
		if (!ae.GetIntMsgFlagVPad(num)) flagText += "<abbr title=\"Invalid padding\">PAD</abbr> ";
142
		if (!ae.GetIntMsgFlagVSig(num)) flagText += "<abbr title=\"Invalid signature\">SIG</abbr> ";
143
		document.getElementById("readmsg_flags").children[0].innerHTML = flagText.trim();
144
	}
145
}
146
147
// Interface
148
function addMsg(isInt, i) {
149
	const inbox = document.getElementById("tbl_inbox");
150
	const sent = document.getElementById("tbl_outbx");
151
152
	const isSent = false; //TODO
153
	const table = isSent ? sent : inbox;
154
155
	const row = table.insertRow(-1);
156
	const cellTime = row.insertCell(-1);
157
	const cellSubj = row.insertCell(-1);
158
	const cellSnd1 = row.insertCell(-1);
159
	const cellSnd2 = row.insertCell(-1);
160
161
	const ts = isInt? ae.GetIntMsgTime(i) : ae.GetExtMsgTime(i);
162
	cellTime.setAttribute("data-ts", ts);
163
	cellTime.textContent = new Date(ts * 1000).toISOString().slice(0, 10);
164
165
	cellSubj.textContent = isInt? ae.GetIntMsgTitle(i) : ae.GetExtMsgTitle(i);
166
167
	if (isInt) {
168
		cellSnd1.textContent = ae.GetIntMsgFrom(i);
169
		cellSnd1.className = (ae.GetIntMsgFrom(i).length === 16) ? "mono" : "";
170
	} else {
171
		const from1 = ae.GetExtMsgFrom(i);
172
		const from2 = from1.substring(from1.indexOf("@") + 1);
173
		const cc = ae.GetExtMsgCountry(i);
174
175
		cellSnd1.textContent = from1.substring(0, from1.indexOf("@"));
176
177
		const flag = document.createElement("abbr");
178
		flag.textContent = getCountryFlag(cc);
179
		flag.title = getCountryName(cc);
180
		cellSnd2.appendChild(flag);
181
182
		const fromText = document.createElement("span");
183
		fromText.textContent = " " + from2;
184
		cellSnd2.appendChild(fromText);
185
	}
186
187
//	divDel.innerHTML = "<input class=\"delMsg\" type=\"checkbox\" data-id=\"" + ae.GetIntMsgIdHex(i) + "\">";
188
189
	row.onclick = function() {
190
		displayMsg(isInt, i);
191
	};
192
/*
193
	cellDel.children[0].onchange = function() {
194
		if (!divDel.children[0].checked) {
195
			const checkboxes = elmt.getElementsByTagName("input");
196
			let checked = false;
197
198
			for (let j = 0; j < checkboxes.length; j++) {
199
				if (checkboxes[j].checked) {
200
					checked = true;
201
					break;
202
				}
203
			}
204
205
			if (!checked) {
206
				document.getElementById(isSent ? "btn_sentdel" : "btn_msgdel").hidden = true;
207
				return;
208
			}
209
		}
210
211
		document.getElementById(isSent? "btn_sentdel" : "btn_msgdel").hidden = false;
212
	};
213
*/
214
}
215
216
function getRowsPerPage() {
217
	const tbl = document.getElementById("tbl_inbox");
218
	tbl.innerHTML = "";
219
	const row = tbl.insertRow(-1);
220
	const cell = row.insertCell(-1);
221
	cell.textContent = "0";
222
223
	const rowsPerPage = Math.floor(getComputedStyle(document.getElementById("div_inbox")).height.replace("px", "") / getComputedStyle(document.querySelector("#tbl_inbox > tbody > tr:first-child")).height.replace("px", "")) - 1; // -1 allows space for 'load more'
224
	tbl.innerHTML = "";
225
	return rowsPerPage;
226
}
227
228
function addMessages() {
229
	const rowsPerPage = getRowsPerPage();
230
	let skipMsgs = rowsPerPage * tabs[TAB_INBOX].cur;
231
232
	const maxExt = ae.GetExtMsgCount();
233
	const maxInt = ae.GetIntMsgCount();
234
235
	tabs[TAB_INBOX].max = Math.floor((maxExt + maxInt) / rowsPerPage);
236
237
	let numExt = 0;
238
	let numInt = 0;
239
	let numAdd = 0;
240
241
	while (numAdd < rowsPerPage) {
242
		const tsInt = (numInt < maxInt) ? ae.GetIntMsgTime(numInt) : -1;
243
		const tsExt = (numExt < maxExt) ? ae.GetExtMsgTime(numExt) : -1;
244
		if (tsInt === -1 && tsExt === -1) break;
245
246
		if (tsInt !== -1 && (tsExt === -1 || tsInt > tsExt)) {
247
			if (skipMsgs > 0) skipMsgs--; else {addMsg(true, numInt); numAdd++;}
248
			numInt++;
249
		} else if (tsExt !== -1) {
250
			if (skipMsgs > 0) skipMsgs--; else {addMsg(false, numExt); numAdd++;}
251
			numExt++;
252
		}
253
	}
254
255
	if (ae.GetReadyMsgKilos() < ae.GetTotalMsgKilos()) {
256
		const inbox = document.getElementById("tbl_inbox");
257
		const row = inbox.insertRow(-1);
258
		const cell = row.insertCell(-1);
259
		cell.textContent = "Load more (" + (ae.GetTotalMsgKilos() - ae.GetReadyMsgKilos()) + " KiB left)";
260
261
		row.onclick = function() {
262
			this.onclick = "";
263
264
			ae.Message_Browse(false, function(successBrowse) {
265
				document.getElementById("tbl_inbox").style.opacity = 1;
266
267
				if (successBrowse) {
268
					addMessages();
269
					if (tabs[tab].cur < tabs[tab].max) document.getElementById("btn_rght").disabled = false;
270
				}
271
			});
272
		};
273
	}
274
}
275
276
function addNotes() {
277
	const tbl = document.getElementById("tbd_texts");
278
279
	for (let i = 0; i < ae.GetNoteCount(); i++) {
280
		const row = tbl.insertRow(-1);
281
		let cell;
282
		cell = row.insertCell(-1); cell.textContent = new Date(ae.GetNoteTime(i) * 1000).toISOString().slice(0, 10);
283
		cell = row.insertCell(-1); cell.textContent = ae.GetNoteTitle(i);
284
		cell = row.insertCell(-1); cell.textContent = ""; // Format
285
		cell = row.insertCell(-1); cell.textContent = ""; // Size
286
		cell = row.insertCell(-1); cell.innerHTML = "<button type=\"button\">X</button>";
287
	}
288
}
289
290
function updateAddressCounts() {
291
	document.getElementById("limit_normal").textContent = (ae.GetAddressCountNormal() + "/" + ae.GetAddressLimitNormal(ae.GetUserLevel())).padStart(ae.GetAddressLimitNormal(ae.GetUserLevel()) > 9 ? 5 : 1);
292
	document.getElementById("limit_shield").textContent = (ae.GetAddressCountShield() + "/" + ae.GetAddressLimitShield(ae.GetUserLevel())).padStart(ae.GetAddressLimitShield(ae.GetUserLevel()) > 9 ? 5 : 1);
293
	document.getElementById("limit_total").textContent = ((ae.GetAddressCountNormal() + ae.GetAddressCountShield()) + "/" + ae.GetAddrPerUser()).padStart(5);
294
}
295
296
function addAccountToTable(i) {
297
	const tblAccs = document.getElementById("tbd_accs");
298
	const row = tblAccs.insertRow(-1);
299
	let cell;
300
	cell = row.insertCell(-1); cell.textContent = ae.Admin_GetUserPkHex(i);
301
	cell = row.insertCell(-1); cell.textContent = ae.Admin_GetUserSpace(i);
302
	cell = row.insertCell(-1); cell.textContent = ae.Admin_GetUserNAddr(i);
303
	cell = row.insertCell(-1); cell.textContent = ae.Admin_GetUserSAddr(i);
304
	cell = row.insertCell(-1); cell.textContent = ae.Admin_GetUserLevel(i);
305
	cell = row.insertCell(-1); cell.innerHTML = "<button type=\"button\" autocomplete=\"off\">+</button>";
306
	cell = row.insertCell(-1); cell.innerHTML = "<button type=\"button\" autocomplete=\"off\">&minus;</button>";
307
	cell = row.insertCell(-1); cell.innerHTML = "<button type=\"button\" autocomplete=\"off\">X</button>";
308
}
309
310
function reloadAccount() {
311
	// Limits
312
	const tblLimits = document.getElementById("tbl_limits");
313
	for (let i = 0; i < 4; i++) {
314
		tblLimits.rows[i].cells[1].children[0].value = ae.GetStorageLimit(i) + 1;
315
		tblLimits.rows[i].cells[2].children[0].value = ae.GetAddressLimitNormal(i);
316
		tblLimits.rows[i].cells[3].children[0].value = ae.GetAddressLimitShield(i);
317
	}
318
319
	// Accounts
320
	const tblAccs = document.getElementById("tbd_accs");
321
322
	// All: Our account
323
	const row = tblAccs.insertRow(-1);
324
	let cell;
325
	cell = row.insertCell(-1); cell.textContent = ae.GetUserPkHex();
326
	cell = row.insertCell(-1); cell.textContent = Math.round(ae.GetTotalMsgKilos() / 1024);
327
	cell = row.insertCell(-1); cell.textContent = ae.GetAddressCountNormal();
328
	cell = row.insertCell(-1); cell.textContent = ae.GetAddressCountShield();
329
	cell = row.insertCell(-1); cell.textContent = ae.GetUserLevel();
330
	cell = row.insertCell(-1); cell.innerHTML = "<button type=\"button\" autocomplete=\"off\" disabled=\"disabled\">+</button>";
331
	cell = row.insertCell(-1); cell.innerHTML = "<button id=\"btn_downme\" type=\"button\" autocomplete=\"off\" disabled=\"disabled\">&minus;</button>";
332
	cell = row.insertCell(-1); cell.innerHTML = "<button id=\"btn_killme\" type=\"button\" autocomplete=\"off\" disabled=\"disabled\">X</button>";
333
334
	// Admin: Other accounts
335
	if (ae.IsUserAdmin()) {
336
		for (let i = 0; i < ae.Admin_GetUserCount(); i++) {
337
			addAccountToTable(i);
338
		}
339
	}
340
341
	document.getElementById("txt_reg").disabled = !ae.IsUserAdmin();
342
	document.getElementById("btn_reg").disabled = !ae.IsUserAdmin();
343
344
	// Contacts
345
	for (let i = 0; i < ae.GetContactCount(); i++) {
346
		addContact(
347
			ae.GetContactMail(i),
348
			ae.GetContactName(i),
349
			ae.GetContactNote(i)
350
		);
351
	}
352
353
	// Addresses
354
	for (let i = 0; i < ae.GetAddressCount(); i++) {
355
		addAddress(i);
356
	}
357
358
	updateAddressCounts();
359
}
360
361 View Code Duplication
function deleteAddress(addr) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
362
	let btns = document.getElementById("tbl_addrs").getElementsByTagName("button");
363
	for (let i = 0; i < btns.length; i++) btns[i].disabled = true;
364
365
	let addressToDelete = -1;
366
367
	for (let i = 0; i < ae.GetAddressCount(); i++) {
368
		if (addr === ae.GetAddress(i)) {
369
			addressToDelete = i;
370
			break;
371
		}
372
	}
373
374
	if (addressToDelete === -1) return;
375
376
	ae.Address_Delete(addressToDelete, function(success) {
377
		if (success) {
378
			document.getElementById("tbl_addrs").deleteRow(addressToDelete);
379
			document.getElementById("write_from").remove(addressToDelete);
380
			updateAddressCounts();
381
382
			if (ae.GetAddressCountNormal() < ae.GetAddressLimitNormal(ae.GetUserLevel())) document.getElementById("btn_address_create_normal").disabled = false;
383
			if (ae.GetAddressCountShield() < ae.GetAddressLimitShield(ae.GetUserLevel())) document.getElementById("btn_address_create_shield").disabled = false;
384
385
			ae.Private_Update(function(success2) {
386
				if (!success2) console.log("Failed to update the Private field");
387
388
				btns = document.getElementById("tbl_addrs").getElementsByTagName("button");
389
				for (let i = 0; i < btns.length; i++) btns[i].disabled = false;
390
			});
391
		} else {
392
			console.log("Failed to delete address");
393
394
			btns = document.getElementById("tbl_addrs").getElementsByTagName("button");
395
			for (let i = 0; i < btns.length; i++) btns[i].disabled = false;
396
		}
397
	});
398
}
399
400 View Code Duplication
function shieldMix(addr) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
401
	let newAddr = "";
402
403
	for (let i = 0; i < 16; i++) {
404
		switch (addr.charAt(i)) {
405
			case '1':
406
				newAddr += "1iIlL".charAt(Math.floor(Math.random() * 5));
407
				break;
408
			case '0':
409
				newAddr += "0oO".charAt(Math.floor(Math.random() * 3));
410
				break;
411
			case 'w':
412
				newAddr += "VvWw".charAt(Math.floor(Math.random() * 4));
413
				break;
414
			default:
415
				newAddr += (Math.random() > 0.5) ? addr.charAt(i) : addr.charAt(i).toUpperCase();
416
		}
417
	}
418
419
	return newAddr;
420
}
421
422
function addAddress(num) {
423
	const addrTable = document.getElementById("tbl_addrs");
424
	const row = addrTable.insertRow(-1);
425
	const cellAddr = row.insertCell(-1);
426
	const cellChk1 = row.insertCell(-1);
427
	const cellChk2 = row.insertCell(-1);
428
	const cellChk3 = row.insertCell(-1);
429
	const cellBtnD = row.insertCell(-1);
430
431
	cellAddr.textContent = ae.GetAddress(num);
432
	cellAddr.onclick = function() {
433
		if (cellAddr.textContent.length === 16)
434
			navigator.clipboard.writeText(shieldMix(cellAddr.textContent) + "@" + ae.GetDomainEml());
1 ignored issue
show
Bug introduced by
The variable navigator seems to be never declared. If this is a global, consider adding a /** global: navigator */ 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...
435
		else
436
			navigator.clipboard.writeText(cellAddr.textContent + "@" + ae.GetDomainEml());
437
	};
438
439
	cellChk1.innerHTML = ae.GetAddressAccExt(num) ? "<input type=\"checkbox\" checked=\"checked\">" : "<input type=\"checkbox\">";
440
	cellChk2.innerHTML = ae.GetAddressAccInt(num) ? "<input type=\"checkbox\" checked=\"checked\">" : "<input type=\"checkbox\">";
441
	cellChk3.innerHTML = ae.GetAddressUse_Gk(num) ? "<input type=\"checkbox\" checked=\"checked\">" : "<input type=\"checkbox\">";
442
443
	cellBtnD.innerHTML = "<button type=\"button\">X</button>";
444
	cellBtnD.onclick = function() {deleteAddress(cellAddr.textContent);};
445
446
	const opt = document.createElement("option");
447
	opt.value = cellAddr.textContent;
448
	opt.textContent = cellAddr.textContent + "@" + ae.GetDomainEml();
449
	document.getElementById("write_from").appendChild(opt);
450
}
451
452
document.getElementById("btn_dele").onclick = function() {
453
	this.blur();
454
455
	if (tab === TAB_WRITE) {
456
		tabs[tab].cur = 0;
457
		updateTab();
458
459
		document.getElementById("write_recv").value = "";
460
		document.getElementById("write_subj").value = "";
461
		document.getElementById("write_body").value = "";
462
463
		document.getElementById("write_recv").focus();
464
	}
465
};
466
467
document.getElementById("btn_updt").onclick = function() {
468
	const btn = this;
469
	btn.disabled = true;
470
	btn.blur();
471
472
	if (tab === TAB_INBOX) {
473
		document.getElementById("tbl_inbox").style.opacity = 0.5;
474
475
		ae.Message_Browse(true, function(successBrowse) {
476
			document.getElementById("tbl_inbox").style.opacity = 1;
477
478
			if (successBrowse) {
479
				addMessages();
480
				addNotes();
481
				btn.disabled = false;
482
			} else {
483
				console.log("Failed to refresh");
484
				btn.disabled = false;
485
			}
486
		});
487
	}
488
};
489
490
function addContact(mail, name, note) {
491
	const tbl = document.getElementById("tbl_ctact");
492
	const row = tbl.insertRow(-1);
493
	const cellMail = row.insertCell(-1);
494
	const cellName = row.insertCell(-1);
495
	const cellNote = row.insertCell(-1);
496
	const cellBtnD = row.insertCell(-1);
497
498
	cellMail.textContent = mail;
499
	cellName.textContent = name;
500
	cellNote.textContent = note;
501
	cellBtnD.innerHTML = "<button type=\"button\">X</button>";
502
503
	cellMail.contentEditable = true;
504
	cellName.contentEditable = true;
505
	cellNote.contentEditable = true;
506
507
	cellBtnD.onclick = function() {row.remove();};
508
}
509
510
document.getElementById("btn_newcontact").onclick = function() {
511
	addContact("", "", "");
512
};
513
514
document.getElementById("btn_savecontacts").onclick = function() {
515
	while (ae.GetContactCount() > 0) {
516
		ae.DeleteContact(0);
517
	}
518
519
	for (const row of document.getElementById("tbl_ctact").rows) {
520
		ae.AddContact(row.cells[0].textContent, row.cells[1].textContent, row.cells[2].textContent);
521
	}
522
523
	const btn = this;
524
	btn.disabled = true;
525
526
	ae.Private_Update(function(success) {
527
		btn.disabled = false;
528
529
		if (!success) {
530
			console.log("Failed contacts update");
531
		}
532
	});
533
};
534
535
function updateTab() {
536
	switch (tab) {
537
		case TAB_INBOX:
538
			addMessages();
539
		break;
540
541
		case TAB_WRITE:
542
			switch (tabs[tab].cur) {
543
				case 0: // Write
544
					document.getElementById("div_write_1").hidden = false;
545
					document.getElementById("div_write_2").hidden = true;
546
					document.getElementById("write_body").focus();
547
				break;
548
549
				case 1: // Verify
550
					ae.Address_Lookup(document.getElementById("write_recv").value, function(pk) {
551
						if (pk) {
552
							document.getElementById("div_write_1").hidden = true;
553
							document.getElementById("div_write_2").hidden = false;
554
555
							document.getElementById("write2_from").textContent = document.getElementById("write_from").value + "@" + ae.GetDomainEml();
556
							document.getElementById("write2_recv").textContent = document.getElementById("write_recv").value;
557
							document.getElementById("write2_pkey").textContent = sodium.to_hex(pk);
1 ignored issue
show
Bug introduced by
The variable sodium seems to be never declared. If this is a global, consider adding a /** global: sodium */ 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...
558
559
							document.getElementById("write2_subj").textContent = document.getElementById("write_subj").value;
560
							document.getElementById("write2_rply").textContent = document.getElementById("write_rply").textContent;
561
							document.getElementById("write2_body").textContent = document.getElementById("write_body").value;
562
						} else {
563
							console.log("Failed lookup");
564
						}
565
					});
566
				break;
567
568
				case 2: // Send
569
					ae.Message_Create(
570
						document.getElementById("write_subj").value,
571
						document.getElementById("write_body").value,
572
						document.getElementById("write_from").value,
573
						document.getElementById("write_recv").value,
574
						document.getElementById("write_rply").textContent,
575
						(document.getElementById("write2_recv").textContent.indexOf("@") > 0) ? null : sodium.from_hex(document.getElementById("write2_pkey").textContent),
1 ignored issue
show
Bug introduced by
The variable sodium seems to be never declared. If this is a global, consider adding a /** global: sodium */ 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...
576
						function(success) {
577
							if (success) {
578
								console.log("Sent ok");
579
							} else {
580
								console.log("Failed sending");
581
							}
582
						}
583
					);
584
				break;
585
			}
586
		break;
587
588
		case TAB_NOTES:
589
			for (let i = 0; i <= tabs[tab].max; i++) {
590
				document.getElementById("div_notes").children[i].hidden = (i !== tabs[tab].cur);
591
			}
592
		break;
593
594
		case TAB_ADMIN:
595
			for (let i = 0; i <= tabs[tab].max; i++) {
596
				document.getElementById("div_admin").children[i].hidden = (i !== tabs[tab].cur);
597
			}
598
		break;
599
	}
600
601
	document.getElementById("btn_left").disabled = (tabs[tab].cur === 0);
602
	document.getElementById("btn_rght").disabled = (tabs[tab].cur === tabs[tab].max);
603
}
604
605
document.getElementById("btn_left").onclick = function() {
606
	tabs[tab].cur--;
607
	if (tabs[tab].cur === 0) this.disabled = true;
608
	if (tabs[tab].cur < tabs[tab].max) document.getElementById("btn_rght").disabled = false;
609
	updateTab();
610
	this.blur();
611
};
612
613
document.getElementById("btn_rght").onclick = function() {
614
	tabs[tab].cur++;
615
	if (tabs[tab].cur === tabs[tab].max) this.disabled = true;
616
	document.getElementById("btn_left").disabled = false;
617
	updateTab();
618
	this.blur();
619
};
620
621
const buttons = document.querySelector("#main1 > .top").getElementsByTagName("button");
622
for (let i = 0; i < buttons.length; i++) {
623
	buttons[i].onclick = function() {
624
		tab = i;
625
626
		for (let j = 0; j < buttons.length; j++) {
627
			document.querySelector("#main1 > .mid").children[j].hidden = (tab !== j);
628
			buttons[j].disabled = (tab === j);
629
		}
630
631
		document.getElementById("btn_left").disabled = (tabs[tab].cur === 0);
0 ignored issues
show
Bug introduced by
The variable tab is changed as part of the for loop for example by i on line 624. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
632
		document.getElementById("btn_rght").disabled = (tabs[tab].cur === tabs[tab].max);
633
		document.getElementById("btn_dele").disabled = !tabs[tab].btnDele;
634
		document.getElementById("btn_updt").disabled = !tabs[tab].btnUpdt;
635
	};
636
}
637
638
function addressCreate(addr) {
639
	const btnN = document.getElementById("btn_address_create_normal");
640
	const btnS = document.getElementById("btn_address_create_shield");
641
	btnN.disabled = true;
642
	btnS.disabled = true;
643
644
	ae.Address_Create(addr, function(success1) {
645
		if (success1) {
646
			ae.Private_Update(function(success2) {
647
				addAddress(ae.GetAddressCount() - 1);
648
				if (addr !== "SHIELD") document.getElementById("txt_address_create_normal").value = "";
649
				updateAddressCounts();
650
651
				if (!success2) console.log("Failed to update the Private field");
652
653
				if (ae.GetAddressCountNormal() < ae.GetAddressLimitNormal(ae.GetUserLevel())) btnN.disabled = false;
654
				if (ae.GetAddressCountShield() < ae.GetAddressLimitShield(ae.GetUserLevel())) btnS.disabled = false;
655
			});
656
		} else {
657
			console.log("Failed to add address");
658
659
			if (ae.GetAddressCountNormal() < ae.GetAddressLimitNormal(ae.GetUserLevel())) btnN.disabled = false;
660
			if (ae.GetAddressCountShield() < ae.GetAddressLimitShield(ae.GetUserLevel())) btnS.disabled = false;
661
		}
662
	});
663
}
664
665
document.getElementById("btn_address_create_normal").onclick = function() {
666
	if (ae.GetAddressCountNormal() >= ae.GetAddressLimitNormal(ae.GetUserLevel())) return;
667
668
	const txtNewAddr = document.getElementById("txt_address_create_normal");
669
	if (!txtNewAddr.reportValidity()) return;
670
671
	addressCreate(txtNewAddr.value);
672
};
673
674
document.getElementById("btn_address_create_shield").onclick = function() {
675
	if (ae.GetAddressCountShield() >= ae.GetAddressLimitShield(ae.GetUserLevel())) return;
676
677
	addressCreate("SHIELD");
678
};
679
680
document.getElementById("btn_reg").onclick = function() {
681
	const btn = document.getElementById("btn_reg");
682
	const txt = document.getElementById("txt_reg");
683
	if (!txt.reportValidity()) return;
684
	btn.disabled = true;
685
686
	ae.Account_Create(txt.value, function(success) {
687
		if (success) {
688
			addAccountToTable(ae.Admin_GetUserCount() - 1);
689
			txt.value = "";
690
		}
691
692
		btn.disabled = false;
693
	});
694
};
695
696
document.getElementById("chk_downme").onclick = function() {document.getElementById("btn_downme").disabled = !this.checked;};
697
document.getElementById("chk_killme").onclick = function() {document.getElementById("btn_killme").disabled = !this.checked;};
698
699
document.getElementById("btn_notepad_savesep").onclick = function() {
700
	const np = document.getElementById("txt_notepad");
701
	np.disabled = true;
702
703
	ae.Message_StoreT("title", np.value, false, function(success) {
704
		if (success) {
705
			np.value = "";
706
			addNotes();
707
		}
708
709
		console.log("Failed to add text");
710
		np.disabled = false;
711
	});
712
};
713
714
document.getElementById("txt_skey").onkeyup = function(event) {
715
	if (event.key === "Enter") {
716
		event.preventDefault();
717
		document.getElementById("btn_enter").click();
718
	}
719
};
720
721
document.getElementById("btn_enter").onclick = function() {
722
	const txtSkey = document.getElementById("txt_skey");
723
	if (!txtSkey.reportValidity()) return;
724
725
	const btn = this;
726
	btn.disabled = true;
727
	document.getElementById("txt_skey").style.background = "#233";
728
729
	ae.SetKeys(txtSkey.value, function(successSetKeys) {
730
		if (successSetKeys) {
731
			ae.Account_Browse(0, function(successBrowse) {
732
				if (successBrowse) {
733
					txtSkey.value = "";
734
735
					reloadAccount();
736
					document.getElementById("div_begin").hidden = true;
737
					document.getElementById("div_main").style.display = "grid";
738
739
					document.getElementById("btn_updt").click();
740
				} else {
741
					console.log("Failed to enter");
742
					btn.disabled = false;
743
					document.getElementById("txt_skey").style.background = "#466";
744
					txtSkey.focus();
745
				}
746
			});
747
		} else {
748
			console.log("Invalid format for key");
749
			btn.disabled = false;
750
			document.getElementById("txt_skey").style.background = "#466";
751
			txtSkey.focus();
752
		}
753
	});
754
};
755
756
});
757