Tags: ryukinix/lisp-chat
Tags
feat(web): client-side /settings, light-theme and auto-load history (#… …162) * feat(web): client-side /settings command with modal panel Adds a /settings command (web client only) that opens a modal panel with user-configurable options stored as cookies: - Image inline preview toggle (default: enabled) - Change nickname (sends /nick command on save) - Timezone selection (default: auto-detect from browser) - Dark/light theme toggle (default: dark) - Reconnection in background toggle (default: enabled) - Max reconnection attempts (default: 0 = infinite) All settings persisted in a single cookie (lispchat_settings) as JSON, valid for 365 days. No server-side changes required. New files: - src/static/modules/settings.js (settings storage + modal logic) Modified files: - src/static/main.js (/settings intercept, settings init) - src/static/modules/formatting.js (runtime image preview toggle) - src/static/modules/network.js (reconnect settings, timezone from settings) - src/static/style.css (modal + light theme CSS) * fix(web): settings panel issues - autocomplete, live refresh, light theme, reorder 1. /settings now appears in slash-command autocomplete (added as client-only command in autocomplete.js) 2. Toggling image preview now re-renders all existing messages (refreshMessageContent in messages.js, called from settings listener) 3. Light theme fixed: msg-content, timestamp, msg-from, links, commands, and user mention colors now have proper contrast against light background. Added CSS filter for inline color spans to darken mention colors in light mode. 4. Settings modal fields reordered: image preview, dark/light theme, reconnect in background, max reconnect attempts, timezone, nickname * fix(web): image preview live refresh, light theme input/contrast, /settings prefix 1. Image preview toggle now properly collapses existing images: - Fixed refreshMessageContent to handle multi-line rawContent (\n) - Split on literal backslash-n and re-join with <br> - Re-applies reply reference states after re-render - Skip empty rawContent entries 2. Light theme fixes: - Input overlay text color now dark (#222) in light theme - Username/mention color contrast improved: brightness(0.55) saturate(1.5) filter on all .message span[style*='color:'] (covers both fromSpan and mention spans) 3. /settings command matching relaxed to startsWith so '/settings ' and '/settings extra' both open the modal * fix(web): robust image preview toggle, settings modal close, light theme prefix 1. Image preview toggle now uses CSS body class (image-preview-disabled) instead of re-rendering all messages. Unchecking hides all existing previews immediately; checking shows them again. New messages generate the img tag and are shown/hidden by the body class. Removed fragile refreshMessageContent logic. 2. Settings modal auto-close fixed: - Added stopPropagation() and preventDefault() on Save/Cancel buttons - Removed focus/blur race conditions from button handlers - Prevent overlay click from bubbling through modal contents 3. Light theme now applies to #username-prefix (dark color + contrast filter) so the nickname label over the input area is readable. 4. Simplified main.js: removed formatting import, listener just calls settings.applyAll() which toggles both theme and image classes. * chore: remove accidental temp files * fix(web): light theme contrast for user list and nickname prefix 1. #sidebar h3 gets dark color and lighter border in light theme. 2. #user-list .user-item applies the same high-contrast filter used for username colors in messages, so bright generated user colors remain readable against the light sidebar. 3. #username-prefix now keeps its generated user color and applies the brightness/saturate filter in light mode instead of being forced to black. The CSS uses color: inherit so JS-styled color still applies. 4. Added window.isLightTheme flag set by settings.applyTheme(). users.js applies filter on render and exposes refreshUserListColors() to update existing items when toggling theme. 5. main.js settings listener re-renders user list colors and the username prefix whenever settings change. * fix(web): settings nickname change sends /nick and updates local state Bug: after saving a new nickname in settings, nothing happened. Root causes: 1. pendingSettings was set to null by closeModal() before the save handler checked pendingSettings.nickname, so the /nick command was never sent. 2. The local auth username and prefix were not updated, so the UI still showed the old nickname even if the server accepted the change. Fix: - Capture newNickname before closing the modal. - Send /nick <newNickname> over the WebSocket when connected. - Immediately call auth.setUsername() and auth.updateUsernamePrefix() so the prefix updates locally without waiting for server broadcast. - notifyListeners() is invoked after the async nick update as well. Non-nick saves keep the previous synchronous notifyListeners() path. * fix(web): pre-fill settings nickname and resolve dynamic import default 1. Nickname input in the settings modal now pre-fills with the current username from auth.getUsername() so users see their nick before editing. 2. The dynamic import('./network.js') returns the module namespace object, whose default export is the network API. The previous code called network.getWs() on the namespace itself, throwing 'network.getWs is not a function'. Fixed by extracting module.default before accessing getWs(). * refactor(web): remove timezone setting, keep auto-detection The timezone dropdown in settings was not actually used by the server for anything meaningful; the WebSocket connection already sent a tz parameter that was previously read from settings. This change removes the timezone UI and setting entirely. - Removed timezone from DEFAULTS and from the settings modal HTML. - Removed timezoneOptions array. - Removed pendingSettings.timezone read from save handler. - getTimezoneOffset() now always auto-detects from the browser. - network.js computes tzOffset directly via Date.getTimezoneOffset(). * fix(web): light theme input cursor and colored prefix 1. Added caret-color: #222 to body.light-theme #message-input so the text cursor is dark on the light input background instead of white. 2. Removed the body.light-theme #username-prefix rule that forced color: inherit. The JS sets prefix.style.color to the generated user color, so keeping that rule makes the prefix use the colored text. The brightness/saturate filter already handles contrast in light mode. * fix(web): reconnect on page focus when background reconnect is disabled The 'Reconnect while in background' setting now only controls whether reconnection happens while the tab is hidden. When disabled: - If the page is visible and the socket disconnects, it reconnects immediately (same as before). - If the page is hidden and the socket disconnects, it waits. When the page becomes visible again, a visibilitychange listener triggers reconnection automatically. When enabled, the behavior is unchanged: reconnection happens regardless of page visibility. - savedOnMessageCallback stores the callback so connect() can be called without arguments from the visibilitychange listener. - Renamed setting label from 'Reconnection in background' to 'Reconnect while in background' for clarity. - Bumped static asset hashes. * revert: keep index.html hash placeholder * fix(web): light theme sidebar and user items on mobile The mobile media query (max-width: 768px) re-declared #sidebar background: #1a1a1a and .user-item background: #2a2a2a, overriding the light-theme rules due to higher specificity. Added light-theme overrides inside the media query: - #sidebar: #e8e8e8 background, #ccc border - .user-item: #ddd background (clear gray instead of dark #2a2a2a) Bumped static asset hashes. * fix(web): remove sidebar/userlist background in light theme Both desktop and mobile light-theme rules for #sidebar and .user-item now use background: transparent. Dark theme keeps #1a1a1a / #2a2a2a. * fix(web): reply highlight visible in light theme, persists until scroll 1. Dark theme: highlight starts at rgba(255,255,255,0.2) and settles to rgba(80,80,80,0.4) gray — stays visible instead of fading to transparent. 2. Light theme: new highlightFadeLight animation starts at rgba(120,120,120,0.35) dark gray and settles to rgba(200,200,200,0.4) lighter gray — visible against the light background. 3. Animation shortened from 3s to 1.5s (settles faster). 4. .focused class now persists until the user scrolls, clicks, or types — same behavior as shared-focus (URL message_ref). Removed the 3s auto-timeout. Listeners added after 800ms delay so the initial scrollIntoView doesn't trigger immediate removal. * revert: restore index.html and bump_static.sh to master state Revert accidental hash bumps to index.html. These files should not be modified in this PR — hash bumping happens at deploy time, not during development. * feat(web): auto-load history on scroll setting (disabled by default) Adds an 'Auto-load history on scroll' checkbox to the settings modal. When enabled: - Scrolling to the top automatically loads older messages (same as clicking the ⬆ button). - Scrolling near the bottom in historical context automatically loads newer messages (same as clicking the ⬇ button). When disabled (default): - Behavior is unchanged: ⬆/⬇ buttons appear on scroll, user clicks to load. Refactored history.js: - Extracted loadOlderHistory() and loadNewerHistory() as standalone async functions (previously inline in click handlers). - isLoadingHistory/isLoadingNewer flags moved to module scope. - Scroll listener checks settings.get('autoloadHistory') and either calls the load functions directly or shows/hides buttons. - Button click handlers now delegate to the same functions. * fix(web): apply same highlight to absolute link message references Changed the class 'shared-focus' to 'focused' when expanding an absolute message_ref in the URL. This re-uses the new highlight animations (with proper light/dark theme contrast) and persists until the user scrolls, clicks, or types. * fix(web): prevent image previews from exceeding viewport width on mobile Added `max-width: min(400px, 100%)` to `.image-preview` (with a 400px fallback for legacy browsers) so that inline images naturally scale down to fit the chat container on narrow mobile screens, preventing them from generating horizontal scrollbars.
fix: timezone localization from client-side (#149) * web: fix timezone localization from client-side * feat: support timezone defined by websockect session from server * Revert "web: fix timezone localization from client-side" This reverts commit 2c48874. * web: fix timezone localization from client-side - Dynamically calculate browser's timezone offset and append it as `tz` query parameter to the WebSocket URL. - Remove hardcoded America/Sao_Paulo timezone from `getTodayDate` allowing the date to be calculated in the local timezone. * emacs: fix timezone localization from client-side - Dynamically calculate system timezone offset and append it as `tz` query parameter to the WebSocket URL during connections and reconnections. * client: fix timezone localization from client-side - Dynamically calculate system timezone offset using get-decoded-time. - Append it as `tz` query parameter to the WebSocket URL during connection.
feat(web): add button to load older messages in top chat area (#143) * feat: add to /log the parameters :before, :after and :around * feat: add button to load old messages * fix: upper arrow of the load message button in html * draft: working version with dirty code * refactor: cleanup useless code during debug of custom headers * fix: ensure session ID is filled up and unify login procedure Problems: - with multiple ways of login when user already has a cookie username or the username prompt is show, only new users would have a properly - when no sessionId is not filled, the Client-Session is not passed, creating a problem of not authenticated command. - raise a error if fetchCommand is called without have a session id (can be improved later by setting a special default parameter called authenticated as false, so when is true it verify this session) * refactor: address code review feedback - Move session ID state from network.js to auth.js - Keep session ID extraction in messages.js as a system message - Unify server message filtering in commands.lisp with filter-messages helper - Improve log command readability with get-messages-around helper - Enhance api.js with provideSession flag and channels method - Update autocomplete.js to use new api methods - Add explanatory comment to sw.js activate event * fix(web): do not cache messages when prepending This prevents 'Load older messages' from overflowing the messageCache length limit with older messages, which was pushing the newest messages out of the cache and causing the duplicate reconnection bug. * fix(web): use rawContent in addRawMessage for consistent deduplication
feat: improve web app UX (#133) * feat(web): highlight /command with green color Closes #111 * feat(web): group multiline message from server Closes #114 * fix(web): keyboard is not autofocused anymore in desktop version Closes #128 * feat(web): web: make login step of username prompt more clear Closes #132 * refactor: desktop min width constant and unify autofocus * refactor: LoginNotification to LoginPanel and new message
fix: userlist consistency across clients (#107) * fix: /users command not always showing response in web client Inverse the logic of the background task counter to track user requests instead of background requests to avoid swallowing manual /users calls. * fix: userlist not updating properly in Emacs client Update userlist by calling /users periodically and on /join, while hiding background users command responses. * fix: TUI users list not updated periodically Send /users command periodically instead of /ping to keep the users list up-to-date, and hide the response unless explicitly requested.
feat: set user-agent for native lisp-chat client (#102) * fix(emacs): set user-agent as Emacs/<version> (<system>) * feat: set user-agent for native lisp-chat client Exposes as user-agent that set of information: - lisp-chat version - operating system - machine type (x86, arm) - kind of client: readline-interface / TUI - lisp implementation / compiler version
fix(tui): prevent periodic ping from auto-scrolling to bottom (#97) * fix(tui): prevent periodic ping from auto-scrolling to bottom * fix(tui): preserve scroll position on layout recalculation * fix(tui): ensure autoscroll works with incoming messages
PreviousNext