bzl

self-hosted ephemeral community engine
Log | Files | Refs | README | LICENSE

commit 76ad80434cb3afe49f972507d574e2aa6c155b26
parent 01be0ea041b9f7b8077f4fa196bdcdc93be4d8a0
Author: SageAzakaela <106701693+SageAzakaela@users.noreply.github.com>
Date:   Mon, 16 Feb 2026 23:58:26 -0700

Ui Changes part 2 - electric not-boogaloo

The last one didn't work because of something I overlooked so had to make peace with looking like a silly person right now.

Diffstat:
MCLEAN_INSTALL/public/app.js | 44++++++++++++++++++++++++++++++++++++++++++++
MCLEAN_INSTALL/public/styles.css | 22++++++++++++++++++++++
Mpublic/app.js | 44++++++++++++++++++++++++++++++++++++++++++++
Mpublic/styles.css | 22++++++++++++++++++++++
4 files changed, 132 insertions(+), 0 deletions(-)

diff --git a/CLEAN_INSTALL/public/app.js b/CLEAN_INSTALL/public/app.js @@ -131,6 +131,7 @@ const sidebarResizeHandle = document.getElementById("sidebarResizeHandle"); const mainResizeHandle = document.getElementById("mainResizeHandle"); const chatPanelEl = document.querySelector(".chat"); const peopleResizeHandle = document.getElementById("peopleResizeHandle"); +const chatHeaderEl = chatPanelEl ? chatPanelEl.querySelector(".panelHeader") : null; const editModal = document.getElementById("editModal"); const editModalTitle = document.getElementById("editModalTitle"); const editModalCloseBtn = document.getElementById("editModalClose"); @@ -215,6 +216,7 @@ let allowedPostReactions = ["👍", "❤️", "😡", "😭", "🥺", "😂", " let allowedChatReactions = ["👍", "❤️", "😡", "😭", "🥺", "😂"]; let userPrefs = { starredPostIds: [], hiddenPostIds: [], ignoredUsers: [], blockedUsers: [] }; let showReactions = localStorage.getItem("bzl_showReactions") !== "0"; +let chatDock = localStorage.getItem("bzl_chatDock") === "right" ? "right" : "left"; let activeHiveView = "all"; let collections = []; let customRoles = []; @@ -352,6 +354,11 @@ function setDmThreads(list) { renderChatPanel(); } +function applyChatDock() { + if (!appRoot) return; + appRoot.classList.toggle("chatRight", chatDock === "right"); +} + function upsertDmThread(rawThread) { const t = normalizeDmThread(rawThread); if (!t) return; @@ -5423,6 +5430,7 @@ applySidebarWidth(readStoredSidebarWidth(), false); applyChatWidth(readStoredChatWidth(), false); applyModWidth(readStoredModWidth(), false); applyPeopleWidth(readStoredPeopleWidth(), false); +applyChatDock(); if (toggleReactionsEl) { toggleReactionsEl.checked = showReactions; @@ -5434,6 +5442,42 @@ if (toggleReactionsEl) { }); } +if (chatHeaderEl && appRoot) { + chatHeaderEl.setAttribute("draggable", "true"); + chatHeaderEl.title = "Drag left/right to dock chat"; + chatHeaderEl.addEventListener("dragstart", (e) => { + try { + e.dataTransfer.effectAllowed = "move"; + e.dataTransfer.setData("text/plain", "bzl:dock:chat"); + } catch { + // ignore + } + appRoot.classList.add("isDocking"); + }); + chatHeaderEl.addEventListener("dragend", () => { + appRoot.classList.remove("isDocking"); + }); + appRoot.addEventListener("dragover", (e) => { + if (!appRoot.classList.contains("isDocking")) return; + e.preventDefault(); + try { + e.dataTransfer.dropEffect = "move"; + } catch { + // ignore + } + }); + appRoot.addEventListener("drop", (e) => { + if (!appRoot.classList.contains("isDocking")) return; + e.preventDefault(); + appRoot.classList.remove("isDocking"); + const next = e.clientX > window.innerWidth * 0.58 ? "right" : "left"; + if (next === chatDock) return; + chatDock = next; + localStorage.setItem("bzl_chatDock", chatDock); + applyChatDock(); + }); +} + installDropUpload(editor, { allowImages: true, allowAudio: true }); installDropUpload(chatEditor, { allowImages: true, allowAudio: true }); installDropUpload(profileBioEditor, { allowImages: true, allowAudio: true }); diff --git a/CLEAN_INSTALL/public/styles.css b/CLEAN_INSTALL/public/styles.css @@ -132,6 +132,16 @@ body { grid-template-areas: "sidebar sidebarResize chat chatResize main mainResize moderation"; } +.app.chatRight { + grid-template-columns: minmax(240px, var(--sidebar-width)) 10px 1fr 10px minmax(380px, var(--chat-width)); + grid-template-areas: "sidebar sidebarResize main chatResize chat"; +} + +.app.hasMod.chatRight { + grid-template-columns: minmax(240px, var(--sidebar-width)) 10px 1fr 10px minmax(380px, var(--chat-width)) 10px minmax(280px, var(--mod-width)); + grid-template-areas: "sidebar sidebarResize main chatResize chat mainResize moderation"; +} + @media (max-width: 760px) { .app { grid-template-columns: 300px 1fr; @@ -334,6 +344,18 @@ body { cursor: col-resize; } +.app.isDocking { + user-select: none; +} + +.chat .panelHeader { + cursor: grab; +} + +.app.isDocking .chat .panelHeader { + cursor: grabbing; +} + .moderation .panelHeader, .moderation .modTabs, .moderation .modFilters { diff --git a/public/app.js b/public/app.js @@ -122,6 +122,7 @@ const sidebarResizeHandle = document.getElementById("sidebarResizeHandle"); const mainResizeHandle = document.getElementById("mainResizeHandle"); const chatPanelEl = document.querySelector(".chat"); const peopleResizeHandle = document.getElementById("peopleResizeHandle"); +const chatHeaderEl = chatPanelEl ? chatPanelEl.querySelector(".panelHeader") : null; const editModal = document.getElementById("editModal"); const editModalTitle = document.getElementById("editModalTitle"); const editModalCloseBtn = document.getElementById("editModalClose"); @@ -210,6 +211,7 @@ let allowedPostReactions = ["👍", "❤️", "😡", "😭", "🥺", "😂", " let allowedChatReactions = ["👍", "❤️", "😡", "😭", "🥺", "😂"]; let userPrefs = { starredPostIds: [], hiddenPostIds: [], ignoredUsers: [], blockedUsers: [] }; let showReactions = localStorage.getItem("bzl_showReactions") !== "0"; +let chatDock = localStorage.getItem("bzl_chatDock") === "right" ? "right" : "left"; let activeHiveView = "all"; let collections = []; let customRoles = []; @@ -557,6 +559,11 @@ function setDmThreads(list) { renderChatPanel(); } +function applyChatDock() { + if (!appRoot) return; + appRoot.classList.toggle("chatRight", chatDock === "right"); +} + function upsertDmThread(rawThread) { const t = normalizeDmThread(rawThread); if (!t) return; @@ -6138,6 +6145,7 @@ applySidebarWidth(readStoredSidebarWidth(), false); applyChatWidth(readStoredChatWidth(), false); applyModWidth(readStoredModWidth(), false); applyPeopleWidth(readStoredPeopleWidth(), false); +applyChatDock(); if (toggleReactionsEl) { toggleReactionsEl.checked = showReactions; @@ -6149,6 +6157,42 @@ if (toggleReactionsEl) { }); } +if (chatHeaderEl && appRoot) { + chatHeaderEl.setAttribute("draggable", "true"); + chatHeaderEl.title = "Drag left/right to dock chat"; + chatHeaderEl.addEventListener("dragstart", (e) => { + try { + e.dataTransfer.effectAllowed = "move"; + e.dataTransfer.setData("text/plain", "bzl:dock:chat"); + } catch { + // ignore + } + appRoot.classList.add("isDocking"); + }); + chatHeaderEl.addEventListener("dragend", () => { + appRoot.classList.remove("isDocking"); + }); + appRoot.addEventListener("dragover", (e) => { + if (!appRoot.classList.contains("isDocking")) return; + e.preventDefault(); + try { + e.dataTransfer.dropEffect = "move"; + } catch { + // ignore + } + }); + appRoot.addEventListener("drop", (e) => { + if (!appRoot.classList.contains("isDocking")) return; + e.preventDefault(); + appRoot.classList.remove("isDocking"); + const next = e.clientX > window.innerWidth * 0.58 ? "right" : "left"; + if (next === chatDock) return; + chatDock = next; + localStorage.setItem("bzl_chatDock", chatDock); + applyChatDock(); + }); +} + installDropUpload(editor, { allowImages: true, allowAudio: true }); installDropUpload(chatEditor, { allowImages: true, allowAudio: true }); installDropUpload(profileBioEditor, { allowImages: true, allowAudio: true }); diff --git a/public/styles.css b/public/styles.css @@ -136,6 +136,16 @@ body { grid-template-areas: "sidebar sidebarResize chat chatResize main mainResize moderation"; } +.app.chatRight { + grid-template-columns: minmax(240px, var(--sidebar-width)) 10px 1fr 10px minmax(380px, var(--chat-width)); + grid-template-areas: "sidebar sidebarResize main chatResize chat"; +} + +.app.hasMod.chatRight { + grid-template-columns: minmax(240px, var(--sidebar-width)) 10px 1fr 10px minmax(380px, var(--chat-width)) 10px minmax(280px, var(--mod-width)); + grid-template-areas: "sidebar sidebarResize main chatResize chat mainResize moderation"; +} + @media (max-width: 760px) { .app { grid-template-columns: 300px 1fr; @@ -338,6 +348,18 @@ body { cursor: col-resize; } +.app.isDocking { + user-select: none; +} + +.chat .panelHeader { + cursor: grab; +} + +.app.isDocking .chat .panelHeader { + cursor: grabbing; +} + .moderation .panelHeader, .moderation .modTabs, .moderation .modFilters {