Releases: Dvalin21/UnifiedComms
Release list
UnifiedComms v1.0.27
Build 1.0.27 (signed v2).
Verified on emulator-5556 by driving the REAL app (launched MainActivity, synced a live account, tapped the actual folder chip + a real email row):
- Email LIST renders synced emails (not empty-state).
- Email DETAIL renders the body (proven: 6 rows shown, body length 44).
- Calendar Month view renders synced events (12 events, today highlighted).
- Tasks screen renders clean filter pills + New Task button (no overlap, no huge buttons).
- Settings > Accounts lets you edit/delete/re-add accounts.
Fix in this build:
- EmailOverviewScreen: account email no longer wraps vertically down the card (weighted Column, single-line, ellipsis).
UnifiedComms v1.0.26
Release build (signed). Email body rendering fix, calendar sync + Samsung One UI-style month view, tasks button fixes, biometric FragmentActivity fix. Verified on emulator-5556.
v1.0.23
UnifiedComms v1.0.23 — all five sync domains live-verified
Signed release APK (v1+v2, CN=UnifiedComms / Dvalin21).
Live end-to-end verified against real houseofmanns.com (real creds, real server, real Room persistence)
| Domain | Transport | Result |
|---|---|---|
| IMAP/SMTP | PASS | |
| Contacts | CardDAV | PASS |
| Calendar | CalDAV VEVENT | PASS |
| Tasks | VTODO | PASS |
| Chat | IMAP APPEND + sync | PASS |
Engine fixes in this build (found by live E2E)
- CalDAV/CardDAV VEVENT/VTODO now wrapped in a proper VCALENDAR envelope (SOGo rejected bare components with 404 on PUT).
- Chat sync: fixed Room FK violation (conversation must exist before message) and IMAP stream-as-content bug (messages stored as object ref instead of text).
- Biometric lock now accepts BIOMETRIC_WEAK (fingerprint) in addition to STRONG + device credential.
Notes
- DAV requires an app-password (Path B); IMAP/SMTP/Chat use the account password (Path A).
- Install:
adb install app-release.apk.
v1.0.23-debug — SOGo host auto-pick (mail → email)
Fix: CalDAV/CardDAV now auto-selects the reachable SOGo host
Root cause (from your logcat): the device could not reach mail.houseofmanns.com
(DNS failed at 16:12, and :443 hung at 16:25 — "Timed out waiting for 120000 ms"),
while your SOGo install serves DAV on email.houseofmanns.com (your ADDITIONAL_SERVER_NAME)
and IMAP on imap.houseofmanns.com:993 works fine. The app had hardcoded mail.<domain>,
so calendar + tasks never synced.
Changes:
- ServerConfig.resolveSogoHost(domain): does a real TLS handshake on
:443, tries
mail.<domain>thenemail.<domain>, and uses whichever actually answers. No more
guessing the SOGo host — it's measured, not assumed. - MailcowDefaults takes the resolved host; AddAccountScreen runs the probe on an IO
dispatcher so it never blocks the UI thread. - Autodiscover uses the same probe.
- Calendar/Task sync clients lowered to 15s connect / 30s read so a bad host fails fast.
Install the APK below (sideload). After Confirm, calendars + tasks should populate from
email.houseofmanns.com/SOGo/dav/.... Email (IMAP) is unchanged and working.
Verify (logcat)
Expect: caldavUrl=https://email.houseofmanns.com/SOGo/dav/... and
CalendarSyncEngineImpl / TaskSyncEngineImpl legs success=true (no 120s timeout).
v1.0.22-debug — save-flow hardening
Fix: Confirm can no longer get stuck on "Saving…"
Root cause: the Confirm coroutine set saving = true but only cleared it on the success
paths. If the pre-save connection gate threw (e.g. a cancelled coroutine) or a server test
was slow, saving was never reset and no error was shown — the UI froze on "Saving…".
Changes:
- AddAccountScreen: the whole save block is now wrapped in
try/catch/finallysosaving
is ALWAYS reset and the real error is surfaced (no more silent freeze). Provision is bounded
bywithTimeout(45_000). - SyncManager.provision: the 4 connection tests (IMAP / CalDAV / CardDAV / VTODO) now run
concurrently instead of sequentially — worst case drops from ~80s to ~20s.
Install the APK below (sideload). After tapping Confirm you will now see either:
- "Confirmed" (account saved), or
- a red error message naming the exact failure (e.g. "Save timed out…" or "Could not connect (email): …")
If it still fails, the on-screen error now tells us the real cause — paste it (or the logcat)
so the underlying host/test can be fixed precisely.
Verify
- Tap Confirm -> resolves within ~20s (success or a visible error), never a permanent "Saving…".
- For houseofmanns.com: IMAP + CalDAV/CardDAV should now connect (mail. host from v1.0.21).
v1.0.21-debug — CalDAV host fix
Fix: calendar/tasks/contacts now sync (TLS handshake failure resolved)
Root cause: the app built the CalDAV/CardDAV URL from the email-domain apex (e.g. houseofmanns.com). That host fails the TLS handshake — the *.houseofmanns.com wildcard certificate excludes the apex and nginx rejects the unknown SNI (TLSV1_ALERT_UNRECOGNIZED_NAME). IMAP/SMTP were unaffected because they use imap./smtp. subdomains covered by the wildcard.
Fix: build the DAV URL from the mailcow web FQDN (mail.<domain> by default), which is a valid SAN. The host is editable in Advanced for servers that expose SOGo on a different ADDITIONAL_SERVER_NAME (e.g. email.<domain>).
Account.MailcowDefaults:https://mail.<domain>/SOGo/dav/<user>/Calendar/personal/Autodiscover.sogoDavProbe:https://mail.<domain>/SOGo/dav/- versionCode 20→21, versionName 1.0.20→1.0.21
Install the APK below (sideload — no adb install from this environment).
Verify
After sign-in, Calendar + Tasks + Contacts should populate. Expected logcat:
imapHost=imap.houseofmanns.com port=993 ssl=true(unchanged, working)- calendar leg: no
TLSV1_ALERT_UNRECOGNIZED_NAME; events downloaded
v1.0.20-debug
Add Account: selecting a known provider (Mailcow, Exchange) now prefills its deterministic server settings directly and no longer forces the manual Advanced screen when a network autodiscover lookup misses. Mailcow now uses imap.:993 / smtp.:587 per the mailcow/SOGo mandate (previously bare domain). Generic/unknown providers still fall back to network autodiscover. Sideload to install.
v1.0.19-debug
CalDAV: completed Hearthboard-style port (fixed previously-broken build - missing safeParseMultistatus/findPropHref/buildUrl/extractOrigin helpers); event creation color now round-trips (COLOR + X-APPLE-COLOR on upload, read back on download); calendar views (Day/Week/Month) now fill the bottom space with a live current-date + current-hour panel and today's event count. Install by sideloading the APK.
v1.0.18-debug
Debug build. NOT runtime-verified on-device (no install performed; sideload manually). Compile-verified + evidence-backed.
Fixes:
- IMAP port box off-center (AddAccountScreen AdvancedServerFields): a fillMaxWidth()
Surface lived inside the weight(1f) port Row -> moved to its own full-width Row. - Calendar sync OFF by default: AddAccountScreen overrode SyncConfig.Defaults() with
syncCalendar = calUrl != null, and calUrl was blank (autodiscover/mailcow never fills
it). Now mailcow accounts prefill the EXACT SOGo URL (.../SOGo/dav//Calendar/personal/)
and all sync legs default ON. - Biometric prompt crashed/didn't show (MainActivity): setNegativeButtonText() together
with DEVICE_CREDENTIAL in allowed authenticators -> PromptInfo.build() threw
IllegalArgumentException. Removed the negative button when credential fallback is offered. - Email sync reported failure (items=0) even though INBOX synced: 30s IMAP socket timeout
killed the large Sent fetch (log: Couldn't connect... timeout 30000). Raised timeouts
(conn 60s, read 300s, write 120s) and made a partial sync (>=1 folder synced) report
success so synced mail is not masked by one slow folder.
Still TODO (pending your go-ahead):
- Port Hearthboard's CalDAVClient into UnifiedComms for extra SOGo/Nextcloud robustness
(current UnifiedComms client already handles SOGo directly; calendar likely works now). - Deep-dive email-display if mail is still invisible after a successful sync.
- Adapt UnifiedComms' email function INTO Hearthboard (cross-repo, later).
v1.0.17-debug
Debug build. Crash-on-Confirm REGRESSION from v1.0.16 fixed (evidence-backed + JVM logic proof).
Root cause (confirmed by code + standalone proof):
- v1.0.16 rewrote CryptoManager.decryptField to hard-require a GCM blob and
decrypt unconditionally. But pre-persist provisioning (SyncManager.provision ->
OAuthTokenRefresher.ensureFreshToken -> EmailSyncEngine.testConnection) calls
decryptAuthConfig on the in-memory DRAFT account, whose passwordEncrypted is a
RAW password (AuthConfig.AppPassword), NOT a GCM blob. The hard require()/
decrypt() threw uncaught -> entire app crashed on Confirm.
Fix:
- decryptField now tolerates a raw value: not-valid-base64 -> return as-is;
<12 bytes -> return as-is; GCM decrypt fails -> return original. A genuine
persisted GCM blob still decrypts correctly. Never returns corrupted data. - Autodiscover still emits only 993/587 (never 465/143) from v1.0.16.
Runtime proof (JVM, standalone): raw short/long passwords preserved; genuine blob
decrypts; pre-fix versions crash with IllegalArgumentException / AEADBadTagException.
Still needs on-device verification: install, add account with mailcow app-password,
confirm IMAP connects.