Another key master referenced from Kotlin but kept only in the generated Compose
XML, so regeneration dropped it. Verified exhaustively this time: every
Res.string.* reference in shared/src/commonMain/kotlin now resolves against the
regenerated values/strings.xml, so no further keys are missing.
Master referenced storage_clear_transfer_cache(_description) and
storage_transfer_cache_cleared from Kotlin but never added them to strings.json —
they lived only in the committed Compose XML. Regenerating l10n from the merged
strings.json dropped them, breaking the shared-kmp build. Add them (kmp target,
all 9 languages, text carried over from master) so generation restores them.
Brings in custom relays, relay connection policies, storage cache clearing, and
receiver-failure reporting. Apple-side conflict resolutions:
- CoreRepository: keep CoreDispatcher, adopt master's relay factory + network
transition guard, drop the now-unused serial queue.
- TransferDetailsView: keep the toolbar-share layout; adopt master's
invitationPresentation-based QR panel and the new .failed receiver case (typed).
- SettingsModel/SettingsScreen: typed L10n titleKey with master's .network case;
relay controls and the Free up space / storage redesign coexist.
- Add the missing transfer_receiver_failed localization key.
- Regenerate l10n from the merged strings.json; keep the Apple catalog untracked.
- Drop the notificationsEnabled test assertion (notifications preference was
intentionally removed on this branch).
The core initializes asynchronously at launch, so for a moment the transfer lists
look empty and the app feels stalled. Show a full-window overlay (centered spinner
+ "Starting…") as the top layer of the root stack while coreState.isInitialized is
false; it fades out once the core is ready.
Redesign the Storage screen for clarity: an "On this device" usage header with a
manual Refresh control, symbol-led action buttons, and a caption under each action
spelling out exactly what it does (Free up space = temp + trash, non-destructive;
Delete all transfers = clears history + cached share content, keeps received
files).
Fix the summary sticking on "Calculating…": it loaded only on .onAppear and bailed
when opened before the core finished its async launch, leaving the loading branch
showing with nothing running (only a manual refresh recovered it). loadStorageUsage
now waits for the core to become ready before reading usage, distinguishes a real
failure (retry) from loading, loads via .task, and can be refreshed on demand. Use
plain button styling with explicit tints so pressing an action no longer flips the
label to the white selection highlight.
Delete all transfers only clears core records, and the blob-store cache is
reclaimed by the core's own timer. Neither touches the app's temporary directory
(leftover picker/staging copies — hundreds of MB on macOS) or the stray .Trash
folders that accumulate in app-owned directories and can't be removed via
Files/Finder. Add a non-destructive Free up space button that empties the temp
directory and removes .Trash folders under the core data dir (and, on iOS, the
fixed Documents receive folder), reporting the bytes reclaimed. Guarded against
running while a transfer is in flight; never touches received files, the core
database, or user-chosen macOS receive folders.
Adds background notifications for the "the thing you were waiting for is
done" moments, alongside the existing incoming-approval-request one:
- a receive finished downloading (receive -> done)
- a receive failed / was interrupted (receive -> failed)
- a share you own failed (send -> failed)
- a receiver finished downloading your share (receiver status completed)
A new TransferNotificationCoordinator observes core state + signals and
publishes these; the decision of which moments notify is a pure function
(plannedTransferNotifications / plannedReceiverNotifications), unit-tested
independently. The first state snapshot only primes existing history as seen
so launch doesn't spam.
Notification permission is now the single source of truth. The in-app
notifications toggle and its decoupled UserDefaults preference are gone;
the Settings section shows an "Allow notifications" button that requests the
OS permission (or deep-links to Settings once decided), and notifications
gate purely on `permission == .granted`.
macOS delivery fixes:
- add a UNUserNotificationCenterDelegate so banners present even while the
app is active (the app window is usually open on macOS)
- present-when-active on macOS, suppress-when-foregrounded on iOS
- reserve the notification id before awaiting publish: the CombineLatest
fired several times and re-added the same identifier, which macOS
coalesces into a silent update with no banner
- LocalNotificationService seeds its permission at init so gating can't
race a not-yet-refreshed .notDetermined
Eight localized title/body strings added (apple-only); the shared
notifications_description copy is generalized from "receive requests" to
"transfer activity".
Add strict custom Iroh relay profiles with safe restart and rollback across the Rust core, Compose apps, and Apple apps. Preserve multi-relay invitations and fail closed on configuration or recovery mismatches.
Replace "раздача"/"раздаваться" (literally "seeding") with neutral
"общий доступ"/"отправка" phrasing across the Russian strings, to avoid
BitTorrent connotations for App Store review.
Translate all 253 user-facing strings to Russian (professional UI register;
count strings use number-neutral "label: {count}" form). transfer_file_count
uses full CLDR plural categories (one/few/many/other). Generates
values-ru/strings.xml for KMP, ru localizations in the Apple catalog, and adds
ru to CFBundleLocalizations. Completes the initial 8-language set.
Translate all 253 user-facing strings to Dutch (formal "u"), including the
transfer_file_count plural. Generates values-nl/strings.xml for KMP, nl
localizations in the Apple catalog, and adds nl to CFBundleLocalizations.
Translate all 253 user-facing strings to Polish (standard professional UI
register; gender-neutral phrasing; count strings use number-neutral "label:
{count}" form). transfer_file_count uses full CLDR plural categories
(one/few/many/other). Generates values-pl/strings.xml for KMP, pl localizations
in the Apple catalog, and adds pl to CFBundleLocalizations.
Translate all 253 user-facing strings to European Portuguese (pt-PT, formal;
EP vocabulary — ficheiro, guardar, Definições, partilhar). Generates
values-pt/strings.xml for KMP, pt localizations in the Apple catalog, and adds
pt to CFBundleLocalizations.
Translate all 253 user-facing strings to German (formal "Sie"; standard iOS
term conventions). Generates values-de/strings.xml for KMP, de localizations in
the Apple catalog, and adds de to CFBundleLocalizations.
Translate all 253 user-facing strings to Italian (formal "Lei"; standard iOS
button terms follow Apple conventions). Generates values-it/strings.xml for
KMP, it localizations in the Apple catalog, and adds it to CFBundleLocalizations.
Translate all 253 user-facing strings to Spanish (formal "usted"), including
the transfer_file_count plural. Generates values-es/strings.xml for KMP, es
localizations in the Apple catalog, and adds es to CFBundleLocalizations.
Translate all 253 user-facing strings to French (formal register), including
the transfer_file_count plural. Generates values-fr/strings.xml for KMP and
fr localizations in the Apple catalog (marked needs_review).
Most strings were imported with a platform-specific `targets` (usually
apple-only) just because that's where they happen to be used today. Drop the
restriction so they default to all targets and are available to KMP too; only
the four literal `%@…` format-composition keys stay apple-only.
Also fix the placeholder parser to tolerate C length modifiers (`%lld`), and
give progress_sending_to_count a proper int arg so it emits `%1$d` on both
platforms instead of a literal `%lld`.
Add localization/ — one strings.json is the source of truth for every
user-facing string, and a Bun CLI generates the platform files:
loc migrate rebuild strings.json from existing platform files (one-time)
loc validate structural checks (plural `other`, arg refs, coverage)
loc generate emit .xcstrings (Apple) + per-language strings.xml (KMP)
Canonical `{name}` placeholders are converted to each platform's positional
printf tokens using declared arg types. Plurals use CLDR categories and emit
native forms: xcstrings plural variations and Compose <plurals> blocks.
Migration folds the KMP `transfer_file_count_one`/`_other` pair into a single
plural key, so `transferFileCountResource` now returns the plural resource and
callers resolve it with pluralStringResource.