changeset 53:9298b04607ae

add unread
author Franklin Schmidt <fschmidt@gmail.com>
date Mon, 03 Mar 2025 19:39:30 -0700
parents c3fabb21b6c4
children 1d724f187cff
files src/add_post.js.luan src/chat.css src/chat.js src/get_chat.js.luan src/lib/Chat.luan src/lib/Db.luan src/lib/Post.luan src/lib/Shared.luan
diffstat 8 files changed, 74 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/src/add_post.js.luan	Mon Mar 03 12:29:06 2025 -0700
+++ b/src/add_post.js.luan	Mon Mar 03 19:39:30 2025 -0700
@@ -39,6 +39,7 @@
 		chat.updated = now
 		chat.save()
 	end )
+	chat.read(user)
 	Notify.add(chat)
 	local html = `post_html(post)`
 	local js = "added("..json_string(html)..")"
--- a/src/chat.css	Mon Mar 03 12:29:06 2025 -0700
+++ b/src/chat.css	Mon Mar 03 19:39:30 2025 -0700
@@ -143,6 +143,20 @@
 	margin-left: 4px;
 }
 
+span[unread] {
+	font-size: small;
+	display: inline-block;
+	background-color: DodgerBlue;
+	color: white;
+	padding: 2px;
+	border-radius: calc(1em + 4px);
+	min-width: calc(1em + 4px);
+	text-align: center;
+	line-height: 1;
+}
+span[unread="0"] {
+	display: none;
+}
 
 @media (min-width: 700px) {
 	div[chat_content] {
--- a/src/chat.js	Mon Mar 03 12:29:06 2025 -0700
+++ b/src/chat.js	Mon Mar 03 19:39:30 2025 -0700
@@ -27,6 +27,7 @@
 	ajax(`get_chat.js?chat=${chatId}`);
 	currentChatId = chatId;
 	history.replaceState(null,null,`?with=${email}`);
+	clearUnread();
 
 	if(eventSource)  eventSource.close();
 	eventSource = new EventSource(`${location.origin}/chat/${chatId}`);
@@ -157,9 +158,11 @@
 
 function getChats(chatId,updated) {
 	let first = document.querySelector('div[chat]');
-	if( !first || first.getAttribute('chat') != chatId ) {
+	if( !first || first.getAttribute('chat') !== chatId ) {
 		// console.log('getChats');
 		ajax('get_chats.js');
+	} else if( first && currentChatId !== chatId ) {
+		incUnread(first);
 	}
 	if( updated )
 		lastUpdate = updated;
@@ -251,3 +254,16 @@
 `		;
 	}
 }
+
+function clearUnread() {
+	let span = document.querySelector(`div[chat="${currentChatId}"] span[unread]`);
+	span.setAttribute('unread','0');
+	span.textContent = '0';
+}
+
+function incUnread(div) {
+	let span = div.querySelector('span[unread]');
+	let n = parseInt(span.getAttribute('unread')) + 1;
+	span.setAttribute('unread',n);
+	span.textContent = n;
+}
--- a/src/get_chat.js.luan	Mon Mar 03 12:29:06 2025 -0700
+++ b/src/get_chat.js.luan	Mon Mar 03 19:39:30 2025 -0700
@@ -22,6 +22,7 @@
 	local user = current_user() or error()
 	local chat = Http.request.parameters.chat or error()
 	chat = get_chat_by_id(chat) or error()
+	chat.read(user)
 	local posts = post_search( "post_chat_id:"..chat.id, "id" )
 %>
 	<div top>
--- a/src/lib/Chat.luan	Mon Mar 03 12:29:06 2025 -0700
+++ b/src/lib/Chat.luan	Mon Mar 03 19:39:30 2025 -0700
@@ -61,6 +61,28 @@
 		error()
 	end
 
+	local function get_chatuser_id(user)
+		return chat.id.."~"..user.id
+	end
+
+	function chat.unread(user)
+		local doc = Db.get_document("chatuser_id:"..get_chatuser_id(user))
+		local read_date = doc and doc.read_date or 0
+		return Db.count("+post_chat_id:"..chat.id.." +post_date:["..read_date.." TO *]")
+	end
+
+	function chat.read(user)
+		run_in_transaction( function()
+			local chatuser_id = get_chatuser_id(user)
+			local doc = Db.get_document("chatuser_id:"..chatuser_id) or {
+				type = "chatuser"
+				chatuser_id = chatuser_id
+			}
+			doc.read_date = time_now()
+			Db.save(doc)
+		end )
+	end
+
 	return chat
 end
 
--- a/src/lib/Db.luan	Mon Mar 03 12:29:06 2025 -0700
+++ b/src/lib/Db.luan	Mon Mar 03 19:39:30 2025 -0700
@@ -1,6 +1,7 @@
 local Luan = require "luan:Luan.luan"
 local error = Luan.error
 local new_error = Luan.new_error or error()
+local ipairs = Luan.ipairs or error()
 local Lucene = require "luan:lucene/Lucene.luan"
 local Io = require "luan:Io.luan"
 local uri = Io.uri or error()
@@ -25,12 +26,22 @@
 Db.indexed_fields.chat_updated = Lucene.type.long
 
 Db.indexed_fields.post_chat_id = Lucene.type.long
+Db.indexed_fields.post_date = Lucene.type.long
+
+Db.indexed_fields.chatuser_id = Lucene.type.string
 
 function Db.not_in_transaction()
 	logger.error(new_error("not in transaction"))
 end
 
 Db.update{
+	[1] = function()
+		local docs = Db.search("type:post",1,1000000)
+		for _, doc in ipairs(docs) do
+			doc.post_date = doc.post_date or doc.date
+			Db.save(doc)
+		end
+	end
 }
 
 if Http.is_serving then
--- a/src/lib/Post.luan	Mon Mar 03 12:29:06 2025 -0700
+++ b/src/lib/Post.luan	Mon Mar 03 19:39:30 2025 -0700
@@ -15,7 +15,7 @@
 		id = doc.id
 		chat_id = doc.post_chat_id
 		author_id = doc.author_id
-		date = doc.date
+		date = doc.post_date
 		content = doc.content
 	}
 end
@@ -26,7 +26,7 @@
 		id = post.id
 		post_chat_id = long(post.chat_id)
 		author_id = long(post.author_id)
-		date = long(post.date)
+		post_date = long(post.date)
 		content = post.content or error()
 	}
 end
--- a/src/lib/Shared.luan	Mon Mar 03 12:29:06 2025 -0700
+++ b/src/lib/Shared.luan	Mon Mar 03 19:39:30 2025 -0700
@@ -147,10 +147,13 @@
 	for _, chat in ipairs(chats) do
 		local user_id = chat.other_user_id(user.id)
 		local other_user = get_user_by_id(user_id) or error()
+		local unread = chat.unread(user)
 %>
-		<div chat="<%=chat.id%>" onclick='selectChat(this,<%=json_string(other_user.email)%>)'><%
-			%><%= other_user.name_html() %><span online="<%= other_user.id %>"></span><%
-		%></div>
+		<div chat="<%=chat.id%>" onclick='selectChat(this,<%=json_string(other_user.email)%>)'>
+			<%= other_user.name_html() %>
+			<span online="<%= other_user.id %>"></span>
+			<span unread="<%=unread%>"><%=unread%></span>
+		</div>
 <%
 	end
 end