Commit Graph
221 Commits
Author SHA1 Message Date
Lotus CI 28dee7bea0 Merge remote-tracking branch 'origin/main' into desktop-keychain
# Conflicts:
#	src-tauri/src/lib.rs
2026-09-30 20:18:53 -04:00
jared 03e3937e21 Merge pull request 'Call page on its own origin, http://127.0.0.1:44548 (cinny #43)' (#27) from desktop-call-origin into main
Build Lotus Chat Desktop / prepare (push) Canceled after 0s
Build Lotus Chat Desktop / build-windows (push) Canceled after 0s
Build Lotus Chat Desktop / build-linux (push) Canceled after 0s
Build Lotus Chat Desktop / build-arch (push) Canceled after 0s
Build Lotus Chat Desktop / update-manifest (push) Canceled after 0s
Merge pull request #27: call page on its own origin, http://127.0.0.1:44548 (cinny #43)
2026-09-30 20:17:24 -04:00
jared 97ccc97a70 Merge pull request 'WebView permissions only for the app's own origin (#22)' (#26) from webview-permission-origin into main
Build Lotus Chat Desktop / prepare (push) Canceled after 0s
Build Lotus Chat Desktop / build-windows (push) Canceled after 0s
Build Lotus Chat Desktop / build-linux (push) Canceled after 0s
Build Lotus Chat Desktop / build-arch (push) Canceled after 0s
Build Lotus Chat Desktop / update-manifest (push) Canceled after 0s
Merge pull request #26: WebView permissions only for the app's own origin (#22)
2026-09-30 20:17:19 -04:00
Lotus CIandClaude Opus 5.5 261d7852cb fix(updater): package installs update through their package manager
On CachyOS the in-app update failed with "Permission denied (os error 13)
at path /usr/bin/tauri_current_app…": the app was installed from the
Arch package, and Tauri's Linux updater can only replace an AppImage — for
anything else it tries to write next to the binary in /usr/bin.

- update_install_kind command: "in-app" on Windows and for an AppImage
  ($APPIMAGE set); on Linux package installs "pacman" (ID/ID_LIKE arch:
  Arch, CachyOS, Manjaro, EndeavourOS…), "deb" (debian/ubuntu and
  derivatives) or "manual". The web UI shows the matching update command.
- install_update refuses up front on a package install
  ("install: package-managed (…)") instead of downloading the whole
  update and failing at the last step.

Tests: CachyOS/Arch → pacman; Ubuntu/Debian/Mint → deb; Fedora/unknown →
manual; AppImage and Windows → in-app.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
2026-09-30 18:46:11 -04:00
Lotus CI bd32048461 Merge remote-tracking branch 'origin/main' into desktop-keychain 2026-09-30 11:00:19 -04:00
Lotus CI 63a8ebe103 Merge remote-tracking branch 'origin/webview-permission-origin' into desktop-call-origin
# Conflicts:
#	config.json
2026-09-30 11:00:17 -04:00
Lotus CI eeb838c00c Merge remote-tracking branch 'origin/main' into webview-permission-origin 2026-09-30 10:59:51 -04:00
Lotus CIandClaude Opus 5.5 12ad4bf681 windows smoke: fake capture devices in the opt-in test mode
The CI VM has no microphone (getUserMedia → NotFoundError). With
LOTUS_WEBVIEW2_DEBUG_PORT set the app also passes
--use-fake-device-for-media-stream; permission requests still go through
the real PermissionRequested handler.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
2026-09-30 10:32:45 -04:00
Lotus CIandClaude Opus 5.5 9f0f782bbb windows smoke: opt-in WebView2 DevTools port via LOTUS_WEBVIEW2_DEBUG_PORT (#19)
WebView2's WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS is ignored because the app
sets its browser arguments explicitly (seen on the runner: the WebView2
command line had only the app's arguments). The app now appends
--remote-debugging-port only when LOTUS_WEBVIEW2_DEBUG_PORT holds a valid
port (>= 1024); otherwise the arguments are exactly as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
2026-09-29 13:19:21 -04:00
Lotus CIandClaude Opus 5.5 032b6e04e7 feat: secure_session commands, login tokens in the OS keychain (cinny #105, step 1)
Commands for the web client to keep a copy of the login tokens in the OS
keychain: secure_session_supported / _set / _get / _clear.

- Windows: Credential Manager via the keyring crate (3.6, windows-native),
  entry "session" in service "Lotus Chat". Only the secrets are stored
  (userId, deviceId, accessToken, refreshToken); the serialized value is
  capped at 1200 chars (Windows' limit is 2560 bytes).
- Other platforms: supported = false and the other commands answer "not
  supported on this platform" (Linux Secret Service can prompt to unlock a
  wallet at startup; that needs its own testing). No new Linux dependency:
  without a platform feature the crate only has its mock store.
- Keychain calls run on the blocking pool, off the main thread.

Step 1 is a mirror only (the web client still reads its session from
localStorage); see the cinny PR.

Tests: round trip + clear, clearing an empty keychain, incomplete and
oversized sessions rejected with nothing written, the JSON shape the web
client sends, a realistic OIDC session fits (keyring's mock store). Linux
release build: commands answer as designed and login is unaffected.
Windows: type-checked only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
2026-09-29 00:25:01 -04:00
Lotus CIandClaude Opus 5.5 5c3ac68328 feat: call page on its own origin, http://127.0.0.1:44548 (cinny #43)
The bundled Element Call page ran on the app's own origin
(http://localhost:44548), so the call frame could read the app's storage
(login token) and DOM. Serve it from http://127.0.0.1:44548 instead: the
same local server and bundle, a different origin.

- The local server binds 127.0.0.1 explicitly. The app is still loaded as
  http://localhost:44548 (its storage stays where it is; the engines try
  127.0.0.1 for `localhost`). Binding the name `localhost` could pick ::1
  only (Windows lists it first), and then 127.0.0.1 wouldn't answer.
- config.json: desktopCallOrigin = http://127.0.0.1:44548. cinny loads the
  call page from there only when this is set (cinny #43 PR).
- CSP frame-src allows http://127.0.0.1:44548.
- Permissions (on top of #22): the call page's origin gets microphone/
  camera/screen only; nothing else.
- The call page gets no IPC: the capability only matches
  http://localhost:44548.

Tested (Linux release build): the server listens on 127.0.0.1:44548 and
the app loads as http://localhost:44548; the call page loads from
127.0.0.1 inside the app under its CSP; from that frame parent.localStorage
and parent.document are SecurityError, while a same-origin frame (the old
setup) reads the app's storage. The call itself was tested in a simulated
desktop (Chromium, the WebView2 engine) against a local Synapse + LiveKit;
see the cinny PR. Rust tests 17 passed; Windows code type-checked.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
2026-09-29 00:09:41 -04:00
Lotus CIandClaude Opus 5.5 3e136d3729 fix: WebView permissions only for the app's own origin (#22)
Linux (WebKitGTK) allowed every permission request of every kind; Windows
(WebView2) auto-allowed mic/camera/notifications without checking who asked.

Now (src-tauri/src/webview_permissions.rs, unit-tested):
- Linux: microphone/camera/screen, device labels, notifications and location
  are granted when the page in the window is the app
  (http://localhost:44548; debug builds also the bundled/dev page).
  Everything else is denied (WebKitGTK has no prompt of its own). WebKitGTK
  doesn't say which frame asked; frames are gated earlier by the Permissions
  Policy (cinny gives microphone/camera only to the same-origin call frame).
- Windows: the same grants (minus location, which keeps WebView2's prompt),
  checked against the origin of the frame that asked (args.Uri()). Other
  origins are denied mic/camera/notifications/location; other kinds keep
  WebView2's default handling.
- Denials are logged ("webview: denied …").

Tested on Linux with a release build under Xvfb + PulseAudio (no WebDriver:
WebKit's automation mode bypasses the handler), before/after:
- app page: mic, device labels, location allowed (unchanged)
- same-origin call frame: mic allowed (unchanged)
- cross-origin frame without allow=: blocked before the handler (unchanged)
- foreign top-level page: mic, device labels, location now denied (were
  allowed)
Real cinny build: boots, logs in, no denials. Windows code type-checked
(x86_64-pc-windows-gnu).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
2026-09-28 20:03:11 -04:00
Lotus CIandClaude Opus 5.5 bb5364b53c fix(linux): NVIDIA + Wayland keeps the GPU renderer (explicit-sync fix)
The 4.12.343 workaround (WEBKIT_DISABLE_DMABUF_RENDERER=1 + GDK_BACKEND=x11)
made the app launch but pushed every frame through shared memory under
XWayland: noticeably laggy at 3840x2058. The reporter's WAYLAND_DEBUG trace
showed the real cause on native Wayland:

  wl_display#1.error(wp_linux_drm_syncobj_surface_v1#51, 4,
    "explicit sync is used, but no acquire point is set")
  Gdk-Message: Error 71 (Protocol error) dispatching to Wayland display.

An explicit-sync bug, not a GBM format/modifier one. Their test matrix
(RTX 3070, driver 615.71.09, webkit2gtk 2.52.6, KDE Wayland):
- __NV_DISABLE_EXPLICIT_SYNC=1 alone: clean, GPU (DMA-BUF) renderer, smooth;
- WEBKIT_DISABLE_DMABUF_RENDERER=1 alone on Wayland: clean (no X11 needed);
- WEBKIT_DMABUF_RENDERER_DISABLE_GBM=1: same explicit-sync error on Wayland,
  "Failed to import DMABuf" under XWayland;
- X11/XWayland with the DMA-BUF renderer: "Failed to create GBM buffer".

New defaults when the NVIDIA driver is loaded:
- native Wayland: __NV_DISABLE_EXPLICIT_SYNC=1, GPU renderer kept;
- X11 session or user-forced GDK_BACKEND=x11: WEBKIT_DISABLE_DMABUF_RENDERER=1;
- never force X11 any more;
- LOTUS_GPU_SAFE_MODE=1: opt-in shared-memory rendering on Wayland too;
- LOTUS_NO_GPU_WORKAROUNDS=1 / user-set values: untouched.
One stderr line says what was set. 9 unit tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
2026-09-27 22:22:00 -04:00
Lotus CIandClaude Opus 5.5 df760abdc7 fix(linux): launch on NVIDIA + Wayland; config webAppUrl for "call in browser"
NVIDIA + Wayland (reported on CachyOS/KDE, driver 615.71, webkit2gtk
2.52.6): no window. GDK dies with "Error 71 (Protocol error) dispatching to
Wayland display"; forced onto XWayland, WebKit's DMA-BUF renderer then fails
with "Failed to create GBM buffer … Invalid argument". The reporter's
workaround, WEBKIT_DISABLE_DMABUF_RENDERER=1 GDK_BACKEND=x11, runs fine.

gpu_workarounds::apply(), first thing in main() (before GTK/WebKit init):
when the NVIDIA driver is loaded (/proc/driver/nvidia/version or
/sys/module/nvidia), set WEBKIT_DISABLE_DMABUF_RENDERER=1, and on a Wayland
session that has XWayland (DISPLAY set) also GDK_BACKEND=x11. Values the user
already set win; LOTUS_NO_GPU_WORKAROUNDS=1 turns it all off. Logs what it
set to stderr. Non-NVIDIA systems are untouched. Unit tests for the decision.

config.json: webAppUrl = https://chat.lotusguild.org, used by the web client
(cinny `calls-open-in-browser`) to send calls this WebKitGTK build can't make
to the web app in the browser.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
2026-09-27 16:56:36 -04:00
Lotus CIandClaude Opus 5.5 71ab1afdaf feat(close): first-close choice — tray or quit — and a call guard (#5)
Build Lotus Chat Desktop / prepare (push) Successful in 10s
Build Lotus Chat Desktop / build-linux (push) Successful in 28m46s
Build Lotus Chat Desktop / build-arch (push) Successful in 14s
Build Lotus Chat Desktop / build-windows (push) Successful in 38m32s
Build Lotus Chat Desktop / update-manifest (push) Successful in 9s
Closing the window (OS close button or the custom title bar's ×) now
goes through one handler:
- in a call → always hide to the tray (a close must never drop a call);
- saved "tray" → hide; "quit" → exit the app;
- "ask" (the default until chosen) → emit `lotus-close-requested` so the
  web client shows the one-time dialog; if the page isn't listening yet,
  fall back to the tray.
The choice lives in `close-behavior` in the app config dir;
get_close_behavior / set_close_behavior / resolve_close_request back the
dialog and the Settings select.

Verified on Linux under Xvfb + openbox with real WM close requests
(wmctrl -c): tray → hidden, still running; quit → exits; unset with no
page listening → hidden; ask with the page listening → window stays,
page receives the event; quit during a call → hidden, still running.

Bump cinny (the dialog + Settings control).

Closes #5

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
2026-09-24 12:51:28 -04:00
Lotus CIandClaude Opus 5.5 67253d02f8 feat(autostart): start minimized to the tray on login (#3)
Build Lotus Chat Desktop / prepare (push) Successful in 7s
Build Lotus Chat Desktop / build-windows (push) Successful in 34m32s
Build Lotus Chat Desktop / build-linux (push) Successful in 36m5s
Build Lotus Chat Desktop / build-arch (push) Successful in 19s
Build Lotus Chat Desktop / update-manifest (push) Successful in 4s
- Launch-on-login now starts the app with `--autostart`. With "Start
  minimized" on (the default), that launch begins "settled", so neither
  the page-load reveal nor the 8 s failsafe shows the window: it stays in
  the tray with sync and notifications running. The tray, a second launch
  or a deep link reveals it.
- The choice is a file in the app config dir (`start-minimized`), read
  before the web client loads; `get_start_minimized` / `set_start_minimized`
  back the new Settings switch.
- Existing registrations made without args are rewritten at startup
  (re-enable), so current launch-on-login users get `--autostart` too.
- window-state no longer restores VISIBLE: it show()ed the window at
  creation whenever it was last closed visible (or on first run), before
  the page painted and even on a login start. Visibility is owned by the
  page-load reveal + failsafe.

Verified on Linux under Xvfb with the debug build:
  normal launch → shown; --autostart → hidden (past the failsafe) and still
  running; --autostart with the setting off → shown; --autostart after
  quitting visible → hidden; normal launch after quitting visible → shown;
  a second launch reveals the hidden instance; an existing autostart entry
  gets `--autostart` added.

Bump cinny (the Settings switch and the SW protocol guard).

Closes #3

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
2026-09-23 22:46:24 -04:00
Lotus CIandClaude Opus 5.5 9e320fa326 feat(native): taskbar progress bar during uploads (#10)
Build Lotus Chat Desktop / prepare (push) Successful in 8s
Build Lotus Chat Desktop / build-windows (push) Canceled after 4m46s
Build Lotus Chat Desktop / build-linux (push) Canceled after 0s
Build Lotus Chat Desktop / build-arch (push) Canceled after 0s
Build Lotus Chat Desktop / update-manifest (push) Canceled after 0s
`set_taskbar_progress(status, progress)` drives Tauri's window progress
bar (Windows taskbar button; launcher/dock elsewhere where supported):
none / normal (0-100) / indeterminate / error. Uses Tauri's built-in
ITaskbarList3 wrapper rather than more hand-written COM.

Bump cinny (the aggregation, throttling and error hold).

Closes #10

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
2026-09-23 22:04:54 -04:00
Lotus CIandClaude Opus 5.5 33d8871ac8 feat(tray): show call state on the tray icon (#4)
`set_tray_call_state({active, muted, deafened})` adds a small ringed dot
to the tray icon's bottom-left: green in a call, amber muted, red
deafened (deafened implies muted). The unread dot stays bottom-right.
The tooltip spells it out ("Lotus Chat — in call, muted · update ready").

Unread, call state and the pending update (#6) now live in one
`TrayIndicators` and re-render together, so none of them overwrites
another. The unread painter is generalised to `draw_dot(left, color)`.
Unit tests cover the tooltip text and dot placement.

Bump cinny to 25fa0f6e (the web half, plus the stale-state fix that
removed a "muted + deafened" flash at every join).

Closes #4

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
2026-09-23 21:54:04 -04:00
Lotus CIandClaude Opus 5.5 687642a096 feat(tray): "Restart to update" item and tooltip (#6)
Build Lotus Chat Desktop / prepare (push) Successful in 6s
Build Lotus Chat Desktop / build-windows (push) Successful in 32m18s
Build Lotus Chat Desktop / build-linux (push) Successful in 39m16s
Build Lotus Chat Desktop / build-arch (push) Successful in 17s
Build Lotus Chat Desktop / update-manifest (push) Successful in 4s
`set_tray_update_ready(version | null)` inserts a "Restart to update
(vX)" item at the top of the tray menu and sets the tooltip to "Lotus
Chat — update ready"; null removes both. The item only exists while an
update is pending. Clicking it reveals the window and emits
`lotus-tray-install-update`, and cinny runs its normal install flow
(progress, retries, failure toast). No icon dot: the unread dot already
uses that corner.

Bump cinny to 6edfe700 (the web half).

Closes #6

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
2026-09-23 21:32:39 -04:00
Lotus CIandClaude Opus 5.5 8f98a82562 fix(updater): retry the check and download, report progress
Build Lotus Chat Desktop / prepare (push) Successful in 5s
Build Lotus Chat Desktop / build-windows (push) Canceled after 4m13s
Build Lotus Chat Desktop / build-linux (push) Canceled after 0s
Build Lotus Chat Desktop / build-arch (push) Canceled after 0s
Build Lotus Chat Desktop / update-manifest (push) Canceled after 0s
A friend's in-app update failed ten times ("error sending request for
url (…nsis.zip)") against a busy Gitea before the 11th worked.

- check_for_update / install_update retry transport errors (Reqwest,
  Network, ReleaseNotFound) with 3 s / 8 s / 15 s backoff — four tries
  per click. Signature or install errors fail at once, never masked.
- Every request gets a 600 s timeout; reqwest has none by default, so a
  stalled connection could leave the UI on "installing" forever.
- Download and install are separate steps so a retry never re-installs.
- `lotus-update-progress` events (downloading %, retrying + wait,
  installing) drive the new progress text in Settings.
- Errors are prefixed `check:` / `download:` / `install:` so the UI says
  which step failed (it used to call a failed download "Update check
  failed").
- Adds tokio (time feature only; already in the tree via tauri).
- Bump cinny to 568f218f (the matching UI).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
2026-09-23 20:54:19 -04:00
Lotus CIandClaude Opus 5.5 5a9bfa8fe4 feat(native): "Mark as read" button on rich toasts (#9)
Build Lotus Chat Desktop / prepare (push) Successful in 7s
Build Lotus Chat Desktop / build-windows (push) Canceled after 32m48s
Build Lotus Chat Desktop / build-linux (push) Canceled after 32m25s
Build Lotus Chat Desktop / build-arch (push) Canceled after 0s
Build Lotus Chat Desktop / update-manifest (push) Canceled after 0s
Toasts with a room id get a Mark as read action next to Send; it emits
`lotus-notification-mark-read {roomId}` without raising the window, and
cinny marks the room read through its existing markAsRead path. Invite
toasts (no room id) get neither button.

Bump cinny to 23649f12.

Closes #9

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
2026-09-23 19:49:54 -04:00
Lotus CIandClaude Opus 5.5 4648c8ccc7 fix(updater): installer waits for the old cinny.exe to release (#1)
Build Lotus Chat Desktop / prepare (push) Canceled after 0s
Build Lotus Chat Desktop / build-windows (push) Canceled after 0s
Build Lotus Chat Desktop / build-linux (push) Canceled after 0s
Build Lotus Chat Desktop / build-arch (push) Canceled after 0s
Build Lotus Chat Desktop / update-manifest (push) Canceled after 0s
The updater launches the NSIS installer with /UPDATE and then exits the
app, but a WebView2 app takes a moment to die and the template only
sleeps 500 ms after its own kill before copying — so the copy raced the
old process ("Error opening file for writing: cinny.exe"), and Ignore
left the old exe in place.

A NSIS_HOOK_PREINSTALL now, on /UPDATE only, polls until cinny.exe can
really be opened for writing (every 250 ms, up to 15 s), then lets the
template carry on. Checked under Wine with a real running exe: without
the hook the copy fails; with it the installer waits out the remaining
~2.8 s and copies; a manual install (no /UPDATE) doesn't wait; a stuck
process hits the 15 s cap and falls through to the template's own
running-app handling.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
2026-09-23 19:39:00 -04:00
Lotus CIandClaude Opus 5.5 c1ae01bf41 fix(native): toast coalescing, real reply target, Focus Assist mount query
Build Lotus Chat Desktop / prepare (push) Canceled after 0s
Build Lotus Chat Desktop / build-windows (push) Canceled after 0s
Build Lotus Chat Desktop / build-linux (push) Canceled after 0s
Build Lotus Chat Desktop / build-arch (push) Canceled after 0s
Build Lotus Chat Desktop / update-manifest (push) Canceled after 0s
- Rich toasts set a WinRT Tag (hash of the web notification tag, since
  room:thread tags exceed the 64-char limit) in a fixed Group, so a newer
  toast for the same room/thread replaces the older one instead of
  stacking; the replaced toast's keep-alive entry is dropped (#16).
- The bridge passes tag, roomId and threadId separately. The reply target
  is the real room id (+ thread), never the coalescing tag, which was
  `room:thread` for threads and `lotus-invites` for invites, so those
  replies failed silently. Toasts with no room id (invites) get no reply
  box (#17).
- New `get_focus_assist` command serves the latest Focus Assist poll so
  the web hook can hydrate on mount; the setup-time first emit was lost
  before the page listened (#15).
- Bump cinny to 3b6de2fd (the matching web-side hooks).

Closes #15, #16, #17

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
2026-09-23 19:33:30 -04:00
jaredandClaude Opus 5 83c89b894a csp: drop fonts.googleapis.com / fonts.gstatic.com — Lotus Chat self-hosts VT323 now
Build Lotus Chat Desktop / prepare (push) Successful in 8s
Build Lotus Chat Desktop / build-linux (push) Successful in 25m25s
Build Lotus Chat Desktop / build-arch (push) Successful in 12s
Build Lotus Chat Desktop / build-windows (push) Canceled after 30m4s
Build Lotus Chat Desktop / update-manifest (push) Canceled after 0s
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
2026-09-19 13:17:18 -04:00
jaredandClaude Opus 5 4d0cfaa194 feat(native): system-wide PTT/deafen via a non-consuming key poll (#2)
Build Lotus Chat Desktop / prepare (push) Successful in 3s
Build Lotus Chat Desktop / build-windows (push) Canceled after 0s
Build Lotus Chat Desktop / build-linux (push) Canceled after 0s
Build Lotus Chat Desktop / build-arch (push) Canceled after 0s
Build Lotus Chat Desktop / update-manifest (push) Canceled after 0s
PTT and deafen are DOM key handlers in cinny and only fire while the Lotus
window has focus — alt-tab into a fullscreen game and the voice controls
stop working.

New native/hotkeys.rs (Windows): `set_global_hotkeys(bindings)` starts a
thread that samples GetAsyncKeyState for the configured W3C key codes every
~8 ms while a call is joined and emits a `lotus-global-hotkey` DOM event
{id, state, ctrl, alt, meta} on each press/release transition; an empty
list stops it. Deliberately NOT RegisterHotKey / a global-shortcut plugin:
those consume the key system-wide (a bare Space PTT would stop every other
app typing spaces). `global_hotkeys_supported` reports false off Windows,
where the commands are no-ops (Linux X11 could poll XQueryKeymap later;
Wayland has no non-consuming path). HotkeyPoll state is managed
unconditionally in setup. Cargo: Win32_UI_Input_KeyboardAndMouse feature.
Cross-checked against windows 0.61 for x86_64-pc-windows-msvc; Linux
cargo check clean.

Web side: cinny 00584d78 (useCallHotkeys + Settings → Calls toggle).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
2026-09-17 13:40:57 -04:00
jaredandClaude Sonnet 5 392de28f46 fix(linux): enable WebRTC in WebKitGTK; add Arch package build
Build Lotus Chat Desktop / prepare (push) Successful in 1m0s
Build Lotus Chat Desktop / build-windows (push) Successful in 41m27s
Build Lotus Chat Desktop / build-linux (push) Successful in 46m34s
Build Lotus Chat Desktop / build-arch (push) Failing after 23s
Build Lotus Chat Desktop / update-manifest (push) Successful in 12s
WebKitGTK ships enable-media-stream/enable-webrtc off by default
(unlike WebView2/WKWebView), leaving navigator.mediaDevices undefined
and Element Call reporting "browser does not support WebRTC" on every
Linux build. Enable both settings and auto-grant the resulting
camera/mic permission request, mirroring the existing WebView2 handling.

Also add a build-arch CI job that repackages the existing .deb into a
real .pkg.tar.zst and uploads it to the Gitea release alongside the
Windows/Linux artifacts, for Arch/CachyOS users who'd rather use pacman
than an AppImage.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-24 22:08:21 -04:00
Claude 58791930db fix(csp): allow Mixcloud, Deezer, and Steam iframe embeds in desktop app
Build Lotus Chat Desktop / prepare (push) Successful in 15s
Build Lotus Chat Desktop / build-linux (push) Successful in 26m57s
Build Lotus Chat Desktop / build-windows (push) Successful in 29m50s
Build Lotus Chat Desktop / update-manifest (push) Successful in 4s
The Tauri frame-src is an enumerated allowlist (unlike the permissive web CSP
`frame-src 'self' https:`), so embeds whose host isn't listed render as a
blank box in the desktop app with no visible error. Adds the two new music
providers (www.mixcloud.com, widget.deezer.com) and store.steampowered.com,
whose Steam widget shipped earlier but was already blank on desktop.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 23:43:14 -04:00
jaredandClaude Opus 4.8 33b1a45edd fix(windows): merge taskbar icon (AUMID) + focus window on notification click
Build Lotus Chat Desktop / prepare (push) Successful in 3s
Build Lotus Chat Desktop / build-linux (push) Successful in 24m50s
Build Lotus Chat Desktop / build-windows (push) Successful in 32m26s
Build Lotus Chat Desktop / update-manifest (push) Successful in 4s
Taskbar showed two icons because the AppUserModelID was (a) set too late — after
the main window was built, so its taskbar button grouped under a mismatched
implicit AUMID — and (b) valued 'LotusGuild.LotusChat', which differs from the
bundle identifier 'org.lotusguild.lotus-chat' that Tauri's NSIS installer stamps
on its shortcuts. Fix both: set the AUMID at the top of run() before the window
is built (new set_process_aumid, split out of ensure_app_user_model_id), and
align the constant to the bundle identifier so the running window and a pinned
installer shortcut group together.

Notification click didn't raise the window: add a focus_main_window command
(reuses show_main) for the web/service-worker path, and call show_main directly
in the rich-toast Activated body-click handler.

Note: existing users who pinned the old mis-grouped icon may need to re-pin once.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 23:40:57 -04:00
jaredandClaude Opus 4.8 527ebd200d fix(csp): allow Bluesky/Loom/Kick embeds in frame-src
Build Lotus Chat Desktop / prepare (push) Successful in 5s
Build Lotus Chat Desktop / build-linux (push) Successful in 24m21s
Build Lotus Chat Desktop / build-windows (push) Successful in 28m30s
Build Lotus Chat Desktop / update-manifest (push) Successful in 1m6s
Add embed.bsky.app, www.loom.com, player.kick.com.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 00:56:08 -04:00
jaredandClaude Opus 4.8 8b37e0c44e fix(csp): allow embed.reddit.com in frame-src
Reddit post embeds moved from www.redditmedia.com to embed.reddit.com.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 00:56:08 -04:00
jaredandClaude Opus 4.8 54c27a49ba fix(csp): allow Instagram/Tidal/Reddit embeds in frame-src
Build Lotus Chat Desktop / prepare (push) Successful in 4s
Build Lotus Chat Desktop / build-linux (push) Successful in 25m14s
Build Lotus Chat Desktop / build-windows (push) Successful in 29m18s
Build Lotus Chat Desktop / update-manifest (push) Successful in 4s
Add www.instagram.com, embed.tidal.com, www.redditmedia.com for the new inline
media embeds.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 23:05:32 -04:00
jaredandClaude Opus 4.8 f9e07434df fix(csp): allow X/Twitter post + Apple Music embeds in frame-src
Build Lotus Chat Desktop / prepare (push) Successful in 3s
Build Lotus Chat Desktop / build-linux (push) Successful in 23m48s
Build Lotus Chat Desktop / build-windows (push) Successful in 25m9s
Build Lotus Chat Desktop / update-manifest (push) Successful in 9s
Add platform.twitter.com (interactive tweet embed) and embed.music.apple.com
(Apple Music player) to the webview frame-src.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 20:24:24 -04:00
jaredandClaude Opus 4.8 5916f2f353 fix(csp): allow TikTok/Twitch/Dailymotion/Streamable/Spotify/SoundCloud embeds
Extend webview frame-src for the newly-added inline media players: www.tiktok.com,
www.dailymotion.com, geo.dailymotion.com, streamable.com, player.twitch.tv,
clips.twitch.tv, open.spotify.com, w.soundcloud.com.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 20:24:24 -04:00
jaredandClaude Opus 4.8 3af04491b2 fix(csp): allow YouTube/Vimeo embed iframes in frame-src
Lotus Chat now plays YouTube/Vimeo links inline; the webview CSP frame-src was
'self' blob: openstreetmap only, which blocked the embed players. Add
youtube-nocookie.com, youtube.com, and player.vimeo.com.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 20:24:24 -04:00
jaredandClaude Opus 4.8 8479d6e768 fix(native): correct PKEY_AppUserModel_ID import (D6 CI build)
Build Lotus Chat Desktop / prepare (push) Successful in 9s
Build Lotus Chat Desktop / build-linux (push) Successful in 25m18s
Build Lotus Chat Desktop / build-windows (push) Successful in 29m40s
Build Lotus Chat Desktop / update-manifest (push) Successful in 4s
Windows CI failed: PROPERTYKEY is not in Win32::UI::Shell::PropertiesSystem.
Use the ready-made PKEY_AppUserModel_ID constant from Win32::Storage::Enhanced
Storage (same module jumplist.rs uses for PKEY_Title, feature already enabled)
instead of hand-rolling the PROPERTYKEY — drops the GUID::from_u128 dependency.
Also simplify IPersistFile::Save's fremember arg (it's bool, not BOOL).

All windows-crate symbols now verified against windows-docs-rs (PKEY_AppUser
Model_ID / IPersistFile::Save / SetCurrentProcessExplicitAppUserModelID /
CreateToastNotifierWithId).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 11:46:53 -04:00
jaredandClaude Opus 4.8 28d960b04f fix(native): dedupe cold-start deep-link double navigation (D4)
Build Lotus Chat Desktop / prepare (push) Successful in 4s
Build Lotus Chat Desktop / build-windows (push) Failing after 26m23s
Build Lotus Chat Desktop / build-linux (push) Successful in 23m35s
Build Lotus Chat Desktop / update-manifest (push) Has been skipped
on_open_url and the argv fallback can both forward the same launch matrix: URL
on cold start, navigating the room twice. forward_deeplink now drops a repeat of
the same URL within ~1s (plain std Mutex/Instant — no windows-crate surface).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 23:19:15 -04:00
jaredandClaude Opus 4.8 f9ed3d7116 feat(native): register AUMID so Windows rich toasts work (D6)
Build Lotus Chat Desktop / prepare (push) Successful in 3s
Build Lotus Chat Desktop / build-windows (push) Failing after 25m37s
Build Lotus Chat Desktop / build-linux (push) Successful in 25m29s
Build Lotus Chat Desktop / update-manifest (push) Has been skipped
The WinRT rich toast (reply box P5-41, click-to-open-room P5-35) was inert on
Windows: CreateToastNotifier needs the process under an AppUserModelID mapped to
a Start-Menu shortcut, and none was registered — so it errored and silently fell
back to the plain plugin toast.

New native/aumid.rs (Windows-only; no-op elsewhere), called first in
native::setup: (1) SetCurrentProcessExplicitAppUserModelID("LotusGuild.LotusChat"),
(2) install/refresh a Start-Menu "Lotus Chat.lnk" carrying PKEY_AppUserModel_ID,
reusing jumplist.rs's IShellLinkW + IPropertyStore + PROPVARIANT + IPersistFile
pattern (best-effort; failures logged + swallowed). toast.rs now binds the
notifier via CreateToastNotifierWithId(AUMID).

CI-compile-only (windows runner); runtime needs a Windows build to confirm the
toast shows a reply box + opens the room. windows-crate 0.61 symbol assumptions
(IPersistFile, SetCurrentProcessExplicitAppUserModelID, PROPERTYKEY,
GUID::from_u128, CreateToastNotifierWithId) validated by CI — all mirror existing
jumplist.rs usage where possible.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 22:32:37 -04:00
jaredandClaude Opus 4.8 3a48771588 fix(native): Wave-2 audit fixes (D1, D3, D5)
- D1 (HIGH): Linux no-sleep was completely non-functional — the zbus
  ScreenSaver inhibit was bound to a function-local D-Bus connection dropped on
  return, so the screensaver service auto-released it instantly. Keep a
  long-lived Connection in managed state (InhibitState { conn, cookie }) so the
  same connection holds Inhibit and issues UnInhibit; created once, reused.
- D3: tray "Do Not Disturb" desynced from the web manualDndAtom after any reload
  (custom-chrome toggle / logout) — the atom is in-memory and reset while the
  tray stayed checked. Added TrayDndState + a get_tray_dnd command so the web
  hook re-hydrates the atom on mount.
- D5: install_update now calls app.restart() after a successful install so the
  new version actually runs (Linux AppImage kept running the old binary; the UI
  hung on "installing").

CI-compile-verified (windows + linux). Web-side wiring (get_tray_dnd query,
updater terminal state) landed on cinny:lotus.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 22:32:37 -04:00
jaredandClaude Opus 4.8 22f8e1566c feat(native): Linux parity + autostart + tray DND (P6-1; no macOS)
Build Lotus Chat Desktop / prepare (push) Successful in 3s
Build Lotus Chat Desktop / build-windows (push) Successful in 23m43s
Build Lotus Chat Desktop / build-linux (push) Successful in 23m57s
Build Lotus Chat Desktop / update-manifest (push) Successful in 4s
Rounds out the native app on Linux (Windows features kept; macOS stays no-op):
- power.rs: no-sleep during calls on Linux via a zbus org.freedesktop.ScreenSaver
  Inhibit/UnInhibit (cookie held in ScreenSaverInhibit managed state).
- set_badge_count: Linux launcher badge via the Unity
  com.canonical.Unity.LauncherEntry.Update D-Bus signal (best-effort; app_uri
  = cinny.desktop per Tauri's mainBinaryName naming).
- tauri-plugin-autostart registered (+ autostart:allow-enable/disable/is-enabled
  capabilities); web toggles it from Settings.
- Tray "Do Not Disturb" CheckMenuItem → emits lotus-dnd-changed to the web,
  which ORs it into the notification quiet-gate.

zbus 5 (Linux target dep; blocking-api default). CI-compile-verified
(windows+linux); reviewer confirmed no build-breakers. Runtime to check on
Linux: DND toggle polarity, badge .desktop id.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 15:18:28 -04:00
jaredandClaude Opus 4.8 1c05ef6a7a fix(config): drop the __csp_notes field — Tauri config schema is strict
Build Lotus Chat Desktop / prepare (push) Successful in 5s
Build Lotus Chat Desktop / build-linux (push) Successful in 23m28s
Build Lotus Chat Desktop / build-windows (push) Successful in 23m28s
Build Lotus Chat Desktop / update-manifest (push) Successful in 8s
`app.security.__csp_notes` failed `tauri.conf.json` schema validation
("Additional properties are not allowed") on BOTH platforms before any
compile. JSON can't hold comments and Tauri forbids extra keys, so the
rationale lives here instead:

CSP rationale (audit 2026-07): tightened from the fully-open policy.
- 'unsafe-eval' MUST stay: the native→web bridge (forward_deeplink /
  emit_to_web) uses window.eval, governed by page CSP; also covers crypto wasm.
- The sha256 hash allowlists the single inline `window.global ||= window;`
  shim in cinny's index.html (~line 96). If that snippet or its indentation
  changes, recompute the hash or the shim is silently blocked.
- connect-src / img-src / media-src keep http: (plain-http homeservers).
- Review-added: Google Fonts (VT323) + OpenStreetMap iframe (m.location).
- style-src keeps 'unsafe-inline' for React style attributes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 09:37:31 -04:00
jaredandClaude Opus 4.8 87950f623b fix(native): jump list IObjectArray/IObjectCollection are in Shell::Common
Build Lotus Chat Desktop / prepare (push) Successful in 39s
Build Lotus Chat Desktop / build-windows (push) Failing after 11m31s
Build Lotus Chat Desktop / build-linux (push) Failing after 13m4s
Build Lotus Chat Desktop / update-manifest (push) Has been skipped
Repairs the CI Windows compile (first build to reach the Rust after the web/
case-collision failures cleared): these two COM interfaces live in
windows::Win32::UI::Shell::Common (feature Win32_UI_Shell_Common), not
System::Com nor Shell. Added the feature; corrected the import.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 08:49:07 -04:00
jaredandClaude Opus 4.8 706b02545d fix(security): tighten the webview CSP (was fully open)
script-src drops unsafe-inline/blob/data/http/https (any-origin script exec is
gone); the single inline shim in index.html is hash-pinned; object-src 'none',
base-uri 'self'. Kept deliberately: 'unsafe-eval' (the window.eval native→web
bridge + crypto wasm), broad connect-src (arbitrary homeservers), http: in
img/media (plain-http homeservers), and review-added allowances for Google
Fonts (VT323) and the OpenStreetMap location iframe.

NEEDS RUNTIME SMOKE ON WINDOWS before release (CI can't catch CSP breakage):
boot, avatars/media, VT323 renders, location map embeds, calls connect, deep
links navigate.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 08:49:07 -04:00
jaredandClaude Opus 4.8 f883781c1f fix(security+audit): strip latent RCE grants, opener allowlist, GDI leaks, CI hardening
From the deep-audit wave (reviewer-verified: capability identifiers valid, no
removed-crate references, GDI free ordering correct):

- Removed 8 never-registered plugins (clipboard-manager, fs, shell, http,
  process, os, dialog, global-shortcut) from Cargo.toml AND their capability
  grants (shell:allow-execute, unscoped fs writes, http:default, …) — verified
  the web never invokes any of them. A latent RCE-class surface is gone.
- on_new_window: only http/https/mailto reach the OS opener (file:///custom
  schemes previously bypassed the opener capability scope entirely).
- set_badge_count: freed hdc + hdc_screen on all three GDI error paths
  (leaked per badge update in a long-running tray app).
- 8s reveal failsafe gated by an AtomicBool: no longer re-shows a window the
  user closed to tray; page-load reveal now fires once only (logout reloads
  don't re-surface a tray-hidden window); recovery for a missed page-load
  event preserved.
- toast.rs: store pruned on Activated too + capped at 20 (was unbounded).
- Startup no longer panics when the bundled icon is missing (tray skipped
  gracefully); msSmartScreenProtection no longer disabled (throttling
  disables kept); rust-version corrected to 1.77.2.
- release.yml update-manifest: fails on empty signatures (was: could publish
  a manifest that traps Windows users in a failed-update loop); partial-
  failure window documented. Deleted the stale upstream tauri.yml workflow.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 08:49:07 -04:00
jaredandClaude Opus 4.8 64569f4736 fix(native): windows 0.61 API paths — repair the CI Windows compile
Build Lotus Chat Desktop / prepare (push) Successful in 5s
Build Lotus Chat Desktop / build-windows (push) Failing after 18m50s
Build Lotus Chat Desktop / build-linux (push) Successful in 23m40s
Build Lotus Chat Desktop / update-manifest (push) Has been skipped
Four unresolved-import/type errors from the release build (first real compile):
- toast.rs: generic IMap moved to the windows-collections crate; read the reply
  from the ValueSet returned by UserInput() directly (HasKey/Lookup are exposed
  on the class).
- jumplist.rs: PROPVARIANT lives in Win32::System::Com::StructuredStorage (not
  windows::core); IObjectArray/IObjectCollection in Win32::System::Com (not
  UI::Shell); PKEY_Title in Win32::Storage::EnhancedStorage (feature added);
  build the title PROPVARIANT via From<&str> (VT_LPWSTR).
- smtc.rs: event registrations return a plain i64 token in windows 0.61 (the
  EventRegistrationToken newtype is gone).
- thumbbar.rs: HICON was imported inside the fn body but used in its signature —
  fully qualify the return type.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 21:18:25 -04:00
jaredandClaude Opus 4.8 e8fba393f0 fix(chrome): P5-47 — Mica vs frameless conflict broke custom window chrome
Root cause: lib.rs applies a Mica backdrop to the main window at startup;
set_custom_chrome then stripped the frame with set_decorations(false), and
Mica + frameless is a broken combination on Windows (DWM backdrop glitches
the whole surface).

- set_custom_chrome: clear_mica() before undecorating, re-apply_mica() when
  restoring the native frame; set_shadow(true) so the frameless window keeps
  its drop shadow + resize borders.
- window-state plugin: exclude StateFlags::DECORATIONS — the chrome toggle
  owns the decorated flag; restoring a saved decorated=false at startup would
  recreate the Mica-on-frameless glitch before the web side loads.

Pairs with the web-side TitleBar drag fix (explicit window_start_drag on
mousedown instead of data-tauri-drag-region) in the cinny repo.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 16:42:17 -04:00
jaredandClaude Opus 4.8 e9132b4489 feat(native): P5-42 keep webview unthrottled in tray (instant background sync)
Build Lotus Chat Desktop / prepare (push) Successful in 3s
Build Lotus Chat Desktop / build-linux (push) Successful in 22m17s
Build Lotus Chat Desktop / build-windows (push) Failing after 17m9s
Build Lotus Chat Desktop / update-manifest (push) Has been skipped
Add WebView2 additional_browser_args to disable Chromium background throttling
(--disable-background-timer-throttling / -renderer-backgrounding /
-backgrounding-occluded-windows) so the existing JS Matrix /sync loop and
notifications keep running full-speed when the app is closed to the tray, instead
of standing up a second headless Rust sync client. Tauri's default WebView2 args
are preserved (setting this overrides them). Windows/WebView2 only; does not block
system sleep (that's P5-46, calls-only). CI Windows compile pending.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 11:04:24 -04:00
jaredandClaude Opus 4.8 a923650d02 feat(native): Tier B — WinRT rich toasts (P5-41/35) + Focus Assist sync (P5-56)
- toast.rs: Windows.UI.Notifications rich toast (reply input + Send action);
  in-process Activated event → emit lotus-notification-activate {path} (click) /
  lotus-notification-reply {roomId,text}. Falls back to tauri-plugin-notification
  (WinRT error / non-Windows). The NOTIFICATION_BRIDGE now routes notifications
  carrying a roomId (tag) to show_rich_toast. Features: UI_Notifications,
  Data_Xml_Dom, Foundation_Collections.
- focus_assist.rs: SHQueryUserNotificationState poll thread → emit
  focus-assist-changed {active} on QUNS_QUIET_TIME/PRESENTATION/D3D_FULLSCREEN/BUSY.
  No new Cargo features.

CI Windows compile pending (no local Rust toolchain). Runtime caveat: WinRT toasts
need a Start-menu shortcut + matching AppUserModelID (org.lotusguild.lotus-chat);
without it CreateToastNotifier errors and the code falls back to the plugin.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 11:04:24 -04:00
jaredandClaude Opus 4.8 73d15b13d2 feat(native): Tier A desktop features (P5-46/36/44/43/49) + window chrome (P5-47)
Adds a `native/` module system (each feature = its own module exposing
`#[tauri::command]`s + optional `setup`; `emit_to_web` pushes DOM CustomEvents to
the web like `forward_deeplink`). Wired into generate_handler! + native::setup;
windows-crate feature union added to Cargo.toml.

- power.rs (P5-46): SetThreadExecutionState held on the main thread while a call
  is active; released on end. Cross-platform (no-op off Windows).
- jumplist.rs (P5-36): ICustomDestinationList "Recent Rooms" of IShellLink tasks
  launching the exe with a matrix: arg (existing deep-link handler opens the room).
- thumbbar.rs (P5-44): ITaskbarList3 ThumbBar Mute/Deafen/End (GDI HICONs) + a
  window subclass catching THBN_CLICKED → emit thumbbar-action.
- smtc.rs (P5-43): WinRT SystemMediaTransportControls via GetForWindow; ButtonPressed
  → smtc-action; call-state command. (Experimental for a non-media app.)
- network.rs (P5-49): INetworkListManager poll thread → emit network-changed.
- chrome.rs (P5-47): cross-platform window-control commands + set_custom_chrome
  (set_decorations) for the opt-in TDS titlebar.

NOT compile-verified locally (no Rust/Windows toolchain on the dev box) — this is
for the CI Windows compile pass (GitHub test.yml / Gitea windows runner). Expect a
possible fixup round (windows-crate feature/namespace paths, e.g. subclass APIs).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 11:04:24 -04:00
jaredandClaude Opus 4.8 324a27577c fix(notify): make TauriNotification.permission assignable (no-op setter)
Build Lotus Chat Desktop / prepare (push) Successful in 4s
Build Lotus Chat Desktop / build-linux (push) Successful in 28m55s
Build Lotus Chat Desktop / build-windows (push) Successful in 40m21s
Build Lotus Chat Desktop / update-manifest (push) Successful in 4s
The injected notification bridge defined `permission` as a getter-only property.
When the notification plugin / a polyfill assigned `Notification.permission`, it
threw "Cannot set property permission of function TauriNotification ... which has
only a getter" at page load. Add a no-op setter so it still reads 'granted' but
assignment can't crash.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 22:35:21 -04:00
jaredandClaude Sonnet 4.6 5cc84991f2 fix(badge): zero-init DIB bits buffer to eliminate black square
Build Lotus Chat Desktop / prepare (push) Successful in 3s
Build Lotus Chat Desktop / update-manifest (push) Has been cancelled
Build Lotus Chat Desktop / build-windows (push) Has been cancelled
Build Lotus Chat Desktop / build-linux (push) Has been cancelled
CreateDIBSection does not guarantee zeroed memory. Uninitialized bytes
with non-zero RGB but zero alpha were getting alpha=255 set by the
existing pixel loop, causing a black square around the badge circle.
Zeroing with write_bytes before GDI drawing ensures only explicitly
painted pixels are opaque.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 20:35:31 -04:00