Skip to content

version 1.3 - #310

Merged
Jdreioe merged 216 commits into
stagingfrom
main
Oct 4, 2026
Merged

Jdreioe merged 216 commits into
stagingfrom
main

Conversation

@Jdreioe

@Jdreioe Jdreioe commented Oct 4, 2026

Copy link
Copy Markdown
Owner

No description provided.

Jdreioe and others added 30 commits August 14, 2026 15:07
- Run Compose instrumentation tests in deploy and security workflows
- Configure KVM and API 35 emulator support
- Document CI coverage and manual accessibility verification
#167 Gate Android CI with critical emulator UI tests
- Keep selection, scanning, and emphasis visuals distinct
- Respect zero-duration highlight settings without a forced flash
Fix Linux selection highlight state handling
* Secure Azure Speech endpoint validation and credential requests

- Validate and canonicalize Azure Speech endpoints across platforms
- Reject untrusted endpoints and disable credential-bearing redirects
- Add endpoint and client security coverage

* #180 Stabilize critical Android UI tests

* #180 Target board card semantics in UI test

* #180 Separate board open and edit actions
- Throw typed errors when iOS storage writes fail
- Preserve dictionary loads when cache writes fail
- Add storage and cache failure coverage
Fix iOS file storage failures and dictionary cache handling
Harden Linux bridge trust boundaries
- Add dependency updates, secret scanning, and vulnerability checks
- Expand Android, Linux, iOS, and Worker verification coverage
- Pin CI actions and toolchains for reproducible builds
- Add iOS sequencer coverage and Linux build compatibility fixes
[#188] Gate supported clients and supply-chain checks
Bumps the cargo group in /linuxApp with 6 updates:

| Package | From | To |
| --- | --- | --- |
| [rfd](https://github.com/PolyMeilex/rfd) | `0.15.4` | `0.16.0` |
| [base64](https://github.com/marshallpierce/rust-base64) | `0.22.1` | `0.23.1` |
| [getrandom](https://github.com/rust-random/getrandom) | `0.3.4` | `0.4.3` |
| [libcosmic](https://github.com/pop-os/libcosmic) | ``8a017a1`` | ``1f8d878`` |
| [miniz_oxide](https://github.com/Frommi/miniz_oxide) | `0.8.9` | `0.9.1` |
| [clap](https://github.com/clap-rs/clap) | `4.5.59` | `4.5.60` |


Updates `rfd` from 0.15.4 to 0.16.0
- [Release notes](https://github.com/PolyMeilex/rfd/releases)
- [Changelog](https://github.com/PolyMeilex/rfd/blob/master/CHANGELOG.md)
- [Commits](PolyMeilex/rfd@0.15.4...0.16.0)

Updates `base64` from 0.22.1 to 0.23.1
- [Changelog](https://github.com/marshallpierce/rust-base64/blob/master/RELEASE-NOTES.md)
- [Commits](marshallpierce/rust-base64@v0.22.1...v0.23.1)

Updates `getrandom` from 0.3.4 to 0.4.3
- [Changelog](https://github.com/rust-random/getrandom/blob/master/CHANGELOG.md)
- [Commits](rust-random/getrandom@v0.3.4...v0.4.3)

Updates `libcosmic` from `8a017a1` to `1f8d878`
- [Commits](pop-os/libcosmic@8a017a1...1f8d878)

Updates `miniz_oxide` from 0.8.9 to 0.9.1
- [Changelog](https://github.com/Frommi/miniz_oxide/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Frommi/miniz_oxide/commits)

Updates `clap` from 4.5.59 to 4.5.60
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](clap-rs/clap@clap_complete-v4.5.59...clap_complete-v4.5.60)

---
updated-dependencies:
- dependency-name: rfd
  dependency-version: 0.16.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: cargo
- dependency-name: base64
  dependency-version: 0.23.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: cargo
- dependency-name: getrandom
  dependency-version: 0.4.3
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: cargo
- dependency-name: libcosmic
  dependency-version: 1f8d8786940cc6db59d412153c5a03f69a20375c
  dependency-type: direct:production
  dependency-group: cargo
- dependency-name: miniz_oxide
  dependency-version: 0.9.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: cargo
- dependency-name: clap
  dependency-version: 4.5.60
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps the opensymbols-proxy group in /infra/opensymbols-proxy with 3 updates: [@cloudflare/workers-types](https://github.com/cloudflare/workerd), [typescript](https://github.com/microsoft/TypeScript) and [wrangler](https://github.com/cloudflare/workers-sdk/tree/HEAD/packages/wrangler).


Updates `@cloudflare/workers-types` from 5.20260809.1 to 5.20260813.1
- [Release notes](https://github.com/cloudflare/workerd/releases)
- [Changelog](https://github.com/cloudflare/workerd/blob/main/RELEASE.md)
- [Commits](https://github.com/cloudflare/workerd/commits)

Updates `typescript` from 5.9.3 to 7.0.2
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Commits](https://github.com/microsoft/TypeScript/commits)

Updates `wrangler` from 4.120.0 to 4.122.0
- [Release notes](https://github.com/cloudflare/workers-sdk/releases)
- [Commits](https://github.com/cloudflare/workers-sdk/commits/wrangler@4.122.0/packages/wrangler)

---
updated-dependencies:
- dependency-name: "@cloudflare/workers-types"
  dependency-version: 5.20260813.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: opensymbols-proxy
- dependency-name: typescript
  dependency-version: 7.0.2
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: opensymbols-proxy
- dependency-name: wrangler
  dependency-version: 4.122.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: opensymbols-proxy
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
- Add atomic file writes and typed persistence failures
- Serialize repository access and quarantine corrupt data
- Add retry handling for phrase loading
- Track playback state and cancel superseded speech requests
- Use versioned, collision-resistant speech cache identities
…facades (#199)

* [#185] Migrate backup/restore to typed feature facades

First vertical slice of the KoinBridge decomposition: backup/restore
across shared Kotlin, iOS, and Linux.

- Add BackupFacade and BackupSharingFacade with constructor-injected
  dependencies, and a BackupManager interface implemented by
  CompleteBackupManager.
- Introduce typed BackupOperationStatus/BackupOperationResult/
  BackupExportResult so callers can distinguish unavailable, not-found,
  validation, persistence, network, sharing, and success (with
  retryability); rethrow coroutine cancellation instead of folding it
  into an ordinary failure.
- Give complete-backup failures stable privacy-safe messages and stop
  leaking raw exception text or media paths.
- Register facades through Koin; remove shareCompleteBackup() and
  restoreCompleteBackup() from the monolithic KoinBridge.
- Move iOS sharing/restore onto BackupSharingFacade and the Linux bridge
  onto an injected BackupFacade with typed HTTP responses; teach the
  Rust client to interpret them.
- Add focused BackupFacadeTest and Koin wiring coverage.

* [#185] Migrate speech to a typed feature facade

Second vertical slice of the KoinBridge decomposition: speech playback,
voice selection, and Azure speech configuration across shared Kotlin and
iOS.

- Add SpeechFacade with a narrow constructor (SpeechService,
  VoiceUseCase, SettingsUseCase, ConfigRepository); playback and config
  calls propagate failures and coroutine cancellation unchanged.
- Register SpeechFacade through Koin and expose it on the iOS
  composition root.
- Move speech playback, voice-selection/language alignment, TTS-engine
  switching, and Azure speech config out of the monolithic KoinBridge
  (102 lines removed); drop the unused updatePrimaryLanguage.
- Point IosViewModel, the voice/Azure sheets, and F0SetupView at the
  facade; duplicate updateSecondaryLanguage and iosSettingsFlags remain
  on the bridge until the settings slice lands.
- Add focused SpeechFacadeTest and Koin wiring coverage.

* [#185] Migrate settings to a typed feature facade

- Move iOS settings updates and editing access behind SettingsFacade
- Slim KoinBridge and remove Swift-facing settings helpers
- Add SettingsFacadeTest coverage

* [#185] Migrate boards to a typed feature facade

- Add BoardsFacade covering board set, board, and grid span operations
- Route IosViewModel board calls through the facade
- Add BoardsFacadeTest

* [#185] Migrate communication to a typed feature facade

- Move phrase store, history, and recording updates out of KoinBridge
- Add CommunicationFacade with tests
- Wire facade through iOS DI bridge

* [#185] Migrate board export to a typed feature facade

- Replace direct KoinBridge usage in SymbolBoardWorkspaceView with IosDiBridge boardsFacade

* [#185] Bind okio FileSystem on iOS
Upgrade Ktor to 3.5.2 so all Netty modules resolve to patched 4.2.16.Final,
closing the 66 Netty advisories against the Linux bridge. Force patched
transitive versions on the build/plugin classpath (BouncyCastle 1.84,
jose4j 0.9.6, jdom2 2.0.6.1, commons-lang3 3.18.0), set an incremental
Dependabot pull-request limit, and document the two remaining Kotlin-pinned
advisories as accepted risks.
- Pin patched transitive deps on project and plugin classpaths
- Pin yanked zune-core 0.5.3 in linuxApp
- Group Dependabot updates and document accepted Rust risks
Bumps the cargo group in /linuxApp with 1 update: [rfd](https://github.com/PolyMeilex/rfd).


Updates `rfd` from 0.16.0 to 0.17.2
- [Release notes](https://github.com/PolyMeilex/rfd/releases)
- [Changelog](https://github.com/PolyMeilex/rfd/blob/master/CHANGELOG.md)
- [Commits](PolyMeilex/rfd@0.16.0...0.17.2)

---
updated-dependencies:
- dependency-name: rfd
  dependency-version: 0.17.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: cargo
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…oup (#202)

Bumps the opensymbols-proxy group in /infra/opensymbols-proxy with 1 update: [wrangler](https://github.com/cloudflare/workers-sdk/tree/HEAD/packages/wrangler).


Updates `wrangler` from 4.122.0 to 4.123.0
- [Release notes](https://github.com/cloudflare/workers-sdk/releases)
- [Commits](https://github.com/cloudflare/workers-sdk/commits/wrangler@4.123.0/packages/wrangler)

---
updated-dependencies:
- dependency-name: wrangler
  dependency-version: 4.123.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: opensymbols-proxy
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Resolve remaining Dependabot dependency advisories
---
updated-dependencies:
- dependency-name: androidx.appcompat:appcompat
  dependency-version: 1.8.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gradle
- dependency-name: androidx.compose.material:material-icons-extended
  dependency-version: 1.7.8
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gradle
- dependency-name: androidx.compose:compose-bom
  dependency-version: 2026.08.00
  dependency-type: direct:production
  dependency-group: gradle
- dependency-name: androidx.constraintlayout:constraintlayout
  dependency-version: 2.2.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gradle
- dependency-name: androidx.core:core-ktx
  dependency-version: 1.19.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gradle
- dependency-name: androidx.lifecycle:lifecycle-runtime-ktx
  dependency-version: 2.11.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gradle
- dependency-name: androidx.lifecycle:lifecycle-runtime-ktx
  dependency-version: 2.11.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gradle
- dependency-name: com.android.application
  dependency-version: 9.3.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gradle
- dependency-name: com.android.kotlin.multiplatform.library
  dependency-version: 9.3.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gradle
- dependency-name: com.android.kotlin.multiplatform.library
  dependency-version: 9.3.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gradle
- dependency-name: com.android.library
  dependency-version: 9.3.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gradle
- dependency-name: com.android.library
  dependency-version: 9.3.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gradle
- dependency-name: com.github.triplet.play
  dependency-version: 4.1.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gradle
- dependency-name: com.squareup.okhttp3:okhttp
  dependency-version: 5.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gradle
- dependency-name: com.squareup.okio:okio
  dependency-version: 3.18.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gradle
- dependency-name: gradle-wrapper
  dependency-version: 9.7.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gradle
- dependency-name: io.github.oshai:kotlin-logging
  dependency-version: 8.0.4
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: gradle
- dependency-name: io.github.pdvrieze.xmlutil:core
  dependency-version: 1.0.2
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: gradle
- dependency-name: io.insert-koin:koin-android
  dependency-version: 4.2.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gradle
- dependency-name: io.insert-koin:koin-android
  dependency-version: 4.2.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gradle
- dependency-name: io.insert-koin:koin-compose
  dependency-version: 4.2.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gradle
- dependency-name: io.insert-koin:koin-compose
  dependency-version: 4.2.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gradle
- dependency-name: io.insert-koin:koin-core
  dependency-version: 4.2.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gradle
- dependency-name: org.apache.commons:commons-compress
  dependency-version: 1.28.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gradle
- dependency-name: org.apache.commons:commons-lang3
  dependency-version: 3.20.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gradle
- dependency-name: org.bouncycastle:bcpkix-jdk18on
  dependency-version: 1.85.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gradle
- dependency-name: org.bouncycastle:bcprov-jdk18on
  dependency-version: 1.85.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gradle
- dependency-name: org.bouncycastle:bcutil-jdk18on
  dependency-version: 1.85.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gradle
- dependency-name: org.jetbrains.androidx.lifecycle:lifecycle-runtime-compose
  dependency-version: 2.11.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gradle
- dependency-name: org.jetbrains.androidx.lifecycle:lifecycle-runtime-compose
  dependency-version: 2.11.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gradle
- dependency-name: org.jetbrains.androidx.lifecycle:lifecycle-viewmodel
  dependency-version: 2.11.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gradle
- dependency-name: org.jetbrains.compose
  dependency-version: 1.11.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gradle
- dependency-name: org.jetbrains.compose.hot-reload
  dependency-version: 1.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gradle
- dependency-name: org.jetbrains.kotlin.multiplatform
  dependency-version: 2.4.10
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gradle
- dependency-name: org.jetbrains.kotlin.multiplatform
  dependency-version: 2.4.10
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gradle
- dependency-name: org.jetbrains.kotlin.plugin.compose
  dependency-version: 2.4.10
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gradle
- dependency-name: org.jetbrains.kotlin.plugin.compose
  dependency-version: 2.4.10
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gradle
- dependency-name: org.jetbrains.kotlin.plugin.serialization
  dependency-version: 2.4.10
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gradle
- dependency-name: org.jetbrains.kotlin.plugin.serialization
  dependency-version: 2.4.10
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gradle
- dependency-name: org.jetbrains.kotlin:kotlin-test
  dependency-version: 2.4.10
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gradle
- dependency-name: org.jetbrains.kotlin:kotlin-test-junit
  dependency-version: 2.4.10
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gradle
- dependency-name: org.jetbrains.kotlin:kotlin-test-junit
  dependency-version: 2.4.10
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gradle
- dependency-name: org.jetbrains.kotlinx:kotlinx-datetime
  dependency-version: 0.8.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gradle
- dependency-name: org.jetbrains.kotlinx:kotlinx-serialization-json
  dependency-version: 1.11.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: gradle
...

Signed-off-by: dependabot[bot] <support@github.com>
Jdreioe and others added 29 commits September 29, 2026 10:18
Removes the old JVM desktop client's source set, the unbound
AndroidVoiceRepository, Azure's token-based synthesis path left behind
by the deleted SecureAzureSpeechService, result-less import wrappers,
and helpers with no callers. The in-memory repositories also lose their
artificial delays, which only slowed tests.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
SQLDelight never had a schema, shared declared Compose without any
Compose code, and the JVM target kept desktop-UI dependencies from the
retired Compose client. Removing Compose from shared also ends the
iosX64 resolution failures printed on every build. The version catalog
loses entries no build file reads.

The JVM target now only runs tests, so it gets a test HTTP engine, and
the two tests that silently relied on Swing's Main dispatcher now set a
test dispatcher like their neighbours.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The C API escaped only a few characters by hand, so an exception message
with any other control character reached Rust as invalid JSON and
surfaced as "Invalid Kotlin core response" instead of the real error.
Use kotlinx.serialization, like DesktopCore's own error responses.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
NativeCore was the only Core, including in tests, so the trait only
added dynamic dispatch. Also collapses the nested if clippy flagged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Android releases, desktop capabilities, Google Cloud voices, bundled gaze
daemon startup, the desktop module list and the Infisical CI secrets had
drifted from the workflows and sources they describe.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Screen delete/duplicate status messages pointed at boardset.* keys that
never existed; point them at the existing board_sets.* strings. Add the
missing common.play, common.delete, phrase.play_recording,
phrase.record.replace, board_sets.error.load_failed and
boardset.error.delete_board_failed keys to Base, da and de, and drop the
shadowed duplicate welcome_flow.finish entry in Base.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The two-parameter onChange closure receives (oldValue, newValue), so the
wiggle started when editing ended and stopped when it began.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Remove views nothing presents (RightSettingsPanel, WelcomeScreenIOS,
AzureSettingsSheet, ReorderPhrasesSheet, LanguageChip), view-model helpers
nothing calls (audio share/copy, setUseSystemTts, board highlight clear,
saveSelectedBoardSet, isHistorySelected, the never-built boardSentence
retry, the one-argument StoreObserver init), and the pre-iOS 17 record
permission fallbacks (the deployment target is iOS 18). Drop the debug
prints that logged voice names and the bound repository, the unused
wiggle timer and stale tuning comments, and build_and_run.sh, which the
Xcode build phase supersedes.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
With the dead Swift callers gone, remove KoinBridge shareAudio/copyAudio,
selectionHighlightClear and debugVoiceRepositoryName, and stop passing
appModule to initKoin twice. Remove the iOS AudioClipboard, SoundPlayer
and SystemVoiceProvider bindings nothing on iOS resolves, the unused
IosSpeechService Wiktionary pronunciation lookup, and the IosDiBridge
start/applyOverrides aliases. Trim SpeechFacade (useSystemTts helpers,
saveSpeechConfig, clearSpeechConfig, unvalidated saveGoogleSpeechConfig)
and SettingsFacade setters without callers, and delete PLATFORM_NOTES.md,
which described an AppDelegate/Flutter setup that no longer exists.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Drop the 45 Base keys (and their da/de counterparts, plus da's orphaned
category.history) that no Swift file references, either literally or
through an interpolated prefix (phrase.symbol.package., phrase.symbol.error.,
boardset.cell.word_type.). Most belonged to the views removed earlier.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Remove screens, dialogs and helpers that nothing reaches: the old Azure
setup screens, full-screen voice picker, update dialog, Category
selector, phrase grid, UI language and settings export dialogs, the
empty rear-display files and the AndroidTheme copy of AppTheme. The
three PhraseScreen dialogs whose show flags were never set go with them.

The voice filter helpers Settings still uses move to VoiceFilters.kt.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…seScreen

App never passes initialBoardId, so the imported-board overlay, its
state, back handler and loader could not run. Drop them along with the
locals nothing reads (OBF parser, update service, file picker, audio
clipboard, share service, import flag, dialog title), the no-op
primaryLanguageState copy and imports left unused.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…c settings

Nothing on Android binds PartnerWindowAvailability and isDesktop() is
always false, so neither toggle could ever show. Remove both end to end
(Settings sections, search entries, view-model actions and state, the
test fake, and the unused UiSettingsDialog). The stored Settings fields
stay in the shared model.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
MainActivity: remove the unused dual-screen operation, the foldable
observer that only fed a debug log, stale comments, an empty else and
redundant imports.

Replace the reflective isReleaseBuild() with BuildConfig.DEBUG and the
PlatformBackHandler pass-through with BackHandler.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Flutter leftovers: LaunchTheme/NormalTheme styles and launch_background
- ic_launcher_round icons (the manifest sets no roundIcon)
- 128 strings no code references, from every locale
- WAKE_LOCK: no code or library in the merged manifest needs it
- koin-android and ktor-client-okhttp (nothing here imports them; shared
  brings the Ktor engine), the duplicate test serialization dependency,
  the ignored composeOptions block and the printAgpVersion task

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Categories are stored in the phrase repository, but adding, moving or
deleting one never reloaded PhraseBloc. Phrases of a deleted Category
stayed in the tray, and after a Category move the next Phrase move used
stale positions. Reload the Phrases after each Category change.

CategoryUseCase is always registered in shared DI, so inject it directly
instead of polling Koin for up to 10 seconds. This also removes the
branch that left an unsaved Category chip on screen as if it had been
created; failures now show the retry panel.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
SettingsBloc and VoiceBloc had no clients, PhraseEvent.AddCategory was
never dispatched, and the repository-only PhraseBloc constructor existed
only for a placeholder test. PhraseBloc no longer needs CategoryUseCase.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
No client dispatches UpdatePhraseDetails or MoveCategory, and the
reorder messages were never sent. Drop them with GetAllItemsUseCase and
the pass-through MovePhraseUseCase; the store moves through the
repository it already holds.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
UpdateService and its AppVersion/UpdateInfo/UpdateStatus models have no
implementation, and the auto-update, partner-window font/lines/idle and
OSK scale settings are never read. Every Settings decoder ignores
unknown keys, so stored and backed-up settings still load.

androidApp's UpdateDialog and the PhraseScreen updateService lookup are
removed on the Android cleanup branch, which must land alongside this.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The cell edit, root-board and single-OBF export helpers had no callers
outside one test assertion; iOS edits cells through BoardsFacade and
exports through exportBoardSetAsObzResult.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Remove UiSettings, the ObfImageSource wrapper over ObfMediaSource,
shouldSpeakPhraseSelection, buildResolvedSentence,
TextEditingPolicy.adjustAfterEdit, Message.edit, the unused
SpeechTextProcessor helpers, SettingsStateManager.reloadSettings,
unused FeatureUsageEvents, and CommunicationAction.InsertPart.

Tests that covered unique behaviour now target the surviving APIs
(obfImageSources, joinSentenceText, Message.replaceRange).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Delete the empty util/time.kt and the no-arg initKoin overload that no
Swift or Kotlin caller uses, and remove a try/catch in
SettingsStateManager.updateSettings that only rethrew.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Replace Q2/Q3/Q4/Q7 codes that pointed at removed ADRs with the reason
itself, and correct comments claiming Android observes PhraseListStore,
that blocs are the only use-case callers, and that every Typing Screen
adapter uses activatePhrase.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The useSystemTts → TtsEngine migration ran on every launch. Stored
settings omit default values, so an explicit System choice looked like
pre-migration data, and any saved Azure credentials switched the engine
back to Azure at the next start.

The migration predates v1.0.0 and has already rewritten every Azure
user's settings, so remove it instead of adding a "migrated" flag.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The Android app no longer declares koin-android, so nothing reads it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Clean up legacy code across the codebase and fix the bugs it hid
SettingsScreen now only wires Koin, the ViewModel, events, and the
controller-bound editing-access dialog. SettingsContent renders supplied
SettingsUiState and reports SettingsAction, so loading, failure, save
retry, and restore confirmation can be previewed and Compose-tested.

Ported from 1bde4be, which never merged and no longer applied to main.

Refs #169

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
VoiceSelectionPage and LanguageSelectionPage (shared by Settings and
Welcome) no longer call VoiceUseCase or SettingsUseCase from
composables. VoiceSelectionViewModel and LanguageSelectionViewModel own
loading, retry, selection, and save-failure state through one
VoiceSelectionOperations seam that runs data access off the main thread;
the composables keep only filter and dialog UI state.

Behavior is unchanged: a failed cloud refresh still shows cached voices,
a failed language save returns to the persisted value with an error.

Refs #169

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Move Settings, voice, and language pages behind testable presentation state
@Jdreioe
Jdreioe merged commit 01e5c11 into staging Oct 4, 2026
29 of 31 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant