diff --git a/README.md b/README.md index 5ad591b..c9c8ac9 100644 --- a/README.md +++ b/README.md @@ -26,22 +26,31 @@ ## TODO +- [ ] should everything be an event in a room? - [X] sign up - [X] check for logged in user session - [X] log in - [X] chat rooms +- [ ] gif support +- [ ] media uploads +- [ ] local upload support (keep it simple for small instances) +- [ ] S3 support (then self-host with your friends: https://garagehq.deuxfleurs.fr/) +- [ ] try to select immediate sibling messages from the same user and hide mulitple avatars - [X] chat messages -- [ ] bulletin board instead of exchange/work? -- [ ] should everything be an event in a room? -- [ ] post-it style notes with tag and keyword filtering? +- [X] user profile page +- [ ] profile editing +- [ ] avatar uploads +- [ ] local upload support (keep it simple for small instances) +- [ ] S3 support (then self-host with your friends: https://garagehq.deuxfleurs.fr/) +- [ ] admin panel +- [ ] add invite code generation +- [ ] AC_REQUIRE_INVITE_CODE: boolean env var/setting +- [ ] AC_DIRECTORY_SERVERS: |-separated list of directory servers to report to + these central servers could be distributed directories - your town might run one, + your state, your country, or you could publish to a public one that is organized + around interests +- [ ] combined "bulletin board" instead of exchange/work? +- [ ] post-it style notes with tag and keyword filtering? - [ ] simple wiki for resources - [ ] simple calendar with public/private event tracking -- [ ] caldav support? -- [ ] add an optional env var where you can specify a list of - "directory servers" (;-separated urls?) to ping with this - server's existence - the idea being these central servers - could be distributed directories - your town might run one, - your state, your country, or you could publish to a public - one that is organized around interests -- [X] user profile page -- [ ] user profile editing +- [ ] caldav support diff --git a/public/tabs/tabs.html b/public/tabs/tabs.html index 5c91597..936214b 100644 --- a/public/tabs/tabs.html +++ b/public/tabs/tabs.html @@ -2,7 +2,13 @@ window.addEventListener("locationchange", () => { const hash = window.location.hash?.slice(1); if (hash) { - const target_tab = document.querySelector(`[data-hash="${hash}"]`); + const target_tab_url = hash.slice(0, hash.slice(1).indexOf("/")); + const target_tab = document.querySelector(`[data-hash="${target_tab_url}"]`); + console.dir({ + hash, + target_tab_url, + target_tab, + }); if (target_tab) { target_tab.click(); } diff --git a/public/tabs/talk.html b/public/tabs/talk.html index 1739b06..4082df8 100644 --- a/public/tabs/talk.html +++ b/public/tabs/talk.html @@ -193,7 +193,22 @@ async function append_room_events(events) { const room_chat_content = document.getElementById("room-chat-content"); const users = {}; + let last_message_id = undefined; for (const event of events) { + // if the last message is undefined, it becomes this event, otherwise, if this event's id is newer, + // it becomes the latest message + last_message_id = + last_message_id === undefined + ? event.id + : event.id > last_message_id + ? event.id + : last_message_id; + + // if the last message has been updated, update the content's dataset to reflect that + if (last_message_id !== room_chat_content.dataset.last_message_id) { + room_chat_content.dataset.last_message_id = last_message_id; + } + users[event.creator_id] = users[event.creator_id] ?? (await api.fetch(`/users/${event.creator_id}`)); @@ -203,13 +218,11 @@ render_text_event(event, users[event.creator_id]), ); } - console.dir({ - users, - events, - room_chat_content, - }); } + // TODO: we need some abortcontroller handling here or something + // similar for when we change rooms, this is the most basic + // first pass outline let room_polling_request_abort_controller = null; async function poll_for_new_events() { const room_chat_content = document.getElementById("room-chat-content"); @@ -222,7 +235,6 @@ signal: room_polling_request_abort_controller.signal, }) .then((new_events) => { - const room; append_room_events(new_events); poll_for_new_events(room_id); }) @@ -236,7 +248,7 @@ if (room_polling_request_abort_controller) { room_polling_request_abort_controller.abort(); room_polling_request_abort_controller = null; - last_message_id = null; + delete room_chat_content.dataset.last_message_id; } const room_response = await api.fetch(`/rooms/${room_id}`); @@ -249,8 +261,17 @@ const room = await room_response.json(); const room_chat_content = document.getElementById("room-chat-content"); + room_chat_content.dataset.room_id = room.id; room_chat_content.innerHTML = ""; + const room_selectors = document.querySelectorAll("li.room"); + for (const room_selector of room_selectors) { + room_selector.classList.remove("active"); + if (room_selector.id === `room-selector-${room_id}`) { + room_selector.classList.add("active"); + } + } + const events_response = await api.fetch( `/rooms/${room_id}/events?type=chat&limit=100&sort=newest`, ); @@ -265,32 +286,17 @@ append_room_events(events); last_message_id = events.length ? events[events.length - 1].id : null; - room_polling_request_abort_controller = new AbortController(); poll_for_new_events(room_id); } - // TODO: one place to handle switching rooms - // TODO: load events when we switch rooms and clear and update the chat - // TODO: try to select immediate siblings from the same user and hide avatars - function check_for_room_in_url() { - const hash = window.location.hash; - const room_id = - hash.indexOf("#/talk/room/") === 0 ? hash.substring(12) : ""; - const room_chat_container = document.getElementById("room-chat-container"); - room_chat_container.dataset.room_id = room_id; - - const room_selectors = document.querySelectorAll("li.room"); - for (const room_selector of room_selectors) { - room_selector.classList.remove("active"); + let last_room_update = undefined; + async function update_chat_rooms() { + const now = new Date(); + const time_since_last_update = now - (last_room_update ?? 0); + if (time_since_last_update < 5_000) { + return; } - const room_selector = document.getElementById(`room-selector-${room_id}`); - room_selector.classList.add("active"); - load_room(room_id); - } - window.addEventListener("locationchange", check_for_room_in_url); - - document.addEventListener("DOMContentLoaded", async () => { const rooms_response = await api.fetch("/rooms"); if (rooms_response.ok) { const room_list = document.getElementById("room-list"); @@ -302,8 +308,44 @@ `