Mercurial Hosting > chat
changeset 73:a63faf49e1d7
last seen
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Sat, 08 Mar 2025 20:26:19 -0700 |
parents | bce0480721c1 |
children | 1c0336a7380f |
files | src/chat.js src/get_chat.js.luan src/heartbeat.js.luan src/lib/Online.luan src/lib/Shared.luan |
diffstat | 5 files changed, 103 insertions(+), 24 deletions(-) [+] |
line wrap: on
line diff
--- a/src/chat.js Sat Mar 08 17:29:57 2025 -0700 +++ b/src/chat.js Sat Mar 08 20:26:19 2025 -0700 @@ -3,7 +3,7 @@ let title = document.title; let currentChatId = null; let eventSource; -let lastUpdate; +let lastUpdate = Date.now(); let userId; let filebinUrl; @@ -227,28 +227,22 @@ } function heartbeat() { - showOnline(); ajax(`heartbeat.js?last_update=${lastUpdate}`); } setInterval( heartbeat, 10000 ); +heartbeat(); let online = {}; -function setOnline(userId) { - online[userId] = Date.now(); -} - function showOnline() { let old = Date.now() - 70000; - for( let id of Object.keys(online) ) { - if( online[id] < old ) - delete online[id]; - } let spans = document.querySelectorAll('span[online]'); for( let span of spans ) { let id = span.getAttribute('online'); - span.setAttribute('is_online',!!online[id]); + let wasOnline = online[id]; + let isOnline = !!wasOnline && wasOnline > old; + span.setAttribute('is_online',isOnline); } } @@ -328,7 +322,53 @@ reader.readAsArrayBuffer(file); } +let times = [ + { + time: 1000*60*60*24, + unit: 'day' + }, + { + time: 1000*60*60, + unit: 'hour' + }, + { + time: 1000*60, + unit: 'minute' + } +]; + +function ago(time) { + for( let t of times ) { + let n = Math.floor(time / t.time); + if( n > 0 ) { + let s = `${n} ${t.unit}`; + if( n > 1 ) + s = s + 's'; + return s + ' ago'; + } + } + return 'just now'; +end +} + function openPeople() { let dialog = document.querySelector('dialog[people]'); + let spans = dialog.querySelectorAll('span[last_seen]'); + let now = Date.now(); + let old = now - 70000; + for( let span of spans ) { + let id = span.getAttribute('last_seen'); + let s; + let lastOnline = online[id]; + if( !lastOnline ) { + s = ''; + } else if( lastOnline > old ) { + s = 'Active now'; + } else { + s = 'Last seen ' + ago(now - lastOnline); + } + console.log(`${id} ${s}`); + span.textContent = s; + } openModal(dialog); }
--- a/src/get_chat.js.luan Sat Mar 08 17:29:57 2025 -0700 +++ b/src/get_chat.js.luan Sat Mar 08 20:26:19 2025 -0700 @@ -68,21 +68,22 @@ local name = user.name local email = user.email local voice_url = user.voice_url - local voice = voice_url and `%> <a href="<%=voice_url%>" title="Call" target="voice"><img phone src="/images/call.svg"><%` or "" + local voice = voice_url and `%> <a href="<%=voice_url%>" title="Call" target="voice"><img phone src="/images/call.svg"></a><%` or "" %> <p> <% if name == nil then %> - <b><%=html_encode(email)%></b><%=voice%> + <b><%=html_encode(email)%></b><%=voice%><br> <% else %> <b><%=html_encode(name)%></b><%=voice%><br> - <%=html_encode(email)%> + <%=html_encode(email)%><br> <% end %> + <span last_seen="<%=user_id%>"></span> </p> <% end
--- a/src/heartbeat.js.luan Sat Mar 08 17:29:57 2025 -0700 +++ b/src/heartbeat.js.luan Sat Mar 08 20:26:19 2025 -0700 @@ -2,6 +2,8 @@ local error = Luan.error local String = require "luan:String.luan" local to_number = String.to_number or error() +local Parsers = require "luan:Parsers.luan" +local json_string = Parsers.json_string or error() local Time = require "luan:Time.luan" local time_now = Time.now or error() local Io = require "luan:Io.luan" @@ -9,28 +11,33 @@ local User = require "site:/lib/User.luan" local current_user = User.current or error() local Shared = require "site:/lib/Shared.luan" -local http_push_to_users = Shared.http_push_to_users or error() +local compressed = Shared.compressed or error() +local Online = require "site:/lib/Online.luan" +local set_online = Online.set or error() +local get_online = Online.get or error() local Logging = require "luan:logging/Logging.luan" local logger = Logging.logger "heartbeat.js" return function() local user = current_user() or error() - local user_ids = user.chatting_with_ids() - local js = "setOnline("..user.id..")" - http_push_to_users( user_ids, js ) + set_online(user) + Io.stdout = Http.response.text_writer() local last_update = Http.request.parameters.last_update or error() last_update = to_number(last_update) or error(last_update) local user_last_update = user.last_update() - local now = time_now() - if now - user_last_update < 10000 or last_update >= user_last_update then - -- logger.info "ok" + if time_now() - user_last_update > 70000 and last_update < user_last_update then + logger.info "update" +%> + location = '/'; +<% return end - logger.info "update" - Io.stdout = Http.response.text_writer() + + local online = get_online(user) %> - location = '/'; + online = <%=json_string(online,compressed)%>; + showOnline(); <% end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/Online.luan Sat Mar 08 20:26:19 2025 -0700 @@ -0,0 +1,29 @@ +local Luan = require "luan:Luan.luan" +local error = Luan.error +local ipairs = Luan.ipairs or error() +local to_string = Luan.to_string or error() +local Time = require "luan:Time.luan" +local time_now = Time.now or error() +local Thread = require "luan:Thread.luan" +local User = require "site:/lib/User.luan" + + +local Online = {} + +local glob = Thread.global_map("online") + +function Online.set(user) + glob[user.id] = time_now() +end + +function Online.get(user) + local online = {} + local ids = user.chatting_with_ids() + ids[#ids+1] = user.id + for _, user_id in ipairs(ids) do + online[to_string(user_id)] = glob[user_id] + end + return online +end + +return Online