v0.2.18
RustBox CI / rustbox (push) Canceled after 0s

This commit is contained in:
Mateusz Gruszczyński committed 2026-11-03 13:02:34 +01:00
1 parent 1309358b68
commit 9003a50eb4
11 files changed
+83 -17

No files matched your search

+6
View File
@@ -1,5 +1,11 @@
# RustBox changelog
### 0.2.19
- Improved vertical space management in the HTML message reader: the sandboxed message iframe now expands to the actual space remaining below the reader toolbar, message header and auxiliary bars instead of stopping at a fixed `68vh`.
- Recalculate the HTML message viewport when the reader, header, attachments, security bars, window size or fullscreen state changes, avoiding an unnecessary short inner scrollbar while preserving the existing iframe sandbox.
- Bumped the application/source release to 0.2.19.
### 0.2.18
- Fixed new-message sender selection so the composer prefers the configured default identity, then the identity matching the active account address, then the first available identity; the visible From field now shows the active account address instead of an ambiguous `Account default` label when no identity is selected.
Generated
+1 -1
View File
@@ -3506,7 +3506,7 @@ dependencies = [
[[package]]
name = "rustbox"
version = "0.2.18"
version = "0.2.19"
dependencies = [
"aes-gcm",
"async-imap",
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "rustbox"
version = "0.2.18"
version = "0.2.19"
edition = "2024"
rust-version = "1.99.1"
default-run = "rustbox"
+1 -1
View File
@@ -1,6 +1,6 @@
# RustBox attribution / notice
RustBox 0.2.18 is derived from the Oxi webmail project:
RustBox 0.2.19 is derived from the Oxi webmail project:
- Upstream: `c0h1b4/oxi`
- Base snapshot: `7f1507c486b78cf33e54beb701dd460d3bd2bd5d`
+1 -1
View File
@@ -1,4 +1,4 @@
# RustBox 0.2.18
# RustBox 0.2.19
RustBox is a webmail derived from `c0h1b4/oxi`. The consumed Oxi revision is recorded in `UPSTREAM_BASE`.
+5 -4
View File
@@ -1,6 +1,7 @@
RustBox 0.2.18 release manifest
RustBox 0.2.19 release manifest
0.2.18 release changes and retained feature set:
0.2.19 release changes and retained feature set:
- expands sandboxed HTML message previews to the real remaining reader height and keeps that height synchronized across layout/fullscreen changes
- adds equal-height text/HTML signature fields and a dedicated raw-HTML + visual signature editor with image insertion
- keeps synchronization activity visible during page/progressive/all mailbox loads and individual message retrieval
- adds Shift-click contiguous message selection and direct first/last pagination controls
@@ -70,14 +71,14 @@ Docker examples:
Operations/docs:
- standalone `scripts/migrate_roundcube.py` imports Roundcube contacts/identities using RustBox config.toml and supports SQLite/MySQL/PostgreSQL targets
- README.md documents 0.2.18 configuration
- README.md documents 0.2.19 configuration
- docker/README.md documents Compose variants
- docs/STORAGE_SEARCH_OPERATIONS.md documents failure modes, shared-storage requirements and migration behavior
- TODO.md leaves live SILO/MinIO/AWS/Ceph and real multi-node acceptance validation explicitly pending
Build/release metadata:
- `scripts/package-release.sh` runs the full Rust release gate before creating ZIP/SHA256 artifacts
- Cargo.toml version = 0.2.18
- Cargo.toml version = 0.2.19
- rust-toolchain.toml pins Rust 1.99.1
- Cargo.lock is retained for reproducible application builds; the release gate generates it only when missing
- CI and scripts/build-release.sh use the retained Cargo.lock (generating it only if missing), then run locked tests/Clippy/release build
+6 -5
View File
@@ -1,6 +1,7 @@
RustBox 0.2.18 - final source validation
RustBox 0.2.19 - final source validation
0.2.18 scope:
0.2.19 scope:
- HTML message reader iframe height follows the actual remaining reader viewport rather than a fixed 68vh, with resize/fullscreen recalculation
- multi-account sessions expose a top-bar quick switcher, per-browser combined notification selection, per-account notification preferences and the administrator `multi_account_enabled` feature gate
- plain-text and HTML signature controls have aligned heights; raw HTML can be pasted into a modal, previewed/edited visually and extended with inline images
- synchronization spinner covers mailbox pagination, progressive/full-folder loading and message/draft body retrieval
@@ -32,15 +33,15 @@ RustBox 0.2.18 - final source validation
- Composing shows only compact attachment/message size-limit values on one line
- 0.2.9 realtime notification gating, browser shortcut preservation and 300-message defaults remain intact
- V047-V050 are consolidated into compatibility baseline V050; V051 migrates existing tenants with adaptive HTML-mail colors and mailbox loading mode; V052 is next
- version metadata remains at 0.2.18
- version metadata identifies 0.2.19
Completed in this environment:
- offline release validator: scripts/validate-release-static.py (413/413 checks passed)
- offline release validator: scripts/validate-release-static.py (420/420 checks passed)
- browser JavaScript assembled in manifest order passes `node --check`
- all JSON files parse successfully
- Python helper scripts compile successfully
- shell scripts pass `bash -n`
- release metadata consistently identifies 0.2.18
- release metadata consistently identifies 0.2.19
- V050 baseline consolidation plus the V051 adaptive-colors/mailbox-loading migration are validated offline
+4 -3
View File
@@ -1,10 +1,11 @@
# RustBox 0.2.18 - implementation status
# RustBox 0.2.19 - implementation status
- Draft saves are realtime-silent: Drafts folder/list updates continue, but saving a draft does not surface as a new-mail notification.
This file tracks the `0.2.18` source snapshot. Storage/search scope and outstanding acceptance work are tracked in `TODO.md`. A feature is only listed as implemented when working code exists in this source tree; partial items are called out explicitly.
This file tracks the `0.2.19` source snapshot. Storage/search scope and outstanding acceptance work are tracked in `TODO.md`. A feature is only listed as implemented when working code exists in this source tree; partial items are called out explicitly.
## 0.2.18 browser mail UX
## 0.2.19 browser mail UX
- HTML message previews use the full remaining vertical reader area and recompute their iframe height as reader chrome/layout changes.
- Signature management uses equal-height text and HTML fields and includes a raw-HTML modal with a sanitized visual editor and inline image import.
- Mail loading activity is represented by the app-bar spinner for pagination, progressive/full-folder retrieval and individual message/draft loading.
- Shift-click selects a contiguous range in the visible message list, and pagination includes direct first/last page navigation.
+1
View File
@@ -152,6 +152,7 @@ require('suppressRealtimeNotificationsForFolder(notificationDestination)' in mai
require('realtimeNotificationSuppressedMessages: new Map()' in bootstrap_js and 'suppressRealtimeNotificationForMessage' in realtime_js and 'consumeRealtimeMessageNotificationSuppression' in realtime_js and 'suppressIntentionalMoveNotification' in mail_actions_js, "intentional message moves suppress the matching realtime new-mail event by destination UID")
require('finishAuthenticatedStartup({ showLoginToast = false } = {})' in auth_js and 'finishAuthenticatedStartup({ showLoginToast: true })' in auth_js and bindings_js.count('finishAuthenticatedStartup();') >= 1, "login success toast is limited to real login, not refresh/session restoration")
require('<meta charset="utf-8">${csp}' in reader_js, "message preview srcdoc explicitly declares UTF-8")
require('function resizeReaderMessageFrame()' in reader_js and 'new ResizeObserver(scheduleReaderMessageFrameResize)' in reader_js and '--reader-message-frame-height' in mail_css and 'min-height: 68vh' not in mail_css, "HTML message preview uses the full remaining reader height instead of fixed 68vh")
require('function sanitizeMessagePreviewHtml(html)' in bootstrap_js and 'if (!node.hasAttribute("target")) node.setAttribute("target", "_blank");' in bootstrap_js and '!["_self", "_parent", "_top"].includes(target)' in bootstrap_js and 'rel.add("noopener");' in bootstrap_js and 'rel.add("noreferrer");' in bootstrap_js and 'sanitizeMessagePreviewHtml(detail.html)' in reader_js, "message preview links default to safe new-window navigation without overriding explicit targets")
require('sourceDoc.head.querySelectorAll("style")' in bootstrap_js and 'messagePreviewBodyPresentation' in reader_js and 'iframe.style.background = previewTheme.surface;' in reader_js and 'background: var(--reader-bg);' in mail_css, "adaptive HTML-mail preview preserves head CSS/body presentation and never exposes a hard-coded white iframe canvas")
require('attachmentContentUrl(folder, uid, attachment)' in reader_js and 'frame.src = attachmentContentUrl(folder, uid, attachment);' in reader_js and 'URL.createObjectURL(blob)' in reader_js, "PDF preview uses authenticated inline URL while other attachment previews retain blob handling")
+2 -1
View File
@@ -593,7 +593,8 @@
.message-body iframe {
display: block;
width: 100%;
min-height: 68vh;
height: var(--reader-message-frame-height, 260px);
min-height: 260px;
border: 0;
background: var(--reader-bg);
}
+55
View File
@@ -503,6 +503,7 @@ function setReaderFullscreen(enabled, options = {}) {
}
restoreReaderScroll();
}
scheduleReaderMessageFrameResize();
}
function enterReaderFullscreen() {
@@ -1164,10 +1165,62 @@ function adaptMessagePreviewColors(html, detail, body) {
return { html: doc.body.innerHTML, targetTheme, surface: adaptiveEmailRgbCss(messageSurface), text: adaptiveEmailRgbCss(messageText) };
}
let readerMessageFrameObserver = null;
let readerMessageFrameResizeRaf = 0;
let readerMessageFrameWindowResizeBound = false;
function resizeReaderMessageFrame() {
readerMessageFrameResizeRaf = 0;
const reader = $("#reader-content");
const body = $("#message-body");
const iframe = body?.querySelector(":scope > iframe");
if (!reader || !body || !iframe || reader.classList.contains("hidden")) return;
let occupiedHeight = 0;
for (const child of reader.children) {
if (child === body) break;
const style = getComputedStyle(child);
if (style.display === "none" || style.position === "absolute" || style.position === "fixed") continue;
const rect = child.getBoundingClientRect();
occupiedHeight += rect.height;
occupiedHeight += Number.parseFloat(style.marginTop) || 0;
occupiedHeight += Number.parseFloat(style.marginBottom) || 0;
}
const availableHeight = Math.max(260, Math.floor(reader.clientHeight - occupiedHeight));
body.style.setProperty("--reader-message-frame-height", `${availableHeight}px`);
}
function scheduleReaderMessageFrameResize() {
if (readerMessageFrameResizeRaf) cancelAnimationFrame(readerMessageFrameResizeRaf);
readerMessageFrameResizeRaf = requestAnimationFrame(resizeReaderMessageFrame);
}
function observeReaderMessageFrameLayout() {
const reader = $("#reader-content");
const body = $("#message-body");
if (!reader || !body) return;
if (typeof ResizeObserver === "function") {
if (!readerMessageFrameObserver) readerMessageFrameObserver = new ResizeObserver(scheduleReaderMessageFrameResize);
readerMessageFrameObserver.disconnect();
readerMessageFrameObserver.observe(reader);
for (const child of reader.children) {
if (child !== body) readerMessageFrameObserver.observe(child);
}
}
if (!readerMessageFrameWindowResizeBound) {
window.addEventListener("resize", scheduleReaderMessageFrameResize, { passive: true });
readerMessageFrameWindowResizeBound = true;
}
}
function renderMessageBody(detail, forceRemote = false) {
const body = $("#message-body");
const remoteBar = $("#remote-image-bar");
body.replaceChildren();
body.style.removeProperty("--reader-message-frame-height");
remoteBar.classList.add("hidden");
const preferredBody = state.mailPrefs.preferred_body || "auto";
if (preferredBody === "text" || !detail?.html) {
@@ -1208,6 +1261,8 @@ function renderMessageBody(detail, forceRemote = false) {
].filter(Boolean).join(" ");
iframe.srcdoc = `<!doctype html><html><head><meta charset="utf-8">${csp}<meta name="color-scheme" content="${previewTheme.targetTheme}"><style>${previewStyle}</style></head><body${bodyAttributes ? ` ${bodyAttributes}` : ""}>${safeHtml}</body></html>`;
body.append(iframe);
observeReaderMessageFrameLayout();
resizeReaderMessageFrame();
}
async function downloadAttachment(folder, uid, attachment) {