0.2.29
RustBox CI / rustbox (push) Canceled after 0s

This commit is contained in:
Mateusz Gruszczyński committed 2026-11-07 10:27:26 +01:00
1 parent 065fc87306
commit 1b12899ff6
8 files changed
+38 -13

No files matched your search

+4
View File
@@ -2,6 +2,10 @@
What changed in each RustBox release, written for the people who use and run it. Technical details are in the [documentation](docs/).
## 0.2.29
- An open message thread now updates automatically when a new message for that thread arrives via realtime events; reopening the thread is no longer required.
## 0.2.28
- Replying to a message you sent no longer addresses the reply back to yourself; RustBox chooses the other thread participant(s), including when aliases/identities are used.
Generated
+1 -1
View File
@@ -3506,7 +3506,7 @@ dependencies = [
[[package]]
name = "rustbox"
version = "0.2.28"
version = "0.2.29"
dependencies = [
"aes-gcm",
"async-imap",
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "rustbox"
version = "0.2.28"
version = "0.2.29"
edition = "2024"
rust-version = "1.99.1"
license = "AGPL-3.0-only"
+1 -1
View File
@@ -1,4 +1,4 @@
# RustBox 0.2.28
# RustBox 0.2.29
**Fast, self-hosted webmail written in Rust.** RustBox connects to any IMAP/SMTP server and ships as one executable with the whole interface built in, so there is no Node.js, PHP or separate frontend to deploy.
+5 -4
View File
@@ -1,6 +1,7 @@
RustBox 0.2.28 release manifest
RustBox 0.2.29 release manifest
0.2.28 release changes:
0.2.29 release changes:
- open message thread refreshes automatically after realtime NewMessages events, without requiring the user to reopen it
- replies to own sent messages target the other participant(s), with account aliases/identities treated as own addresses
- mailbox toolbar toggles between grouped threads and individual messages using the persisted mailbox `thread_mode` preference; thread rows expand/collapse and use Message-ID/In-Reply-To/References metadata
- legacy Polish text repair covers common UTF-8/Windows-1252 and ISO-8859-2/Western-Latin mojibake in headers, bodies and cached summaries/details; exact ISO-8859-2 folded-subject coverage added
@@ -131,14 +132,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.28 configuration
- README.md documents 0.2.29 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.28
- Cargo.toml version = 0.2.29
- 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
+5 -4
View File
@@ -1,6 +1,7 @@
RustBox 0.2.28 - final source validation
RustBox 0.2.29 - final source validation
0.2.28 scope:
0.2.29 scope:
- realtime refresh of the currently open message thread when NewMessages arrives
- correct reply recipients for own sent messages in threads, Roundcube-style mailbox thread/flat list toggle (compact icon-button matching Select messages, with an icon reflecting the active mode), and stronger Polish legacy-encoding/mojibake repair, plus the 0.2.27 mail-list and appearance baseline
0.2.25 scope:
@@ -67,7 +68,7 @@ RustBox 0.2.28 - 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-V052 are consolidated into compatibility baseline V052; V053 adds `skin_depth` and `skin_gradients`; V054 adds the theme schedule and account colour; V055 is next
- version metadata identifies 0.2.28
- version metadata identifies 0.2.29
Completed in this environment:
- offline release validator: scripts/validate-release-static.py (458/458 checks passed)
@@ -78,7 +79,7 @@ Completed in this environment:
- all JSON files parse successfully
- Python helper scripts compile successfully
- shell scripts pass `bash -n`
- release metadata consistently identifies 0.2.28
- release metadata consistently identifies 0.2.29
- V052 baseline consolidation plus the V053 skin-depth migration are validated offline
- 0.2.25 filter UI (apply now, run now, always move from sender), context submenus and preset editing exercised in Playwright against a mocked API; the 0.2.24 styles rendered at standard and immersive depth with gradients on and off; earlier: all 37 interface styles rendered in light and dark at the immersive depth against a mocked API (Playwright), with no page errors
+6 -2
View File
@@ -1,7 +1,11 @@
# RustBox 0.2.28 - implementation status
# RustBox 0.2.29 - 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.28` 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.29` 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.29 realtime open-thread refresh
- When realtime reports `NewMessages`, the currently open message detail is re-fetched and its thread is re-rendered if the user is still viewing the same message.
## 0.2.28 thread replies and legacy Polish mail decoding
+15
View File
@@ -662,6 +662,19 @@ async function resyncRealtimeState() {
return state.realtimeSyncPromise;
}
async function refreshOpenThread() {
const current = state.currentDetail;
if (!current) return;
const folder = current.folder;
const uid = current.uid;
try {
const fresh = await request(`/messages/${encodeURIComponent(folder)}/${uid}`, { method: "GET" });
if (!state.currentDetail || state.currentDetail.folder !== folder || Number(state.currentDetail.uid) !== Number(uid)) return;
state.currentDetail.thread = fresh.thread || [];
renderThread(state.currentDetail);
} catch (_) { }
}
function scheduleRealtimeRefresh(event, accountId) {
if (accountId !== state.accountId) return;
state.realtimeRefreshEvents.push(event);
@@ -669,6 +682,7 @@ function scheduleRealtimeRefresh(event, accountId) {
state.realtimeRefreshTimer = setTimeout(async () => {
const events = state.realtimeRefreshEvents.splice(0);
const folderTreeChanged = events.some((item) => item.type === "FolderUpdated");
const hasNewMessages = events.some((item) => item.type === "NewMessages");
const newInCurrent = events.some((item) => item.type === "NewMessages" && item.data?.folder === state.folder);
const structuralFlagsInCurrent = events.some((item) => item.type === "FlagsChanged" && item.data?.folder === state.folder && !(item.data?.changes || []).length);
const tasks = [];
@@ -678,6 +692,7 @@ function scheduleRealtimeRefresh(event, accountId) {
else tasks.push(loadMessages(true, { background: true }));
}
if (tasks.length) await Promise.all(tasks);
if (hasNewMessages && state.currentDetail) await refreshOpenThread();
}, 80);
}