refactor: some work to get initial page load working a bit better
This commit is contained in:
parent
200b89954b
commit
f276fe74da
3 changed files with 98 additions and 41 deletions
31
README.md
31
README.md
|
@ -26,22 +26,31 @@
|
||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
|
- [ ] should everything be an event in a room?
|
||||||
- [X] sign up
|
- [X] sign up
|
||||||
- [X] check for logged in user session
|
- [X] check for logged in user session
|
||||||
- [X] log in
|
- [X] log in
|
||||||
- [X] chat rooms
|
- [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
|
- [X] chat messages
|
||||||
- [ ] bulletin board instead of exchange/work?
|
- [X] user profile page
|
||||||
- [ ] should everything be an event in a room?
|
- [ ] 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?
|
- [ ] post-it style notes with tag and keyword filtering?
|
||||||
- [ ] simple wiki for resources
|
- [ ] simple wiki for resources
|
||||||
- [ ] simple calendar with public/private event tracking
|
- [ ] simple calendar with public/private event tracking
|
||||||
- [ ] caldav support?
|
- [ ] 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
|
|
||||||
|
|
|
@ -2,7 +2,13 @@
|
||||||
window.addEventListener("locationchange", () => {
|
window.addEventListener("locationchange", () => {
|
||||||
const hash = window.location.hash?.slice(1);
|
const hash = window.location.hash?.slice(1);
|
||||||
if (hash) {
|
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) {
|
if (target_tab) {
|
||||||
target_tab.click();
|
target_tab.click();
|
||||||
}
|
}
|
||||||
|
|
|
@ -193,7 +193,22 @@
|
||||||
async function append_room_events(events) {
|
async function append_room_events(events) {
|
||||||
const room_chat_content = document.getElementById("room-chat-content");
|
const room_chat_content = document.getElementById("room-chat-content");
|
||||||
const users = {};
|
const users = {};
|
||||||
|
let last_message_id = undefined;
|
||||||
for (const event of events) {
|
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] =
|
||||||
users[event.creator_id] ??
|
users[event.creator_id] ??
|
||||||
(await api.fetch(`/users/${event.creator_id}`));
|
(await api.fetch(`/users/${event.creator_id}`));
|
||||||
|
@ -203,13 +218,11 @@
|
||||||
render_text_event(event, users[event.creator_id]),
|
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;
|
let room_polling_request_abort_controller = null;
|
||||||
async function poll_for_new_events() {
|
async function poll_for_new_events() {
|
||||||
const room_chat_content = document.getElementById("room-chat-content");
|
const room_chat_content = document.getElementById("room-chat-content");
|
||||||
|
@ -222,7 +235,6 @@
|
||||||
signal: room_polling_request_abort_controller.signal,
|
signal: room_polling_request_abort_controller.signal,
|
||||||
})
|
})
|
||||||
.then((new_events) => {
|
.then((new_events) => {
|
||||||
const room;
|
|
||||||
append_room_events(new_events);
|
append_room_events(new_events);
|
||||||
poll_for_new_events(room_id);
|
poll_for_new_events(room_id);
|
||||||
})
|
})
|
||||||
|
@ -236,7 +248,7 @@
|
||||||
if (room_polling_request_abort_controller) {
|
if (room_polling_request_abort_controller) {
|
||||||
room_polling_request_abort_controller.abort();
|
room_polling_request_abort_controller.abort();
|
||||||
room_polling_request_abort_controller = null;
|
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}`);
|
const room_response = await api.fetch(`/rooms/${room_id}`);
|
||||||
|
@ -249,8 +261,17 @@
|
||||||
const room = await room_response.json();
|
const room = await room_response.json();
|
||||||
const room_chat_content = document.getElementById("room-chat-content");
|
const room_chat_content = document.getElementById("room-chat-content");
|
||||||
|
|
||||||
|
room_chat_content.dataset.room_id = room.id;
|
||||||
room_chat_content.innerHTML = "";
|
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(
|
const events_response = await api.fetch(
|
||||||
`/rooms/${room_id}/events?type=chat&limit=100&sort=newest`,
|
`/rooms/${room_id}/events?type=chat&limit=100&sort=newest`,
|
||||||
);
|
);
|
||||||
|
@ -265,32 +286,17 @@
|
||||||
append_room_events(events);
|
append_room_events(events);
|
||||||
last_message_id = events.length ? events[events.length - 1].id : null;
|
last_message_id = events.length ? events[events.length - 1].id : null;
|
||||||
|
|
||||||
room_polling_request_abort_controller = new AbortController();
|
|
||||||
poll_for_new_events(room_id);
|
poll_for_new_events(room_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: one place to handle switching rooms
|
let last_room_update = undefined;
|
||||||
// TODO: load events when we switch rooms and clear and update the chat
|
async function update_chat_rooms() {
|
||||||
// TODO: try to select immediate siblings from the same user and hide avatars
|
const now = new Date();
|
||||||
function check_for_room_in_url() {
|
const time_since_last_update = now - (last_room_update ?? 0);
|
||||||
const hash = window.location.hash;
|
if (time_since_last_update < 5_000) {
|
||||||
const room_id =
|
return;
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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");
|
const rooms_response = await api.fetch("/rooms");
|
||||||
if (rooms_response.ok) {
|
if (rooms_response.ok) {
|
||||||
const room_list = document.getElementById("room-list");
|
const room_list = document.getElementById("room-list");
|
||||||
|
@ -302,8 +308,44 @@
|
||||||
`<li id="room-selector-${room.id}" class="room"><a href="#/talk/room/${room.id}">${room.name}</a></li>`,
|
`<li id="room-selector-${room.id}" class="room"><a href="#/talk/room/${room.id}">${room.name}</a></li>`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
last_room_update = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
window.addEventListener("locationchange", update_chat_rooms);
|
||||||
|
|
||||||
|
function check_for_room_in_url() {
|
||||||
|
const hash = window.location.hash;
|
||||||
|
const talk_in_url = hash.indexOf("#/talk") === 0;
|
||||||
|
if (!talk_in_url) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const first_room_id = document.querySelector("li.room")?.id.substring(14);
|
||||||
|
|
||||||
|
// #/talk/room/{room_id}
|
||||||
|
// ^ 12
|
||||||
|
const room_id = hash.substring(12) || first_room_id;
|
||||||
|
|
||||||
|
if (!room_id) {
|
||||||
|
alert("failed to load chat room!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const room_chat_container = document.getElementById("room-chat-container");
|
||||||
|
room_chat_container.dataset.room_id = room_id;
|
||||||
|
|
||||||
|
load_room(room_id);
|
||||||
|
}
|
||||||
|
window.addEventListener("locationchange", check_for_room_in_url);
|
||||||
|
|
||||||
|
document.addEventListener("DOMContentLoaded", async () => {
|
||||||
|
await update_chat_rooms();
|
||||||
|
check_for_room_in_url();
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO: this should be moved to be handled by a smartform
|
||||||
|
document.addEventListener("DOMContentLoaded", async () => {
|
||||||
const chat_input = document.getElementById("room-chat-input");
|
const chat_input = document.getElementById("room-chat-input");
|
||||||
async function on_send_message(event) {
|
async function on_send_message(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue