MeshMessenger text starts at bottom.

Ylian Saint-Hilaire committed Mar 21, 2021 at 13:16 UTC d5639f1121007bbf34df844f51b43987e4871b2c
3 files changed +66 -7
views/default-mobile.handlebars
+54 -4
@@ -677,9 +677,6 @@
677 </div>
678 <div style="padding:0;font-size:25px;background-color:#036;width:50px;border-radius:0 0 10px 0;height:36px">&#9664;</div>
679 </td>
680 - <td>
681 - <img src="/images/user-50.png" width=50 height=50 />
682 - </td>
680 <td>
681 <div style=margin-left:5px>
682 <strong style="font-size:large"><span id=p3userName></span></strong><br />
@@ -688,6 +685,7 @@
685 </tr>
686 </table>
687 <div id=p3info style="overflow-y:auto;position:absolute;top:55px;bottom:0px;width:100%">
688 + <img id="p2AccountImage" alt="" loading="lazy" width="128" height="128" onclick="account_manageImage(0)" src="images/user-256.png" style="position:absolute;right:8px;top:7px;border-radius:8px;box-shadow:0px 0px 7px #000" />
689 <div style="margin-left:8px">
690 <div id="p3AccountActions">
691 <div id="p2AccountSecurity" style="display:none">
@@ -1118,6 +1116,7 @@
1116 <div id="idx_dlgButtonBar" style="padding:10px;margin-bottom:20px">
1117 <input id="idx_dlgCancelButton" type="button" value="Cancel" style="float:right;width:80px;margin-left:5px" onclick="dialogclose(0)">
1118 <input id="idx_dlgOkButton" type="button" value="OK" style="float:right;width:80px" onclick="dialogclose(1)">
1119 + <div><input id="idx_dlgDeleteButton" type="button" value="Delete" style="display:none" onclick="dialogclose(2)" /></div>
1120 </div>
1121 </div>
1122 <div id=topMenu style="z-index:1000;background-color:#EEE;box-shadow:0px 0px 15px #666;font-family:Arial,Helvetica,sans-serif;border-radius:0px 0px 5px 5px;position:fixed;top:50px;right:5px;width:170px;display:none">
@@ -1311,6 +1310,14 @@
1310 QV('p3createMeshLink1', false);
1311 QV('p3createMeshLink2', false);
1312
1313 + // Update user image
1314 + if ((userinfo.flags != null) && (userinfo.flags & 1)) {
1315 + if (userinfo.accountImageRnd == null) { userinfo.accountImageRnd = Math.floor(Math.random() * 9999999999); }
1316 + Q('p2AccountImage').src = 'userimage.ashx?rnd=' + userinfo.accountImageRnd;
1317 + } else {
1318 + Q('p2AccountImage').src = 'images/user-256.png';
1319 + }
1320 +
1321 if (typeof userinfo.passchange == 'number') {
1322 if (userinfo.passchange == -1) { QH('p2nextPasswordUpdateTime', " - Reset on next login."); }
1323 else if ((passRequirements != null) && (typeof passRequirements.reset == 'number')) {
@@ -1568,7 +1575,7 @@
1575 }
1576 case 'previousLogins': {
1577 if ((xxdialogMode == 2) && (xxdialogTag == 'previousLogins')) {
1571 - var x = '', c = 'BBB';
1578 + var x = '', c = 'BBB', xx = '';
1579 if (message.events.length == 0) {
1580 x += 'No previous login.';
1581 } else {
@@ -2045,6 +2052,48 @@
2052 meshserver.send({ action: 'previousLogins' });
2053 }
2054
2055 + function account_manageImage(mode) {
2056 + if (xxdialogMode) return;
2057 + var user = (mode == 0) ? userinfo : currentUser;
2058 + var x = '<input id=p2file type=file style=width:100% accept="image/*" onchange=account_manageImageEx()><div style=width:100%><canvas id=p2canvas width=256 height=256 style="width:256px;height:256px;margin-left:12px;margin-top:8px;border-radius:16px;box-shadow: 0px 0px 15px #000" onclick=account_canvasClick() /></div>';
2059 + setDialogMode(2, "Manage Account Image", 7, account_manageImageEx2, x, user._id);
2060 + var ctx = Q('p2canvas').getContext('2d');
2061 + if (user.accountImageRnd == null) { user.accountImageRnd = Math.floor(Math.random() * 9999999999); }
2062 + var arg = '';
2063 + if (mode == 1) { arg = '&id=' + user._id.split('/')[2]; }
2064 + var myImg = new Image();
2065 + myImg.onload = function () { ctx.clearRect(0, 0, 256, 256); ctx.drawImage(myImg, 0, 0); };
2066 + myImg.src = ((user.flags != null) && (user.flags & 1)) ? ('userimage.ashx?rnd=' + user.accountImageRnd + arg) : 'images/user-256.png';
2067 + QE('idx_dlgDeleteButton', (user.flags != null) && (user.flags & 1));
2068 + QE('idx_dlgOkButton', false);
2069 + }
2070 +
2071 + function account_canvasClick() { Q('p2file').click(); }
2072 +
2073 + function account_manageImageEx() {
2074 + var file = Q('p2file').files[0];
2075 + var img = new Image;
2076 + img.onload = function () {
2077 + var cx = 0, cy = 0, min = Math.min(img.width, img.height);
2078 + if (img.width > min) { cx = (img.width - min) / 2; }
2079 + if (img.height > min) { cy = (img.height - min) / 2; }
2080 + var ctx = Q('p2canvas').getContext('2d');
2081 + ctx.imageSmoothingEnabled = true;
2082 + ctx.webkitImageSmoothingEnabled = true;
2083 + ctx.mozImageSmoothingEnabled = true;
2084 + ctx.clearRect(0, 0, 256, 256);
2085 + ctx.drawImage(img, cx, cy, min, min, 0, 0, 256, 256);
2086 + QE('idx_dlgOkButton', true);
2087 + }
2088 + img.src = URL.createObjectURL(file);
2089 + }
2090 +
2091 + function account_manageImageEx2(b, userid) {
2092 + // Send updated image, or 0 if we pressed the delete button
2093 + meshserver.send({ action: 'updateUserImage', userid: userid, image: (b == 2) ? 0 : Q('p2canvas').toDataURL('image/jpeg', 0.8) });
2094 + //meshserver.send({ action: 'updateUserImage', image: (b == 2)?0:Q('p2canvas').toDataURL('image/png', 0.8) });
2095 + }
2096 +
2097 function toggleNightMode() {
2098 if (xxdialogMode) return;
2099 var cNightMode = getstore('nightMode', '0');
@@ -5621,6 +5670,7 @@
5670 QV('idx_dlgOkButton', b & 1);
5671 QV('idx_dlgCancelButton', b & 2);
5672 QV('id_dialogclose', (b & 2) || (b & 8));
5673 + QV('idx_dlgDeleteButton', b & 4);
5674 QV('idx_dlgButtonBar', b & 7);
5675 if (y) QH('id_dialogtitle', y);
5676 for (var i = 1; i < 24; i++) { QV('dialog' + i, i == x); } // Edit this line when more dialogs are added
views/default.handlebars
-2
@@ -2683,8 +2683,6 @@
2683 if (userinfo._id == message.event.account._id) {
2684 var newsiteadmin = message.event.account.siteadmin?message.event.account.siteadmin:0;
2685 var oldsiteadmin = userinfo.siteadmin?userinfo.siteadmin:0;
2686 - var newflags = message.event.account.flags?message.event.account.flags:0;
2687 - var oldflags = userinfo.flags?userinfo.flags:0;
2686 if ((message.event.account.quota != userinfo.quota) || (((userinfo.siteadmin & 8) == 0) && ((message.event.account.siteadmin & 8) != 0))) { meshserver.send({ action: 'files' }); }
2687 var oldgroups = userinfo.groups;
2688 userinfo = message.event.account;
views/messenger.handlebars
+12 -1
@@ -27,7 +27,7 @@
27 <div style="padding-top:9px;padding-left:6px;font-size:20px;display:inline-block"><b><span id="xtitle"></span></b></div>
28 </div>
29 <div id="xmiddle" style="position:absolute;left:0;right:0;top:38px;bottom:36px;font-size:18px">
30 - <div id="xmsgparent" style="position:absolute;left:0;right:0;top:0;bottom:0;overflow-y:scroll">
30 + <div id="xmsgparent" style="position:absolute;left:0;right:0;bottom:0;max-height:100%;overflow-y:auto">
31 <div id="xmsg" style="padding:5px"></div>
32 <div id="typingIndicator" style="display:none;margin-left:5px;clear:both"><img src="images/3dots-24.gif" srcset="images/3dots-48.gif 2x" /></div>
33 </div>
@@ -379,6 +379,17 @@
379 if (typeof data == 'string') {
380 try { data = JSON.parse(data); } catch (ex) { console.log('Unable to parse', data); return; }
381 //console.log('RECV', data);
382 +
383 + // Handle control command
384 + if (data.ctrlChannel == '102938') {
385 + switch (data.type) {
386 + case 'ping': { send({ ctrlChannel: '102938', type: 'pong' }); break; }
387 + case 'pong': { break; }
388 + }
389 + return;
390 + }
391 +
392 + // Handle command
393 switch (data.action) {
394 case 'chat': { displayRemote(data.msg); updateRemoteOutText(false); break; } // Incoming chat message.
395 case 'outtext': { updateRemoteOutText(data.value); break; }