From 832acd7cdef8f677592c9d341449bc06db72b4c2 Mon Sep 17 00:00:00 2001 From: dev Date: Fri, 30 Oct 2026 05:58:54 +0000 Subject: [PATCH] Update static/js/08-settings.js --- static/js/08-settings.js | 115 ++++++++++++++++++--------------------- 1 file changed, 52 insertions(+), 63 deletions(-) diff --git a/static/js/08-settings.js b/static/js/08-settings.js index 83b6aa6..7892f44 100644 --- a/static/js/08-settings.js +++ b/static/js/08-settings.js @@ -1,3 +1,4 @@ +```javascript // static/js/08-settings.js "use strict"; window.Glow = window.Glow || {}; @@ -42,15 +43,19 @@ Glow.renderHeaderMenu = () => { const list = Glow.els.headerMenuList; if (!list) return; list.replaceChildren(); + const addItem = ({ label, hint = "", onClick, hidden = false }) => { if (hidden) return; const button = document.createElement("button"); button.className = "header-menu-item"; button.type = "button"; + const left = document.createElement("span"); left.textContent = label; + const right = document.createElement("small"); right.textContent = hint; + button.append(left, right); button.addEventListener("click", () => { Glow.closeHeaderMenu?.(); @@ -58,17 +63,20 @@ Glow.renderHeaderMenu = () => { }); list.append(button); }; + addItem({ label: "My profile", hint: Glow.state.currentUser ? `@${Glow.state.currentUser.username}` : "", onClick: () => Glow.openMyProfile?.(), hidden: !Glow.state.currentUser }); + addItem({ label: "Settings", hint: "Theme, CSS, profile", onClick: () => Glow.openSettings?.() }); + addItem({ label: "Direct messages", hint: Glow.state.currentUser ? "Private chat" : "", @@ -80,24 +88,28 @@ Glow.renderHeaderMenu = () => { }, hidden: !Glow.state.currentUser }); + addItem({ label: "Create team", hint: "Up to 3 max", onClick: () => Glow.openCreateTeamDialog?.(), hidden: !Glow.state.currentUser }); + addItem({ label: "Edit current team", hint: Glow.state.activeTeam?.can_manage ? "Manage" : "", onClick: () => Glow.openEditTeamDialog?.(Glow.state.activeTeam), hidden: !Glow.state.activeTeam || !Glow.state.activeTeam.can_manage }); + addItem({ label: "Add channel", hint: Glow.state.activeTeam?.name || "", onClick: () => Glow.openCreateChannelDialog?.(Glow.state.activeTeam), hidden: !Glow.state.activeTeam || !Glow.state.activeTeam.can_manage }); + addItem({ label: "Edit current channel", hint: Glow.state.activeChannel?.name || Glow.state.activeRoom?.name || "", @@ -111,18 +123,21 @@ Glow.renderHeaderMenu = () => { !(Glow.state.activeChannel || Glow.state.activeRoom) || Glow.state.activeView === "dm" }); + addItem({ label: "Manage team members", hint: Glow.state.activeTeam?.can_manage ? "Members" : "", onClick: () => Glow.manageTeamMembers?.(Glow.state.activeTeam), hidden: !Glow.state.activeTeam || !Glow.state.activeTeam.can_manage }); + addItem({ label: "Create team invite", hint: Glow.state.activeTeam?.can_manage ? "Share" : "", onClick: () => Glow.createTeamInviteLink?.(Glow.state.activeTeam), hidden: !Glow.state.activeTeam || !Glow.state.activeTeam.can_manage }); + addItem({ label: "Delete current channel", hint: Glow.state.activeChannel?.name || "", @@ -164,9 +179,11 @@ Glow.openSettings = async () => { Glow.renderNameColorPreview = value => { const wrap = document.createElement("div"); wrap.className = "settings-row"; + const label = document.createElement("div"); label.className = "header-subtitle"; label.textContent = "Preview"; + const preview = document.createElement("div"); preview.className = "name-color-preview"; preview.textContent = @@ -174,6 +191,7 @@ Glow.renderNameColorPreview = value => { preview.style.color = Glow.normalizeNameColor(value) || Glow.roleDefaultNameColor(Glow.state.currentUser?.role); + wrap.append(label, preview); return wrap; }; @@ -187,13 +205,16 @@ Glow.renderSettingsView = () => { const appearance = document.createElement("section"); appearance.className = "settings-section"; + const aTitle = document.createElement("h2"); aTitle.textContent = "Appearance"; + const aText = document.createElement("p"); aText.textContent = "Set your theme mode, accent color, username color, profile background, and banner color."; const themeRow = document.createElement("div"); themeRow.className = "settings-theme-row"; + const currentTheme = Glow.state.settings?.theme_mode || localStorage.getItem("glow_theme_mode") || @@ -203,6 +224,7 @@ Glow.renderSettingsView = () => { darkButton.className = `theme-pill${currentTheme !== "light" ? " active" : ""}`; darkButton.type = "button"; darkButton.textContent = "Dark"; + const lightButton = document.createElement("button"); lightButton.className = `theme-pill${currentTheme === "light" ? " active" : ""}`; lightButton.type = "button"; @@ -214,19 +236,23 @@ Glow.renderSettingsView = () => { Glow.state.settings.theme_mode = "dark"; Glow.renderSettingsView(); }); + lightButton.addEventListener("click", () => { Glow.applyThemeMode("light"); Glow.state.settings ||= {}; Glow.state.settings.theme_mode = "light"; Glow.renderSettingsView(); }); + themeRow.append(darkButton, lightButton); const accentWrap = document.createElement("div"); accentWrap.className = "settings-row"; + const accentLabel = document.createElement("label"); accentLabel.className = "dialog-label"; accentLabel.textContent = "Accent color"; + const accentInput = document.createElement("input"); accentInput.type = "color"; accentInput.className = "accent-color-input"; @@ -234,53 +260,65 @@ Glow.renderSettingsView = () => { Glow.normalizeAccentColor( Glow.state.settings?.accent_color || Glow.state.accentColor ) || Glow.DEFAULT_ACCENT_COLOR; + accentInput.addEventListener("input", () => { Glow.applyAccentColor(accentInput.value); Glow.state.settings ||= {}; Glow.state.settings.accent_color = accentInput.value; }); + accentLabel.append(accentInput); accentWrap.append(accentLabel); const backgroundWrap = document.createElement("div"); backgroundWrap.className = "settings-row"; + const backgroundLabel = document.createElement("label"); backgroundLabel.className = "dialog-label"; backgroundLabel.textContent = "Profile background color"; + const backgroundInput = document.createElement("input"); backgroundInput.type = "color"; backgroundInput.className = "accent-color-input"; backgroundInput.value = Glow.normalizeAccentColor(Glow.state.settings?.profile_background_color) || "#121214"; + backgroundInput.addEventListener("input", () => { Glow.state.settings ||= {}; Glow.state.settings.profile_background_color = backgroundInput.value; }); + backgroundLabel.append(backgroundInput); backgroundWrap.append(backgroundLabel); const bannerWrap = document.createElement("div"); bannerWrap.className = "settings-row"; + const bannerLabel = document.createElement("label"); bannerLabel.className = "dialog-label"; bannerLabel.textContent = "Profile banner color"; + const bannerInput = document.createElement("input"); bannerInput.type = "color"; bannerInput.className = "accent-color-input"; bannerInput.value = Glow.normalizeAccentColor(Glow.state.settings?.profile_banner_color) || "#3a3140"; + bannerInput.addEventListener("input", () => { Glow.state.settings ||= {}; Glow.state.settings.profile_banner_color = bannerInput.value; }); + bannerLabel.append(bannerInput); bannerWrap.append(bannerLabel); const nameColorWrap = document.createElement("div"); nameColorWrap.className = "settings-row"; + const nameColorLabel = document.createElement("label"); nameColorLabel.className = "dialog-label"; nameColorLabel.textContent = "Username color"; + const nameColorInput = document.createElement("input"); nameColorInput.type = "color"; nameColorInput.className = "accent-color-input"; @@ -298,6 +336,7 @@ Glow.renderSettingsView = () => { const nameRow = document.createElement("div"); nameRow.className = "accent-picker-row"; + const previewSwatch = document.createElement("span"); previewSwatch.className = "accent-preview"; previewSwatch.style.background = @@ -361,74 +400,16 @@ Glow.renderSettingsView = () => { nameColorWrap ); - const presenceSection = document.createElement("section"); - presenceSection.className = "settings-section"; - const pTitle = document.createElement("h2"); - pTitle.textContent = "Presence & privacy"; - const pText = document.createElement("p"); - pText.textContent = "Control who can view your profile and last active time, and set your presence mode."; - - const profileVisibility = document.createElement("input"); - profileVisibility.className = "field"; - profileVisibility.value = Glow.state.settings?.profile_visibility || "public"; - profileVisibility.placeholder = "public | members | private"; - - const lastActiveVisibility = document.createElement("input"); - lastActiveVisibility.className = "field"; - lastActiveVisibility.value = Glow.state.settings?.last_active_visibility || "everyone"; - lastActiveVisibility.placeholder = "everyone | members | nobody"; - - const presenceMode = document.createElement("input"); - presenceMode.className = "field"; - presenceMode.value = Glow.state.settings?.presence_mode || Glow.state.currentUser?.presence_mode || "online"; - presenceMode.placeholder = "online | silent | focus | dnd"; - - profileVisibility.addEventListener("input", () => { - Glow.state.settings ||= {}; - Glow.state.settings.profile_visibility = profileVisibility.value.trim().toLowerCase(); - }); - lastActiveVisibility.addEventListener("input", () => { - Glow.state.settings ||= {}; - Glow.state.settings.last_active_visibility = lastActiveVisibility.value.trim().toLowerCase(); - }); - presenceMode.addEventListener("input", () => { - Glow.state.settings ||= {}; - Glow.state.settings.presence_mode = presenceMode.value.trim().toLowerCase(); - }); - - presenceSection.append( - pTitle, - pText, - (() => { - const label = document.createElement("label"); - label.className = "dialog-label"; - label.textContent = "Profile visibility"; - label.append(profileVisibility); - return label; - })(), - (() => { - const label = document.createElement("label"); - label.className = "dialog-label"; - label.textContent = "Last active visibility"; - label.append(lastActiveVisibility); - return label; - })(), - (() => { - const label = document.createElement("label"); - label.className = "dialog-label"; - label.textContent = "Presence mode"; - label.append(presenceMode); - return label; - })() - ); - const cssSection = document.createElement("section"); cssSection.className = "settings-section"; + const cTitle = document.createElement("h2"); cTitle.textContent = "Custom CSS"; + const cText = document.createElement("p"); cText.textContent = "Optional CSS applied only for your account in this browser session and saved to your settings. \n ex: *,html,body{font-size:95%;text-transform:lowercase;}"; + const cssInput = document.createElement("textarea"); cssInput.className = "field settings-custom-css"; cssInput.placeholder = "/* Custom CSS */"; @@ -438,14 +419,18 @@ Glow.renderSettingsView = () => { Glow.state.settings ||= {}; Glow.state.settings.custom_css = cssInput.value; }); + cssSection.append(cTitle, cText, cssInput); const accountSection = document.createElement("section"); accountSection.className = "settings-section"; + const accountTitle = document.createElement("h2"); accountTitle.textContent = "Account"; + const accountText = document.createElement("p"); accountText.textContent = "Update your public profile and application preferences."; + const actions = document.createElement("div"); actions.className = "settings-actions"; @@ -486,11 +471,14 @@ Glow.renderSettingsView = () => { presence_mode: Glow.state.settings?.presence_mode || "online" }; + const data = await Glow.apiUpdateMySettings(payload); Glow.state.settings = data.settings || payload; + if (Glow.state.currentUser) { Glow.state.currentUser.presence_mode = Glow.state.settings.presence_mode || "online"; } + Glow.showToast("Settings saved."); Glow.renderSettingsView(); } catch (error) { @@ -512,6 +500,7 @@ Glow.renderSettingsView = () => { actions.append(editProfile, saveSettings, resetAccent); accountSection.append(accountTitle, accountText, actions); - card.append(appearance, presenceSection, cssSection, accountSection); + card.append(appearance, cssSection, accountSection); box.append(card); -}; \ No newline at end of file +}; +``` \ No newline at end of file