Added remote typing icon to messenger.

Ylian Saint-Hilaire committed Feb 2, 2021 at 14:08 UTC f5049055d249da7c8977f8dbbbfb2f836c45d299
4 files changed +42 -12
agents/meshcore.js
+11 -9
@@ -580,9 +580,9 @@ function getIpLocationDataEx(func) {
580
581 // Remove all Gateway MAC addresses for interface list. This is useful because the gateway MAC is not always populated reliably.
582 function clearGatewayMac(str) {
583 - if (str == null) return null;
583 + if (typeof str != 'string') return null;
584 var x = JSON.parse(str);
585 - for (var i in x.netif) { if (x.netif[i].gatewaymac) { delete x.netif[i].gatewaymac } }
585 + for (var i in x.netif) { try { if (x.netif[i].gatewaymac) { delete x.netif[i].gatewaymac } } catch (ex) { } }
586 return JSON.stringify(x);
587 }
588
@@ -4207,13 +4207,15 @@ function sendNetworkUpdateNagle() { if (sendNetworkUpdateNagleTimer != null) { c
4207 function sendNetworkUpdate(force) {
4208 sendNetworkUpdateNagleTimer = null;
4209
4210 - // Update the network interfaces information data
4211 - var netInfo = { netif2: require('os').networkInterfaces() };
4212 - if (netInfo.netif2) {
4213 - netInfo.action = 'netinfo';
4214 - var netInfoStr = JSON.stringify(netInfo);
4215 - if ((force == true) || (clearGatewayMac(netInfoStr) != clearGatewayMac(lastNetworkInfo))) { mesh.SendCommand(netInfo); lastNetworkInfo = netInfoStr; }
4216 - }
4210 + try {
4211 + // Update the network interfaces information data
4212 + var netInfo = { netif2: require('os').networkInterfaces() };
4213 + if (netInfo.netif2) {
4214 + netInfo.action = 'netinfo';
4215 + var netInfoStr = JSON.stringify(netInfo);
4216 + if ((force == true) || (clearGatewayMac(netInfoStr) != clearGatewayMac(lastNetworkInfo))) { mesh.SendCommand(netInfo); lastNetworkInfo = netInfoStr; }
4217 + }
4218 + } catch (ex) { }
4219 }
4220
4221 // Called periodically to check if we need to send updates to the server
public/images/3dots-24.gif
Binary files /dev/null and b/public/images/3dots-24.gif differ
public/images/3dots-48.gif
Binary files /dev/null and b/public/images/3dots-48.gif differ
views/messenger.handlebars
+31 -3
@@ -29,13 +29,14 @@
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">
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>
34 </div>
35 <div id="xbottom" style="position:absolute;left:0;right:0;bottom:0px;height:36px;background-color:#036;font-size:18px">
36 <table style="width:100%">
37 <tr>
38 <td>
38 - <input id="xouttext" type="text" style="box-sizing:border-box;width:100%;font-size:18px" onfocus=onUserInputFocus(1) onblur=onUserInputFocus(0) />
39 + <input id="xouttext" type="text" style="box-sizing:border-box;width:100%;font-size:18px" onfocus=onUserInputFocus(1) onblur=onUserInputFocus(0) onkeyup="updateLocalOutText()" />
40 </td>
41 <td style="width:1px">
42 <input type="button" id="sendButton" value="Send" style="box-sizing: border-box;float:right;font-size:18px" onclick="xsend(event)" />
@@ -83,6 +84,8 @@
84 if (webrtcconfiguration == '') { webrtcconfiguration = null; } else { try { webrtcconfiguration = JSON.parse(decodeURIComponent(webrtcconfiguration)); } catch (ex) { console.log('Invalid WebRTC config: "' + webrtcconfiguration + '".'); webrtcconfiguration = null; } }
85 var windowFocus = true;
86 var chatTextSession = new Date().toString() + '\r\n';
87 + var localOutText = false;
88 + var remoteOutText = false;
89
90 // File transfer state
91 var fileUploads = [];
@@ -136,6 +139,7 @@
139 // Backspace
140 var outtext = Q('xouttext').value;
141 if (outtext.length > 0) { Q('xouttext').value = outtext.substring(0, outtext.length - 1); }
142 + updateLocalOutText();
143 }
144 }
145 if (userInputFocus == 0) { haltEvent(e); return false; }
@@ -151,7 +155,7 @@
155 xsend(e);
156 } else {
157 // Any other key
154 - if ((userInputFocus == 0) && (e.key.length == 1)) { Q('xouttext').value = Q('xouttext').value + e.key; }
158 + if ((userInputFocus == 0) && (e.key.length == 1)) { Q('xouttext').value = Q('xouttext').value + e.key; updateLocalOutText(); }
159 }
160 }
161 if (userInputFocus == 0) { haltEvent(e); return false; }
@@ -233,6 +237,7 @@
237 if ((state == 2) || pushMessaging) { send({ action: 'chat', msg: outtext }); }
238 Q('xouttext').value = '';
239 Q('xouttext').focus();
240 + localOutText = false;
241 }
242 }
243
@@ -247,6 +252,7 @@
252 QV('camButton', webchannel && webchannel.ok && !localStream && (userMediaSupport == 2));
253 QV('micButton', webchannel && webchannel.ok && !localStream && (userMediaSupport > 0));
254 QV('hangupButton', webchannel && webchannel.ok && localStream);
255 + updateLocalOutText();
256 }
257
258 // This is the WebRTC setup
@@ -345,6 +351,8 @@
351 if (socket != null) { socket.close(); socket = null; }
352 updateControls();
353 state = 0;
354 + updateLocalOutText();
355 + updateRemoteOutText();
356 }
357
358 // Send data over the current transport (WebRTC first)
@@ -372,7 +380,8 @@
380 try { data = JSON.parse(data); } catch (ex) { console.log('Unable to parse', data); return; }
381 //console.log('RECV', data);
382 switch (data.action) {
375 - case 'chat': { displayRemote(data.msg); break; } // Incoming chat message.
383 + case 'chat': { displayRemote(data.msg); updateRemoteOutText(false); break; } // Incoming chat message.
384 + case 'outtext': { updateRemoteOutText(data.value); break; }
385 case 'ctrl': {
386 if (data.value == 1) { displayControl("Sent as push notification."); }
387 else if (data.value == 2) { displayControl("Push notification failed."); }
@@ -688,6 +697,8 @@
697 state = 2;
698 updateControls();
699 sendws({ action: 'random', random: random }); // Send a random number. Higher number starts the WebRTC session.
700 + updateLocalOutText();
701 + updateRemoteOutText();
702 return;
703 }
704 if (msg.data[0] == '{') { processMessage(msg.data, 1); }
@@ -726,6 +737,23 @@
737 return r;
738 }
739
740 + function updateLocalOutText() {
741 + var l = Q('xouttext').value;
742 + if (((state != 2) || (l == '')) && (localOutText == true)) {
743 + localOutText = false;
744 + send({ action: 'outtext', value: false });
745 + } else if ((state == 2) && ((l != '') && (localOutText == false))) {
746 + localOutText = true;
747 + send({ action: 'outtext', value: true });
748 + }
749 + }
750 +
751 + function updateRemoteOutText(newState) {
752 + //console.log('updateRemoteOutText', newState);
753 + if (state != 2) { newState = false; }
754 + if (remoteOutText != newState) { remoteOutText = newState; QV('typingIndicator', remoteOutText); }
755 + }
756 +
757 </script>
758 </body>
759 </html>