From 44c3f42dfc9ad177d97055a2c1a09c3020e06778 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 24 Sep 2026 19:10:20 +0000 Subject: [PATCH 01/79] ci: Bump the github-actions group with 2 updates Bumps the github-actions group with 2 updates: [github/codeql-action/init](https://github.com/github/codeql-action) and [github/codeql-action/analyze](https://github.com/github/codeql-action). Updates `github/codeql-action/init` from 4.38.0 to 4.38.1 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/b96794f015dfd88f77b49b1c93e0fa7110f94c63...1c5b675653bb5c22dbe9b12b556ec555138e09fd) Updates `github/codeql-action/analyze` from 4.38.0 to 4.38.1 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/b96794f015dfd88f77b49b1c93e0fa7110f94c63...1c5b675653bb5c22dbe9b12b556ec555138e09fd) --- updated-dependencies: - dependency-name: github/codeql-action/init dependency-version: 4.38.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions - dependency-name: github/codeql-action/analyze dependency-version: 4.38.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index e783b823..0d5e9c43 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -37,13 +37,13 @@ jobs: persist-credentials: false - name: Initialize CodeQL - uses: github/codeql-action/init@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4 + uses: github/codeql-action/init@1c5b675653bb5c22dbe9b12b556ec555138e09fd # v4 with: languages: actions build-mode: none - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4 + uses: github/codeql-action/analyze@1c5b675653bb5c22dbe9b12b556ec555138e09fd # v4 with: category: "/language:actions" @@ -96,7 +96,7 @@ jobs: -resolvePackageDependencies - name: Initialize CodeQL - uses: github/codeql-action/init@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4 + uses: github/codeql-action/init@1c5b675653bb5c22dbe9b12b556ec555138e09fd # v4 with: languages: swift build-mode: manual @@ -123,6 +123,6 @@ jobs: build - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4 + uses: github/codeql-action/analyze@1c5b675653bb5c22dbe9b12b556ec555138e09fd # v4 with: category: "/language:swift" From 058791a83db24a53a992a93e4ae1604ebfe538e4 Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Thu, 24 Sep 2026 14:43:34 -0400 Subject: [PATCH 02/79] Build BlurtEngine for iOS: fence the macOS-only files, make the seams portable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The engine now declares iOS 18 beside macOS 15. The Accessibility reads, the clipboard paste and its ⌘V, the CoreAudio route reads, the TCC reset and the code-signing probe are fenced behind `#if os(macOS)`; the pipeline, the dictation client and the settings stores compile for both. Three pieces the fenced files used to own move to platform-free files, since the pipeline and the iOS host need them: `CapturedFocus` + `FocusedFieldContext` (`FocusContext.swift`), `PermissionStatus`, and the spacing rule as `InsertionSeparator` (it was `KeyInjector`'s extension; an iOS keyboard writing through `insertText` faces the same decision). Two seams change shape so an iOS host can use them. `InjectorProtocol`'s `setTargetApp(NSRunningApplication?)` becomes `setTarget(CapturedFocus?)` — a pid and a name, resolved to the process handle inside `KeyInjector` on macOS. `DictationSession`'s public initializer takes a `HostFocusCapture`, the two closures that replace the Accessibility capture where there is none (an iOS keyboard hands in `documentContextBeforeInput` as the text before the cursor). `check.yml` gains a required `ios-build` job that compiles the library for the iOS simulator, the only place a symbol that escapes its fence is caught, and the dependency and invariant guards widen from `App/Blurt` to every `App/*`. Also unwraps the double-wrapped capture failure: `MicCapture.start()` already throws a `BlurtError`, and wrapping it again read as "Audio capture failed: Audio capture failed: …". Redoes the approach of the unmerged `feat/blurtengine-ios` branch against the current engine. Co-Authored-By: Claude Fable 5.1 --- .github/workflows/check.yml | 71 ++- AGENTS.md | 42 +- App/Blurt/Blurt/UITestSupport.swift | 2 +- Package.swift | 7 +- .../BlurtEngine/Audio/AudioInputDevices.swift | 14 +- Sources/BlurtEngine/Audio/AudioRoute.swift | 130 ++-- .../BlurtEngine/Audio/AudioRouteMonitor.swift | 276 ++++----- .../BlurtEngine/Audio/AudioTransport.swift | 49 +- .../Audio/CaptureSessionRecorder.swift | 9 +- Sources/BlurtEngine/Config/InstallReset.swift | 10 +- .../FocusCapture+Editability.swift | 282 ++++----- .../FocusCapture/FocusCapture+Pure.swift | 4 +- .../FocusCapture/FocusCapture.swift | 506 ++++++++-------- .../FocusCapture/FocusContext.swift | 76 +++ .../Injection/InjectorProtocol.swift | 11 +- ...parator.swift => InsertionSeparator.swift} | 39 +- .../Injection/KeyInjector+SystemActions.swift | 148 ++--- .../BlurtEngine/Injection/KeyInjector.swift | 552 ++++++++--------- .../Injection/SystemClipboard.swift | 268 ++++----- .../Permissions/PermissionStatus.swift | 26 + .../Permissions/PermissionsChecker.swift | 192 +++--- .../Permissions/PermissionsReset.swift | 150 ++--- .../Permissions/SigningIdentity.swift | 178 +++--- .../BlurtEngine/Pipeline/DictationLog.swift | 2 +- .../Pipeline/DictationSession+Press.swift | 13 +- .../Pipeline/DictationSession+Seams.swift | 71 ++- .../Pipeline/DictationSession.swift | 15 +- Sources/BlurtEngine/README.md | 12 +- Sources/BlurtEngine/UserAgent.swift | 13 +- Tests/BlurtEngineTests/AXDowncastTests.swift | 76 +-- .../AudioInputDevicesTests.swift | 350 +++++------ .../BrowserBundleIDTests.swift | 256 ++++---- Tests/BlurtEngineTests/CancelRaceTests.swift | 3 +- .../BlurtEngineTests/ChunkedUploadTests.swift | 2 +- .../BlurtEngineTests/DictationLogTests.swift | 6 +- .../DictationSessionContextTests.swift | 8 +- .../EditableTargetTests.swift | 130 ++-- .../BlurtEngineTests/FocusCaptureTests.swift | 16 +- .../InsertionSeparatorTests.swift | 164 +++++ .../KeyInjectorFallbackTests.swift | 170 +++--- .../KeyInjectorInsertTests.swift | 500 ++++++++-------- .../KeyInjectorLeadingSeparatorTests.swift | 162 ----- .../KeyInjectorSystemActionsTests.swift | 158 ++--- Tests/BlurtEngineTests/MemoryLeakTests.swift | 12 +- Tests/BlurtEngineTests/MicLivenessTests.swift | 562 +++++++++--------- .../PermissionsCheckerTests.swift | 140 ++--- .../PermissionsResetTests.swift | 56 +- .../SigningIdentityMigrationTests.swift | 194 +++--- .../SigningIdentityTests.swift | 104 ++-- .../Stubs/DictationSessionTestSupport.swift | 6 +- .../Stubs/FakeClipboard.swift | 94 +-- .../Stubs/InjectorTestSupport.swift | 207 ++++--- .../BlurtEngineTests/Stubs/StubInjector.swift | 3 +- .../SystemClipboardTests.swift | 364 ++++++------ scripts/check-invariants.sh | 7 +- scripts/check.sh | 23 +- 56 files changed, 3620 insertions(+), 3321 deletions(-) create mode 100644 Sources/BlurtEngine/FocusCapture/FocusContext.swift rename Sources/BlurtEngine/Injection/{KeyInjector+Separator.swift => InsertionSeparator.swift} (56%) create mode 100644 Sources/BlurtEngine/Permissions/PermissionStatus.swift create mode 100644 Tests/BlurtEngineTests/InsertionSeparatorTests.swift delete mode 100644 Tests/BlurtEngineTests/KeyInjectorLeadingSeparatorTests.swift diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index eb523615..e4fb1d30 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -213,6 +213,39 @@ jobs: if-no-files-found: error retention-days: 14 + # The engine is a two-platform package, and `check` only ever compiles it for + # macOS: `swift test` builds for the host, and every job above runs on one. + # A macOS-only symbol that escapes its `#if os(macOS)` fence therefore passes + # `check` and breaks the iOS app, which is why this job exists and why `gate` + # treats it as required. It builds the library alone, for the simulator SDK — + # `xcodebuild` rather than `swift build`, because cross-compiling needs the + # SDK/destination handling xcodebuild owns, and it resolves the package + # straight from the checkout, no project needed. `generic/platform=iOS + # Simulator` builds against the runner's default (latest installed) simulator + # SDK without naming a device or pinning an iOS version. The scheme is the + # package's own `BlurtEngine` product scheme, so only the library builds; the + # test target stays a macOS (`swift test`) concern. + ios-build: + needs: changes + if: needs.changes.outputs.code == 'true' + runs-on: macos-26 + timeout-minutes: 15 + + steps: + - name: Checkout blurt + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + path: blurt + persist-credentials: false + + - name: Build BlurtEngine for iOS + working-directory: blurt + run: | + xcodebuild -scheme BlurtEngine \ + -destination 'generic/platform=iOS Simulator' \ + -derivedDataPath "$RUNNER_TEMP/BlurtEngine-iOS" \ + build + # Always-runs summary job, so a *skipped* `check` can't be mistaken for a pass. # GitHub reports a skipped required check to branch protection as successful, so # anything that makes `check` skip — the `changes` filter erroring, a `needs` @@ -223,30 +256,38 @@ jobs: # NOTE: this only protects the repo once branch protection requires `gate` # instead of (or as well as) `check` — that's a repo settings change. gate: - needs: [changes, check] + needs: [changes, check, ios-build] if: always() runs-on: ubuntu-latest steps: - - name: Assert the macOS gate ran or was intentionally skipped + - name: Assert the macOS and iOS gates ran or were intentionally skipped env: CHECK_RESULT: ${{ needs.check.result }} + IOS_RESULT: ${{ needs.ios-build.result }} CHANGES_RESULT: ${{ needs.changes.result }} CODE_CHANGED: ${{ needs.changes.outputs.code }} run: | - echo "changes=$CHANGES_RESULT code=$CODE_CHANGED check=$CHECK_RESULT" + echo "changes=$CHANGES_RESULT code=$CODE_CHANGED check=$CHECK_RESULT ios-build=$IOS_RESULT" if [ "$CHANGES_RESULT" != "success" ]; then echo "error: the changes filter did not succeed, so the gate cannot be trusted" >&2 exit 1 fi - case "$CHECK_RESULT" in - success) echo "macOS gate passed" ;; - skipped) - if [ "$CODE_CHANGED" = "false" ]; then - echo "docs-only change; macOS gate intentionally skipped" - else - echo "error: check was skipped but code changed" >&2 - exit 1 - fi - ;; - *) echo "error: macOS gate result was '$CHECK_RESULT'" >&2; exit 1 ;; - esac + # Same rule for both platform gates: green, or skipped only because the + # change was docs-only. Written once so the iOS gate can't drift into + # a looser reading than the macOS one. + assert_gate() { + case "$2" in + success) echo "$1 gate passed" ;; + skipped) + if [ "$CODE_CHANGED" = "false" ]; then + echo "docs-only change; $1 gate intentionally skipped" + else + echo "error: $1 gate was skipped but code changed" >&2 + exit 1 + fi + ;; + *) echo "error: $1 gate result was '$2'" >&2; exit 1 ;; + esac + } + assert_gate macOS "$CHECK_RESULT" + assert_gate iOS "$IOS_RESULT" diff --git a/AGENTS.md b/AGENTS.md index caece3da..56d4fada 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -32,10 +32,10 @@ Four reflexes before you touch anything: ### The two layers -| Layer | What it is | -| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `Sources/BlurtEngine/` | Swift package (`swift-tools-version:6.2`, `platforms: [.macOS(.v15)]`) owning the pipeline. Pure logic behind protocol seams, no AppKit-shell deps, **no external SPM deps** — Foundation/Security/AVFoundation/CoreAudio plus toolchain modules like Synchronization, with AppKit types only at the seams. | -| `App/Blurt/` | AppKit/SwiftUI shell (Xcode project generated by XcodeGen) that wires the engine to an overlay window, the main window, a Settings scene, a menu bar item, and the trigger key. Its only package is the local `BlurtEngine` (declared in `App/Blurt/project.yml`). | +| Layer | What it is | +| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `Sources/BlurtEngine/` | Swift package (`swift-tools-version:6.2`, `platforms: [.macOS(.v15), .iOS(.v18)]`) owning the pipeline. Pure logic behind protocol seams, no AppKit-shell deps, **no external SPM deps** — Foundation/Security/AVFoundation/CoreAudio plus toolchain modules like Synchronization, with AppKit types only at the seams. The macOS-only files (Accessibility reads, clipboard paste, CoreAudio route reads, TCC and code-signing helpers) are fenced behind `#if os(macOS)`; `check.yml`'s `ios-build` job builds the library for the iOS simulator so a symbol that escapes its fence fails the PR. | +| `App/Blurt/` | AppKit/SwiftUI shell (Xcode project generated by XcodeGen) that wires the engine to an overlay window, the main window, a Settings scene, a menu bar item, and the trigger key. Its only package is the local `BlurtEngine` (declared in `App/Blurt/project.yml`). | The engine's dependency-free rule is a **rule**; the app merely happens to carry none today. The former `mxcl/AppUpdater` dependency and its in-place self-updater were removed (see [Updates](#updates)), @@ -53,8 +53,8 @@ Sources/BlurtEngine/ the engine (dependency-free Swift package) README.md the engine's developer guide (quick start, seams, error table) Audio/ MicCapture (+meter) over CaptureSessionRecorder (the AVCaptureSession backend), MicLiveness (mic bring-up gate), - AudioRoute (+Monitor) — the CoreAudio output route, AudioTransport - — what a transport type means, + AudioRoute (+Monitor) — the CoreAudio output route (macOS only), + AudioTransport — what a transport type means, AudioInputDevices + MicDeviceStore (microphone selection), SoundPack/Catalog/Store (the voice *descriptors*; the voices themselves are app-side) @@ -63,10 +63,15 @@ Sources/BlurtEngine/ the engine (dependency-free Swift package) Config/ Keychain-backed API key, key terms, developer mode, style profiles, DefaultsKey + PersistedSettings (every defaults key, and the reset sweep over them) - FocusCapture/ Accessibility reads of the frontmost app / focused field + FocusCapture/ FocusContext (CapturedFocus + FocusedFieldContext, every platform); + the Accessibility reads of the frontmost app / focused field + (macOS only); +Pure, the decisions that need no AX call Hotkey/ TriggerKey(+Store), DictationKeyGate, DictationKeyRouter - Injection/ KeyInjector (clipboard paste), SystemClipboard - Permissions/ PermissionsChecker (mic + Accessibility) + Injection/ InsertionSeparator (the spacing rule, every platform); KeyInjector + (clipboard paste) + SystemClipboard (macOS only) + Permissions/ PermissionStatus + SetupReadiness (every platform); + PermissionsChecker (mic + Accessibility), PermissionsReset, + SigningIdentity (macOS only) Pipeline/ DictationSession (actor) + phases, UI projections, geometry, log STT/ AssemblyAITranscriber, Conversation/TranscriptionContext, KeytermsBoost, CleanupInstruction, SyncSTTLimits @@ -93,7 +98,8 @@ evals/ offline decision support — the repo's only Python dictation-prompt/ DSPy harness for tuning the dictation API's cleanup instruction; check.sh lints (ruff), format-checks (ruff format), and tests it ruff.toml ruff config for the above — the repo's only Python config -.github/workflows/ check.yml (the gate, macos-26), +.github/workflows/ check.yml (the gate, macos-26; its ios-build job compiles + the engine for the iOS simulator), release-bump.yml (version bump) + release.yml (sign + publish), codeql.yml .claude/ Claude Code hooks, skills, subagents (see CLAUDE.md) @@ -180,9 +186,14 @@ the two checks that genuinely need the build products stay behind them (step 12) two checks that can't move earlier. CI (`.github/workflows/check.yml`) installs all of these via Homebrew on `macos-26` and runs the same -script, so a clean local `check.sh` matches CI by construction. Two sibling jobs exist purely to -shorten the loop for whoever is editing Swift without a toolchain, and **neither is a required -check** — both can only go red where `check` would too: +script, so a clean local `check.sh` matches CI by construction. One more job **is** required, because +`check.sh` cannot cover it: **`ios-build`** compiles the engine for the iOS simulator +(`xcodebuild -scheme BlurtEngine -destination 'generic/platform=iOS Simulator'`), which is the only +place a macOS-only symbol that escaped its `#if os(macOS)` fence gets caught — `swift test` builds +for the host, and every other job runs on a Mac. `gate` fails unless both platform builds are green +(or skipped for a docs-only change). Two sibling jobs exist purely to shorten the loop for whoever is +editing Swift without a toolchain, and **neither is a required check** — both can only go red where +`check` would too: - **`compile`** — `swift build --build-tests -Xswiftc -warnings-as-errors` and nothing else. A test target that doesn't build is the most common way a PR here goes red, and this reports it in ~2 @@ -735,8 +746,9 @@ those degrades to the plain-text floor rather than a byte-faithful round trip. It first activates the captured target app; if that app has terminated or won't activate, it leaves the transcript on the clipboard and throws `.targetAppLost`, which the pipeline degrades to the quiet "copied" notice (`.noTarget`) rather than a red failure. Consecutive dictations are joined with a -leading separator space via `withLeadingSeparator`; when the prior text is unreadable, the separator -basis falls back to what was last pasted — but only when the target app **and** window title both +leading separator space via `InsertionSeparator.withLeadingSeparator` (its own platform-free type, +because a host that inserts text itself faces the same decision); when the prior text is unreadable, +the separator basis falls back to what was last pasted — but only when the target app **and** window title both match the last successful insert, so the fallback tracks "the same window", not just "the same process" (a browser hosts many unrelated tabs under one PID). diff --git a/App/Blurt/Blurt/UITestSupport.swift b/App/Blurt/Blurt/UITestSupport.swift index f47114f2..401d7d8a 100644 --- a/App/Blurt/Blurt/UITestSupport.swift +++ b/App/Blurt/Blurt/UITestSupport.swift @@ -108,7 +108,7 @@ /// target app). The harness window plays the role of "the app being pasted /// into", surfacing the recorded text for the test to assert on. nonisolated struct UITestInjector: InjectorProtocol { - func setTargetApp(_ app: NSRunningApplication?) async {} + func setTarget(_ focus: CapturedFocus?) async {} func insert(_ text: String, after priorText: String?, windowTitle: String?) async throws { await MainActor.run { UITestState.shared.recordPaste(text) } } diff --git a/Package.swift b/Package.swift index badb5a39..69b49e7a 100644 --- a/Package.swift +++ b/Package.swift @@ -3,7 +3,12 @@ import PackageDescription let package = Package( name: "BlurtEngine", - platforms: [.macOS(.v15)], + // iOS 18 is the era-matching floor for macOS 15: the engine's `Synchronization` + // imports (`Mutex`) need it, and nothing portable here wants anything newer. + // The macOS-only capture, injection, Accessibility and TCC files are fenced + // behind `#if os(macOS)`; the pipeline, STT client and settings stores compile + // for both platforms. CI's `ios-build` job is what keeps that true. + platforms: [.macOS(.v15), .iOS(.v18)], products: [ .library(name: "BlurtEngine", targets: ["BlurtEngine"]) ], diff --git a/Sources/BlurtEngine/Audio/AudioInputDevices.swift b/Sources/BlurtEngine/Audio/AudioInputDevices.swift index 7d681ceb..3f7bb08b 100644 --- a/Sources/BlurtEngine/Audio/AudioInputDevices.swift +++ b/Sources/BlurtEngine/Audio/AudioInputDevices.swift @@ -102,7 +102,19 @@ public enum AudioInputDevices { /// `AudioTransport` matches against CoreAudio's `kAudioDeviceTransportType*` /// constants. Bit-pattern converted rather than numerically: these are packed /// ASCII, and the sign of the `Int32` spelling is an accident of the API. + /// + /// macOS only: `transportType` is not in the iOS SDK, and iOS exposes a single + /// microphone whose physical route the audio session decides. There this + /// answers nil — which `AudioTransport` reads as "unclassified", the middle + /// liveness cap and no tail linger — and, through `transportType(forUID:)`, + /// also reads as "the pinned device is absent", so an iOS capture always + /// follows the system route. Both hold until the iOS capture path classifies + /// `AVAudioSession` ports instead. private static func transportType(of device: AVCaptureDevice?) -> UInt32? { - device.map { UInt32(bitPattern: $0.transportType) } + #if os(macOS) + return device.map { UInt32(bitPattern: $0.transportType) } + #else + return nil + #endif } } diff --git a/Sources/BlurtEngine/Audio/AudioRoute.swift b/Sources/BlurtEngine/Audio/AudioRoute.swift index 142315ff..e64c7130 100644 --- a/Sources/BlurtEngine/Audio/AudioRoute.swift +++ b/Sources/BlurtEngine/Audio/AudioRoute.swift @@ -1,71 +1,73 @@ -import CoreAudio +#if os(macOS) + import CoreAudio -/// The CoreAudio reads that are left: which device is the default *output*, and -/// the property addressing `AudioRouteMonitor` shares with it. -/// -/// The input side used to live here too — which device is the default input, and -/// what transport it is on — and both have moved to `AVCaptureDevice` -/// (`AudioInputDevices`), which answers them off the same object the recorder -/// opens. That move waited on confirming `AVCaptureDevice.transportType` reports -/// `blue` for AirPods, because a transport that failed to read as Bluetooth -/// silently costs the 2.5 s liveness cap and the 220 ms tail linger — the -/// missing-last-word bug both exist to fix. It does; the parallel HAL read went. -/// -/// Output has no such replacement: `AVCaptureDevice` describes *capture* -/// devices, and what `AudioRouteMonitor` watches is the output route the cue -/// players render into. -/// -/// Raw reads only — no policy. Needs real hardware to answer anything, so it is -/// excluded from the coverage gate and must not be where a decision hides. -/// -/// Internal, not public: the app never asks these directly (it observes route -/// *changes* through `AudioRouteMonitor`), and `.periphery.yml` runs with -/// `retain_public: false`, so a `public` symbol only the engine reaches fails -/// the unused-code scan. -enum AudioRoute { - /// The system's current default *output* device — what `AudioRouteMonitor` - /// hangs its format listener on. Nil when there is none, or the read failed. - static func defaultOutputDeviceID() -> AudioDeviceID? { - defaultDeviceID(for: kAudioHardwarePropertyDefaultOutputDevice) - } + /// The CoreAudio reads that are left: which device is the default *output*, and + /// the property addressing `AudioRouteMonitor` shares with it. + /// + /// The input side used to live here too — which device is the default input, and + /// what transport it is on — and both have moved to `AVCaptureDevice` + /// (`AudioInputDevices`), which answers them off the same object the recorder + /// opens. That move waited on confirming `AVCaptureDevice.transportType` reports + /// `blue` for AirPods, because a transport that failed to read as Bluetooth + /// silently costs the 2.5 s liveness cap and the 220 ms tail linger — the + /// missing-last-word bug both exist to fix. It does; the parallel HAL read went. + /// + /// Output has no such replacement: `AVCaptureDevice` describes *capture* + /// devices, and what `AudioRouteMonitor` watches is the output route the cue + /// players render into. + /// + /// Raw reads only — no policy. Needs real hardware to answer anything, so it is + /// excluded from the coverage gate and must not be where a decision hides. + /// + /// Internal, not public: the app never asks these directly (it observes route + /// *changes* through `AudioRouteMonitor`), and `.periphery.yml` runs with + /// `retain_public: false`, so a `public` symbol only the engine reaches fails + /// the unused-code scan. + enum AudioRoute { + /// The system's current default *output* device — what `AudioRouteMonitor` + /// hangs its format listener on. Nil when there is none, or the read failed. + static func defaultOutputDeviceID() -> AudioDeviceID? { + defaultDeviceID(for: kAudioHardwarePropertyDefaultOutputDevice) + } - // MARK: - CoreAudio addressing + // MARK: - CoreAudio addressing - /// The system-wide audio object, which owns the default-device properties. - static var systemObject: AudioObjectID { AudioObjectID(kAudioObjectSystemObject) } + /// The system-wide audio object, which owns the default-device properties. + static var systemObject: AudioObjectID { AudioObjectID(kAudioObjectSystemObject) } - /// A global-scope address for `selector`. Returned fresh per call rather than - /// stored, because every caller needs its own copy to pass `inout` to - /// CoreAudio. Shared with `AudioRouteMonitor`, which addresses the same object - /// graph and would otherwise restate this three-field literal. - static func globalAddress(_ selector: AudioObjectPropertySelector) -> AudioObjectPropertyAddress { - AudioObjectPropertyAddress( - mSelector: selector, - mScope: kAudioObjectPropertyScopeGlobal, - mElement: kAudioObjectPropertyElementMain) - } + /// A global-scope address for `selector`. Returned fresh per call rather than + /// stored, because every caller needs its own copy to pass `inout` to + /// CoreAudio. Shared with `AudioRouteMonitor`, which addresses the same object + /// graph and would otherwise restate this three-field literal. + static func globalAddress(_ selector: AudioObjectPropertySelector) -> AudioObjectPropertyAddress { + AudioObjectPropertyAddress( + mSelector: selector, + mScope: kAudioObjectPropertyScopeGlobal, + mElement: kAudioObjectPropertyElementMain) + } - // MARK: - CoreAudio reads + // MARK: - CoreAudio reads - /// The device the system object reports for `selector` (a default-device - /// property). Nil covers both a failed read and the "no such device" sentinel, - /// which callers treat identically. - /// - /// Spelled out rather than shared behind a generic `read(_:from:initial:)`. - /// That reads better but doesn't compile: `&value` on an unconstrained `T` is - /// "forming 'UnsafeMutableRawPointer' to a variable of type 'T'; this is likely - /// incorrect because 'T' may contain an object reference". Making it work means - /// constraining to `BitwiseCopyable` and going through `withUnsafeMutableBytes` - /// — more machinery than one five-line read is worth, in a file the coverage - /// gate can't check anyway. - private static func defaultDeviceID(for selector: AudioObjectPropertySelector) -> AudioDeviceID? { - var address = globalAddress(selector) - var deviceID = AudioDeviceID(0) - var size = UInt32(MemoryLayout.size) - let status = AudioObjectGetPropertyData(systemObject, &address, 0, nil, &size, &deviceID) - // 0 is `kAudioObjectUnknown` — "there is no such device" — spelled as the - // literal so this doesn't depend on how the constant imports. - guard status == noErr, deviceID != 0 else { return nil } - return deviceID + /// The device the system object reports for `selector` (a default-device + /// property). Nil covers both a failed read and the "no such device" sentinel, + /// which callers treat identically. + /// + /// Spelled out rather than shared behind a generic `read(_:from:initial:)`. + /// That reads better but doesn't compile: `&value` on an unconstrained `T` is + /// "forming 'UnsafeMutableRawPointer' to a variable of type 'T'; this is likely + /// incorrect because 'T' may contain an object reference". Making it work means + /// constraining to `BitwiseCopyable` and going through `withUnsafeMutableBytes` + /// — more machinery than one five-line read is worth, in a file the coverage + /// gate can't check anyway. + private static func defaultDeviceID(for selector: AudioObjectPropertySelector) -> AudioDeviceID? { + var address = globalAddress(selector) + var deviceID = AudioDeviceID(0) + var size = UInt32(MemoryLayout.size) + let status = AudioObjectGetPropertyData(systemObject, &address, 0, nil, &size, &deviceID) + // 0 is `kAudioObjectUnknown` — "there is no such device" — spelled as the + // literal so this doesn't depend on how the constant imports. + guard status == noErr, deviceID != 0 else { return nil } + return deviceID + } } -} +#endif diff --git a/Sources/BlurtEngine/Audio/AudioRouteMonitor.swift b/Sources/BlurtEngine/Audio/AudioRouteMonitor.swift index a1a24fa3..31f1cf93 100644 --- a/Sources/BlurtEngine/Audio/AudioRouteMonitor.swift +++ b/Sources/BlurtEngine/Audio/AudioRouteMonitor.swift @@ -1,152 +1,154 @@ -import CoreAudio -import Dispatch -import os +#if os(macOS) + import CoreAudio + import Dispatch + import os -/// Ticks whenever the system's audio **output** route changes in a way that -/// invalidates an already-pre-rolled `AVAudioPlayer`. -/// -/// This exists for the record cue chimes. `CueSoundPlayer` decodes and -/// `prepareToPlay()`s them once at launch so the first chime never stalls the -/// pill — but that pre-roll is bound to the output route it was made against, -/// and Blurt's own capture is what invalidates it: opening the mic flips AirPods -/// out of their output-only profile into the bidirectional one, which drops the -/// output format underneath the primed players. The first chime after such a -/// flip is exactly the one that stalls, which is the chime at the start of a -/// dictation. -/// -/// Two properties are watched, because "the route changed" has two shapes: -/// -/// - `kAudioHardwarePropertyDefaultOutputDevice` on the system object — the user -/// switched output devices (built-in speakers → AirPods). -/// - `kAudioDevicePropertyNominalSampleRate` on whichever device is *currently* -/// default — the same device renegotiated its format, which is what the -/// profile flip looks like from CoreAudio. That listener is re-targeted -/// whenever the first one fires, so it always tracks the live device. -/// -/// Public because the app owns the cue players; the engine's own use of -/// CoreAudio routing (`AudioRoute`) stays internal. -/// -/// `@unchecked Sendable` because the listener registrations below are confined -/// to `queue` rather than protected by a lock — see their declarations. -public final class AudioRouteMonitor: @unchecked Sendable { - private static let logger = HostIdentity.current.logger("AudioRoute") + /// Ticks whenever the system's audio **output** route changes in a way that + /// invalidates an already-pre-rolled `AVAudioPlayer`. + /// + /// This exists for the record cue chimes. `CueSoundPlayer` decodes and + /// `prepareToPlay()`s them once at launch so the first chime never stalls the + /// pill — but that pre-roll is bound to the output route it was made against, + /// and Blurt's own capture is what invalidates it: opening the mic flips AirPods + /// out of their output-only profile into the bidirectional one, which drops the + /// output format underneath the primed players. The first chime after such a + /// flip is exactly the one that stalls, which is the chime at the start of a + /// dictation. + /// + /// Two properties are watched, because "the route changed" has two shapes: + /// + /// - `kAudioHardwarePropertyDefaultOutputDevice` on the system object — the user + /// switched output devices (built-in speakers → AirPods). + /// - `kAudioDevicePropertyNominalSampleRate` on whichever device is *currently* + /// default — the same device renegotiated its format, which is what the + /// profile flip looks like from CoreAudio. That listener is re-targeted + /// whenever the first one fires, so it always tracks the live device. + /// + /// Public because the app owns the cue players; the engine's own use of + /// CoreAudio routing (`AudioRoute`) stays internal. + /// + /// `@unchecked Sendable` because the listener registrations below are confined + /// to `queue` rather than protected by a lock — see their declarations. + public final class AudioRouteMonitor: @unchecked Sendable { + private static let logger = HostIdentity.current.logger("AudioRoute") - /// Fires once per observed route change. `.bufferingNewest(1)` because this is - /// an invalidation signal, not a log: a consumer that was busy through three - /// changes needs to re-prime once, not three times. - public let outputRouteChanges: AsyncStream - private let continuation: AsyncStream.Continuation + /// Fires once per observed route change. `.bufferingNewest(1)` because this is + /// an invalidation signal, not a log: a consumer that was busy through three + /// changes needs to re-prime once, not three times. + public let outputRouteChanges: AsyncStream + private let continuation: AsyncStream.Continuation - /// The queue CoreAudio delivers every listener callback on, and the one place - /// the registrations below are touched. Serial, so a re-target triggered by a - /// default-device change can't interleave with itself. - private let queue: DispatchQueue + /// The queue CoreAudio delivers every listener callback on, and the one place + /// the registrations below are touched. Serial, so a re-target triggered by a + /// default-device change can't interleave with itself. + private let queue: DispatchQueue - /// The registered listener blocks, kept so they can be handed back to - /// CoreAudio — removal matches on block identity, so a re-created block would - /// deregister nothing. - /// - /// `nonisolated(unsafe)` rather than lock-guarded: every read and write happens - /// inside a `queue` block, including the initial registration (`init` wraps it - /// in `queue.sync` precisely so a listener can't fire before the property - /// recording it has been written). Dispatch's serial ordering supplies both the - /// exclusion and the memory barriers a lock would. - private nonisolated(unsafe) var systemListener: AudioObjectPropertyListenerBlock? - private nonisolated(unsafe) var deviceListener: (id: AudioDeviceID, block: AudioObjectPropertyListenerBlock)? + /// The registered listener blocks, kept so they can be handed back to + /// CoreAudio — removal matches on block identity, so a re-created block would + /// deregister nothing. + /// + /// `nonisolated(unsafe)` rather than lock-guarded: every read and write happens + /// inside a `queue` block, including the initial registration (`init` wraps it + /// in `queue.sync` precisely so a listener can't fire before the property + /// recording it has been written). Dispatch's serial ordering supplies both the + /// exclusion and the memory barriers a lock would. + private nonisolated(unsafe) var systemListener: AudioObjectPropertyListenerBlock? + private nonisolated(unsafe) var deviceListener: (id: AudioDeviceID, block: AudioObjectPropertyListenerBlock)? - public init() { - let (stream, continuation) = AsyncStream.makeStream(bufferingPolicy: .bufferingNewest(1)) - self.outputRouteChanges = stream - self.continuation = continuation - self.queue = DispatchQueue(label: HostIdentity.current.queueLabel("AudioRoute")) - queue.sync { - installDefaultDeviceListener() - retargetFormatListener() + public init() { + let (stream, continuation) = AsyncStream.makeStream(bufferingPolicy: .bufferingNewest(1)) + self.outputRouteChanges = stream + self.continuation = continuation + self.queue = DispatchQueue(label: HostIdentity.current.queueLabel("AudioRoute")) + queue.sync { + installDefaultDeviceListener() + retargetFormatListener() + } } - } - /// The monitor is owned for the app's lifetime, so this never runs in - /// practice — but deregistering mirrors the `[weak self]` care below and - /// documents that the CoreAudio registrations are owned rather than leaked: a - /// listener left behind outlives the monitor, since CoreAudio retains the block - /// and nothing else would ever hand it back. - /// - /// Removal happens **inline, with no hop onto `queue`** — deliberately. - /// - /// A `queue.sync` here can self-deadlock. The listener blocks capture `self` - /// weakly, but `guard let self` upgrades that to a strong reference for the - /// body's duration, so while a block is running `queue` *is* an owner. If the - /// last other reference is dropped in that window, the block's release is the - /// final one and this `deinit` runs **on `queue`** — where `queue.sync` - /// deadlocks against itself. - /// - /// Inline removal is also race-free without the hop. `deinit` only runs once - /// the last reference is gone, so no block can be *inside* its `guard let self` - /// concurrently with this — a block that starts now fails the upgrade and - /// touches nothing. That leaves these reads of the queue-confined - /// registrations unopposed. (`queue` is still passed to CoreAudio, because - /// removal matches on the queue the listener was added with; that's an argument, - /// not an execution context.) - deinit { - continuation.finish() - if let systemListener { - var address = AudioRoute.globalAddress(kAudioHardwarePropertyDefaultOutputDevice) - _ = AudioObjectRemovePropertyListenerBlock( - AudioRoute.systemObject, &address, queue, systemListener) - } - if let deviceListener { - var address = AudioRoute.globalAddress(kAudioDevicePropertyNominalSampleRate) - _ = AudioObjectRemovePropertyListenerBlock( - deviceListener.id, &address, queue, deviceListener.block) + /// The monitor is owned for the app's lifetime, so this never runs in + /// practice — but deregistering mirrors the `[weak self]` care below and + /// documents that the CoreAudio registrations are owned rather than leaked: a + /// listener left behind outlives the monitor, since CoreAudio retains the block + /// and nothing else would ever hand it back. + /// + /// Removal happens **inline, with no hop onto `queue`** — deliberately. + /// + /// A `queue.sync` here can self-deadlock. The listener blocks capture `self` + /// weakly, but `guard let self` upgrades that to a strong reference for the + /// body's duration, so while a block is running `queue` *is* an owner. If the + /// last other reference is dropped in that window, the block's release is the + /// final one and this `deinit` runs **on `queue`** — where `queue.sync` + /// deadlocks against itself. + /// + /// Inline removal is also race-free without the hop. `deinit` only runs once + /// the last reference is gone, so no block can be *inside* its `guard let self` + /// concurrently with this — a block that starts now fails the upgrade and + /// touches nothing. That leaves these reads of the queue-confined + /// registrations unopposed. (`queue` is still passed to CoreAudio, because + /// removal matches on the queue the listener was added with; that's an argument, + /// not an execution context.) + deinit { + continuation.finish() + if let systemListener { + var address = AudioRoute.globalAddress(kAudioHardwarePropertyDefaultOutputDevice) + _ = AudioObjectRemovePropertyListenerBlock( + AudioRoute.systemObject, &address, queue, systemListener) + } + if let deviceListener { + var address = AudioRoute.globalAddress(kAudioDevicePropertyNominalSampleRate) + _ = AudioObjectRemovePropertyListenerBlock( + deviceListener.id, &address, queue, deviceListener.block) + } } - } - // MARK: - Registration (queue-confined) + // MARK: - Registration (queue-confined) - /// Watches for the default output device itself changing. Registered once and - /// never re-targeted — the system object is always there. - private func installDefaultDeviceListener() { - var address = AudioRoute.globalAddress(kAudioHardwarePropertyDefaultOutputDevice) - // `[weak self]`, so CoreAudio's strong hold on the block doesn't keep the - // monitor alive forever — and so a callback landing during teardown finds - // nil rather than a half-destroyed object. - let block: AudioObjectPropertyListenerBlock = { [weak self] _, _ in - guard let self else { return } - // Re-target first, then publish: a consumer that re-primes on this tick - // should already be behind a listener pointed at the new device. - self.retargetFormatListener() - self.continuation.yield() - } - let status = AudioObjectAddPropertyListenerBlock(AudioRoute.systemObject, &address, queue, block) - guard status == noErr else { - Self.logger.error("default-output listener failed: \(status)") - return + /// Watches for the default output device itself changing. Registered once and + /// never re-targeted — the system object is always there. + private func installDefaultDeviceListener() { + var address = AudioRoute.globalAddress(kAudioHardwarePropertyDefaultOutputDevice) + // `[weak self]`, so CoreAudio's strong hold on the block doesn't keep the + // monitor alive forever — and so a callback landing during teardown finds + // nil rather than a half-destroyed object. + let block: AudioObjectPropertyListenerBlock = { [weak self] _, _ in + guard let self else { return } + // Re-target first, then publish: a consumer that re-primes on this tick + // should already be behind a listener pointed at the new device. + self.retargetFormatListener() + self.continuation.yield() + } + let status = AudioObjectAddPropertyListenerBlock(AudioRoute.systemObject, &address, queue, block) + guard status == noErr else { + Self.logger.error("default-output listener failed: \(status)") + return + } + systemListener = block } - systemListener = block - } - /// Points the format listener at the current default output device, removing - /// the one on the previous device. A no-op when the device hasn't actually - /// changed, so a notification that resolves to the same device doesn't churn - /// the registration. - private func retargetFormatListener() { - let device = AudioRoute.defaultOutputDeviceID() - if let existing = deviceListener { - guard existing.id != device else { return } + /// Points the format listener at the current default output device, removing + /// the one on the previous device. A no-op when the device hasn't actually + /// changed, so a notification that resolves to the same device doesn't churn + /// the registration. + private func retargetFormatListener() { + let device = AudioRoute.defaultOutputDeviceID() + if let existing = deviceListener { + guard existing.id != device else { return } + var address = AudioRoute.globalAddress(kAudioDevicePropertyNominalSampleRate) + _ = AudioObjectRemovePropertyListenerBlock(existing.id, &address, queue, existing.block) + deviceListener = nil + } + guard let device else { return } + let block: AudioObjectPropertyListenerBlock = { [weak self] _, _ in + self?.continuation.yield() + } var address = AudioRoute.globalAddress(kAudioDevicePropertyNominalSampleRate) - _ = AudioObjectRemovePropertyListenerBlock(existing.id, &address, queue, existing.block) - deviceListener = nil - } - guard let device else { return } - let block: AudioObjectPropertyListenerBlock = { [weak self] _, _ in - self?.continuation.yield() - } - var address = AudioRoute.globalAddress(kAudioDevicePropertyNominalSampleRate) - let status = AudioObjectAddPropertyListenerBlock(device, &address, queue, block) - guard status == noErr else { - Self.logger.error("output-format listener failed: \(status)") - return + let status = AudioObjectAddPropertyListenerBlock(device, &address, queue, block) + guard status == noErr else { + Self.logger.error("output-format listener failed: \(status)") + return + } + deviceListener = (id: device, block: block) } - deviceListener = (id: device, block: block) } -} +#endif diff --git a/Sources/BlurtEngine/Audio/AudioTransport.swift b/Sources/BlurtEngine/Audio/AudioTransport.swift index 99046b11..eee1bd94 100644 --- a/Sources/BlurtEngine/Audio/AudioTransport.swift +++ b/Sources/BlurtEngine/Audio/AudioTransport.swift @@ -1,4 +1,6 @@ -import CoreAudio +#if os(macOS) + import CoreAudio +#endif /// Classification of a CoreAudio device's transport type /// (`kAudioDevicePropertyTransportType`). @@ -12,6 +14,13 @@ import CoreAudio /// bring-up gate. /// - `MicCapture`'s tail linger, which keeps capturing past key-up so the last /// word doesn't get truncated by the link's buffering. +/// +/// The transport codes are HAL constants, which exist on macOS only. On iOS +/// nothing produces one — `AudioInputDevices` answers nil there — so both +/// classifiers answer `false`, which lands every iOS capture on the middle +/// liveness cap with no tail linger: the conservative reading, and a +/// placeholder until the iOS capture path classifies `AVAudioSession` ports +/// (`.bluetoothHFP` is the AirPods case that matters) the same way. enum AudioTransport { /// Whether the transport is a Bluetooth one. Both types count: AirPods and /// other wireless headsets report the classic `bluetooth` transport, LE Audio @@ -23,9 +32,13 @@ enum AudioTransport { /// and no linger. Padding every wired capture with a delay would be a worse /// regression than losing the tail on a device we couldn't classify. static func isBluetooth(_ transportType: UInt32?) -> Bool { - guard let transportType else { return false } - return transportType == kAudioDeviceTransportTypeBluetooth - || transportType == kAudioDeviceTransportTypeBluetoothLE + #if os(macOS) + guard let transportType else { return false } + return transportType == kAudioDeviceTransportTypeBluetooth + || transportType == kAudioDeviceTransportTypeBluetoothLE + #else + return false + #endif } /// Whether the transport is a wired or on-board one — a device that begins @@ -45,19 +58,23 @@ enum AudioTransport { /// the middle cap, which is the safe direction — a slightly longer wait on an /// exotic input, never a truncated one. static func isLocal(_ transportType: UInt32?) -> Bool { - guard let transportType else { return false } - switch transportType { - case kAudioDeviceTransportTypeBuiltIn, - kAudioDeviceTransportTypeUSB, - kAudioDeviceTransportTypePCI, - kAudioDeviceTransportTypeFireWire, - kAudioDeviceTransportTypeThunderbolt, - kAudioDeviceTransportTypeDisplayPort, - kAudioDeviceTransportTypeHDMI: - return true - default: + #if os(macOS) + guard let transportType else { return false } + switch transportType { + case kAudioDeviceTransportTypeBuiltIn, + kAudioDeviceTransportTypeUSB, + kAudioDeviceTransportTypePCI, + kAudioDeviceTransportTypeFireWire, + kAudioDeviceTransportTypeThunderbolt, + kAudioDeviceTransportTypeDisplayPort, + kAudioDeviceTransportTypeHDMI: + return true + default: + return false + } + #else return false - } + #endif } /// How much longer capture runs past the key-up that ends it, for a device of diff --git a/Sources/BlurtEngine/Audio/CaptureSessionRecorder.swift b/Sources/BlurtEngine/Audio/CaptureSessionRecorder.swift index 4fceab0d..f9090b69 100644 --- a/Sources/BlurtEngine/Audio/CaptureSessionRecorder.swift +++ b/Sources/BlurtEngine/Audio/CaptureSessionRecorder.swift @@ -154,7 +154,14 @@ final class CaptureSessionRecorder: NSObject, @unchecked Sendable { "session refused the input device \(device.localizedName, privacy: .public)") } } - output.audioSettings = Self.audioSettings() + // macOS only: `audioSettings` is not in the iOS SDK, where the output vends + // samples in the device's native format. Until the iOS capture path adds a + // conversion stage, what it delivers is not the 16 kHz mono S16LE the + // dictation API is declared to receive — so an iOS host must not upload + // this recorder's frames yet. + #if os(macOS) + output.audioSettings = Self.audioSettings() + #endif output.setSampleBufferDelegate(self, queue: delegateQueue) if session.canAddOutput(output) { session.addOutput(output) diff --git a/Sources/BlurtEngine/Config/InstallReset.swift b/Sources/BlurtEngine/Config/InstallReset.swift index 2d6bdf17..46a1ef66 100644 --- a/Sources/BlurtEngine/Config/InstallReset.swift +++ b/Sources/BlurtEngine/Config/InstallReset.swift @@ -73,7 +73,15 @@ public struct InstallReset { self.init( clearSettings: { PersistedSettings.resetAll() }, clearAPIKey: { keyStore.save(nil) }, - resetPermissions: { PermissionsReset.resetAll(bundleID: bundleID) }, + resetPermissions: { + #if os(macOS) + return PermissionsReset.resetAll(bundleID: bundleID) + #else + // iOS lets no app revoke its own grants — they go with the install — + // so there is nothing for this step to do, and nothing to report. + return true + #endif + }, clearLogs: { DictationLog.removeStoredLogs() }) } diff --git a/Sources/BlurtEngine/FocusCapture/FocusCapture+Editability.swift b/Sources/BlurtEngine/FocusCapture/FocusCapture+Editability.swift index e8749888..cb463370 100644 --- a/Sources/BlurtEngine/FocusCapture/FocusCapture+Editability.swift +++ b/Sources/BlurtEngine/FocusCapture/FocusCapture+Editability.swift @@ -1,155 +1,157 @@ -import AppKit -import ApplicationServices +#if os(macOS) + import AppKit + import ApplicationServices -// The "can this target accept a paste?" half of `FocusCapture`, split out of -// `FocusCapture.swift` to stay within the lint file-length budget — the same -// reason `DictationSession` is split across `+Commands`/`+Observation`/`+Pipeline`. -// -// Cohesive as its own file: everything here serves `KeyInjector`'s pre-paste -// "no beep" guard, whereas `FocusCapture.swift` proper serves the press-time -// context capture that primes the STT request. -extension FocusCapture { - /// AX roles a focused element reports when it accepts typed/pasted text. - /// Includes `secureFieldRole`: a password field is a valid *paste* target even - /// though its contents are never read (see `isSecureField`). - private static let editableRoles: Set = [ - "AXTextField", "AXTextArea", "AXComboBox", secureFieldRole, "AXSearchField", - ] + // The "can this target accept a paste?" half of `FocusCapture`, split out of + // `FocusCapture.swift` to stay within the lint file-length budget — the same + // reason `DictationSession` is split across `+Commands`/`+Observation`/`+Pipeline`. + // + // Cohesive as its own file: everything here serves `KeyInjector`'s pre-paste + // "no beep" guard, whereas `FocusCapture.swift` proper serves the press-time + // context capture that primes the STT request. + extension FocusCapture { + /// AX roles a focused element reports when it accepts typed/pasted text. + /// Includes `secureFieldRole`: a password field is a valid *paste* target even + /// though its contents are never read (see `isSecureField`). + private static let editableRoles: Set = [ + "AXTextField", "AXTextArea", "AXComboBox", secureFieldRole, "AXSearchField", + ] - /// Pure decision: do these signals, read off a focused element, mean it accepts - /// pasted text? The injector calls this just before a synthesized ⌘V — if it - /// returns false the paste is skipped (so macOS doesn't beep into a non-editable - /// target) and the transcript is left on the clipboard with a quiet "Copied" - /// notice. The "is anything focused at all?" question is answered by the caller, - /// which never gets this far without an element (see `hasEditableFocusedElement`). - /// - /// Requires a *positive* editability signal: a known text role, a settable value, - /// or an insertion point. Anything else — a non-text control, an unknown role, or - /// no readable role — is treated as not editable, so we copy rather than beep a - /// ⌘V into a target that can't take it. - /// - /// AX-opaque apps — Electron editors (VS Code, Slack) and web browsers — can - /// expose *none* of these signals even for a genuine text field, so this - /// returns false for them too. The injector still pastes into those via a - /// separate app-identity check (see `isAXOpaqueApp` / `KeyInjector.insert`), - /// so the user's words aren't dropped to copy-only there. - static func isEditableTarget(role: String?, valueSettable: Bool, hasInsertionPoint: Bool) -> Bool { - if let role, editableRoles.contains(role) { return true } - return valueSettable || hasInsertionPoint - } + /// Pure decision: do these signals, read off a focused element, mean it accepts + /// pasted text? The injector calls this just before a synthesized ⌘V — if it + /// returns false the paste is skipped (so macOS doesn't beep into a non-editable + /// target) and the transcript is left on the clipboard with a quiet "Copied" + /// notice. The "is anything focused at all?" question is answered by the caller, + /// which never gets this far without an element (see `hasEditableFocusedElement`). + /// + /// Requires a *positive* editability signal: a known text role, a settable value, + /// or an insertion point. Anything else — a non-text control, an unknown role, or + /// no readable role — is treated as not editable, so we copy rather than beep a + /// ⌘V into a target that can't take it. + /// + /// AX-opaque apps — Electron editors (VS Code, Slack) and web browsers — can + /// expose *none* of these signals even for a genuine text field, so this + /// returns false for them too. The injector still pastes into those via a + /// separate app-identity check (see `isAXOpaqueApp` / `KeyInjector.insert`), + /// so the user's words aren't dropped to copy-only there. + static func isEditableTarget(role: String?, valueSettable: Bool, hasInsertionPoint: Bool) -> Bool { + if let role, editableRoles.contains(role) { return true } + return valueSettable || hasInsertionPoint + } - /// Whether `app` is an Electron/Chromium-based app, detected by the bundled - /// Electron framework. Such apps ship with their accessibility tree off, so even - /// a focused text field exposes no editable AX signal and - /// `hasEditableFocusedElement` reads them as non-editable. A native app with - /// genuinely no editable focus bundles no such framework and correctly falls - /// back to copy. - static func isElectronApp(_ app: NSRunningApplication?) -> Bool { - isElectronBundle(app?.bundleURL) - } + /// Whether `app` is an Electron/Chromium-based app, detected by the bundled + /// Electron framework. Such apps ship with their accessibility tree off, so even + /// a focused text field exposes no editable AX signal and + /// `hasEditableFocusedElement` reads them as non-editable. A native app with + /// genuinely no editable focus bundles no such framework and correctly falls + /// back to copy. + static func isElectronApp(_ app: NSRunningApplication?) -> Bool { + isElectronBundle(app?.bundleURL) + } - /// Pure decision behind `isElectronApp`: does the bundle at `bundleURL` ship the - /// Electron framework? Split from the `NSRunningApplication` wrapper for the same - /// reason as `isBrowserBundleID` — the detection is then unit-testable against a - /// fixture bundle, instead of requiring an Electron app to be installed *and* - /// running on the machine under test. - static func isElectronBundle(_ bundleURL: URL?) -> Bool { - guard let bundleURL else { return false } - let electronFramework = bundleURL.appendingPathComponent( - "Contents/Frameworks/Electron Framework.framework") - return FileManager.default.fileExists(atPath: electronFramework.path) - } + /// Pure decision behind `isElectronApp`: does the bundle at `bundleURL` ship the + /// Electron framework? Split from the `NSRunningApplication` wrapper for the same + /// reason as `isBrowserBundleID` — the detection is then unit-testable against a + /// fixture bundle, instead of requiring an Electron app to be installed *and* + /// running on the machine under test. + static func isElectronBundle(_ bundleURL: URL?) -> Bool { + guard let bundleURL else { return false } + let electronFramework = bundleURL.appendingPathComponent( + "Contents/Frameworks/Electron Framework.framework") + return FileManager.default.fileExists(atPath: electronFramework.path) + } - /// Bundle-identifier prefixes of known web browsers. Prefix-matched so channel - /// variants classify with their stable siblings (`com.google.Chrome.beta`, - /// `com.apple.SafariTechnologyPreview`). - private static let browserBundleIDPrefixes: [String] = [ - "com.apple.Safari", // Safari + Safari Technology Preview - "com.google.Chrome", // Chrome + Beta/Dev/Canary - "org.chromium.Chromium", - "com.microsoft.edgemac", // Edge + Beta/Dev/Canary - "com.brave.Browser", // Brave + Beta/Nightly - "com.operasoftware.Opera", - "com.vivaldi.Vivaldi", - "company.thebrowser.Browser", // Arc - "org.mozilla.firefox", - "com.duckduckgo.macos.browser", - "com.kagi.kagimacOS", // Orion - ] + /// Bundle-identifier prefixes of known web browsers. Prefix-matched so channel + /// variants classify with their stable siblings (`com.google.Chrome.beta`, + /// `com.apple.SafariTechnologyPreview`). + private static let browserBundleIDPrefixes: [String] = [ + "com.apple.Safari", // Safari + Safari Technology Preview + "com.google.Chrome", // Chrome + Beta/Dev/Canary + "org.chromium.Chromium", + "com.microsoft.edgemac", // Edge + Beta/Dev/Canary + "com.brave.Browser", // Brave + Beta/Nightly + "com.operasoftware.Opera", + "com.vivaldi.Vivaldi", + "company.thebrowser.Browser", // Arc + "org.mozilla.firefox", + "com.duckduckgo.macos.browser", + "com.kagi.kagimacOS", // Orion + ] - /// Pure decision behind `isBrowserApp`: does this bundle identifier belong to a - /// known browser? Split from the `NSRunningApplication` wrapper so the - /// classification is unit-testable without live running apps. - static func isBrowserBundleID(_ bundleID: String?) -> Bool { - guard let bundleID else { return false } - return browserBundleIDPrefixes.contains { bundleID.hasPrefix($0) } - } + /// Pure decision behind `isBrowserApp`: does this bundle identifier belong to a + /// known browser? Split from the `NSRunningApplication` wrapper so the + /// classification is unit-testable without live running apps. + static func isBrowserBundleID(_ bundleID: String?) -> Bool { + guard let bundleID else { return false } + return browserBundleIDPrefixes.contains { bundleID.hasPrefix($0) } + } - /// Whether `app` is a known web browser. Web content is AX-opaque in practice: - /// Chromium builds its accessibility tree lazily (the first query after launch - /// resolves only a bare `AXWebArea` with no editable signal), and even with the - /// tree live, a `contenteditable` composer (ChatGPT's ProseMirror field) can - /// surface as a generic group with no settable value. So "no editable signal" - /// in a browser usually means "AX can't see the field," not "no field." - static func isBrowserApp(_ app: NSRunningApplication?) -> Bool { - isBrowserBundleID(app?.bundleIdentifier) - } + /// Whether `app` is a known web browser. Web content is AX-opaque in practice: + /// Chromium builds its accessibility tree lazily (the first query after launch + /// resolves only a bare `AXWebArea` with no editable signal), and even with the + /// tree live, a `contenteditable` composer (ChatGPT's ProseMirror field) can + /// surface as a generic group with no settable value. So "no editable signal" + /// in a browser usually means "AX can't see the field," not "no field." + static func isBrowserApp(_ app: NSRunningApplication?) -> Bool { + isBrowserBundleID(app?.bundleIdentifier) + } - /// Whether `app` is AX-opaque — an Electron editor or a web browser — where a - /// focused text field can expose no editable AX signal at all. These are the - /// one case the injector still pastes into on no signal: dropping the user's - /// words into a copy-only fallback there would be the worse mistake. The - /// accepted trade-off is a rare ⌘V beep when such an app truly has nothing - /// editable focused. - static func isAXOpaqueApp(_ app: NSRunningApplication?) -> Bool { - // Browser first: it's a string prefix check, whereas isElectronApp probes - // the disk (FileManager.fileExists) — skip that I/O for the common case. - isBrowserApp(app) || isElectronApp(app) - } + /// Whether `app` is AX-opaque — an Electron editor or a web browser — where a + /// focused text field can expose no editable AX signal at all. These are the + /// one case the injector still pastes into on no signal: dropping the user's + /// words into a copy-only fallback there would be the worse mistake. The + /// accepted trade-off is a rare ⌘V beep when such an app truly has nothing + /// editable focused. + static func isAXOpaqueApp(_ app: NSRunningApplication?) -> Bool { + // Browser first: it's a string prefix check, whereas isElectronApp probes + // the disk (FileManager.fileExists) — skip that I/O for the common case. + isBrowserApp(app) || isElectronApp(app) + } - /// Whether the system-wide focused element can accept pasted text right now. - /// Read by `KeyInjector` (off the main actor, after it has activated the target - /// app) just before pasting — the Accessibility *client* read APIs are - /// thread-safe. Returns `true` whenever AX can't be consulted (process not - /// trusted) or can't resolve a focused element, so an unknowable state still - /// attempts the paste — the injector's own trust check then handles the - /// missing-permission case. - nonisolated static func hasEditableFocusedElement() -> Bool { - guard AXIsProcessTrusted() else { return true } + /// Whether the system-wide focused element can accept pasted text right now. + /// Read by `KeyInjector` (off the main actor, after it has activated the target + /// app) just before pasting — the Accessibility *client* read APIs are + /// thread-safe. Returns `true` whenever AX can't be consulted (process not + /// trusted) or can't resolve a focused element, so an unknowable state still + /// attempts the paste — the injector's own trust check then handles the + /// missing-permission case. + nonisolated static func hasEditableFocusedElement() -> Bool { + guard AXIsProcessTrusted() else { return true } - guard let element = systemFocusedElement() else { - // AX is trusted but reports no focused element — e.g. a native app frontmost - // with nothing editable focused (Finder, the desktop, a button-only window). - // Posting ⌘V there only beeps, so treat it as non-editable and copy instead. - // AX-opaque apps (Electron editors like VS Code/Slack, and browsers before - // Chromium's lazy accessibility tree is built) also expose no focused - // element here, but the injector's app-identity check still pastes into - // those (see `KeyInjector.insert` / `isAXOpaqueApp`). - return false - } + guard let element = systemFocusedElement() else { + // AX is trusted but reports no focused element — e.g. a native app frontmost + // with nothing editable focused (Finder, the desktop, a button-only window). + // Posting ⌘V there only beeps, so treat it as non-editable and copy instead. + // AX-opaque apps (Electron editors like VS Code/Slack, and browsers before + // Chromium's lazy accessibility tree is built) also expose no focused + // element here, but the injector's app-identity check still pastes into + // those (see `KeyInjector.insert` / `isAXOpaqueApp`). + return false + } - // Same checked reader `captureFieldContext` uses for this attribute, so the - // editability path and the secure-field path can't disagree about what a - // misbehaving app's role reads as. - let role = stringValue(element, kAXRoleAttribute) + // Same checked reader `captureFieldContext` uses for this attribute, so the + // editability path and the secure-field path can't disagree about what a + // misbehaving app's role reads as. + let role = stringValue(element, kAXRoleAttribute) - var settable = DarwinBoolean(false) - let valueSettable = - AXUIElementIsAttributeSettable(element, kAXValueAttribute as CFString, &settable) == .success - && settable.boolValue + var settable = DarwinBoolean(false) + let valueSettable = + AXUIElementIsAttributeSettable(element, kAXValueAttribute as CFString, &settable) == .success + && settable.boolValue - // A readable selected-text *range* means the element has an insertion point — - // the hallmark of a text input even when its value isn't reported settable. - // Require the range to actually decode, not merely that the read succeeded: a - // `.success` carrying a non-CFRange payload is not an insertion point, and this - // signal is one of the two that can green-light a ⌘V on an unknown role. - var rangeRef: CFTypeRef? - let hasInsertionPoint = - AXUIElementCopyAttributeValue( - element, kAXSelectedTextRangeAttribute as CFString, &rangeRef) == .success - && rangeRef.flatMap(axRange) != nil + // A readable selected-text *range* means the element has an insertion point — + // the hallmark of a text input even when its value isn't reported settable. + // Require the range to actually decode, not merely that the read succeeded: a + // `.success` carrying a non-CFRange payload is not an insertion point, and this + // signal is one of the two that can green-light a ⌘V on an unknown role. + var rangeRef: CFTypeRef? + let hasInsertionPoint = + AXUIElementCopyAttributeValue( + element, kAXSelectedTextRangeAttribute as CFString, &rangeRef) == .success + && rangeRef.flatMap(axRange) != nil - return isEditableTarget( - role: role, valueSettable: valueSettable, hasInsertionPoint: hasInsertionPoint) + return isEditableTarget( + role: role, valueSettable: valueSettable, hasInsertionPoint: hasInsertionPoint) + } } -} +#endif diff --git a/Sources/BlurtEngine/FocusCapture/FocusCapture+Pure.swift b/Sources/BlurtEngine/FocusCapture/FocusCapture+Pure.swift index aee3e060..b2f6a8e7 100644 --- a/Sources/BlurtEngine/FocusCapture/FocusCapture+Pure.swift +++ b/Sources/BlurtEngine/FocusCapture/FocusCapture+Pure.swift @@ -50,12 +50,12 @@ extension FocusCapture { /// /// Google Docs (and some other web editors) expose the text before the caret as /// a lone U+200B ZERO WIDTH SPACE — invisible, not real content, yet crucially - /// *not* `Character.isWhitespace`. Left as-is, `KeyInjector.withLeadingSeparator` + /// *not* `Character.isWhitespace`. Left as-is, `InsertionSeparator.withLeadingSeparator` /// reads it as substantive preceding text that doesn't end in whitespace and /// prepends a stray separator space on every dictation. Treating an /// entirely-invisible read as "nothing readable here" (`nil`) instead routes the /// field into the same-window separator fallback like any other - /// Accessibility-opaque editor (see `KeyInjector.separatorBasis`). + /// Accessibility-opaque editor (see `InsertionSeparator.basis`). /// /// "Invisible" means every scalar is a default-ignorable code point (zero-width /// spaces, joiners, bidi marks, BOM, …). Regular whitespace (space/tab/newline) diff --git a/Sources/BlurtEngine/FocusCapture/FocusCapture.swift b/Sources/BlurtEngine/FocusCapture/FocusCapture.swift index 5d2043dc..c4874a05 100644 --- a/Sources/BlurtEngine/FocusCapture/FocusCapture.swift +++ b/Sources/BlurtEngine/FocusCapture/FocusCapture.swift @@ -1,295 +1,261 @@ -import AppKit -import ApplicationServices +#if os(macOS) + import AppKit + import ApplicationServices -struct CapturedFocus: Sendable { - let pid: pid_t - let processName: String? -} - -enum FocusCapture { - @MainActor - static func captureFrontmost() -> CapturedFocus? { - guard let app = NSWorkspace.shared.frontmostApplication else { return nil } - return CapturedFocus( - pid: app.processIdentifier, - processName: app.localizedName - ) - } - - static func runningApp(for captured: CapturedFocus) -> NSRunningApplication? { - NSRunningApplication(processIdentifier: captured.pid) - } + // The Accessibility-backed half of the press-time focus capture. `FocusCapture` + // itself, `CapturedFocus` and `FocusedFieldContext` are declared in + // `FocusContext.swift`, which builds on every platform; this file is macOS only. + extension FocusCapture { + @MainActor + static func captureFrontmost() -> CapturedFocus? { + guard let app = NSWorkspace.shared.frontmostApplication else { return nil } + return CapturedFocus( + pid: app.processIdentifier, + processName: app.localizedName + ) + } - /// Accessibility-derived priming read from the system-wide focused UI element - /// at dictation start (see `TranscriptionContext`). Every field is - /// best-effort: any signal that can't be read is `nil`, and a fully-empty - /// result simply means less context, never an error. - struct FocusedFieldContext: Sendable { - /// Text immediately preceding the insertion point ("prior chunk context"). - let priorText: String? - /// The text currently selected in the focused field — the dictation will - /// replace it, so it primes the model on what the utterance is about. - let selectedText: String? - /// The focused window's title — a dense topic hint. - let windowTitle: String? - /// A short label for the focused field ("To", "Search", "Message"). - let fieldLabel: String? - /// Whether `mustRedactContents` refused to read this field — a password input, - /// or an element whose role couldn't be read at all (that guard fails closed). - /// `priorText`/`selectedText` are always nil when this is true, but the flag is - /// carried separately because "we read nothing" and "we refused to read" - /// license different downstream behaviour: only the latter means the transcript - /// the user is about to dictate must not be remembered as history (see - /// `DictationSession.recentDictations`). + /// Reads window title, field label, and up to `maxPriorChars` of text before + /// the cursor from the focused UI element in a single Accessibility traversal. /// - /// Defaults to `false` so a test fixture describes an ordinary field without - /// restating it; the production capture always passes its real verdict. - var isSecure: Bool = false - - static let empty = FocusedFieldContext( - priorText: nil, selectedText: nil, windowTitle: nil, fieldLabel: nil) - } - - /// Reads window title, field label, and up to `maxPriorChars` of text before - /// the cursor from the focused UI element in a single Accessibility traversal. - /// - /// Returns `.empty` whenever nothing can be read — the process lacks - /// Accessibility trust or no element is focused. Each field is independently - /// best-effort. Requires the same Accessibility permission the app already - /// holds for paste injection, so it adds no new prompt. - /// - /// Secure text fields (password inputs) are detected by role **or** subrole and - /// never have their contents read. This guard is what keeps a typed password out - /// of the developer-mode log and — since the text before the cursor is sent as - /// the request's contextual prompt (`STTPrompt`) — off the wire - /// entirely. The check - /// fails closed: an unreadable role is treated as secure, since it can't be - /// shown not to be. - /// - /// Deliberately `nonisolated`: each read below is a synchronous cross-process - /// IPC round trip into the frontmost app, and an unresponsive app blocks the - /// calling thread until the AX messaging timeout. On the main actor that froze - /// the overlay and menu bar right at hotkey press; callers run this off-main - /// (the AX *client* read APIs are thread-safe — see `systemFocusedElement`). - nonisolated static func captureFieldContext(maxPriorChars: Int = 320, maxSelectedChars: Int = 320) - -> FocusedFieldContext - { - guard AXIsProcessTrusted() else { return .empty } - guard let element = systemFocusedElement() else { return .empty } + /// Returns `.empty` whenever nothing can be read — the process lacks + /// Accessibility trust or no element is focused. Each field is independently + /// best-effort. Requires the same Accessibility permission the app already + /// holds for paste injection, so it adds no new prompt. + /// + /// Secure text fields (password inputs) are detected by role **or** subrole and + /// never have their contents read. This guard is what keeps a typed password out + /// of the developer-mode log and — since the text before the cursor is sent as + /// the request's contextual prompt (`STTPrompt`) — off the wire + /// entirely. The check + /// fails closed: an unreadable role is treated as secure, since it can't be + /// shown not to be. + /// + /// Deliberately `nonisolated`: each read below is a synchronous cross-process + /// IPC round trip into the frontmost app, and an unresponsive app blocks the + /// calling thread until the AX messaging timeout. On the main actor that froze + /// the overlay and menu bar right at hotkey press; callers run this off-main + /// (the AX *client* read APIs are thread-safe — see `systemFocusedElement`). + nonisolated static func captureFieldContext(maxPriorChars: Int = 320, maxSelectedChars: Int = 320) + -> FocusedFieldContext + { + guard AXIsProcessTrusted() else { return .empty } + guard let element = systemFocusedElement() else { return .empty } - // Don't read the value of a password field into the request. The whole - // decision — including the fail-closed arm — lives in `mustRedactContents`, - // where it is unit-tested; this function needs a live AX element, so anything - // decided inline here would be covered by nothing. - let isSecure = mustRedactContents( - role: stringValue(element, kAXRoleAttribute), - subrole: stringValue(element, kAXSubroleAttribute)) - // Both text slices stay nil for a secure field — the whole point of the guard - // above — so the reads that feed them are skipped wholesale rather than each - // being individually conditional. - var prior: String? - var selected: String? - if !isSecure { - // One read of the selected range serves both slices: its location *is* the - // insertion point the prior-text slice ends at, and its extent is what the - // selected-text slice asks for. Reading it here rather than inside each slice - // costs the capture one cross-process round trip for it instead of two. - let selection = selectedTextRange(of: element) - // `visibleTextOrNil` collapses an all-invisible read (e.g. Google Docs' lone - // U+200B before the caret) to nil so it can't masquerade as real prior text. - prior = visibleTextOrNil(priorText(of: element, selection: selection, maxChars: maxPriorChars)) - // The selected range's text (empty when there's no selection). Capped like - // prior text so a huge highlight can't dominate the context budget. - selected = visibleTextOrNil(selectedText(of: element, selection: selection, maxChars: maxSelectedChars)) + // Don't read the value of a password field into the request. The whole + // decision — including the fail-closed arm — lives in `mustRedactContents`, + // where it is unit-tested; this function needs a live AX element, so anything + // decided inline here would be covered by nothing. + let isSecure = mustRedactContents( + role: stringValue(element, kAXRoleAttribute), + subrole: stringValue(element, kAXSubroleAttribute)) + // Both text slices stay nil for a secure field — the whole point of the guard + // above — so the reads that feed them are skipped wholesale rather than each + // being individually conditional. + var prior: String? + var selected: String? + if !isSecure { + // One read of the selected range serves both slices: its location *is* the + // insertion point the prior-text slice ends at, and its extent is what the + // selected-text slice asks for. Reading it here rather than inside each slice + // costs the capture one cross-process round trip for it instead of two. + let selection = selectedTextRange(of: element) + // `visibleTextOrNil` collapses an all-invisible read (e.g. Google Docs' lone + // U+200B before the caret) to nil so it can't masquerade as real prior text. + prior = visibleTextOrNil(priorText(of: element, selection: selection, maxChars: maxPriorChars)) + // The selected range's text (empty when there's no selection). Capped like + // prior text so a huge highlight can't dominate the context budget. + selected = visibleTextOrNil(selectedText(of: element, selection: selection, maxChars: maxSelectedChars)) + } + return FocusedFieldContext( + priorText: prior, + selectedText: selected, + windowTitle: clip(windowTitle(of: element), to: 120), + fieldLabel: clip(fieldLabel(of: element), to: 80), + isSecure: isSecure) } - return FocusedFieldContext( - priorText: prior, - selectedText: selected, - windowTitle: clip(windowTitle(of: element), to: 120), - fieldLabel: clip(fieldLabel(of: element), to: 80), - isSecure: isSecure) - } - /// Cap on each cross-process AX round trip this process makes. An unresponsive - /// frontmost app costs a read this long, not the ~6 s system default; the - /// context capture is best-effort priming, so partial answers beat waiting. - private static let axMessagingTimeoutSeconds: Float = 1 + /// Cap on each cross-process AX round trip this process makes. An unresponsive + /// frontmost app costs a read this long, not the ~6 s system default; the + /// context capture is best-effort priming, so partial answers beat waiting. + private static let axMessagingTimeoutSeconds: Float = 1 - // Internal, not private: `hasEditableFocusedElement` in - // FocusCapture+Editability.swift calls it from another file. - /// The system-wide focused UI element, or `nil` when none is resolvable - /// (process not trusted, or nothing focused). The Accessibility *client* read - /// APIs are thread-safe, so this serves both the off-main context capture - /// and the injector's off-main editability check. - nonisolated static func systemFocusedElement() -> AXUIElement? { - let system = AXUIElementCreateSystemWide() - // Setting the timeout on the system-wide element applies it process-wide - // (per AXUIElement.h), bounding this focused-element lookup AND every later - // read — including ones on *other* element refs a per-element timeout would - // miss (the window element behind `windowTitle`, the editability probes). - AXUIElementSetMessagingTimeout(system, axMessagingTimeoutSeconds) - var focusedRef: CFTypeRef? - guard - AXUIElementCopyAttributeValue(system, kAXFocusedUIElementAttribute as CFString, &focusedRef) - == .success, - let focusedRef - else { return nil } - return axElement(focusedRef) - } + // Internal, not private: `hasEditableFocusedElement` in + // FocusCapture+Editability.swift calls it from another file. + /// The system-wide focused UI element, or `nil` when none is resolvable + /// (process not trusted, or nothing focused). The Accessibility *client* read + /// APIs are thread-safe, so this serves both the off-main context capture + /// and the injector's off-main editability check. + nonisolated static func systemFocusedElement() -> AXUIElement? { + let system = AXUIElementCreateSystemWide() + // Setting the timeout on the system-wide element applies it process-wide + // (per AXUIElement.h), bounding this focused-element lookup AND every later + // read — including ones on *other* element refs a per-element timeout would + // miss (the window element behind `windowTitle`, the editability probes). + AXUIElementSetMessagingTimeout(system, axMessagingTimeoutSeconds) + var focusedRef: CFTypeRef? + guard + AXUIElementCopyAttributeValue(system, kAXFocusedUIElementAttribute as CFString, &focusedRef) + == .success, + let focusedRef + else { return nil } + return axElement(focusedRef) + } - // MARK: - Checked CF downcasts - // - // AX attribute values arrive as CFTypeRef from *other apps'* accessibility - // implementations, so a misbehaving app returning the wrong CF type must read - // as "nothing readable" (nil), never flow onward mistyped. CF bridging makes - // `as?` a compile-time "always succeeds" warning (an error under - // -warnings-as-errors), so the runtime check is CFGetTypeID; after it the - // force-cast below each guard is provably safe — these two helpers are the - // only force_cast sites in the repo. Internal (not private) so the unit tests - // can exercise both arms without Accessibility trust. + // MARK: - Checked CF downcasts + // + // AX attribute values arrive as CFTypeRef from *other apps'* accessibility + // implementations, so a misbehaving app returning the wrong CF type must read + // as "nothing readable" (nil), never flow onward mistyped. CF bridging makes + // `as?` a compile-time "always succeeds" warning (an error under + // -warnings-as-errors), so the runtime check is CFGetTypeID; after it the + // force-cast below each guard is provably safe — these two helpers are the + // only force_cast sites in the repo. Internal (not private) so the unit tests + // can exercise both arms without Accessibility trust. - /// `ref` as an `AXUIElement`, or `nil` when it's some other CF type. - nonisolated static func axElement(_ ref: CFTypeRef) -> AXUIElement? { - guard CFGetTypeID(ref) == AXUIElementGetTypeID() else { return nil } - // swiftlint:disable:next force_cast - return (ref as! AXUIElement) - } + /// `ref` as an `AXUIElement`, or `nil` when it's some other CF type. + nonisolated static func axElement(_ ref: CFTypeRef) -> AXUIElement? { + guard CFGetTypeID(ref) == AXUIElementGetTypeID() else { return nil } + // swiftlint:disable:next force_cast + return (ref as! AXUIElement) + } - /// `ref` decoded as an `AXValue`-wrapped `CFRange` (the selected-text-range - /// payload), or `nil` when it's some other CF type or a non-range `AXValue` - /// (`AXValueGetValue` checks the payload type and refuses a mismatch). - nonisolated static func axRange(_ ref: CFTypeRef) -> CFRange? { - guard CFGetTypeID(ref) == AXValueGetTypeID() else { return nil } - // swiftlint:disable:next force_cast - let value = ref as! AXValue - var range = CFRange() - guard AXValueGetValue(value, .cfRange, &range) else { return nil } - return range - } + /// `ref` decoded as an `AXValue`-wrapped `CFRange` (the selected-text-range + /// payload), or `nil` when it's some other CF type or a non-range `AXValue` + /// (`AXValueGetValue` checks the payload type and refuses a mismatch). + nonisolated static func axRange(_ ref: CFTypeRef) -> CFRange? { + guard CFGetTypeID(ref) == AXValueGetTypeID() else { return nil } + // swiftlint:disable:next force_cast + let value = ref as! AXValue + var range = CFRange() + guard AXValueGetValue(value, .cfRange, &range) else { return nil } + return range + } - /// The element's selected text range — a zero-length range when there's just a - /// caret — or `nil` when it exposes no readable selection. Its `location` is the - /// insertion point. - private nonisolated static func selectedTextRange(of element: AXUIElement) -> CFRange? { - var rangeRef: CFTypeRef? - guard - AXUIElementCopyAttributeValue(element, kAXSelectedTextRangeAttribute as CFString, &rangeRef) - == .success, - let rangeRef - else { return nil } - return axRange(rangeRef) - } + /// The element's selected text range — a zero-length range when there's just a + /// caret — or `nil` when it exposes no readable selection. Its `location` is the + /// insertion point. + private nonisolated static func selectedTextRange(of element: AXUIElement) -> CFRange? { + var rangeRef: CFTypeRef? + guard + AXUIElementCopyAttributeValue(element, kAXSelectedTextRangeAttribute as CFString, &rangeRef) + == .success, + let rangeRef + else { return nil } + return axRange(rangeRef) + } - /// The element's text for `range` via the parameterized "string for range" - /// attribute, so only the slice asked for crosses Accessibility IPC rather than - /// the whole field value. Shared by the prior-text and selected-text reads, - /// which differ only in the range they request and how they post-process it. - private nonisolated static func string(of element: AXUIElement, in range: CFRange) -> String? { - var range = range - guard let axRange = AXValueCreate(.cfRange, &range) else { return nil } - var sliceRef: CFTypeRef? - guard - AXUIElementCopyParameterizedAttributeValue( - element, kAXStringForRangeParameterizedAttribute as CFString, axRange, &sliceRef) - == .success, - let slice = sliceRef as? String - else { return nil } - return slice - } + /// The element's text for `range` via the parameterized "string for range" + /// attribute, so only the slice asked for crosses Accessibility IPC rather than + /// the whole field value. Shared by the prior-text and selected-text reads, + /// which differ only in the range they request and how they post-process it. + private nonisolated static func string(of element: AXUIElement, in range: CFRange) -> String? { + var range = range + guard let axRange = AXValueCreate(.cfRange, &range) else { return nil } + var sliceRef: CFTypeRef? + guard + AXUIElementCopyParameterizedAttributeValue( + element, kAXStringForRangeParameterizedAttribute as CFString, axRange, &sliceRef) + == .success, + let slice = sliceRef as? String + else { return nil } + return slice + } - /// Up to `maxChars` of text immediately preceding the insertion point, or - /// `nil` when the element exposes no readable text before the cursor. - /// `selection` is the already-read selected range (see `selectedTextRange`). - private nonisolated static func priorText( - of element: AXUIElement, selection: CFRange?, maxChars: Int - ) -> String? { - // Insertion point = the location of the (possibly empty) selected range. - let caret = selection?.location ?? -1 + /// Up to `maxChars` of text immediately preceding the insertion point, or + /// `nil` when the element exposes no readable text before the cursor. + /// `selection` is the already-read selected range (see `selectedTextRange`). + private nonisolated static func priorText( + of element: AXUIElement, selection: CFRange?, maxChars: Int + ) -> String? { + // Insertion point = the location of the (possibly empty) selected range. + let caret = selection?.location ?? -1 - // Prefer the parameterized "string for range" so we read only the slice we - // need (cheap even in huge documents) rather than the whole field value. - if caret > 0 { - let start = max(0, caret - maxChars) - if let slice = string(of: element, in: CFRange(location: start, length: caret - start)), - !slice.isEmpty - { - return slice + // Prefer the parameterized "string for range" so we read only the slice we + // need (cheap even in huge documents) rather than the whole field value. + if caret > 0 { + let start = max(0, caret - maxChars) + if let slice = string(of: element, in: CFRange(location: start, length: caret - start)), + !slice.isEmpty + { + return slice + } } - } - // Fallback: read the full value and clip to the caret (or the tail). Read it - // RAW — `caret` is a UTF-16 offset into the untrimmed value, so a trimmed - // string would be indexed with offsets that no longer refer to it. - return priorSlice(full: rawStringValue(element, kAXValueAttribute) ?? "", caret: caret, maxChars: maxChars) - } + // Fallback: read the full value and clip to the caret (or the tail). Read it + // RAW — `caret` is a UTF-16 offset into the untrimmed value, so a trimmed + // string would be indexed with offsets that no longer refer to it. + return priorSlice(full: rawStringValue(element, kAXValueAttribute) ?? "", caret: caret, maxChars: maxChars) + } - /// Up to `maxChars` of selected text, or `nil` when the element exposes no - /// readable selection. Slices `selection` through the parameterized - /// string-for-range attribute first so a huge highlight does not copy the full - /// selection across Accessibility IPC before being clipped locally; falls back - /// to `kAXSelectedText` for elements that expose no string-for-range. - private nonisolated static func selectedText( - of element: AXUIElement, selection: CFRange?, maxChars: Int - ) -> String? { - if var selectedRange = selection, selectedRange.length > 0 { - selectedRange.length = min(selectedRange.length, maxChars) - if let slice = string(of: element, in: selectedRange) { - return clip(slice.trimmedNonEmpty(), to: maxChars) + /// Up to `maxChars` of selected text, or `nil` when the element exposes no + /// readable selection. Slices `selection` through the parameterized + /// string-for-range attribute first so a huge highlight does not copy the full + /// selection across Accessibility IPC before being clipped locally; falls back + /// to `kAXSelectedText` for elements that expose no string-for-range. + private nonisolated static func selectedText( + of element: AXUIElement, selection: CFRange?, maxChars: Int + ) -> String? { + if var selectedRange = selection, selectedRange.length > 0 { + selectedRange.length = min(selectedRange.length, maxChars) + if let slice = string(of: element, in: selectedRange) { + return clip(slice.trimmedNonEmpty(), to: maxChars) + } } - } - return clip(stringValue(element, kAXSelectedTextAttribute), to: maxChars) - } + return clip(stringValue(element, kAXSelectedTextAttribute), to: maxChars) + } - /// The title of the window containing the focused element, if exposed. - private nonisolated static func windowTitle(of element: AXUIElement) -> String? { - guard let window = elementValue(element, kAXWindowAttribute) else { return nil } - return stringValue(window, kAXTitleAttribute) - } + /// The title of the window containing the focused element, if exposed. + private nonisolated static func windowTitle(of element: AXUIElement) -> String? { + guard let window = elementValue(element, kAXWindowAttribute) else { return nil } + return stringValue(window, kAXTitleAttribute) + } - /// A short, human-meaningful label for the field, chosen by priority from the - /// attributes the focused element exposes. - private nonisolated static func fieldLabel(of element: AXUIElement) -> String? { - selectLabel( - placeholder: stringValue(element, kAXPlaceholderValueAttribute), - description: stringValue(element, kAXDescriptionAttribute), - title: stringValue(element, kAXTitleAttribute), - roleDescription: stringValue(element, kAXRoleDescriptionAttribute)) - } + /// A short, human-meaningful label for the field, chosen by priority from the + /// attributes the focused element exposes. + private nonisolated static func fieldLabel(of element: AXUIElement) -> String? { + selectLabel( + placeholder: stringValue(element, kAXPlaceholderValueAttribute), + description: stringValue(element, kAXDescriptionAttribute), + title: stringValue(element, kAXTitleAttribute), + roleDescription: stringValue(element, kAXRoleDescriptionAttribute)) + } - // Internal for the same reason as `systemFocusedElement`: the editability path in - // FocusCapture+Editability.swift reads the role through it. - /// Reads a `String`-valued AX attribute, returning `nil` for missing, - /// non-string, or blank values. Trims, which is what the *label-ish* attributes - /// want (role, title, placeholder, description). Do **not** use it for - /// `kAXValueAttribute` when a caret offset will index the result — see - /// `rawStringValue`. - nonisolated static func stringValue(_ element: AXUIElement, _ attribute: String) -> String? { - rawStringValue(element, attribute)?.trimmedNonEmpty() - } + // Internal for the same reason as `systemFocusedElement`: the editability path in + // FocusCapture+Editability.swift reads the role through it. + /// Reads a `String`-valued AX attribute, returning `nil` for missing, + /// non-string, or blank values. Trims, which is what the *label-ish* attributes + /// want (role, title, placeholder, description). Do **not** use it for + /// `kAXValueAttribute` when a caret offset will index the result — see + /// `rawStringValue`. + nonisolated static func stringValue(_ element: AXUIElement, _ attribute: String) -> String? { + rawStringValue(element, attribute)?.trimmedNonEmpty() + } - /// Reads a `String`-valued AX attribute **verbatim** — no trimming, so a - /// caret offset taken from the same element still indexes it correctly. - /// - /// `kAXSelectedTextRange` locations are UTF-16 offsets into the element's - /// *original* value. Trimming shifts every offset past a leading whitespace run - /// and shortens the string, so slicing a trimmed value with an untrimmed caret - /// silently returns the wrong text (or falls back to the whole tail, which - /// destroys the trailing-whitespace signal `withLeadingSeparator` reads). - private nonisolated static func rawStringValue(_ element: AXUIElement, _ attribute: String) -> String? { - var ref: CFTypeRef? - guard AXUIElementCopyAttributeValue(element, attribute as CFString, &ref) == .success, - let value = ref as? String - else { return nil } - return value - } + /// Reads a `String`-valued AX attribute **verbatim** — no trimming, so a + /// caret offset taken from the same element still indexes it correctly. + /// + /// `kAXSelectedTextRange` locations are UTF-16 offsets into the element's + /// *original* value. Trimming shifts every offset past a leading whitespace run + /// and shortens the string, so slicing a trimmed value with an untrimmed caret + /// silently returns the wrong text (or falls back to the whole tail, which + /// destroys the trailing-whitespace signal `withLeadingSeparator` reads). + private nonisolated static func rawStringValue(_ element: AXUIElement, _ attribute: String) -> String? { + var ref: CFTypeRef? + guard AXUIElementCopyAttributeValue(element, attribute as CFString, &ref) == .success, + let value = ref as? String + else { return nil } + return value + } - /// Reads an `AXUIElement`-valued AX attribute (e.g. the containing window). - private nonisolated static func elementValue(_ element: AXUIElement, _ attribute: String) -> AXUIElement? { - var ref: CFTypeRef? - guard AXUIElementCopyAttributeValue(element, attribute as CFString, &ref) == .success, - let ref - else { return nil } - return axElement(ref) + /// Reads an `AXUIElement`-valued AX attribute (e.g. the containing window). + private nonisolated static func elementValue(_ element: AXUIElement, _ attribute: String) -> AXUIElement? { + var ref: CFTypeRef? + guard AXUIElementCopyAttributeValue(element, attribute as CFString, &ref) == .success, + let ref + else { return nil } + return axElement(ref) + } } -} +#endif diff --git a/Sources/BlurtEngine/FocusCapture/FocusContext.swift b/Sources/BlurtEngine/FocusCapture/FocusContext.swift new file mode 100644 index 00000000..21d812c7 --- /dev/null +++ b/Sources/BlurtEngine/FocusCapture/FocusContext.swift @@ -0,0 +1,76 @@ +import Foundation + +/// The application that was frontmost when the user pressed the trigger — the +/// paste target, and the context's app name. +/// +/// A pid and a display name rather than an `NSRunningApplication`, so the value +/// crosses the engine's public seams (`InjectorProtocol.setTarget`, +/// `DictationSession.HostFocusCapture`) on every platform the engine builds +/// for. `KeyInjector` resolves the process handle from the pid on macOS; a host +/// on iOS has no process to name — a keyboard cannot see which app hosts it — +/// and passes nil. +public struct CapturedFocus: Sendable { + public let pid: pid_t + public let processName: String? + + public init(pid: pid_t, processName: String?) { + self.pid = pid + self.processName = processName + } +} + +// periphery:ignore - public for hosts outside this repo (the iOS app); the Mac app never names it. +/// Priming read from the focused field at dictation start (see +/// `TranscriptionContext`). Every field is best-effort: any signal that can't be +/// read is `nil`, and a fully-empty result simply means less context, never an +/// error. +/// +/// On macOS `FocusCapture.captureFieldContext` fills it from Accessibility. A +/// host on another platform builds it from whatever its own text surface +/// exposes — an iPhone keyboard's `documentContextBeforeInput` is `priorText`, +/// its `selectedText` is `selectedText`, and the app name, window title and +/// field label stay nil because a keyboard cannot see them — and hands it to +/// `DictationSession` through `HostFocusCapture`. +public struct FocusedFieldContext: Sendable { + /// Text immediately preceding the insertion point ("prior chunk context"). + public let priorText: String? + /// The text currently selected in the focused field — the dictation will + /// replace it, so it primes the model on what the utterance is about. + public let selectedText: String? + /// The focused window's title — a dense topic hint. + public let windowTitle: String? + /// A short label for the focused field ("To", "Search", "Message"). + public let fieldLabel: String? + /// Whether `mustRedactContents` refused to read this field — a password input, + /// or an element whose role couldn't be read at all (that guard fails closed). + /// `priorText`/`selectedText` are always nil when this is true, but the flag is + /// carried separately because "we read nothing" and "we refused to read" + /// license different downstream behaviour: only the latter means the transcript + /// the user is about to dictate must not be remembered as history (see + /// `DictationSession.recentDictations`). + /// + /// Defaults to `false` so a test fixture describes an ordinary field without + /// restating it; the production capture always passes its real verdict. + public var isSecure: Bool + + public init( + priorText: String?, selectedText: String?, windowTitle: String?, fieldLabel: String?, + isSecure: Bool = false + ) { + self.priorText = priorText + self.selectedText = selectedText + self.windowTitle = windowTitle + self.fieldLabel = fieldLabel + self.isSecure = isSecure + } + + public static let empty = FocusedFieldContext( + priorText: nil, selectedText: nil, windowTitle: nil, fieldLabel: nil) +} + +/// The press-time focus capture. The Accessibility-backed reads live in +/// `FocusCapture.swift` and `FocusCapture+Editability.swift`, which exist on +/// macOS only; the decisions that need no Accessibility call +/// (`FocusCapture+Pure.swift`) build on every platform, which is why the type +/// itself is declared here rather than beside the reads. +enum FocusCapture {} diff --git a/Sources/BlurtEngine/Injection/InjectorProtocol.swift b/Sources/BlurtEngine/Injection/InjectorProtocol.swift index 79d7eda4..d50155ff 100644 --- a/Sources/BlurtEngine/Injection/InjectorProtocol.swift +++ b/Sources/BlurtEngine/Injection/InjectorProtocol.swift @@ -1,14 +1,17 @@ -import AppKit - public protocol InjectorProtocol: Sendable { - func setTargetApp(_ app: NSRunningApplication?) async + /// Pins where the next `insert` lands: the focus captured when the trigger + /// went down, so the paste follows the user even if focus moves during + /// transcription. `nil` means "wherever focus is now". A host with no notion + /// of a target app — an iPhone keyboard inserts into the field it is already + /// attached to — receives nil and ignores it. + func setTarget(_ focus: CapturedFocus?) async /// Insert text into whatever the OS currently treats as the focus target. /// `priorText` is the text immediately before the caret (captured at press time), /// used to decide whether a separating space is needed so consecutive dictations /// don't run together; nil when the field is empty or its contents are opaque. /// `windowTitle` is the focused window's title at that same press-time capture — /// used to recognize a *continuing* dictation into the same window when - /// `priorText` is unreadable (see `KeyInjector.separatorBasis`); nil when the + /// `priorText` is unreadable (see `InsertionSeparator.basis`); nil when the /// window exposes no title. func insert(_ text: String, after priorText: String?, windowTitle: String?) async throws } diff --git a/Sources/BlurtEngine/Injection/KeyInjector+Separator.swift b/Sources/BlurtEngine/Injection/InsertionSeparator.swift similarity index 56% rename from Sources/BlurtEngine/Injection/KeyInjector+Separator.swift rename to Sources/BlurtEngine/Injection/InsertionSeparator.swift index 79aec915..5b2e8d91 100644 --- a/Sources/BlurtEngine/Injection/KeyInjector+Separator.swift +++ b/Sources/BlurtEngine/Injection/InsertionSeparator.swift @@ -1,13 +1,14 @@ -// `KeyInjector`'s separator decision: the pure text rules for joining a new -// dictation onto whatever already sits before the caret. Split out of -// `KeyInjector.swift` to stay within the lint file-length budget, on the seam its -// tests already use — `KeyInjectorLeadingSeparatorTests` and the -// `KeyInjector.separatorBasis` suite cover exactly these two functions, and -// neither touches the pasteboard, the event system, or the actor's state. -// `resolveInsert`, which composes them with the window-identity decision, stays -// beside that state in `KeyInjector.swift` (it needs `pid_t`, and this file -// deliberately imports nothing). -extension KeyInjector { +/// The pure text rules for joining a new dictation onto whatever already sits +/// before the caret. +/// +/// Shared by `KeyInjector` — the macOS clipboard paste — and by any host that +/// inserts text itself: an iPhone keyboard writing the transcript through +/// `insertText` faces exactly this decision, with `documentContextBeforeInput` +/// as the prior text. So it lives on its own type with no platform imports +/// rather than as `KeyInjector`'s extension (where it started; the tests moved +/// with it). `KeyInjector.resolveInsert` composes these two with the +/// window-identity decision, which stays beside the actor's state. +public enum InsertionSeparator { /// Joins `text` to whatever precedes the caret with exactly one separating space, /// so consecutive dictations don't run together. Prepends a *leading* space only /// when there's preceding text (`priorText`) that doesn't already end in @@ -33,15 +34,15 @@ extension KeyInjector { /// Code — or a browser tab like Google Docs, whose canvas-rendered body is just /// as opaque) — we can't tell those apart from AX alone, so we fall back to the /// text we last pasted, but only when this dictation targets the *same window* - /// as last time (see `WindowIdentity`): that's the in-progress-run case where - /// our own paste is what now sits before the caret. This is deliberately - /// app-agnostic rather than an allowlist of "known opaque editors": a window - /// match is a reasonable proxy for "still the same document" across *any* app, - /// opaque or not, whereas a shared process id alone isn't (one browser process - /// hosts many unrelated tabs/documents). Otherwise (a different window or - /// nothing pasted yet) we return nil rather than risk a stray leading space - /// into what may be a genuinely fresh field. - static func separatorBasis(priorText: String?, lastInserted: String?, sameWindow: Bool) -> String? { + /// as last time (see `KeyInjector.WindowIdentity`): that's the in-progress-run + /// case where our own paste is what now sits before the caret. This is + /// deliberately app-agnostic rather than an allowlist of "known opaque + /// editors": a window match is a reasonable proxy for "still the same document" + /// across *any* app, opaque or not, whereas a shared process id alone isn't + /// (one browser process hosts many unrelated tabs/documents). Otherwise (a + /// different window or nothing pasted yet) we return nil rather than risk a + /// stray leading space into what may be a genuinely fresh field. + static func basis(priorText: String?, lastInserted: String?, sameWindow: Bool) -> String? { if priorText != nil { return priorText } return sameWindow ? lastInserted : nil } diff --git a/Sources/BlurtEngine/Injection/KeyInjector+SystemActions.swift b/Sources/BlurtEngine/Injection/KeyInjector+SystemActions.swift index 92ba8e65..b06192ac 100644 --- a/Sources/BlurtEngine/Injection/KeyInjector+SystemActions.swift +++ b/Sources/BlurtEngine/Injection/KeyInjector+SystemActions.swift @@ -1,82 +1,84 @@ -import AppKit -import ApplicationServices -import CoreGraphics +#if os(macOS) + import AppKit + import ApplicationServices + import CoreGraphics -// The system side effects behind `KeyInjector`'s injectable seams: the default -// implementations of app activation, the frontmost-wait, the Accessibility-trust -// check, and the synthesized ⌘V. Split out from the actor's paste orchestration -// (`KeyInjector.swift`) because these are pure AppKit/CoreGraphics glue with no -// actor state — the only place `KeyInjector` needs CoreGraphics or -// ApplicationServices at all. `static`, not `private`, so the initializers in -// `KeyInjector.swift` can wire them as the defaults across the file boundary. -extension KeyInjector { - static func activate(_ app: NSRunningApplication) -> Bool { - app.activate() - } + // The system side effects behind `KeyInjector`'s injectable seams: the default + // implementations of app activation, the frontmost-wait, the Accessibility-trust + // check, and the synthesized ⌘V. Split out from the actor's paste orchestration + // (`KeyInjector.swift`) because these are pure AppKit/CoreGraphics glue with no + // actor state — the only place `KeyInjector` needs CoreGraphics or + // ApplicationServices at all. `static`, not `private`, so the initializers in + // `KeyInjector.swift` can wire them as the defaults across the file boundary. + extension KeyInjector { + static func activate(_ app: NSRunningApplication) -> Bool { + app.activate() + } - static func waitUntilFrontmost(_ app: NSRunningApplication) async -> Bool { - let pid = app.processIdentifier - let clock = ContinuousClock() - let deadline = clock.now.advanced(by: .milliseconds(350)) - while clock.now < deadline { - if await isFrontmost(pid) { return true } - try? await Task.sleep(for: .milliseconds(10)) + static func waitUntilFrontmost(_ app: NSRunningApplication) async -> Bool { + let pid = app.processIdentifier + let clock = ContinuousClock() + let deadline = clock.now.advanced(by: .milliseconds(350)) + while clock.now < deadline { + if await isFrontmost(pid) { return true } + try? await Task.sleep(for: .milliseconds(10)) + } + // One last read: the final sleep may have carried us past the deadline just + // before the activation landed. + return await isFrontmost(pid) } - // One last read: the final sleep may have carried us past the deadline just - // before the activation landed. - return await isFrontmost(pid) - } - /// Whether `pid` owns the frontmost application right now. Named rather than - /// inlined so the poll and the post-deadline check share one expression — and so - /// neither needs `MainActor.run`'s explicit `body:` label, which a trailing - /// closure in an `if` condition can't use. - private static func isFrontmost(_ pid: pid_t) async -> Bool { - await MainActor.run { - NSWorkspace.shared.frontmostApplication?.processIdentifier == pid + /// Whether `pid` owns the frontmost application right now. Named rather than + /// inlined so the poll and the post-deadline check share one expression — and so + /// neither needs `MainActor.run`'s explicit `body:` label, which a trailing + /// closure in an `if` condition can't use. + private static func isFrontmost(_ pid: pid_t) async -> Bool { + await MainActor.run { + NSWorkspace.shared.frontmostApplication?.processIdentifier == pid + } } - } - static func accessibilityTrusted() -> Bool { - AXIsProcessTrusted() - } + static func accessibilityTrusted() -> Bool { + AXIsProcessTrusted() + } - /// The Cmd-V key-down/key-up pair, or `nil` when CoreGraphics refuses to build - /// them. Split from `postCmdV` because only the *posting* is untestable: building - /// an event needs no Accessibility trust, while posting one sends a live - /// keystroke into whatever app has focus — not something `swift test` may do to - /// the machine it runs on. So the part carrying an actual invariant (the ⌘ flag - /// on both events and the `kVK_ANSI_V` keycode, which is what makes the paste a - /// paste) is asserted in `KeyInjectorSystemActionsTests`, and only the two - /// `.post` calls below stay covered by running the app. - static func cmdVEvents() -> (down: CGEvent, up: CGEvent)? { - let vKey: CGKeyCode = 0x09 // kVK_ANSI_V - guard let source = CGEventSource(stateID: .combinedSessionState), - let down = CGEvent(keyboardEventSource: source, virtualKey: vKey, keyDown: true), - let up = CGEvent(keyboardEventSource: source, virtualKey: vKey, keyDown: false) - else { return nil } - // Set on both: a key-up carrying no ⌘ reads as the modifier having been - // released mid-chord, which some apps treat as cancelling the shortcut. - down.flags = .maskCommand - up.flags = .maskCommand - return (down, up) - } + /// The Cmd-V key-down/key-up pair, or `nil` when CoreGraphics refuses to build + /// them. Split from `postCmdV` because only the *posting* is untestable: building + /// an event needs no Accessibility trust, while posting one sends a live + /// keystroke into whatever app has focus — not something `swift test` may do to + /// the machine it runs on. So the part carrying an actual invariant (the ⌘ flag + /// on both events and the `kVK_ANSI_V` keycode, which is what makes the paste a + /// paste) is asserted in `KeyInjectorSystemActionsTests`, and only the two + /// `.post` calls below stay covered by running the app. + static func cmdVEvents() -> (down: CGEvent, up: CGEvent)? { + let vKey: CGKeyCode = 0x09 // kVK_ANSI_V + guard let source = CGEventSource(stateID: .combinedSessionState), + let down = CGEvent(keyboardEventSource: source, virtualKey: vKey, keyDown: true), + let up = CGEvent(keyboardEventSource: source, virtualKey: vKey, keyDown: false) + else { return nil } + // Set on both: a key-up carrying no ⌘ reads as the modifier having been + // released mid-chord, which some apps treat as cancelling the shortcut. + down.flags = .maskCommand + up.flags = .maskCommand + return (down, up) + } - /// Posts Cmd-V. Returns `false` if the events couldn't be built. The real side - /// effect (a keystroke into the focused app) is why this is the injectable seam - /// tests replace. - static func postCmdV() -> Bool { - guard let (down, up) = cmdVEvents() else { return false } - // Post to the annotated session tap rather than the HID tap: the session tap - // honors exactly the flags set above instead of OR-ing in the live hardware - // modifier state, so a still-held hotkey modifier can't corrupt Cmd-V into a - // combo the target app ignores. (We deliberately don't suppress local events - // during the post: `setLocalEventsFilterDuringSuppressionState` lingers for - // the source's ~0.25s suppression interval and would swallow the user's next - // dictation keypress right after a paste — the annotated tap already prevents - // the modifier merge that suppression was guarding against.) - down.post(tap: .cgAnnotatedSessionEventTap) - up.post(tap: .cgAnnotatedSessionEventTap) - return true + /// Posts Cmd-V. Returns `false` if the events couldn't be built. The real side + /// effect (a keystroke into the focused app) is why this is the injectable seam + /// tests replace. + static func postCmdV() -> Bool { + guard let (down, up) = cmdVEvents() else { return false } + // Post to the annotated session tap rather than the HID tap: the session tap + // honors exactly the flags set above instead of OR-ing in the live hardware + // modifier state, so a still-held hotkey modifier can't corrupt Cmd-V into a + // combo the target app ignores. (We deliberately don't suppress local events + // during the post: `setLocalEventsFilterDuringSuppressionState` lingers for + // the source's ~0.25s suppression interval and would swallow the user's next + // dictation keypress right after a paste — the annotated tap already prevents + // the modifier merge that suppression was guarding against.) + down.post(tap: .cgAnnotatedSessionEventTap) + up.post(tap: .cgAnnotatedSessionEventTap) + return true + } } -} +#endif diff --git a/Sources/BlurtEngine/Injection/KeyInjector.swift b/Sources/BlurtEngine/Injection/KeyInjector.swift index c59802fd..d045fb51 100644 --- a/Sources/BlurtEngine/Injection/KeyInjector.swift +++ b/Sources/BlurtEngine/Injection/KeyInjector.swift @@ -1,298 +1,306 @@ -import AppKit +#if os(macOS) + import AppKit -public actor KeyInjector: InjectorProtocol { - private var targetApp: NSRunningApplication? + public actor KeyInjector: InjectorProtocol { + private var targetApp: NSRunningApplication? - /// How long to wait after posting Cmd-V before clearing and restoring the - /// pasteboard. The paste is asynchronous: clear too soon and a slow target - /// (VNC/Remote Desktop, heavy Electron apps) reads an already-cleared - /// clipboard. 400 ms is a pragmatic margin over local apps' near-instant read. - /// This wait runs in a background settle task (see `pendingSettle`), *not* on - /// `insert`'s caller, so it no longer delays the pipeline re-arming. - private let pasteSettleDuration: Duration + /// How long to wait after posting Cmd-V before clearing and restoring the + /// pasteboard. The paste is asynchronous: clear too soon and a slow target + /// (VNC/Remote Desktop, heavy Electron apps) reads an already-cleared + /// clipboard. 400 ms is a pragmatic margin over local apps' near-instant read. + /// This wait runs in a background settle task (see `pendingSettle`), *not* on + /// `insert`'s caller, so it no longer delays the pipeline re-arming. + private let pasteSettleDuration: Duration - /// Synthesizes the paste keystroke. Returns `false` if the event subsystem - /// couldn't build the events. Injectable so tests exercise the clipboard - /// save/restore logic without posting a real Cmd-V into the focused app. - private let postPaste: @Sendable () -> Bool + /// Synthesizes the paste keystroke. Returns `false` if the event subsystem + /// couldn't build the events. Injectable so tests exercise the clipboard + /// save/restore logic without posting a real Cmd-V into the focused app. + private let postPaste: @Sendable () -> Bool - /// Identifies a window by its app's pid plus its title — a pid alone isn't - /// enough (one browser process hosts many unrelated tabs/documents), and a - /// title alone isn't stable across apps, so both travel together as one - /// value rather than two optionals that would have to stay in sync by hand. - /// Title equality is itself a heuristic, not a strict identity check (two - /// tabs can coincidentally share a title, or a title can change mid-session - /// for reasons unrelated to the document, e.g. an unsaved-changes marker); - /// accepted here because the safe failure mode is just a missing separator. - /// - /// Internal rather than private so `resolveInsert` — the pure form of the - /// decision it feeds — can be driven from tests with plain pids and titles. - struct WindowIdentity: Equatable { - let pid: pid_t - let title: String + /// Identifies a window by its app's pid plus its title — a pid alone isn't + /// enough (one browser process hosts many unrelated tabs/documents), and a + /// title alone isn't stable across apps, so both travel together as one + /// value rather than two optionals that would have to stay in sync by hand. + /// Title equality is itself a heuristic, not a strict identity check (two + /// tabs can coincidentally share a title, or a title can change mid-session + /// for reasons unrelated to the document, e.g. an unsaved-changes marker); + /// accepted here because the safe failure mode is just a missing separator. + /// + /// Internal rather than private so `resolveInsert` — the pure form of the + /// decision it feeds — can be driven from tests with plain pids and titles. + struct WindowIdentity: Equatable { + let pid: pid_t + let title: String - // Hand-written rather than synthesized: Periphery's static analysis can't - // see through a compiler-synthesized `==`, so it flags `pid`/`title` as - // assigned-but-unused. Spelling out the comparison gives it a real usage - // site to index. - static func == (lhs: WindowIdentity, rhs: WindowIdentity) -> Bool { - lhs.pid == rhs.pid && lhs.title == rhs.title + // Hand-written rather than synthesized: Periphery's static analysis can't + // see through a compiler-synthesized `==`, so it flags `pid`/`title` as + // assigned-but-unused. Spelling out the comparison gives it a real usage + // site to index. + static func == (lhs: WindowIdentity, rhs: WindowIdentity) -> Bool { + lhs.pid == rhs.pid && lhs.title == rhs.title + } } - } - - /// The previous insert's resolution: the exact text it pasted (including any - /// leading separator it added) and the window it landed in. One value rather - /// than two optionals kept in sync by hand — the same reasoning as - /// `WindowIdentity` above, and they are only ever written together. - /// - /// Lets `insert` recover spacing in Accessibility-opaque editors - /// (Electron/Monaco, e.g. VS Code — and, just as opaque, a browser tab like - /// Google Docs) where no prior text can be read: if the next dictation targets - /// the same window, the text we just pasted is what now precedes the caret, so - /// it drives the separator decision (see `separatorBasis`). A different window - /// — a different tab, a different file, or an unreadable title — means a - /// different field, so the fallback doesn't fire. - private var lastInserted: ResolvedInsert? - /// Tail of the paste chain: each insert links behind the previous insert's - /// ENTIRE critical section — paste *plus* its backgrounded settle/restore — so - /// two pastes can never interleave on the global `NSPasteboard`. `insert` - /// itself returns as soon as its paste is posted (the settle trails inside the - /// chain link), so the pipeline re-arms immediately while the next paste still - /// waits out the restore window. Chaining replaces a hand-rolled continuation - /// mutex whose lock had to be handed off to the settle task. Exposed - /// (internal get) so tests can await the deferred restore before asserting - /// clipboard state; production never reads it. - private(set) var pendingSettle: Task? + /// The previous insert's resolution: the exact text it pasted (including any + /// leading separator it added) and the window it landed in. One value rather + /// than two optionals kept in sync by hand — the same reasoning as + /// `WindowIdentity` above, and they are only ever written together. + /// + /// Lets `insert` recover spacing in Accessibility-opaque editors + /// (Electron/Monaco, e.g. VS Code — and, just as opaque, a browser tab like + /// Google Docs) where no prior text can be read: if the next dictation targets + /// the same window, the text we just pasted is what now precedes the caret, so + /// it drives the separator decision (see `separatorBasis`). A different window + /// — a different tab, a different file, or an unreadable title — means a + /// different field, so the fallback doesn't fire. + private var lastInserted: ResolvedInsert? - /// Brings the captured target app back to the foreground before pasting. - /// Injectable so tests can cover activation failure without depending on - /// another live application. - private let activateTarget: @Sendable (NSRunningApplication) -> Bool + /// Tail of the paste chain: each insert links behind the previous insert's + /// ENTIRE critical section — paste *plus* its backgrounded settle/restore — so + /// two pastes can never interleave on the global `NSPasteboard`. `insert` + /// itself returns as soon as its paste is posted (the settle trails inside the + /// chain link), so the pipeline re-arms immediately while the next paste still + /// waits out the restore window. Chaining replaces a hand-rolled continuation + /// mutex whose lock had to be handed off to the settle task. Exposed + /// (internal get) so tests can await the deferred restore before asserting + /// clipboard state; production never reads it. + private(set) var pendingSettle: Task? - /// Waits until the app activation has actually become visible to - /// `NSWorkspace` before editability is checked and Cmd-V is posted. Kept - /// injectable so tests that stub activation don't depend on the host's live - /// foreground app. - private let waitForTargetActivation: @Sendable (NSRunningApplication) async -> Bool + /// Brings the captured target app back to the foreground before pasting. + /// Injectable so tests can cover activation failure without depending on + /// another live application. + private let activateTarget: @Sendable (NSRunningApplication) -> Bool - /// Whether the process is trusted for Accessibility. Posting the synthesized - /// Cmd-V requires it (macOS 10.14+); without it `CGEvent.post` is silently - /// dropped, so we check first and fail loudly instead of reporting a paste that - /// never happened. Injectable so tests don't depend on the host's AX state - /// (defaults to trusted there). - private let isAccessibilityTrusted: @Sendable () -> Bool + /// Waits until the app activation has actually become visible to + /// `NSWorkspace` before editability is checked and Cmd-V is posted. Kept + /// injectable so tests that stub activation don't depend on the host's live + /// foreground app. + private let waitForTargetActivation: @Sendable (NSRunningApplication) async -> Bool - /// Whether something editable is focused to receive the paste. Checked right - /// before the synthesized ⌘V (after the target app is activated): when false, - /// the paste is skipped and the transcript is left on the clipboard instead of - /// beeping into a non-editable target. Injectable so tests don't depend on the - /// host's live focus (defaults to "editable" there). - private let hasEditableTarget: @Sendable () -> Bool + /// Whether the process is trusted for Accessibility. Posting the synthesized + /// Cmd-V requires it (macOS 10.14+); without it `CGEvent.post` is silently + /// dropped, so we check first and fail loudly instead of reporting a paste that + /// never happened. Injectable so tests don't depend on the host's AX state + /// (defaults to trusted there). + private let isAccessibilityTrusted: @Sendable () -> Bool - /// Whether the captured target app is AX-opaque — an Electron/Chromium editor - /// (VS Code, Slack) or a web browser — which can expose no editable AX signal - /// even for a real text field (Chromium builds its accessibility tree lazily, - /// and `contenteditable` composers like ChatGPT's surface no editable role). - /// When `hasEditableTarget` reads false but this is true, we still paste - /// rather than copy — dropping the user's words into a field they're clearly - /// typing in would be the worse mistake. Injectable so tests don't depend on - /// which apps are installed (defaults to "not opaque"). - private let isAXOpaqueApp: @Sendable (NSRunningApplication?) -> Bool + /// Whether something editable is focused to receive the paste. Checked right + /// before the synthesized ⌘V (after the target app is activated): when false, + /// the paste is skipped and the transcript is left on the clipboard instead of + /// beeping into a non-editable target. Injectable so tests don't depend on the + /// host's live focus (defaults to "editable" there). + private let hasEditableTarget: @Sendable () -> Bool - /// The pasteboard the paste reads, writes, and restores. Behind a seam so - /// tests exercise the save/restore + changeCount logic against an in-memory - /// fake instead of the real system pasteboard — whose contents another process - /// can change mid-test, which (correctly) suppresses the restore and would - /// otherwise flake. - private let clipboard: any ClipboardAccess + /// Whether the captured target app is AX-opaque — an Electron/Chromium editor + /// (VS Code, Slack) or a web browser — which can expose no editable AX signal + /// even for a real text field (Chromium builds its accessibility tree lazily, + /// and `contenteditable` composers like ChatGPT's surface no editable role). + /// When `hasEditableTarget` reads false but this is true, we still paste + /// rather than copy — dropping the user's words into a field they're clearly + /// typing in would be the worse mistake. Injectable so tests don't depend on + /// which apps are installed (defaults to "not opaque"). + private let isAXOpaqueApp: @Sendable (NSRunningApplication?) -> Bool - public init(pasteSettleDuration: Duration = .milliseconds(400)) { - self.init( - pasteSettleDuration: pasteSettleDuration, - postPaste: KeyInjector.postCmdV, - activateTarget: KeyInjector.activate, - waitForTargetActivation: KeyInjector.waitUntilFrontmost, - isAccessibilityTrusted: KeyInjector.accessibilityTrusted, - hasEditableTarget: FocusCapture.hasEditableFocusedElement, - isAXOpaqueApp: FocusCapture.isAXOpaqueApp) - } - - init( - pasteSettleDuration: Duration, - postPaste: @escaping @Sendable () -> Bool, - activateTarget: @escaping @Sendable (NSRunningApplication) -> Bool = KeyInjector.activate, - waitForTargetActivation: @escaping @Sendable (NSRunningApplication) async -> Bool = { _ in true }, - isAccessibilityTrusted: @escaping @Sendable () -> Bool = { true }, - hasEditableTarget: @escaping @Sendable () -> Bool = { true }, - isAXOpaqueApp: @escaping @Sendable (NSRunningApplication?) -> Bool = { _ in false }, - clipboard: any ClipboardAccess = SystemClipboard() - ) { - self.pasteSettleDuration = pasteSettleDuration - self.postPaste = postPaste - self.activateTarget = activateTarget - self.waitForTargetActivation = waitForTargetActivation - self.isAccessibilityTrusted = isAccessibilityTrusted - self.hasEditableTarget = hasEditableTarget - self.isAXOpaqueApp = isAXOpaqueApp - self.clipboard = clipboard - } - - public func setTargetApp(_ app: NSRunningApplication?) async { - targetApp = app - } - - /// Brings the captured target app frontmost before a paste, then waits a beat - /// for the activation to settle. No-op when no target was captured. Throws - /// `.targetAppLost` if the app quit between capture and now, or if activation - /// fails — pasting into whatever currently has focus would land the - /// keystrokes in the wrong place. (`performInsert` puts the transcript on the - /// clipboard before letting this error propagate, so the words survive.) - /// Takes the target as a parameter (the caller's snapshot) rather than - /// re-reading `targetApp`, so a `setTargetApp` racing in across the settle - /// sleep can't swap it mid-paste. - private func activateTargetApp(_ target: NSRunningApplication?) async throws(BlurtError) { - guard let target else { return } - guard !target.isTerminated else { throw BlurtError.targetAppLost } - guard activateTarget(target) else { throw BlurtError.targetAppLost } - guard await waitForTargetActivation(target) else { throw BlurtError.targetAppLost } - } + /// The pasteboard the paste reads, writes, and restores. Behind a seam so + /// tests exercise the save/restore + changeCount logic against an in-memory + /// fake instead of the real system pasteboard — whose contents another process + /// can change mid-test, which (correctly) suppresses the restore and would + /// otherwise flake. + private let clipboard: any ClipboardAccess - public func insert(_ text: String, after priorText: String? = nil, windowTitle: String? = nil) async throws { - guard !text.isEmpty else { return } - // Serialize the whole paste critical section by chaining behind the previous - // insert's link (which includes its settle/restore — see `pendingSettle`). - // The actor is reentrant across the `await`s in `performInsert`, so an - // unserialized second insert would snapshot the pasteboard while it still - // holds this insert's transcript and later restore that instead of the - // user's original clipboard. - let previous = pendingSettle - let timeout = pasteSettleDuration - let paste = Task<(@Sendable () -> Void)?, any Error> { - await previous?.value - return try await self.performInsert(text, after: priorText, windowTitle: windowTitle) + public init(pasteSettleDuration: Duration = .milliseconds(400)) { + self.init( + pasteSettleDuration: pasteSettleDuration, + postPaste: KeyInjector.postCmdV, + activateTarget: KeyInjector.activate, + waitForTargetActivation: KeyInjector.waitUntilFrontmost, + isAccessibilityTrusted: KeyInjector.accessibilityTrusted, + hasEditableTarget: FocusCapture.hasEditableFocusedElement, + isAXOpaqueApp: FocusCapture.isAXOpaqueApp) } - // Strong `self` captures, deliberately: each link is bounded (one paste, one - // settle sleep — no cycle), and a weak capture would let an injector torn - // down mid-window skip the paste. The restore closure captures the clipboard - // (not `self`), so the user's contents come back even if the injector is - // gone by the time the settle fires. - pendingSettle = Task { - guard let restore = try? await paste.value else { return } - try? await Task.sleep(for: timeout) - restore() + + init( + pasteSettleDuration: Duration, + postPaste: @escaping @Sendable () -> Bool, + activateTarget: @escaping @Sendable (NSRunningApplication) -> Bool = KeyInjector.activate, + waitForTargetActivation: @escaping @Sendable (NSRunningApplication) async -> Bool = { _ in true }, + isAccessibilityTrusted: @escaping @Sendable () -> Bool = { true }, + hasEditableTarget: @escaping @Sendable () -> Bool = { true }, + isAXOpaqueApp: @escaping @Sendable (NSRunningApplication?) -> Bool = { _ in false }, + clipboard: any ClipboardAccess = SystemClipboard() + ) { + self.pasteSettleDuration = pasteSettleDuration + self.postPaste = postPaste + self.activateTarget = activateTarget + self.waitForTargetActivation = waitForTargetActivation + self.isAccessibilityTrusted = isAccessibilityTrusted + self.hasEditableTarget = hasEditableTarget + self.isAXOpaqueApp = isAXOpaqueApp + self.clipboard = clipboard } - // Forward the caller's cancellation into the chain link: the paste task is - // unstructured, so `pipelineTask.cancel()` in the session wouldn't otherwise - // reach `performInsert`'s cancellation gates. - try await withTaskCancellationHandler { - _ = try await paste.value - } onCancel: { - paste.cancel() + + /// Pins the paste target: the app that was frontmost at press time, resolved + /// from its pid here because `NSRunningApplication` is the handle activation + /// needs while a pid is what `CapturedFocus` can carry across the engine's + /// public seam on every platform. A pid that no longer resolves (the app quit + /// before the press was even joined) leaves no target, and `insert` then + /// pastes wherever focus is — the same thing a nil capture always meant. + public func setTarget(_ focus: CapturedFocus?) async { + targetApp = focus.flatMap { NSRunningApplication(processIdentifier: $0.pid) } } - } - /// The paste critical section: runs with the chain's guarantee that no other - /// insert (or its settle) is mid-flight. Returns the deferred clipboard-restore - /// action for the settle link to run once the paste has landed. - private func performInsert( - _ text: String, after priorText: String?, windowTitle: String? - ) async throws -> @Sendable () -> Void { - try Task.checkCancellation() - // Snapshot the target at entry and use only the local below: this method - // suspends (activation settle), the actor is reentrant, and a - // setTargetApp() interleaving mid-insert must not make us activate one app - // while judging editability and recording `lastInserted` for another. - let target = targetApp - let resolved = KeyInjector.resolveInsert( - text: text, priorText: priorText, windowTitle: windowTitle, - targetPID: target?.processIdentifier, - lastInserted: lastInserted) - let finalText = resolved.text - do { - try await activateTargetApp(target) - } catch { - // The target app quit or refused activation between capture and paste. - // Transcription already succeeded, so leave the words on the clipboard — - // the pipeline degrades this to the quiet "copied" notice instead of a - // hard failure that would lose the dictation. - clipboard.write(finalText) - throw error + /// Brings the captured target app frontmost before a paste, then waits a beat + /// for the activation to settle. No-op when no target was captured. Throws + /// `.targetAppLost` if the app quit between capture and now, or if activation + /// fails — pasting into whatever currently has focus would land the + /// keystrokes in the wrong place. (`performInsert` puts the transcript on the + /// clipboard before letting this error propagate, so the words survive.) + /// Takes the target as a parameter (the caller's snapshot) rather than + /// re-reading `targetApp`, so a `setTarget` racing in across the settle + /// sleep can't swap it mid-paste. + private func activateTargetApp(_ target: NSRunningApplication?) async throws(BlurtError) { + guard let target else { return } + guard !target.isTerminated else { throw BlurtError.targetAppLost } + guard activateTarget(target) else { throw BlurtError.targetAppLost } + guard await waitForTargetActivation(target) else { throw BlurtError.targetAppLost } } - // Final cancellation gate before the irreversible paste: a cancel() that - // landed during activation must not type into the focused app. - try Task.checkCancellation() - // Nothing editable is focused (checked now that the target app is frontmost): - // a synthesized ⌘V would just make macOS beep. Leave the transcript on the - // clipboard so the user can paste it by hand, and signal the pipeline to show - // a quiet "copied" notice instead of typing. The exception is an AX-opaque - // app — an Electron editor (VS Code, Slack) or a web browser — which can - // report no editable signal even for a real text field; there we still paste - // rather than drop the user's words. - guard hasEditableTarget() || isAXOpaqueApp(target) else { - clipboard.write(finalText) - throw BlurtError.noEditableTarget + + public func insert(_ text: String, after priorText: String? = nil, windowTitle: String? = nil) async throws { + guard !text.isEmpty else { return } + // Serialize the whole paste critical section by chaining behind the previous + // insert's link (which includes its settle/restore — see `pendingSettle`). + // The actor is reentrant across the `await`s in `performInsert`, so an + // unserialized second insert would snapshot the pasteboard while it still + // holds this insert's transcript and later restore that instead of the + // user's original clipboard. + let previous = pendingSettle + let timeout = pasteSettleDuration + let paste = Task<(@Sendable () -> Void)?, any Error> { + await previous?.value + return try await self.performInsert(text, after: priorText, windowTitle: windowTitle) + } + // Strong `self` captures, deliberately: each link is bounded (one paste, one + // settle sleep — no cycle), and a weak capture would let an injector torn + // down mid-window skip the paste. The restore closure captures the clipboard + // (not `self`), so the user's contents come back even if the injector is + // gone by the time the settle fires. + pendingSettle = Task { + guard let restore = try? await paste.value else { return } + try? await Task.sleep(for: timeout) + restore() + } + // Forward the caller's cancellation into the chain link: the paste task is + // unstructured, so `pipelineTask.cancel()` in the session wouldn't otherwise + // reach `performInsert`'s cancellation gates. + try await withTaskCancellationHandler { + _ = try await paste.value + } onCancel: { + paste.cancel() + } } - // Bail before touching the pasteboard if we can't actually paste: without - // Accessibility trust the Cmd-V post below is silently dropped, which would - // otherwise clobber-and-restore the clipboard for a paste that never lands. - guard isAccessibilityTrusted() else { throw BlurtError.accessibilityPermissionMissing } - // Put the transcript on the clipboard and keep the deferred restore that - // brings the user's contents back once the paste settles. - let restore = clipboard.writeAndPrepareRestore(finalText) - // If the event subsystem won't synthesize the keystroke, the paste can't - // happen. The transcript is already on the pasteboard — leave it there (the - // user's words beat the stale pre-paste snapshot) so the failure degrades - // to the "copied" notice, matching the lost-target path above. - guard postPaste() else { throw BlurtError.targetAppLost } - // The paste is posted and the text is visible. Record what landed (including - // any leading separator) and which window it landed in so a following - // dictation into the same window can recover its spacing, then hand the - // deferred restore back to the chain link (see `insert`). `insert` returns - // now — so the pipeline reaches `.idle` and re-arms without waiting out the - // restore window — while the next paste still serializes behind the settle. - lastInserted = resolved - return restore - } + /// The paste critical section: runs with the chain's guarantee that no other + /// insert (or its settle) is mid-flight. Returns the deferred clipboard-restore + /// action for the settle link to run once the paste has landed. + private func performInsert( + _ text: String, after priorText: String?, windowTitle: String? + ) async throws -> @Sendable () -> Void { + try Task.checkCancellation() + // Snapshot the target at entry and use only the local below: this method + // suspends (activation settle), the actor is reentrant, and a + // setTarget() interleaving mid-insert must not make us activate one app + // while judging editability and recording `lastInserted` for another. + let target = targetApp + let resolved = KeyInjector.resolveInsert( + text: text, priorText: priorText, windowTitle: windowTitle, + targetPID: target?.processIdentifier, + lastInserted: lastInserted) + let finalText = resolved.text + do { + try await activateTargetApp(target) + } catch { + // The target app quit or refused activation between capture and paste. + // Transcription already succeeded, so leave the words on the clipboard — + // the pipeline degrades this to the quiet "copied" notice instead of a + // hard failure that would lose the dictation. + clipboard.write(finalText) + throw error + } + // Final cancellation gate before the irreversible paste: a cancel() that + // landed during activation must not type into the focused app. + try Task.checkCancellation() + // Nothing editable is focused (checked now that the target app is frontmost): + // a synthesized ⌘V would just make macOS beep. Leave the transcript on the + // clipboard so the user can paste it by hand, and signal the pipeline to show + // a quiet "copied" notice instead of typing. The exception is an AX-opaque + // app — an Electron editor (VS Code, Slack) or a web browser — which can + // report no editable signal even for a real text field; there we still paste + // rather than drop the user's words. + guard hasEditableTarget() || isAXOpaqueApp(target) else { + clipboard.write(finalText) + throw BlurtError.noEditableTarget + } + // Bail before touching the pasteboard if we can't actually paste: without + // Accessibility trust the Cmd-V post below is silently dropped, which would + // otherwise clobber-and-restore the clipboard for a paste that never lands. + guard isAccessibilityTrusted() else { throw BlurtError.accessibilityPermissionMissing } - /// What one insert resolves to before anything is activated or pasted: the - /// exact text to write (any leading separator included) and the window - /// identity to remember it against. Fed straight back in as the next insert's - /// `lastInserted` — a resolution and the memory it becomes are the same pair, - /// so there is one type for both. - struct ResolvedInsert: Equatable { - let text: String - let window: WindowIdentity? - } + // Put the transcript on the clipboard and keep the deferred restore that + // brings the user's contents back once the paste settles. + let restore = clipboard.writeAndPrepareRestore(finalText) + // If the event subsystem won't synthesize the keystroke, the paste can't + // happen. The transcript is already on the pasteboard — leave it there (the + // user's words beat the stale pre-paste snapshot) so the failure degrades + // to the "copied" notice, matching the lost-target path above. + guard postPaste() else { throw BlurtError.targetAppLost } + // The paste is posted and the text is visible. Record what landed (including + // any leading separator) and which window it landed in so a following + // dictation into the same window can recover its spacing, then hand the + // deferred restore back to the chain link (see `insert`). `insert` returns + // now — so the pipeline reaches `.idle` and re-arms without waiting out the + // restore window — while the next paste still serializes behind the settle. + lastInserted = resolved + return restore + } + + /// What one insert resolves to before anything is activated or pasted: the + /// exact text to write (any leading separator included) and the window + /// identity to remember it against. Fed straight back in as the next insert's + /// `lastInserted` — a resolution and the memory it becomes are the same pair, + /// so there is one type for both. + struct ResolvedInsert: Equatable { + let text: String + let window: WindowIdentity? + } - /// Both of `performInsert`'s continuity decisions, as one pure function taking - /// the paste target as a plain pid rather than an `NSRunningApplication`: - /// which text to write, and which window to remember writing it into. - /// - /// A pid is all the decision ever needed. Computed inline in `performInsert`, - /// it could only be reached through a full `insert`, so its four cases were - /// covered by scraping `NSWorkspace` for live processes — one case required - /// the host to be running two — which activated the developer's foreground app - /// and failed whenever the unordered pick landed on a background-only process. - /// Here the same cases are plain values, and `insert` keeps one end-to-end test - /// for the wiring. - static func resolveInsert( - text: String, - priorText: String?, - windowTitle: String?, - targetPID: pid_t?, - lastInserted: ResolvedInsert? - ) -> ResolvedInsert { - let currentWindow = targetPID.flatMap { pid in - windowTitle.map { WindowIdentity(pid: pid, title: $0) } + /// Both of `performInsert`'s continuity decisions, as one pure function taking + /// the paste target as a plain pid rather than an `NSRunningApplication`: + /// which text to write, and which window to remember writing it into. + /// + /// A pid is all the decision ever needed. Computed inline in `performInsert`, + /// it could only be reached through a full `insert`, so its four cases were + /// covered by scraping `NSWorkspace` for live processes — one case required + /// the host to be running two — which activated the developer's foreground app + /// and failed whenever the unordered pick landed on a background-only process. + /// Here the same cases are plain values, and `insert` keeps one end-to-end test + /// for the wiring. + static func resolveInsert( + text: String, + priorText: String?, + windowTitle: String?, + targetPID: pid_t?, + lastInserted: ResolvedInsert? + ) -> ResolvedInsert { + let currentWindow = targetPID.flatMap { pid in + windowTitle.map { WindowIdentity(pid: pid, title: $0) } + } + // `currentWindow.map { ... } ?? false` rather than `currentWindow == lastInserted?.window`: + // both sides being nil (nothing readable this time, nothing pasted last time) + // must not count as a match. + let sameWindow = currentWindow.map { $0 == lastInserted?.window } ?? false + let basis = InsertionSeparator.basis( + priorText: priorText, lastInserted: lastInserted?.text, sameWindow: sameWindow) + return ResolvedInsert(text: InsertionSeparator.withLeadingSeparator(text, after: basis), window: currentWindow) } - // `currentWindow.map { ... } ?? false` rather than `currentWindow == lastInserted?.window`: - // both sides being nil (nothing readable this time, nothing pasted last time) - // must not count as a match. - let sameWindow = currentWindow.map { $0 == lastInserted?.window } ?? false - let basis = separatorBasis( - priorText: priorText, lastInserted: lastInserted?.text, sameWindow: sameWindow) - return ResolvedInsert(text: withLeadingSeparator(text, after: basis), window: currentWindow) } -} +#endif diff --git a/Sources/BlurtEngine/Injection/SystemClipboard.swift b/Sources/BlurtEngine/Injection/SystemClipboard.swift index 1c3c8b1d..e6102c39 100644 --- a/Sources/BlurtEngine/Injection/SystemClipboard.swift +++ b/Sources/BlurtEngine/Injection/SystemClipboard.swift @@ -1,154 +1,156 @@ -import AppKit -import Foundation +#if os(macOS) + import AppKit + import Foundation -/// A thread-safe, value-type representation of a pasteboard item containing its data -/// keyed by pasteboard types, allowing it to cross concurrency boundaries safely. -struct SendablePasteboardItem: Sendable { - let dataMap: [NSPasteboard.PasteboardType: Data] -} + /// A thread-safe, value-type representation of a pasteboard item containing its data + /// keyed by pasteboard types, allowing it to cross concurrency boundaries safely. + struct SendablePasteboardItem: Sendable { + let dataMap: [NSPasteboard.PasteboardType: Data] + } -/// A best-effort snapshot of the whole pasteboard, taken before a paste so the -/// user's contents can be put back afterwards. -/// -/// The distinction that matters: this type is only ever produced when the -/// pasteboard was *readable*. `SystemClipboard.snapshot()` returns `nil` when the -/// read itself failed, so a failure can never be mistaken for "the clipboard was -/// empty" — conflating those two is what made the restore clear the user's -/// clipboard instead of restoring it. -/// -/// Known, inherent limitation: pasteboard data can be *promised* (provided lazily -/// by the owning app on demand). A promise cannot be copied, only materialized, and -/// an app may decline. Types that decline are absent from `dataMap`, so a restore -/// of promise-backed contents is a best-effort downgrade, not a byte-faithful -/// round trip — `plainText` exists to keep at least the text when that happens. -struct PasteboardSnapshot: Sendable { - /// One entry per item the pasteboard held, in order. An entry with an empty - /// `dataMap` means the item existed but none of its representations could be - /// materialized — distinct from the pasteboard having held no items at all, - /// which is `items.isEmpty`. - let items: [SendablePasteboardItem] - /// The pasteboard's plain-string flavor, kept separately as a restore floor for - /// when no item's representations could be materialized. - let plainText: String? -} + /// A best-effort snapshot of the whole pasteboard, taken before a paste so the + /// user's contents can be put back afterwards. + /// + /// The distinction that matters: this type is only ever produced when the + /// pasteboard was *readable*. `SystemClipboard.snapshot()` returns `nil` when the + /// read itself failed, so a failure can never be mistaken for "the clipboard was + /// empty" — conflating those two is what made the restore clear the user's + /// clipboard instead of restoring it. + /// + /// Known, inherent limitation: pasteboard data can be *promised* (provided lazily + /// by the owning app on demand). A promise cannot be copied, only materialized, and + /// an app may decline. Types that decline are absent from `dataMap`, so a restore + /// of promise-backed contents is a best-effort downgrade, not a byte-faithful + /// round trip — `plainText` exists to keep at least the text when that happens. + struct PasteboardSnapshot: Sendable { + /// One entry per item the pasteboard held, in order. An entry with an empty + /// `dataMap` means the item existed but none of its representations could be + /// materialized — distinct from the pasteboard having held no items at all, + /// which is `items.isEmpty`. + let items: [SendablePasteboardItem] + /// The pasteboard's plain-string flavor, kept separately as a restore floor for + /// when no item's representations could be materialized. + let plainText: String? + } -/// The two clipboard operations `KeyInjector` actually performs around a paste — -/// a plain overwrite, or an overwrite that can later restore what it displaced — -/// rather than exposing NSPasteboard's raw change-count/multi-item bookkeeping. -/// A seam so tests substitute a trivial in-memory fake that never has to -/// re-derive the pasteboard's change-count semantics to stay faithful. -protocol ClipboardAccess: Sendable { - /// Overwrite the clipboard with a single plain-string item, discarding the - /// previous contents. The degraded paste paths call this to leave the - /// transcript on the clipboard for a manual paste. - func write(_ text: String) - /// Overwrite the clipboard with `text`, returning an action that restores the - /// previous contents — but only if nothing else has written to the clipboard - /// in the meantime (so a user copy during the paste-settle window survives). - /// Call the returned action once the paste has settled. - func writeAndPrepareRestore(_ text: String) -> @Sendable () -> Void -} + /// The two clipboard operations `KeyInjector` actually performs around a paste — + /// a plain overwrite, or an overwrite that can later restore what it displaced — + /// rather than exposing NSPasteboard's raw change-count/multi-item bookkeeping. + /// A seam so tests substitute a trivial in-memory fake that never has to + /// re-derive the pasteboard's change-count semantics to stay faithful. + protocol ClipboardAccess: Sendable { + /// Overwrite the clipboard with a single plain-string item, discarding the + /// previous contents. The degraded paste paths call this to leave the + /// transcript on the clipboard for a manual paste. + func write(_ text: String) + /// Overwrite the clipboard with `text`, returning an action that restores the + /// previous contents — but only if nothing else has written to the clipboard + /// in the meantime (so a user copy during the paste-settle window survives). + /// Call the returned action once the paste has settled. + func writeAndPrepareRestore(_ text: String) -> @Sendable () -> Void + } -/// `ClipboardAccess` backed by the real `NSPasteboard.general`. The change-count -/// comparison that gates the deferred restore lives here, behind the seam, so a -/// fake never re-implements it. -struct SystemClipboard: ClipboardAccess { - func write(_ text: String) { setString(text) } + /// `ClipboardAccess` backed by the real `NSPasteboard.general`. The change-count + /// comparison that gates the deferred restore lives here, behind the seam, so a + /// fake never re-implements it. + struct SystemClipboard: ClipboardAccess { + func write(_ text: String) { setString(text) } - func writeAndPrepareRestore(_ text: String) -> @Sendable () -> Void { - let saved = snapshot() - setString(text) - // Snapshot the change count our own write produced. If anything else writes - // to the pasteboard before the restore fires (e.g. the user copies - // something), the count moves and the restore leaves their newer contents - // alone rather than clobbering them with the stale pre-paste snapshot. - let ourChangeCount = changeCount - return { [self] in - guard changeCount == ourChangeCount else { return } - // A nil snapshot means the pasteboard could not be read at all. There is - // nothing to put back, so leave the transcript on the clipboard (the same - // degraded-but-recoverable outcome as the `.noTarget` path) rather than - // clearing the user's clipboard to nothing. - guard let saved else { return } - restore(saved) + func writeAndPrepareRestore(_ text: String) -> @Sendable () -> Void { + let saved = snapshot() + setString(text) + // Snapshot the change count our own write produced. If anything else writes + // to the pasteboard before the restore fires (e.g. the user copies + // something), the count moves and the restore leaves their newer contents + // alone rather than clobbering them with the stale pre-paste snapshot. + let ourChangeCount = changeCount + return { [self] in + guard changeCount == ourChangeCount else { return } + // A nil snapshot means the pasteboard could not be read at all. There is + // nothing to put back, so leave the transcript on the clipboard (the same + // degraded-but-recoverable outcome as the `.noTarget` path) rather than + // clearing the user's clipboard to nothing. + guard let saved else { return } + restore(saved) + } } - } - // MARK: - NSPasteboard building blocks (also exercised directly by SystemClipboardTests) + // MARK: - NSPasteboard building blocks (also exercised directly by SystemClipboardTests) - var changeCount: Int { NSPasteboard.general.changeCount } + var changeCount: Int { NSPasteboard.general.changeCount } - /// Snapshots the pasteboard, or `nil` when it can't be read at all - /// (`pasteboardItems` is documented to return nil on error). Callers must treat - /// nil as "don't restore" — never as an empty clipboard. - func snapshot() -> PasteboardSnapshot? { - let pasteboard = NSPasteboard.general - guard let items = pasteboard.pasteboardItems else { return nil } - let captured = items.map { item in - var dataMap: [NSPasteboard.PasteboardType: Data] = [:] - for type in item.types { - // A nil read is a promised representation the owning app declined to - // materialize; record what we did get and let `plainText` be the floor. - if let data = item.data(forType: type) { - dataMap[type] = data + /// Snapshots the pasteboard, or `nil` when it can't be read at all + /// (`pasteboardItems` is documented to return nil on error). Callers must treat + /// nil as "don't restore" — never as an empty clipboard. + func snapshot() -> PasteboardSnapshot? { + let pasteboard = NSPasteboard.general + guard let items = pasteboard.pasteboardItems else { return nil } + let captured = items.map { item in + var dataMap: [NSPasteboard.PasteboardType: Data] = [:] + for type in item.types { + // A nil read is a promised representation the owning app declined to + // materialize; record what we did get and let `plainText` be the floor. + if let data = item.data(forType: type) { + dataMap[type] = data + } } + return SendablePasteboardItem(dataMap: dataMap) } - return SendablePasteboardItem(dataMap: dataMap) + return PasteboardSnapshot(items: captured, plainText: pasteboard.string(forType: .string)) } - return PasteboardSnapshot(items: captured, plainText: pasteboard.string(forType: .string)) - } - - func setString(_ text: String) { - let pasteboard = NSPasteboard.general - pasteboard.clearContents() - pasteboard.setString(text, forType: .string) - } - func restore(_ saved: PasteboardSnapshot) { - let pasteboard = NSPasteboard.general - - // The pasteboard genuinely held nothing, so restoring it means emptying it. - // Safe to clear because the snapshot succeeded — a *failed* read is nil and - // never reaches here. - guard !saved.items.isEmpty else { + func setString(_ text: String) { + let pasteboard = NSPasteboard.general pasteboard.clearContents() - return + pasteboard.setString(text, forType: .string) } - // Build the items BEFORE clearing. Clearing first and then discovering there - // is nothing to write is how the user's clipboard got destroyed whenever a - // snapshot came back degraded. - let rebuilt = saved.items.compactMap { item -> NSPasteboardItem? in - guard !item.dataMap.isEmpty else { return nil } - let pasteboardItem = NSPasteboardItem() - for (type, data) in item.dataMap { - pasteboardItem.setData(data, forType: type) + func restore(_ saved: PasteboardSnapshot) { + let pasteboard = NSPasteboard.general + + // The pasteboard genuinely held nothing, so restoring it means emptying it. + // Safe to clear because the snapshot succeeded — a *failed* read is nil and + // never reaches here. + guard !saved.items.isEmpty else { + pasteboard.clearContents() + return } - return pasteboardItem - } - if !rebuilt.isEmpty { - pasteboard.clearContents() - // `writeObjects` can refuse the batch; fall through to the text floor - // rather than leaving the pasteboard empty. - if pasteboard.writeObjects(rebuilt) { return } - } + // Build the items BEFORE clearing. Clearing first and then discovering there + // is nothing to write is how the user's clipboard got destroyed whenever a + // snapshot came back degraded. + let rebuilt = saved.items.compactMap { item -> NSPasteboardItem? in + guard !item.dataMap.isEmpty else { return nil } + let pasteboardItem = NSPasteboardItem() + for (type, data) in item.dataMap { + pasteboardItem.setData(data, forType: type) + } + return pasteboardItem + } - // Either nothing was materializable, or the write above was refused. Put the - // text back if we have it. - // - // Precise about the one case this does NOT recover: if items DID materialize, - // `writeObjects` refused them, and there was no plain-string flavor, the - // pasteboard has already been cleared and stays empty. That is not gated on - // `plainText` being non-nil on purpose — skipping the item write whenever - // there's no text flavor would refuse to restore an image-only or - // file-only clipboard, which is a far more common clipboard than a refused - // batch write. `writeObjects` failing on a freshly-cleared pasteboard holding - // valid `NSPasteboardItem`s is a programming error, not a runtime condition, - // and NSPasteboard offers no way to test a write before clearing. - if let plainText = saved.plainText { - pasteboard.clearContents() - pasteboard.setString(plainText, forType: .string) + if !rebuilt.isEmpty { + pasteboard.clearContents() + // `writeObjects` can refuse the batch; fall through to the text floor + // rather than leaving the pasteboard empty. + if pasteboard.writeObjects(rebuilt) { return } + } + + // Either nothing was materializable, or the write above was refused. Put the + // text back if we have it. + // + // Precise about the one case this does NOT recover: if items DID materialize, + // `writeObjects` refused them, and there was no plain-string flavor, the + // pasteboard has already been cleared and stays empty. That is not gated on + // `plainText` being non-nil on purpose — skipping the item write whenever + // there's no text flavor would refuse to restore an image-only or + // file-only clipboard, which is a far more common clipboard than a refused + // batch write. `writeObjects` failing on a freshly-cleared pasteboard holding + // valid `NSPasteboardItem`s is a programming error, not a runtime condition, + // and NSPasteboard offers no way to test a write before clearing. + if let plainText = saved.plainText { + pasteboard.clearContents() + pasteboard.setString(plainText, forType: .string) + } } } -} +#endif diff --git a/Sources/BlurtEngine/Permissions/PermissionStatus.swift b/Sources/BlurtEngine/Permissions/PermissionStatus.swift new file mode 100644 index 00000000..5f1e87d1 --- /dev/null +++ b/Sources/BlurtEngine/Permissions/PermissionStatus.swift @@ -0,0 +1,26 @@ +/// The grants a Blurt install needs, as one reading. A pure value — two Bools +/// and their derivations — consumed by the portable `SetupReadiness` policy, +/// which is why it lives apart from `PermissionsChecker`: only *reading* the +/// grants needs the macOS-only TCC probes, and the rule that decides what +/// "ready" means must build on every platform the engine does. +public struct PermissionStatus: Equatable, Sendable { + public let microphone: Bool + public let accessibility: Bool + + public init(microphone: Bool, accessibility: Bool) { + self.microphone = microphone + self.accessibility = accessibility + } + + public var allGranted: Bool { microphone && accessibility } + + /// True when `previous` had every permission and this reading no longer does — + /// i.e. the user revoked one in System Settings, possibly while no window was + /// open. The shell reacts by pulling them back into onboarding rather than + /// leaving a dead overlay, so this is a behavioural edge worth a test; it lives + /// next to `allGranted`, the derivation it's built from, rather than being + /// spelled out at the one call site that watches for it. + public func lostGrant(since previous: PermissionStatus) -> Bool { + previous.allGranted && !allGranted + } +} diff --git a/Sources/BlurtEngine/Permissions/PermissionsChecker.swift b/Sources/BlurtEngine/Permissions/PermissionsChecker.swift index 190cb6ff..1c06b8b1 100644 --- a/Sources/BlurtEngine/Permissions/PermissionsChecker.swift +++ b/Sources/BlurtEngine/Permissions/PermissionsChecker.swift @@ -1,115 +1,95 @@ -import AVFoundation -import AppKit -import ApplicationServices -import Foundation +#if os(macOS) + import AVFoundation + import AppKit + import ApplicationServices + import Foundation -public struct PermissionStatus: Equatable, Sendable { - public let microphone: Bool - public let accessibility: Bool - - public init(microphone: Bool, accessibility: Bool) { - self.microphone = microphone - self.accessibility = accessibility - } - - public var allGranted: Bool { microphone && accessibility } - - /// True when `previous` had every permission and this reading no longer does — - /// i.e. the user revoked one in System Settings, possibly while no window was - /// open. The shell reacts by pulling them back into onboarding rather than - /// leaving a dead overlay, so this is a behavioural edge worth a test; it lives - /// next to `allGranted`, the derivation it's built from, rather than being - /// spelled out at the one call site that watches for it. - public func lostGrant(since previous: PermissionStatus) -> Bool { - previous.allGranted && !allGranted - } -} - -public enum PermissionsChecker { - /// The current grant state, read without prompting. - public static func check() -> PermissionStatus { - check(micGranted: { micGranted() }, axTrusted: { AXIsProcessTrusted() }) - } + public enum PermissionsChecker { + /// The current grant state, read without prompting. + public static func check() -> PermissionStatus { + check(micGranted: { micGranted() }, axTrusted: { AXIsProcessTrusted() }) + } - /// The composition `check()` performs, with both probes injected. The probes - /// themselves read process-global TCC state the test host can't set, so with - /// them hard-coded the only assertable claim about `check()` was that it - /// doesn't crash — and the test that made it ended up restating `allGranted`'s - /// own definition instead. Injected, the wiring is assertable: each probe's - /// answer has to land in its own field, so a swapped pair fails. - static func check(micGranted: () -> Bool, axTrusted: () -> Bool) -> PermissionStatus { - PermissionStatus( - microphone: micGranted(), - accessibility: axTrusted() - ) - } + /// The composition `check()` performs, with both probes injected. The probes + /// themselves read process-global TCC state the test host can't set, so with + /// them hard-coded the only assertable claim about `check()` was that it + /// doesn't crash — and the test that made it ended up restating `allGranted`'s + /// own definition instead. Injected, the wiring is assertable: each probe's + /// answer has to land in its own field, so a swapped pair fails. + static func check(micGranted: () -> Bool, axTrusted: () -> Bool) -> PermissionStatus { + PermissionStatus( + microphone: micGranted(), + accessibility: axTrusted() + ) + } - private static func micGranted() -> Bool { - AVAudioApplication.shared.recordPermission == .granted - } + private static func micGranted() -> Bool { + AVAudioApplication.shared.recordPermission == .granted + } - public static func requestMicrophone() async -> Bool { - await AVAudioApplication.requestRecordPermission() - } + public static func requestMicrophone() async -> Bool { + await AVAudioApplication.requestRecordPermission() + } - /// Opens System Settings to Privacy › Microphone. The fallback when the in-app - /// `requestMicrophone()` prompt can't grant access — the user declined it, or - /// the system won't re-present it once the status is determined — so the - /// Microphone row still has a way forward, mirroring the Accessibility row's - /// "open Settings" flow rather than being a dead-end button. - @MainActor - public static func openMicrophoneSettings() { - guard - let url = URL( - string: - "x-apple.systempreferences:com.apple.settings.PrivacySecurity.extension?Privacy_Microphone") - else { return } - NSWorkspace.shared.open(url) - } + /// Opens System Settings to Privacy › Microphone. The fallback when the in-app + /// `requestMicrophone()` prompt can't grant access — the user declined it, or + /// the system won't re-present it once the status is determined — so the + /// Microphone row still has a way forward, mirroring the Accessibility row's + /// "open Settings" flow rather than being a dead-end button. + @MainActor + public static func openMicrophoneSettings() { + guard + let url = URL( + string: + "x-apple.systempreferences:com.apple.settings.PrivacySecurity.extension?Privacy_Microphone") + else { return } + NSWorkspace.shared.open(url) + } - /// Trigger the Accessibility permission flow: - /// 1. Make a *real* AX-protected call against another app's UI tree — - /// this is what reliably registers Blurt in TCC on macOS 26. - /// `AXIsProcessTrustedWithOptions` and the system-wide query don't - /// appear to count as "activity" for registration purposes. - /// 2. Show the trust prompt with an "Open System Settings" button. - @MainActor - public static func openAccessibilitySettings() { - forceAccessibilityActivity() - // The literal spells out `kAXTrustedCheckOptionPrompt`'s value: the SDK - // header declares the constant as a non-const `extern CFStringRef`, so it - // imports into Swift as a global `var` that strict concurrency refuses to - // reference ("shared mutable state") — the framework constant cannot be - // used here. - let prompt: NSDictionary = ["AXTrustedCheckOptionPrompt": true] - _ = AXIsProcessTrustedWithOptions(prompt) - } + /// Trigger the Accessibility permission flow: + /// 1. Make a *real* AX-protected call against another app's UI tree — + /// this is what reliably registers Blurt in TCC on macOS 26. + /// `AXIsProcessTrustedWithOptions` and the system-wide query don't + /// appear to count as "activity" for registration purposes. + /// 2. Show the trust prompt with an "Open System Settings" button. + @MainActor + public static func openAccessibilitySettings() { + forceAccessibilityActivity() + // The literal spells out `kAXTrustedCheckOptionPrompt`'s value: the SDK + // header declares the constant as a non-const `extern CFStringRef`, so it + // imports into Swift as a global `var` that strict concurrency refuses to + // reference ("shared mutable state") — the framework constant cannot be + // used here. + let prompt: NSDictionary = ["AXTrustedCheckOptionPrompt": true] + _ = AXIsProcessTrustedWithOptions(prompt) + } - /// Makes a *real* AX-protected call against another app's UI tree — what - /// reliably registers Blurt in TCC on macOS 26, and the no-prompt first step - /// of `openAccessibilitySettings`. Internal rather than private so the engine - /// tests can exercise it directly, without the trust prompt that - /// `openAccessibilitySettings` adds on top. - @MainActor - static func forceAccessibilityActivity() { - // AX reads against our own pid are NOT TCC-protected — apps can always - // read their own UI. We must target a different process so tccd sees - // a denied request and registers Blurt in the Accessibility list. - // `frontmostApplication` is Blurt itself when this runs from a - // button in our own window, which is why prior versions never worked. - let myPid = ProcessInfo.processInfo.processIdentifier - let others = NSWorkspace.shared.runningApplications.filter { - $0.processIdentifier > 0 && $0.processIdentifier != myPid + /// Makes a *real* AX-protected call against another app's UI tree — what + /// reliably registers Blurt in TCC on macOS 26, and the no-prompt first step + /// of `openAccessibilitySettings`. Internal rather than private so the engine + /// tests can exercise it directly, without the trust prompt that + /// `openAccessibilitySettings` adds on top. + @MainActor + static func forceAccessibilityActivity() { + // AX reads against our own pid are NOT TCC-protected — apps can always + // read their own UI. We must target a different process so tccd sees + // a denied request and registers Blurt in the Accessibility list. + // `frontmostApplication` is Blurt itself when this runs from a + // button in our own window, which is why prior versions never worked. + let myPid = ProcessInfo.processInfo.processIdentifier + let others = NSWorkspace.shared.runningApplications.filter { + $0.processIdentifier > 0 && $0.processIdentifier != myPid + } + let target = + others.first(where: { $0.bundleIdentifier == "com.apple.finder" }) + ?? others.first(where: { $0.activationPolicy == .regular }) + ?? others.first + guard let pid = target?.processIdentifier else { return } + let element = AXUIElementCreateApplication(pid) + var value: CFTypeRef? + _ = AXUIElementCopyAttributeValue( + element, kAXFocusedUIElementAttribute as CFString, &value) } - let target = - others.first(where: { $0.bundleIdentifier == "com.apple.finder" }) - ?? others.first(where: { $0.activationPolicy == .regular }) - ?? others.first - guard let pid = target?.processIdentifier else { return } - let element = AXUIElementCreateApplication(pid) - var value: CFTypeRef? - _ = AXUIElementCopyAttributeValue( - element, kAXFocusedUIElementAttribute as CFString, &value) - } -} + } +#endif diff --git a/Sources/BlurtEngine/Permissions/PermissionsReset.swift b/Sources/BlurtEngine/Permissions/PermissionsReset.swift index 15216a15..693d5c97 100644 --- a/Sources/BlurtEngine/Permissions/PermissionsReset.swift +++ b/Sources/BlurtEngine/Permissions/PermissionsReset.swift @@ -1,83 +1,85 @@ -import Foundation -import os +#if os(macOS) + import Foundation + import os -/// Clears the TCC grants an install holds, by running `tccutil reset ` -/// against a bundle id. The in-process half of what `scripts/reset-install.sh` -/// does from a terminal, so the Settings window's reset can offer the same thing -/// without one. -/// -/// Resetting a bundle's *own* grants needs no admin rights, which is what makes -/// this usable from the app at all. It is still a system call with no dry run: -/// pass the **running** bundle id (`Bundle.main.bundleIdentifier`), never -/// `HostIdentity.current.subsystem` — debug builds ship under -/// `dev.alex.blurt.dev` (see `project.yml`), so the constant would have a dev -/// build clearing the released Blurt's grants, the one app whose permissions -/// this process has no business touching. -public enum PermissionsReset { - private static let log = HostIdentity.current.logger("PermissionsReset") - - /// The TCC services a Blurt install can hold a grant under — the set - /// `resetAll` sweeps, and the same three `scripts/reset-install.sh` lists - /// (bash can't read this enum, so the two are kept in step by hand). + /// Clears the TCC grants an install holds, by running `tccutil reset ` + /// against a bundle id. The in-process half of what `scripts/reset-install.sh` + /// does from a terminal, so the Settings window's reset can offer the same thing + /// without one. /// - /// Raw values are `tccutil`'s own service names, which are not all the names - /// System Settings shows. - public enum Service: String, CaseIterable, Sendable { - /// Typing into other apps, and the focused-field reads that feed the paste - /// path (`KeyInjector`, `FocusCapture`). - case accessibility = "Accessibility" - /// Recording (`MicCapture`). - case microphone = "Microphone" - /// Input Monitoring — the `CGEventTap` behind the hold-to-dictate hotkey - /// (`DictationKeyTap`). `tccutil` knows it by its internal name, - /// `ListenEvent`. - case inputMonitoring = "ListenEvent" - } + /// Resetting a bundle's *own* grants needs no admin rights, which is what makes + /// this usable from the app at all. It is still a system call with no dry run: + /// pass the **running** bundle id (`Bundle.main.bundleIdentifier`), never + /// `HostIdentity.current.subsystem` — debug builds ship under + /// `dev.alex.blurt.dev` (see `project.yml`), so the constant would have a dev + /// build clearing the released Blurt's grants, the one app whose permissions + /// this process has no business touching. + public enum PermissionsReset { + private static let log = HostIdentity.current.logger("PermissionsReset") + + /// The TCC services a Blurt install can hold a grant under — the set + /// `resetAll` sweeps, and the same three `scripts/reset-install.sh` lists + /// (bash can't read this enum, so the two are kept in step by hand). + /// + /// Raw values are `tccutil`'s own service names, which are not all the names + /// System Settings shows. + public enum Service: String, CaseIterable, Sendable { + /// Typing into other apps, and the focused-field reads that feed the paste + /// path (`KeyInjector`, `FocusCapture`). + case accessibility = "Accessibility" + /// Recording (`MicCapture`). + case microphone = "Microphone" + /// Input Monitoring — the `CGEventTap` behind the hold-to-dictate hotkey + /// (`DictationKeyTap`). `tccutil` knows it by its internal name, + /// `ListenEvent`. + case inputMonitoring = "ListenEvent" + } - /// Clears `service` for `bundleID`. Returns whether `tccutil` exited 0 — a - /// non-zero exit (or a launch failure) is reported rather than thrown, since - /// every caller's answer to a failed reset is the same: say so, and leave the - /// rest of the sweep to run. - @discardableResult - public static func reset(_ service: Service, bundleID: String) -> Bool { - let proc = Process() - proc.executableURL = URL(fileURLWithPath: "/usr/bin/tccutil") - proc.arguments = ["reset", service.rawValue, bundleID] - do { - try proc.run() - proc.waitUntilExit() - let ok = proc.terminationStatus == 0 - if !ok { - log.warning( - "tccutil reset \(service.rawValue, privacy: .public) exited \(proc.terminationStatus)") + /// Clears `service` for `bundleID`. Returns whether `tccutil` exited 0 — a + /// non-zero exit (or a launch failure) is reported rather than thrown, since + /// every caller's answer to a failed reset is the same: say so, and leave the + /// rest of the sweep to run. + @discardableResult + public static func reset(_ service: Service, bundleID: String) -> Bool { + let proc = Process() + proc.executableURL = URL(fileURLWithPath: "/usr/bin/tccutil") + proc.arguments = ["reset", service.rawValue, bundleID] + do { + try proc.run() + proc.waitUntilExit() + let ok = proc.terminationStatus == 0 + if !ok { + log.warning( + "tccutil reset \(service.rawValue, privacy: .public) exited \(proc.terminationStatus)") + } + return ok + } catch { + let reason = error.localizedDescription + log.error( + "tccutil reset \(service.rawValue, privacy: .public) failed to launch: \(reason, privacy: .public)") + return false } - return ok - } catch { - let reason = error.localizedDescription - log.error( - "tccutil reset \(service.rawValue, privacy: .public) failed to launch: \(reason, privacy: .public)") - return false } - } - /// The services a full reset sweeps. Spelled out case by case rather than - /// taken from `allCases` because Periphery can't follow a case that is only - /// ever reached through `allCases` and reports it as dead; - /// `PermissionsResetTests` pins this list against `allCases`, so a service - /// added to the enum and forgotten here fails there rather than silently - /// surviving every "full" reset. - static let sweep: [Service] = [.accessibility, .microphone, .inputMonitoring] + /// The services a full reset sweeps. Spelled out case by case rather than + /// taken from `allCases` because Periphery can't follow a case that is only + /// ever reached through `allCases` and reports it as dead; + /// `PermissionsResetTests` pins this list against `allCases`, so a service + /// added to the enum and forgotten here fails there rather than silently + /// surviving every "full" reset. + static let sweep: [Service] = [.accessibility, .microphone, .inputMonitoring] - /// Clears every service in `sweep` for `bundleID`, returning true only when - /// all of them succeeded. Every service is attempted even after one fails: a - /// half-reset install is the state this exists to get *out* of, so stopping at - /// the first failure would leave more behind than reporting it does. - @discardableResult - static func resetAll(bundleID: String) -> Bool { - var allCleared = true - for service in sweep where !reset(service, bundleID: bundleID) { - allCleared = false + /// Clears every service in `sweep` for `bundleID`, returning true only when + /// all of them succeeded. Every service is attempted even after one fails: a + /// half-reset install is the state this exists to get *out* of, so stopping at + /// the first failure would leave more behind than reporting it does. + @discardableResult + static func resetAll(bundleID: String) -> Bool { + var allCleared = true + for service in sweep where !reset(service, bundleID: bundleID) { + allCleared = false + } + return allCleared } - return allCleared } -} +#endif diff --git a/Sources/BlurtEngine/Permissions/SigningIdentity.swift b/Sources/BlurtEngine/Permissions/SigningIdentity.swift index c12e0bf2..67424cf8 100644 --- a/Sources/BlurtEngine/Permissions/SigningIdentity.swift +++ b/Sources/BlurtEngine/Permissions/SigningIdentity.swift @@ -1,94 +1,96 @@ -import Security +#if os(macOS) + import Security -/// The integration adapter for the signing-identity migration: reads the -/// identity this process's signature pins into its designated requirement. Kept -/// separate from the pure `SigningIdentityMigration` so the decision logic stays -/// testable and this `Security` handshake stays thin. Clearing the stale grant -/// the migration decides on is `PermissionsReset`'s half. -public enum SigningIdentity { - /// Namespace marker on a recorded identity. Every build before this one recorded - /// a bare Team ID (10 alphanumerics, no colon), so the prefix keeps the two - /// shapes disjoint — a marker left by an older build can never accidentally - /// compare equal to a requirement — and makes a dumped `defaults read` value - /// self-describing. - static let requirementPrefix = "dr:" + /// The integration adapter for the signing-identity migration: reads the + /// identity this process's signature pins into its designated requirement. Kept + /// separate from the pure `SigningIdentityMigration` so the decision logic stays + /// testable and this `Security` handshake stays thin. Clearing the stale grant + /// the migration decides on is `PermissionsReset`'s half. + public enum SigningIdentity { + /// Namespace marker on a recorded identity. Every build before this one recorded + /// a bare Team ID (10 alphanumerics, no colon), so the prefix keeps the two + /// shapes disjoint — a marker left by an older build can never accidentally + /// compare equal to a requirement — and makes a dumped `defaults read` value + /// self-describing. + static let requirementPrefix = "dr:" - /// Whatever an Accessibility grant taken *right now* would be pinned to: this - /// binary's **designated requirement**, serialized. - /// - /// The DR is what `tccd` stores alongside a grant and re-checks the running - /// binary against, so it is the identity — not a proxy for it. That distinction - /// is the whole bug this used to have: it recorded the *Team ID*, and the two - /// ways Blurt is team-signed carry the same team while pinning different - /// requirements. - /// - /// - **Dev builds** (`Apple Development`, re-signed by the `project.yml` - /// post-build install) pin an explicit team-based requirement: - /// `identifier … and anchor apple generic and certificate leaf[subject.OU] = `. - /// Cert rotation inside the team leaves that string byte-identical, which is - /// why the explicit requirement is stamped in the first place. - /// - **Releases** (`Developer ID`, `scripts/release-build.sh`) carry codesign's - /// *default* requirement, which additionally pins the leaf cert's Common Name - /// and the Developer ID marker OIDs — so re-issuing that certificate moves the - /// requirement and orphans every installed user's grant. - /// - /// `nil` for **unsigned or ad-hoc code**, which the migration reads as "no - /// action". Ad-hoc signatures pin a cdhash, so honouring them would mean every - /// `uitest.sh` / `check.sh` run — each one a throwaway ad-hoc binary under the - /// debug bundle id — resetting the developer's own Blurt Dev grant. Refusing - /// them here makes that structural rather than a flag the call site has to - /// remember to pass. The cost is a contributor who builds ad-hoc *and* copies - /// the result to /Applications by hand: they re-grant per rebuild, and - /// `tccutil reset Accessibility dev.alex.blurt.dev` is the way out. - public static func current() -> String? { - guard let code = staticCodeForSelf() else { return nil } - // A team identifier is present exactly when the signature isn't ad-hoc, so it - // is the probe for that carve-out — never the recorded value. - guard teamIdentifier(of: code) != nil else { return nil } - guard let requirement = designatedRequirement(of: code) else { return nil } - return requirementPrefix + requirement - } + /// Whatever an Accessibility grant taken *right now* would be pinned to: this + /// binary's **designated requirement**, serialized. + /// + /// The DR is what `tccd` stores alongside a grant and re-checks the running + /// binary against, so it is the identity — not a proxy for it. That distinction + /// is the whole bug this used to have: it recorded the *Team ID*, and the two + /// ways Blurt is team-signed carry the same team while pinning different + /// requirements. + /// + /// - **Dev builds** (`Apple Development`, re-signed by the `project.yml` + /// post-build install) pin an explicit team-based requirement: + /// `identifier … and anchor apple generic and certificate leaf[subject.OU] = `. + /// Cert rotation inside the team leaves that string byte-identical, which is + /// why the explicit requirement is stamped in the first place. + /// - **Releases** (`Developer ID`, `scripts/release-build.sh`) carry codesign's + /// *default* requirement, which additionally pins the leaf cert's Common Name + /// and the Developer ID marker OIDs — so re-issuing that certificate moves the + /// requirement and orphans every installed user's grant. + /// + /// `nil` for **unsigned or ad-hoc code**, which the migration reads as "no + /// action". Ad-hoc signatures pin a cdhash, so honouring them would mean every + /// `uitest.sh` / `check.sh` run — each one a throwaway ad-hoc binary under the + /// debug bundle id — resetting the developer's own Blurt Dev grant. Refusing + /// them here makes that structural rather than a flag the call site has to + /// remember to pass. The cost is a contributor who builds ad-hoc *and* copies + /// the result to /Applications by hand: they re-grant per rebuild, and + /// `tccutil reset Accessibility dev.alex.blurt.dev` is the way out. + public static func current() -> String? { + guard let code = staticCodeForSelf() else { return nil } + // A team identifier is present exactly when the signature isn't ad-hoc, so it + // is the probe for that carve-out — never the recorded value. + guard teamIdentifier(of: code) != nil else { return nil } + guard let requirement = designatedRequirement(of: code) else { return nil } + return requirementPrefix + requirement + } - /// The on-disk code object backing this process, or `nil` when any step of the - /// `Security` handshake fails. - static func staticCodeForSelf() -> SecStaticCode? { - var code: SecCode? - guard SecCodeCopySelf(SecCSFlags(), &code) == errSecSuccess, let code else { return nil } - var staticCode: SecStaticCode? - guard SecCodeCopyStaticCode(code, SecCSFlags(), &staticCode) == errSecSuccess, let staticCode - else { return nil } - return staticCode - } + /// The on-disk code object backing this process, or `nil` when any step of the + /// `Security` handshake fails. + static func staticCodeForSelf() -> SecStaticCode? { + var code: SecCode? + guard SecCodeCopySelf(SecCSFlags(), &code) == errSecSuccess, let code else { return nil } + var staticCode: SecStaticCode? + guard SecCodeCopyStaticCode(code, SecCSFlags(), &staticCode) == errSecSuccess, let staticCode + else { return nil } + return staticCode + } - /// The signature's team identifier — `nil` for unsigned or ad-hoc code. - private static func teamIdentifier(of code: SecStaticCode) -> String? { - var info: CFDictionary? - let flags = SecCSFlags(rawValue: kSecCSSigningInformation) - guard SecCodeCopySigningInformation(code, flags, &info) == errSecSuccess, - let dict = info as? [String: Any] - else { return nil } - return dict[kSecCodeInfoTeamIdentifier as String] as? String - } + /// The signature's team identifier — `nil` for unsigned or ad-hoc code. + private static func teamIdentifier(of code: SecStaticCode) -> String? { + var info: CFDictionary? + let flags = SecCSFlags(rawValue: kSecCSSigningInformation) + guard SecCodeCopySigningInformation(code, flags, &info) == errSecSuccess, + let dict = info as? [String: Any] + else { return nil } + return dict[kSecCodeInfoTeamIdentifier as String] as? String + } - /// The designated requirement, serialized to the same text `codesign -d -r-` - /// prints. Read through `SecCodeCopyDesignatedRequirement` rather than the - /// `kSecCodeInfoDesignatedRequirement` key of the signing-information - /// dictionary: that dictionary is `[String: Any]`, and narrowing an `Any` back - /// to a CoreFoundation type needs a cast the compiler flags as always-succeeding - /// (or a banned force cast). This spelling is typed end to end. - /// - /// Takes the code object rather than reading `self` so the tests can point it at - /// a binary whose requirement is known — the whole `Security` handshake is the - /// one part of this file that isn't pure logic, and the test host's own - /// signature varies by how the suite was launched. - static func designatedRequirement(of code: SecStaticCode) -> String? { - var requirement: SecRequirement? - guard SecCodeCopyDesignatedRequirement(code, SecCSFlags(), &requirement) == errSecSuccess, - let requirement - else { return nil } - var text: CFString? - guard SecRequirementCopyString(requirement, SecCSFlags(), &text) == errSecSuccess, let text - else { return nil } - return text as String + /// The designated requirement, serialized to the same text `codesign -d -r-` + /// prints. Read through `SecCodeCopyDesignatedRequirement` rather than the + /// `kSecCodeInfoDesignatedRequirement` key of the signing-information + /// dictionary: that dictionary is `[String: Any]`, and narrowing an `Any` back + /// to a CoreFoundation type needs a cast the compiler flags as always-succeeding + /// (or a banned force cast). This spelling is typed end to end. + /// + /// Takes the code object rather than reading `self` so the tests can point it at + /// a binary whose requirement is known — the whole `Security` handshake is the + /// one part of this file that isn't pure logic, and the test host's own + /// signature varies by how the suite was launched. + static func designatedRequirement(of code: SecStaticCode) -> String? { + var requirement: SecRequirement? + guard SecCodeCopyDesignatedRequirement(code, SecCSFlags(), &requirement) == errSecSuccess, + let requirement + else { return nil } + var text: CFString? + guard SecRequirementCopyString(requirement, SecCSFlags(), &text) == errSecSuccess, let text + else { return nil } + return text as String + } } -} +#endif diff --git a/Sources/BlurtEngine/Pipeline/DictationLog.swift b/Sources/BlurtEngine/Pipeline/DictationLog.swift index 748ab058..08a83e0d 100644 --- a/Sources/BlurtEngine/Pipeline/DictationLog.swift +++ b/Sources/BlurtEngine/Pipeline/DictationLog.swift @@ -31,7 +31,7 @@ public enum DictationLog { /// chunk is *trimmed* and joined to the history; /// this records it raw. The difference is load-bearing twice over. Its trailing /// whitespace is the entire input to the paste's leading-separator decision - /// (`KeyInjector.withLeadingSeparator` branches on `prior.last.isWhitespace`), + /// (`InsertionSeparator.withLeadingSeparator` branches on `prior.last.isWhitespace`), /// so a spacing bug is undiagnosable from a trimmed copy. And a nil here /// distinguishes "no prior text was read" from "the prompt ends with the /// newest recent dictation", which `sttPrompt` alone cannot say. diff --git a/Sources/BlurtEngine/Pipeline/DictationSession+Press.swift b/Sources/BlurtEngine/Pipeline/DictationSession+Press.swift index 29cc49bc..27d5fb74 100644 --- a/Sources/BlurtEngine/Pipeline/DictationSession+Press.swift +++ b/Sources/BlurtEngine/Pipeline/DictationSession+Press.swift @@ -124,7 +124,16 @@ extension DictationSession { if !consumeCancelRequest() { setPhase(.cancelled) } return } - setPhase(.failed(.audioCaptureFailed(underlying: error))) + // `MicCapture.start()` already throws a `BlurtError` for its own failures + // (no input device, the liveness gate failing closed); wrapping that a + // second time read as "Audio capture failed: Audio capture failed: …" on + // the pill and in `errors.jsonl`. Only a conformer's untyped error needs + // the wrap — the same rule `awaitUpload` applies to the transcriber's. + if let blurtError = error as? BlurtError { + setPhase(.failed(blurtError)) + } else { + setPhase(.failed(.audioCaptureFailed(underlying: error))) + } } } @@ -142,7 +151,7 @@ extension DictationSession { // above) so the call is a Sendable closure rather than isolated state. let captureFrontmost = seams.captureFrontmost let captured = await captureFrontmost() - await injector.setTargetApp(captured.flatMap { FocusCapture.runningApp(for: $0) }) + await injector.setTarget(captured) // Key terms are read synchronously at press (cheap UserDefaults read), so // each dictation observably re-reads Settings edits at press time. let keyTerms = keyTermsProvider() diff --git a/Sources/BlurtEngine/Pipeline/DictationSession+Seams.swift b/Sources/BlurtEngine/Pipeline/DictationSession+Seams.swift index 460eb9a0..765aabc3 100644 --- a/Sources/BlurtEngine/Pipeline/DictationSession+Seams.swift +++ b/Sources/BlurtEngine/Pipeline/DictationSession+Seams.swift @@ -10,11 +10,13 @@ extension DictationSession { /// `~/Library/Logs/Blurt`, so on a machine with developer mode switched on /// `swift test` appended its fixtures to the user's own dictation corpus. /// - /// Bundled into one value rather than four initializer parameters: the - /// public initializer can't name these types (`CapturedFocus` and - /// `FocusedFieldContext` are internal), so the seams ride on the internal - /// initializer, and one required parameter there keeps the two initializers - /// unambiguous at every call site. + /// Bundled into one value rather than four initializer parameters: the log + /// seams have no business on the public initializer, so the whole set rides + /// on the internal one, and one required parameter there keeps the two + /// initializers unambiguous at every call site. The focus half *is* public — + /// as `HostFocusCapture`, below — because a host on another platform has to + /// supply it: the production defaults here are Accessibility reads, and only + /// macOS has those. /// /// Spelled with `var` properties: the synthesized memberwise initializer omits /// `let` properties that already carry a default value, so a test could not @@ -22,17 +24,29 @@ extension DictationSession { /// session stores one and never writes to it. struct Seams: Sendable { /// Captures the frontmost application — the paste target, and the context's - /// app name. On the main actor because it's an AppKit read. + /// app name. On the main actor because it's an AppKit read. Off macOS there + /// is no frontmost app to read (a keyboard cannot see its host), so the + /// default reports nothing and a host with real context supplies its own. var captureFrontmost: @Sendable () async -> CapturedFocus? = { - await MainActor.run { FocusCapture.captureFrontmost() } + #if os(macOS) + return await MainActor.run { FocusCapture.captureFrontmost() } + #else + return nil + #endif } /// Reads the focused field's Accessibility context. Deliberately /// synchronous: `performPress` runs it on a Dispatch queue precisely because /// it blocks a thread against an unresponsive app (see its call site), and - /// that stays true of the production capture behind this seam. - var captureFieldContext: @Sendable () -> FocusCapture.FocusedFieldContext = { - FocusCapture.captureFieldContext() + /// that stays true of the production capture behind this seam. Off macOS + /// the default reads nothing; an iPhone host hands the keyboard's text + /// before the cursor in through `HostFocusCapture` instead. + var captureFieldContext: @Sendable () -> FocusedFieldContext = { + #if os(macOS) + return FocusCapture.captureFieldContext() + #else + return .empty + #endif } /// Records a completed dictation in the developer-mode log. Gated on the @@ -49,7 +63,42 @@ extension DictationSession { } /// The real focus capture and the real log — what the public initializer - /// passes, and the only value production ever uses. + /// passes when the host supplies no `HostFocusCapture`, and the only value + /// production on macOS ever uses. static let production = Seams() } + + // periphery:ignore - public for hosts outside this repo (the iOS app); the Mac app relies on the defaults. + /// What a host that is not this repo's Mac app knows about the field being + /// dictated into, supplied to the public initializer in place of the + /// Accessibility reads the engine performs on macOS. + /// + /// `field` is read once per press, off the actor, and consumed when the + /// upload opens (bounded by `contextWaitBudget`) — the same contract the + /// Accessibility capture has, so a host's read may block briefly but must + /// never hang. An iPhone keyboard's `documentContextBeforeInput` is the + /// `priorText` the request's `stt_prompt` continues from; everything a + /// keyboard cannot see stays nil. `frontmost` is the paste target handed to + /// `InjectorProtocol.setTarget`; a host with no such notion returns nil. + public struct HostFocusCapture: Sendable { + public var frontmost: @Sendable () async -> CapturedFocus? + public var field: @Sendable () -> FocusedFieldContext + + public init( + frontmost: @escaping @Sendable () async -> CapturedFocus?, + field: @escaping @Sendable () -> FocusedFieldContext + ) { + self.frontmost = frontmost + self.field = field + } + } +} + +extension DictationSession.Seams { + /// The production seams with the focus half replaced by the host's. In an + /// extension so the struct keeps its memberwise initializer, which the tests + /// build their seams with. + init(hostFocusCapture host: DictationSession.HostFocusCapture) { + self.init(captureFrontmost: host.frontmost, captureFieldContext: host.field) + } } diff --git a/Sources/BlurtEngine/Pipeline/DictationSession.swift b/Sources/BlurtEngine/Pipeline/DictationSession.swift index 3247b997..5149f981 100644 --- a/Sources/BlurtEngine/Pipeline/DictationSession.swift +++ b/Sources/BlurtEngine/Pipeline/DictationSession.swift @@ -166,9 +166,12 @@ public actor DictationSession { /// route settles the context up front, so `cancel()` is now the whole of it. var upload: Task? - /// The production entry point: the real focus capture and the real - /// developer-mode log. Delegates to the seam-carrying initializer below, which - /// can't be public because it names internal types. + /// The production entry point: the real developer-mode log, and the real + /// focus capture unless the host supplies its own — `hostFocusCapture` is how + /// a host on a platform without Accessibility reads (the iOS app, whose + /// keyboard knows the text before the cursor) hands that context in. + /// Delegates to the seam-carrying initializer below, which can't be public + /// because it names the internal log seams. public init( mic: MicCaptureProtocol, transcriber: TranscriberProtocol, @@ -178,14 +181,16 @@ public actor DictationSession { keyTermsProvider: (@Sendable () -> [String])? = nil, styleNameProvider: (@Sendable () -> String?)? = nil, readinessCheck: @escaping @Sendable () -> BlurtError? = { nil }, - onTranscriptDelivered: (@Sendable (String, RecentDictations) -> Void)? = nil + onTranscriptDelivered: (@Sendable (String, RecentDictations) -> Void)? = nil, + hostFocusCapture: HostFocusCapture? = nil ) { self.init( mic: mic, transcriber: transcriber, injector: injector, maxRecordingSeconds: maxRecordingSeconds, clock: clock, keyTermsProvider: keyTermsProvider, styleNameProvider: styleNameProvider, readinessCheck: readinessCheck, - onTranscriptDelivered: onTranscriptDelivered, seams: .production) + onTranscriptDelivered: onTranscriptDelivered, + seams: hostFocusCapture.map(Seams.init(hostFocusCapture:)) ?? .production) } /// `seams` is deliberately required rather than defaulted: it's what keeps this diff --git a/Sources/BlurtEngine/README.md b/Sources/BlurtEngine/README.md index 9d4a7893..fd826439 100644 --- a/Sources/BlurtEngine/README.md +++ b/Sources/BlurtEngine/README.md @@ -4,7 +4,7 @@ BlurtEngine is the Swift package that powers [Blurt](../../README.md)'s dictatio ## What you get -- **`Sources/BlurtEngine/`** — a Swift package (`swift-tools-version:6.2`, macOS 15+, Swift 6 strict concurrency) with **no external dependencies**: just Foundation, Security, AVFoundation, CoreAudio, toolchain modules like Synchronization, and AppKit types at the seams. That dependency-free rule is deliberate and enforced — don't add SPM dependencies to the engine. +- **`Sources/BlurtEngine/`** — a Swift package (`swift-tools-version:6.2`, macOS 15+ and iOS 18+, Swift 6 strict concurrency) with **no external dependencies**: just Foundation, Security, AVFoundation, CoreAudio, toolchain modules like Synchronization, and AppKit types at the seams. That dependency-free rule is deliberate and enforced — don't add SPM dependencies to the engine. The pipeline, the dictation client and the settings stores build for both platforms; the Accessibility reads, the clipboard paste, the CoreAudio route reads and the TCC/code-signing helpers are macOS only, fenced behind `#if os(macOS)` — CI's `ios-build` job is what keeps the fence honest, since `swift test` only ever compiles for the host. - Pure logic behind three protocol seams (`MicCaptureProtocol`, `TranscriberProtocol`, `InjectorProtocol`), so every collaborator can be stubbed in tests and replaced in a host app. - Production implementations of all three seams (`MicCapture`, `AssemblyAITranscriber`, `KeyInjector`), plus the supporting pieces a dictation product needs: Keychain-backed API-key storage, per-utterance contextual prompting (the text before the cursor, and nothing else about the user's screen), a hotkey state machine, permission checks, and UI-state projections. @@ -198,19 +198,21 @@ The model's limits live in `SyncSTTLimits` (16 kHz sample rate, ~0.1 s–120 s a ### `InjectorProtocol` → `KeyInjector` ```swift -func setTargetApp(_ app: NSRunningApplication?) async +func setTarget(_ focus: CapturedFocus?) async func insert(_ text: String, after priorText: String?, windowTitle: String?) async throws ``` -`KeyInjector.insert` **always** pastes: it saves the current pasteboard, writes the transcript, activates the captured target app, posts a synthesized ⌘V, waits for the target to read the clipboard (`pasteSettleDuration`, default 400 ms, tunable in the initializer), then restores the prior pasteboard contents. That restore never destroys what it can't put back: an unreadable pasteboard snapshots as `nil` (not as empty) and is skipped, and the replacement items are built before `clearContents()`, with the plain-string flavor as a floor when promised representations can't be materialized. There is no keystroke-by-keystroke typing path and no length threshold. If the target app is gone or nothing editable is focused it leaves the text on the clipboard and throws `.targetAppLost` / `.noEditableTarget` — which the session turns into the quiet `.noTarget` outcome. AX-opaque targets — Electron editors and web browsers, per `FocusCapture.isAXOpaqueApp` — are exempt from the editability gate and are pasted into even with no editable AX signal: web content is routinely invisible to Accessibility (Chromium builds its tree lazily; `contenteditable` composers expose no editable role), so "no signal" there usually means "AX can't see the field," not "no field," and the accepted trade-off is a rare beep over dropping the user's words to copy-only. `priorText` (the text before the caret, captured at press time) drives `withLeadingSeparator`, which joins consecutive dictations with a space so they don't run together. When `priorText` is unreadable (an Accessibility-opaque editor, or a browser tab like Google Docs whose canvas-rendered body exposes no AX text), `separatorBasis` falls back to what was last pasted — but only when both the target app **and** `windowTitle` match the last successful insert, so the fallback tracks "the same window," not just "the same process" (a browser hosts many unrelated tabs/documents under one PID). +`CapturedFocus` is a pid and a display name rather than an `NSRunningApplication`, so the seam is the same on every platform the engine builds for: `KeyInjector` resolves the process handle from the pid on macOS, and a host with no notion of a target app — an iPhone keyboard inserts into the field it is already attached to — receives `nil` and ignores it. -The session calls `setTargetApp` at press time with the app that was frontmost when recording started — so the paste lands where the user was, even if focus moved during transcription. +`KeyInjector.insert` **always** pastes: it saves the current pasteboard, writes the transcript, activates the captured target app, posts a synthesized ⌘V, waits for the target to read the clipboard (`pasteSettleDuration`, default 400 ms, tunable in the initializer), then restores the prior pasteboard contents. That restore never destroys what it can't put back: an unreadable pasteboard snapshots as `nil` (not as empty) and is skipped, and the replacement items are built before `clearContents()`, with the plain-string flavor as a floor when promised representations can't be materialized. There is no keystroke-by-keystroke typing path and no length threshold. If the target app is gone or nothing editable is focused it leaves the text on the clipboard and throws `.targetAppLost` / `.noEditableTarget` — which the session turns into the quiet `.noTarget` outcome. AX-opaque targets — Electron editors and web browsers, per `FocusCapture.isAXOpaqueApp` — are exempt from the editability gate and are pasted into even with no editable AX signal: web content is routinely invisible to Accessibility (Chromium builds its tree lazily; `contenteditable` composers expose no editable role), so "no signal" there usually means "AX can't see the field," not "no field," and the accepted trade-off is a rare beep over dropping the user's words to copy-only. `priorText` (the text before the caret, captured at press time) drives `InsertionSeparator.withLeadingSeparator`, which joins consecutive dictations with a space so they don't run together — a platform-free type, because a host that inserts text itself faces the same decision. When `priorText` is unreadable (an Accessibility-opaque editor, or a browser tab like Google Docs whose canvas-rendered body exposes no AX text), `InsertionSeparator.basis` falls back to what was last pasted — but only when both the target app **and** `windowTitle` match the last successful insert, so the fallback tracks "the same window," not just "the same process" (a browser hosts many unrelated tabs/documents under one PID). + +The session calls `setTarget` at press time with the app that was frontmost when recording started — so the paste lands where the user was, even if focus moved during transcription. ## Context and prompting **Most of what is captured never leaves the machine.** The request's transcription prompt carries one context signal — the text immediately before the cursor — and the rest of the focus snapshot is collected for local work (paste spacing, the injector's window identity, the developer-mode log). The user's key terms are sent too, but on their own field rather than in the prompt. Hosts don't call these APIs directly, but should know what's collected, what it's for, and which part is sent: -- **`TranscriptionContext`** carries the frontmost app name, window title, focused-field label, the text before the caret, the selected text (which a paste will replace), and the user's key terms — of which two are sent: `priorText` (as the prompt) and `keyTerms` (as the `keyterms_prompt` list). It's captured via Accessibility at press time (skipped in secure fields), off the hot path — and consumed when the upload opens, with a bounded wait (`DictationSession.contextWaitBudget`), so a hung read costs the request its priming rather than delaying the audio. Of the focus signals only `priorText` is sent; the app name, window title, field label and selected text stay local — the injector reads `priorText`/`windowTitle` to decide the paste's leading separator and to recognize the captured window, and the developer-mode log records the rest. +- **`TranscriptionContext`** carries the frontmost app name, window title, focused-field label, the text before the caret, the selected text (which a paste will replace), and the user's key terms — of which two are sent: `priorText` (as the prompt) and `keyTerms` (as the `keyterms_prompt` list). It's captured via Accessibility at press time (skipped in secure fields), off the hot path — and consumed when the upload opens, with a bounded wait (`DictationSession.contextWaitBudget`), so a hung read costs the request its priming rather than delaying the audio. That capture is macOS-only; a host on another platform passes a `DictationSession.HostFocusCapture` to the session's initializer — two closures supplying the frontmost app (or `nil`) and a `FocusedFieldContext` built from whatever its own text surface exposes, such as an iPhone keyboard's `documentContextBeforeInput` — and the session consumes it on the same schedule and with the same bounded wait. Of the focus signals only `priorText` is sent; the app name, window title, field label and selected text stay local — the injector reads `priorText`/`windowTitle` to decide the paste's leading separator and to recognize the captured window, and the developer-mode log records the rest. - **`STTPrompt.text(context:)`** renders the prior text into the dictation request's `config.stt_prompt` (transcription steering only — the cleanup rewrite is the separate `llm_instruction`): one newline-joined string, the user's recent dictations oldest-first followed by the text before the caret last, fitted to a **4096-scalar** budget by dropping the oldest entries first. That cap is the API's and it **rejects** rather than trims (`400 stt_prompt: String should have at most 4096 characters`), so `fitted` is what stands between a long history and every dictation failing; its unit was measured — 4096 `é` (8192 bytes) passes, 820 family emoji (4100 scalars, 820 graphemes) does not — which is why it counts `unicodeScalars` and not Swift's grapheme `count`. It reads no other field of the context. A context with neither history nor prior text yields `""`, which omits the field so the model works from the audio alone. History the prior chunk already ends with is dropped rather than sent twice — after a paste the field contains what was just dictated. **`stt_prompt` is `config.prompt` under its other name** (`provide only one of stt_prompt or prompt; they are the same field`), and it replaced `config.conversation_context`, the array-of-turns field that carried the same two signals; both still work, so re-adding the turn list would send the prior text twice rather than fail. The trade the swap accepted is that a custom prompt displaces the service's managed default; re-measured 2026-09-10, language detection survives it (a Spanish clip came back in Spanish with an English prompt, a Spanish one, and none at all). Two deliberate omissions survive from the older prompt, both regression-tested: no language steering (pinning to English hurt non-English speech) and no "remove filler words" clause (not in the model's trained instruction set — a no-op). Don't reintroduce either, don't put a `Previous transcript:` heading or any instruction in the string, and don't widen the context back out to the app/window/field hints the old prompt used to carry. - **`CleanupInstruction.text`** is the other half: the string sent as `config.llm_instruction`, which the service applies to the verbatim transcript with its own rewrite model. It is the winner of a GEPA run of `evals/dictation-prompt/`, compressed to fit the API's **2048-character** cap on that field — a different, smaller limit than the 4096 on `config.stt_prompt` — and counted in a different unit (UTF-8 bytes here, Unicode scalars there), so `CleanupInstruction.characterCap` is asserted in tests rather than borrowed. Treat it as a measured artifact: a new hypothesis belongs in that harness plus a fresh run, not a hand-edit. Two caveats ship with it — it has only ever been scored against other text candidates on a stand-in model, never against the service's own default instruction on its own rewrite model, and every corpus behind it is English. Dropping the field restores the service default in one line — which is _not_ the same as turning the rewrite off; nothing on the request does that, and the **enhanced transcripts** switch works on the response instead. - **`KeytermsBoost.fitted(_:)`** turns those terms into the request's `config.keyterms_prompt` — keyterms prompting, the other steering field next to `stt_prompt`, and a flat array of strings rather than prose. It takes whole terms in the user's order while they fit the field's own **2048-character** cap (`KeytermsBoost.characterCap`, in UTF-8 bytes — a third limit, distinct from the 4096 scalars on `config.stt_prompt` and the 2048 bytes on `config.llm_instruction`) and while the list stays within **100 terms** (`KeytermsBoost.termCap`, the reference's `maxItems` on the same field — a count, not a size, and the one a byte budget doesn't imply: 150 short terms clear 2048 bytes and 400 on the count), and returns a plain `[String]`; an empty result omits the field on the wire rather than sending `[]`. `keyterms_prompt` is the canonical name — `keyterms` and `word_boost` are legacy aliases for the same feature, mutually exclusive with it, so send exactly one (this sent `word_boost` until 2026-09-10). Don't fold key terms back into the context as a `Keywords:` clause; that was the older, worse shape for the same intent. diff --git a/Sources/BlurtEngine/UserAgent.swift b/Sources/BlurtEngine/UserAgent.swift index 1a39d58e..eeb78ee5 100644 --- a/Sources/BlurtEngine/UserAgent.swift +++ b/Sources/BlurtEngine/UserAgent.swift @@ -79,14 +79,21 @@ enum UserAgent { return "\(name) (\(comment.joined(separator: "; ")))" } - /// `macOS 15.5` — major and minor, for the reason the type doc gives. + /// `macOS 15.5` — major and minor, for the reason the type doc gives — or + /// `iOS 18.1` when the engine is running on a phone: the OS name is the one + /// fact about the platform the service-side baseline has to split on. /// /// `ProcessInfo` rather than AppKit's `NSProcessInfo`-adjacent niceties or a /// `sw_vers` shell-out, because the engine is a dependency-free Swift package - /// and this is the one Foundation API that answers it. + /// and this is the one Foundation API that answers it on both platforms. private static func osDetail() -> String { let version = ProcessInfo.processInfo.operatingSystemVersion - return "macOS \(version.majorVersion).\(version.minorVersion)" + #if os(macOS) + let name = "macOS" + #else + let name = "iOS" + #endif + return "\(name) \(version.majorVersion).\(version.minorVersion)" } /// `dev` for anything that isn't a release build, and nothing at all for a diff --git a/Tests/BlurtEngineTests/AXDowncastTests.swift b/Tests/BlurtEngineTests/AXDowncastTests.swift index ba50daca..07f80bf4 100644 --- a/Tests/BlurtEngineTests/AXDowncastTests.swift +++ b/Tests/BlurtEngineTests/AXDowncastTests.swift @@ -1,44 +1,46 @@ -import ApplicationServices -import Testing +#if os(macOS) + import ApplicationServices + import Testing -@testable import BlurtEngine + @testable import BlurtEngine -/// The checked CFTypeRef downcasts behind the Accessibility reads -/// (`FocusCapture.axElement` / `.axRange`). Attribute values arrive from -/// *other apps'* AX implementations, so a wrong CF type must decode to `nil`, -/// never flow onward mistyped. Pure type checks — no Accessibility trust, no -/// focused element, and no cross-process IPC needed. -@Suite("FocusCapture checked AX downcasts") -struct AXDowncastTests { - @Test("axElement passes a real AXUIElement through") - func elementAccepted() { - // The system-wide element is just a local ref — creating it needs no trust. - #expect(FocusCapture.axElement(AXUIElementCreateSystemWide()) != nil) - } + /// The checked CFTypeRef downcasts behind the Accessibility reads + /// (`FocusCapture.axElement` / `.axRange`). Attribute values arrive from + /// *other apps'* AX implementations, so a wrong CF type must decode to `nil`, + /// never flow onward mistyped. Pure type checks — no Accessibility trust, no + /// focused element, and no cross-process IPC needed. + @Suite("FocusCapture checked AX downcasts") + struct AXDowncastTests { + @Test("axElement passes a real AXUIElement through") + func elementAccepted() { + // The system-wide element is just a local ref — creating it needs no trust. + #expect(FocusCapture.axElement(AXUIElementCreateSystemWide()) != nil) + } - @Test("axElement rejects a non-element CF value") - func elementWrongTypeRejected() { - #expect(FocusCapture.axElement("not an element" as CFString) == nil) - } + @Test("axElement rejects a non-element CF value") + func elementWrongTypeRejected() { + #expect(FocusCapture.axElement("not an element" as CFString) == nil) + } - @Test("axRange decodes an AXValue-wrapped CFRange") - func rangeDecoded() throws { - var range = CFRange(location: 4, length: 2) - let wrapped = try #require(AXValueCreate(.cfRange, &range)) - let decoded = try #require(FocusCapture.axRange(wrapped)) - #expect(decoded.location == 4) - #expect(decoded.length == 2) - } + @Test("axRange decodes an AXValue-wrapped CFRange") + func rangeDecoded() throws { + var range = CFRange(location: 4, length: 2) + let wrapped = try #require(AXValueCreate(.cfRange, &range)) + let decoded = try #require(FocusCapture.axRange(wrapped)) + #expect(decoded.location == 4) + #expect(decoded.length == 2) + } - @Test("axRange rejects a non-AXValue CF value") - func rangeWrongTypeRejected() { - #expect(FocusCapture.axRange("not a range" as CFString) == nil) - } + @Test("axRange rejects a non-AXValue CF value") + func rangeWrongTypeRejected() { + #expect(FocusCapture.axRange("not a range" as CFString) == nil) + } - @Test("axRange rejects an AXValue holding a non-range payload") - func rangeWrongPayloadRejected() throws { - var point = CGPoint(x: 1, y: 2) - let wrapped = try #require(AXValueCreate(.cgPoint, &point)) - #expect(FocusCapture.axRange(wrapped) == nil) + @Test("axRange rejects an AXValue holding a non-range payload") + func rangeWrongPayloadRejected() throws { + var point = CGPoint(x: 1, y: 2) + let wrapped = try #require(AXValueCreate(.cgPoint, &point)) + #expect(FocusCapture.axRange(wrapped) == nil) + } } -} +#endif diff --git a/Tests/BlurtEngineTests/AudioInputDevicesTests.swift b/Tests/BlurtEngineTests/AudioInputDevicesTests.swift index e4940e3b..52b74bca 100644 --- a/Tests/BlurtEngineTests/AudioInputDevicesTests.swift +++ b/Tests/BlurtEngineTests/AudioInputDevicesTests.swift @@ -1,186 +1,188 @@ -@preconcurrency import AVFoundation -import CoreAudio -import Foundation -import Testing - -@testable import BlurtEngine - -/// Live-hardware checks for the microphone-selection plumbing: the device -/// enumeration the Settings picker lists, the UID lookups the capture path -/// resolves a pin with, and the session recorder itself. -/// -/// Gated on BLURT_LIVE_AUDIO_TESTS=1 like the other capture suites — every test -/// here talks to real devices (and two of them open one), which a headless CI -/// runner cannot answer for. Documents and locks the behavior for a human -/// running it on a Mac with a microphone; `AudioInputDevices.swift` and -/// `CaptureSessionRecorder.swift` are excluded from the coverage gate for the -/// same reason `MicCapture.swift` is. -@Suite( - "AudioInputDevices & capture session (live)", - ConditionTrait.requiresLiveAudio, - .tags(.liveAudio), - // Serialized: three of these open the default input, and the engagement test - // reads whether *anyone* has it open. Run in parallel they'd flag each other. - .serialized, - .timeLimit(.minutes(1))) -struct AudioInputDevicesTests { - @Test("enumeration lists named, uniquely-identified input devices") - func enumerationListsInputDevices() throws { - let devices = AudioInputDevices.all() - try #require(!devices.isEmpty, "a machine running this suite needs at least one input device") - - // Every entry must be renderable in the picker and pinnable by the store. - // Closures rather than key paths inside the macros — the rethrows + key-path - // combination is the documented `#expect` trap (see AGENTS.md's testing notes). - #expect(devices.allSatisfy { !$0.uid.isEmpty && !$0.name.isEmpty }) - let uids = devices.map { $0.uid } - #expect(Set(uids).count == uids.count, "device UIDs must be unique") - - // The default input has a name for the "Same as system (…)" label. - #expect(AudioInputDevices.systemDefaultInputName() != nil) - } - - @Test("a listed UID classifies; a bogus one reads as absent") - func uidLookupsAgreeWithTheEnumeration() throws { - let first = try #require(AudioInputDevices.all().first) +#if os(macOS) + @preconcurrency import AVFoundation + import CoreAudio + import Foundation + import Testing + + @testable import BlurtEngine + + /// Live-hardware checks for the microphone-selection plumbing: the device + /// enumeration the Settings picker lists, the UID lookups the capture path + /// resolves a pin with, and the session recorder itself. + /// + /// Gated on BLURT_LIVE_AUDIO_TESTS=1 like the other capture suites — every test + /// here talks to real devices (and two of them open one), which a headless CI + /// runner cannot answer for. Documents and locks the behavior for a human + /// running it on a Mac with a microphone; `AudioInputDevices.swift` and + /// `CaptureSessionRecorder.swift` are excluded from the coverage gate for the + /// same reason `MicCapture.swift` is. + @Suite( + "AudioInputDevices & capture session (live)", + ConditionTrait.requiresLiveAudio, + .tags(.liveAudio), + // Serialized: three of these open the default input, and the engagement test + // reads whether *anyone* has it open. Run in parallel they'd flag each other. + .serialized, + .timeLimit(.minutes(1))) + struct AudioInputDevicesTests { + @Test("enumeration lists named, uniquely-identified input devices") + func enumerationListsInputDevices() throws { + let devices = AudioInputDevices.all() + try #require(!devices.isEmpty, "a machine running this suite needs at least one input device") + + // Every entry must be renderable in the picker and pinnable by the store. + // Closures rather than key paths inside the macros — the rethrows + key-path + // combination is the documented `#expect` trap (see AGENTS.md's testing notes). + #expect(devices.allSatisfy { !$0.uid.isEmpty && !$0.name.isEmpty }) + let uids = devices.map { $0.uid } + #expect(Set(uids).count == uids.count, "device UIDs must be unique") + + // The default input has a name for the "Same as system (…)" label. + #expect(AudioInputDevices.systemDefaultInputName() != nil) + } - // One read answers both questions `MicCapture.resolveInput` asks of a pin — - // is the device there, and what transport is it on. That it holds for every - // enumerated device is the load-bearing part: the picker must not offer a - // device the capture path would then treat as missing (or fail to classify, - // which silently loses the Bluetooth caps). - #expect(AudioInputDevices.transportType(forUID: first.uid) != nil) + @Test("a listed UID classifies; a bogus one reads as absent") + func uidLookupsAgreeWithTheEnumeration() throws { + let first = try #require(AudioInputDevices.all().first) - // The missing-device signal `MicDeviceSelection.effective` falls back on. - #expect(AudioInputDevices.transportType(forUID: "blurt-test-no-such-device") == nil) - } + // One read answers both questions `MicCapture.resolveInput` asks of a pin — + // is the device there, and what transport is it on. That it holds for every + // enumerated device is the load-bearing part: the picker must not offer a + // device the capture path would then treat as missing (or fail to classify, + // which silently loses the Bluetooth caps). + #expect(AudioInputDevices.transportType(forUID: first.uid) != nil) - @Test("building a recorder — and warming up — leaves the microphone closed") - func buildingASessionDoesNotEngageTheDevice() async throws { - await LiveAudioDevice.acquire() - defer { LiveAudioDevice.release() } - - // The measurement the warm-up design rests on, as a regression test: a built - // but unstarted session must not open the device, or `warmUp()` at launch - // would light the input indicator and pin AirPods into their mic-capable - // profile (where *output* audio is degraded) for as long as the app runs. - let device = try #require(AVCaptureDevice.default(for: .audio)) - // Wait for the device to be free rather than demanding it already is: this - // suite is `.serialized`, but the other live suites are separate suites and - // run in parallel with it, and two of them open this same device. Polling - // makes the precondition deterministic instead of dependent on which suite - // got there first; a device that never frees up is a real failure with a - // message that says so. - try #require( - await Self.poll(upTo: .seconds(3)) { Self.isRunningSomewhere(uid: device.uniqueID) == false }, - "the default input stayed busy — another app (or suite) is capturing from it") - - let recorder = try await CaptureSessionRecorder.make(pinnedUID: device.uniqueID) - #expect(Self.isRunningSomewhere(uid: device.uniqueID) == false, "building must not open the device") - - await MicCapture(deviceSelection: { .systemDefault }).warmUp() - #expect(Self.isRunningSomewhere(uid: device.uniqueID) == false, "warm-up must not open the device") - - // And the same recorder still opens it on demand, so "closed" isn't just a - // recorder that was never usable. - // - // Polled rather than asserted outright, because when the open *completes* - // is transport-dependent — the measurement that shaped the liveness gate. - // On a USB interface `startRunning()` blocks until the device is running, so - // this holds the instant `record()` returns; on AirPods it returns in ~80 ms - // and the device comes up ~400 ms later. Asserting immediately passes on - // wired hardware and fails on the transport the gate exists for. - try #require(await recorder.record()) - #expect( - await Self.waitForRunning(uid: device.uniqueID), - "record() is what opens the device, even if the link finishes opening it later") - recorder.stopAndDiscard() - } + // The missing-device signal `MicDeviceSelection.effective` falls back on. + #expect(AudioInputDevices.transportType(forUID: "blurt-test-no-such-device") == nil) + } - @Test("the session recorder captures S16LE audio from the device it was pinned to") - func pinnedRecorderCapturesAudio() async throws { - await LiveAudioDevice.acquire() - defer { LiveAudioDevice.release() } - - // Pin to the current default input — the one device a machine running this - // suite is known to have working — by the same UID the picker would store. - let uid = try #require(AVCaptureDevice.default(for: .audio)?.uniqueID) - #expect(AudioInputDevices.all().contains { $0.uid == uid }, "the default input should be listed") - - let recorder = try await CaptureSessionRecorder.make(pinnedUID: uid) - try #require(await recorder.record(), "the session recorder should start on a live device") - - // Wait for frames the way the liveness gate does, rather than sleeping a - // fixed 500 ms: on AirPods the first buffer lands ~490 ms after - // `startRunning()` returns, so a fixed sleep sits right on the edge and this - // suite would flake on a cold link. - try #require( - await Self.poll(upTo: MicLiveness.bluetoothTimeout) { recorder.deliveredFrames > 0 }, - "buffers should be arriving") - // The meter must read as a live analog input, not digital silence — this is - // the reading `MicLiveness.silenceFloorDB` gates on, and the assertion that - // proves the session meter's floor semantics on real hardware. - // - // Polled for the same reason the frame wait is, and this is the sharper - // case: the channel's power lags the first frames, reporting - // `-Float.greatestFiniteMagnitude` until its first update (measured on - // AirPods). That is exactly why the gate polls *both* terms instead of - // metering once frames appear. - #expect( - await Self.poll(upTo: MicLiveness.bluetoothTimeout) { - recorder.meteredPowerDB() > MicLiveness.silenceFloorDB - }, "a live mic must out-read the silence floor") - - let byteCount = recorder.stopAndReadByteCount() - #expect(byteCount > 0, "half a second of capture should deliver samples") - #expect( - byteCount % SyncSTTLimits.bytesPerSample == 0, "the capture must be whole S16LE samples") - } + @Test("building a recorder — and warming up — leaves the microphone closed") + func buildingASessionDoesNotEngageTheDevice() async throws { + await LiveAudioDevice.acquire() + defer { LiveAudioDevice.release() } + + // The measurement the warm-up design rests on, as a regression test: a built + // but unstarted session must not open the device, or `warmUp()` at launch + // would light the input indicator and pin AirPods into their mic-capable + // profile (where *output* audio is degraded) for as long as the app runs. + let device = try #require(AVCaptureDevice.default(for: .audio)) + // Wait for the device to be free rather than demanding it already is: this + // suite is `.serialized`, but the other live suites are separate suites and + // run in parallel with it, and two of them open this same device. Polling + // makes the precondition deterministic instead of dependent on which suite + // got there first; a device that never frees up is a real failure with a + // message that says so. + try #require( + await Self.poll(upTo: .seconds(3)) { Self.isRunningSomewhere(uid: device.uniqueID) == false }, + "the default input stayed busy — another app (or suite) is capturing from it") + + let recorder = try await CaptureSessionRecorder.make(pinnedUID: device.uniqueID) + #expect(Self.isRunningSomewhere(uid: device.uniqueID) == false, "building must not open the device") + + await MicCapture(deviceSelection: { .systemDefault }).warmUp() + #expect(Self.isRunningSomewhere(uid: device.uniqueID) == false, "warm-up must not open the device") + + // And the same recorder still opens it on demand, so "closed" isn't just a + // recorder that was never usable. + // + // Polled rather than asserted outright, because when the open *completes* + // is transport-dependent — the measurement that shaped the liveness gate. + // On a USB interface `startRunning()` blocks until the device is running, so + // this holds the instant `record()` returns; on AirPods it returns in ~80 ms + // and the device comes up ~400 ms later. Asserting immediately passes on + // wired hardware and fails on the transport the gate exists for. + try #require(await recorder.record()) + #expect( + await Self.waitForRunning(uid: device.uniqueID), + "record() is what opens the device, even if the link finishes opening it later") + recorder.stopAndDiscard() + } - /// Polls `condition` on a short tick until it holds or `timeout` elapses, - /// answering whether it ever held. The suite's own miniature of - /// `MicLiveness.waitUntilLive`, for the same reason that exists: nothing about - /// a capture device is synchronous just because the call that started it - /// returned. - private static func poll( - upTo timeout: Duration, _ condition: @Sendable () -> Bool - ) async -> Bool { - let deadline = ContinuousClock().now.advanced(by: timeout) - while ContinuousClock().now < deadline { - if condition() { return true } - try? await Task.sleep(for: .milliseconds(20)) + @Test("the session recorder captures S16LE audio from the device it was pinned to") + func pinnedRecorderCapturesAudio() async throws { + await LiveAudioDevice.acquire() + defer { LiveAudioDevice.release() } + + // Pin to the current default input — the one device a machine running this + // suite is known to have working — by the same UID the picker would store. + let uid = try #require(AVCaptureDevice.default(for: .audio)?.uniqueID) + #expect(AudioInputDevices.all().contains { $0.uid == uid }, "the default input should be listed") + + let recorder = try await CaptureSessionRecorder.make(pinnedUID: uid) + try #require(await recorder.record(), "the session recorder should start on a live device") + + // Wait for frames the way the liveness gate does, rather than sleeping a + // fixed 500 ms: on AirPods the first buffer lands ~490 ms after + // `startRunning()` returns, so a fixed sleep sits right on the edge and this + // suite would flake on a cold link. + try #require( + await Self.poll(upTo: MicLiveness.bluetoothTimeout) { recorder.deliveredFrames > 0 }, + "buffers should be arriving") + // The meter must read as a live analog input, not digital silence — this is + // the reading `MicLiveness.silenceFloorDB` gates on, and the assertion that + // proves the session meter's floor semantics on real hardware. + // + // Polled for the same reason the frame wait is, and this is the sharper + // case: the channel's power lags the first frames, reporting + // `-Float.greatestFiniteMagnitude` until its first update (measured on + // AirPods). That is exactly why the gate polls *both* terms instead of + // metering once frames appear. + #expect( + await Self.poll(upTo: MicLiveness.bluetoothTimeout) { + recorder.meteredPowerDB() > MicLiveness.silenceFloorDB + }, "a live mic must out-read the silence floor") + + let byteCount = recorder.stopAndReadByteCount() + #expect(byteCount > 0, "half a second of capture should deliver samples") + #expect( + byteCount % SyncSTTLimits.bytesPerSample == 0, "the capture must be whole S16LE samples") } - return condition() - } - /// Whether the device carrying `uid` comes up as capturing within the - /// Bluetooth cap — the widest the product itself ever waits. - private static func waitForRunning(uid: String) async -> Bool { - await poll(upTo: MicLiveness.bluetoothTimeout) { isRunningSomewhere(uid: uid) } - } + /// Polls `condition` on a short tick until it holds or `timeout` elapses, + /// answering whether it ever held. The suite's own miniature of + /// `MicLiveness.waitUntilLive`, for the same reason that exists: nothing about + /// a capture device is synchronous just because the call that started it + /// returned. + private static func poll( + upTo timeout: Duration, _ condition: @Sendable () -> Bool + ) async -> Bool { + let deadline = ContinuousClock().now.advanced(by: timeout) + while ContinuousClock().now < deadline { + if condition() { return true } + try? await Task.sleep(for: .milliseconds(20)) + } + return condition() + } - /// CoreAudio's own answer to "is this device capturing right now" — the bit - /// behind the system input indicator. Test-local rather than a production - /// helper: nothing in the app needs to ask, and the point of the assertions - /// above is to check the *device*, not our bookkeeping about it. - private static func isRunningSomewhere(uid: String) -> Bool { - var translate = AudioRoute.globalAddress(kAudioHardwarePropertyTranslateUIDToDevice) - var cfUID = uid as CFString - var deviceID = AudioDeviceID(0) - var idSize = UInt32(MemoryLayout.size) - let translated = withUnsafeMutablePointer(to: &cfUID) { qualifier in - AudioObjectGetPropertyData( - AudioRoute.systemObject, &translate, UInt32(MemoryLayout.size), qualifier, - &idSize, &deviceID) + /// Whether the device carrying `uid` comes up as capturing within the + /// Bluetooth cap — the widest the product itself ever waits. + private static func waitForRunning(uid: String) async -> Bool { + await poll(upTo: MicLiveness.bluetoothTimeout) { isRunningSomewhere(uid: uid) } } - guard translated == noErr, deviceID != 0 else { return false } - var address = AudioRoute.globalAddress(kAudioDevicePropertyDeviceIsRunningSomewhere) - var running = UInt32(0) - var size = UInt32(MemoryLayout.size) - guard AudioObjectGetPropertyData(deviceID, &address, 0, nil, &size, &running) == noErr else { - return false + /// CoreAudio's own answer to "is this device capturing right now" — the bit + /// behind the system input indicator. Test-local rather than a production + /// helper: nothing in the app needs to ask, and the point of the assertions + /// above is to check the *device*, not our bookkeeping about it. + private static func isRunningSomewhere(uid: String) -> Bool { + var translate = AudioRoute.globalAddress(kAudioHardwarePropertyTranslateUIDToDevice) + var cfUID = uid as CFString + var deviceID = AudioDeviceID(0) + var idSize = UInt32(MemoryLayout.size) + let translated = withUnsafeMutablePointer(to: &cfUID) { qualifier in + AudioObjectGetPropertyData( + AudioRoute.systemObject, &translate, UInt32(MemoryLayout.size), qualifier, + &idSize, &deviceID) + } + guard translated == noErr, deviceID != 0 else { return false } + + var address = AudioRoute.globalAddress(kAudioDevicePropertyDeviceIsRunningSomewhere) + var running = UInt32(0) + var size = UInt32(MemoryLayout.size) + guard AudioObjectGetPropertyData(deviceID, &address, 0, nil, &size, &running) == noErr else { + return false + } + return running != 0 } - return running != 0 } -} +#endif diff --git a/Tests/BlurtEngineTests/BrowserBundleIDTests.swift b/Tests/BlurtEngineTests/BrowserBundleIDTests.swift index 967ad2fa..c1f64609 100644 --- a/Tests/BlurtEngineTests/BrowserBundleIDTests.swift +++ b/Tests/BlurtEngineTests/BrowserBundleIDTests.swift @@ -1,144 +1,146 @@ -import AppKit -import Foundation -import Testing +#if os(macOS) + import AppKit + import Foundation + import Testing -@testable import BlurtEngine + @testable import BlurtEngine -/// Pins the browser classification behind the injector's AX-opaque exemption -/// (see `FocusCapture.isAXOpaqueApp`): a known browser pastes even when the -/// focused element exposes no editable AX signal, because web content is -/// routinely opaque (Chromium's lazy accessibility tree, `contenteditable` -/// composers like ChatGPT's) — "no signal" there means "AX can't see the -/// field," not "no field." -@Suite("FocusCapture.isBrowserBundleID") -struct BrowserBundleIDTests { - @Test( - "known browser bundle IDs classify as browsers", - arguments: [ - "com.apple.Safari", - "com.google.Chrome", - "org.chromium.Chromium", - "com.microsoft.edgemac", - "com.brave.Browser", - "com.operasoftware.Opera", - "com.vivaldi.Vivaldi", - "company.thebrowser.Browser", - "org.mozilla.firefox", - "com.duckduckgo.macos.browser", - "com.kagi.kagimacOS", - ]) - func knownBrowsers(bundleID: String) { - #expect(FocusCapture.isBrowserBundleID(bundleID)) - } + /// Pins the browser classification behind the injector's AX-opaque exemption + /// (see `FocusCapture.isAXOpaqueApp`): a known browser pastes even when the + /// focused element exposes no editable AX signal, because web content is + /// routinely opaque (Chromium's lazy accessibility tree, `contenteditable` + /// composers like ChatGPT's) — "no signal" there means "AX can't see the + /// field," not "no field." + @Suite("FocusCapture.isBrowserBundleID") + struct BrowserBundleIDTests { + @Test( + "known browser bundle IDs classify as browsers", + arguments: [ + "com.apple.Safari", + "com.google.Chrome", + "org.chromium.Chromium", + "com.microsoft.edgemac", + "com.brave.Browser", + "com.operasoftware.Opera", + "com.vivaldi.Vivaldi", + "company.thebrowser.Browser", + "org.mozilla.firefox", + "com.duckduckgo.macos.browser", + "com.kagi.kagimacOS", + ]) + func knownBrowsers(bundleID: String) { + #expect(FocusCapture.isBrowserBundleID(bundleID)) + } - @Test( - "channel variants classify with their stable siblings (prefix match)", - arguments: [ - "com.apple.SafariTechnologyPreview", - "com.google.Chrome.beta", - "com.google.Chrome.canary", - "com.microsoft.edgemac.Dev", - "com.brave.Browser.nightly", - ]) - func channelVariants(bundleID: String) { - #expect(FocusCapture.isBrowserBundleID(bundleID)) - } + @Test( + "channel variants classify with their stable siblings (prefix match)", + arguments: [ + "com.apple.SafariTechnologyPreview", + "com.google.Chrome.beta", + "com.google.Chrome.canary", + "com.microsoft.edgemac.Dev", + "com.brave.Browser.nightly", + ]) + func channelVariants(bundleID: String) { + #expect(FocusCapture.isBrowserBundleID(bundleID)) + } - @Test( - "non-browser apps are not browsers — they keep the copy-don't-beep fallback", - arguments: [ - "com.apple.finder", - "com.apple.TextEdit", - "com.apple.dt.Xcode", - "com.microsoft.VSCode", // Electron: exempted by isElectronApp, not here - "com.googlecode.iterm2", // "com.google" lookalike must not prefix-match - ]) - func nonBrowsers(bundleID: String) { - #expect(!FocusCapture.isBrowserBundleID(bundleID)) - } + @Test( + "non-browser apps are not browsers — they keep the copy-don't-beep fallback", + arguments: [ + "com.apple.finder", + "com.apple.TextEdit", + "com.apple.dt.Xcode", + "com.microsoft.VSCode", // Electron: exempted by isElectronApp, not here + "com.googlecode.iterm2", // "com.google" lookalike must not prefix-match + ]) + func nonBrowsers(bundleID: String) { + #expect(!FocusCapture.isBrowserBundleID(bundleID)) + } - @Test("a nil bundle ID is not a browser") - func nilBundleID() { - #expect(!FocusCapture.isBrowserBundleID(nil)) + @Test("a nil bundle ID is not a browser") + func nilBundleID() { + #expect(!FocusCapture.isBrowserBundleID(nil)) + } } -} -/// The other half of the AX-opaque exemption: Electron detection, and the -/// `isAXOpaqueApp` disjunction the injector actually calls. -/// -/// Electron apps are classified by the framework they bundle rather than by -/// bundle ID, because the set is open-ended (every Electron app ever shipped), -/// so the fixtures here are directory trees rather than identifier strings — -/// `isElectronBundle` is split out of the `NSRunningApplication` wrapper for -/// exactly that reason. -@Suite("FocusCapture AX-opaque app classification") -struct AXOpaqueAppTests { + /// The other half of the AX-opaque exemption: Electron detection, and the + /// `isAXOpaqueApp` disjunction the injector actually calls. + /// + /// Electron apps are classified by the framework they bundle rather than by + /// bundle ID, because the set is open-ended (every Electron app ever shipped), + /// so the fixtures here are directory trees rather than identifier strings — + /// `isElectronBundle` is split out of the `NSRunningApplication` wrapper for + /// exactly that reason. + @Suite("FocusCapture AX-opaque app classification") + struct AXOpaqueAppTests { - /// An app bundle skeleton in a temp directory, with the Electron framework - /// present or absent. Only the *path* matters to the check — nothing is loaded — - /// so an empty directory at the framework's location is a faithful fixture. - private func makeBundle(withElectron: Bool) throws -> URL { - let bundle = URL.temporaryDirectory.appending(path: "Blurt-\(UUID().uuidString).app") - let contents = - withElectron - ? bundle.appending(path: "Contents/Frameworks/Electron Framework.framework") - : bundle.appending(path: "Contents/Frameworks") - try FileManager.default.createDirectory(at: contents, withIntermediateDirectories: true) - return bundle - } + /// An app bundle skeleton in a temp directory, with the Electron framework + /// present or absent. Only the *path* matters to the check — nothing is loaded — + /// so an empty directory at the framework's location is a faithful fixture. + private func makeBundle(withElectron: Bool) throws -> URL { + let bundle = URL.temporaryDirectory.appending(path: "Blurt-\(UUID().uuidString).app") + let contents = + withElectron + ? bundle.appending(path: "Contents/Frameworks/Electron Framework.framework") + : bundle.appending(path: "Contents/Frameworks") + try FileManager.default.createDirectory(at: contents, withIntermediateDirectories: true) + return bundle + } - // MARK: isElectronBundle + // MARK: isElectronBundle - @Test("a bundle shipping the Electron framework is Electron") - func electronBundleDetected() throws { - let bundle = try makeBundle(withElectron: true) - defer { try? FileManager.default.removeItem(at: bundle) } - // The true arm is what keeps VS Code and Slack on the paste path: their focused - // text fields expose no editable AX signal, so without this they'd fall back to - // copy-only and the user's words would never land. - #expect(FocusCapture.isElectronBundle(bundle)) - } + @Test("a bundle shipping the Electron framework is Electron") + func electronBundleDetected() throws { + let bundle = try makeBundle(withElectron: true) + defer { try? FileManager.default.removeItem(at: bundle) } + // The true arm is what keeps VS Code and Slack on the paste path: their focused + // text fields expose no editable AX signal, so without this they'd fall back to + // copy-only and the user's words would never land. + #expect(FocusCapture.isElectronBundle(bundle)) + } - @Test("a native bundle with no Electron framework is not Electron") - func nativeBundleRejected() throws { - let bundle = try makeBundle(withElectron: false) - defer { try? FileManager.default.removeItem(at: bundle) } - // The false arm matters just as much: a native app with genuinely nothing - // editable focused must fall back to copy rather than beep a ⌘V. - #expect(!FocusCapture.isElectronBundle(bundle)) - } + @Test("a native bundle with no Electron framework is not Electron") + func nativeBundleRejected() throws { + let bundle = try makeBundle(withElectron: false) + defer { try? FileManager.default.removeItem(at: bundle) } + // The false arm matters just as much: a native app with genuinely nothing + // editable focused must fall back to copy rather than beep a ⌘V. + #expect(!FocusCapture.isElectronBundle(bundle)) + } - @Test("a bundle URL that doesn't exist is not Electron") - func missingBundleRejected() { - #expect(!FocusCapture.isElectronBundle(URL(filePath: "/nonexistent/Ghost.app"))) - } + @Test("a bundle URL that doesn't exist is not Electron") + func missingBundleRejected() { + #expect(!FocusCapture.isElectronBundle(URL(filePath: "/nonexistent/Ghost.app"))) + } - @Test("a nil bundle URL is not Electron") - func nilBundleURLRejected() { - #expect(!FocusCapture.isElectronBundle(nil)) - } + @Test("a nil bundle URL is not Electron") + func nilBundleURLRejected() { + #expect(!FocusCapture.isElectronBundle(nil)) + } - // MARK: NSRunningApplication wrappers + // MARK: NSRunningApplication wrappers - @Test("the test host is neither a browser nor Electron") - func testHostIsNotOpaque() { - // The one live `NSRunningApplication` a unit test can count on. Weak as an - // assertion about *this* process, but it pins the wrappers as pass-throughs to - // the two pure checks rather than, say, defaulting to opaque — which would make - // the injector paste into every non-editable target and beep. - let current = NSRunningApplication.current - #expect(!FocusCapture.isBrowserApp(current)) - #expect(!FocusCapture.isElectronApp(current)) - #expect(!FocusCapture.isAXOpaqueApp(current)) - } + @Test("the test host is neither a browser nor Electron") + func testHostIsNotOpaque() { + // The one live `NSRunningApplication` a unit test can count on. Weak as an + // assertion about *this* process, but it pins the wrappers as pass-throughs to + // the two pure checks rather than, say, defaulting to opaque — which would make + // the injector paste into every non-editable target and beep. + let current = NSRunningApplication.current + #expect(!FocusCapture.isBrowserApp(current)) + #expect(!FocusCapture.isElectronApp(current)) + #expect(!FocusCapture.isAXOpaqueApp(current)) + } - @Test("no app at all is not AX-opaque") - func nilAppIsNotOpaque() { - // `KeyInjector` passes its captured target, which is nil when nothing was - // captured — that must not be treated as opaque, or a paste with no known - // target would be attempted anyway. - #expect(!FocusCapture.isBrowserApp(nil)) - #expect(!FocusCapture.isElectronApp(nil)) - #expect(!FocusCapture.isAXOpaqueApp(nil)) + @Test("no app at all is not AX-opaque") + func nilAppIsNotOpaque() { + // `KeyInjector` passes its captured target, which is nil when nothing was + // captured — that must not be treated as opaque, or a paste with no known + // target would be attempted anyway. + #expect(!FocusCapture.isBrowserApp(nil)) + #expect(!FocusCapture.isElectronApp(nil)) + #expect(!FocusCapture.isAXOpaqueApp(nil)) + } } -} +#endif diff --git a/Tests/BlurtEngineTests/CancelRaceTests.swift b/Tests/BlurtEngineTests/CancelRaceTests.swift index 67fcc3de..5e4d9a2b 100644 --- a/Tests/BlurtEngineTests/CancelRaceTests.swift +++ b/Tests/BlurtEngineTests/CancelRaceTests.swift @@ -1,4 +1,3 @@ -import AppKit import Foundation import Testing @@ -325,7 +324,7 @@ private actor GatedInjector: InjectorProtocol { self.onRecord = onRecord } - func setTargetApp(_ app: NSRunningApplication?) async {} + func setTarget(_ focus: CapturedFocus?) async {} func insert(_ text: String, after priorText: String?, windowTitle: String?) async throws { await gate.enter() diff --git a/Tests/BlurtEngineTests/ChunkedUploadTests.swift b/Tests/BlurtEngineTests/ChunkedUploadTests.swift index 77a456c4..fc5a0716 100644 --- a/Tests/BlurtEngineTests/ChunkedUploadTests.swift +++ b/Tests/BlurtEngineTests/ChunkedUploadTests.swift @@ -140,7 +140,7 @@ struct ChunkedUploadTests { let session = makeSession( transcriber: FailsBeforeContext(), seams: testSeams( - field: FocusCapture.FocusedFieldContext( + field: FocusedFieldContext( priorText: "Dear Sam,", selectedText: nil, windowTitle: nil, fieldLabel: nil), log: log)) diff --git a/Tests/BlurtEngineTests/DictationLogTests.swift b/Tests/BlurtEngineTests/DictationLogTests.swift index 99a777bb..c5d878ab 100644 --- a/Tests/BlurtEngineTests/DictationLogTests.swift +++ b/Tests/BlurtEngineTests/DictationLogTests.swift @@ -114,7 +114,7 @@ struct DictationLogEntryTests { func priorIsRawWhereTheTurnIsTrimmed() { // Why `prior` isn't redundant with the prompt's tail. The trailing space is the // whole input to the paste's leading-separator decision - // (`KeyInjector.withLeadingSeparator` branches on `prior.last.isWhitespace`), + // (`InsertionSeparator.withLeadingSeparator` branches on `prior.last.isWhitespace`), // and the wire copy has it trimmed off — so dropping `prior` for being a // duplicate would take the only record of that bit with it. let entry = DictationLog.makeEntry( @@ -122,8 +122,8 @@ struct DictationLogEntryTests { now: Date()) #expect(entry.prior == "Hi Sam, ") #expect(entry.sttPrompt == "Hi Sam,") - #expect(KeyInjector.withLeadingSeparator("p", after: entry.prior) == "p") - #expect(KeyInjector.withLeadingSeparator("p", after: entry.sttPrompt) == " p") + #expect(InsertionSeparator.withLeadingSeparator("p", after: entry.prior) == "p") + #expect(InsertionSeparator.withLeadingSeparator("p", after: entry.sttPrompt) == " p") } @Test("a nil prior tells a history-only prompt apart from a prior chunk") diff --git a/Tests/BlurtEngineTests/DictationSessionContextTests.swift b/Tests/BlurtEngineTests/DictationSessionContextTests.swift index cb10b644..be8d044b 100644 --- a/Tests/BlurtEngineTests/DictationSessionContextTests.swift +++ b/Tests/BlurtEngineTests/DictationSessionContextTests.swift @@ -11,14 +11,14 @@ import Testing /// the seams (`testSeams`) both are ordinary values. @Suite("DictationSession captured context", .timeLimit(.minutes(1))) struct DictationSessionContextTests { - private static let field = FocusCapture.FocusedFieldContext( + private static let field = FocusedFieldContext( priorText: "Hi Sam,", selectedText: "the old plan", windowTitle: "Re: Q3 pricing", fieldLabel: "Body") /// The secure-target fixture, shared by the two tests that assert a password /// is never remembered — one where the read lands in time, one where it lands /// after the upload's budget. - private static let secureField = FocusCapture.FocusedFieldContext( + private static let secureField = FocusedFieldContext( priorText: nil, selectedText: nil, windowTitle: "1Password", fieldLabel: "Password", isSecure: true) @@ -217,7 +217,7 @@ struct DictationSessionContextTests { // `isEmpty` has to count `targetIsSecure`: a secure field yields no prior or // selected text, so without that the snapshot would collapse to `nil` on the // way through `contextStream` and the guard above would never see the flag. - let secure = FocusCapture.FocusedFieldContext( + let secure = FocusedFieldContext( priorText: nil, selectedText: nil, windowTitle: nil, fieldLabel: nil, isSecure: true) #expect(!TranscriptionContext(appName: nil, priorText: nil, targetIsSecure: true).isEmpty) let fixture = makeSession(mode: .transcript("hunter2"), field: secure, frontmost: nil) @@ -313,7 +313,7 @@ struct DictationSessionFailureLogTests { func failureIsLogged() async throws { let fixture = makeSession( mode: .throwError(BlurtError.apiKeyMissing), - field: FocusCapture.FocusedFieldContext( + field: FocusedFieldContext( priorText: nil, selectedText: nil, windowTitle: "Vault", fieldLabel: "Password")) await fixture.session.press() diff --git a/Tests/BlurtEngineTests/EditableTargetTests.swift b/Tests/BlurtEngineTests/EditableTargetTests.swift index 27e45b7d..48297d38 100644 --- a/Tests/BlurtEngineTests/EditableTargetTests.swift +++ b/Tests/BlurtEngineTests/EditableTargetTests.swift @@ -1,76 +1,78 @@ -import Testing +#if os(macOS) + import Testing -@testable import BlurtEngine + @testable import BlurtEngine -@Suite("FocusCapture.isEditableTarget") -struct EditableTargetTests { - @Test("a known text role is editable") - func textRole() { - #expect( - FocusCapture.isEditableTarget( - role: "AXTextArea", valueSettable: false, hasInsertionPoint: false)) - } + @Suite("FocusCapture.isEditableTarget") + struct EditableTargetTests { + @Test("a known text role is editable") + func textRole() { + #expect( + FocusCapture.isEditableTarget( + role: "AXTextArea", valueSettable: false, hasInsertionPoint: false)) + } - @Test("a secure (password) field is still a paste target despite prompt redaction") - func secureFieldIsEditable() { - // Redaction (never read a password into the STT prompt) and editability - // (the paste may land there) are independent: dictating into a password - // field must type, even though its contents are never captured. - #expect( - FocusCapture.isEditableTarget( - role: FocusCapture.secureFieldRole, valueSettable: false, hasInsertionPoint: false)) - } + @Test("a secure (password) field is still a paste target despite prompt redaction") + func secureFieldIsEditable() { + // Redaction (never read a password into the STT prompt) and editability + // (the paste may land there) are independent: dictating into a password + // field must type, even though its contents are never captured. + #expect( + FocusCapture.isEditableTarget( + role: FocusCapture.secureFieldRole, valueSettable: false, hasInsertionPoint: false)) + } - @Test("a settable value is editable even with an unknown role") - func settableValue() { - #expect( - FocusCapture.isEditableTarget( - role: "AXUnknown", valueSettable: true, hasInsertionPoint: false)) - } + @Test("a settable value is editable even with an unknown role") + func settableValue() { + #expect( + FocusCapture.isEditableTarget( + role: "AXUnknown", valueSettable: true, hasInsertionPoint: false)) + } - @Test("an insertion point is editable even with an unknown role") - func insertionPoint() { - #expect( - FocusCapture.isEditableTarget( - role: nil, valueSettable: false, hasInsertionPoint: true)) - } + @Test("an insertion point is editable even with an unknown role") + func insertionPoint() { + #expect( + FocusCapture.isEditableTarget( + role: nil, valueSettable: false, hasInsertionPoint: true)) + } - @Test("a non-text control with no editable signal is not editable") - func nonEditableControl() { - #expect( - !FocusCapture.isEditableTarget( - role: "AXButton", valueSettable: false, hasInsertionPoint: false)) - } + @Test("a non-text control with no editable signal is not editable") + func nonEditableControl() { + #expect( + !FocusCapture.isEditableTarget( + role: "AXButton", valueSettable: false, hasInsertionPoint: false)) + } - @Test("an unknown role with no editable signal is not editable (copy, don't beep)") - func unknownRoleWithoutSignalCopies() { - // A focused element that reports an unrecognized role and exposes no settable - // value or insertion point isn't a text target — copy rather than beep a ⌘V - // into it. (AX-opaque apps — Electron editors and browsers — also land here, - // but are pasted into via the injector's separate app-identity check, not - // this signal test.) - #expect( - !FocusCapture.isEditableTarget( - role: "AXWebArea", valueSettable: false, hasInsertionPoint: false)) - } + @Test("an unknown role with no editable signal is not editable (copy, don't beep)") + func unknownRoleWithoutSignalCopies() { + // A focused element that reports an unrecognized role and exposes no settable + // value or insertion point isn't a text target — copy rather than beep a ⌘V + // into it. (AX-opaque apps — Electron editors and browsers — also land here, + // but are pasted into via the injector's separate app-identity check, not + // this signal test.) + #expect( + !FocusCapture.isEditableTarget( + role: "AXWebArea", valueSettable: false, hasInsertionPoint: false)) + } - @Test("a focused element with an unreadable role is not editable (copy, don't beep)") - func nilRoleWithoutSignalCopies() { - #expect( - !FocusCapture.isEditableTarget( - role: nil, valueSettable: false, hasInsertionPoint: false)) + @Test("a focused element with an unreadable role is not editable (copy, don't beep)") + func nilRoleWithoutSignalCopies() { + #expect( + !FocusCapture.isEditableTarget( + role: nil, valueSettable: false, hasInsertionPoint: false)) + } } -} -@Suite("noTarget phase + overlay mapping") -struct NoTargetPhaseTests { - @Test("noTarget is terminal") - func terminal() { - #expect(PipelinePhase.noTarget.isTerminal) - } + @Suite("noTarget phase + overlay mapping") + struct NoTargetPhaseTests { + @Test("noTarget is terminal") + func terminal() { + #expect(PipelinePhase.noTarget.isTerminal) + } - @Test("noTarget maps to the quiet overlay state, not an error") - func overlayMapping() { - #expect(PipelinePhase.noTarget.overlayState == .noTarget) + @Test("noTarget maps to the quiet overlay state, not an error") + func overlayMapping() { + #expect(PipelinePhase.noTarget.overlayState == .noTarget) + } } -} +#endif diff --git a/Tests/BlurtEngineTests/FocusCaptureTests.swift b/Tests/BlurtEngineTests/FocusCaptureTests.swift index c2fdbe3a..35b1e6b7 100644 --- a/Tests/BlurtEngineTests/FocusCaptureTests.swift +++ b/Tests/BlurtEngineTests/FocusCaptureTests.swift @@ -222,11 +222,13 @@ struct FocusCaptureTests { // MARK: isElectronApp - @Test("isElectronApp is false for a missing app") - func electronNilApp() { - // The positive branch probes the app bundle on disk and is host-dependent; - // the nil guard (no captured target → never the Electron paste exception) - // is the deterministic half. - #expect(!FocusCapture.isElectronApp(nil)) - } + #if os(macOS) + @Test("isElectronApp is false for a missing app") + func electronNilApp() { + // The positive branch probes the app bundle on disk and is host-dependent; + // the nil guard (no captured target → never the Electron paste exception) + // is the deterministic half. + #expect(!FocusCapture.isElectronApp(nil)) + } + #endif } diff --git a/Tests/BlurtEngineTests/InsertionSeparatorTests.swift b/Tests/BlurtEngineTests/InsertionSeparatorTests.swift new file mode 100644 index 00000000..97198f25 --- /dev/null +++ b/Tests/BlurtEngineTests/InsertionSeparatorTests.swift @@ -0,0 +1,164 @@ +// Foundation for `pid_t`: the resolve-insert suite below names it, and the two +// pure text-rule suites this file started as needed no imports at all. +import Foundation +import Testing + +@testable import BlurtEngine + +@Suite("InsertionSeparator.withLeadingSeparator") +struct InsertionSeparatorTests { + @Test("prepends a space when prior text doesn't end in whitespace") + func prependsSpace() { + #expect(InsertionSeparator.withLeadingSeparator("Second.", after: "First.") == " Second.") + } + + @Test("no separator when prior text already ends in a space") + func priorEndsInSpace() { + #expect(InsertionSeparator.withLeadingSeparator("Second.", after: "First. ") == "Second.") + } + + @Test("no separator when prior text ends in a newline") + func priorEndsInNewline() { + #expect(InsertionSeparator.withLeadingSeparator("Second.", after: "First.\n") == "Second.") + } + + @Test("no leading space into an empty field (nil prior text)") + func nilPrior() { + #expect(InsertionSeparator.withLeadingSeparator("Second.", after: nil) == "Second.") + } + + @Test("no leading space when prior text is empty") + func emptyPrior() { + #expect(InsertionSeparator.withLeadingSeparator("Second.", after: "") == "Second.") + } + + @Test("doesn't double up when the new text already starts with whitespace") + func textStartsWithSpace() { + #expect(InsertionSeparator.withLeadingSeparator(" Second.", after: "First.") == " Second.") + } + + @Test("returns empty text unchanged") + func emptyText() { + #expect(InsertionSeparator.withLeadingSeparator("", after: "First.") == "") + } + + @Test("every whitespace class counts, not just space and newline") + func otherWhitespaceClasses() { + // The rules key on Character.isWhitespace: a trailing tab, carriage return, + // or non-breaking space suppresses the separator like a plain space does… + #expect(InsertionSeparator.withLeadingSeparator("Second.", after: "First.\t") == "Second.") + #expect(InsertionSeparator.withLeadingSeparator("Second.", after: "First.\r") == "Second.") + #expect(InsertionSeparator.withLeadingSeparator("Second.", after: "First.\u{00A0}") == "Second.") + // …and text already leading with a tab or non-breaking space isn't doubled. + #expect(InsertionSeparator.withLeadingSeparator("\tSecond.", after: "First.") == "\tSecond.") + #expect(InsertionSeparator.withLeadingSeparator("\u{00A0}Second.", after: "First.") == "\u{00A0}Second.") + } +} + +@Suite("InsertionSeparator.basis") +struct InsertionSeparatorBasisTests { + @Test("AX-read prior text wins even when a prior paste is on record") + func priorTextWins() { + #expect( + InsertionSeparator.basis(priorText: "AX.", lastInserted: "Old.", sameWindow: false) == "AX.") + } + + @Test("falls back to the last paste when AX is opaque and the window is unchanged") + func opaqueSameWindowFallsBack() { + #expect( + InsertionSeparator.basis(priorText: nil, lastInserted: "First.", sameWindow: true) + == "First.") + } + + @Test("does not carry a prior paste across a different window") + func opaqueDifferentWindowNoFallback() { + #expect( + InsertionSeparator.basis(priorText: nil, lastInserted: "First.", sameWindow: false) == nil) + } + + @Test("no basis when AX is opaque and nothing was pasted yet") + func opaqueNoPriorPaste() { + #expect(InsertionSeparator.basis(priorText: nil, lastInserted: nil, sameWindow: true) == nil) + } +} + +#if os(macOS) + /// `resolveInsert` — everything `performInsert` decides before it activates + /// anything: the text to write and the window to remember writing it into. The + /// same-window derivation used to be inline in `performInsert`, so these cases + /// could only be driven by scraping `NSWorkspace` for live applications (and one + /// of them by requiring two). Here the target is just a pid. + @Suite("KeyInjector.resolveInsert") + struct KeyInjectorResolveInsertTests { + private let editor = KeyInjector.WindowIdentity(pid: 501, title: "notes.txt — Editor") + + /// A second dictation with no AX prior text, resolved against `editor`. + private func secondInsert( + targetPID: pid_t?, windowTitle: String?, priorText: String? = nil + ) -> KeyInjector.ResolvedInsert { + KeyInjector.resolveInsert( + text: "Second.", priorText: priorText, windowTitle: windowTitle, targetPID: targetPID, + lastInserted: KeyInjector.ResolvedInsert(text: "First.", window: editor)) + } + + @Test("opaque editor: the same pid and title recovers the spacing from the last paste") + func sameWindowSeparates() { + // Two back-to-back dictations into the same VS Code file or Google Docs tab: + // AX gives no prior text, so what we pasted a moment ago is what precedes + // the caret. + #expect( + secondInsert(targetPID: editor.pid, windowTitle: editor.title) + == KeyInjector.ResolvedInsert(text: " Second.", window: editor)) + } + + @Test("opaque editor: a changed title is a different field, so no phantom space") + func changedTitleDoesNotSeparate() { + // One browser process (or one Electron window) but a different tab or file — + // a shared pid alone must not carry spacing into an unrelated document. The + // new window is still remembered, so a *third* dictation into it separates. + let resolved = secondInsert(targetPID: editor.pid, windowTitle: "Untitled document — Docs") + #expect(resolved.text == "Second.") + #expect(resolved.window == KeyInjector.WindowIdentity(pid: editor.pid, title: "Untitled document — Docs")) + } + + @Test("no readable window title means no match and nothing to remember") + func missingTitleDoesNotSeparate() { + // Can't confirm it's the same window, so the fallback stays off rather than + // guessing — and with no identity to record, the next dictation can't match + // this one either. + #expect( + secondInsert(targetPID: editor.pid, windowTitle: nil) + == KeyInjector.ResolvedInsert(text: "Second.", window: nil)) + } + + @Test("a different target app never inherits the previous paste's spacing") + func changedTargetDoesNotSeparate() { + let resolved = secondInsert(targetPID: 777, windowTitle: editor.title) + #expect(resolved.text == "Second.") + #expect(resolved.window == KeyInjector.WindowIdentity(pid: 777, title: editor.title)) + } + + @Test("no captured target at all: nothing to match, nothing to remember") + func noTargetDoesNotSeparate() { + #expect( + secondInsert(targetPID: nil, windowTitle: editor.title) + == KeyInjector.ResolvedInsert(text: "Second.", window: nil)) + } + + @Test("AX prior text wins over the remembered paste, in the same window or not") + func priorTextWinsOverMemory() { + // The field is readable, so the caret's real neighbour decides — here it + // already ends in whitespace, which the remembered "First." would not have. + #expect(secondInsert(targetPID: editor.pid, windowTitle: editor.title, priorText: "Hello ").text == "Second.") + #expect(secondInsert(targetPID: 777, windowTitle: "Other", priorText: "Hello").text == " Second.") + } + + @Test("a first-ever insert has no memory to fall back on") + func firstInsertHasNoBasis() { + let resolved = KeyInjector.resolveInsert( + text: "First.", priorText: nil, windowTitle: editor.title, targetPID: editor.pid, + lastInserted: nil) + #expect(resolved == KeyInjector.ResolvedInsert(text: "First.", window: editor)) + } + } +#endif diff --git a/Tests/BlurtEngineTests/KeyInjectorFallbackTests.swift b/Tests/BlurtEngineTests/KeyInjectorFallbackTests.swift index f6978ec7..f7f80b22 100644 --- a/Tests/BlurtEngineTests/KeyInjectorFallbackTests.swift +++ b/Tests/BlurtEngineTests/KeyInjectorFallbackTests.swift @@ -1,97 +1,99 @@ -import AppKit -import Foundation -import Testing +#if os(macOS) + import AppKit + import Foundation + import Testing -@testable import BlurtEngine + @testable import BlurtEngine -/// Exercises `KeyInjector.insert`'s abort paths: the mid-activation cancel gate -/// and the copy-to-clipboard fallbacks. Split from `KeyInjectorInsertTests` -/// (same seams, same shared fixtures in `Stubs/InjectorTestSupport.swift`) to -/// stay within the lint file-length budget. -@Suite("KeyInjector.insert fallback & cancel") -struct KeyInjectorFallbackTests { + /// Exercises `KeyInjector.insert`'s abort paths: the mid-activation cancel gate + /// and the copy-to-clipboard fallbacks. Split from `KeyInjectorInsertTests` + /// (same seams, same shared fixtures in `Stubs/InjectorTestSupport.swift`) to + /// stay within the lint file-length budget. + @Suite("KeyInjector.insert fallback & cancel") + struct KeyInjectorFallbackTests { - @Test("a cancel landing during target activation aborts before the paste") - func cancelDuringActivationSkipsPaste() async throws { - let clip = FakeClipboard(string: "user-clipboard") - let posted = ValueBox(false) - let insertTask = ValueBox?>(nil) - let injector = KeyInjector( - pasteSettleDuration: .zero, - postPaste: { - posted.value = true - return true - }, - activateTarget: { _ in - // The cancel lands while activation is in flight; activation itself - // still succeeds, so only the post-activation cancellation gate stands - // between the cancel and the irreversible ⌘V. - insertTask.value?.cancel() - return true - }, - clipboard: clip) - await injector.setTargetApp(try liveTargetApp()) + @Test("a cancel landing during target activation aborts before the paste") + func cancelDuringActivationSkipsPaste() async throws { + let clip = FakeClipboard(string: "user-clipboard") + let posted = ValueBox(false) + let insertTask = ValueBox?>(nil) + let injector = KeyInjector( + pasteSettleDuration: .zero, + postPaste: { + posted.value = true + return true + }, + activateTarget: { _ in + // The cancel lands while activation is in flight; activation itself + // still succeeds, so only the post-activation cancellation gate stands + // between the cancel and the irreversible ⌘V. + insertTask.value?.cancel() + return true + }, + clipboard: clip) + await injector.setTarget(try liveTargetFocus()) - // Park the insert behind a gate until the task handle is stored, so the - // activation closure deterministically has something to cancel. - let gate = AsyncGate() - let task = Task { - await gate.wait() - try await injector.insert("text") - } - insertTask.value = task - gate.open() + // Park the insert behind a gate until the task handle is stored, so the + // activation closure deterministically has something to cancel. + let gate = AsyncGate() + let task = Task { + await gate.wait() + try await injector.insert("text") + } + insertTask.value = task + gate.open() - await #expect(throws: CancellationError.self) { - try await task.value + await #expect(throws: CancellationError.self) { + try await task.value + } + // No ⌘V was posted and the user's clipboard was never touched — the abort + // happened before the save/overwrite stage. + #expect(posted.value == false) + #expect(clip.string == "user-clipboard") } - // No ⌘V was posted and the user's clipboard was never touched — the abort - // happened before the save/overwrite stage. - #expect(posted.value == false) - #expect(clip.string == "user-clipboard") - } - @Test("the clipboard fallback carries the leading separator, not the raw text") - func fallbackKeepsLeadingSeparator() async throws { - let clip = FakeClipboard(string: "user-clipboard") - let injector = KeyInjector( - pasteSettleDuration: .zero, - postPaste: { true }, - activateTarget: { _ in false }, - clipboard: clip) - await injector.setTargetApp(try liveTargetApp()) + @Test("the clipboard fallback carries the leading separator, not the raw text") + func fallbackKeepsLeadingSeparator() async throws { + let clip = FakeClipboard(string: "user-clipboard") + let injector = KeyInjector( + pasteSettleDuration: .zero, + postPaste: { true }, + activateTarget: { _ in false }, + clipboard: clip) + await injector.setTarget(try liveTargetFocus()) - await #expect(throws: BlurtError.targetAppLost) { - try await injector.insert("Second.", after: "First.") + await #expect(throws: BlurtError.targetAppLost) { + try await injector.insert("Second.", after: "First.") + } + // What lands on the clipboard is the final text a paste would have typed — + // separator included — so a manual ⌘V still joins the prior text correctly. + #expect(clip.string == " Second.") } - // What lands on the clipboard is the final text a paste would have typed — - // separator included — so a manual ⌘V still joins the prior text correctly. - #expect(clip.string == " Second.") - } - @Test("a thrown insert releases the paste lock for the next dictation", .timeLimit(.minutes(1))) - func failedInsertReleasesLock() async throws { - let clip = FakeClipboard(string: "user-clipboard") - let editable = ValueBox(false) - let injector = KeyInjector( - pasteSettleDuration: .zero, - postPaste: { true }, - hasEditableTarget: { editable.value }, - clipboard: clip) + @Test("a thrown insert releases the paste lock for the next dictation", .timeLimit(.minutes(1))) + func failedInsertReleasesLock() async throws { + let clip = FakeClipboard(string: "user-clipboard") + let editable = ValueBox(false) + let injector = KeyInjector( + pasteSettleDuration: .zero, + postPaste: { true }, + hasEditableTarget: { editable.value }, + clipboard: clip) - // First insert: nothing editable focused → copy fallback throws. - await #expect(throws: BlurtError.noEditableTarget) { - try await injector.insert("first") - } + // First insert: nothing editable focused → copy fallback throws. + await #expect(throws: BlurtError.noEditableTarget) { + try await injector.insert("first") + } - // The throw path must have released the paste lock: a following insert - // proceeds (rather than deadlocking behind a leaked lock, which the time - // limit would surface) and completes a normal paste + deferred restore. - editable.value = true - try await injector.insert("second") - await injector.pendingSettle?.value - // The restore brings back the pre-paste contents — which the failed insert - // deliberately left as its copied transcript. - #expect(clip.string == "first") + // The throw path must have released the paste lock: a following insert + // proceeds (rather than deadlocking behind a leaked lock, which the time + // limit would surface) and completes a normal paste + deferred restore. + editable.value = true + try await injector.insert("second") + await injector.pendingSettle?.value + // The restore brings back the pre-paste contents — which the failed insert + // deliberately left as its copied transcript. + #expect(clip.string == "first") + } } -} +#endif diff --git a/Tests/BlurtEngineTests/KeyInjectorInsertTests.swift b/Tests/BlurtEngineTests/KeyInjectorInsertTests.swift index 2e973308..d7685db6 100644 --- a/Tests/BlurtEngineTests/KeyInjectorInsertTests.swift +++ b/Tests/BlurtEngineTests/KeyInjectorInsertTests.swift @@ -1,289 +1,291 @@ -import AppKit -import Foundation -import Testing +#if os(macOS) + import AppKit + import Foundation + import Testing -@testable import BlurtEngine + @testable import BlurtEngine -/// Exercises `KeyInjector.insert` and its clipboard save/restore. The real Cmd-V -/// poster is replaced with an injected closure so no keystroke is sent to the -/// focused app, and an in-memory `FakeClipboard` stands in for the system -/// pasteboard so the save/restore + changeCount logic is tested in full -/// isolation — no dependency on (or races with) the host's real clipboard. -@Suite("KeyInjector.insert") -struct KeyInjectorInsertTests { + /// Exercises `KeyInjector.insert` and its clipboard save/restore. The real Cmd-V + /// poster is replaced with an injected closure so no keystroke is sent to the + /// focused app, and an in-memory `FakeClipboard` stands in for the system + /// pasteboard so the save/restore + changeCount logic is tested in full + /// isolation — no dependency on (or races with) the host's real clipboard. + @Suite("KeyInjector.insert") + struct KeyInjectorInsertTests { - @Test("restores the prior pasteboard contents after pasting") - func restoresClipboard() async throws { - let clip = FakeClipboard(string: "user-clipboard") - let injector = KeyInjector(pasteSettleDuration: .zero, postPaste: { true }, clipboard: clip) - try await injector.insert("dictated text") - // The restore is deferred to the background settle task; await it before - // asserting the user's clipboard came back. - await injector.pendingSettle?.value + @Test("restores the prior pasteboard contents after pasting") + func restoresClipboard() async throws { + let clip = FakeClipboard(string: "user-clipboard") + let injector = KeyInjector(pasteSettleDuration: .zero, postPaste: { true }, clipboard: clip) + try await injector.insert("dictated text") + // The restore is deferred to the background settle task; await it before + // asserting the user's clipboard came back. + await injector.pendingSettle?.value - #expect(clip.string == "user-clipboard") - } + #expect(clip.string == "user-clipboard") + } - @Test("insert returns before the deferred clipboard restore runs") - func deferRestoreReArmsEarly() async throws { - let clip = FakeClipboard(string: "user-clipboard") - // A 1s settle: long enough that the assertions below run well before the - // background restore fires, so the "still pending" checks are deterministic. - let injector = KeyInjector( - pasteSettleDuration: .seconds(1), postPaste: { true }, clipboard: clip) + @Test("insert returns before the deferred clipboard restore runs") + func deferRestoreReArmsEarly() async throws { + let clip = FakeClipboard(string: "user-clipboard") + // A 1s settle: long enough that the assertions below run well before the + // background restore fires, so the "still pending" checks are deterministic. + let injector = KeyInjector( + pasteSettleDuration: .seconds(1), postPaste: { true }, clipboard: clip) - try await injector.insert("dictated text") + try await injector.insert("dictated text") - // insert() has returned, but the restore is deferred: the pasted text is - // still on the clipboard and a settle task is in flight. This is what lets - // the pipeline re-arm immediately instead of waiting out the settle. - let settle = await injector.pendingSettle - #expect(clip.string == "dictated text") - #expect(settle != nil) + // insert() has returned, but the restore is deferred: the pasted text is + // still on the clipboard and a settle task is in flight. This is what lets + // the pipeline re-arm immediately instead of waiting out the settle. + let settle = await injector.pendingSettle + #expect(clip.string == "dictated text") + #expect(settle != nil) - // The backgrounded settle eventually restores the user's clipboard. - await settle?.value - #expect(clip.string == "user-clipboard") - } + // The backgrounded settle eventually restores the user's clipboard. + await settle?.value + #expect(clip.string == "user-clipboard") + } - @Test("activates a live target app before pasting") - func activatesTargetApp() async throws { - let activated = ValueBox(false) - let injector = KeyInjector( - pasteSettleDuration: .zero, - postPaste: { true }, - activateTarget: { _ in - activated.value = true - return true - }, - clipboard: FakeClipboard(string: nil)) - await injector.setTargetApp(try liveTargetApp()) - try await injector.insert("dictated text") // must not throw - #expect(activated.value) - } + @Test("activates a live target app before pasting") + func activatesTargetApp() async throws { + let activated = ValueBox(false) + let injector = KeyInjector( + pasteSettleDuration: .zero, + postPaste: { true }, + activateTarget: { _ in + activated.value = true + return true + }, + clipboard: FakeClipboard(string: nil)) + await injector.setTarget(try liveTargetFocus()) + try await injector.insert("dictated text") // must not throw + #expect(activated.value) + } - @Test("activation failure: skips the paste but leaves the transcript on the clipboard") - func activationFailureSkipsPaste() async throws { - let clip = FakeClipboard(string: "user-clipboard") - let posted = ValueBox(false) - let injector = KeyInjector( - pasteSettleDuration: .zero, - postPaste: { - posted.value = true - return true - }, - activateTarget: { _ in false }, - clipboard: clip) - await injector.setTargetApp(try liveTargetApp()) + @Test("activation failure: skips the paste but leaves the transcript on the clipboard") + func activationFailureSkipsPaste() async throws { + let clip = FakeClipboard(string: "user-clipboard") + let posted = ValueBox(false) + let injector = KeyInjector( + pasteSettleDuration: .zero, + postPaste: { + posted.value = true + return true + }, + activateTarget: { _ in false }, + clipboard: clip) + await injector.setTarget(try liveTargetFocus()) - await #expect(throws: BlurtError.targetAppLost) { - try await injector.insert("text") + await #expect(throws: BlurtError.targetAppLost) { + try await injector.insert("text") + } + // No ⌘V was posted into whatever now has focus, but the transcript survives + // on the clipboard so the failure degrades to a "copied" notice. + #expect(posted.value == false) + #expect(clip.string == "text") } - // No ⌘V was posted into whatever now has focus, but the transcript survives - // on the clipboard so the failure degrades to a "copied" notice. - #expect(posted.value == false) - #expect(clip.string == "text") - } - @Test("empty text is a no-op (no paste posted)") - func emptyTextNoOp() async throws { - let posted = ValueBox(false) - let injector = KeyInjector( - pasteSettleDuration: .zero, - postPaste: { - posted.value = true - return true - }) - try await injector.insert("") - #expect(posted.value == false) - } + @Test("empty text is a no-op (no paste posted)") + func emptyTextNoOp() async throws { + let posted = ValueBox(false) + let injector = KeyInjector( + pasteSettleDuration: .zero, + postPaste: { + posted.value = true + return true + }) + try await injector.insert("") + #expect(posted.value == false) + } - @Test("paste synthesis failure: throws .targetAppLost, transcript stays on the clipboard") - func pasteSynthesisFailureThrows() async { - let clip = FakeClipboard(string: "user-clipboard") - let injector = KeyInjector(pasteSettleDuration: .zero, postPaste: { false }, clipboard: clip) - await #expect(throws: BlurtError.targetAppLost) { - try await injector.insert("text") + @Test("paste synthesis failure: throws .targetAppLost, transcript stays on the clipboard") + func pasteSynthesisFailureThrows() async { + let clip = FakeClipboard(string: "user-clipboard") + let injector = KeyInjector(pasteSettleDuration: .zero, postPaste: { false }, clipboard: clip) + await #expect(throws: BlurtError.targetAppLost) { + try await injector.insert("text") + } + // The paste never happened, so the transcript is deliberately left on the + // clipboard (not restored away) — the user's words beat the stale snapshot. + #expect(clip.string == "text") } - // The paste never happened, so the transcript is deliberately left on the - // clipboard (not restored away) — the user's words beat the stale snapshot. - #expect(clip.string == "text") - } - @Test("throws .accessibilityPermissionMissing and leaves the clipboard untouched") - func notAccessibilityTrustedThrows() async throws { - let clip = FakeClipboard(string: "user-clipboard") - let posted = ValueBox(false) - let injector = KeyInjector( - pasteSettleDuration: .zero, - postPaste: { - posted.value = true - return true - }, - isAccessibilityTrusted: { false }, - clipboard: clip) + @Test("throws .accessibilityPermissionMissing and leaves the clipboard untouched") + func notAccessibilityTrustedThrows() async throws { + let clip = FakeClipboard(string: "user-clipboard") + let posted = ValueBox(false) + let injector = KeyInjector( + pasteSettleDuration: .zero, + postPaste: { + posted.value = true + return true + }, + isAccessibilityTrusted: { false }, + clipboard: clip) - await #expect(throws: BlurtError.accessibilityPermissionMissing) { - try await injector.insert("text") + await #expect(throws: BlurtError.accessibilityPermissionMissing) { + try await injector.insert("text") + } + // No paste posted, and the user's clipboard is left exactly as it was. + #expect(posted.value == false) + #expect(clip.string == "user-clipboard") } - // No paste posted, and the user's clipboard is left exactly as it was. - #expect(posted.value == false) - #expect(clip.string == "user-clipboard") - } - @Test("no editable target: skips the paste and leaves the transcript on the clipboard") - func noEditableTargetKeepsClipboard() async throws { - let clip = FakeClipboard(string: "user-clipboard") - let posted = ValueBox(false) - let injector = KeyInjector( - pasteSettleDuration: .zero, - postPaste: { - posted.value = true - return true - }, - hasEditableTarget: { false }, - clipboard: clip) + @Test("no editable target: skips the paste and leaves the transcript on the clipboard") + func noEditableTargetKeepsClipboard() async throws { + let clip = FakeClipboard(string: "user-clipboard") + let posted = ValueBox(false) + let injector = KeyInjector( + pasteSettleDuration: .zero, + postPaste: { + posted.value = true + return true + }, + hasEditableTarget: { false }, + clipboard: clip) - await #expect(throws: BlurtError.noEditableTarget) { - try await injector.insert("dictated text") + await #expect(throws: BlurtError.noEditableTarget) { + try await injector.insert("dictated text") + } + // No ⌘V was posted (so macOS never beeps), and the transcript is left on the + // clipboard for a manual paste rather than being restored away. + #expect(posted.value == false) + #expect(clip.string == "dictated text") } - // No ⌘V was posted (so macOS never beeps), and the transcript is left on the - // clipboard for a manual paste rather than being restored away. - #expect(posted.value == false) - #expect(clip.string == "dictated text") - } - @Test("AX-opaque Electron editor still pastes despite no editable signal") - func electronEditorPastesWithoutSignal() async throws { - let clip = FakeClipboard(string: "user-clipboard") - let posted = ValueBox(false) - let injector = KeyInjector( - pasteSettleDuration: .zero, - postPaste: { - posted.value = true - return true - }, - hasEditableTarget: { false }, // Electron/Chromium exposes no editable AX signal - isAXOpaqueApp: { _ in true }, // …but it *is* an AX-opaque app (Electron editor) - clipboard: clip) + @Test("AX-opaque Electron editor still pastes despite no editable signal") + func electronEditorPastesWithoutSignal() async throws { + let clip = FakeClipboard(string: "user-clipboard") + let posted = ValueBox(false) + let injector = KeyInjector( + pasteSettleDuration: .zero, + postPaste: { + posted.value = true + return true + }, + hasEditableTarget: { false }, // Electron/Chromium exposes no editable AX signal + isAXOpaqueApp: { _ in true }, // …but it *is* an AX-opaque app (Electron editor) + clipboard: clip) - // Must not throw noEditableTarget: the Electron exception keeps the paste. - try await injector.insert("dictated text") - await injector.pendingSettle?.value + // Must not throw noEditableTarget: the Electron exception keeps the paste. + try await injector.insert("dictated text") + await injector.pendingSettle?.value - // The ⌘V was posted (words pasted, not copy-only), and the user's clipboard - // is restored after the settle. - #expect(posted.value == true) - #expect(clip.string == "user-clipboard") - } + // The ⌘V was posted (words pasted, not copy-only), and the user's clipboard + // is restored after the settle. + #expect(posted.value == true) + #expect(clip.string == "user-clipboard") + } - @Test("opaque editor: a second dictation into the same window gets a separating space") - func opaqueEditorSameWindowInsertsSeparated() async throws { - let (injector, pasted) = makeRecordingInjector() - // Same target app AND window title for both dictations — e.g. two - // back-to-back dictations into the same VS Code file, or the same Google - // Docs tab. Prior text is nil because both surfaces are Accessibility-opaque. - await injector.setTargetApp(try liveTargetApp()) + @Test("opaque editor: a second dictation into the same window gets a separating space") + func opaqueEditorSameWindowInsertsSeparated() async throws { + let (injector, pasted) = makeRecordingInjector() + // Same target app AND window title for both dictations — e.g. two + // back-to-back dictations into the same VS Code file, or the same Google + // Docs tab. Prior text is nil because both surfaces are Accessibility-opaque. + await injector.setTarget(try liveTargetFocus()) - try await injector.insert("First.", after: nil, windowTitle: "notes.txt — Editor") - try await injector.insert("Second.", after: nil, windowTitle: "notes.txt — Editor") + try await injector.insert("First.", after: nil, windowTitle: "notes.txt — Editor") + try await injector.insert("Second.", after: nil, windowTitle: "notes.txt — Editor") - // First paste lands as-is; the second is separated from it even though AX - // gave us no prior text — the injector remembers what it just pasted into - // this same window. - // - // The one end-to-end case: it pins that `insert` actually threads its - // resolution through (feeding the target's pid in, recording the resolved - // window after the paste). The rules themselves — a changed title, a missing - // title, a changed target — are cases of `resolveInsert` and live in - // `KeyInjectorResolveInsertTests`, which needs no live process at all. - #expect(pasted.values == ["First.", " Second."]) - } + // First paste lands as-is; the second is separated from it even though AX + // gave us no prior text — the injector remembers what it just pasted into + // this same window. + // + // The one end-to-end case: it pins that `insert` actually threads its + // resolution through (feeding the target's pid in, recording the resolved + // window after the paste). The rules themselves — a changed title, a missing + // title, a changed target — are cases of `resolveInsert` and live in + // `KeyInjectorResolveInsertTests`, which needs no live process at all. + #expect(pasted.values == ["First.", " Second."]) + } - @Test("overlapping inserts still restore the user's original clipboard") - func overlappingInsertsRestoreOriginal() async throws { - let clip = FakeClipboard(string: "user-clipboard") - // A non-zero settle keeps insert #1's backgrounded settle task holding the - // paste lock while a second insert arrives. Without serialization, insert #2 - // would snapshot the clipboard while it still holds insert #1's "first" text - // and later restore *that* instead of the user's original. `postPaste` opens - // the gate while #1 still holds the lock (insert #1 then hands the lock to - // its settle task and returns), so when `wait()` returns insert #2 - // deterministically blocks on the lock until #1's settle restores and - // releases — rather than interleaving. No timing margin needed. - let firstParked = AsyncGate() - let injector = KeyInjector( - pasteSettleDuration: .milliseconds(100), - postPaste: { - firstParked.open() - return true - }, - clipboard: clip) + @Test("overlapping inserts still restore the user's original clipboard") + func overlappingInsertsRestoreOriginal() async throws { + let clip = FakeClipboard(string: "user-clipboard") + // A non-zero settle keeps insert #1's backgrounded settle task holding the + // paste lock while a second insert arrives. Without serialization, insert #2 + // would snapshot the clipboard while it still holds insert #1's "first" text + // and later restore *that* instead of the user's original. `postPaste` opens + // the gate while #1 still holds the lock (insert #1 then hands the lock to + // its settle task and returns), so when `wait()` returns insert #2 + // deterministically blocks on the lock until #1's settle restores and + // releases — rather than interleaving. No timing margin needed. + let firstParked = AsyncGate() + let injector = KeyInjector( + pasteSettleDuration: .milliseconds(100), + postPaste: { + firstParked.open() + return true + }, + clipboard: clip) - let first = Task { try await injector.insert("first") } - await firstParked.wait() - try await injector.insert("second") - try await first.value - // Await the second insert's deferred settle (insert returns before it runs). - await injector.pendingSettle?.value + let first = Task { try await injector.insert("first") } + await firstParked.wait() + try await injector.insert("second") + try await first.value + // Await the second insert's deferred settle (insert returns before it runs). + await injector.pendingSettle?.value - #expect(clip.string == "user-clipboard") - } - - @Test("a copy during the settle window is preserved, not clobbered by restore") - func copyDuringSettleIsPreserved() async throws { - let clip = FakeClipboard(string: "user-clipboard") - // The paste posts, then the deferred settle waits. During that wait the user - // copies something new. The restore must not blow that away with the stale - // pre-paste snapshot — once the pasteboard changed under us, the right move - // is to leave the newer contents alone. - let pasted = AsyncGate() - let injector = KeyInjector( - pasteSettleDuration: .milliseconds(100), - postPaste: { - pasted.open() - return true - }, - clipboard: clip) + #expect(clip.string == "user-clipboard") + } - let task = Task { try await injector.insert("dictated") } - await pasted.wait() - clip.externalWrite("copied-mid-paste") - try await task.value - // Await the deferred settle: it must see the changed changeCount and skip the - // restore, leaving the user's mid-paste copy intact. - await injector.pendingSettle?.value + @Test("a copy during the settle window is preserved, not clobbered by restore") + func copyDuringSettleIsPreserved() async throws { + let clip = FakeClipboard(string: "user-clipboard") + // The paste posts, then the deferred settle waits. During that wait the user + // copies something new. The restore must not blow that away with the stale + // pre-paste snapshot — once the pasteboard changed under us, the right move + // is to leave the newer contents alone. + let pasted = AsyncGate() + let injector = KeyInjector( + pasteSettleDuration: .milliseconds(100), + postPaste: { + pasted.open() + return true + }, + clipboard: clip) - #expect(clip.string == "copied-mid-paste") - } + let task = Task { try await injector.insert("dictated") } + await pasted.wait() + clip.externalWrite("copied-mid-paste") + try await task.value + // Await the deferred settle: it must see the changed changeCount and skip the + // restore, leaving the user's mid-paste copy intact. + await injector.pendingSettle?.value - @Test("a cancelled task throws before posting any paste") - func cancelledBeforePaste() async throws { - let posted = ValueBox(false) - let injector = KeyInjector( - pasteSettleDuration: .zero, - postPaste: { - posted.value = true - return true - }) - // Gate the body so `cancel()` is guaranteed to land before `insert` reaches - // its first cancellation check. Without this, a busy machine can run the - // task past that check before `cancel()` arrives, posting the paste and - // flaking the assertion. The gate opens only after the cancel. - let gate = AsyncGate() - let task = Task { - await gate.wait() - try await injector.insert("text") + #expect(clip.string == "copied-mid-paste") } - task.cancel() - gate.open() - await #expect(throws: CancellationError.self) { - try await task.value + + @Test("a cancelled task throws before posting any paste") + func cancelledBeforePaste() async throws { + let posted = ValueBox(false) + let injector = KeyInjector( + pasteSettleDuration: .zero, + postPaste: { + posted.value = true + return true + }) + // Gate the body so `cancel()` is guaranteed to land before `insert` reaches + // its first cancellation check. Without this, a busy machine can run the + // task past that check before `cancel()` arrives, posting the paste and + // flaking the assertion. The gate opens only after the cancel. + let gate = AsyncGate() + let task = Task { + await gate.wait() + try await injector.insert("text") + } + task.cancel() + gate.open() + await #expect(throws: CancellationError.self) { + try await task.value + } + #expect(posted.value == false) } - #expect(posted.value == false) } -} // The shared fixtures these tests drive the injector with — `liveTargetApp`, // `AsyncGate`, `StringListBox`, `ValueBox` — live in `Stubs/InjectorTestSupport.swift` // so the fallback/cancel suite (a separate file) can reuse them. +#endif diff --git a/Tests/BlurtEngineTests/KeyInjectorLeadingSeparatorTests.swift b/Tests/BlurtEngineTests/KeyInjectorLeadingSeparatorTests.swift deleted file mode 100644 index 311b9ab5..00000000 --- a/Tests/BlurtEngineTests/KeyInjectorLeadingSeparatorTests.swift +++ /dev/null @@ -1,162 +0,0 @@ -// Foundation for `pid_t`: the resolve-insert suite below names it, and the two -// pure text-rule suites this file started as needed no imports at all. -import Foundation -import Testing - -@testable import BlurtEngine - -@Suite("KeyInjector.withLeadingSeparator") -struct KeyInjectorLeadingSeparatorTests { - @Test("prepends a space when prior text doesn't end in whitespace") - func prependsSpace() { - #expect(KeyInjector.withLeadingSeparator("Second.", after: "First.") == " Second.") - } - - @Test("no separator when prior text already ends in a space") - func priorEndsInSpace() { - #expect(KeyInjector.withLeadingSeparator("Second.", after: "First. ") == "Second.") - } - - @Test("no separator when prior text ends in a newline") - func priorEndsInNewline() { - #expect(KeyInjector.withLeadingSeparator("Second.", after: "First.\n") == "Second.") - } - - @Test("no leading space into an empty field (nil prior text)") - func nilPrior() { - #expect(KeyInjector.withLeadingSeparator("Second.", after: nil) == "Second.") - } - - @Test("no leading space when prior text is empty") - func emptyPrior() { - #expect(KeyInjector.withLeadingSeparator("Second.", after: "") == "Second.") - } - - @Test("doesn't double up when the new text already starts with whitespace") - func textStartsWithSpace() { - #expect(KeyInjector.withLeadingSeparator(" Second.", after: "First.") == " Second.") - } - - @Test("returns empty text unchanged") - func emptyText() { - #expect(KeyInjector.withLeadingSeparator("", after: "First.") == "") - } - - @Test("every whitespace class counts, not just space and newline") - func otherWhitespaceClasses() { - // The rules key on Character.isWhitespace: a trailing tab, carriage return, - // or non-breaking space suppresses the separator like a plain space does… - #expect(KeyInjector.withLeadingSeparator("Second.", after: "First.\t") == "Second.") - #expect(KeyInjector.withLeadingSeparator("Second.", after: "First.\r") == "Second.") - #expect(KeyInjector.withLeadingSeparator("Second.", after: "First.\u{00A0}") == "Second.") - // …and text already leading with a tab or non-breaking space isn't doubled. - #expect(KeyInjector.withLeadingSeparator("\tSecond.", after: "First.") == "\tSecond.") - #expect(KeyInjector.withLeadingSeparator("\u{00A0}Second.", after: "First.") == "\u{00A0}Second.") - } -} - -@Suite("KeyInjector.separatorBasis") -struct KeyInjectorSeparatorBasisTests { - @Test("AX-read prior text wins even when a prior paste is on record") - func priorTextWins() { - #expect( - KeyInjector.separatorBasis(priorText: "AX.", lastInserted: "Old.", sameWindow: false) == "AX.") - } - - @Test("falls back to the last paste when AX is opaque and the window is unchanged") - func opaqueSameWindowFallsBack() { - #expect( - KeyInjector.separatorBasis(priorText: nil, lastInserted: "First.", sameWindow: true) - == "First.") - } - - @Test("does not carry a prior paste across a different window") - func opaqueDifferentWindowNoFallback() { - #expect( - KeyInjector.separatorBasis(priorText: nil, lastInserted: "First.", sameWindow: false) == nil) - } - - @Test("no basis when AX is opaque and nothing was pasted yet") - func opaqueNoPriorPaste() { - #expect(KeyInjector.separatorBasis(priorText: nil, lastInserted: nil, sameWindow: true) == nil) - } -} - -/// `resolveInsert` — everything `performInsert` decides before it activates -/// anything: the text to write and the window to remember writing it into. The -/// same-window derivation used to be inline in `performInsert`, so these cases -/// could only be driven by scraping `NSWorkspace` for live applications (and one -/// of them by requiring two). Here the target is just a pid. -@Suite("KeyInjector.resolveInsert") -struct KeyInjectorResolveInsertTests { - private let editor = KeyInjector.WindowIdentity(pid: 501, title: "notes.txt — Editor") - - /// A second dictation with no AX prior text, resolved against `editor`. - private func secondInsert( - targetPID: pid_t?, windowTitle: String?, priorText: String? = nil - ) -> KeyInjector.ResolvedInsert { - KeyInjector.resolveInsert( - text: "Second.", priorText: priorText, windowTitle: windowTitle, targetPID: targetPID, - lastInserted: KeyInjector.ResolvedInsert(text: "First.", window: editor)) - } - - @Test("opaque editor: the same pid and title recovers the spacing from the last paste") - func sameWindowSeparates() { - // Two back-to-back dictations into the same VS Code file or Google Docs tab: - // AX gives no prior text, so what we pasted a moment ago is what precedes - // the caret. - #expect( - secondInsert(targetPID: editor.pid, windowTitle: editor.title) - == KeyInjector.ResolvedInsert(text: " Second.", window: editor)) - } - - @Test("opaque editor: a changed title is a different field, so no phantom space") - func changedTitleDoesNotSeparate() { - // One browser process (or one Electron window) but a different tab or file — - // a shared pid alone must not carry spacing into an unrelated document. The - // new window is still remembered, so a *third* dictation into it separates. - let resolved = secondInsert(targetPID: editor.pid, windowTitle: "Untitled document — Docs") - #expect(resolved.text == "Second.") - #expect(resolved.window == KeyInjector.WindowIdentity(pid: editor.pid, title: "Untitled document — Docs")) - } - - @Test("no readable window title means no match and nothing to remember") - func missingTitleDoesNotSeparate() { - // Can't confirm it's the same window, so the fallback stays off rather than - // guessing — and with no identity to record, the next dictation can't match - // this one either. - #expect( - secondInsert(targetPID: editor.pid, windowTitle: nil) - == KeyInjector.ResolvedInsert(text: "Second.", window: nil)) - } - - @Test("a different target app never inherits the previous paste's spacing") - func changedTargetDoesNotSeparate() { - let resolved = secondInsert(targetPID: 777, windowTitle: editor.title) - #expect(resolved.text == "Second.") - #expect(resolved.window == KeyInjector.WindowIdentity(pid: 777, title: editor.title)) - } - - @Test("no captured target at all: nothing to match, nothing to remember") - func noTargetDoesNotSeparate() { - #expect( - secondInsert(targetPID: nil, windowTitle: editor.title) - == KeyInjector.ResolvedInsert(text: "Second.", window: nil)) - } - - @Test("AX prior text wins over the remembered paste, in the same window or not") - func priorTextWinsOverMemory() { - // The field is readable, so the caret's real neighbour decides — here it - // already ends in whitespace, which the remembered "First." would not have. - #expect(secondInsert(targetPID: editor.pid, windowTitle: editor.title, priorText: "Hello ").text == "Second.") - #expect(secondInsert(targetPID: 777, windowTitle: "Other", priorText: "Hello").text == " Second.") - } - - @Test("a first-ever insert has no memory to fall back on") - func firstInsertHasNoBasis() { - let resolved = KeyInjector.resolveInsert( - text: "First.", priorText: nil, windowTitle: editor.title, targetPID: editor.pid, - lastInserted: nil) - #expect(resolved == KeyInjector.ResolvedInsert(text: "First.", window: editor)) - } -} diff --git a/Tests/BlurtEngineTests/KeyInjectorSystemActionsTests.swift b/Tests/BlurtEngineTests/KeyInjectorSystemActionsTests.swift index e683c745..de66ea96 100644 --- a/Tests/BlurtEngineTests/KeyInjectorSystemActionsTests.swift +++ b/Tests/BlurtEngineTests/KeyInjectorSystemActionsTests.swift @@ -1,95 +1,97 @@ -import AppKit -import CoreGraphics -import Testing +#if os(macOS) + import AppKit + import CoreGraphics + import Testing -@testable import BlurtEngine + @testable import BlurtEngine -/// The system side of `KeyInjector`'s seams (`KeyInjector+SystemActions.swift`), -/// covering the parts that can be asserted without changing the state of the -/// machine running the suite. -/// -/// The line this suite draws: *reads* of process-global state are fair game -/// (`accessibilityTrusted`, the frontmost-app poll), and so is *building* a -/// CGEvent. What is deliberately left to running the real app is anything that -/// mutates the session — `activate` steals focus, and `postCmdV`'s two `.post` -/// calls would fire a live ⌘V into whatever the developer had open. That is the -/// same reason `check.sh` runs the XCUITest suite on CI only: it commandeers the -/// GUI session. -@Suite("KeyInjector system actions") -struct KeyInjectorSystemActionsTests { + /// The system side of `KeyInjector`'s seams (`KeyInjector+SystemActions.swift`), + /// covering the parts that can be asserted without changing the state of the + /// machine running the suite. + /// + /// The line this suite draws: *reads* of process-global state are fair game + /// (`accessibilityTrusted`, the frontmost-app poll), and so is *building* a + /// CGEvent. What is deliberately left to running the real app is anything that + /// mutates the session — `activate` steals focus, and `postCmdV`'s two `.post` + /// calls would fire a live ⌘V into whatever the developer had open. That is the + /// same reason `check.sh` runs the XCUITest suite on CI only: it commandeers the + /// GUI session. + @Suite("KeyInjector system actions") + struct KeyInjectorSystemActionsTests { - // MARK: - Cmd-V event construction + // MARK: - Cmd-V event construction - @Test("cmdVEvents builds a V key-down/key-up pair") - func cmdVEventsBuildsPair() throws { - let events = try #require(KeyInjector.cmdVEvents()) + @Test("cmdVEvents builds a V key-down/key-up pair") + func cmdVEventsBuildsPair() throws { + let events = try #require(KeyInjector.cmdVEvents()) - #expect(events.down.type == .keyDown) - #expect(events.up.type == .keyUp) - // 0x09 is kVK_ANSI_V. Asserted numerically because the Carbon constant isn't - // importable here, which is why the source spells it as a literal too — this - // is the check that keeps that literal honest. - #expect(events.down.getIntegerValueField(.keyboardEventKeycode) == 0x09) - #expect(events.up.getIntegerValueField(.keyboardEventKeycode) == 0x09) - } + #expect(events.down.type == .keyDown) + #expect(events.up.type == .keyUp) + // 0x09 is kVK_ANSI_V. Asserted numerically because the Carbon constant isn't + // importable here, which is why the source spells it as a literal too — this + // is the check that keeps that literal honest. + #expect(events.down.getIntegerValueField(.keyboardEventKeycode) == 0x09) + #expect(events.up.getIntegerValueField(.keyboardEventKeycode) == 0x09) + } - @Test("both Cmd-V events carry the command flag") - func cmdVEventsCarryCommand() throws { - let events = try #require(KeyInjector.cmdVEvents()) + @Test("both Cmd-V events carry the command flag") + func cmdVEventsCarryCommand() throws { + let events = try #require(KeyInjector.cmdVEvents()) - // A ⌘-less key-down is a plain "v" — it types a character into the target - // instead of pasting, which is the visible failure this pins. - #expect(events.down.flags.contains(.maskCommand)) - // And a ⌘-less key-up reads as the modifier having been released mid-chord. - #expect(events.up.flags.contains(.maskCommand)) - } + // A ⌘-less key-down is a plain "v" — it types a character into the target + // instead of pasting, which is the visible failure this pins. + #expect(events.down.flags.contains(.maskCommand)) + // And a ⌘-less key-up reads as the modifier having been released mid-chord. + #expect(events.up.flags.contains(.maskCommand)) + } - @Test("Cmd-V events carry no modifier beyond command") - func cmdVEventsCarryNoOtherModifier() throws { - let events = try #require(KeyInjector.cmdVEvents()) + @Test("Cmd-V events carry no modifier beyond command") + func cmdVEventsCarryNoOtherModifier() throws { + let events = try #require(KeyInjector.cmdVEvents()) - // ⌘⌥V and ⌘⇧V are "paste and match style" in most apps, and ⌃⌘V is bound - // elsewhere again — so a stray extra modifier doesn't fail loudly, it pastes - // the wrong way. `flags` is assigned (not OR-ed) in `cmdVEvents`, and this is - // what keeps it that way. - for flags in [events.down.flags, events.up.flags] { - #expect(!flags.contains(.maskAlternate)) - #expect(!flags.contains(.maskShift)) - #expect(!flags.contains(.maskControl)) - #expect(!flags.contains(.maskSecondaryFn)) + // ⌘⌥V and ⌘⇧V are "paste and match style" in most apps, and ⌃⌘V is bound + // elsewhere again — so a stray extra modifier doesn't fail loudly, it pastes + // the wrong way. `flags` is assigned (not OR-ed) in `cmdVEvents`, and this is + // what keeps it that way. + for flags in [events.down.flags, events.up.flags] { + #expect(!flags.contains(.maskAlternate)) + #expect(!flags.contains(.maskShift)) + #expect(!flags.contains(.maskControl)) + #expect(!flags.contains(.maskSecondaryFn)) + } } - } - // MARK: - Accessibility trust probe + // MARK: - Accessibility trust probe - @Test("accessibilityTrusted reports the process-wide AX trust state") - func accessibilityTrustedMatchesSystem() { - // The test host's trust state isn't ours to set, so the assertable claim is - // that the seam is a pass-through and not, say, a hard-coded `true` that would - // make `KeyInjector` skip its permission check in production. - #expect(KeyInjector.accessibilityTrusted() == AXIsProcessTrusted()) - } + @Test("accessibilityTrusted reports the process-wide AX trust state") + func accessibilityTrustedMatchesSystem() { + // The test host's trust state isn't ours to set, so the assertable claim is + // that the seam is a pass-through and not, say, a hard-coded `true` that would + // make `KeyInjector` skip its permission check in production. + #expect(KeyInjector.accessibilityTrusted() == AXIsProcessTrusted()) + } - // MARK: - Frontmost wait + // MARK: - Frontmost wait - @Test("waitUntilFrontmost reports failure for an app that never comes frontmost") - func waitUntilFrontmostGivesUp() async { - // The test host is a command-line process with no windows, so the window - // server never reports it frontmost — the deterministic "activation didn't - // land" case. `KeyInjector.activateTargetApp` turns this `false` into - // `.targetAppLost` rather than pasting into the wrong app. - #expect(await KeyInjector.waitUntilFrontmost(.current) == false) - } + @Test("waitUntilFrontmost reports failure for an app that never comes frontmost") + func waitUntilFrontmostGivesUp() async { + // The test host is a command-line process with no windows, so the window + // server never reports it frontmost — the deterministic "activation didn't + // land" case. `KeyInjector.activateTargetApp` turns this `false` into + // `.targetAppLost` rather than pasting into the wrong app. + #expect(await KeyInjector.waitUntilFrontmost(.current) == false) + } - @Test("waitUntilFrontmost gives up on a bounded deadline instead of hanging") - func waitUntilFrontmostIsBounded() async { - // Sits on the press→paste path, so an unbounded wait would freeze the paste, - // not just slow it. 350 ms budget; the ceiling leaves room for a loaded CI - // box's scheduling without being loose enough to pass an unbounded loop. - let clock = ContinuousClock() - let elapsed = await clock.measure { - _ = await KeyInjector.waitUntilFrontmost(.current) + @Test("waitUntilFrontmost gives up on a bounded deadline instead of hanging") + func waitUntilFrontmostIsBounded() async { + // Sits on the press→paste path, so an unbounded wait would freeze the paste, + // not just slow it. 350 ms budget; the ceiling leaves room for a loaded CI + // box's scheduling without being loose enough to pass an unbounded loop. + let clock = ContinuousClock() + let elapsed = await clock.measure { + _ = await KeyInjector.waitUntilFrontmost(.current) + } + #expect(elapsed < .seconds(3)) } - #expect(elapsed < .seconds(3)) } -} +#endif diff --git a/Tests/BlurtEngineTests/MemoryLeakTests.swift b/Tests/BlurtEngineTests/MemoryLeakTests.swift index d5d988e1..90617fa4 100644 --- a/Tests/BlurtEngineTests/MemoryLeakTests.swift +++ b/Tests/BlurtEngineTests/MemoryLeakTests.swift @@ -44,10 +44,12 @@ struct MemoryLeakTests { } } - @Test("KeyInjector deallocates") - func keyInjectorNoLeak() async { - await expectNoLeak("KeyInjector") { - KeyInjector() + #if os(macOS) + @Test("KeyInjector deallocates") + func keyInjectorNoLeak() async { + await expectNoLeak("KeyInjector") { + KeyInjector() + } } - } + #endif } diff --git a/Tests/BlurtEngineTests/MicLivenessTests.swift b/Tests/BlurtEngineTests/MicLivenessTests.swift index 26730b15..61e1def8 100644 --- a/Tests/BlurtEngineTests/MicLivenessTests.swift +++ b/Tests/BlurtEngineTests/MicLivenessTests.swift @@ -1,307 +1,309 @@ -import CoreAudio -import Foundation -import Synchronization -import Testing +#if os(macOS) + import CoreAudio + import Foundation + import Synchronization + import Testing -@testable import BlurtEngine + @testable import BlurtEngine -/// What a live input reads even with nobody talking: a mic's own self-noise sits -/// far above `MicLiveness.silenceFloorDB` (one least-significant bit of a 16-bit -/// sample is already about -90 dBFS). The floor separates *digital* silence from -/// any analog input, so this is what a quiet room must look like — live. -private let quietRoomPowerDB: Float = -90 + /// What a live input reads even with nobody talking: a mic's own self-noise sits + /// far above `MicLiveness.silenceFloorDB` (one least-significant bit of a 16-bit + /// sample is already about -90 dBFS). The floor separates *digital* silence from + /// any analog input, so this is what a quiet room must look like — live. + private let quietRoomPowerDB: Float = -90 -/// What a zero-filled buffer from a device that hasn't finished switching reads. -private let digitalSilencePowerDB: Float = -160 + /// What a zero-filled buffer from a device that hasn't finished switching reads. + private let digitalSilencePowerDB: Float = -160 -/// The pure half of `MicCapture.start()`'s liveness gate: the transport-aware -/// wait cap and the poll-until-the-recorder-is-clocking-*and*-metering loop. Driven -/// against `TestClock` so the Bluetooth cap is exercised without waiting real -/// seconds. -@Suite("MicLiveness", .timeLimit(.minutes(1))) -struct MicLivenessTests { - @Test("each transport class gets its own cap: Bluetooth, local, unclassifiable") - func transportTimeouts() { - // The profile switch is the whole reason the gate exists — both Bluetooth - // transport types must get the multi-second budget. - #expect( - MicLiveness.timeout(forTransportType: kAudioDeviceTransportTypeBluetooth) - == MicLiveness.bluetoothTimeout) - #expect( - MicLiveness.timeout(forTransportType: kAudioDeviceTransportTypeBluetoothLE) - == MicLiveness.bluetoothTimeout) - // Wired/built-in inputs deliver frames near-instantly; a long cap there - // would make a genuinely broken mic feel like a hang. - #expect( - MicLiveness.timeout(forTransportType: kAudioDeviceTransportTypeBuiltIn) - == MicLiveness.defaultTimeout) - #expect( - MicLiveness.timeout(forTransportType: kAudioDeviceTransportTypeUSB) - == MicLiveness.defaultTimeout) - // Every other local transport takes the same budget — the whole set is - // asserted in `AudioTransportTests.localTransports`. - #expect( - MicLiveness.timeout(forTransportType: kAudioDeviceTransportTypeThunderbolt) - == MicLiveness.defaultTimeout) - // An aggregate or virtual input, an unnamed type, and an unreadable read all - // take the middle cap rather than the wired one: the wrapper reports its own - // transport, so real AirPods can be switching underneath it, and 300 ms - // cannot cover that. (This is the assertion that read `defaultTimeout` for - // nil before — the second half of the lost-first-words bug.) - #expect( - MicLiveness.timeout(forTransportType: kAudioDeviceTransportTypeAggregate) - == MicLiveness.unknownTransportTimeout) - #expect( - MicLiveness.timeout(forTransportType: kAudioDeviceTransportTypeVirtual) - == MicLiveness.unknownTransportTimeout) - #expect( - MicLiveness.timeout(forTransportType: kAudioDeviceTransportTypeUnknown) - == MicLiveness.unknownTransportTimeout) - #expect(MicLiveness.timeout(forTransportType: nil) == MicLiveness.unknownTransportTimeout) - // It has to sit strictly between the two caps it splits, or it is just one of - // them under a second name. - #expect(MicLiveness.defaultTimeout < MicLiveness.unknownTransportTimeout) - #expect(MicLiveness.unknownTransportTimeout < MicLiveness.bluetoothTimeout) - } + /// The pure half of `MicCapture.start()`'s liveness gate: the transport-aware + /// wait cap and the poll-until-the-recorder-is-clocking-*and*-metering loop. Driven + /// against `TestClock` so the Bluetooth cap is exercised without waiting real + /// seconds. + @Suite("MicLiveness", .timeLimit(.minutes(1))) + struct MicLivenessTests { + @Test("each transport class gets its own cap: Bluetooth, local, unclassifiable") + func transportTimeouts() { + // The profile switch is the whole reason the gate exists — both Bluetooth + // transport types must get the multi-second budget. + #expect( + MicLiveness.timeout(forTransportType: kAudioDeviceTransportTypeBluetooth) + == MicLiveness.bluetoothTimeout) + #expect( + MicLiveness.timeout(forTransportType: kAudioDeviceTransportTypeBluetoothLE) + == MicLiveness.bluetoothTimeout) + // Wired/built-in inputs deliver frames near-instantly; a long cap there + // would make a genuinely broken mic feel like a hang. + #expect( + MicLiveness.timeout(forTransportType: kAudioDeviceTransportTypeBuiltIn) + == MicLiveness.defaultTimeout) + #expect( + MicLiveness.timeout(forTransportType: kAudioDeviceTransportTypeUSB) + == MicLiveness.defaultTimeout) + // Every other local transport takes the same budget — the whole set is + // asserted in `AudioTransportTests.localTransports`. + #expect( + MicLiveness.timeout(forTransportType: kAudioDeviceTransportTypeThunderbolt) + == MicLiveness.defaultTimeout) + // An aggregate or virtual input, an unnamed type, and an unreadable read all + // take the middle cap rather than the wired one: the wrapper reports its own + // transport, so real AirPods can be switching underneath it, and 300 ms + // cannot cover that. (This is the assertion that read `defaultTimeout` for + // nil before — the second half of the lost-first-words bug.) + #expect( + MicLiveness.timeout(forTransportType: kAudioDeviceTransportTypeAggregate) + == MicLiveness.unknownTransportTimeout) + #expect( + MicLiveness.timeout(forTransportType: kAudioDeviceTransportTypeVirtual) + == MicLiveness.unknownTransportTimeout) + #expect( + MicLiveness.timeout(forTransportType: kAudioDeviceTransportTypeUnknown) + == MicLiveness.unknownTransportTimeout) + #expect(MicLiveness.timeout(forTransportType: nil) == MicLiveness.unknownTransportTimeout) + // It has to sit strictly between the two caps it splits, or it is just one of + // them under a second name. + #expect(MicLiveness.defaultTimeout < MicLiveness.unknownTransportTimeout) + #expect(MicLiveness.unknownTransportTimeout < MicLiveness.bluetoothTimeout) + } - @Test("frames already arriving confirm immediately, without sleeping") - func immediateLiveness() async { - let clock = TestClock() - // Never advanced: a sleep would park forever, so returning at all proves - // the fast path never sleeps (the suite's time limit backs that up). - let gap = await MicLiveness.waitUntilLive( - timeout: .seconds(1), clock: clock, deliveredFrames: { 1024 }, - inputPowerDB: { quietRoomPowerDB }) - #expect(gap == .zero) - } + @Test("frames already arriving confirm immediately, without sleeping") + func immediateLiveness() async { + let clock = TestClock() + // Never advanced: a sleep would park forever, so returning at all proves + // the fast path never sleeps (the suite's time limit backs that up). + let gap = await MicLiveness.waitUntilLive( + timeout: .seconds(1), clock: clock, deliveredFrames: { 1024 }, + inputPowerDB: { quietRoomPowerDB }) + #expect(gap == .zero) + } - @Test("the poll interval doubles, so a slow bring-up isn't hundreds of wakeups") - func livenessBacksOff() async { - let clock = TestClock() - let polls = Mutex(0) - async let gap = MicLiveness.waitUntilLive( - timeout: MicLiveness.bluetoothTimeout, clock: clock, - deliveredFrames: { - // Nothing delivered for the first three checks — the route still - // switching — then buffers start arriving. - polls.withLock { polls in - polls += 1 - return polls < 4 ? 0 : 1024 - } - }, inputPowerDB: { quietRoomPowerDB }) - // Each wait is twice the last: 1 ms, 2 ms, 4 ms. Driving the clock by the - // exact expected delay is also the assertion — `waitUntilSleeping` matches on - // the deadline, so a loop that slept a fixed quantum would hang here rather - // than quietly pass. - var expected = MicLiveness.initialPollInterval - var elapsed = Duration.zero - for _ in 1...3 { - await clock.waitUntilSleeping(for: expected) - clock.advance(by: expected) - elapsed += expected - expected = min(expected * 2, MicLiveness.maxPollInterval) + @Test("the poll interval doubles, so a slow bring-up isn't hundreds of wakeups") + func livenessBacksOff() async { + let clock = TestClock() + let polls = Mutex(0) + async let gap = MicLiveness.waitUntilLive( + timeout: MicLiveness.bluetoothTimeout, clock: clock, + deliveredFrames: { + // Nothing delivered for the first three checks — the route still + // switching — then buffers start arriving. + polls.withLock { polls in + polls += 1 + return polls < 4 ? 0 : 1024 + } + }, inputPowerDB: { quietRoomPowerDB }) + // Each wait is twice the last: 1 ms, 2 ms, 4 ms. Driving the clock by the + // exact expected delay is also the assertion — `waitUntilSleeping` matches on + // the deadline, so a loop that slept a fixed quantum would hang here rather + // than quietly pass. + var expected = MicLiveness.initialPollInterval + var elapsed = Duration.zero + for _ in 1...3 { + await clock.waitUntilSleeping(for: expected) + clock.advance(by: expected) + elapsed += expected + expected = min(expected * 2, MicLiveness.maxPollInterval) + } + #expect(await gap == elapsed) } - #expect(await gap == elapsed) - } - @Test("the backoff is capped rather than doubling without limit") - func backoffIsCapped() async { - // Otherwise a 2.5 s Bluetooth cap would end in multi-second sleeps and - // overshoot the deadline it is supposed to respect. - let clock = TestClock() - let polls = Mutex(0) - async let gap = MicLiveness.waitUntilLive( - timeout: .seconds(30), clock: clock, - deliveredFrames: { - polls.withLock { polls in - polls += 1 - return polls < 12 ? 0 : 1024 - } - }, inputPowerDB: { quietRoomPowerDB }) - var expected = MicLiveness.initialPollInterval - for _ in 1...11 { - await clock.waitUntilSleeping(for: expected) - clock.advance(by: expected) - expected = min(expected * 2, MicLiveness.maxPollInterval) + @Test("the backoff is capped rather than doubling without limit") + func backoffIsCapped() async { + // Otherwise a 2.5 s Bluetooth cap would end in multi-second sleeps and + // overshoot the deadline it is supposed to respect. + let clock = TestClock() + let polls = Mutex(0) + async let gap = MicLiveness.waitUntilLive( + timeout: .seconds(30), clock: clock, + deliveredFrames: { + polls.withLock { polls in + polls += 1 + return polls < 12 ? 0 : 1024 + } + }, inputPowerDB: { quietRoomPowerDB }) + var expected = MicLiveness.initialPollInterval + for _ in 1...11 { + await clock.waitUntilSleeping(for: expected) + clock.advance(by: expected) + expected = min(expected * 2, MicLiveness.maxPollInterval) + } + #expect(expected == MicLiveness.maxPollInterval) + #expect(await gap != nil) } - #expect(expected == MicLiveness.maxPollInterval) - #expect(await gap != nil) - } - @Test("frames arriving as digital silence are not live — the shipped bug") - func zeroFilledBuffersAreNotLive() async { - // The gate's original signal was frame arrival alone, and macOS can hand - // a stale or not-yet-switched device's queue all-zero buffers (the same - // failure that retired the `AVAudioEngine` capture path). Frames of digital - // silence arrive and count exactly like real audio, so the wait - // was satisfied on the first ~1 ms poll while the AirPods link was still - // renegotiating: the "Connecting…" pill flashed past and the start chime - // fired over a dead mic. With the power term the wait holds, and a device - // that never delivers ends in nil — which `MicCapture` fails the press on. - #expect(await waitToCap(powerDB: { digitalSilencePowerDB }) == nil) - } + @Test("frames arriving as digital silence are not live — the shipped bug") + func zeroFilledBuffersAreNotLive() async { + // The gate's original signal was frame arrival alone, and macOS can hand + // a stale or not-yet-switched device's queue all-zero buffers (the same + // failure that retired the `AVAudioEngine` capture path). Frames of digital + // silence arrive and count exactly like real audio, so the wait + // was satisfied on the first ~1 ms poll while the AirPods link was still + // renegotiating: the "Connecting…" pill flashed past and the start chime + // fired over a dead mic. With the power term the wait holds, and a device + // that never delivers ends in nil — which `MicCapture` fails the press on. + #expect(await waitToCap(powerDB: { digitalSilencePowerDB }) == nil) + } - @Test("the floor is exclusive, and a non-finite reading is not live either") - func silenceFloorEdges() async { - // At the floor, not above it. - #expect(await waitToCap(powerDB: { MicLiveness.silenceFloorDB }) == nil) - // NaN fails both comparisons; -infinity is what a truly muted device can - // report. Both must read as not-live, so the press fails rather than - // confirming a route that is delivering nothing. - #expect(await waitToCap(powerDB: { Float.nan }) == nil) - #expect(await waitToCap(powerDB: { -Float.infinity }) == nil) - } + @Test("the floor is exclusive, and a non-finite reading is not live either") + func silenceFloorEdges() async { + // At the floor, not above it. + #expect(await waitToCap(powerDB: { MicLiveness.silenceFloorDB }) == nil) + // NaN fails both comparisons; -infinity is what a truly muted device can + // report. Both must read as not-live, so the press fails rather than + // confirming a route that is delivering nothing. + #expect(await waitToCap(powerDB: { Float.nan }) == nil) + #expect(await waitToCap(powerDB: { -Float.infinity }) == nil) + } - @Test("delivered frames plus real input power confirm at once") - func realInputPowerConfirmsPromptly() async { - // The other half of the floor's job: it must not become voice-activity - // detection. A live mic in a silent room reads its own self-noise, well above - // the floor, so a user who presses and says nothing is confirmed immediately - // instead of failing at the cap — no grace period needed. The clock is never - // advanced here, so a sleep would park forever and the suite's time limit - // would fail this rather than let it pass slowly. - let clock = TestClock() - let gap = await MicLiveness.waitUntilLive( - timeout: MicLiveness.bluetoothTimeout, clock: clock, deliveredFrames: { 1024 }, - inputPowerDB: { quietRoomPowerDB }) - #expect(gap == .zero) - } + @Test("delivered frames plus real input power confirm at once") + func realInputPowerConfirmsPromptly() async { + // The other half of the floor's job: it must not become voice-activity + // detection. A live mic in a silent room reads its own self-noise, well above + // the floor, so a user who presses and says nothing is confirmed immediately + // instead of failing at the cap — no grace period needed. The clock is never + // advanced here, so a sleep would park forever and the suite's time limit + // would fail this rather than let it pass slowly. + let clock = TestClock() + let gap = await MicLiveness.waitUntilLive( + timeout: MicLiveness.bluetoothTimeout, clock: clock, deliveredFrames: { 1024 }, + inputPowerDB: { quietRoomPowerDB }) + #expect(gap == .zero) + } - @Test("the gate's log line carries the transport, the wait, and the meter") - func logSummaryCarriesTheDiagnosis() { - // This line is the field evidence for the zero-buffer premise, which can't be - // reproduced without a Mac and AirPods — so what it must contain is pinned - // here rather than left to an untested call site in `MicCapture`. - let confirmed = MicLiveness.logSummary( - gap: .milliseconds(1420), timeout: MicLiveness.bluetoothTimeout, - transportType: kAudioDeviceTransportTypeBluetooth, powerDB: -37.5) - #expect(confirmed.contains("live after 1420 ms")) - #expect(confirmed.contains("transport=\(kAudioDeviceTransportTypeBluetooth)")) - #expect(confirmed.contains("powerDB=-37.5")) + @Test("the gate's log line carries the transport, the wait, and the meter") + func logSummaryCarriesTheDiagnosis() { + // This line is the field evidence for the zero-buffer premise, which can't be + // reproduced without a Mac and AirPods — so what it must contain is pinned + // here rather than left to an untested call site in `MicCapture`. + let confirmed = MicLiveness.logSummary( + gap: .milliseconds(1420), timeout: MicLiveness.bluetoothTimeout, + transportType: kAudioDeviceTransportTypeBluetooth, powerDB: -37.5) + #expect(confirmed.contains("live after 1420 ms")) + #expect(confirmed.contains("transport=\(kAudioDeviceTransportTypeBluetooth)")) + #expect(confirmed.contains("powerDB=-37.5")) - // A timeout reports the cap it waited out. An unreadable transport has to - // stay distinguishable from `kAudioDeviceTransportTypeUnknown`, which is 0. - let failedOpen = MicLiveness.logSummary( - gap: nil, timeout: MicLiveness.unknownTransportTimeout, transportType: nil, - powerDB: digitalSilencePowerDB) - #expect(failedOpen.contains("unconfirmed after 1000 ms")) - #expect(failedOpen.contains("transport=nil")) - #expect(failedOpen.contains("powerDB=-160.0")) - } + // A timeout reports the cap it waited out. An unreadable transport has to + // stay distinguishable from `kAudioDeviceTransportTypeUnknown`, which is 0. + let failedOpen = MicLiveness.logSummary( + gap: nil, timeout: MicLiveness.unknownTransportTimeout, transportType: nil, + powerDB: digitalSilencePowerDB) + #expect(failedOpen.contains("unconfirmed after 1000 ms")) + #expect(failedOpen.contains("transport=nil")) + #expect(failedOpen.contains("powerDB=-160.0")) + } - @Test("a recorder that never delivers times out with nil — the not-live verdict") - func timeoutReturnsNil() async { - // nil is pure information — the *caller* decides what it means, and - // `MicCapture.start()` fails the press closed on it (tears the recorder - // down, throws `.audioCaptureFailed`, the error pill). What is pinned here - // is only that the deadline actually produces the verdict. - let clock = TestClock() - let timeout = MicLiveness.initialPollInterval * 3 - async let gap = MicLiveness.waitUntilLive( - timeout: timeout, clock: clock, deliveredFrames: { 0 }, - inputPowerDB: { digitalSilencePowerDB }) - var expected = MicLiveness.initialPollInterval - for _ in 1...2 { - await clock.waitUntilSleeping(for: expected) - clock.advance(by: expected) - expected = min(expected * 2, MicLiveness.maxPollInterval) + @Test("a recorder that never delivers times out with nil — the not-live verdict") + func timeoutReturnsNil() async { + // nil is pure information — the *caller* decides what it means, and + // `MicCapture.start()` fails the press closed on it (tears the recorder + // down, throws `.audioCaptureFailed`, the error pill). What is pinned here + // is only that the deadline actually produces the verdict. + let clock = TestClock() + let timeout = MicLiveness.initialPollInterval * 3 + async let gap = MicLiveness.waitUntilLive( + timeout: timeout, clock: clock, deliveredFrames: { 0 }, + inputPowerDB: { digitalSilencePowerDB }) + var expected = MicLiveness.initialPollInterval + for _ in 1...2 { + await clock.waitUntilSleeping(for: expected) + clock.advance(by: expected) + expected = min(expected * 2, MicLiveness.maxPollInterval) + } + #expect(await gap == nil) } - #expect(await gap == nil) - } - /// Drives the wait to its cap against a clock this test owns, for a power probe - /// that never reports live while frames are already arriving. - /// Shared so each "not live" reading is one assertion rather than a copy of the - /// backoff-driving loop. - private func waitToCap(powerDB: @escaping @Sendable () -> Float) async -> Duration? { - let clock = TestClock() - let timeout = MicLiveness.initialPollInterval * 3 - async let gap = MicLiveness.waitUntilLive( - timeout: timeout, clock: clock, deliveredFrames: { 1024 }, inputPowerDB: powerDB) - var expected = MicLiveness.initialPollInterval - for _ in 1...2 { - await clock.waitUntilSleeping(for: expected) - clock.advance(by: expected) - expected = min(expected * 2, MicLiveness.maxPollInterval) + /// Drives the wait to its cap against a clock this test owns, for a power probe + /// that never reports live while frames are already arriving. + /// Shared so each "not live" reading is one assertion rather than a copy of the + /// backoff-driving loop. + private func waitToCap(powerDB: @escaping @Sendable () -> Float) async -> Duration? { + let clock = TestClock() + let timeout = MicLiveness.initialPollInterval * 3 + async let gap = MicLiveness.waitUntilLive( + timeout: timeout, clock: clock, deliveredFrames: { 1024 }, inputPowerDB: powerDB) + var expected = MicLiveness.initialPollInterval + for _ in 1...2 { + await clock.waitUntilSleeping(for: expected) + clock.advance(by: expected) + expected = min(expected * 2, MicLiveness.maxPollInterval) + } + return await gap } - return await gap } -} -/// The transport classification both the liveness cap and `MicCapture`'s tail -/// linger hang off. Pure and pinned here because `AudioRoute`, which reads the -/// raw value, needs real hardware and is excluded from the coverage gate — so -/// this is the only place the decision can be tested. -@Suite("AudioTransport") -struct AudioTransportTests { - @Test("both Bluetooth transport types count") - func bluetoothTransports() { - #expect(AudioTransport.isBluetooth(kAudioDeviceTransportTypeBluetooth)) - #expect(AudioTransport.isBluetooth(kAudioDeviceTransportTypeBluetoothLE)) - } + /// The transport classification both the liveness cap and `MicCapture`'s tail + /// linger hang off. Pure and pinned here because `AudioRoute`, which reads the + /// raw value, needs real hardware and is excluded from the coverage gate — so + /// this is the only place the decision can be tested. + @Suite("AudioTransport") + struct AudioTransportTests { + @Test("both Bluetooth transport types count") + func bluetoothTransports() { + #expect(AudioTransport.isBluetooth(kAudioDeviceTransportTypeBluetooth)) + #expect(AudioTransport.isBluetooth(kAudioDeviceTransportTypeBluetoothLE)) + } - @Test("the tail linger is Bluetooth-only") - func tailLinger() { - // The other transport-conditional policy, here rather than in `MicCapture` - // so it is reachable by `swift test` at all — the capture actor needs real - // hardware and is excluded from the coverage gate. - #expect( - AudioTransport.tailLinger(forTransportType: kAudioDeviceTransportTypeBluetooth) - == AudioTransport.bluetoothTailLinger) - // `.zero`, not a small duration: `stop()` skips the sleep entirely on a - // wired input rather than awaiting a nominal one. - #expect(AudioTransport.tailLinger(forTransportType: kAudioDeviceTransportTypeBuiltIn) == .zero) - #expect(AudioTransport.tailLinger(forTransportType: nil) == .zero) - } + @Test("the tail linger is Bluetooth-only") + func tailLinger() { + // The other transport-conditional policy, here rather than in `MicCapture` + // so it is reachable by `swift test` at all — the capture actor needs real + // hardware and is excluded from the coverage gate. + #expect( + AudioTransport.tailLinger(forTransportType: kAudioDeviceTransportTypeBluetooth) + == AudioTransport.bluetoothTailLinger) + // `.zero`, not a small duration: `stop()` skips the sleep entirely on a + // wired input rather than awaiting a nominal one. + #expect(AudioTransport.tailLinger(forTransportType: kAudioDeviceTransportTypeBuiltIn) == .zero) + #expect(AudioTransport.tailLinger(forTransportType: nil) == .zero) + } - @Test("every wired and on-board transport counts as local") - func localTransports() { - // Each constant asserted individually: `isLocal` is a switch over all of - // them, and a value that only matches the first pattern never executes the - // rest — so this is also what keeps those lines covered. - #expect(AudioTransport.isLocal(kAudioDeviceTransportTypeBuiltIn)) - #expect(AudioTransport.isLocal(kAudioDeviceTransportTypeUSB)) - #expect(AudioTransport.isLocal(kAudioDeviceTransportTypePCI)) - #expect(AudioTransport.isLocal(kAudioDeviceTransportTypeFireWire)) - #expect(AudioTransport.isLocal(kAudioDeviceTransportTypeThunderbolt)) - #expect(AudioTransport.isLocal(kAudioDeviceTransportTypeDisplayPort)) - #expect(AudioTransport.isLocal(kAudioDeviceTransportTypeHDMI)) - } + @Test("every wired and on-board transport counts as local") + func localTransports() { + // Each constant asserted individually: `isLocal` is a switch over all of + // them, and a value that only matches the first pattern never executes the + // rest — so this is also what keeps those lines covered. + #expect(AudioTransport.isLocal(kAudioDeviceTransportTypeBuiltIn)) + #expect(AudioTransport.isLocal(kAudioDeviceTransportTypeUSB)) + #expect(AudioTransport.isLocal(kAudioDeviceTransportTypePCI)) + #expect(AudioTransport.isLocal(kAudioDeviceTransportTypeFireWire)) + #expect(AudioTransport.isLocal(kAudioDeviceTransportTypeThunderbolt)) + #expect(AudioTransport.isLocal(kAudioDeviceTransportTypeDisplayPort)) + #expect(AudioTransport.isLocal(kAudioDeviceTransportTypeHDMI)) + } - @Test("Bluetooth, wrapped, unnamed and unreadable transports are not local") - func nonLocalTransports() { - // `isLocal` is deliberately not `!isBluetooth`: these all fall through to - // `MicLiveness.unknownTransportTimeout`, because an aggregate or virtual - // device reports its own transport while real AirPods switch underneath it. - #expect(!AudioTransport.isLocal(kAudioDeviceTransportTypeAggregate)) - #expect(!AudioTransport.isLocal(kAudioDeviceTransportTypeVirtual)) - #expect(!AudioTransport.isLocal(kAudioDeviceTransportTypeUnknown)) - #expect(!AudioTransport.isLocal(kAudioDeviceTransportTypeBluetooth)) - #expect(!AudioTransport.isLocal(nil)) - } + @Test("Bluetooth, wrapped, unnamed and unreadable transports are not local") + func nonLocalTransports() { + // `isLocal` is deliberately not `!isBluetooth`: these all fall through to + // `MicLiveness.unknownTransportTimeout`, because an aggregate or virtual + // device reports its own transport while real AirPods switch underneath it. + #expect(!AudioTransport.isLocal(kAudioDeviceTransportTypeAggregate)) + #expect(!AudioTransport.isLocal(kAudioDeviceTransportTypeVirtual)) + #expect(!AudioTransport.isLocal(kAudioDeviceTransportTypeUnknown)) + #expect(!AudioTransport.isLocal(kAudioDeviceTransportTypeBluetooth)) + #expect(!AudioTransport.isLocal(nil)) + } - @Test("wired, built-in, and unreadable transports do not") - func nonBluetoothTransports() { - #expect(!AudioTransport.isBluetooth(kAudioDeviceTransportTypeBuiltIn)) - #expect(!AudioTransport.isBluetooth(kAudioDeviceTransportTypeUSB)) - #expect(!AudioTransport.isBluetooth(kAudioDeviceTransportTypeAggregate)) - // nil is the conservative answer for both consumers: the short wait cap and - // no tail linger. Padding every wired capture with a delay would be a worse - // regression than losing the tail on a device we couldn't classify. - #expect(!AudioTransport.isBluetooth(nil)) + @Test("wired, built-in, and unreadable transports do not") + func nonBluetoothTransports() { + #expect(!AudioTransport.isBluetooth(kAudioDeviceTransportTypeBuiltIn)) + #expect(!AudioTransport.isBluetooth(kAudioDeviceTransportTypeUSB)) + #expect(!AudioTransport.isBluetooth(kAudioDeviceTransportTypeAggregate)) + // nil is the conservative answer for both consumers: the short wait cap and + // no tail linger. Padding every wired capture with a delay would be a worse + // regression than losing the tail on a device we couldn't classify. + #expect(!AudioTransport.isBluetooth(nil)) + } } -} -/// `Duration.milliseconds` backs the latency lines `MicCapture` logs for the -/// liveness gap — the field evidence for whether the gate is doing anything — -/// so a silently wrong conversion would make those logs lie. -@Suite("Duration.milliseconds") -struct DurationMillisecondsTests { - @Test func convertsWholeAndFractionalDurations() { - #expect(Duration.milliseconds(250).milliseconds == 250) - #expect(Duration.seconds(2).milliseconds == 2000) - #expect(Duration.zero.milliseconds == 0) - // Sub-millisecond durations keep their fraction rather than truncating to 0. - #expect(Duration.microseconds(500).milliseconds == 0.5) + /// `Duration.milliseconds` backs the latency lines `MicCapture` logs for the + /// liveness gap — the field evidence for whether the gate is doing anything — + /// so a silently wrong conversion would make those logs lie. + @Suite("Duration.milliseconds") + struct DurationMillisecondsTests { + @Test func convertsWholeAndFractionalDurations() { + #expect(Duration.milliseconds(250).milliseconds == 250) + #expect(Duration.seconds(2).milliseconds == 2000) + #expect(Duration.zero.milliseconds == 0) + // Sub-millisecond durations keep their fraction rather than truncating to 0. + #expect(Duration.microseconds(500).milliseconds == 0.5) + } } -} +#endif diff --git a/Tests/BlurtEngineTests/PermissionsCheckerTests.swift b/Tests/BlurtEngineTests/PermissionsCheckerTests.swift index 02d5c50f..9ba23e5c 100644 --- a/Tests/BlurtEngineTests/PermissionsCheckerTests.swift +++ b/Tests/BlurtEngineTests/PermissionsCheckerTests.swift @@ -1,80 +1,82 @@ -import Foundation -import Testing +#if os(macOS) + import Foundation + import Testing -@testable import BlurtEngine + @testable import BlurtEngine -@Suite("PermissionsChecker") -struct PermissionsCheckerTests { + @Suite("PermissionsChecker") + struct PermissionsCheckerTests { - @Test("allGranted requires both microphone and accessibility") - func allGrantedLogic() { - #expect(PermissionStatus(microphone: true, accessibility: true).allGranted) - #expect(!PermissionStatus(microphone: true, accessibility: false).allGranted) - #expect(!PermissionStatus(microphone: false, accessibility: true).allGranted) - #expect(!PermissionStatus(microphone: false, accessibility: false).allGranted) - } + @Test("allGranted requires both microphone and accessibility") + func allGrantedLogic() { + #expect(PermissionStatus(microphone: true, accessibility: true).allGranted) + #expect(!PermissionStatus(microphone: true, accessibility: false).allGranted) + #expect(!PermissionStatus(microphone: false, accessibility: true).allGranted) + #expect(!PermissionStatus(microphone: false, accessibility: false).allGranted) + } - @Test("PermissionStatus is value-equatable") - func equatable() { - #expect( - PermissionStatus(microphone: true, accessibility: false) - == PermissionStatus(microphone: true, accessibility: false)) - #expect( - PermissionStatus(microphone: true, accessibility: false) - != PermissionStatus(microphone: false, accessibility: false)) - } + @Test("PermissionStatus is value-equatable") + func equatable() { + #expect( + PermissionStatus(microphone: true, accessibility: false) + == PermissionStatus(microphone: true, accessibility: false)) + #expect( + PermissionStatus(microphone: true, accessibility: false) + != PermissionStatus(microphone: false, accessibility: false)) + } - /// Every combination of the two probes, so the field each one feeds is pinned. - static let probeCases: [(mic: Bool, accessibility: Bool)] = [ - (true, true), (true, false), (false, true), (false, false), - ] + /// Every combination of the two probes, so the field each one feeds is pinned. + static let probeCases: [(mic: Bool, accessibility: Bool)] = [ + (true, true), (true, false), (false, true), (false, false), + ] - @Test("check reports each probe in its own field", arguments: probeCases) - func checkWiresProbesToFields(mic: Bool, accessibility: Bool) { - // The one thing `check()` does that can be wrong: which probe feeds which - // field. Driving both probes pins it — swap them and half these rows fail. - #expect( - PermissionsChecker.check(micGranted: { mic }, axTrusted: { accessibility }) - == PermissionStatus(microphone: mic, accessibility: accessibility)) - } - - @Test("check consults both probes exactly once") - func checkReadsEachProbeOnce() { - // Each real probe is a TCC read on the permission-poll timer; re-reading one - // per call would double that traffic for a struct with two fields. - let micReads = Counter() - let axReads = Counter() - _ = PermissionsChecker.check( - micGranted: { - _ = micReads.next() - return true - }, - axTrusted: { - _ = axReads.next() - return true - }) - #expect(micReads.value == 1) - #expect(axReads.value == 1) - } + @Test("check reports each probe in its own field", arguments: probeCases) + func checkWiresProbesToFields(mic: Bool, accessibility: Bool) { + // The one thing `check()` does that can be wrong: which probe feeds which + // field. Driving both probes pins it — swap them and half these rows fail. + #expect( + PermissionsChecker.check(micGranted: { mic }, axTrusted: { accessibility }) + == PermissionStatus(microphone: mic, accessibility: accessibility)) + } - /// Smoke tests, deliberately assertion-free: both entry points read - /// process-global TCC state this host can't set, so all they can establish is - /// that the real probes run without throwing or prompting. The behaviour they - /// compose is covered above, against injected probes. - @Suite("PermissionsChecker smoke") - struct SmokeTests { - @Test("the production check() runs against the real probes without prompting") - func productionCheckRuns() { - _ = PermissionsChecker.check() + @Test("check consults both probes exactly once") + func checkReadsEachProbeOnce() { + // Each real probe is a TCC read on the permission-poll timer; re-reading one + // per call would double that traffic for a struct with two fields. + let micReads = Counter() + let axReads = Counter() + _ = PermissionsChecker.check( + micGranted: { + _ = micReads.next() + return true + }, + axTrusted: { + _ = axReads.next() + return true + }) + #expect(micReads.value == 1) + #expect(axReads.value == 1) } - @Test("forceAccessibilityActivity runs without prompting") - @MainActor - func forceAccessibilityActivityRuns() { - // Best-effort, side-effect-light (a read-only AX query against another - // process). This is the no-prompt half of the Accessibility flow — - // `openAccessibilitySettings` adds the trust prompt. - PermissionsChecker.forceAccessibilityActivity() + /// Smoke tests, deliberately assertion-free: both entry points read + /// process-global TCC state this host can't set, so all they can establish is + /// that the real probes run without throwing or prompting. The behaviour they + /// compose is covered above, against injected probes. + @Suite("PermissionsChecker smoke") + struct SmokeTests { + @Test("the production check() runs against the real probes without prompting") + func productionCheckRuns() { + _ = PermissionsChecker.check() + } + + @Test("forceAccessibilityActivity runs without prompting") + @MainActor + func forceAccessibilityActivityRuns() { + // Best-effort, side-effect-light (a read-only AX query against another + // process). This is the no-prompt half of the Accessibility flow — + // `openAccessibilitySettings` adds the trust prompt. + PermissionsChecker.forceAccessibilityActivity() + } } } -} +#endif diff --git a/Tests/BlurtEngineTests/PermissionsResetTests.swift b/Tests/BlurtEngineTests/PermissionsResetTests.swift index 4fd0eee0..72b96e3d 100644 --- a/Tests/BlurtEngineTests/PermissionsResetTests.swift +++ b/Tests/BlurtEngineTests/PermissionsResetTests.swift @@ -1,31 +1,33 @@ -import Testing +#if os(macOS) + import Testing -@testable import BlurtEngine + @testable import BlurtEngine -/// The service names are the whole contract with `tccutil`: it exits 0 for a -/// name it doesn't know as readily as for one it does, so a typo here is a reset -/// that silently clears nothing while reporting success. `reset` itself isn't -/// exercised — running it would clear the developer's own grants — so the names -/// and the roster are what a test can hold. -@Suite("PermissionsReset.Service") -struct PermissionsResetTests { - @Test("names the services tccutil knows") - func serviceNames() { - #expect(PermissionsReset.Service.accessibility.rawValue == "Accessibility") - #expect(PermissionsReset.Service.microphone.rawValue == "Microphone") - // Input Monitoring's internal name — what `tccutil` takes, and not what - // System Settings calls the row. - #expect(PermissionsReset.Service.inputMonitoring.rawValue == "ListenEvent") - } + /// The service names are the whole contract with `tccutil`: it exits 0 for a + /// name it doesn't know as readily as for one it does, so a typo here is a reset + /// that silently clears nothing while reporting success. `reset` itself isn't + /// exercised — running it would clear the developer's own grants — so the names + /// and the roster are what a test can hold. + @Suite("PermissionsReset.Service") + struct PermissionsResetTests { + @Test("names the services tccutil knows") + func serviceNames() { + #expect(PermissionsReset.Service.accessibility.rawValue == "Accessibility") + #expect(PermissionsReset.Service.microphone.rawValue == "Microphone") + // Input Monitoring's internal name — what `tccutil` takes, and not what + // System Settings calls the row. + #expect(PermissionsReset.Service.inputMonitoring.rawValue == "ListenEvent") + } - /// `resetAll` walks the hand-written `sweep` (Periphery can't follow a case - /// reached only through `allCases`), so this is what keeps that list honest: a - /// service added to the enum and forgotten there would otherwise survive every - /// "full" reset in silence. The three are also the ones - /// `scripts/reset-install.sh` lists — a fourth belongs in both places. - @Test("the sweep covers every service the enum names") - func sweepCoversEveryService() { - #expect(Set(PermissionsReset.sweep) == Set(PermissionsReset.Service.allCases)) - #expect(Set(PermissionsReset.sweep) == [.accessibility, .microphone, .inputMonitoring]) + /// `resetAll` walks the hand-written `sweep` (Periphery can't follow a case + /// reached only through `allCases`), so this is what keeps that list honest: a + /// service added to the enum and forgotten there would otherwise survive every + /// "full" reset in silence. The three are also the ones + /// `scripts/reset-install.sh` lists — a fourth belongs in both places. + @Test("the sweep covers every service the enum names") + func sweepCoversEveryService() { + #expect(Set(PermissionsReset.sweep) == Set(PermissionsReset.Service.allCases)) + #expect(Set(PermissionsReset.sweep) == [.accessibility, .microphone, .inputMonitoring]) + } } -} +#endif diff --git a/Tests/BlurtEngineTests/SigningIdentityMigrationTests.swift b/Tests/BlurtEngineTests/SigningIdentityMigrationTests.swift index b50fa30a..2b913895 100644 --- a/Tests/BlurtEngineTests/SigningIdentityMigrationTests.swift +++ b/Tests/BlurtEngineTests/SigningIdentityMigrationTests.swift @@ -1,111 +1,113 @@ -import Testing +#if os(macOS) + import Testing -@testable import BlurtEngine + @testable import BlurtEngine -@Suite struct SigningIdentityMigrationTests { - private typealias Migration = SigningIdentityMigration + @Suite struct SigningIdentityMigrationTests { + private typealias Migration = SigningIdentityMigration - // The identities `SigningIdentity.current()` produces, one per way Blurt is - // signed. The migration treats them alike — it only ever compares strings — but - // which pairs of them differ is the whole reason the cases below exist, so they - // are spelled out rather than left implied. - // - // A dev build's requirement is explicit and team-based (stamped by the - // `project.yml` post-build install, stable across cert rotation); a release - // carries codesign's default, which names the leaf certificate — so re-issuing - // that certificate produces `reissuedRelease` and orphans the grant. - private static let prefix = SigningIdentity.requirementPrefix - private static let anchor = "identifier \"dev.alex.blurt\" and anchor apple generic" - private static let devBuild = "\(prefix)\(anchor) and certificate leaf[subject.OU] = \"B2VQF7Q2QY\"" - private static let release = "\(prefix)\(anchor) and certificate leaf[subject.CN] = \"Dev ID 2024\"" - private static let reissuedRelease = - "\(prefix)\(anchor) and certificate leaf[subject.CN] = \"Dev ID 2029\"" + // The identities `SigningIdentity.current()` produces, one per way Blurt is + // signed. The migration treats them alike — it only ever compares strings — but + // which pairs of them differ is the whole reason the cases below exist, so they + // are spelled out rather than left implied. + // + // A dev build's requirement is explicit and team-based (stamped by the + // `project.yml` post-build install, stable across cert rotation); a release + // carries codesign's default, which names the leaf certificate — so re-issuing + // that certificate produces `reissuedRelease` and orphans the grant. + private static let prefix = SigningIdentity.requirementPrefix + private static let anchor = "identifier \"dev.alex.blurt\" and anchor apple generic" + private static let devBuild = "\(prefix)\(anchor) and certificate leaf[subject.OU] = \"B2VQF7Q2QY\"" + private static let release = "\(prefix)\(anchor) and certificate leaf[subject.CN] = \"Dev ID 2024\"" + private static let reissuedRelease = + "\(prefix)\(anchor) and certificate leaf[subject.CN] = \"Dev ID 2029\"" - // decide(): unsigned builds never act. - @Test func unsignedNeverActs() { - #expect(Migration.decide(lastIdentity: nil, currentIdentity: nil, isTrusted: false) == .noAction) - #expect(Migration.decide(lastIdentity: "OLD", currentIdentity: nil, isTrusted: true) == .noAction) - } + // decide(): unsigned builds never act. + @Test func unsignedNeverActs() { + #expect(Migration.decide(lastIdentity: nil, currentIdentity: nil, isTrusted: false) == .noAction) + #expect(Migration.decide(lastIdentity: "OLD", currentIdentity: nil, isTrusted: true) == .noAction) + } - // decide(): same identity as last launch is steady state, regardless of trust. - @Test func steadyStateIsNoAction() { - #expect(Migration.decide(lastIdentity: "NEW", currentIdentity: "NEW", isTrusted: false) == .noAction) - #expect(Migration.decide(lastIdentity: "NEW", currentIdentity: "NEW", isTrusted: true) == .noAction) - } + // decide(): same identity as last launch is steady state, regardless of trust. + @Test func steadyStateIsNoAction() { + #expect(Migration.decide(lastIdentity: "NEW", currentIdentity: "NEW", isTrusted: false) == .noAction) + #expect(Migration.decide(lastIdentity: "NEW", currentIdentity: "NEW", isTrusted: true) == .noAction) + } - // decide(): no marker (every build predating it) is treated as changed. - @Test func firstSeenUntrustedResets() { - let decision = Migration.decide(lastIdentity: nil, currentIdentity: "NEW", isTrusted: false) - #expect(decision == .resetThenRecord("NEW")) - } - @Test func firstSeenTrustedRecordsOnly() { - let decision = Migration.decide(lastIdentity: nil, currentIdentity: "NEW", isTrusted: true) - #expect(decision == .record("NEW")) - } + // decide(): no marker (every build predating it) is treated as changed. + @Test func firstSeenUntrustedResets() { + let decision = Migration.decide(lastIdentity: nil, currentIdentity: "NEW", isTrusted: false) + #expect(decision == .resetThenRecord("NEW")) + } + @Test func firstSeenTrustedRecordsOnly() { + let decision = Migration.decide(lastIdentity: nil, currentIdentity: "NEW", isTrusted: true) + #expect(decision == .record("NEW")) + } - // decide(): any identity change at all. - @Test func identityChangedUntrustedResets() { - let decision = Migration.decide(lastIdentity: "OLD", currentIdentity: "NEW", isTrusted: false) - #expect(decision == .resetThenRecord("NEW")) - } - @Test func identityChangedTrustedRecordsOnly() { - let decision = Migration.decide(lastIdentity: "OLD", currentIdentity: "NEW", isTrusted: true) - #expect(decision == .record("NEW")) - } + // decide(): any identity change at all. + @Test func identityChangedUntrustedResets() { + let decision = Migration.decide(lastIdentity: "OLD", currentIdentity: "NEW", isTrusted: false) + #expect(decision == .resetThenRecord("NEW")) + } + @Test func identityChangedTrustedRecordsOnly() { + let decision = Migration.decide(lastIdentity: "OLD", currentIdentity: "NEW", isTrusted: true) + #expect(decision == .record("NEW")) + } - // decide(): the case this exists for now that debug builds carry their own - // bundle id. Re-issuing the Developer ID certificate (RELEASE.md's rotation - // procedure) changes the leaf its default requirement names, so every installed - // user's grant is suddenly pinned to a requirement the update cannot satisfy — - // switched on in System Settings, denied by `AXIsProcessTrusted()`, with no way - // past the wizard. Nothing at signing time can pre-empt it: the requirement was - // handed to `tccd` before the rotation existed. - @Test func reissuedReleaseCertificateResets() { - let decision = Migration.decide( - lastIdentity: Self.release, currentIdentity: Self.reissuedRelease, isTrusted: false) - #expect(decision == .resetThenRecord(Self.reissuedRelease)) - } + // decide(): the case this exists for now that debug builds carry their own + // bundle id. Re-issuing the Developer ID certificate (RELEASE.md's rotation + // procedure) changes the leaf its default requirement names, so every installed + // user's grant is suddenly pinned to a requirement the update cannot satisfy — + // switched on in System Settings, denied by `AXIsProcessTrusted()`, with no way + // past the wizard. Nothing at signing time can pre-empt it: the requirement was + // handed to `tccd` before the rotation existed. + @Test func reissuedReleaseCertificateResets() { + let decision = Migration.decide( + lastIdentity: Self.release, currentIdentity: Self.reissuedRelease, isTrusted: false) + #expect(decision == .resetThenRecord(Self.reissuedRelease)) + } - // decide(): the flip side — the identity must be *stable* for the loop that - // rebuilds the same way over and over. Two `dev-build.sh` runs pin the same - // team-based requirement, so a working grant survives a rebuild; nothing here - // may reset on every launch. - @Test func rebuildingTheSameWayIsNoAction() { - #expect( - Migration.decide(lastIdentity: Self.devBuild, currentIdentity: Self.devBuild, isTrusted: true) - == .noAction) - #expect( - Migration.decide(lastIdentity: Self.release, currentIdentity: Self.release, isTrusted: false) - == .noAction) - } + // decide(): the flip side — the identity must be *stable* for the loop that + // rebuilds the same way over and over. Two `dev-build.sh` runs pin the same + // team-based requirement, so a working grant survives a rebuild; nothing here + // may reset on every launch. + @Test func rebuildingTheSameWayIsNoAction() { + #expect( + Migration.decide(lastIdentity: Self.devBuild, currentIdentity: Self.devBuild, isTrusted: true) + == .noAction) + #expect( + Migration.decide(lastIdentity: Self.release, currentIdentity: Self.release, isTrusted: false) + == .noAction) + } - // run(): steady state / unsigned persist nothing and never reset. - @Test func runNoActionPersistsNothingAndSkipsReset() { - let out = Migration.run(lastIdentity: "NEW", currentIdentity: "NEW", isTrusted: false) { - Issue.record("reset must not run for .noAction") - return true + // run(): steady state / unsigned persist nothing and never reset. + @Test func runNoActionPersistsNothingAndSkipsReset() { + let out = Migration.run(lastIdentity: "NEW", currentIdentity: "NEW", isTrusted: false) { + Issue.record("reset must not run for .noAction") + return true + } + #expect(out == nil) } - #expect(out == nil) - } - // run(): a trusted identity change records without resetting. - @Test func runRecordsWithoutResetting() { - var didReset = false - let out = Migration.run(lastIdentity: "OLD", currentIdentity: "NEW", isTrusted: true) { - didReset = true - return true + // run(): a trusted identity change records without resetting. + @Test func runRecordsWithoutResetting() { + var didReset = false + let out = Migration.run(lastIdentity: "OLD", currentIdentity: "NEW", isTrusted: true) { + didReset = true + return true + } + #expect(out == "NEW") + #expect(didReset == false) } - #expect(out == "NEW") - #expect(didReset == false) - } - // run(): an untrusted identity change resets, then persists only on success. - @Test func runResetsThenPersistsOnSuccess() { - let out = Migration.run(lastIdentity: "OLD", currentIdentity: "NEW", isTrusted: false) { true } - #expect(out == "NEW") - } - @Test func runDoesNotPersistWhenResetFails() { - let out = Migration.run(lastIdentity: "OLD", currentIdentity: "NEW", isTrusted: false) { false } - #expect(out == nil) + // run(): an untrusted identity change resets, then persists only on success. + @Test func runResetsThenPersistsOnSuccess() { + let out = Migration.run(lastIdentity: "OLD", currentIdentity: "NEW", isTrusted: false) { true } + #expect(out == "NEW") + } + @Test func runDoesNotPersistWhenResetFails() { + let out = Migration.run(lastIdentity: "OLD", currentIdentity: "NEW", isTrusted: false) { false } + #expect(out == nil) + } } -} +#endif diff --git a/Tests/BlurtEngineTests/SigningIdentityTests.swift b/Tests/BlurtEngineTests/SigningIdentityTests.swift index d93d58a5..f7b41bb3 100644 --- a/Tests/BlurtEngineTests/SigningIdentityTests.swift +++ b/Tests/BlurtEngineTests/SigningIdentityTests.swift @@ -1,59 +1,61 @@ -import Foundation -import Security -import Testing +#if os(macOS) + import Foundation + import Security + import Testing -@testable import BlurtEngine + @testable import BlurtEngine -@Suite("SigningIdentity") -struct SigningIdentityTests { + @Suite("SigningIdentity") + struct SigningIdentityTests { - // The value the migration compares must be a property of the *binary*, not of - // the moment it was read — an identity that varied per call would reset the - // Accessibility grant on every launch. - @Test("current() is stable across reads") - func currentIsStable() { - #expect(SigningIdentity.current() == SigningIdentity.current()) - } + // The value the migration compares must be a property of the *binary*, not of + // the moment it was read — an identity that varied per call would reset the + // Accessibility grant on every launch. + @Test("current() is stable across reads") + func currentIsStable() { + #expect(SigningIdentity.current() == SigningIdentity.current()) + } - // What the test host reports depends on how it was signed (ad-hoc under - // `swift test`, team-signed under Xcode), so this asserts the shape of whatever - // this host gives rather than a literal — including the shape of "nothing", - // which is the answer for the ad-hoc host and the one the migration reads as - // "no action". - @Test("current() is either absent or a namespaced requirement") - func currentIsNamespacedWhenPresent() { - guard let identity = SigningIdentity.current() else { - return // ad-hoc or unsigned host: refusing to answer is the contract + // What the test host reports depends on how it was signed (ad-hoc under + // `swift test`, team-signed under Xcode), so this asserts the shape of whatever + // this host gives rather than a literal — including the shape of "nothing", + // which is the answer for the ad-hoc host and the one the migration reads as + // "no action". + @Test("current() is either absent or a namespaced requirement") + func currentIsNamespacedWhenPresent() { + guard let identity = SigningIdentity.current() else { + return // ad-hoc or unsigned host: refusing to answer is the contract + } + #expect(identity.hasPrefix(SigningIdentity.requirementPrefix)) + // Never a bare Team ID (10 alphanumerics, no colon): the marker recorded by + // builds that predate this shape has to stay distinguishable from one + // recorded now, or an upgrade would read as steady state. + #expect(identity.contains(":")) + #expect(identity.count > SigningIdentity.requirementPrefix.count) } - #expect(identity.hasPrefix(SigningIdentity.requirementPrefix)) - // Never a bare Team ID (10 alphanumerics, no colon): the marker recorded by - // builds that predate this shape has to stay distinguishable from one - // recorded now, or an upgrade would read as steady state. - #expect(identity.contains(":")) - #expect(identity.count > SigningIdentity.requirementPrefix.count) - } - // The `Security` handshake is the one part of this file that isn't pure logic, - // and the host's own signature can't exercise it (ad-hoc under `swift test`). - // `/bin/ls` can: it is present on every Mac and Apple-signed, so its designated - // requirement is both readable and known. If this returns nil the migration - // silently degrades to "never act" — a grant orphaned by a re-issued release - // certificate would then strand every user with no way past the wizard. - @Test("a designated requirement can actually be read") - func designatedRequirementIsReadable() throws { - var code: SecStaticCode? - let status = SecStaticCodeCreateWithPath( - URL(fileURLWithPath: "/bin/ls") as CFURL, SecCSFlags(), &code) - #expect(status == errSecSuccess) - let staticCode = try #require(code) - let requirement = try #require(SigningIdentity.designatedRequirement(of: staticCode)) - #expect(requirement.contains("anchor apple")) - } + // The `Security` handshake is the one part of this file that isn't pure logic, + // and the host's own signature can't exercise it (ad-hoc under `swift test`). + // `/bin/ls` can: it is present on every Mac and Apple-signed, so its designated + // requirement is both readable and known. If this returns nil the migration + // silently degrades to "never act" — a grant orphaned by a re-issued release + // certificate would then strand every user with no way past the wizard. + @Test("a designated requirement can actually be read") + func designatedRequirementIsReadable() throws { + var code: SecStaticCode? + let status = SecStaticCodeCreateWithPath( + URL(fileURLWithPath: "/bin/ls") as CFURL, SecCSFlags(), &code) + #expect(status == errSecSuccess) + let staticCode = try #require(code) + let requirement = try #require(SigningIdentity.designatedRequirement(of: staticCode)) + #expect(requirement.contains("anchor apple")) + } - // The process's own code object has to resolve, or `current()` can only ever - // answer nil and the migration is dead weight in every build. - @Test("this process's code object resolves") - func selfStaticCodeResolves() throws { - _ = try #require(SigningIdentity.staticCodeForSelf()) + // The process's own code object has to resolve, or `current()` can only ever + // answer nil and the migration is dead weight in every build. + @Test("this process's code object resolves") + func selfStaticCodeResolves() throws { + _ = try #require(SigningIdentity.staticCodeForSelf()) + } } -} +#endif diff --git a/Tests/BlurtEngineTests/Stubs/DictationSessionTestSupport.swift b/Tests/BlurtEngineTests/Stubs/DictationSessionTestSupport.swift index 65ad9c8d..4afcdc5c 100644 --- a/Tests/BlurtEngineTests/Stubs/DictationSessionTestSupport.swift +++ b/Tests/BlurtEngineTests/Stubs/DictationSessionTestSupport.swift @@ -23,7 +23,7 @@ struct SessionFixture { func makeSession( mode: StubTranscriber.Mode = .transcript("Hello world."), maxRecordingSeconds: Double = SyncSTTLimits.autoReleaseSeconds, - field: FocusCapture.FocusedFieldContext = .empty, + field: FocusedFieldContext = .empty, frontmost: CapturedFocus? = nil, keyTerms: [String] = [], onTranscriptDelivered: (@Sendable (String, RecentDictations) -> Void)? = nil @@ -50,7 +50,7 @@ func makeSession( /// the press-time context, so a test can assert on it instead of counting that /// *something* host-dependent arrived. func testSeams( - field: FocusCapture.FocusedFieldContext = .empty, + field: FocusedFieldContext = .empty, frontmost: CapturedFocus? = nil, log: RecordedLog = RecordedLog() ) -> DictationSession.Seams { @@ -69,7 +69,7 @@ func testSeams( /// did, and both copies quietly dropped the transcript recording `testSeams` /// wires up, so a later assertion on `log.transcripts` would have seen nothing. func hungFieldSeams( - field: FocusCapture.FocusedFieldContext = .empty, + field: FocusedFieldContext = .empty, log: RecordedLog = RecordedLog() ) -> (seams: DictationSession.Seams, release: DispatchSemaphore) { let hung = DispatchSemaphore(value: 0) diff --git a/Tests/BlurtEngineTests/Stubs/FakeClipboard.swift b/Tests/BlurtEngineTests/Stubs/FakeClipboard.swift index de0b9617..563feffd 100644 --- a/Tests/BlurtEngineTests/Stubs/FakeClipboard.swift +++ b/Tests/BlurtEngineTests/Stubs/FakeClipboard.swift @@ -1,58 +1,60 @@ -import Foundation -import Synchronization +#if os(macOS) + import Foundation + import Synchronization -@testable import BlurtEngine + @testable import BlurtEngine -/// In-memory `ClipboardAccess` for tests: holds a single plain string without -/// touching the system pasteboard, and lets a test simulate another process -/// overwriting the clipboard via `externalWrite`. Shared by the KeyInjector -/// insert and delete suites. A `Mutex` guards the state, making the `Sendable` -/// conformance compiler-checked. -/// -/// The narrowed `ClipboardAccess` seam keeps the pasteboard's change-count and -/// restore-if-unchanged policy inside `SystemClipboard`, so this fake only has -/// to hold a string and a write counter — it never re-derives that policy. -final class FakeClipboard: ClipboardAccess, Sendable { - private struct State { - var text: String? - var count = 0 - } - private let state: Mutex - - init(string: String?) { - state = Mutex(State(text: string)) - } + /// In-memory `ClipboardAccess` for tests: holds a single plain string without + /// touching the system pasteboard, and lets a test simulate another process + /// overwriting the clipboard via `externalWrite`. Shared by the KeyInjector + /// insert and delete suites. A `Mutex` guards the state, making the `Sendable` + /// conformance compiler-checked. + /// + /// The narrowed `ClipboardAccess` seam keeps the pasteboard's change-count and + /// restore-if-unchanged policy inside `SystemClipboard`, so this fake only has + /// to hold a string and a write counter — it never re-derives that policy. + final class FakeClipboard: ClipboardAccess, Sendable { + private struct State { + var text: String? + var count = 0 + } + private let state: Mutex - func write(_ text: String) { - state.withLock { - $0.text = text - $0.count += 1 + init(string: String?) { + state = Mutex(State(text: string)) } - } - func writeAndPrepareRestore(_ text: String) -> @Sendable () -> Void { - let (saved, mark) = state.withLock { s -> (String?, Int) in - let previous = s.text - s.text = text - s.count += 1 - return (previous, s.count) + func write(_ text: String) { + state.withLock { + $0.text = text + $0.count += 1 + } } - return { [self] in - state.withLock { s in - // Another writer bumped the count during the settle window — leave their - // newer contents alone (mirrors SystemClipboard's changeCount guard). - guard s.count == mark else { return } - s.text = saved + + func writeAndPrepareRestore(_ text: String) -> @Sendable () -> Void { + let (saved, mark) = state.withLock { s -> (String?, Int) in + let previous = s.text + s.text = text s.count += 1 + return (previous, s.count) + } + return { [self] in + state.withLock { s in + // Another writer bumped the count during the settle window — leave their + // newer contents alone (mirrors SystemClipboard's changeCount guard). + guard s.count == mark else { return } + s.text = saved + s.count += 1 + } } } - } - /// Simulate another process writing the clipboard mid-paste. - func externalWrite(_ text: String) { write(text) } + /// Simulate another process writing the clipboard mid-paste. + func externalWrite(_ text: String) { write(text) } - /// Current plain-string content, for assertions. - var string: String? { - state.withLock { $0.text } + /// Current plain-string content, for assertions. + var string: String? { + state.withLock { $0.text } + } } -} +#endif diff --git a/Tests/BlurtEngineTests/Stubs/InjectorTestSupport.swift b/Tests/BlurtEngineTests/Stubs/InjectorTestSupport.swift index 181b892f..19db4d24 100644 --- a/Tests/BlurtEngineTests/Stubs/InjectorTestSupport.swift +++ b/Tests/BlurtEngineTests/Stubs/InjectorTestSupport.swift @@ -1,115 +1,124 @@ -import AppKit -import Synchronization -import Testing +#if os(macOS) + import AppKit + import Synchronization + import Testing -@testable import BlurtEngine + @testable import BlurtEngine -/// Shared fixtures for the `KeyInjector.insert` suites (the main insert suite -/// and the fallback/cancel suite live in separate files to stay within the -/// lint file-length budget, but drive the injector the same way). -/// -/// The boxes are classes over `Mutex` (not actors) because they're poked from -/// synchronous `@Sendable` seams like `postPaste`; the `Mutex` makes each -/// `Sendable` conformance compiler-checked instead of `@unchecked`-asserted. + /// Shared fixtures for the `KeyInjector.insert` suites (the main insert suite + /// and the fallback/cancel suite live in separate files to stay within the + /// lint file-length budget, but drive the injector the same way). + /// + /// The boxes are classes over `Mutex` (not actors) because they're poked from + /// synchronous `@Sendable` seams like `postPaste`; the `Mutex` makes each + /// `Sendable` conformance compiler-checked instead of `@unchecked`-asserted. -/// Some live application to stand in as the captured paste target. -func liveTargetApp() throws -> NSRunningApplication { - try #require( - NSWorkspace.shared.runningApplications.first { - $0.processIdentifier > 0 && !$0.isTerminated - }) -} + /// Some live application to stand in as the captured paste target. + func liveTargetApp() throws -> NSRunningApplication { + try #require( + NSWorkspace.shared.runningApplications.first { + $0.processIdentifier > 0 && !$0.isTerminated + }) + } -/// A `KeyInjector` wired to an in-memory clipboard, with `postPaste` recording -/// each pasted string (captured after `setString`, before the deferred -/// restore) into the returned box — for the end-to-end case that pins `insert` -/// threading its resolution through to the paste. (The continuity rules -/// themselves are cases of `resolveInsert` and need no injector at all.) -func makeRecordingInjector() -> (injector: KeyInjector, pasted: StringListBox) { - let clip = FakeClipboard(string: nil) - let pasted = StringListBox() - let injector = KeyInjector( - pasteSettleDuration: .zero, - postPaste: { - pasted.append(clip.string) - return true - }, - // Stub the activation. Omitting this defaulted to `KeyInjector.activate`, a - // REAL `NSRunningApplication.activate()` — so this test yanked the - // developer's foreground app, and failed spuriously whenever - // `liveTargetApp()`'s unordered pick landed on a background-only process - // whose activate() returns false (the injector then throws `.targetAppLost` - // for reasons unrelated to separator logic). It needs a stable non-nil app - // identity, not activation. - activateTarget: { _ in true }, - clipboard: clip) - return (injector, pasted) -} + /// That application as the `CapturedFocus` `KeyInjector.setTarget` takes, so the + /// insert suites pin a target the way `DictationSession` does. + func liveTargetFocus() throws -> CapturedFocus { + let app = try liveTargetApp() + return CapturedFocus(pid: app.processIdentifier, processName: app.localizedName) + } -/// One-shot async gate: `wait()` suspends until `open()` is called. Tolerates -/// `open()` racing ahead of `wait()` (the waiter then returns immediately), and -/// any number of concurrent waiters — `Gate`, which is built from a pair of -/// these, needs that for the stubs whose blocked method is called twice by the -/// regression under test. -/// -/// `open()` is synchronous (a `Mutex`-guarded class, not an actor) because the -/// seams that trip these gates are synchronous `@Sendable` closures like -/// `KeyInjector.postPaste`. -final class AsyncGate: Sendable { - private struct State { - var waiters: [CheckedContinuation] = [] - var opened = false + /// A `KeyInjector` wired to an in-memory clipboard, with `postPaste` recording + /// each pasted string (captured after `setString`, before the deferred + /// restore) into the returned box — for the end-to-end case that pins `insert` + /// threading its resolution through to the paste. (The continuity rules + /// themselves are cases of `resolveInsert` and need no injector at all.) + func makeRecordingInjector() -> (injector: KeyInjector, pasted: StringListBox) { + let clip = FakeClipboard(string: nil) + let pasted = StringListBox() + let injector = KeyInjector( + pasteSettleDuration: .zero, + postPaste: { + pasted.append(clip.string) + return true + }, + // Stub the activation. Omitting this defaulted to `KeyInjector.activate`, a + // REAL `NSRunningApplication.activate()` — so this test yanked the + // developer's foreground app, and failed spuriously whenever + // `liveTargetApp()`'s unordered pick landed on a background-only process + // whose activate() returns false (the injector then throws `.targetAppLost` + // for reasons unrelated to separator logic). It needs a stable non-nil app + // identity, not activation. + activateTarget: { _ in true }, + clipboard: clip) + return (injector, pasted) } - private let state = Mutex(State()) - func wait() async { - await withCheckedContinuation { cont in - let openedAlready = state.withLock { s -> Bool in - if s.opened { return true } - s.waiters.append(cont) - return false + /// One-shot async gate: `wait()` suspends until `open()` is called. Tolerates + /// `open()` racing ahead of `wait()` (the waiter then returns immediately), and + /// any number of concurrent waiters — `Gate`, which is built from a pair of + /// these, needs that for the stubs whose blocked method is called twice by the + /// regression under test. + /// + /// `open()` is synchronous (a `Mutex`-guarded class, not an actor) because the + /// seams that trip these gates are synchronous `@Sendable` closures like + /// `KeyInjector.postPaste`. + final class AsyncGate: Sendable { + private struct State { + var waiters: [CheckedContinuation] = [] + var opened = false + } + private let state = Mutex(State()) + + func wait() async { + await withCheckedContinuation { cont in + let openedAlready = state.withLock { s -> Bool in + if s.opened { return true } + s.waiters.append(cont) + return false + } + if openedAlready { cont.resume() } } - if openedAlready { cont.resume() } } - } - func open() { - let waiters = state.withLock { s -> [CheckedContinuation] in - s.opened = true - let pending = s.waiters - s.waiters.removeAll() - return pending + func open() { + let waiters = state.withLock { s -> [CheckedContinuation] in + s.opened = true + let pending = s.waiters + s.waiters.removeAll() + return pending + } + for waiter in waiters { waiter.resume() } } - for waiter in waiters { waiter.resume() } } -} -/// Thread-safe ordered list of strings recorded inside a `@Sendable` closure, -/// for asserting the sequence of texts a test observed being pasted. Not a -/// `ValueBox<[String]>`: the atomic append is the point — appending through a -/// get-then-set property would race two recorders against each other. -final class StringListBox: Sendable { - private let items = Mutex<[String]>([]) - func append(_ value: String?) { - items.withLock { $0.append(value ?? "") } - } - var values: [String] { - items.withLock { $0 } + /// Thread-safe ordered list of strings recorded inside a `@Sendable` closure, + /// for asserting the sequence of texts a test observed being pasted. Not a + /// `ValueBox<[String]>`: the atomic append is the point — appending through a + /// get-then-set property would race two recorders against each other. + final class StringListBox: Sendable { + private let items = Mutex<[String]>([]) + func append(_ value: String?) { + items.withLock { $0.append(value ?? "") } + } + var values: [String] { + items.withLock { $0 } + } } -} -/// Thread-safe single-value cell for capturing an arbitrary value written inside -/// a `@Sendable` closure and reading it back after the awaited call returns — -/// also how a closure holds the handle of the very task executing it, so it can -/// cancel it (a `Task` is `Sendable`, so that needs no separate box). -final class ValueBox: Sendable { - private let stored: Mutex - init(_ initial: T) { stored = Mutex(initial) } - /// One settable property rather than a `value` getter beside a `set(_:)` — the - /// `Mutex` is what makes the class `Sendable`, so both accessors can go through - /// it and callers read as ordinary assignment. - var value: T { - get { stored.withLock { $0 } } - set { stored.withLock { $0 = newValue } } + /// Thread-safe single-value cell for capturing an arbitrary value written inside + /// a `@Sendable` closure and reading it back after the awaited call returns — + /// also how a closure holds the handle of the very task executing it, so it can + /// cancel it (a `Task` is `Sendable`, so that needs no separate box). + final class ValueBox: Sendable { + private let stored: Mutex + init(_ initial: T) { stored = Mutex(initial) } + /// One settable property rather than a `value` getter beside a `set(_:)` — the + /// `Mutex` is what makes the class `Sendable`, so both accessors can go through + /// it and callers read as ordinary assignment. + var value: T { + get { stored.withLock { $0 } } + set { stored.withLock { $0 = newValue } } + } } -} +#endif diff --git a/Tests/BlurtEngineTests/Stubs/StubInjector.swift b/Tests/BlurtEngineTests/Stubs/StubInjector.swift index 0c5f2ef6..eddb56cf 100644 --- a/Tests/BlurtEngineTests/Stubs/StubInjector.swift +++ b/Tests/BlurtEngineTests/Stubs/StubInjector.swift @@ -1,4 +1,3 @@ -import AppKit import Foundation @testable import BlurtEngine @@ -20,6 +19,6 @@ actor StubInjector: InjectorProtocol { insertedPrior.append(priorText) insertedWindowTitles.append(windowTitle) } - func setTargetApp(_ app: NSRunningApplication?) async {} + func setTarget(_ focus: CapturedFocus?) async {} func setError(_ error: (any Error & Sendable)?) { self.error = error } } diff --git a/Tests/BlurtEngineTests/SystemClipboardTests.swift b/Tests/BlurtEngineTests/SystemClipboardTests.swift index 1564d87a..fa46eee3 100644 --- a/Tests/BlurtEngineTests/SystemClipboardTests.swift +++ b/Tests/BlurtEngineTests/SystemClipboardTests.swift @@ -1,211 +1,213 @@ -import AppKit -import Foundation -import Testing - -@testable import BlurtEngine - -/// Covers `SystemClipboard`, the real-`NSPasteboard` implementation of the -/// `ClipboardAccess` seam (`KeyInjector` uses a fake in its own tests). These -/// run synchronously with no settle window, so they don't race other processes' -/// clipboard activity; `.serialized` because they touch `NSPasteboard.general`. -@Suite("SystemClipboard", .serialized) -struct SystemClipboardTests { - - /// Snapshot/restore the user's clipboard around a test body so the suite leaves - /// the real pasteboard as it found it. - /// - /// Uses the full `snapshot()`/`restore()` primitives rather than just the string - /// flavor: snapshotting only `.string` and then clearing unconditionally meant - /// running these tests wiped a developer's real clipboard whenever it held an - /// image, a file, or styled text. - private func withClipboardRestored(_ body: () throws -> Void) rethrows { - let clip = SystemClipboard() - let saved = clip.snapshot() - defer { - if let saved { clip.restore(saved) } +#if os(macOS) + import AppKit + import Foundation + import Testing + + @testable import BlurtEngine + + /// Covers `SystemClipboard`, the real-`NSPasteboard` implementation of the + /// `ClipboardAccess` seam (`KeyInjector` uses a fake in its own tests). These + /// run synchronously with no settle window, so they don't race other processes' + /// clipboard activity; `.serialized` because they touch `NSPasteboard.general`. + @Suite("SystemClipboard", .serialized) + struct SystemClipboardTests { + + /// Snapshot/restore the user's clipboard around a test body so the suite leaves + /// the real pasteboard as it found it. + /// + /// Uses the full `snapshot()`/`restore()` primitives rather than just the string + /// flavor: snapshotting only `.string` and then clearing unconditionally meant + /// running these tests wiped a developer's real clipboard whenever it held an + /// image, a file, or styled text. + private func withClipboardRestored(_ body: () throws -> Void) rethrows { + let clip = SystemClipboard() + let saved = clip.snapshot() + defer { + if let saved { clip.restore(saved) } + } + try body() } - try body() - } - @Test("setString writes the string and advances changeCount") - func setStringWrites() { - withClipboardRestored { - let pb = NSPasteboard.general - let clip = SystemClipboard() + @Test("setString writes the string and advances changeCount") + func setStringWrites() { + withClipboardRestored { + let pb = NSPasteboard.general + let clip = SystemClipboard() - let before = clip.changeCount - clip.setString("written") + let before = clip.changeCount + clip.setString("written") - #expect(pb.string(forType: .string) == "written") - #expect(clip.changeCount > before) + #expect(pb.string(forType: .string) == "written") + #expect(clip.changeCount > before) + } } - } - @Test("snapshot captures contents that restore brings back") - func snapshotRestoreRoundTrips() throws { - try withClipboardRestored { - let pb = NSPasteboard.general - let clip = SystemClipboard() + @Test("snapshot captures contents that restore brings back") + func snapshotRestoreRoundTrips() throws { + try withClipboardRestored { + let pb = NSPasteboard.general + let clip = SystemClipboard() - pb.clearContents() - pb.setString("original", forType: .string) - let snapshot = try #require(clip.snapshot()) + pb.clearContents() + pb.setString("original", forType: .string) + let snapshot = try #require(clip.snapshot()) - clip.setString("overwritten") - #expect(pb.string(forType: .string) == "overwritten") + clip.setString("overwritten") + #expect(pb.string(forType: .string) == "overwritten") - clip.restore(snapshot) - #expect(pb.string(forType: .string) == "original") + clip.restore(snapshot) + #expect(pb.string(forType: .string) == "original") + } } - } - - @Test("snapshot/restore preserves every representation of multi-type, multi-item contents") - func multiTypeSnapshotRoundTrips() throws { - // The reason `SendablePasteboardItem` keys data by pasteboard *type*: a copy - // of styled text carries several representations (plain string + RTF), and - // the restore must bring all of them back — a string-only round trip would - // silently downgrade the user's clipboard to plain text. - try withClipboardRestored { - let pb = NSPasteboard.general - let clip = SystemClipboard() - let styled = NSPasteboardItem() - styled.setString("styled", forType: .string) - styled.setData(Data("{\\rtf1 styled}".utf8), forType: .rtf) - let plain = NSPasteboardItem() - plain.setString("second item", forType: .string) - pb.clearContents() - pb.writeObjects([styled, plain]) - let snapshot = try #require(clip.snapshot()) - - clip.setString("overwritten") - clip.restore(snapshot) - - let restored = pb.pasteboardItems ?? [] - #expect(restored.count == 2) - #expect(restored.first?.string(forType: .string) == "styled") - #expect(restored.first?.data(forType: .rtf) == Data("{\\rtf1 styled}".utf8)) - #expect(restored.last?.string(forType: .string) == "second item") + @Test("snapshot/restore preserves every representation of multi-type, multi-item contents") + func multiTypeSnapshotRoundTrips() throws { + // The reason `SendablePasteboardItem` keys data by pasteboard *type*: a copy + // of styled text carries several representations (plain string + RTF), and + // the restore must bring all of them back — a string-only round trip would + // silently downgrade the user's clipboard to plain text. + try withClipboardRestored { + let pb = NSPasteboard.general + let clip = SystemClipboard() + + let styled = NSPasteboardItem() + styled.setString("styled", forType: .string) + styled.setData(Data("{\\rtf1 styled}".utf8), forType: .rtf) + let plain = NSPasteboardItem() + plain.setString("second item", forType: .string) + pb.clearContents() + pb.writeObjects([styled, plain]) + let snapshot = try #require(clip.snapshot()) + + clip.setString("overwritten") + clip.restore(snapshot) + + let restored = pb.pasteboardItems ?? [] + #expect(restored.count == 2) + #expect(restored.first?.string(forType: .string) == "styled") + #expect(restored.first?.data(forType: .rtf) == Data("{\\rtf1 styled}".utf8)) + #expect(restored.last?.string(forType: .string) == "second item") + } } - } - - @Test("a degraded snapshot never clears the clipboard it cannot replace") - func degradedSnapshotDoesNotDestroy() { - // The failure this guards: an item that exists but whose representations can't - // be materialized (a promise the owning app declines) used to produce an - // all-empty snapshot, and `restore` cleared first and wrote nothing — so the - // user's clipboard came back EMPTY instead of unchanged. - withClipboardRestored { - let pb = NSPasteboard.general - let clip = SystemClipboard() - - // An item with a declared type but no retrievable data models the promise. - let degraded = PasteboardSnapshot( - items: [SendablePasteboardItem(dataMap: [:])], plainText: nil) - clip.setString("transcript") - clip.restore(degraded) - - // Left alone rather than emptied — the transcript is still recoverable. - #expect(pb.string(forType: .string) == "transcript") + @Test("a degraded snapshot never clears the clipboard it cannot replace") + func degradedSnapshotDoesNotDestroy() { + // The failure this guards: an item that exists but whose representations can't + // be materialized (a promise the owning app declines) used to produce an + // all-empty snapshot, and `restore` cleared first and wrote nothing — so the + // user's clipboard came back EMPTY instead of unchanged. + withClipboardRestored { + let pb = NSPasteboard.general + let clip = SystemClipboard() + + // An item with a declared type but no retrievable data models the promise. + let degraded = PasteboardSnapshot( + items: [SendablePasteboardItem(dataMap: [:])], plainText: nil) + + clip.setString("transcript") + clip.restore(degraded) + + // Left alone rather than emptied — the transcript is still recoverable. + #expect(pb.string(forType: .string) == "transcript") + } } - } - @Test("a partly-readable snapshot falls back to the plain-text floor") - func degradedSnapshotUsesTextFloor() { - withClipboardRestored { - let pb = NSPasteboard.general - let clip = SystemClipboard() + @Test("a partly-readable snapshot falls back to the plain-text floor") + func degradedSnapshotUsesTextFloor() { + withClipboardRestored { + let pb = NSPasteboard.general + let clip = SystemClipboard() - let degraded = PasteboardSnapshot( - items: [SendablePasteboardItem(dataMap: [:])], plainText: "original text") + let degraded = PasteboardSnapshot( + items: [SendablePasteboardItem(dataMap: [:])], plainText: "original text") - clip.setString("transcript") - clip.restore(degraded) + clip.setString("transcript") + clip.restore(degraded) - // Not byte-faithful (the richer flavors are unrecoverable), but the user's - // text survives instead of their clipboard being emptied. - #expect(pb.string(forType: .string) == "original text") + // Not byte-faithful (the richer flavors are unrecoverable), but the user's + // text survives instead of their clipboard being emptied. + #expect(pb.string(forType: .string) == "original text") + } } - } - @Test("writeAndPrepareRestore writes the text and its restore puts the saved contents back") - func writeAndPrepareRestoreRoundTrips() { - // The entry point `KeyInjector` actually pastes through, and the one primitive - // in this type that no test reached: the injector suites drive `FakeClipboard`, - // which holds a string and a counter and deliberately does *not* re-derive the - // save-write-restore policy — the whole point of narrowing the - // `ClipboardAccess` seam. So the policy only exists here, and only here can it - // be checked. - withClipboardRestored { - let pb = NSPasteboard.general - let clip = SystemClipboard() - - pb.clearContents() - pb.setString("original", forType: .string) - - let restore = clip.writeAndPrepareRestore("transcript") - // The transcript is on the clipboard for the target app's ⌘V to read. - #expect(pb.string(forType: .string) == "transcript") - - restore() - #expect(pb.string(forType: .string) == "original") + @Test("writeAndPrepareRestore writes the text and its restore puts the saved contents back") + func writeAndPrepareRestoreRoundTrips() { + // The entry point `KeyInjector` actually pastes through, and the one primitive + // in this type that no test reached: the injector suites drive `FakeClipboard`, + // which holds a string and a counter and deliberately does *not* re-derive the + // save-write-restore policy — the whole point of narrowing the + // `ClipboardAccess` seam. So the policy only exists here, and only here can it + // be checked. + withClipboardRestored { + let pb = NSPasteboard.general + let clip = SystemClipboard() + + pb.clearContents() + pb.setString("original", forType: .string) + + let restore = clip.writeAndPrepareRestore("transcript") + // The transcript is on the clipboard for the target app's ⌘V to read. + #expect(pb.string(forType: .string) == "transcript") + + restore() + #expect(pb.string(forType: .string) == "original") + } } - } - - @Test("a clipboard changed after our paste is left alone rather than restored over") - func restoreSkipsAfterAnExternalWrite() { - // The change-count guard. The restore is deferred by `pasteSettleDuration`, and - // during that window the user may copy something new — restoring then would - // silently destroy what they just copied, which is a worse outcome than leaving - // the transcript behind. So a pasteboard that has moved on since our write is - // not touched. - withClipboardRestored { - let pb = NSPasteboard.general - let clip = SystemClipboard() - - pb.clearContents() - pb.setString("original", forType: .string) - let restore = clip.writeAndPrepareRestore("transcript") - // Someone else copies inside the settle window. - pb.clearContents() - pb.setString("user copied this", forType: .string) - - restore() - #expect(pb.string(forType: .string) == "user copied this") + @Test("a clipboard changed after our paste is left alone rather than restored over") + func restoreSkipsAfterAnExternalWrite() { + // The change-count guard. The restore is deferred by `pasteSettleDuration`, and + // during that window the user may copy something new — restoring then would + // silently destroy what they just copied, which is a worse outcome than leaving + // the transcript behind. So a pasteboard that has moved on since our write is + // not touched. + withClipboardRestored { + let pb = NSPasteboard.general + let clip = SystemClipboard() + + pb.clearContents() + pb.setString("original", forType: .string) + let restore = clip.writeAndPrepareRestore("transcript") + + // Someone else copies inside the settle window. + pb.clearContents() + pb.setString("user copied this", forType: .string) + + restore() + #expect(pb.string(forType: .string) == "user copied this") + } } - } - - @Test("write overwrites the clipboard with just the text") - func writeOverwrites() { - withClipboardRestored { - let pb = NSPasteboard.general - let clip = SystemClipboard() - pb.clearContents() - pb.setString("previous", forType: .string) - // The `ClipboardAccess` half the degraded paste paths use: no restore is - // prepared, because the transcript is meant to *stay* on the clipboard for - // the user to paste by hand. So the previous contents must be gone. - clip.write("transcript") - - #expect(pb.string(forType: .string) == "transcript") + @Test("write overwrites the clipboard with just the text") + func writeOverwrites() { + withClipboardRestored { + let pb = NSPasteboard.general + let clip = SystemClipboard() + + pb.clearContents() + pb.setString("previous", forType: .string) + // The `ClipboardAccess` half the degraded paste paths use: no restore is + // prepared, because the transcript is meant to *stay* on the clipboard for + // the user to paste by hand. So the previous contents must be gone. + clip.write("transcript") + + #expect(pb.string(forType: .string) == "transcript") + } } - } - @Test("restore of an empty snapshot leaves the cleared pasteboard empty") - func restoreEmptyIsNoOp() throws { - try withClipboardRestored { - let pb = NSPasteboard.general - let clip = SystemClipboard() + @Test("restore of an empty snapshot leaves the cleared pasteboard empty") + func restoreEmptyIsNoOp() throws { + try withClipboardRestored { + let pb = NSPasteboard.general + let clip = SystemClipboard() - pb.clearContents() // an empty pasteboard has no items to snapshot - let empty = try #require(clip.snapshot()) - clip.setString("temp") - clip.restore(empty) + pb.clearContents() // an empty pasteboard has no items to snapshot + let empty = try #require(clip.snapshot()) + clip.setString("temp") + clip.restore(empty) - #expect(pb.string(forType: .string) == nil) + #expect(pb.string(forType: .string) == nil) + } } } -} +#endif diff --git a/scripts/check-invariants.sh b/scripts/check-invariants.sh index fb1614d8..8ec67642 100755 --- a/scripts/check-invariants.sh +++ b/scripts/check-invariants.sh @@ -75,7 +75,10 @@ GUARDRAILS=".claude/skills/project-guardrails/SKILL.md" # code extensions also keeps the app scope off the .png and .m4a resources it # was otherwise grepping byte by byte. ENGINE="Sources/*.swift" -APP="App/Blurt/*.swift App/Blurt/*.yml App/Blurt/*.plist :!App/Blurt/Blurt.xcodeproj" +# The app scope is `App/`, not `App/Blurt/`: there is a second app spec now +# (the iOS app), and a scope pinned to one app silently stops covering the +# next one. +APP="App/*.swift App/*.yml App/*.plist :!App/Blurt/Blurt.xcodeproj" TESTS="Tests/*.swift App/Blurt/BlurtUITests/*.swift" # Four parallel arrays rather than one delimited list, for the reason @@ -288,7 +291,7 @@ fi # here until it is staged — and a scan that skips the file you just wrote reads # exactly like a scan that approved it. Warn rather than fail, because an # untracked file is a normal state mid-edit; `git add -N` brings it into scope. -UNTRACKED=$(git ls-files --others --exclude-standard -- Sources Tests App/Blurt) +UNTRACKED=$(git ls-files --others --exclude-standard -- Sources Tests App) if [ -n "$UNTRACKED" ]; then echo "note: untracked files are NOT scanned (git add -N to include them):" printf '%s\n' "$UNTRACKED" | sed 's/^/ /' diff --git a/scripts/check.sh b/scripts/check.sh index 751c43da..bb473508 100755 --- a/scripts/check.sh +++ b/scripts/check.sh @@ -236,16 +236,23 @@ check_no_external_deps() { violation=1 fi - # App: only the local BlurtEngine (path:) package is allowed. A remote package + # Apps: only the local BlurtEngine (path:) package is allowed. A remote package # is declared with a url:/github: key inside project.yml's `packages:` block, so # extract that block and reject any such key. - local app_packages - app_packages="$(awk '/^packages:/{f=1;next} /^[^[:space:]]/{f=0} f' "$APP_DIR/project.yml")" - if printf '%s\n' "$app_packages" | grep -nE '(^|[[:space:]])(url|github):' >/dev/null 2>&1; then - echo "error: App/Blurt/project.yml declares a remote SPM package — the app must carry only the local BlurtEngine:" >&2 - printf '%s\n' "$app_packages" | grep -nE '(^|[[:space:]])(url|github):' >&2 - violation=1 - fi + # + # Every App/*/project.yml, not just the mac app's: the iOS app carries its own + # spec with its own `packages:` block, and a guard that names one file is a + # guard the next app walks around without anyone noticing. + local spec spec_path app_packages + for spec in "$REPO_ROOT"/App/*/project.yml; do + spec_path="${spec#"$REPO_ROOT"/}" + app_packages="$(awk '/^packages:/{f=1;next} /^[^[:space:]]/{f=0} f' "$spec")" + if printf '%s\n' "$app_packages" | grep -nE '(^|[[:space:]])(url|github):' >/dev/null 2>&1; then + echo "error: $spec_path declares a remote SPM package — the app must carry only the local BlurtEngine:" >&2 + printf '%s\n' "$app_packages" | grep -nE '(^|[[:space:]])(url|github):' >&2 + violation=1 + fi + done [ "$violation" -eq 0 ] || return 1 echo "no external dependencies (engine dependency-free; app carries only local BlurtEngine)" From b6f4a0c5d32e4b398f5901c80442fb098976b813 Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Thu, 24 Sep 2026 14:58:20 -0400 Subject: [PATCH 03/79] Add the iPhone app and its keyboard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `App/BlurtiOS/` beside `App/Blurt/`: a SwiftUI app plus a keyboard extension, generated by XcodeGen from their own `project.yml` (the project is not committed; CI and a checkout generate it). The shape iPhone forces: iOS lets no keyboard use the microphone, so the app listens and transcribes and the keyboard is a remote control that inserts the words. They share an App Group (`Shared/SharedState.swift`) and wake each other with Darwin notifications. The app keeps the microphone open for a listening window (`ListeningWindow`, extended by every dictation) over an always-on audio-only capture session (`WindowedAudioSource`) that converts the phone's native format to the 16 kHz mono PCM the dictation API wants (`PCMConverter`) — iOS refuses to open the mic from the background, and during a dictation the app is in the background. The engine's `DictationSession` runs unchanged over that capture, with the keyboard's text-before-cursor arriving through `HostFocusCapture` and the result leaving through `KeyboardRelayInjector` (clipboard plus the quiet "Copied" when no keyboard is around). The keyboard drives the engine's `DictationKeyGate` from the mic key's finger down/up, so a tap latches and a hold is push-to-talk as on the Mac; it inserts through `InsertionSeparator`, reads the phone's contact names for the request's key terms, and taps the haptics on the phase edges. Three layouts — slim bar, mic panel, full keyboard — over one model, chosen in the app. Sign in with AssemblyAI is a stub until the login service exists; debug builds take a pasted key. `check.yml`'s `ios-build` job now generates and builds the app for the simulator too, and SwiftLint covers the new sources. Co-Authored-By: Claude Fable 5.1 --- .github/workflows/check.yml | 26 ++ .gitignore | 8 + .swiftlint.yml | 1 + AGENTS.md | 9 + .../Sources/FullKeyboardView.swift | 66 +++++ .../BlurtKeyboard/Sources/KeyboardModel.swift | 234 +++++++++++++++++ .../Sources/KeyboardViewController.swift | 51 ++++ .../BlurtKeyboard/Sources/KeyboardViews.swift | 212 +++++++++++++++ .../BlurtiOS/Sources/APIKeyModel.swift | 105 ++++++++ .../BlurtiOS/Sources/AudioSource.swift | 232 ++++++++++++++++ .../BlurtiOS/Sources/BlurtiOSApp.swift | 35 +++ .../Sources/DictationCoordinator.swift | 208 +++++++++++++++ App/BlurtiOS/BlurtiOS/Sources/HomeView.swift | 226 ++++++++++++++++ .../BlurtiOS/Sources/KeyEntryView.swift | 50 ++++ .../Sources/KeyboardRelayInjector.swift | 32 +++ .../BlurtiOS/Sources/ListeningWindow.swift | 69 +++++ App/BlurtiOS/README.md | 52 ++++ App/BlurtiOS/Shared/SharedState.swift | 248 ++++++++++++++++++ App/BlurtiOS/project.yml | 130 +++++++++ 19 files changed, 1994 insertions(+) create mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift create mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift create mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift create mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift create mode 100644 App/BlurtiOS/BlurtiOS/Sources/APIKeyModel.swift create mode 100644 App/BlurtiOS/BlurtiOS/Sources/AudioSource.swift create mode 100644 App/BlurtiOS/BlurtiOS/Sources/BlurtiOSApp.swift create mode 100644 App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift create mode 100644 App/BlurtiOS/BlurtiOS/Sources/HomeView.swift create mode 100644 App/BlurtiOS/BlurtiOS/Sources/KeyEntryView.swift create mode 100644 App/BlurtiOS/BlurtiOS/Sources/KeyboardRelayInjector.swift create mode 100644 App/BlurtiOS/BlurtiOS/Sources/ListeningWindow.swift create mode 100644 App/BlurtiOS/README.md create mode 100644 App/BlurtiOS/Shared/SharedState.swift create mode 100644 App/BlurtiOS/project.yml diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index e4fb1d30..719719ef 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -246,6 +246,32 @@ jobs: -derivedDataPath "$RUNNER_TEMP/BlurtEngine-iOS" \ build + - name: Install XcodeGen + # Just the one formula, not `brew bundle --file=Brewfile`: the iPhone + # app's project is the only thing this job generates, and installing the + # other eleven tools would cost more than the build it precedes. xcodegen + # is in the Brewfile too, so this is the version check.sh uses. + run: brew install xcodegen + + - name: Generate the iPhone app's project + working-directory: blurt/App/BlurtiOS + # Generated here rather than committed, unlike App/Blurt/Blurt.xcodeproj: + # that project is committed because people open it; this one is generated + # a second before every build, so it can never go stale against its yml. + run: xcodegen generate --quiet + + - name: Build the iPhone app and its keyboard + working-directory: blurt + # The app embeds the keyboard, so one scheme builds both. Signing is off: + # a simulator build needs no identity, and the App Group entitlement is + # not checked without one. + run: | + xcodebuild -project App/BlurtiOS/BlurtiOS.xcodeproj -scheme BlurtiOS \ + -destination 'generic/platform=iOS Simulator' \ + -derivedDataPath "$RUNNER_TEMP/BlurtiOS" \ + CODE_SIGNING_ALLOWED=NO CODE_SIGN_IDENTITY="" \ + build + # Always-runs summary job, so a *skipped* `check` can't be mistaken for a pass. # GitHub reports a skipped required check to branch protection as successful, so # anything that makes `check` skip — the `changes` filter erroring, a `needs` diff --git a/.gitignore b/.gitignore index fa6e3894..e2f3481f 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,11 @@ __pycache__/ # working notes rather than repo content — quote a number into the PR instead. results*.json *.log + +# The iPhone app's project, Info.plists and entitlements are generated by +# `xcodegen generate` from App/BlurtiOS/project.yml (CI does it right before it +# builds; so does a local checkout). Nothing opens a stale copy, so none of it +# is committed — unlike App/Blurt, whose project people open in Xcode. +App/BlurtiOS/BlurtiOS.xcodeproj/ +App/BlurtiOS/*/Info.plist +App/BlurtiOS/*/*.entitlements diff --git a/.swiftlint.yml b/.swiftlint.yml index 7d9848e0..ed3b3834 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -13,6 +13,7 @@ included: - Tests - App/Blurt/Blurt - App/Blurt/BlurtUITests + - App/BlurtiOS excluded: - .build diff --git a/AGENTS.md b/AGENTS.md index 56d4fada..da88a0dc 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -36,6 +36,7 @@ Four reflexes before you touch anything: | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `Sources/BlurtEngine/` | Swift package (`swift-tools-version:6.2`, `platforms: [.macOS(.v15), .iOS(.v18)]`) owning the pipeline. Pure logic behind protocol seams, no AppKit-shell deps, **no external SPM deps** — Foundation/Security/AVFoundation/CoreAudio plus toolchain modules like Synchronization, with AppKit types only at the seams. The macOS-only files (Accessibility reads, clipboard paste, CoreAudio route reads, TCC and code-signing helpers) are fenced behind `#if os(macOS)`; `check.yml`'s `ios-build` job builds the library for the iOS simulator so a symbol that escapes its fence fails the PR. | | `App/Blurt/` | AppKit/SwiftUI shell (Xcode project generated by XcodeGen) that wires the engine to an overlay window, the main window, a Settings scene, a menu bar item, and the trigger key. Its only package is the local `BlurtEngine` (declared in `App/Blurt/project.yml`). | +| `App/BlurtiOS/` | The iPhone app (SwiftUI) and the keyboard it embeds, generated by XcodeGen from its own `project.yml` and built by `check.yml`'s `ios-build` job. The app owns the engine's pipeline over an always-on capture; the keyboard is a remote control that inserts the words. `App/BlurtiOS/README.md` is its guide. | The engine's dependency-free rule is a **rule**; the app merely happens to carry none today. The former `mxcl/AppUpdater` dependency and its in-place self-updater were removed (see [Updates](#updates)), @@ -84,6 +85,14 @@ App/Blurt/ Resources/Sounds/ audio they name) Shared/ UITestIdentifiers.swift — compiled into BOTH app and UI-test targets BlurtUITests/ XCUITest bundle (see Tests) +App/BlurtiOS/ the iPhone app and its keyboard (README.md there is the guide): + project.yml XcodeGen source of truth — the project is generated, NOT committed + BlurtiOS/Sources/ the app: DictationCoordinator (composition root), ListeningWindow + + WindowedAudioSource (the always-on capture, since iOS can't open + the mic from the background), KeyboardRelayInjector, HomeView + BlurtKeyboard/Sources/ the keyboard: a remote control that inserts the words; three + layouts (slim bar / panel / full keyboard) over one model + Shared/ SharedState.swift — the App Group contract, compiled into BOTH Tests/BlurtEngineTests/ Swift Testing suites; Stubs/ holds the seam doubles scripts/ check.sh, check-portability.sh, check-invariants.sh, bootstrap.sh, dev-build.sh, uitest.sh, leaks.sh, release*.sh diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift b/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift new file mode 100644 index 00000000..216de928 --- /dev/null +++ b/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift @@ -0,0 +1,66 @@ +import SwiftUI + +/// A complete keyboard with the mic as the main key. Letters, shift, a symbols +/// page, space and return — enough to fix a typo without leaving Blurt; no +/// autocorrect or suggestions yet. iOS swaps in its own keyboard for password +/// and phone-number fields, so those never reach here. +struct FullKeyboardView: View { + var model: KeyboardModel + + private static let letters = ["qwertyuiop", "asdfghjkl", "zxcvbnm"] + private static let symbols = ["1234567890", "-/:;()$&@\"", ".,?!'"] + + var body: some View { + VStack(spacing: 8) { + StatusPill(model: model) + ForEach(Array(rows.enumerated()), id: \.offset) { index, row in + HStack(spacing: 5) { + if index == 2 { modifierKey } + ForEach(Array(row), id: \.self) { character in + LetterKey(label: label(for: character)) { model.type(label(for: character)) } + } + if index == 2 { KeyCap(systemImage: "delete.left") { model.deleteBackward() } } + } + } + HStack(spacing: 6) { + if model.needsGlobe { KeyCap(systemImage: "globe") { model.globe() } } + KeyCap(title: model.symbolsPage ? "ABC" : "123") { model.toggleSymbols() } + KeyCap(title: "space", flexible: true) { model.space() } + MicKey(model: model, size: 44) + KeyCap(systemImage: "return") { model.newline() } + } + } + } + + private var rows: [String] { model.symbolsPage ? Self.symbols : Self.letters } + + private func label(for character: Character) -> String { + let text = String(character) + return model.shifted && !model.symbolsPage ? text.uppercased() : text + } + + @ViewBuilder private var modifierKey: some View { + if model.symbolsPage { + KeyCap(title: "#+=") { model.toggleSymbols() } + } else { + KeyCap(systemImage: model.shifted ? "shift.fill" : "shift") { model.toggleShift() } + } + } +} + +/// A letter key: narrower than `KeyCap` so ten fit across a phone. +private struct LetterKey: View { + let label: String + let action: () -> Void + + var body: some View { + Button(action: action) { + Text(label) + .font(.system(size: 21)) + .foregroundStyle(.primary) + .frame(maxWidth: .infinity, minHeight: 40) + .background(Color(uiColor: .secondarySystemGroupedBackground), in: RoundedRectangle(cornerRadius: 6)) + } + .buttonStyle(.plain) + } +} diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift new file mode 100644 index 00000000..65bea6f6 --- /dev/null +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift @@ -0,0 +1,234 @@ +import BlurtEngine +import Foundation +import Observation +import UIKit + +/// The keyboard's state and its side of the conversation with the app: it +/// sends press / release / cancel with the text around the cursor, shows the +/// phase the app publishes, and inserts the words that come back. +/// +/// The mic key's tap-versus-hold rule is the engine's own `DictationKeyGate`, +/// driven by the finger instead of a modifier key: finger down is the key going +/// down, finger up the key coming up, so a tap latches and a hold is +/// push-to-talk exactly as on the Mac. +@MainActor +@Observable +final class KeyboardModel { + var layout: KeyboardLayout = .panel + var snapshot = PhaseSnapshot.idle + var isListening = false + var hasFullAccess = false + var needsGlobe = true + var shifted = true + var symbolsPage = false + + @ObservationIgnored private weak var controller: UIInputViewController? + @ObservationIgnored private var observers: [DarwinObserver] = [] + @ObservationIgnored private var gate = DictationKeyGate() + @ObservationIgnored private let clockStart = ContinuousClock.now + @ObservationIgnored private var lastResultID: UUID? + @ObservationIgnored private var heartbeat: Task? + + var proxy: (any UITextDocumentProxy)? { controller?.textDocumentProxy } + + /// Whether the phase leaves nothing in flight — the moments the gate has to + /// be reset, since a dictation can end with no finger event to close it. + private var isSettled: Bool { + switch snapshot.state { + case .idle, .pasted, .copied, .error: true + case .connecting, .recording, .processing: false + } + } + + // MARK: - Lifecycle + + func attach(to controller: UIInputViewController) { + self.controller = controller + observers = [ + DarwinObserver(name: BlurtShared.Signal.phase) { + Task { @MainActor [weak self] in self?.phaseChanged() } + }, + DarwinObserver(name: BlurtShared.Signal.result) { + Task { @MainActor [weak self] in self?.resultArrived() } + }, + ] + } + + func appeared() { + hasFullAccess = controller?.hasFullAccess ?? false + needsGlobe = controller?.needsInputModeSwitchKey ?? true + // Without Full Access the App Group is out of reach: the keyboard still + // types, and says what it needs (see `KeyboardRootView`), but nothing below + // can run. + guard hasFullAccess else { return } + layout = SharedStore.layout + SharedStore.keyboardEverSeen = true + refresh() + startHeartbeat() + requestLexicon() + } + + func disappeared() { + heartbeat?.cancel() + heartbeat = nil + } + + func contextChanged() {} + + private func refresh() { + isListening = SharedStore.isListening + if let current = SharedStore.read(PhaseSnapshot.self, forKey: BlurtShared.Key.phase) { + apply(current) + } + } + + /// Tells the app the keyboard is on screen, so a finished dictation is + /// handed here rather than copied to the clipboard. + private func startHeartbeat() { + heartbeat?.cancel() + heartbeat = Task { [weak self] in + while !Task.isCancelled { + SharedStore.keyboardSeenAt = Date() + self?.isListening = SharedStore.isListening + try? await Task.sleep(for: .seconds(4)) + } + } + } + + /// The phone's own word list — contact names and text replacements — for + /// the app to spell names right with no setup. Read here because only the + /// keyboard is offered it; the app reads it back out of the App Group. + private func requestLexicon() { + controller?.requestSupplementaryLexicon { @Sendable lexicon in + let entries = lexicon.entries.map { + LexiconEntry(userInput: $0.userInput, documentText: $0.documentText) + } + SharedStore.write(entries, forKey: BlurtShared.Key.lexicon) + SharedStore.post(BlurtShared.Signal.lexicon) + } + } + + // MARK: - The mic key + + func micDown() { + guard hasFullAccess else { return } + guard isListening else { + openApp() + return + } + perform(gate.modifierDown(at: elapsed)) + } + + func micUp() { + guard hasFullAccess, isListening else { return } + perform(gate.modifierUp(at: elapsed)) + } + + func cancel() { + gate.reset() + send(.cancel) + } + + private var elapsed: Duration { clockStart.duration(to: ContinuousClock.now) } + + private func perform(_ action: DictationKeyGate.Action) { + switch action { + case .start: send(.press) + case .stop: send(.release) + case .cancel: send(.cancel) + case .none: break + } + } + + private func send(_ kind: KeyboardCommand.Kind) { + let command = KeyboardCommand( + id: UUID(), kind: kind, priorText: proxy?.documentContextBeforeInput, + selectedText: proxy?.selectedText, sentAt: Date()) + SharedStore.write(command, forKey: BlurtShared.Key.command) + SharedStore.post(BlurtShared.Signal.command) + } + + // MARK: - What comes back + + private func phaseChanged() { + guard let current = SharedStore.read(PhaseSnapshot.self, forKey: BlurtShared.Key.phase) else { return } + apply(current) + } + + private func apply(_ current: PhaseSnapshot) { + let previous = snapshot.state + snapshot = current + isListening = SharedStore.isListening + if current.state != previous { haptics(from: previous, to: current.state) } + // A dictation that ended without a finger event (auto-release, an error) + // would leave the gate latched and swallow the next tap — the same sync the + // Mac shell does on every terminal phase. + if isSettled, !gate.isIdle { gate.reset() } + } + + private func resultArrived() { + guard let result = SharedStore.read(DictationResult.self, forKey: BlurtShared.Key.result), + result.id != lastResultID, let proxy + else { return } + lastResultID = result.id + // Joined against the live text before the cursor, not the press-time + // snapshot: the user may have typed since. + proxy.insertText(InsertionSeparator.withLeadingSeparator(result.text, after: proxy.documentContextBeforeInput)) + } + + private func haptics(from previous: PhaseSnapshot.State, to state: PhaseSnapshot.State) { + guard hasFullAccess else { return } + switch state { + case .recording: + UIImpactFeedbackGenerator(style: .medium).impactOccurred() + case .processing where previous == .recording: + UIImpactFeedbackGenerator(style: .light).impactOccurred() + case .pasted, .copied: + UINotificationFeedbackGenerator().notificationOccurred(.success) + case .error: + UINotificationFeedbackGenerator().notificationOccurred(.error) + case .idle, .connecting, .processing: + break + } + } +} + +// MARK: - Typing and the app + +extension KeyboardModel { + func type(_ text: String) { + proxy?.insertText(text) + if shifted, !symbolsPage { shifted = false } + } + + func deleteBackward() { proxy?.deleteBackward() } + + func newline() { proxy?.insertText("\n") } + + func space() { proxy?.insertText(" ") } + + func toggleShift() { shifted.toggle() } + + func toggleSymbols() { symbolsPage.toggle() } + + func globe() { controller?.advanceToNextInputMode() } + + /// Brings the app forward to open the microphone — the one thing a keyboard + /// cannot do for itself. iOS gives extensions no `open(_:)`, so this walks the + /// responder chain to the application object and asks it, the way every + /// keyboard that opens its app does. + func openApp() { + guard let controller, + let url = URL(string: "\(BlurtShared.urlScheme)://\(BlurtShared.startHost)") + else { return } + let selector = sel_registerName("openURL:") + var responder: UIResponder? = controller + while let current = responder { + if current.responds(to: selector) { + _ = current.perform(selector, with: url) + return + } + responder = current.next + } + } +} diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift new file mode 100644 index 00000000..fd63fdf1 --- /dev/null +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift @@ -0,0 +1,51 @@ +import SwiftUI +import UIKit + +/// The keyboard's entry point — what iOS instantiates when the user picks Blurt +/// from the globe key. Thin on purpose: it hosts the SwiftUI keyboard, sizes it +/// to the layout the user chose, and forwards the lifecycle to `KeyboardModel`, +/// which does the talking to the app. It never hears anything: iOS lets no +/// keyboard use the microphone, so the app listens and this inserts. +final class KeyboardViewController: UIInputViewController { + private let model = KeyboardModel() + private var heightConstraint: NSLayoutConstraint? + + override func viewDidLoad() { + super.viewDidLoad() + model.attach(to: self) + let host = UIHostingController(rootView: KeyboardRootView(model: model)) + addChild(host) + host.view.translatesAutoresizingMaskIntoConstraints = false + host.view.backgroundColor = .clear + view.addSubview(host.view) + NSLayoutConstraint.activate([ + host.view.leadingAnchor.constraint(equalTo: view.leadingAnchor), + host.view.trailingAnchor.constraint(equalTo: view.trailingAnchor), + host.view.topAnchor.constraint(equalTo: view.topAnchor), + host.view.bottomAnchor.constraint(equalTo: view.bottomAnchor), + ]) + host.didMove(toParent: self) + // The keyboard's height is ours to declare; iOS honours a constraint on the + // input view at just under required priority. + let height = view.heightAnchor.constraint(equalToConstant: model.layout.height) + height.priority = UILayoutPriority(999) + height.isActive = true + heightConstraint = height + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + model.appeared() + heightConstraint?.constant = model.layout.height + } + + override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + model.disappeared() + } + + override func textDidChange(_ textInput: (any UITextInput)?) { + super.textDidChange(textInput) + model.contextChanged() + } +} diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift new file mode 100644 index 00000000..8a05a33d --- /dev/null +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift @@ -0,0 +1,212 @@ +import SwiftUI + +/// Picks the layout the user chose. All three share `MicKey`, `StatusPill` and +/// the same model underneath; they differ in how much keyboard surrounds the mic. +struct KeyboardRootView: View { + var model: KeyboardModel + + var body: some View { + Group { + switch model.layout { + case .slimBar: SlimBarView(model: model) + case .panel: PanelView(model: model) + case .full: FullKeyboardView(model: model) + } + } + .padding(.horizontal, 6) + .padding(.vertical, 6) + .frame(maxWidth: .infinity, maxHeight: .infinity) + .background(Color(uiColor: .systemGroupedBackground)) + } +} + +/// A slim strip: the mic, delete, return and the globe. +struct SlimBarView: View { + var model: KeyboardModel + + var body: some View { + HStack(spacing: 8) { + if model.needsGlobe { KeyCap(systemImage: "globe") { model.globe() } } + StatusPill(model: model) + MicKey(model: model, size: 48) + KeyCap(systemImage: "delete.left") { model.deleteBackward() } + KeyCap(systemImage: "return") { model.newline() } + } + } +} + +/// A mic panel: big mic, the status pill, cancel, and a row of keys. +struct PanelView: View { + var model: KeyboardModel + + var body: some View { + VStack(spacing: 10) { + StatusPill(model: model) + HStack(spacing: 24) { + Spacer() + MicKey(model: model, size: 84) + if !model.isSettledState { + KeyCap(systemImage: "xmark", tint: BlurtBrand.errorOrange) { model.cancel() } + } + Spacer() + } + HStack(spacing: 8) { + if model.needsGlobe { KeyCap(systemImage: "globe") { model.globe() } } + KeyCap(title: "space", flexible: true) { model.space() } + KeyCap(systemImage: "delete.left") { model.deleteBackward() } + KeyCap(systemImage: "return") { model.newline() } + } + } + } +} + +/// The phase line: what the app is doing, with a live meter while it records. +struct StatusPill: View { + var model: KeyboardModel + + var body: some View { + HStack(spacing: 8) { + if model.snapshot.state == .recording { + MeterBars(level: model.snapshot.level) + } + Text(text) + .font(.footnote.weight(.medium)) + .foregroundStyle(tint) + .lineLimit(1) + .minimumScaleFactor(0.7) + } + .frame(maxWidth: .infinity) + .padding(.horizontal, 12) + .padding(.vertical, 8) + .background(BlurtBrand.ink, in: Capsule()) + } + + private var text: String { + guard model.hasFullAccess else { return "Allow Full Access for Blurt in Settings → Keyboards" } + guard model.isListening else { return "Tap the mic to start Blurt" } + switch model.snapshot.state { + case .idle: return "Tap to talk, or hold to talk" + case .connecting: return "Connecting…" + case .recording: return "Listening…" + case .processing: return "Transcribing…" + case .pasted: return "Pasted" + case .copied: return "Copied" + case .error: return model.snapshot.message ?? "Something went wrong" + } + } + + private var tint: Color { + model.snapshot.state == .error ? BlurtBrand.errorOrange : BlurtBrand.greenOnDark + } +} + +/// A handful of bars that follow the microphone level. +struct MeterBars: View { + let level: Double + + var body: some View { + HStack(spacing: 2) { + ForEach(0..<5, id: \.self) { index in + Capsule() + .fill(BlurtBrand.greenOnDark) + .frame(width: 3, height: 4 + 12 * CGFloat(max(0, level - Double(index) * 0.15))) + } + } + .frame(height: 16) + .animation(.easeOut(duration: 0.08), value: level) + } +} + +/// The mic. Finger down starts, finger up decides tap (latched) or hold +/// (push-to-talk) — `KeyboardModel` runs the engine's gate. When the app isn't +/// listening the key reads "Start" and opens the app instead. +struct MicKey: View { + var model: KeyboardModel + var size: CGFloat + @State private var pressed = false + + var body: some View { + ZStack { + Circle().fill(fill) + if model.snapshot.state == .recording { + Circle().strokeBorder(BlurtBrand.greenOnDark, lineWidth: 3).scaleEffect(1.12) + } + Image(systemName: model.isListening || !model.hasFullAccess ? "mic.fill" : "play.fill") + .font(.system(size: size * 0.42, weight: .semibold)) + .foregroundStyle(.white) + } + .frame(width: size, height: size) + .scaleEffect(pressed ? 0.94 : 1) + .animation(.easeOut(duration: 0.1), value: pressed) + .accessibilityLabel(model.isListening ? "Dictate" : "Start Blurt") + .simultaneousGesture( + DragGesture(minimumDistance: 0) + .onChanged { _ in + guard !pressed else { return } + pressed = true + model.micDown() + } + .onEnded { _ in + pressed = false + model.micUp() + } + ) + } + + private var fill: Color { + switch model.snapshot.state { + case .recording: BlurtBrand.errorOrange + case .connecting, .processing: BlurtBrand.ink + case .idle, .pasted, .copied, .error: BlurtBrand.green + } + } +} + +/// One ordinary key. `flexible` keys (the space bar) take the width they're +/// given; the rest are square. +struct KeyCap: View { + var title: String? + var systemImage: String? + var tint: Color = .primary + var flexible = false + var action: () -> Void + + init( + title: String? = nil, systemImage: String? = nil, tint: Color = .primary, flexible: Bool = false, + action: @escaping () -> Void + ) { + self.title = title + self.systemImage = systemImage + self.tint = tint + self.flexible = flexible + self.action = action + } + + var body: some View { + Button(action: action) { + Group { + if let systemImage { + Image(systemName: systemImage) + } else { + Text(title ?? "") + } + } + .font(.system(size: 17, weight: .medium)) + .foregroundStyle(tint) + .frame(maxWidth: flexible ? .infinity : 44, minHeight: 40) + .frame(minWidth: 44) + .background(Color(uiColor: .secondarySystemGroupedBackground), in: RoundedRectangle(cornerRadius: 8)) + } + .buttonStyle(.plain) + } +} + +extension KeyboardModel { + /// Whether nothing is in flight, for the views that hide the cancel key. + var isSettledState: Bool { + switch snapshot.state { + case .idle, .pasted, .copied, .error: true + case .connecting, .recording, .processing: false + } + } +} diff --git a/App/BlurtiOS/BlurtiOS/Sources/APIKeyModel.swift b/App/BlurtiOS/BlurtiOS/Sources/APIKeyModel.swift new file mode 100644 index 00000000..c28cfa7e --- /dev/null +++ b/App/BlurtiOS/BlurtiOS/Sources/APIKeyModel.swift @@ -0,0 +1,105 @@ +import BlurtEngine +import Observation + +/// A copy of the Mac shell's `APIKeyModel` (App/Blurt/Blurt/APIKeyModel.swift): +/// nothing in it is platform-specific, and the two apps are separate targets +/// that cannot share a file without a third package. Keep the two in step. +/// +/// The app shell's API-key surface, extracted from `AppCoordinator` so the +/// coordinator stays focused on wiring the pipeline to the UI. Owns the storage +/// seam (`APIKeyGateway`), the validate-then-save flow (`APIKeySubmission`), and +/// the observable `hasAPIKey` flag the wizard/Settings react to. +/// +/// `@Observable` so views that only care about the key (the API-key step, the +/// wizard's readiness gate) observe *this* directly instead of reaching through +/// the coordinator. The validate-and-never-persist-an-unverified-key rules +/// themselves live in the engine's `APIKeySubmission`, where `swift test` covers +/// them; this type just forwards and mirrors the result into `hasAPIKey`. +@Observable +final class APIKeyModel { + /// Storage for the API key. Production hits the Keychain via `APIKeyStore`; + /// UI tests inject an in-memory store so the real key is never touched. + @ObservationIgnored private let keyStore: any APIKeyGateway + /// The validate-then-save flow over `keyStore` (engine-owned + unit-tested). + /// Carries the injected validator: AssemblyAI's real network check in + /// production, an offline stub under UI testing — both through the one submit + /// path, so there's no test-only branch here. + @ObservationIgnored private let submission: APIKeySubmission + + /// Whether an AssemblyAI API key is currently saved. Drives the wizard (which + /// gates dictation on having a key) and the Settings UI. + private(set) var hasAPIKey: Bool + + /// `validateKey` defaults to the engine's real AssemblyAI check; UI tests + /// inject an offline validator so the settings flow needs no network. + /// + /// The `hasKey` read below also loads the Keychain memo (`APIKeyStore.current`), + /// so every later readiness check on the press→recording latency path is + /// served from memory instead of paying a cold `SecItemCopyMatching`. + init( + keyStore: any APIKeyGateway = ProductionAPIKeyStore(), + validateKey: @escaping @Sendable (String) async -> APIKeyValidator.Result = { + await APIKeyValidator().validate($0) + } + ) { + self.keyStore = keyStore + self.submission = APIKeySubmission(keyStore: keyStore, validate: validateKey) + self.hasAPIKey = keyStore.hasKey + } + + /// The key currently stored, read through the gateway. The setup/settings + /// API-key view reads this (rather than `APIKeyStore` directly) so a UI-test + /// run sees the injected in-memory store instead of the real Keychain. + var current: String? { keyStore.current } + + /// The storage seam itself, handed to the Settings window's full-install reset + /// (`InstallReset`) so the sweep deletes the key from the *injected* store — + /// the in-memory one under UI testing — rather than reaching past this model + /// to the production Keychain item. Exposed rather than wrapped in a `clear()` + /// here because the reset owns the sweep; what this model owns is + /// `refreshStatus()`, which is how `hasAPIKey` catches up afterwards. + var storage: any APIKeyGateway { keyStore } + + /// A `@Sendable` snapshot of the readiness gate for `DictationSession`: a press + /// with no key saved fails fast as `.failed(.apiKeyMissing)` before any capture. + /// Captures the (Sendable) store, not this main-actor model, so it can cross + /// into the session's `@Sendable` closure. + func readinessCheck() -> @Sendable () -> BlurtError? { + let keyStore = keyStore + return { keyStore.hasKey ? nil : .apiKeyMissing } + } + + /// Saves the AssemblyAI API key and refreshes `hasAPIKey` so observers — + /// including the wizard — react. Returns true only when a non-empty key is + /// actually readable from Keychain after the write (the engine's + /// `APIKeySubmission.save` owns that read-back rule). + @discardableResult + func save(_ key: String) -> Bool { + let saved = submission.save(key) + refreshStatus() + return saved + } + + /// Re-reads the Keychain and updates `hasAPIKey`. The flag is otherwise only + /// set at `init` and after `save`, so it can drift out of sync with what's + /// actually stored — e.g. an early-launch Keychain read fails (the item's ACL + /// needs re-approval after a re-sign) before a later read succeeds. Calling this + /// when the API-key UI appears keeps the readiness gate honest: a key that's + /// already present flips `hasAPIKey` true, so the wizard advances to the ready + /// screen instead of stranding the user on a setup step whose only control (a + /// *changed*-key "Update") is disabled. + func refreshStatus() { + let hasKey = keyStore.hasKey + if hasKey != hasAPIKey { hasAPIKey = hasKey } + } + + /// Verifies `key` against AssemblyAI and saves it only when AssemblyAI + /// actively accepts it (`.valid`) — the engine's `APIKeySubmission` owns + /// (and unit-tests) that never-persist-an-unverified-key rule. Mirrors the + /// outcome into `hasAPIKey` so the wizard/Settings UI reacts. + func submit(_ key: String) async -> APIKeySubmission.Outcome { + let outcome = await submission.submit(key) + refreshStatus() + return outcome + } +} diff --git a/App/BlurtiOS/BlurtiOS/Sources/AudioSource.swift b/App/BlurtiOS/BlurtiOS/Sources/AudioSource.swift new file mode 100644 index 00000000..5fb7122d --- /dev/null +++ b/App/BlurtiOS/BlurtiOS/Sources/AudioSource.swift @@ -0,0 +1,232 @@ +import AVFoundation +import BlurtEngine +import CoreMedia +import Foundation +import Synchronization + +/// The microphone behind an iOS dictation: an audio-only capture session that +/// stays open for the whole listening window and hands each utterance its own +/// feed. +/// +/// This is deliberately not the Mac's fresh-session-per-press `MicCapture`. +/// iOS refuses to open the microphone from the background, and during a +/// dictation the app *is* in the background — the user is in the app they are +/// typing in, with the Blurt keyboard up. So the app opens the microphone once, +/// while it is in front (the `blurt://start` hop the keyboard makes), keeps it +/// open for the window, and a press simply starts forwarding the frames that +/// are already flowing. What that buys beyond legality is the fastest start +/// the engine has ever had: no device open, no liveness wait, `.recording` +/// within a frame of the press. What it costs is the orange microphone +/// indicator for the length of the window, which is the trade every iPhone +/// dictation keyboard makes. +/// +/// The output's native format is converted to the 16 kHz mono 16-bit the +/// dictation API wants by `PCMConverter` (`audioSettings`, which does that on +/// the Mac, is not in the iOS SDK). `@unchecked Sendable` by confinement, the +/// same way the Mac recorder is: the feed and its tally live behind a `Mutex`, +/// the converter is touched only on the serial delivery queue, and the session +/// is configured once and then only started and stopped. +nonisolated final class WindowedAudioSource: NSObject, MicCaptureProtocol, @unchecked Sendable { + enum Failure: Error, LocalizedError { + /// A press arrived with no listening window open — the keyboard's job is to + /// open the app first, so this is a plumbing fault, not a user error. + case windowClosed + case noInputDevice + + var errorDescription: String? { + switch self { + case .windowClosed: "Blurt isn't listening. Open Blurt to start." + case .noInputDevice: "No microphone is available." + } + } + } + + private struct Feed { + var sink: AsyncStream.Continuation? + var bytes = 0 + } + + private let feed = Mutex(Feed()) + private let session = AVCaptureSession() + private let output = AVCaptureAudioDataOutput() + /// Serial, so the converter below needs no lock. + private let deliveryQueue = DispatchQueue(label: "dev.alex.blurt.ios.capture") + private nonisolated(unsafe) var converter: PCMConverter? + private let levelsContinuation: AsyncStream.Continuation + /// The 0…1 meter the keyboard pill renders, at the output's own cadence. + let levels: AsyncStream + + override init() { + let (stream, continuation) = AsyncStream.makeStream(bufferingPolicy: .bufferingNewest(1)) + levels = stream + levelsContinuation = continuation + super.init() + output.setSampleBufferDelegate(self, queue: deliveryQueue) + } + + var isOpen: Bool { session.isRunning } + + /// Opens the microphone. Only works from the foreground; the audio session + /// must already be active (`ListeningWindow` does both, in that order). + func open() throws { + guard !session.isRunning else { return } + session.beginConfiguration() + session.automaticallyConfiguresApplicationAudioSession = false + if session.inputs.isEmpty { + guard let device = AVCaptureDevice.default(for: .audio) else { + session.commitConfiguration() + throw Failure.noInputDevice + } + let input = try AVCaptureDeviceInput(device: device) + if session.canAddInput(input) { session.addInput(input) } + } + if session.outputs.isEmpty, session.canAddOutput(output) { session.addOutput(output) } + session.commitConfiguration() + session.startRunning() + guard session.isRunning else { throw Failure.noInputDevice } + } + + /// Releases the microphone and ends any utterance in flight. + func close() { + if session.isRunning { session.stopRunning() } + _ = endUtterance() + } + + // MARK: MicCaptureProtocol + + func start() throws -> AsyncStream { + guard session.isRunning else { + throw BlurtError.audioCaptureFailed(underlying: Failure.windowClosed) + } + let (stream, continuation) = AsyncStream.makeStream(bufferingPolicy: .unbounded) + feed.withLock { feed in + feed.sink?.finish() + feed.sink = continuation + feed.bytes = 0 + } + return stream + } + + func stop() -> Int { endUtterance() } + + func cancelCapture() { _ = endUtterance() } + + private func endUtterance() -> Int { + feed.withLock { feed in + let bytes = feed.bytes + feed.sink?.finish() + feed.sink = nil + feed.bytes = 0 + return bytes + } + } + + /// dBFS of a chunk of 16-bit PCM, mapped to 0…1 with the Mac meter's -50 dB + /// floor so room ambient reads as empty bars. + static func level(of pcm: Data) -> Float { + let count = pcm.count / MemoryLayout.size + guard count > 0 else { return 0 } + let energy = pcm.withUnsafeBytes { raw -> Double in + raw.bindMemory(to: Int16.self).reduce(0) { sum, sample in + let value = Double(sample) + return sum + value * value + } + } + let rms = (energy / Double(count)).squareRoot() / Double(Int16.max) + guard rms > 0 else { return 0 } + let floor = -50.0 + let db = 20 * log10(rms) + guard db > floor else { return 0 } + return Float(min(1, (db - floor) / -floor)) + } +} + +extension WindowedAudioSource: AVCaptureAudioDataOutputSampleBufferDelegate { + func captureOutput( + _ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection + ) { + if converter == nil { converter = PCMConverter() } + guard let converter, let chunk = converter.convert(sampleBuffer), !chunk.isEmpty else { return } + levelsContinuation.yield(Self.level(of: chunk)) + feed.withLock { feed in + guard let sink = feed.sink else { return } + feed.bytes += chunk.count + sink.yield(chunk) + } + } +} + +/// Converts whatever format the microphone delivers into the dictation API's +/// 16 kHz mono 16-bit little-endian PCM. One instance per delivery queue; it +/// rebuilds its converter if the input format changes underneath it (a route +/// change to AirPods, say). +nonisolated final class PCMConverter { + private let outputFormat: AVAudioFormat + private var inputFormat: AVAudioFormat? + private var converter: AVAudioConverter? + + init?() { + guard + let format = AVAudioFormat( + commonFormat: .pcmFormatInt16, sampleRate: Double(SyncSTTLimits.sampleRate), channels: 1, + interleaved: true) + else { return nil } + outputFormat = format + } + + func convert(_ sampleBuffer: CMSampleBuffer) -> Data? { + guard let description = CMSampleBufferGetFormatDescription(sampleBuffer), + let streamDescription = CMAudioFormatDescriptionGetStreamBasicDescription(description) + else { return nil } + let frames = AVAudioFrameCount(CMSampleBufferGetNumSamples(sampleBuffer)) + guard frames > 0, let input = inputBuffer(matching: streamDescription, frames: frames) else { return nil } + input.frameLength = frames + let copied = CMSampleBufferCopyPCMDataIntoAudioBufferList( + sampleBuffer, at: 0, frameCount: Int32(frames), into: input.mutableAudioBufferList) + guard copied == noErr, let converter, let inputFormat else { return nil } + let ratio = outputFormat.sampleRate / inputFormat.sampleRate + let capacity = AVAudioFrameCount((Double(frames) * ratio).rounded(.up)) + 64 + guard let outputBuffer = AVAudioPCMBuffer(pcmFormat: outputFormat, frameCapacity: capacity) else { + return nil + } + var handedOver = false + var conversionError: NSError? + let status = converter.convert(to: outputBuffer, error: &conversionError) { _, inputStatus in + if handedOver { + inputStatus.pointee = .noDataNow + return nil + } + handedOver = true + inputStatus.pointee = .haveData + return input + } + guard status != .error, conversionError == nil, outputBuffer.frameLength > 0, + let channels = outputBuffer.int16ChannelData + else { return nil } + return Data(bytes: channels[0], count: Int(outputBuffer.frameLength) * MemoryLayout.size) + } + + /// A buffer in the input's own format, rebuilding the converter when the + /// format is new or changed. + private func inputBuffer( + matching streamDescription: UnsafePointer, frames: AVAudioFrameCount + ) -> AVAudioPCMBuffer? { + if inputFormat == nil || !Self.matches(inputFormat, streamDescription.pointee) { + guard let format = AVAudioFormat(streamDescription: streamDescription) else { return nil } + inputFormat = format + converter = AVAudioConverter(from: format, to: outputFormat) + } + guard let inputFormat else { return nil } + return AVAudioPCMBuffer(pcmFormat: inputFormat, frameCapacity: frames) + } + + private static func matches(_ format: AVAudioFormat?, _ description: AudioStreamBasicDescription) -> Bool { + guard let format else { return false } + let current = format.streamDescription.pointee + return current.mSampleRate == description.mSampleRate + && current.mChannelsPerFrame == description.mChannelsPerFrame + && current.mFormatID == description.mFormatID + && current.mFormatFlags == description.mFormatFlags + && current.mBitsPerChannel == description.mBitsPerChannel + } +} diff --git a/App/BlurtiOS/BlurtiOS/Sources/BlurtiOSApp.swift b/App/BlurtiOS/BlurtiOS/Sources/BlurtiOSApp.swift new file mode 100644 index 00000000..2966fe28 --- /dev/null +++ b/App/BlurtiOS/BlurtiOS/Sources/BlurtiOSApp.swift @@ -0,0 +1,35 @@ +import BlurtEngine +import SwiftUI + +@main +struct BlurtiOSApp: App { + @State private var coordinator: DictationCoordinator + + /// The composition root, and the first thing that runs: the engine's identity + /// has to be set before any engine type is touched (`HostIdentity.configure` + /// documents why), and the coordinator below touches the Keychain in its + /// initializer. The identity is the iPhone app's own — its Keychain item is + /// separate from the Mac app's by construction, since Keychains are per + /// device, but naming it separately keeps the two builds' data apart the day + /// they share an iCloud Keychain. The defaults prefix stays `Blurt` so the + /// engine's stores read and write the same keys they do on the Mac. + init() { + HostIdentity.configure( + HostIdentity( + productName: "Blurt", + subsystem: "dev.alex.blurt.ios", + keychainService: "blurt-ios", + defaultsPrefix: "Blurt", + logDirectoryName: "Blurt", + releaseURL: HostIdentity.blurt.releaseURL)) + _coordinator = State(initialValue: DictationCoordinator()) + } + + var body: some Scene { + WindowGroup { + HomeView(coordinator: coordinator) + .onOpenURL { coordinator.handle($0) } + .task { coordinator.start() } + } + } +} diff --git a/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift b/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift new file mode 100644 index 00000000..92febcee --- /dev/null +++ b/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift @@ -0,0 +1,208 @@ +import AVFoundation +import BlurtEngine +import Foundation +import Observation + +/// The one place the engine is composed for the iPhone app — the role +/// `AppCoordinator` plays in the Mac shell. It owns the listening window (the +/// microphone), the session, and the two channels to the keyboard: commands +/// coming in over the App Group, phase and results going back out. +@MainActor +@Observable +final class DictationCoordinator { + let window: ListeningWindow + let apiKey: APIKeyModel + private(set) var phase: PipelinePhase = .idle + private(set) var recent = RecentDictations() + private(set) var level: Float = 0 + private(set) var microphoneDenied = false + /// How many contact names the keyboard last read off the phone — the key + /// terms that come for free, so the home screen can say so. + private(set) var lexiconNameCount = 0 + + @ObservationIgnored private let session: DictationSession + @ObservationIgnored private let recents: AsyncStream + @ObservationIgnored private var observers: [DarwinObserver] = [] + @ObservationIgnored private var tasks: [Task] = [] + @ObservationIgnored private var lastCommandID: UUID? + @ObservationIgnored private var lastLevelPublish = ContinuousClock.now + + init(apiKey: APIKeyModel = APIKeyModel()) { + let window = ListeningWindow() + self.window = window + self.apiKey = apiKey + let (recents, continuation) = AsyncStream.makeStream( + of: RecentDictations.self, bufferingPolicy: .bufferingNewest(1)) + self.recents = recents + session = DictationSession( + mic: window.source, + transcriber: AssemblyAITranscriber(), + injector: KeyboardRelayInjector(), + keyTermsProvider: { Self.keyTerms() }, + readinessCheck: apiKey.readinessCheck(), + onTranscriptDelivered: { _, ring in continuation.yield(ring) }, + // The keyboard is the only thing that can see the field: the press + // command carries the text before the cursor, and that is what primes + // the request — the same signal the Mac reads through Accessibility. + hostFocusCapture: DictationSession.HostFocusCapture( + frontmost: { nil }, field: { Self.fieldContext() })) + } + + func start() { + observers = [ + DarwinObserver(name: BlurtShared.Signal.command) { + Task { @MainActor [weak self] in self?.handleCommand() } + }, + DarwinObserver(name: BlurtShared.Signal.lexicon) { + Task { @MainActor [weak self] in self?.reloadLexicon() } + }, + ] + reloadLexicon() + tasks = [observePhases(), observeLevels(), observeRecents()] + } + + // MARK: - The listening window + + /// Opens the microphone for the keyboard. Foreground only — this is what + /// `blurt://start` arrives to do. + func startListening() async { + guard await AVAudioApplication.requestRecordPermission() else { + microphoneDenied = true + return + } + microphoneDenied = false + window.open() + } + + func stopListening() { + if phase.isCapturing { session.submit(.cancel) } + window.close() + publish(.idle) + } + + func handle(_ url: URL) { + guard url.scheme == BlurtShared.urlScheme, url.host() == BlurtShared.startHost else { return } + Task { await startListening() } + } + + /// A dictation started from the app itself, with no keyboard to land in — + /// the words go to the clipboard. The way to try Blurt before the keyboard is + /// set up, and the way to test the pipeline without one. + func toggleDictation() { + session.submit(phase.isCapturing ? .release : .press) + } + + // MARK: - Commands from the keyboard + + private func handleCommand() { + guard let command = SharedStore.read(KeyboardCommand.self, forKey: BlurtShared.Key.command), + command.id != lastCommandID + else { return } + lastCommandID = command.id + switch command.kind { + case .press: session.submit(.press) + case .release: session.submit(.release) + case .cancel: session.submit(.cancel) + } + } + + private func reloadLexicon() { + let entries = SharedStore.read([LexiconEntry].self, forKey: BlurtShared.Key.lexicon) ?? [] + lexiconNameCount = entries.filter(\.isName).count + } + + /// The user's typed key terms, then the contact names the keyboard read off + /// the phone, deduplicated case-insensitively. `KeytermsBoost` fits the list + /// to the request's caps (100 terms, 2048 bytes), first entries first, which + /// is why the typed terms lead. + nonisolated static func keyTerms() -> [String] { + let typed = UserDefaults.standard.string(forKey: KeyTermsStore.defaultsKey) ?? "" + let names = (SharedStore.read([LexiconEntry].self, forKey: BlurtShared.Key.lexicon) ?? []) + .filter(\.isName).map(\.documentText) + let candidates = typed.split(separator: ",").map { String($0).trimmingCharacters(in: .whitespacesAndNewlines) } + var seen = Set() + var terms: [String] = [] + for term in candidates + names where !term.isEmpty && seen.insert(term.lowercased()).inserted { + terms.append(term) + } + return terms + } + + /// What the keyboard saw around the cursor when it sent the press. + nonisolated static func fieldContext() -> FocusedFieldContext { + guard let command = SharedStore.read(KeyboardCommand.self, forKey: BlurtShared.Key.command), + command.kind == .press + else { return .empty } + return FocusedFieldContext( + priorText: command.priorText, selectedText: command.selectedText, windowTitle: nil, fieldLabel: nil) + } + + // MARK: - Phase, level and results out to the keyboard + + private func observePhases() -> Task { + let session = session + return Task { [weak self] in + for await phase in await session.phaseStream() { + guard let self else { return } + self.render(phase) + } + } + } + + private func render(_ phase: PipelinePhase) { + self.phase = phase + if phase == .recording { window.extend() } + publish(phase.overlayState) + } + + private func observeLevels() -> Task { + let levels = window.source.levels + return Task { [weak self] in + for await value in levels { + guard let self else { return } + self.level = value + // The keyboard redraws its meter from these; ~12 Hz is plenty for a pill + // and keeps the shared-defaults writes off the capture path's back. + guard self.phase == .recording, + self.lastLevelPublish.duration(to: ContinuousClock.now) > .milliseconds(80) + else { continue } + self.lastLevelPublish = ContinuousClock.now + self.publish(.recording) + } + } + } + + private func observeRecents() -> Task { + let recents = recents + return Task { [weak self] in + for await ring in recents { + guard let self else { return } + self.recent = ring + } + } + } + + private func publish(_ state: OverlayUIState) { + let snapshot = PhaseSnapshot( + state: Self.snapshotState(state), message: Self.message(state), level: Double(level), at: Date()) + SharedStore.write(snapshot, forKey: BlurtShared.Key.phase) + SharedStore.post(BlurtShared.Signal.phase) + } + + private static func snapshotState(_ state: OverlayUIState) -> PhaseSnapshot.State { + switch state { + case .idle: .idle + case .connecting: .connecting + case .recording: .recording + case .processing: .processing + case .pasted: .pasted + case .noTarget: .copied + case .error: .error + } + } + + private static func message(_ state: OverlayUIState) -> String? { + guard case .error(let message) = state else { return nil } + return message + } +} diff --git a/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift b/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift new file mode 100644 index 00000000..0e2874b9 --- /dev/null +++ b/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift @@ -0,0 +1,226 @@ +import AVFoundation +import BlurtEngine +import SwiftUI +import UIKit + +/// The app's one screen: setup while anything is missing, then the listening +/// window, a way to try a dictation right here, the keyboard choice, and the +/// settings the request reads. Plain SwiftUI on purpose — the design pass comes +/// once the loop works on a phone. +struct HomeView: View { + var coordinator: DictationCoordinator + @Environment(\.scenePhase) private var scenePhase + @State private var microphoneGranted = AVAudioApplication.shared.recordPermission == .granted + @State private var keyboardSeen = SharedStore.keyboardEverSeen + @State private var layout = SharedStore.layout + @State private var windowMinutes = SharedStore.windowMinutes + @State private var showsKeyEntry = false + @AppStorage(KeyTermsStore.defaultsKey) private var keyTerms = "" + @AppStorage(EnhancedTranscriptsStore.defaultsKey) private var enhancedTranscripts = + EnhancedTranscriptsStore.defaultValue + + private var isSetUp: Bool { coordinator.apiKey.hasAPIKey && microphoneGranted && keyboardSeen } + + var body: some View { + NavigationStack { + List { + if !isSetUp { setupSection } + listeningSection + tryItSection + keyboardSection + settingsSection + recentSection + } + .navigationTitle("Blurt") + .onChange(of: scenePhase) { _, phase in + if phase == .active { refreshStatus() } + } + .sheet(isPresented: $showsKeyEntry) { KeyEntryView(apiKey: coordinator.apiKey) } + } + .tint(BlurtBrand.green) + } + + private func refreshStatus() { + microphoneGranted = AVAudioApplication.shared.recordPermission == .granted + keyboardSeen = SharedStore.keyboardEverSeen + coordinator.apiKey.refreshStatus() + } + + // MARK: - Setup + + private var setupSection: some View { + Section("Set up") { + SetupRow(done: coordinator.apiKey.hasAPIKey, title: "Sign in with AssemblyAI") { + VStack(alignment: .leading, spacing: 6) { + Text("Coming soon — sign-in needs the AssemblyAI login service.") + .font(.footnote).foregroundStyle(.secondary) + #if DEBUG + Button("Use an API key instead") { showsKeyEntry = true } + #endif + } + } + SetupRow(done: microphoneGranted, title: "Allow the microphone") { + Button("Allow") { + Task { + await coordinator.startListening() + refreshStatus() + } + } + } + SetupRow(done: keyboardSeen, title: "Add the Blurt keyboard") { + VStack(alignment: .leading, spacing: 6) { + Text( + "Settings → Keyboards: turn on Blurt and Allow Full Access. " + + "Full Access is what lets the keyboard send your words to Blurt." + ) + .font(.footnote).foregroundStyle(.secondary) + Button("Open Settings") { openAppSettings() } + } + } + } + } + + private func openAppSettings() { + guard let url = URL(string: UIApplication.openSettingsURLString) else { return } + UIApplication.shared.open(url) + } + + // MARK: - Listening + + private var listeningSection: some View { + Section("Listening") { + if coordinator.window.isOpen { + VStack(alignment: .leading, spacing: 6) { + Label(listeningLabel, systemImage: "mic.fill").foregroundStyle(BlurtBrand.green) + Text("Go back to the app you're typing in and tap the mic on the Blurt keyboard.") + .font(.footnote).foregroundStyle(.secondary) + } + Button("Stop listening", role: .destructive) { coordinator.stopListening() } + } else { + Button("Start listening") { Task { await coordinator.startListening() } } + .disabled(!coordinator.apiKey.hasAPIKey) + Text("Opens the mic for \(windowLabel) so the keyboard can dictate without opening Blurt each time.") + .font(.footnote).foregroundStyle(.secondary) + } + if let error = coordinator.window.lastError { + Text(error).font(.footnote).foregroundStyle(BlurtBrand.errorOrange) + } + if coordinator.microphoneDenied { + Text("Blurt needs the microphone. Allow it in Settings.").font(.footnote) + .foregroundStyle(BlurtBrand.errorOrange) + } + } + } + + private var listeningLabel: String { + guard let until = coordinator.window.until, until != .distantFuture else { return "Listening" } + return "Listening until \(until.formatted(date: .omitted, time: .shortened))" + } + + private var windowLabel: String { + windowMinutes == 0 ? "as long as you like" : "\(windowMinutes) minutes at a time" + } + + // MARK: - Try it + + private var tryItSection: some View { + Section("Try it here") { + Button(coordinator.phase.isCapturing ? "Stop and transcribe" : "Dictate to the clipboard") { + coordinator.toggleDictation() + } + .disabled(!coordinator.window.isOpen) + PhaseLine(phase: coordinator.phase, level: coordinator.level) + } + } + + // MARK: - Keyboard + + private var keyboardSection: some View { + Section { + Picker("Layout", selection: $layout) { + ForEach(KeyboardLayout.allCases) { Text($0.title).tag($0) } + } + .pickerStyle(.segmented) + .onChange(of: layout) { _, value in SharedStore.layout = value } + Text(layout.summary).font(.footnote).foregroundStyle(.secondary) + } header: { + Text("Keyboard") + } footer: { + Text("Any of the three works the same underneath; pick the one that fits how you type.") + } + } + + // MARK: - Settings + + private var settingsSection: some View { + Section("Dictation") { + Picker("Keep listening for", selection: $windowMinutes) { + Text("5 minutes").tag(5) + Text("15 minutes").tag(15) + Text("1 hour").tag(60) + Text("Until I stop it").tag(0) + } + .onChange(of: windowMinutes) { _, value in SharedStore.windowMinutes = value } + Toggle("Enhanced transcripts", isOn: $enhancedTranscripts) + TextField("Key terms, comma-separated", text: $keyTerms, axis: .vertical) + .autocorrectionDisabled() + Text( + "Names and jargon to spell right. \(coordinator.lexiconNameCount) contact names come along automatically." + ) + .font(.footnote).foregroundStyle(.secondary) + } + } + + // MARK: - Recent + + private var recentSection: some View { + Section("Recent") { + if coordinator.recent.entries.isEmpty { + Text("Your recent blurts will appear here").foregroundStyle(.secondary) + } + ForEach(coordinator.recent.displayed) { entry in + VStack(alignment: .leading, spacing: 4) { + Text(entry.text).lineLimit(3) + Text(entry.relativeLabel(now: Date())).font(.caption).foregroundStyle(.secondary) + } + .contextMenu { + Button("Copy") { UIPasteboard.general.string = entry.text } + } + } + } + } +} + +/// One line of the setup checklist: a check or a circle, the step, and its +/// control while it is still to do. +private struct SetupRow: View { + let done: Bool + let title: String + @ViewBuilder let action: () -> Action + + var body: some View { + HStack(alignment: .top, spacing: 12) { + Image(systemName: done ? "checkmark.circle.fill" : "circle") + .foregroundStyle(done ? BlurtBrand.green : Color.secondary) + VStack(alignment: .leading, spacing: 6) { + Text(title) + if !done { action() } + } + } + } +} + +/// The pipeline phase as one line, with a small level meter while recording. +private struct PhaseLine: View { + let phase: PipelinePhase + let level: Float + + var body: some View { + HStack(spacing: 10) { + Text(phase.overlayState.accessibilityLabel).font(.footnote).foregroundStyle(.secondary) + if phase == .recording { + ProgressView(value: Double(level)).tint(BlurtBrand.green).frame(width: 80) + } + } + } +} diff --git a/App/BlurtiOS/BlurtiOS/Sources/KeyEntryView.swift b/App/BlurtiOS/BlurtiOS/Sources/KeyEntryView.swift new file mode 100644 index 00000000..19b561bb --- /dev/null +++ b/App/BlurtiOS/BlurtiOS/Sources/KeyEntryView.swift @@ -0,0 +1,50 @@ +import BlurtEngine +import SwiftUI + +/// Paste an AssemblyAI API key, verified against the API before it is saved +/// (`APIKeySubmission` owns that rule). Debug builds only: the shipping app +/// signs in with AssemblyAI and never shows a key. It exists so the pipeline can +/// be tested on a phone before that service is in place. +struct KeyEntryView: View { + var apiKey: APIKeyModel + @Environment(\.dismiss) private var dismiss + @State private var key = "" + @State private var inlineError: String? + @State private var isSubmitting = false + + var body: some View { + NavigationStack { + Form { + Section { + SecureField("Paste your key", text: $key) + .autocorrectionDisabled() + .textInputAutocapitalization(.never) + if let inlineError { + Text(inlineError).font(.footnote).foregroundStyle(BlurtBrand.errorOrange) + } + } footer: { + Text("Keys live at assemblyai.com/dashboard/api-keys. Stored in the Keychain on this phone.") + } + } + .navigationTitle("API key") + .toolbar { + ToolbarItem(placement: .cancellationAction) { Button("Cancel") { dismiss() } } + ToolbarItem(placement: .confirmationAction) { + Button(isSubmitting ? "Checking…" : "Connect") { Task { await submit() } } + .disabled(key.trimmingCharacters(in: .whitespaces).isEmpty || isSubmitting) + } + } + } + } + + private func submit() async { + isSubmitting = true + defer { isSubmitting = false } + let outcome = await apiKey.submit(key) + switch outcome.failureReport { + case nil: dismiss() + case .inline(let message): inlineError = message + case .alert(let title, let message): inlineError = "\(title) \(message)" + } + } +} diff --git a/App/BlurtiOS/BlurtiOS/Sources/KeyboardRelayInjector.swift b/App/BlurtiOS/BlurtiOS/Sources/KeyboardRelayInjector.swift new file mode 100644 index 00000000..7fafbf25 --- /dev/null +++ b/App/BlurtiOS/BlurtiOS/Sources/KeyboardRelayInjector.swift @@ -0,0 +1,32 @@ +import BlurtEngine +import Foundation +import UIKit + +/// The engine's paste seam on iPhone. Nothing here can type into another app; +/// only the keyboard can, so "insert" means hand the words to the keyboard and +/// ping it. When no keyboard is around to take them — it was dismissed, or the +/// dictation was started from the app itself — the words go to the clipboard +/// instead and the pipeline shows its quiet "Copied" notice, exactly the +/// degradation the Mac uses when nothing editable is focused. +/// +/// The text goes over as returned: the keyboard applies +/// `InsertionSeparator.withLeadingSeparator` against the *live* text before the +/// cursor, which may have moved since the press. +nonisolated struct KeyboardRelayInjector: InjectorProtocol { + /// How recently the keyboard must have checked in to count as present. Its + /// heartbeat is every few seconds while it is on screen. + static let keyboardPresenceWindow: TimeInterval = 15 + + func setTarget(_ focus: CapturedFocus?) async {} + + func insert(_ text: String, after priorText: String?, windowTitle: String?) async throws { + let result = DictationResult(id: UUID(), text: text, deliveredAt: Date()) + SharedStore.write(result, forKey: BlurtShared.Key.result) + SharedStore.post(BlurtShared.Signal.result) + let seen = SharedStore.keyboardSeenAt ?? .distantPast + guard Date().timeIntervalSince(seen) < Self.keyboardPresenceWindow else { + await MainActor.run { UIPasteboard.general.string = text } + throw BlurtError.noEditableTarget + } + } +} diff --git a/App/BlurtiOS/BlurtiOS/Sources/ListeningWindow.swift b/App/BlurtiOS/BlurtiOS/Sources/ListeningWindow.swift new file mode 100644 index 00000000..c98fb01d --- /dev/null +++ b/App/BlurtiOS/BlurtiOS/Sources/ListeningWindow.swift @@ -0,0 +1,69 @@ +import AVFoundation +import Foundation +import Observation + +/// The stretch of time the app keeps the microphone open so the keyboard can +/// start a dictation without bringing the app forward — Wispr calls the same +/// thing a "Flow Session". +/// +/// Opening needs the app in front (iOS refuses to start capture from the +/// background), which is why the keyboard's mic key opens `blurt://start` when +/// no window is open. Once open, `UIBackgroundModes: audio` plus the active +/// audio session keep it alive after the user swipes back. Every dictation +/// extends the window; it closes on its own after `SharedStore.windowMinutes` +/// of silence (0 means never), or when the user closes it in the app. +@MainActor +@Observable +final class ListeningWindow { + let source = WindowedAudioSource() + private(set) var until: Date? + private(set) var lastError: String? + @ObservationIgnored private var expiry: Task? + + var isOpen: Bool { source.isOpen && (until.map { $0 > Date() } ?? false) } + + /// Opens the microphone for `SharedStore.windowMinutes`. Foreground only. + func open() { + do { + let audioSession = AVAudioSession.sharedInstance() + // `.mixWithOthers` so the window doesn't silence whatever the user is + // playing for the whole time it is open; `.defaultToSpeaker` so that + // audio doesn't drop to the earpiece while the microphone is ours; HFP + // so AirPods can be the input. + try audioSession.setCategory( + .playAndRecord, mode: .default, options: [.allowBluetoothHFP, .mixWithOthers, .defaultToSpeaker]) + try audioSession.setActive(true) + try source.open() + lastError = nil + extend() + } catch { + lastError = error.localizedDescription + close() + } + } + + /// Pushes the window's end out again — called on open and after every + /// dictation, so a window only closes on real silence. + func extend() { + let minutes = SharedStore.windowMinutes + let end = minutes > 0 ? Date().addingTimeInterval(TimeInterval(minutes * 60)) : Date.distantFuture + until = end + SharedStore.listeningUntil = end + expiry?.cancel() + guard end != .distantFuture else { return } + expiry = Task { [weak self] in + try? await Task.sleep(for: .seconds(end.timeIntervalSinceNow)) + guard !Task.isCancelled else { return } + self?.close() + } + } + + func close() { + expiry?.cancel() + expiry = nil + source.close() + until = nil + SharedStore.listeningUntil = nil + try? AVAudioSession.sharedInstance().setActive(false, options: .notifyOthersOnDeactivation) + } +} diff --git a/App/BlurtiOS/README.md b/App/BlurtiOS/README.md new file mode 100644 index 00000000..fd97ab53 --- /dev/null +++ b/App/BlurtiOS/README.md @@ -0,0 +1,52 @@ +# Blurt for iPhone + +The iPhone app and the keyboard it ships. Same engine as the Mac app +(`Sources/BlurtEngine`), a different shell, because iPhone leaves no other shape: + +- **The app listens and transcribes.** iOS lets no keyboard use the microphone. The + app opens the microphone while it is in front (the keyboard sends it there with + `blurt://start`), keeps it open for a _listening window_ (`ListeningWindow`, + default 15 minutes, extended by every dictation), and runs the engine's + `DictationSession` over that always-on capture (`WindowedAudioSource`, which + converts the phone's native audio to the 16 kHz mono PCM the dictation API wants). +- **The keyboard is a remote control.** It sends press / release / cancel with the + text around the cursor (the same context the Mac reads through Accessibility), + shows the phase the app publishes, inserts the words that come back through + `textDocumentProxy`, and reads the phone's word list (`UILexicon`: contact names + and text replacements) so names come back spelled right with no setup. +- **They talk through an App Group** (`Shared/SharedState.swift`): payloads in the + shared defaults, Darwin notifications to wake each other. Full Access is what + lets the keyboard reach the group — without it the keyboard still types, and says + what it needs. +- **Three layouts, the user's choice**: a slim mic bar, a mic panel (the Wispr / + Aqua shape), or a full keyboard with the mic as the main key. One keyboard + target, one setting, one set of plumbing. + +## Build + +```bash +cd App/BlurtiOS && xcodegen generate # the project is generated, not committed +open BlurtiOS.xcodeproj # scheme BlurtiOS builds and embeds the keyboard +``` + +CI builds it for the simulator on every PR (`check.yml`'s `ios-build` job). Running +on a phone needs Xcode with a team that can provision the App Group; every id in +`project.yml` (`dev.alex.blurt.ios`, `group.dev.alex.blurt`) is a placeholder +inherited from the Mac app and must become org-owned before the App Store. + +## What is still a stub + +- **Sign in with AssemblyAI.** The shipping app signs the user in and gets a key + behind the scenes; that service does not exist yet. Debug builds show "Use an API + key instead" (`KeyEntryView`) so the pipeline can be tested now. +- **Returning to the host app.** After "Start Blurt" the user swipes back; iOS 26.4 + ended automatic switch-back for everyone. +- **The full keyboard** has no autocorrect or suggestions yet. +- **Interruptions** (a phone call) close the listening window; the user reopens it. + +## What to verify on a phone first + +The listening window's life in the background (capture keeps flowing after the +swipe back; battery over an hour); keyboard → app → back on iOS 26 and 27; the +keyboard's memory with the pill animating; how long the lexicon takes on a phone +with thousands of contacts; and, once the service exists, sign-in end to end. diff --git a/App/BlurtiOS/Shared/SharedState.swift b/App/BlurtiOS/Shared/SharedState.swift new file mode 100644 index 00000000..a78faf79 --- /dev/null +++ b/App/BlurtiOS/Shared/SharedState.swift @@ -0,0 +1,248 @@ +import Foundation +import SwiftUI + +// MARK: - The App Group contract + +/// What the Blurt app and the Blurt keyboard agree on. They are two processes: +/// the app listens and transcribes (iOS lets no keyboard use the microphone), +/// the keyboard drops the words into the field it is attached to. They talk +/// through the App Group's shared defaults and wake each other with Darwin +/// notifications — a system-wide "something changed" ping that carries no data, +/// so every payload lives in the defaults under one of the keys below. +enum BlurtShared { + /// The App Group both targets declare. A placeholder namespace inherited from + /// the Mac app; an org-owned id replaces it before the App Store, and the app + /// and the keyboard must change together. + static let appGroup = "group.dev.alex.blurt" + /// The URL the keyboard opens to bring the app forward (`blurt://start`) — + /// the one moment iOS insists on before the microphone may open. + static let urlScheme = "blurt" + static let startHost = "start" + + enum Key { + static let layout = "keyboardLayout" + static let listeningUntil = "listeningUntil" + static let windowMinutes = "listeningWindowMinutes" + static let phase = "phase" + static let command = "command" + static let result = "result" + static let keyboardSeenAt = "keyboardSeenAt" + static let keyboardEverSeen = "keyboardEverSeen" + static let lexicon = "lexicon" + } + + /// Darwin notification names. Reverse-DNS so they can't collide with another + /// app's on the same device. + enum Signal { + static let command = "dev.alex.blurt.ios.command" + static let phase = "dev.alex.blurt.ios.phase" + static let result = "dev.alex.blurt.ios.result" + static let lexicon = "dev.alex.blurt.ios.lexicon" + } +} + +/// Which keyboard the user chose. All three share the same plumbing underneath; +/// they differ only in how much keyboard sits around the mic. +enum KeyboardLayout: String, CaseIterable, Codable, Sendable, Identifiable { + /// A slim strip: the mic, delete, return and the globe. Typing letters means + /// switching back to the system keyboard. + case slimBar + /// A mic panel with the status pill, a cancel button and a few keys — the + /// shape Wispr and Aqua ship. + case panel + /// A complete keyboard with the mic as the main key, so nobody has to switch + /// keyboards to fix a typo. + case full + + var id: String { rawValue } + + var title: String { + switch self { + case .slimBar: "Mic bar" + case .panel: "Mic panel" + case .full: "Full keyboard" + } + } + + var summary: String { + switch self { + case .slimBar: "Just the mic and a few keys. Switch keyboards to type." + case .panel: "A big mic with status and cancel. Switch keyboards to type." + case .full: "Every letter key, with the mic as the main key." + } + } + + /// The keyboard's height in points. Fixed per layout; the system keyboard is + /// about 216 on a phone, which is what `panel` matches. + var height: CGFloat { + switch self { + case .slimBar: 72 + case .panel: 216 + case .full: 264 + } + } +} + +// MARK: - Payloads + +/// What the keyboard asks the app to do, with the context only the keyboard can +/// see: the text before the cursor primes the transcript exactly as the Mac's +/// Accessibility read does. +struct KeyboardCommand: Codable, Sendable { + enum Kind: String, Codable, Sendable { + case press + case release + case cancel + } + + let id: UUID + let kind: Kind + let priorText: String? + let selectedText: String? + let sentAt: Date +} + +/// The words the app got back, for the keyboard to insert. The keyboard joins +/// them onto the live text before the cursor itself (`InsertionSeparator`), +/// since the user may have typed since the press. +struct DictationResult: Codable, Sendable { + let id: UUID + let text: String + let deliveredAt: Date +} + +/// What the keyboard shows while the app works: the pipeline's phase, flattened +/// to what a pill can render, plus the live microphone level. +struct PhaseSnapshot: Codable, Sendable, Equatable { + enum State: String, Codable, Sendable { + case idle + case connecting + case recording + case processing + case pasted + case copied + case error + } + + let state: State + let message: String? + let level: Double + let at: Date + + static let idle = PhaseSnapshot(state: .idle, message: nil, level: 0, at: .distantPast) +} + +/// One entry of the phone's own word list (`UILexicon`): contact names and the +/// user's text replacements. Names go to the request as key terms so they come +/// back spelled right; replacements are the phone's own text shortcuts. +struct LexiconEntry: Codable, Sendable, Hashable { + let userInput: String + let documentText: String + + /// Contact names come through with both fields equal; a text replacement + /// has a shortcut on one side and its expansion on the other. + var isName: Bool { userInput == documentText } +} + +// MARK: - Shared defaults + +/// Typed access to the App Group's defaults, usable from any thread — the +/// keyboard writes from the main actor, the app's capture path reads from +/// wherever the engine calls it. +nonisolated enum SharedStore { + private static var defaults: UserDefaults { + UserDefaults(suiteName: BlurtShared.appGroup) ?? .standard + } + + static func write(_ value: Value, forKey key: String) { + guard let data = try? JSONEncoder().encode(value) else { return } + defaults.set(data, forKey: key) + } + + static func read(_ type: Value.Type, forKey key: String) -> Value? { + guard let data = defaults.data(forKey: key) else { return nil } + return try? JSONDecoder().decode(type, from: data) + } + + static var layout: KeyboardLayout { + get { KeyboardLayout(rawValue: defaults.string(forKey: BlurtShared.Key.layout) ?? "") ?? .panel } + set { defaults.set(newValue.rawValue, forKey: BlurtShared.Key.layout) } + } + + /// How long a listening window stays open with nobody dictating, in minutes. + /// 0 means until the user closes it. + static var windowMinutes: Int { + get { + guard defaults.object(forKey: BlurtShared.Key.windowMinutes) != nil else { return 15 } + return defaults.integer(forKey: BlurtShared.Key.windowMinutes) + } + set { defaults.set(newValue, forKey: BlurtShared.Key.windowMinutes) } + } + + static var listeningUntil: Date? { + get { defaults.object(forKey: BlurtShared.Key.listeningUntil) as? Date } + set { defaults.set(newValue, forKey: BlurtShared.Key.listeningUntil) } + } + + /// Whether the app currently has the microphone open for the keyboard. + static var isListening: Bool { (listeningUntil ?? .distantPast) > Date() } + + static var keyboardSeenAt: Date? { + get { defaults.object(forKey: BlurtShared.Key.keyboardSeenAt) as? Date } + set { defaults.set(newValue, forKey: BlurtShared.Key.keyboardSeenAt) } + } + + /// Set by the keyboard the first time it runs with Full Access — the only + /// public-API way the app can tell that the keyboard was added and allowed. + static var keyboardEverSeen: Bool { + get { defaults.bool(forKey: BlurtShared.Key.keyboardEverSeen) } + set { defaults.set(newValue, forKey: BlurtShared.Key.keyboardEverSeen) } + } + + /// Fires a Darwin notification. Carries nothing: the receiver reads the + /// payload back out of these defaults. + static func post(_ signal: String) { + CFNotificationCenterPostNotification( + CFNotificationCenterGetDarwinNotifyCenter(), CFNotificationName(signal as CFString), nil, nil, true) + } +} + +/// A Darwin-notification subscription that lives as long as this object does. +/// +/// The handler runs on whichever thread the system delivers on and is +/// `@Sendable` for that reason; hop to the main actor inside it when the work +/// is UI. A class rather than a token so `deinit` can deregister — a listener +/// left behind outlives its owner, since the system holds the callback. +nonisolated final class DarwinObserver: Sendable { + private let name: String + private let handler: @Sendable () -> Void + + init(name: String, handler: @escaping @Sendable () -> Void) { + self.name = name + self.handler = handler + let observer = Unmanaged.passUnretained(self).toOpaque() + CFNotificationCenterAddObserver( + CFNotificationCenterGetDarwinNotifyCenter(), observer, + { _, observer, _, _, _ in + guard let observer else { return } + Unmanaged.fromOpaque(observer).takeUnretainedValue().handler() + }, name as CFString, nil, .deliverImmediately) + } + + deinit { + CFNotificationCenterRemoveObserver( + CFNotificationCenterGetDarwinNotifyCenter(), Unmanaged.passUnretained(self).toOpaque(), + CFNotificationName(name as CFString), nil) + } +} + +// MARK: - Brand + +/// The Mac app's palette (`App/Blurt/Blurt/Branding/BlurtBrand.swift`), for the +/// two iOS targets. Values, not assets, so the keyboard needs no catalog. +enum BlurtBrand { + static let green = Color(red: 1 / 255, green: 118 / 255, blue: 47 / 255) + static let greenOnDark = Color(red: 103 / 255, green: 173 / 255, blue: 130 / 255) + static let ink = Color(red: 29 / 255, green: 27 / 255, blue: 22 / 255) + static let errorOrange = Color(red: 230 / 255, green: 127 / 255, blue: 54 / 255) +} diff --git a/App/BlurtiOS/project.yml b/App/BlurtiOS/project.yml new file mode 100644 index 00000000..330b810e --- /dev/null +++ b/App/BlurtiOS/project.yml @@ -0,0 +1,130 @@ +# XcodeGen spec for Blurt on iPhone: the app (listens and transcribes) plus the +# keyboard it ships (drops the words into whatever app you are typing in). +# +# Like App/Blurt/project.yml this is the source of truth, but unlike it the +# generated BlurtiOS.xcodeproj is NOT committed: nobody opens a stale one, CI +# runs `xcodegen generate` right before it builds, and a local checkout does the +# same (`cd App/BlurtiOS && xcodegen generate`). The Info.plist and entitlements +# files below are generated from the `info:`/`entitlements:` blocks the same way. +# +# Two processes, one App Group. iOS lets no keyboard use the microphone, so the +# app records and talks to AssemblyAI while the keyboard is a remote control that +# inserts the result; they share `group.dev.alex.blurt` (see Shared/). Every id +# here is a placeholder namespace inherited from the Mac app — the App Store +# submission needs org-owned bundle ids, an org App Group and a team that can +# provision them. +name: BlurtiOS +options: + bundleIdPrefix: dev.alex + deploymentTarget: + # Matches Package.swift's `.iOS(.v18)`: an app floor below the package's fails + # to resolve the dependency at all. + iOS: "18.0" + developmentLanguage: en +settings: + base: + SWIFT_VERSION: "6.0" + IPHONEOS_DEPLOYMENT_TARGET: "18.0" + # iPhone first. iPad needs its own keyboard sizing pass. + TARGETED_DEVICE_FAMILY: "1" + DEVELOPMENT_TEAM: B2VQF7Q2QY + CODE_SIGN_STYLE: Automatic +packages: + # The same local package the Mac app carries, reached from App/BlurtiOS. No + # remote packages: check.sh's dependency guard reads every App/*/project.yml. + BlurtEngine: + path: ../.. +targets: + BlurtiOS: + type: application + platform: iOS + sources: + - path: BlurtiOS/Sources + # The App Group contract, compiled into BOTH the app and the keyboard (an + # extension can't import the app's module) — one source, no duplication, + # the same shape as App/Blurt/Shared. + - path: Shared + settings: + base: + PRODUCT_BUNDLE_IDENTIFIER: dev.alex.blurt.ios + # Warnings are failures for our own code, scoped to the target for the + # reason App/Blurt/project.yml gives (the project base collides with the + # -suppress-warnings Xcode applies to SPM packages). + SWIFT_TREAT_WARNINGS_AS_ERRORS: YES + # UI code defaults to the main actor (Swift 6.2), like the Mac shell; + # the capture path and the App Group plumbing opt out with `nonisolated`. + SWIFT_DEFAULT_ACTOR_ISOLATION: MainActor + info: + path: BlurtiOS/Info.plist + properties: + CFBundleDisplayName: Blurt + CFBundleShortVersionString: "0.1.0" + CFBundleVersion: "1" + LSApplicationCategoryType: public.app-category.productivity + NSMicrophoneUsageDescription: Blurt listens only while you dictate, and sends that audio to AssemblyAI to turn it into text. + # Keeps the listening window alive while the user is back in the app + # they are typing in: iOS ends a backgrounded app's capture without it. + UIBackgroundModes: [audio] + UILaunchScreen: {} + UIApplicationSceneManifest: + UIApplicationSupportsMultipleScenes: false + UISupportedInterfaceOrientations: [UIInterfaceOrientationPortrait] + ITSAppUsesNonExemptEncryption: false + # `blurt://start` — what the keyboard opens to bring the app forward, the + # one moment iOS insists on before the microphone may open. + CFBundleURLTypes: + - CFBundleURLName: dev.alex.blurt.ios + CFBundleURLSchemes: [blurt] + entitlements: + path: BlurtiOS/BlurtiOS.entitlements + properties: + com.apple.security.application-groups: [group.dev.alex.blurt] + dependencies: + - package: BlurtEngine + product: BlurtEngine + - target: BlurtKeyboard + # The keyboard. It types, it starts and stops a dictation, it inserts the + # words; it never hears anything. `RequestsOpenAccess` asks the user for Full + # Access, which is what lets it reach the App Group and the app. + BlurtKeyboard: + type: app-extension + platform: iOS + sources: + - path: BlurtKeyboard/Sources + - path: Shared + settings: + base: + PRODUCT_BUNDLE_IDENTIFIER: dev.alex.blurt.ios.keyboard + SWIFT_TREAT_WARNINGS_AS_ERRORS: YES + SWIFT_DEFAULT_ACTOR_ISOLATION: MainActor + APPLICATION_EXTENSION_API_ONLY: YES + info: + path: BlurtKeyboard/Info.plist + properties: + CFBundleDisplayName: Blurt + CFBundleShortVersionString: "0.1.0" + CFBundleVersion: "1" + NSExtension: + NSExtensionPointIdentifier: com.apple.keyboard-service + NSExtensionPrincipalClass: $(PRODUCT_MODULE_NAME).KeyboardViewController + NSExtensionAttributes: + IsASCIICapable: false + PrefersRightToLeft: false + PrimaryLanguage: en-US + RequestsOpenAccess: true + entitlements: + path: BlurtKeyboard/BlurtKeyboard.entitlements + properties: + com.apple.security.application-groups: [group.dev.alex.blurt] + dependencies: + - package: BlurtEngine + product: BlurtEngine +# XcodeGen emits a scheme only where one is declared, and `xcodebuild -scheme` +# needs a shared one. Building the app builds the keyboard it embeds. +schemes: + BlurtiOS: + build: + targets: + BlurtiOS: all + run: + config: Debug From c351de0a35739716c35e70f2954b9bb854de9b6b Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Thu, 24 Sep 2026 15:02:08 -0400 Subject: [PATCH 04/79] Fix the check job: recorder file length, an unused import, redundant public `CaptureSessionRecorder.audioSettings()` moves to its own file so the recorder stays within the 400-line lint budget (the fence tipped it over). `FocusContext.swift` needed no Foundation once `pid` is spelled as the `Int32` it is. `InsertionSeparator` is public for the iOS keyboard, which periphery's Mac scan cannot see, so it carries the same ignore the other iOS-facing API does. Also adds the output-styles screen to the iPhone app: Default plus up to four named profiles over `StyleProfileStore`, with the Mac editor's caps. Co-Authored-By: Claude Fable 5.1 --- App/BlurtiOS/BlurtiOS/Sources/HomeView.swift | 1 + .../BlurtiOS/Sources/StylesView.swift | 144 ++++++++++++++++++ ...CaptureSessionRecorder+AudioSettings.swift | 30 ++++ .../Audio/CaptureSessionRecorder.swift | 29 +--- .../FocusCapture/FocusContext.swift | 9 +- .../Injection/InsertionSeparator.swift | 2 + 6 files changed, 183 insertions(+), 32 deletions(-) create mode 100644 App/BlurtiOS/BlurtiOS/Sources/StylesView.swift create mode 100644 Sources/BlurtEngine/Audio/CaptureSessionRecorder+AudioSettings.swift diff --git a/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift b/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift index 0e2874b9..542d6d8d 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift @@ -162,6 +162,7 @@ struct HomeView: View { } .onChange(of: windowMinutes) { _, value in SharedStore.windowMinutes = value } Toggle("Enhanced transcripts", isOn: $enhancedTranscripts) + NavigationLink("Output styles") { StylesView() } TextField("Key terms, comma-separated", text: $keyTerms, axis: .vertical) .autocorrectionDisabled() Text( diff --git a/App/BlurtiOS/BlurtiOS/Sources/StylesView.swift b/App/BlurtiOS/BlurtiOS/Sources/StylesView.swift new file mode 100644 index 00000000..7abcfb07 --- /dev/null +++ b/App/BlurtiOS/BlurtiOS/Sources/StylesView.swift @@ -0,0 +1,144 @@ +import BlurtEngine +import SwiftUI + +/// Output styles: Default (the engine's base cleanup) plus up to four named +/// profiles whose instructions ride the cleanup rewrite. The store owns the +/// JSON and the active-style rule (`StyleProfileStore`); this view binds to the +/// raw defaults slots only to redraw when they change, and writes through the +/// store, the same discipline as the Mac's style row. +struct StylesView: View { + @AppStorage(StyleProfileStore.defaultsKey) private var profilesRaw = "" + @AppStorage(StyleProfileStore.activeDefaultsKey) private var activeRaw = "" + @State private var editing: StyleProfile? + @State private var adding = false + private let store = StyleProfileStore() + + private var profiles: [StyleProfile] { store.profiles(decoding: profilesRaw) } + private var active: StyleProfile? { StyleProfileStore.active(in: profiles, id: activeRaw) } + + var body: some View { + List { + Section { + StyleRow( + name: StyleProfileStore.defaultStyleName, detail: "Filler out, punctuation fixed, your words kept.", + isActive: active == nil + ) { store.activateDefault() } + ForEach(profiles) { profile in + StyleRow(name: profile.name, detail: profile.instructions, isActive: active?.id == profile.id) { + store.activate(profile) + } + .swipeActions { + Button("Edit") { editing = profile }.tint(BlurtBrand.green) + } + } + } footer: { + Text("Tap a style to use it. Swipe a style to edit it. Up to \(StyleProfileStore.profileLimit).") + } + Section { + Button("Add style") { adding = true } + .disabled(profiles.count >= StyleProfileStore.profileLimit) + } + } + .navigationTitle("Output styles") + .sheet(isPresented: $adding) { StyleEditor(profile: nil, store: store) } + .sheet(item: $editing) { StyleEditor(profile: $0, store: store) } + } +} + +private struct StyleRow: View { + let name: String + let detail: String + let isActive: Bool + let activate: () -> Void + + var body: some View { + Button(action: activate) { + HStack { + VStack(alignment: .leading, spacing: 3) { + Text(name).foregroundStyle(.primary) + Text(detail).font(.footnote).foregroundStyle(.secondary).lineLimit(2) + } + Spacer() + if isActive { Image(systemName: "checkmark").foregroundStyle(BlurtBrand.green) } + } + } + } +} + +/// Name plus instructions, with the same caps the Mac's editor enforces: 24 +/// characters of name, and instructions trimmed to the bytes the API's +/// instruction cap leaves once the base cleanup text has taken its share. +private struct StyleEditor: View { + let profile: StyleProfile? + let store: StyleProfileStore + @Environment(\.dismiss) private var dismiss + @State private var name: String + @State private var instructions: String + + init(profile: StyleProfile?, store: StyleProfileStore) { + self.profile = profile + self.store = store + _name = State(initialValue: profile?.name ?? "") + _instructions = State(initialValue: profile?.instructions ?? "") + } + + private var canSave: Bool { + !name.trimmingCharacters(in: .whitespaces).isEmpty + && !instructions.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty + } + + var body: some View { + NavigationStack { + Form { + Section("Name") { + TextField("e.g. Casual", text: $name) + .onChange(of: name) { _, value in + if value.count > StyleProfileStore.nameLimit { name = String(value.prefix(StyleProfileStore.nameLimit)) } + } + } + Section { + TextField( + "e.g. add fitting emojis sparingly, or always write in lowercase", text: $instructions, axis: .vertical + ) + .lineLimit(3...8) + .onChange(of: instructions) { _, value in + let trimmed = value.prefix(maxUTF8Bytes: StyleProfileStore.characterLimit) + if trimmed != value { instructions = trimmed } + } + } header: { + Text("Instructions") + } footer: { + Text("\(instructions.utf8.count)/\(StyleProfileStore.characterLimit)") + } + if profile != nil { + Section { + Button("Delete style", role: .destructive) { + store.profiles = store.profiles.filter { $0.id != profile?.id } + dismiss() + } + } + } + } + .navigationTitle(profile == nil ? "New style" : "Edit style") + .toolbar { + ToolbarItem(placement: .cancellationAction) { Button("Cancel") { dismiss() } } + ToolbarItem(placement: .confirmationAction) { Button("Save") { save() }.disabled(!canSave) } + } + } + } + + private func save() { + var list = store.profiles + if let profile, let index = list.firstIndex(where: { $0.id == profile.id }) { + list[index].name = name + list[index].instructions = instructions + store.profiles = list + } else { + let created = StyleProfile(name: name, instructions: instructions) + list.append(created) + store.profiles = list + store.activate(created) + } + dismiss() + } +} diff --git a/Sources/BlurtEngine/Audio/CaptureSessionRecorder+AudioSettings.swift b/Sources/BlurtEngine/Audio/CaptureSessionRecorder+AudioSettings.swift new file mode 100644 index 00000000..ccdd43e4 --- /dev/null +++ b/Sources/BlurtEngine/Audio/CaptureSessionRecorder+AudioSettings.swift @@ -0,0 +1,30 @@ +@preconcurrency import AVFoundation + +// The output's format request, in its own file so `CaptureSessionRecorder.swift` +// stays within the lint file-length budget — the same split `DictationSession` +// makes. macOS only: `audioSettings` is not in the iOS SDK (see the recorder). +#if os(macOS) + extension CaptureSessionRecorder { + /// The dictation API's geometry, converted by the output itself — the same six + /// keys the retired WAV recorder asked of its file, so capture still lands in + /// upload-ready S16LE with no resample pass anywhere. + /// + /// Every number comes from `SyncSTTLimits`, which also owns the byte math the + /// upload side applies to the result. They are one contract: a stereo or + /// 8-bit recorder would silently halve or double every duration the pipeline + /// computes. Device-free, so `MicCaptureFormatTests` can assert it despite + /// this file being coverage-excluded; a function rather than a stored static + /// because `[String: Any]` is not `Sendable`, and it is built once per + /// recorder regardless. + static func audioSettings() -> [String: Any] { + [ + AVFormatIDKey: kAudioFormatLinearPCM, + AVSampleRateKey: Double(SyncSTTLimits.sampleRate), + AVNumberOfChannelsKey: SyncSTTLimits.channelCount, + AVLinearPCMBitDepthKey: SyncSTTLimits.bitDepth, + AVLinearPCMIsFloatKey: false, + AVLinearPCMIsBigEndianKey: false, + ] + } + } +#endif diff --git a/Sources/BlurtEngine/Audio/CaptureSessionRecorder.swift b/Sources/BlurtEngine/Audio/CaptureSessionRecorder.swift index f9090b69..b573cca4 100644 --- a/Sources/BlurtEngine/Audio/CaptureSessionRecorder.swift +++ b/Sources/BlurtEngine/Audio/CaptureSessionRecorder.swift @@ -154,11 +154,8 @@ final class CaptureSessionRecorder: NSObject, @unchecked Sendable { "session refused the input device \(device.localizedName, privacy: .public)") } } - // macOS only: `audioSettings` is not in the iOS SDK, where the output vends - // samples in the device's native format. Until the iOS capture path adds a - // conversion stage, what it delivers is not the 16 kHz mono S16LE the - // dictation API is declared to receive — so an iOS host must not upload - // this recorder's frames yet. + // macOS only: `audioSettings` is not in the iOS SDK, so there the output + // vends the device's native format — an iOS host brings its own capture. #if os(macOS) output.audioSettings = Self.audioSettings() #endif @@ -196,28 +193,6 @@ final class CaptureSessionRecorder: NSObject, @unchecked Sendable { return AudioInputDevices.systemDefaultDevice } - /// The dictation API's geometry, converted by the output itself — the same six - /// keys the retired WAV recorder asked of its file, so capture still lands in - /// upload-ready S16LE with no resample pass anywhere. - /// - /// Every number comes from `SyncSTTLimits`, which also owns the byte math the - /// upload side applies to the result. They are one contract: a stereo or - /// 8-bit recorder would silently halve or double every duration the pipeline - /// computes. Device-free, so `MicCaptureFormatTests` can assert it despite - /// this file being coverage-excluded; a function rather than a stored static - /// because `[String: Any]` is not `Sendable`, and it is built once per - /// recorder regardless. - static func audioSettings() -> [String: Any] { - [ - AVFormatIDKey: kAudioFormatLinearPCM, - AVSampleRateKey: Double(SyncSTTLimits.sampleRate), - AVNumberOfChannelsKey: SyncSTTLimits.channelCount, - AVLinearPCMBitDepthKey: SyncSTTLimits.bitDepth, - AVLinearPCMIsFloatKey: false, - AVLinearPCMIsBigEndianKey: false, - ] - } - /// Opens the device and starts capture, answering false when there is no /// usable input: nothing was attached at build time, or the session refused to /// run. diff --git a/Sources/BlurtEngine/FocusCapture/FocusContext.swift b/Sources/BlurtEngine/FocusCapture/FocusContext.swift index 21d812c7..56006f09 100644 --- a/Sources/BlurtEngine/FocusCapture/FocusContext.swift +++ b/Sources/BlurtEngine/FocusCapture/FocusContext.swift @@ -1,19 +1,18 @@ -import Foundation - /// The application that was frontmost when the user pressed the trigger — the /// paste target, and the context's app name. /// -/// A pid and a display name rather than an `NSRunningApplication`, so the value +/// A pid (an `Int32`, which is what `pid_t` is) and a display name rather than +/// an `NSRunningApplication`, so the value /// crosses the engine's public seams (`InjectorProtocol.setTarget`, /// `DictationSession.HostFocusCapture`) on every platform the engine builds /// for. `KeyInjector` resolves the process handle from the pid on macOS; a host /// on iOS has no process to name — a keyboard cannot see which app hosts it — /// and passes nil. public struct CapturedFocus: Sendable { - public let pid: pid_t + public let pid: Int32 public let processName: String? - public init(pid: pid_t, processName: String?) { + public init(pid: Int32, processName: String?) { self.pid = pid self.processName = processName } diff --git a/Sources/BlurtEngine/Injection/InsertionSeparator.swift b/Sources/BlurtEngine/Injection/InsertionSeparator.swift index 5b2e8d91..717ed660 100644 --- a/Sources/BlurtEngine/Injection/InsertionSeparator.swift +++ b/Sources/BlurtEngine/Injection/InsertionSeparator.swift @@ -1,3 +1,4 @@ +// periphery:ignore - public for the iOS keyboard (App/BlurtiOS), which the Mac scan doesn't index. /// The pure text rules for joining a new dictation onto whatever already sits /// before the caret. /// @@ -9,6 +10,7 @@ /// with it). `KeyInjector.resolveInsert` composes these two with the /// window-identity decision, which stays beside the actor's state. public enum InsertionSeparator { + // periphery:ignore - public for the iOS keyboard (App/BlurtiOS), which the Mac scan doesn't index. /// Joins `text` to whatever precedes the caret with exactly one separating space, /// so consecutive dictations don't run together. Prepends a *leading* space only /// when there's preceding text (`priorText`) that doesn't already end in From 7d0857883e1e1a2ad9930f436f718f89f01a06b3 Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Thu, 24 Sep 2026 15:05:47 -0400 Subject: [PATCH 05/79] docs: on-device testing steps for the iPhone app; tidy a doc comment Co-Authored-By: Claude Fable 5.1 --- App/BlurtiOS/README.md | 15 +++++++++++++++ .../BlurtEngine/FocusCapture/FocusContext.swift | 11 +++++------ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/App/BlurtiOS/README.md b/App/BlurtiOS/README.md index fd97ab53..a012a1fc 100644 --- a/App/BlurtiOS/README.md +++ b/App/BlurtiOS/README.md @@ -34,6 +34,21 @@ on a phone needs Xcode with a team that can provision the App Group; every id in `project.yml` (`dev.alex.blurt.ios`, `group.dev.alex.blurt`) is a placeholder inherited from the Mac app and must become org-owned before the App Store. +## Testing on a phone + +1. Install Xcode 27 (targeting iOS 27 requires it), then `sudo xcode-select -s /Applications/Xcode.app` + and `scripts/bootstrap.sh` from the repo root for xcodegen and the linters. +2. `cd App/BlurtiOS && xcodegen generate && open BlurtiOS.xcodeproj`. Select your team on both + targets; automatic signing registers the App Group if the account may create identifiers + (otherwise add `group.dev.alex.blurt` in the developer portal first). +3. Run the `BlurtiOS` scheme on the phone. In the app: **Use an API key instead** (debug builds + only), **Allow** the microphone, then **Open Settings → Keyboards**: turn on Blurt and + **Allow Full Access**. +4. Back in the app, **Start listening**, then go to Messages, hold the globe key, pick Blurt, + and tap the mic. Tap again to stop, or hold it while you talk. The words land in the field. +5. Try the other two layouts from the app's Keyboard picker; the keyboard reads the choice the + next time it comes up. + ## What is still a stub - **Sign in with AssemblyAI.** The shipping app signs the user in and gets a key diff --git a/Sources/BlurtEngine/FocusCapture/FocusContext.swift b/Sources/BlurtEngine/FocusCapture/FocusContext.swift index 56006f09..eee50ad5 100644 --- a/Sources/BlurtEngine/FocusCapture/FocusContext.swift +++ b/Sources/BlurtEngine/FocusCapture/FocusContext.swift @@ -2,12 +2,11 @@ /// paste target, and the context's app name. /// /// A pid (an `Int32`, which is what `pid_t` is) and a display name rather than -/// an `NSRunningApplication`, so the value -/// crosses the engine's public seams (`InjectorProtocol.setTarget`, -/// `DictationSession.HostFocusCapture`) on every platform the engine builds -/// for. `KeyInjector` resolves the process handle from the pid on macOS; a host -/// on iOS has no process to name — a keyboard cannot see which app hosts it — -/// and passes nil. +/// an `NSRunningApplication`, so the value crosses the engine's public seams +/// (`InjectorProtocol.setTarget`, `DictationSession.HostFocusCapture`) on every +/// platform the engine builds for. `KeyInjector` resolves the process handle +/// from the pid on macOS; a host on iOS has no process to name — a keyboard +/// cannot see which app hosts it — and passes nil. public struct CapturedFocus: Sendable { public let pid: Int32 public let processName: String? From 58698bb3a7f7d33e861d3592cabd98229a60d9a8 Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Thu, 24 Sep 2026 15:17:21 -0400 Subject: [PATCH 06/79] iOS: opt the shared payloads out of main-actor isolation; lexicon read on main MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The keyboard and the app default every declaration to the main actor, but the App Group payloads and the constants that name them cross into the capture path and the engine's closures, which run anywhere — so they are nonisolated. The lexicon completion reads UIKit's entries where UIKit hands them over, on the main thread. The converter's one-buffer handoff uses a Mutex rather than a captured var, in case the input block is typed as Sendable. Co-Authored-By: Claude Fable 5.1 --- .../BlurtKeyboard/Sources/KeyboardModel.swift | 4 +++- .../BlurtiOS/Sources/AudioSource.swift | 17 +++++++------ .../BlurtiOS/Sources/KeyEntryView.swift | 6 ++--- App/BlurtiOS/Shared/SharedState.swift | 24 +++++++++++-------- 4 files changed, 30 insertions(+), 21 deletions(-) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift index 65bea6f6..a3b05578 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift @@ -99,7 +99,9 @@ final class KeyboardModel { /// the app to spell names right with no setup. Read here because only the /// keyboard is offered it; the app reads it back out of the App Group. private func requestLexicon() { - controller?.requestSupplementaryLexicon { @Sendable lexicon in + // UIKit hands the lexicon back on the main thread, which is where its + // entries may be read; the closure stays main-actor for that reason. + controller?.requestSupplementaryLexicon { lexicon in let entries = lexicon.entries.map { LexiconEntry(userInput: $0.userInput, documentText: $0.documentText) } diff --git a/App/BlurtiOS/BlurtiOS/Sources/AudioSource.swift b/App/BlurtiOS/BlurtiOS/Sources/AudioSource.swift index 5fb7122d..305ce680 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/AudioSource.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/AudioSource.swift @@ -189,16 +189,19 @@ nonisolated final class PCMConverter { guard let outputBuffer = AVAudioPCMBuffer(pcmFormat: outputFormat, frameCapacity: capacity) else { return nil } - var handedOver = false + // One buffer per call: the first pull gets it, every later pull is told + // there is no more for now. A `Mutex` rather than a captured `var`, since + // the converter's input block may be typed as `@Sendable`. + let handedOver = Mutex(false) var conversionError: NSError? let status = converter.convert(to: outputBuffer, error: &conversionError) { _, inputStatus in - if handedOver { - inputStatus.pointee = .noDataNow - return nil + let first = handedOver.withLock { done -> Bool in + if done { return false } + done = true + return true } - handedOver = true - inputStatus.pointee = .haveData - return input + inputStatus.pointee = first ? .haveData : .noDataNow + return first ? input : nil } guard status != .error, conversionError == nil, outputBuffer.frameLength > 0, let channels = outputBuffer.int16ChannelData diff --git a/App/BlurtiOS/BlurtiOS/Sources/KeyEntryView.swift b/App/BlurtiOS/BlurtiOS/Sources/KeyEntryView.swift index 19b561bb..9866c71e 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/KeyEntryView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/KeyEntryView.swift @@ -42,9 +42,9 @@ struct KeyEntryView: View { defer { isSubmitting = false } let outcome = await apiKey.submit(key) switch outcome.failureReport { - case nil: dismiss() - case .inline(let message): inlineError = message - case .alert(let title, let message): inlineError = "\(title) \(message)" + case .none: dismiss() + case .some(.inline(let message)): inlineError = message + case .some(.alert(let title, let message)): inlineError = "\(title) \(message)" } } } diff --git a/App/BlurtiOS/Shared/SharedState.swift b/App/BlurtiOS/Shared/SharedState.swift index a78faf79..d842d413 100644 --- a/App/BlurtiOS/Shared/SharedState.swift +++ b/App/BlurtiOS/Shared/SharedState.swift @@ -9,7 +9,7 @@ import SwiftUI /// through the App Group's shared defaults and wake each other with Darwin /// notifications — a system-wide "something changed" ping that carries no data, /// so every payload lives in the defaults under one of the keys below. -enum BlurtShared { +nonisolated enum BlurtShared { /// The App Group both targets declare. A placeholder namespace inherited from /// the Mac app; an org-owned id replaces it before the App Store, and the app /// and the keyboard must change together. @@ -19,7 +19,7 @@ enum BlurtShared { static let urlScheme = "blurt" static let startHost = "start" - enum Key { + nonisolated enum Key { static let layout = "keyboardLayout" static let listeningUntil = "listeningUntil" static let windowMinutes = "listeningWindowMinutes" @@ -33,7 +33,7 @@ enum BlurtShared { /// Darwin notification names. Reverse-DNS so they can't collide with another /// app's on the same device. - enum Signal { + nonisolated enum Signal { static let command = "dev.alex.blurt.ios.command" static let phase = "dev.alex.blurt.ios.phase" static let result = "dev.alex.blurt.ios.result" @@ -43,7 +43,7 @@ enum BlurtShared { /// Which keyboard the user chose. All three share the same plumbing underneath; /// they differ only in how much keyboard sits around the mic. -enum KeyboardLayout: String, CaseIterable, Codable, Sendable, Identifiable { +nonisolated enum KeyboardLayout: String, CaseIterable, Codable, Sendable, Identifiable { /// A slim strip: the mic, delete, return and the globe. Typing letters means /// switching back to the system keyboard. case slimBar @@ -84,12 +84,16 @@ enum KeyboardLayout: String, CaseIterable, Codable, Sendable, Identifiable { } // MARK: - Payloads +// +// Every type below is `nonisolated`: both targets default their declarations to +// the main actor (`SWIFT_DEFAULT_ACTOR_ISOLATION`), but these values cross into +// the app's capture path and the engine's closures, which run anywhere. /// What the keyboard asks the app to do, with the context only the keyboard can /// see: the text before the cursor primes the transcript exactly as the Mac's /// Accessibility read does. -struct KeyboardCommand: Codable, Sendable { - enum Kind: String, Codable, Sendable { +nonisolated struct KeyboardCommand: Codable, Sendable { + nonisolated enum Kind: String, Codable, Sendable { case press case release case cancel @@ -105,7 +109,7 @@ struct KeyboardCommand: Codable, Sendable { /// The words the app got back, for the keyboard to insert. The keyboard joins /// them onto the live text before the cursor itself (`InsertionSeparator`), /// since the user may have typed since the press. -struct DictationResult: Codable, Sendable { +nonisolated struct DictationResult: Codable, Sendable { let id: UUID let text: String let deliveredAt: Date @@ -113,8 +117,8 @@ struct DictationResult: Codable, Sendable { /// What the keyboard shows while the app works: the pipeline's phase, flattened /// to what a pill can render, plus the live microphone level. -struct PhaseSnapshot: Codable, Sendable, Equatable { - enum State: String, Codable, Sendable { +nonisolated struct PhaseSnapshot: Codable, Sendable, Equatable { + nonisolated enum State: String, Codable, Sendable { case idle case connecting case recording @@ -135,7 +139,7 @@ struct PhaseSnapshot: Codable, Sendable, Equatable { /// One entry of the phone's own word list (`UILexicon`): contact names and the /// user's text replacements. Names go to the request as key terms so they come /// back spelled right; replacements are the phone's own text shortcuts. -struct LexiconEntry: Codable, Sendable, Hashable { +nonisolated struct LexiconEntry: Codable, Sendable, Hashable { let userInput: String let documentText: String From bd7424cd76c229f3424ffb3913ef93c074858cc9 Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Thu, 24 Sep 2026 15:26:59 -0400 Subject: [PATCH 07/79] iOS: nonisolated delegate conformance, unchecked buffer handoff; add scripts/ios-typecheck.sh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The capture output calls its delegate on the delivery queue, but with the target defaulting to the main actor the extension's conformance was inferred main-actor even on a nonisolated class — spell it nonisolated. The converter's input block is @Sendable and runs synchronously before convert returns, so the buffer crosses into it unchecked. Both were caught by the new script, which typechecks the iPhone targets against the Mac Catalyst frameworks on a Mac with no iOS SDK — the same flags each project.yml target sets. CI's ios-build job stays the authority. Co-Authored-By: Claude Fable 5.1 --- AGENTS.md | 3 +- .../BlurtiOS/Sources/AudioSource.swift | 13 +++-- App/BlurtiOS/README.md | 5 +- scripts/ios-typecheck.sh | 54 +++++++++++++++++++ 4 files changed, 69 insertions(+), 6 deletions(-) create mode 100755 scripts/ios-typecheck.sh diff --git a/AGENTS.md b/AGENTS.md index da88a0dc..7cc6375d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -95,7 +95,8 @@ App/BlurtiOS/ the iPhone app and its keyboard (README.md there is Shared/ SharedState.swift — the App Group contract, compiled into BOTH Tests/BlurtEngineTests/ Swift Testing suites; Stubs/ holds the seam doubles scripts/ check.sh, check-portability.sh, check-invariants.sh, - bootstrap.sh, dev-build.sh, uitest.sh, leaks.sh, release*.sh + bootstrap.sh, dev-build.sh, uitest.sh, leaks.sh, release*.sh, + ios-typecheck.sh (the iPhone targets without an iOS SDK) hand-run maintainer tools — no automated caller, invoked by a human, so "nothing references it" here does NOT mean dead code: screenshot.swift + beautify.swift (window imagery, capture diff --git a/App/BlurtiOS/BlurtiOS/Sources/AudioSource.swift b/App/BlurtiOS/BlurtiOS/Sources/AudioSource.swift index 305ce680..d81502cc 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/AudioSource.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/AudioSource.swift @@ -141,7 +141,10 @@ nonisolated final class WindowedAudioSource: NSObject, MicCaptureProtocol, @unch } } -extension WindowedAudioSource: AVCaptureAudioDataOutputSampleBufferDelegate { +// The conformance is spelled `nonisolated`: with the target defaulting to the +// main actor, an extension's conformance is inferred main-actor even on a +// `nonisolated` class, and the output calls it on the delivery queue. +extension WindowedAudioSource: nonisolated AVCaptureAudioDataOutputSampleBufferDelegate { func captureOutput( _ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection ) { @@ -190,8 +193,10 @@ nonisolated final class PCMConverter { return nil } // One buffer per call: the first pull gets it, every later pull is told - // there is no more for now. A `Mutex` rather than a captured `var`, since - // the converter's input block may be typed as `@Sendable`. + // there is no more for now. The converter's input block is `@Sendable`, + // but it runs synchronously on this thread before `convert` returns, so + // handing the buffer across unchecked is sound; the flag sits in a `Mutex`. + nonisolated(unsafe) let handoff = input let handedOver = Mutex(false) var conversionError: NSError? let status = converter.convert(to: outputBuffer, error: &conversionError) { _, inputStatus in @@ -201,7 +206,7 @@ nonisolated final class PCMConverter { return true } inputStatus.pointee = first ? .haveData : .noDataNow - return first ? input : nil + return first ? handoff : nil } guard status != .error, conversionError == nil, outputBuffer.frameLength > 0, let channels = outputBuffer.int16ChannelData diff --git a/App/BlurtiOS/README.md b/App/BlurtiOS/README.md index a012a1fc..5cbbb2d4 100644 --- a/App/BlurtiOS/README.md +++ b/App/BlurtiOS/README.md @@ -29,7 +29,10 @@ cd App/BlurtiOS && xcodegen generate # the project is generated, not committ open BlurtiOS.xcodeproj # scheme BlurtiOS builds and embeds the keyboard ``` -CI builds it for the simulator on every PR (`check.yml`'s `ios-build` job). Running +CI builds it for the simulator on every PR (`check.yml`'s `ios-build` job). On a +Mac with only the Command Line Tools — no iOS SDK — `scripts/ios-typecheck.sh` +typechecks both targets against the Mac Catalyst frameworks with the same +flags, which catches the Swift 6 isolation errors before CI does. Running on a phone needs Xcode with a team that can provision the App Group; every id in `project.yml` (`dev.alex.blurt.ios`, `group.dev.alex.blurt`) is a placeholder inherited from the Mac app and must become org-owned before the App Store. diff --git a/scripts/ios-typecheck.sh b/scripts/ios-typecheck.sh new file mode 100755 index 00000000..27c94793 --- /dev/null +++ b/scripts/ios-typecheck.sh @@ -0,0 +1,54 @@ +#!/bin/bash +# Typecheck the iPhone app and its keyboard on a Mac that has no iOS SDK. +# +# The Command Line Tools ship no iOS SDK, but their macOS SDK carries the Mac +# Catalyst frameworks (UIKit, SwiftUI and AVFAudio built for iOS-on-Mac). That +# is the closest stand-in for iOS an Xcode-less Mac has: `os(iOS)` is true, the +# engine builds in its iOS shape, and the Swift 6 isolation errors the iPhone +# targets can hit surface here with the same wording CI's `ios-build` job +# prints. Each target is checked with the flags its project.yml sets — warnings +# are errors, and every declaration defaults to the main actor. +# +# What it cannot see: APIs that differ between Catalyst and iOS proper, code +# signing, linking, and the generated project itself. CI stays the authority; +# this is the fast local loop for the App/BlurtiOS sources. +set -euo pipefail + +REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" +SDK="$(xcrun --show-sdk-path)" +CATALYST="$SDK/System/iOSSupport" +if [ ! -d "$CATALYST/System/Library/Frameworks/UIKit.framework" ]; then + echo "ios-typecheck: no Mac Catalyst frameworks under $SDK" >&2 + exit 1 +fi + +WORK="$(mktemp -d)" +trap 'rm -rf "$WORK"' EXIT + +TARGET=arm64-apple-ios18.0-macabi +COMMON=( + -target "$TARGET" -sdk "$SDK" + -F "$CATALYST/System/Library/Frameworks" -I "$CATALYST/usr/include" + -swift-version 6 -parse-as-library +) + +echo "BlurtEngine → $TARGET" +find "$REPO_ROOT/Sources/BlurtEngine" -name '*.swift' -print0 \ + | xargs -0 xcrun swiftc "${COMMON[@]}" -module-name BlurtEngine \ + -emit-module -emit-module-path "$WORK/BlurtEngine.swiftmodule" + +IOS="$REPO_ROOT/App/BlurtiOS" +TARGET_FLAGS=( + "${COMMON[@]}" -typecheck -I "$WORK" -warnings-as-errors + -Xfrontend -default-isolation -Xfrontend MainActor +) + +echo "BlurtiOS" +xcrun swiftc "${TARGET_FLAGS[@]}" -module-name BlurtiOS \ + "$IOS"/BlurtiOS/Sources/*.swift "$IOS"/Shared/*.swift + +echo "BlurtKeyboard" +xcrun swiftc "${TARGET_FLAGS[@]}" -application-extension -module-name BlurtKeyboard \ + "$IOS"/BlurtKeyboard/Sources/*.swift "$IOS"/Shared/*.swift + +echo "ios-typecheck: ok" From d626c5c68d4a5b0b55617afc079fc7c6d46e2d59 Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Thu, 24 Sep 2026 15:42:42 -0400 Subject: [PATCH 08/79] Keyboard: insert a result once and only while fresh; presence means on screen; periphery config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A Darwin notification is held for a suspended process and delivered when it resumes, so the keyboard inside the app the user left would insert a dictation done elsewhere — every host app runs its own keyboard process. A result is now taken out of the App Group once inserted and ignored after ten seconds. The keyboard clears its presence when it leaves the screen, so a dictation that finishes after that goes to the clipboard; the app checks presence before it writes a result. The phone's word list is re-read at most hourly. Periphery: the iPhone app consumes engine API the Mac-project scan cannot see, so those declarations carry ignore comments, and periphery ≥ 3.5 reports every ignore on a referenced declaration as superfluous. That check is off, with the honest fix (a scan that sees both apps) noted in .periphery.yml. Co-Authored-By: Claude Fable 5.1 --- .periphery.yml | 9 ++++++++ .../BlurtKeyboard/Sources/KeyboardModel.swift | 22 ++++++++++++++++++- .../Sources/KeyboardRelayInjector.swift | 6 ++--- App/BlurtiOS/Shared/SharedState.swift | 11 ++++++++++ 4 files changed, 44 insertions(+), 4 deletions(-) diff --git a/.periphery.yml b/.periphery.yml index 4f9465c9..63f572bd 100644 --- a/.periphery.yml +++ b/.periphery.yml @@ -7,6 +7,15 @@ schemes: # redundant-public and fails --strict. Keep engine internals `internal`; tests # see them through `@testable import`. retain_public: false +# The iPhone app (App/BlurtiOS, its own generated project) consumes engine API +# this scan can't see — FocusedFieldContext, InsertionSeparator, +# DictationSession.HostFocusCapture — so those carry `// periphery:ignore` to +# keep their `public` off the redundant-public list. Periphery ≥ 3.5 reports an +# ignore on any referenced declaration as superfluous, even when it is there to +# suppress that result, so the superfluous-ignore check is off. Turn it back on +# once the scan covers both apps (a workspace with both projects, or a second +# scan of App/BlurtiOS in the ios-build job). +superfluous_ignore_comments: false # DictationLog.Entry's and .ErrorEntry's properties exist solely to be encoded by # JSONEncoder; Periphery can't see Codable's reflective key emission. retain_codable_properties: true diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift index a3b05578..ce03d441 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift @@ -14,6 +14,16 @@ import UIKit @MainActor @Observable final class KeyboardModel { + /// How old a result may be and still be inserted. Darwin notifications are + /// held for a suspended process and delivered when it resumes, so the + /// keyboard inside the app the user *left* hears about a dictation done + /// elsewhere minutes later; anything older than this is not its to insert. + static let resultFreshnessWindow: TimeInterval = 10 + /// The phone's word list is re-read at most this often. Contacts change by + /// the day, and reading thousands of them on every appearance is what the + /// keyboard's memory budget cannot afford. + static let lexiconRefreshInterval: TimeInterval = 60 * 60 + var layout: KeyboardLayout = .panel var snapshot = PhaseSnapshot.idle var isListening = false @@ -71,6 +81,9 @@ final class KeyboardModel { func disappeared() { heartbeat?.cancel() heartbeat = nil + // Presence means on screen. A dictation that finishes after the keyboard + // is gone goes to the clipboard, not to a keyboard nobody can see. + SharedStore.keyboardSeenAt = nil } func contextChanged() {} @@ -99,6 +112,8 @@ final class KeyboardModel { /// the app to spell names right with no setup. Read here because only the /// keyboard is offered it; the app reads it back out of the App Group. private func requestLexicon() { + let refreshed = SharedStore.lexiconRefreshedAt ?? .distantPast + guard Date().timeIntervalSince(refreshed) > Self.lexiconRefreshInterval else { return } // UIKit hands the lexicon back on the main thread, which is where its // entries may be read; the closure stays main-actor for that reason. controller?.requestSupplementaryLexicon { lexicon in @@ -106,6 +121,7 @@ final class KeyboardModel { LexiconEntry(userInput: $0.userInput, documentText: $0.documentText) } SharedStore.write(entries, forKey: BlurtShared.Key.lexicon) + SharedStore.lexiconRefreshedAt = Date() SharedStore.post(BlurtShared.Signal.lexicon) } } @@ -170,9 +186,13 @@ final class KeyboardModel { private func resultArrived() { guard let result = SharedStore.read(DictationResult.self, forKey: BlurtShared.Key.result), - result.id != lastResultID, let proxy + result.id != lastResultID, let proxy, + Date().timeIntervalSince(result.deliveredAt) < Self.resultFreshnessWindow else { return } lastResultID = result.id + // Taken out of the store once inserted, so no other keyboard process — + // each host app runs its own — can insert the same words again. + SharedStore.remove(forKey: BlurtShared.Key.result) // Joined against the live text before the cursor, not the press-time // snapshot: the user may have typed since. proxy.insertText(InsertionSeparator.withLeadingSeparator(result.text, after: proxy.documentContextBeforeInput)) diff --git a/App/BlurtiOS/BlurtiOS/Sources/KeyboardRelayInjector.swift b/App/BlurtiOS/BlurtiOS/Sources/KeyboardRelayInjector.swift index 7fafbf25..4d962fbb 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/KeyboardRelayInjector.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/KeyboardRelayInjector.swift @@ -20,13 +20,13 @@ nonisolated struct KeyboardRelayInjector: InjectorProtocol { func setTarget(_ focus: CapturedFocus?) async {} func insert(_ text: String, after priorText: String?, windowTitle: String?) async throws { - let result = DictationResult(id: UUID(), text: text, deliveredAt: Date()) - SharedStore.write(result, forKey: BlurtShared.Key.result) - SharedStore.post(BlurtShared.Signal.result) let seen = SharedStore.keyboardSeenAt ?? .distantPast guard Date().timeIntervalSince(seen) < Self.keyboardPresenceWindow else { await MainActor.run { UIPasteboard.general.string = text } throw BlurtError.noEditableTarget } + let result = DictationResult(id: UUID(), text: text, deliveredAt: Date()) + SharedStore.write(result, forKey: BlurtShared.Key.result) + SharedStore.post(BlurtShared.Signal.result) } } diff --git a/App/BlurtiOS/Shared/SharedState.swift b/App/BlurtiOS/Shared/SharedState.swift index d842d413..f9a55256 100644 --- a/App/BlurtiOS/Shared/SharedState.swift +++ b/App/BlurtiOS/Shared/SharedState.swift @@ -29,6 +29,7 @@ nonisolated enum BlurtShared { static let keyboardSeenAt = "keyboardSeenAt" static let keyboardEverSeen = "keyboardEverSeen" static let lexicon = "lexicon" + static let lexiconRefreshedAt = "lexiconRefreshedAt" } /// Darwin notification names. Reverse-DNS so they can't collide with another @@ -168,6 +169,10 @@ nonisolated enum SharedStore { return try? JSONDecoder().decode(type, from: data) } + static func remove(forKey key: String) { + defaults.removeObject(forKey: key) + } + static var layout: KeyboardLayout { get { KeyboardLayout(rawValue: defaults.string(forKey: BlurtShared.Key.layout) ?? "") ?? .panel } set { defaults.set(newValue.rawValue, forKey: BlurtShared.Key.layout) } @@ -196,6 +201,12 @@ nonisolated enum SharedStore { set { defaults.set(newValue, forKey: BlurtShared.Key.keyboardSeenAt) } } + /// When the keyboard last copied the phone's word list into the App Group. + static var lexiconRefreshedAt: Date? { + get { defaults.object(forKey: BlurtShared.Key.lexiconRefreshedAt) as? Date } + set { defaults.set(newValue, forKey: BlurtShared.Key.lexiconRefreshedAt) } + } + /// Set by the keyboard the first time it runs with Full Access — the only /// public-API way the app can tell that the keyboard was added and allowed. static var keyboardEverSeen: Bool { From d88bb5872284e67b1fabb261d5f64041b470f202 Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Thu, 24 Sep 2026 15:45:13 -0400 Subject: [PATCH 09/79] iOS: the keyboard trusts only a live app and a fresh phase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Listening now means the window has not lapsed AND the app has checked in within fifteen seconds with the microphone really open — not interrupted by a call, not killed by iOS with the window's end still in the future. Otherwise the mic key opens the app, which reopens the window, instead of sending a press nobody answers. The keyboard drops a phase snapshot that is over (a notice older than three seconds, an in-flight state older than any dictation can be), and the app publishes idle at launch so the last run's state is gone. Co-Authored-By: Claude Fable 5.1 --- .../BlurtKeyboard/Sources/KeyboardModel.swift | 4 +-- .../BlurtiOS/Sources/AudioSource.swift | 4 ++- .../Sources/DictationCoordinator.swift | 2 ++ .../BlurtiOS/Sources/ListeningWindow.swift | 20 +++++++++++ App/BlurtiOS/Shared/SharedState.swift | 36 +++++++++++++++++-- 5 files changed, 61 insertions(+), 5 deletions(-) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift index ce03d441..b1adec94 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift @@ -91,7 +91,7 @@ final class KeyboardModel { private func refresh() { isListening = SharedStore.isListening if let current = SharedStore.read(PhaseSnapshot.self, forKey: BlurtShared.Key.phase) { - apply(current) + apply(current.isStale ? .idle : current) } } @@ -170,7 +170,7 @@ final class KeyboardModel { private func phaseChanged() { guard let current = SharedStore.read(PhaseSnapshot.self, forKey: BlurtShared.Key.phase) else { return } - apply(current) + apply(current.isStale ? .idle : current) } private func apply(_ current: PhaseSnapshot) { diff --git a/App/BlurtiOS/BlurtiOS/Sources/AudioSource.swift b/App/BlurtiOS/BlurtiOS/Sources/AudioSource.swift index d81502cc..b5532015 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/AudioSource.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/AudioSource.swift @@ -64,7 +64,9 @@ nonisolated final class WindowedAudioSource: NSObject, MicCaptureProtocol, @unch output.setSampleBufferDelegate(self, queue: deliveryQueue) } - var isOpen: Bool { session.isRunning } + /// Running and not taken away: iOS keeps a session "running" through an + /// interruption (a phone call, Siri), while no frames arrive. + var isOpen: Bool { session.isRunning && !session.isInterrupted } /// Opens the microphone. Only works from the foreground; the audio session /// must already be active (`ListeningWindow` does both, in that order). diff --git a/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift b/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift index 92febcee..1dab0cc9 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift @@ -59,6 +59,8 @@ final class DictationCoordinator { ] reloadLexicon() tasks = [observePhases(), observeLevels(), observeRecents()] + // Whatever the last run left in the App Group is over. + publish(.idle) } // MARK: - The listening window diff --git a/App/BlurtiOS/BlurtiOS/Sources/ListeningWindow.swift b/App/BlurtiOS/BlurtiOS/Sources/ListeningWindow.swift index c98fb01d..88510034 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/ListeningWindow.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/ListeningWindow.swift @@ -19,6 +19,7 @@ final class ListeningWindow { private(set) var until: Date? private(set) var lastError: String? @ObservationIgnored private var expiry: Task? + @ObservationIgnored private var heartbeat: Task? var isOpen: Bool { source.isOpen && (until.map { $0 > Date() } ?? false) } @@ -36,6 +37,7 @@ final class ListeningWindow { try source.open() lastError = nil extend() + startHeartbeat() } catch { lastError = error.localizedDescription close() @@ -58,12 +60,30 @@ final class ListeningWindow { } } + /// Tells the keyboard the app is alive and the microphone really is open — + /// `SharedStore.isListening` needs both. Stops reporting the moment capture + /// is interrupted (a phone call), so the keyboard's next tap reopens the app + /// instead of sending a press into silence. + private func startHeartbeat() { + heartbeat?.cancel() + heartbeat = Task { [weak self] in + while !Task.isCancelled { + guard let self else { return } + SharedStore.appSeenAt = source.isOpen ? Date() : nil + try? await Task.sleep(for: .seconds(5)) + } + } + } + func close() { expiry?.cancel() expiry = nil + heartbeat?.cancel() + heartbeat = nil source.close() until = nil SharedStore.listeningUntil = nil + SharedStore.appSeenAt = nil try? AVAudioSession.sharedInstance().setActive(false, options: .notifyOthersOnDeactivation) } } diff --git a/App/BlurtiOS/Shared/SharedState.swift b/App/BlurtiOS/Shared/SharedState.swift index f9a55256..dc6a8c39 100644 --- a/App/BlurtiOS/Shared/SharedState.swift +++ b/App/BlurtiOS/Shared/SharedState.swift @@ -27,6 +27,7 @@ nonisolated enum BlurtShared { static let command = "command" static let result = "result" static let keyboardSeenAt = "keyboardSeenAt" + static let appSeenAt = "appSeenAt" static let keyboardEverSeen = "keyboardEverSeen" static let lexicon = "lexicon" static let lexiconRefreshedAt = "lexiconRefreshedAt" @@ -135,6 +136,21 @@ nonisolated struct PhaseSnapshot: Codable, Sendable, Equatable { let at: Date static let idle = PhaseSnapshot(state: .idle, message: nil, level: 0, at: .distantPast) + + /// Whether this is too old to show. A notice (pasted, copied, error) dwells + /// for a moment and is then over; an in-flight state older than the longest + /// possible dictation belongs to an app that was killed under it. The + /// keyboard reads the snapshot back on every appearance and on every signal, + /// including signals held while it was suspended, so it must decide for + /// itself. + var isStale: Bool { + let age = Date().timeIntervalSince(at) + switch state { + case .idle: return false + case .pasted, .copied, .error: return age > 3 + case .connecting, .recording, .processing: return age > 130 + } + } } /// One entry of the phone's own word list (`UILexicon`): contact names and the @@ -193,8 +209,24 @@ nonisolated enum SharedStore { set { defaults.set(newValue, forKey: BlurtShared.Key.listeningUntil) } } - /// Whether the app currently has the microphone open for the keyboard. - static var isListening: Bool { (listeningUntil ?? .distantPast) > Date() } + /// How recently the app must have checked in to count as alive. Its + /// heartbeat is every few seconds while the microphone is open. + static let appPresenceWindow: TimeInterval = 15 + + /// Whether the app currently has the microphone open for the keyboard: the + /// window has not lapsed, and the app is still there to hear — iOS may have + /// killed it, or a phone call taken the microphone, with the window's end + /// still in the future. The keyboard then opens the app rather than sending + /// a press nobody would answer. + static var isListening: Bool { + guard (listeningUntil ?? .distantPast) > Date() else { return false } + return Date().timeIntervalSince(appSeenAt ?? .distantPast) < appPresenceWindow + } + + static var appSeenAt: Date? { + get { defaults.object(forKey: BlurtShared.Key.appSeenAt) as? Date } + set { defaults.set(newValue, forKey: BlurtShared.Key.appSeenAt) } + } static var keyboardSeenAt: Date? { get { defaults.object(forKey: BlurtShared.Key.keyboardSeenAt) as? Date } From e22b580c747a11f097995f84138e906be8c884b4 Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Thu, 24 Sep 2026 16:03:35 -0400 Subject: [PATCH 10/79] Keyboard: the mic key opens the app before Full Access too Without Full Access the key did nothing; now it brings the user to the app, whose checklist says what is missing. Opening the app needs no Full Access. Co-Authored-By: Claude Fable 5.1 --- App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift index b1adec94..06c1c174 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift @@ -129,8 +129,10 @@ final class KeyboardModel { // MARK: - The mic key func micDown() { - guard hasFullAccess else { return } - guard isListening else { + // No Full Access, or the app isn't listening: the mic key's job is to get + // the user to the app, whose checklist says what is missing. Opening the + // app needs no Full Access; everything else here does. + guard hasFullAccess, isListening else { openApp() return } From 884a2d899447563df1c40896b539309bf4284aa4 Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Thu, 24 Sep 2026 16:36:19 -0400 Subject: [PATCH 11/79] iOS: signing team comes from BLURT_TEAM; phone-testing steps spelled out The generated project no longer hard-codes the Mac app's team: XcodeGen expands ${BLURT_TEAM} from the environment, and unset it resolves to no team, which CI (signing off) is fine with. The README walks the first phone run from the App Store download through Developer Mode and the App Group. Co-Authored-By: Claude Fable 5.1 --- App/BlurtiOS/README.md | 31 +++++++++++++++++++++++-------- App/BlurtiOS/project.yml | 6 +++++- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/App/BlurtiOS/README.md b/App/BlurtiOS/README.md index 5cbbb2d4..96736aa6 100644 --- a/App/BlurtiOS/README.md +++ b/App/BlurtiOS/README.md @@ -39,17 +39,32 @@ inherited from the Mac app and must become org-owned before the App Store. ## Testing on a phone -1. Install Xcode 27 (targeting iOS 27 requires it), then `sudo xcode-select -s /Applications/Xcode.app` - and `scripts/bootstrap.sh` from the repo root for xcodegen and the linters. -2. `cd App/BlurtiOS && xcodegen generate && open BlurtiOS.xcodeproj`. Select your team on both - targets; automatic signing registers the App Group if the account may create identifiers - (otherwise add `group.dev.alex.blurt` in the developer portal first). -3. Run the `BlurtiOS` scheme on the phone. In the app: **Use an API key instead** (debug builds +1. Install Xcode 27 from the Mac App Store (targeting iOS 27 requires it), then once: + + ```bash + sudo xcode-select -s /Applications/Xcode.app + sudo xcodebuild -license accept + sudo xcodebuild -runFirstLaunch + xcodebuild -downloadPlatform iOS # only for the simulator; a phone needs no download + ``` + + `scripts/bootstrap.sh` from the repo root installs xcodegen and the linters if `brew` has not. + +2. Sign in to Xcode with your Apple ID (Settings → Accounts) and note your team ID (the ten + characters after the team's name). The App Group needs a paid team — a free Personal Team + cannot register one, so use the org's team, not your own. +3. `cd App/BlurtiOS && BLURT_TEAM= xcodegen generate && open BlurtiOS.xcodeproj`. + Automatic signing registers `dev.alex.blurt.ios`, `dev.alex.blurt.ios.keyboard` and + `group.dev.alex.blurt` under that team on the first build; it fails if another team already + owns them. +4. Plug the phone in (Developer Mode on: Settings → Privacy & Security), pick it as the run + destination, run the `BlurtiOS` scheme. On the phone, trust the developer app (Settings → + General → VPN & Device Management). In the app: **Use an API key instead** (debug builds only), **Allow** the microphone, then **Open Settings → Keyboards**: turn on Blurt and **Allow Full Access**. -4. Back in the app, **Start listening**, then go to Messages, hold the globe key, pick Blurt, +5. Back in the app, **Start listening**, then go to Messages, hold the globe key, pick Blurt, and tap the mic. Tap again to stop, or hold it while you talk. The words land in the field. -5. Try the other two layouts from the app's Keyboard picker; the keyboard reads the choice the +6. Try the other two layouts from the app's Keyboard picker; the keyboard reads the choice the next time it comes up. ## What is still a stub diff --git a/App/BlurtiOS/project.yml b/App/BlurtiOS/project.yml index 330b810e..13d653ca 100644 --- a/App/BlurtiOS/project.yml +++ b/App/BlurtiOS/project.yml @@ -27,7 +27,11 @@ settings: IPHONEOS_DEPLOYMENT_TARGET: "18.0" # iPhone first. iPad needs its own keyboard sizing pass. TARGETED_DEVICE_FAMILY: "1" - DEVELOPMENT_TEAM: B2VQF7Q2QY + # Whoever generates the project signs with their own team: XcodeGen expands + # `${BLURT_TEAM}` from the environment (`BLURT_TEAM=XXXXXXXXXX xcodegen + # generate`). Unset, it stays a reference that resolves to no team, which is + # what CI wants — it builds with signing off. App Groups need a paid team. + DEVELOPMENT_TEAM: ${BLURT_TEAM} CODE_SIGN_STYLE: Automatic packages: # The same local package the Mac app carries, reached from App/BlurtiOS. No From e4a44bf4a9be0ddcd69689ec45e709d6ac1c97c4 Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Thu, 24 Sep 2026 16:59:20 -0400 Subject: [PATCH 12/79] docs: Xcode 26.6 is enough for a phone on iOS 26; 27 only for iOS 27 Co-Authored-By: Claude Fable 5.1 --- App/BlurtiOS/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/App/BlurtiOS/README.md b/App/BlurtiOS/README.md index 96736aa6..79e2f6b7 100644 --- a/App/BlurtiOS/README.md +++ b/App/BlurtiOS/README.md @@ -39,7 +39,8 @@ inherited from the Mac app and must become org-owned before the App Store. ## Testing on a phone -1. Install Xcode 27 from the Mac App Store (targeting iOS 27 requires it), then once: +1. Install Xcode 26.6 or newer — the version CI builds with (`xcodes install 26.6 --select`, or + the Mac App Store). A phone on iOS 27 needs Xcode 27, which needs macOS 26.6. Then once: ```bash sudo xcode-select -s /Applications/Xcode.app From b2be01f65a18bb5cb9326cfb537b525beefddacc Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Thu, 24 Sep 2026 19:12:30 -0400 Subject: [PATCH 13/79] iOS: build under Xcode 27's compiler Two diagnostics Swift 6.4 adds and warnings-as-errors turns fatal: a weak capture inside a closure that itself captures self strongly (the Darwin observers now capture weak at the outer closure), and a Mutex captured by the audio converter's escaping-typed input block (now an unchecked handoff box, sound because the block runs synchronously before convert returns). Verified with a simulator build on Xcode 27.0; CI's Xcode 26.6 accepts both forms. Co-Authored-By: Claude Fable 5.1 --- .../BlurtKeyboard/Sources/KeyboardModel.swift | 8 ++--- .../BlurtiOS/Sources/AudioSource.swift | 34 ++++++++++++------- .../Sources/DictationCoordinator.swift | 8 ++--- 3 files changed, 30 insertions(+), 20 deletions(-) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift index 06c1c174..b6c4dcd1 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift @@ -55,11 +55,11 @@ final class KeyboardModel { func attach(to controller: UIInputViewController) { self.controller = controller observers = [ - DarwinObserver(name: BlurtShared.Signal.phase) { - Task { @MainActor [weak self] in self?.phaseChanged() } + DarwinObserver(name: BlurtShared.Signal.phase) { [weak self] in + Task { @MainActor in self?.phaseChanged() } }, - DarwinObserver(name: BlurtShared.Signal.result) { - Task { @MainActor [weak self] in self?.resultArrived() } + DarwinObserver(name: BlurtShared.Signal.result) { [weak self] in + Task { @MainActor in self?.resultArrived() } }, ] } diff --git a/App/BlurtiOS/BlurtiOS/Sources/AudioSource.swift b/App/BlurtiOS/BlurtiOS/Sources/AudioSource.swift index b5532015..cd4b6b30 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/AudioSource.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/AudioSource.swift @@ -166,6 +166,22 @@ extension WindowedAudioSource: nonisolated AVCaptureAudioDataOutputSampleBufferD /// rebuilds its converter if the input format changes underneath it (a route /// change to AirPods, say). nonisolated final class PCMConverter { + /// One buffer per `convert` call: the first pull gets it, every later pull + /// is told there is no more for now. The converter's input block is + /// `@Sendable` and escaping in type but runs synchronously on this thread + /// before `convert` returns, so an unchecked box is sound — and unlike a + /// `Mutex`, it can be captured. + private final class Handoff: @unchecked Sendable { + private var buffer: AVAudioPCMBuffer? + + init(_ buffer: AVAudioPCMBuffer) { self.buffer = buffer } + + func take() -> AVAudioPCMBuffer? { + defer { buffer = nil } + return buffer + } + } + private let outputFormat: AVAudioFormat private var inputFormat: AVAudioFormat? private var converter: AVAudioConverter? @@ -194,21 +210,15 @@ nonisolated final class PCMConverter { guard let outputBuffer = AVAudioPCMBuffer(pcmFormat: outputFormat, frameCapacity: capacity) else { return nil } - // One buffer per call: the first pull gets it, every later pull is told - // there is no more for now. The converter's input block is `@Sendable`, - // but it runs synchronously on this thread before `convert` returns, so - // handing the buffer across unchecked is sound; the flag sits in a `Mutex`. - nonisolated(unsafe) let handoff = input - let handedOver = Mutex(false) + let handoff = Handoff(input) var conversionError: NSError? let status = converter.convert(to: outputBuffer, error: &conversionError) { _, inputStatus in - let first = handedOver.withLock { done -> Bool in - if done { return false } - done = true - return true + guard let buffer = handoff.take() else { + inputStatus.pointee = .noDataNow + return nil } - inputStatus.pointee = first ? .haveData : .noDataNow - return first ? handoff : nil + inputStatus.pointee = .haveData + return buffer } guard status != .error, conversionError == nil, outputBuffer.frameLength > 0, let channels = outputBuffer.int16ChannelData diff --git a/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift b/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift index 1dab0cc9..649dcb42 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift @@ -50,11 +50,11 @@ final class DictationCoordinator { func start() { observers = [ - DarwinObserver(name: BlurtShared.Signal.command) { - Task { @MainActor [weak self] in self?.handleCommand() } + DarwinObserver(name: BlurtShared.Signal.command) { [weak self] in + Task { @MainActor in self?.handleCommand() } }, - DarwinObserver(name: BlurtShared.Signal.lexicon) { - Task { @MainActor [weak self] in self?.reloadLexicon() } + DarwinObserver(name: BlurtShared.Signal.lexicon) { [weak self] in + Task { @MainActor in self?.reloadLexicon() } }, ] reloadLexicon() From e852a555255120d2d5f1933a6a30187a85d3dc82 Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Thu, 24 Sep 2026 20:02:22 -0400 Subject: [PATCH 14/79] iOS: a simulator microphone, and the keyboard no longer crashes on appear MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AVCaptureSession carries no audio in the simulator (FigCaptureSessionSimulator fails with -12782 on start), so the listening window now takes any ListeningSource: WindowedAudioSource on a phone, SimulatorAudioSource — an Audio Queue asking for 16 kHz mono 16-bit outright — in the simulator. The per-utterance feed both push into is UtteranceFeed. The keyboard died the moment it appeared: UIKit returns the supplementary lexicon on an XPC queue, and a main-actor closure there traps. The callback is now Sendable, hands the immutable lexicon over, and reads it on the main actor. Co-Authored-By: Claude Fable 5.1 --- .../BlurtKeyboard/Sources/KeyboardModel.swift | 30 +++++-- .../BlurtiOS/Sources/AudioSource.swift | 72 +++------------ .../BlurtiOS/Sources/ListeningSource.swift | 90 +++++++++++++++++++ .../BlurtiOS/Sources/ListeningWindow.swift | 7 +- .../Sources/SimulatorAudioSource.swift | 85 ++++++++++++++++++ App/BlurtiOS/README.md | 20 +++++ 6 files changed, 233 insertions(+), 71 deletions(-) create mode 100644 App/BlurtiOS/BlurtiOS/Sources/ListeningSource.swift create mode 100644 App/BlurtiOS/BlurtiOS/Sources/SimulatorAudioSource.swift diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift index b6c4dcd1..207b968b 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift @@ -114,16 +114,28 @@ final class KeyboardModel { private func requestLexicon() { let refreshed = SharedStore.lexiconRefreshedAt ?? .distantPast guard Date().timeIntervalSince(refreshed) > Self.lexiconRefreshInterval else { return } - // UIKit hands the lexicon back on the main thread, which is where its - // entries may be read; the closure stays main-actor for that reason. - controller?.requestSupplementaryLexicon { lexicon in - let entries = lexicon.entries.map { - LexiconEntry(userInput: $0.userInput, documentText: $0.documentText) - } - SharedStore.write(entries, forKey: BlurtShared.Key.lexicon) - SharedStore.lexiconRefreshedAt = Date() - SharedStore.post(BlurtShared.Signal.lexicon) + // UIKit calls back on an XPC queue, not the main thread (a main-actor + // closure here traps), while the lexicon's entries are main-actor in + // Swift's eyes. So: take the callback anywhere, hand the immutable lexicon + // over, and read it on the main actor. + controller?.requestSupplementaryLexicon { @Sendable lexicon in + let handoff = LexiconHandoff(lexicon) + Task { @MainActor in Self.store(handoff.lexicon) } + } + } + + private nonisolated struct LexiconHandoff: @unchecked Sendable { + let lexicon: UILexicon + init(_ lexicon: UILexicon) { self.lexicon = lexicon } + } + + private static func store(_ lexicon: UILexicon) { + let entries = lexicon.entries.map { + LexiconEntry(userInput: $0.userInput, documentText: $0.documentText) } + SharedStore.write(entries, forKey: BlurtShared.Key.lexicon) + SharedStore.lexiconRefreshedAt = Date() + SharedStore.post(BlurtShared.Signal.lexicon) } // MARK: - The mic key diff --git a/App/BlurtiOS/BlurtiOS/Sources/AudioSource.swift b/App/BlurtiOS/BlurtiOS/Sources/AudioSource.swift index cd4b6b30..e10c505d 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/AudioSource.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/AudioSource.swift @@ -2,7 +2,6 @@ import AVFoundation import BlurtEngine import CoreMedia import Foundation -import Synchronization /// The microphone behind an iOS dictation: an audio-only capture session that /// stays open for the whole listening window and hands each utterance its own @@ -23,10 +22,10 @@ import Synchronization /// The output's native format is converted to the 16 kHz mono 16-bit the /// dictation API wants by `PCMConverter` (`audioSettings`, which does that on /// the Mac, is not in the iOS SDK). `@unchecked Sendable` by confinement, the -/// same way the Mac recorder is: the feed and its tally live behind a `Mutex`, +/// same way the Mac recorder is: the feed and its tally live behind `UtteranceFeed`'s lock, /// the converter is touched only on the serial delivery queue, and the session /// is configured once and then only started and stopped. -nonisolated final class WindowedAudioSource: NSObject, MicCaptureProtocol, @unchecked Sendable { +nonisolated final class WindowedAudioSource: NSObject, ListeningSource, @unchecked Sendable { enum Failure: Error, LocalizedError { /// A press arrived with no listening window open — the keyboard's job is to /// open the app first, so this is a plumbing fault, not a user error. @@ -41,25 +40,16 @@ nonisolated final class WindowedAudioSource: NSObject, MicCaptureProtocol, @unch } } - private struct Feed { - var sink: AsyncStream.Continuation? - var bytes = 0 - } - - private let feed = Mutex(Feed()) + private let feed = UtteranceFeed() private let session = AVCaptureSession() private let output = AVCaptureAudioDataOutput() /// Serial, so the converter below needs no lock. private let deliveryQueue = DispatchQueue(label: "dev.alex.blurt.ios.capture") private nonisolated(unsafe) var converter: PCMConverter? - private let levelsContinuation: AsyncStream.Continuation - /// The 0…1 meter the keyboard pill renders, at the output's own cadence. - let levels: AsyncStream + + var levels: AsyncStream { feed.levels } override init() { - let (stream, continuation) = AsyncStream.makeStream(bufferingPolicy: .bufferingNewest(1)) - levels = stream - levelsContinuation = continuation super.init() output.setSampleBufferDelegate(self, queue: deliveryQueue) } @@ -91,7 +81,7 @@ nonisolated final class WindowedAudioSource: NSObject, MicCaptureProtocol, @unch /// Releases the microphone and ends any utterance in flight. func close() { if session.isRunning { session.stopRunning() } - _ = endUtterance() + feed.end() } // MARK: MicCaptureProtocol @@ -100,47 +90,12 @@ nonisolated final class WindowedAudioSource: NSObject, MicCaptureProtocol, @unch guard session.isRunning else { throw BlurtError.audioCaptureFailed(underlying: Failure.windowClosed) } - let (stream, continuation) = AsyncStream.makeStream(bufferingPolicy: .unbounded) - feed.withLock { feed in - feed.sink?.finish() - feed.sink = continuation - feed.bytes = 0 - } - return stream + return feed.begin() } - func stop() -> Int { endUtterance() } - - func cancelCapture() { _ = endUtterance() } - - private func endUtterance() -> Int { - feed.withLock { feed in - let bytes = feed.bytes - feed.sink?.finish() - feed.sink = nil - feed.bytes = 0 - return bytes - } - } + func stop() -> Int { feed.end() } - /// dBFS of a chunk of 16-bit PCM, mapped to 0…1 with the Mac meter's -50 dB - /// floor so room ambient reads as empty bars. - static func level(of pcm: Data) -> Float { - let count = pcm.count / MemoryLayout.size - guard count > 0 else { return 0 } - let energy = pcm.withUnsafeBytes { raw -> Double in - raw.bindMemory(to: Int16.self).reduce(0) { sum, sample in - let value = Double(sample) - return sum + value * value - } - } - let rms = (energy / Double(count)).squareRoot() / Double(Int16.max) - guard rms > 0 else { return 0 } - let floor = -50.0 - let db = 20 * log10(rms) - guard db > floor else { return 0 } - return Float(min(1, (db - floor) / -floor)) - } + func cancelCapture() { feed.end() } } // The conformance is spelled `nonisolated`: with the target defaulting to the @@ -151,13 +106,8 @@ extension WindowedAudioSource: nonisolated AVCaptureAudioDataOutputSampleBufferD _ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection ) { if converter == nil { converter = PCMConverter() } - guard let converter, let chunk = converter.convert(sampleBuffer), !chunk.isEmpty else { return } - levelsContinuation.yield(Self.level(of: chunk)) - feed.withLock { feed in - guard let sink = feed.sink else { return } - feed.bytes += chunk.count - sink.yield(chunk) - } + guard let converter, let chunk = converter.convert(sampleBuffer) else { return } + feed.deliver(chunk) } } diff --git a/App/BlurtiOS/BlurtiOS/Sources/ListeningSource.swift b/App/BlurtiOS/BlurtiOS/Sources/ListeningSource.swift new file mode 100644 index 00000000..e24bc6b2 --- /dev/null +++ b/App/BlurtiOS/BlurtiOS/Sources/ListeningSource.swift @@ -0,0 +1,90 @@ +import BlurtEngine +import Foundation +import Synchronization + +/// What the listening window needs from a microphone: opened once for the +/// window, closed with it, and feeding the engine per utterance in between. +/// `WindowedAudioSource` is the phone's; `SimulatorAudioSource` stands in +/// where the simulator has no capture session. +nonisolated protocol ListeningSource: MicCaptureProtocol { + var isOpen: Bool { get } + /// The 0…1 meter the keyboard pill renders, one value per chunk. + var levels: AsyncStream { get } + func open() throws + func close() +} + +/// The per-utterance feed both microphones push into: the engine gets one +/// stream per press, the meter a level per chunk, and the byte tally is what +/// `stop()` reports so the engine can drop a press too short to transcribe. +nonisolated final class UtteranceFeed: Sendable { + private struct State { + var sink: AsyncStream.Continuation? + var bytes = 0 + } + + private let state = Mutex(State()) + private let levelsContinuation: AsyncStream.Continuation + let levels: AsyncStream + + init() { + let (stream, continuation) = AsyncStream.makeStream(bufferingPolicy: .bufferingNewest(1)) + levels = stream + levelsContinuation = continuation + } + + /// Starts an utterance: chunks delivered from now on go to the returned + /// stream. Any utterance still open is finished first. + func begin() -> AsyncStream { + let (stream, continuation) = AsyncStream.makeStream(bufferingPolicy: .unbounded) + state.withLock { state in + state.sink?.finish() + state.sink = continuation + state.bytes = 0 + } + return stream + } + + /// Ends the utterance and reports how many bytes it carried. + @discardableResult + func end() -> Int { + state.withLock { state in + let bytes = state.bytes + state.sink?.finish() + state.sink = nil + state.bytes = 0 + return bytes + } + } + + /// A chunk of 16 kHz mono 16-bit PCM from the microphone, on whatever + /// thread the microphone delivers on. + func deliver(_ chunk: Data) { + guard !chunk.isEmpty else { return } + levelsContinuation.yield(Self.level(of: chunk)) + state.withLock { state in + guard let sink = state.sink else { return } + state.bytes += chunk.count + sink.yield(chunk) + } + } + + /// dBFS of a chunk of 16-bit PCM, mapped to 0…1 with the Mac meter's -50 dB + /// floor so room ambient reads as empty bars. + static func level(of pcm: Data) -> Float { + let count = pcm.count / MemoryLayout.size + guard count > 0 else { return 0 } + let energy = pcm.withUnsafeBytes { raw -> Double in + raw.bindMemory(to: Int16.self).reduce(0) { sum, sample in + let value = Double(sample) + return sum + value * value + } + } + let rms = (energy / Double(count)).squareRoot() / Double(Int16.max) + guard rms > 0 else { return 0 } + let floor = -50.0 + let db = 20 * log10(rms) + guard db > floor else { return 0 } + return Float(min(1, (db - floor) / -floor)) + } +} diff --git a/App/BlurtiOS/BlurtiOS/Sources/ListeningWindow.swift b/App/BlurtiOS/BlurtiOS/Sources/ListeningWindow.swift index 88510034..001a14b9 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/ListeningWindow.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/ListeningWindow.swift @@ -15,7 +15,12 @@ import Observation @MainActor @Observable final class ListeningWindow { - let source = WindowedAudioSource() + #if targetEnvironment(simulator) + // The simulator's capture session carries no audio; see SimulatorAudioSource. + let source: any ListeningSource = SimulatorAudioSource() + #else + let source: any ListeningSource = WindowedAudioSource() + #endif private(set) var until: Date? private(set) var lastError: String? @ObservationIgnored private var expiry: Task? diff --git a/App/BlurtiOS/BlurtiOS/Sources/SimulatorAudioSource.swift b/App/BlurtiOS/BlurtiOS/Sources/SimulatorAudioSource.swift new file mode 100644 index 00000000..0c7efda5 --- /dev/null +++ b/App/BlurtiOS/BlurtiOS/Sources/SimulatorAudioSource.swift @@ -0,0 +1,85 @@ +#if targetEnvironment(simulator) + import AudioToolbox + import BlurtEngine + import Foundation + + /// The simulator's microphone. `AVCaptureSession` carries no audio there + /// (FigCaptureSessionSimulator fails with -12782 the moment it starts), so + /// this feeds the same stream from an Audio Queue that asks for the dictation + /// format outright — 16 kHz mono 16-bit — and lets Core Audio convert from + /// the Mac's microphone. Never built for a phone; `WindowedAudioSource` is + /// the real thing and this only has to be good enough to exercise the loop. + nonisolated final class SimulatorAudioSource: ListeningSource, @unchecked Sendable { + /// 100 ms per buffer, three in flight. + private static let bufferBytes: UInt32 = 3200 + private static let bufferCount = 3 + + private let feed = UtteranceFeed() + private nonisolated(unsafe) var queue: AudioQueueRef? + private(set) nonisolated(unsafe) var isOpen = false + + var levels: AsyncStream { feed.levels } + + deinit { close() } + + func open() throws { + guard queue == nil else { return } + var format = AudioStreamBasicDescription( + mSampleRate: Double(SyncSTTLimits.sampleRate), mFormatID: kAudioFormatLinearPCM, + mFormatFlags: kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked, + mBytesPerPacket: 2, mFramesPerPacket: 1, mBytesPerFrame: 2, mChannelsPerFrame: 1, mBitsPerChannel: 16, + mReserved: 0) + var created: AudioQueueRef? + let unmanagedSelf = Unmanaged.passUnretained(self).toOpaque() + guard AudioQueueNewInput(&format, Self.deliver, unmanagedSelf, nil, nil, 0, &created) == noErr, + let created + else { throw WindowedAudioSource.Failure.noInputDevice } + for _ in 0.. AsyncStream { + guard isOpen else { + throw BlurtError.audioCaptureFailed(underlying: WindowedAudioSource.Failure.windowClosed) + } + return feed.begin() + } + + func stop() -> Int { feed.end() } + + func cancelCapture() { feed.end() } + + /// Core Audio's callback: a C function pointer, so it captures nothing and + /// finds its way back to the source through the user-data pointer. + private static let deliver: AudioQueueInputCallback = { userData, queue, buffer, _, _, _ in + guard let userData else { return } + let source = Unmanaged.fromOpaque(userData).takeUnretainedValue() + let count = Int(buffer.pointee.mAudioDataByteSize) + if count > 0 { + source.feed.deliver(Data(bytes: buffer.pointee.mAudioData, count: count)) + } + _ = AudioQueueEnqueueBuffer(queue, buffer, 0, nil) + } + } +#endif diff --git a/App/BlurtiOS/README.md b/App/BlurtiOS/README.md index 79e2f6b7..bb0c9298 100644 --- a/App/BlurtiOS/README.md +++ b/App/BlurtiOS/README.md @@ -37,6 +37,26 @@ on a phone needs Xcode with a team that can provision the App Group; every id in `project.yml` (`dev.alex.blurt.ios`, `group.dev.alex.blurt`) is a placeholder inherited from the Mac app and must become org-owned before the App Store. +## Testing in the simulator + +Signing and the team don't matter here, and the App Group works, so the whole +loop runs. `AVCaptureSession` carries no audio in the simulator, so the app uses +`SimulatorAudioSource` (an Audio Queue on the Mac's microphone) there and +`WindowedAudioSource` on a phone. + +```bash +cd App/BlurtiOS && xcodegen generate +xcodebuild -project BlurtiOS.xcodeproj -scheme BlurtiOS -destination 'generic/platform=iOS Simulator' \ + CODE_SIGN_STYLE=Manual CODE_SIGN_IDENTITY=- CODE_SIGNING_REQUIRED=NO DEVELOPMENT_TEAM= build +xcrun simctl boot "iPhone 18 Pro" && xcrun simctl install booted /Build/Products/Debug-iphonesimulator/BlurtiOS.app +xcrun simctl privacy booted grant microphone dev.alex.blurt.ios && xcrun simctl launch booted dev.alex.blurt.ios +``` + +Xcode 27 replaced Simulator.app with Device Hub (`Xcode.app/Contents/Applications/DeviceHub.app`); +turn off its **Always simulate hardware keyboard** setting or no on-screen keyboard appears. +Then: Blurt → Open Settings → Keyboards → Blurt on, Allow Full Access; Start listening; +in Notes, hold the globe key, pick Blurt, tap the mic. + ## Testing on a phone 1. Install Xcode 26.6 or newer — the version CI builds with (`xcodes install 26.6 --select`, or From fb31aef14bac9644708b325f0118c1169c7874c5 Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Thu, 24 Sep 2026 20:05:59 -0400 Subject: [PATCH 15/79] =?UTF-8?q?docs:=20scripts/ios-sim.sh=20=E2=80=94=20?= =?UTF-8?q?the=20simulator=20loop=20in=20one=20command;=20getting=20Xcode?= =?UTF-8?q?=20without=20the=20App=20Store?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5.1 --- AGENTS.md | 3 +- App/BlurtiOS/README.md | 31 ++++++++++++++------ scripts/ios-sim.sh | 66 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 10 deletions(-) create mode 100755 scripts/ios-sim.sh diff --git a/AGENTS.md b/AGENTS.md index 7cc6375d..5be6a596 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -96,7 +96,8 @@ App/BlurtiOS/ the iPhone app and its keyboard (README.md there is Tests/BlurtEngineTests/ Swift Testing suites; Stubs/ holds the seam doubles scripts/ check.sh, check-portability.sh, check-invariants.sh, bootstrap.sh, dev-build.sh, uitest.sh, leaks.sh, release*.sh, - ios-typecheck.sh (the iPhone targets without an iOS SDK) + ios-typecheck.sh (the iPhone targets without an iOS SDK), + ios-sim.sh (build + run the iPhone app in the simulator) hand-run maintainer tools — no automated caller, invoked by a human, so "nothing references it" here does NOT mean dead code: screenshot.swift + beautify.swift (window imagery, capture diff --git a/App/BlurtiOS/README.md b/App/BlurtiOS/README.md index bb0c9298..66340897 100644 --- a/App/BlurtiOS/README.md +++ b/App/BlurtiOS/README.md @@ -37,6 +37,19 @@ on a phone needs Xcode with a team that can provision the App Group; every id in `project.yml` (`dev.alex.blurt.ios`, `group.dev.alex.blurt`) is a placeholder inherited from the Mac app and must become org-owned before the App Store. +## Getting Xcode + +Any Xcode from 26.6 (what CI builds with) works; a phone on iOS 27 needs Xcode 27, which +needs macOS 26.6. The Mac App Store is one way. The other is Apple's developer site through +[`xcodes`](https://github.com/XcodesOrg/xcodes): Homebrew cannot build it without Xcode +already present (chicken and egg), so take the prebuilt binary — +`gh release download --repo XcodesOrg/xcodes --pattern xcodes.zip`, unzip, put `xcodes` on +`PATH` — then `xcodes install 27.0 --select`. It signs in with an Apple ID that has accepted +the Apple Developer Agreement at developer.apple.com/account; a company-managed Apple ID +(Apple Business Manager) cannot accept it and gets a 403, so use a personal one for the +download. The archive lands in `~/Library/Application Support/com.robotsandpencils.xcodes/`; +an 83 KB "xip" there is a saved error page, delete it and retry. + ## Testing in the simulator Signing and the team don't matter here, and the App Group works, so the whole @@ -45,17 +58,17 @@ loop runs. `AVCaptureSession` carries no audio in the simulator, so the app uses `WindowedAudioSource` on a phone. ```bash -cd App/BlurtiOS && xcodegen generate -xcodebuild -project BlurtiOS.xcodeproj -scheme BlurtiOS -destination 'generic/platform=iOS Simulator' \ - CODE_SIGN_STYLE=Manual CODE_SIGN_IDENTITY=- CODE_SIGNING_REQUIRED=NO DEVELOPMENT_TEAM= build -xcrun simctl boot "iPhone 18 Pro" && xcrun simctl install booted /Build/Products/Debug-iphonesimulator/BlurtiOS.app -xcrun simctl privacy booted grant microphone dev.alex.blurt.ios && xcrun simctl launch booted dev.alex.blurt.ios +scripts/ios-sim.sh # generate, build, boot, install, grant mic, launch +scripts/ios-sim.sh --screenshot shot.png # …and capture the screen ``` -Xcode 27 replaced Simulator.app with Device Hub (`Xcode.app/Contents/Applications/DeviceHub.app`); -turn off its **Always simulate hardware keyboard** setting or no on-screen keyboard appears. -Then: Blurt → Open Settings → Keyboards → Blurt on, Allow Full Access; Start listening; -in Notes, hold the globe key, pick Blurt, tap the mic. +Xcode 27 replaced Simulator.app with Device Hub (`Xcode.app/Contents/Applications/DeviceHub.app`), +which the script opens; turn off its **Always simulate hardware keyboard** setting (Device Hub → +Settings…) or no on-screen keyboard ever appears. Then: Blurt → Open Settings → Keyboards → +Blurt on, Allow Full Access; Start listening; in Notes, hold the globe key, pick Blurt, tap the +mic. The keyboard's crash logs, if any, land in `~/Library/Logs/DiagnosticReports/BlurtKeyboard-*`, +and `xcrun simctl spawn booted log show --last 5m --predicate 'process == "BlurtKeyboard"'` +shows its console. ## Testing on a phone diff --git a/scripts/ios-sim.sh b/scripts/ios-sim.sh new file mode 100755 index 00000000..a3f66327 --- /dev/null +++ b/scripts/ios-sim.sh @@ -0,0 +1,66 @@ +#!/bin/bash +# Build the iPhone app and run it in the iOS Simulator: the whole loop in one +# command, for anyone with Xcode and no Apple team. Signing is ad hoc, which the +# simulator accepts, and the App Group works there without provisioning, so the +# app, the keyboard and everything between them run for real; only the phone's +# microphone, background behaviour and haptics need a device. +# +# scripts/ios-sim.sh # build, boot, install, launch +# scripts/ios-sim.sh --screenshot out.png # …then capture the screen +# BLURT_SIM_DEVICE="iPhone 17" scripts/ios-sim.sh +# +# Xcode 27 replaced Simulator.app with Device Hub; either is opened if found. +# In Device Hub, turn off "Always simulate hardware keyboard" or no on-screen +# keyboard ever appears. +set -euo pipefail + +REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" +DEVICE="${BLURT_SIM_DEVICE:-iPhone 18 Pro}" +DERIVED="${BLURT_DERIVED_DATA:-$REPO_ROOT/.build/ios-sim}" +BUNDLE_ID=dev.alex.blurt.ios +SHOT="" +if [ "${1:-}" = "--screenshot" ]; then + SHOT="${2:?usage: ios-sim.sh --screenshot }" +fi + +echo "generate + build" +(cd "$REPO_ROOT/App/BlurtiOS" && xcodegen generate --quiet) +xcodebuild -project "$REPO_ROOT/App/BlurtiOS/BlurtiOS.xcodeproj" -scheme BlurtiOS \ + -destination 'generic/platform=iOS Simulator' -derivedDataPath "$DERIVED" \ + CODE_SIGN_STYLE=Manual CODE_SIGN_IDENTITY=- CODE_SIGNING_REQUIRED=NO DEVELOPMENT_TEAM= \ + -quiet build + +UDID="$(xcrun simctl list devices available -j | python3 -c ' +import json, sys +name = sys.argv[1] +runtimes = json.load(sys.stdin)["devices"] +found = [(rt, d["udid"]) for rt, devs in runtimes.items() if "iOS" in rt for d in devs if d["name"] == name] +found.sort() +print(found[-1][1] if found else "") +' "$DEVICE")" +if [ -z "$UDID" ]; then + echo "ios-sim: no available simulator named '$DEVICE' (xcrun simctl list devices)" >&2 + exit 1 +fi + +echo "boot $DEVICE ($UDID)" +xcrun simctl boot "$UDID" 2>/dev/null || true +DEVELOPER_DIR="$(xcode-select -p)" +for app in "$DEVELOPER_DIR/../Applications/DeviceHub.app" "$DEVELOPER_DIR/Applications/Simulator.app"; do + if [ -d "$app" ]; then + open "$app" + break + fi +done + +echo "install + launch" +APP="$DERIVED/Build/Products/Debug-iphonesimulator/BlurtiOS.app" +xcrun simctl install "$UDID" "$APP" +xcrun simctl privacy "$UDID" grant microphone "$BUNDLE_ID" +xcrun simctl terminate "$UDID" "$BUNDLE_ID" 2>/dev/null || true +xcrun simctl launch "$UDID" "$BUNDLE_ID" + +if [ -n "$SHOT" ]; then + sleep 3 + xcrun simctl io "$UDID" screenshot "$SHOT" +fi From aa64c2b0d63467c94f8f09017b4ae8486ee0329a Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Thu, 24 Sep 2026 20:14:48 -0400 Subject: [PATCH 16/79] Keyboard: the Mac's design on the phone, and a gallery to render it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ink surface, the status pill (36 pt, rim, shadow, inset 12, gap 8), the orb with its sweeping ring, the engine's own meter geometry, tracked-uppercase status words — every number from the Mac's BrandOrb, OverlayView and BlurtBrand. The orb is the mic key (96 / 44 / 42 pt by layout) with a mic glyph, a stop glyph and a level-driven glow while recording. Keys are warm white on raised ink, modifiers a step darker, brightening on press. Heights follow from the rows: 60 / 216 / 252. Debug builds render any layout in any state from a launch argument (-BlurtGallery ), with the keyboard's sources compiled into the app for it, so a screenshot never needs Notes. App/BlurtiOS/DESIGN.md records the tokens, the state table, the layout arithmetic and the procedure. Co-Authored-By: Claude Fable 5.1 --- .../BlurtKeyboard/Sources/BrandOrb.swift | 77 +++++++ .../Sources/FullKeyboardView.swift | 35 ++-- .../BlurtKeyboard/Sources/KeyboardViews.swift | 189 ++++++++---------- .../BlurtKeyboard/Sources/StatusPill.swift | 135 +++++++++++++ .../BlurtiOS/Sources/BlurtiOSApp.swift | 19 +- .../Sources/KeyboardGalleryView.swift | 78 ++++++++ App/BlurtiOS/DESIGN.md | 132 ++++++++++++ App/BlurtiOS/README.md | 6 + App/BlurtiOS/Shared/BlurtBrand.swift | 54 +++++ App/BlurtiOS/Shared/SharedState.swift | 16 +- App/BlurtiOS/project.yml | 6 + scripts/ios-sim.sh | 4 +- 12 files changed, 618 insertions(+), 133 deletions(-) create mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/BrandOrb.swift create mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/StatusPill.swift create mode 100644 App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift create mode 100644 App/BlurtiOS/DESIGN.md create mode 100644 App/BlurtiOS/Shared/BlurtBrand.swift diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/BrandOrb.swift b/App/BlurtiOS/BlurtKeyboard/Sources/BrandOrb.swift new file mode 100644 index 00000000..de98e3b8 --- /dev/null +++ b/App/BlurtiOS/BlurtKeyboard/Sources/BrandOrb.swift @@ -0,0 +1,77 @@ +import BlurtEngine +import SwiftUI + +/// The redraw cap for the keyboard's continuous motion — the ring's sweep, the +/// meter's idle wave. The Mac pill reads the same number from the engine: the +/// level feed moves at this cadence, so drawing faster only burns the +/// keyboard's tight energy and memory budget. +let keyboardAnimationInterval = MicCapture.meterIntervalSeconds + +/// The brand orb, as the Mac pill draws it (`App/Blurt/Blurt/Overlay/BrandOrb.swift`): +/// the gradient disc, and a hairline ring that sweeps round it while something +/// is happening. It spins rather than pulses — a pulse says "alive", a sweep +/// says "working, and still going" — and the disc underneath never moves. +/// +/// Sized by the caller, because the keyboard draws it at two scales: inside +/// the status pill, and as the mic key itself. +struct BrandOrb: View { + var diameter: CGFloat + /// Whether the ring sweeps. Off under Reduce Motion, where the ring is still + /// drawn — it is part of the mark — but holds still. + var animated: Bool + var ringWidth: CGFloat = 1 + + /// One turn every 1.6 s: the Mac's cadence. + static let period: Double = 1.6 + + var body: some View { + Circle() + .fill(BlurtBrand.orbGradient) + .frame(width: diameter, height: diameter) + .overlay { ring } + .accessibilityHidden(true) + } + + @ViewBuilder private var ring: some View { + if animated { + // The angle is a pure function of the clock (engine geometry), so the + // sweep can't drift or restart mid-turn when the state beside it changes. + TimelineView(.animation(minimumInterval: keyboardAnimationInterval)) { timeline in + ringShape.rotationEffect( + .degrees( + MeterBarGeometry.rotationDegrees( + time: timeline.date.timeIntervalSinceReferenceDate, period: Self.period))) + } + } else { + ringShape + } + } + + /// `strokeBorder` so the ring sits inside the disc instead of fringing it. + private var ringShape: some View { + Circle().strokeBorder(BlurtBrand.orbRingGradient, lineWidth: ringWidth) + } +} + +/// The pill's status word — "Transcribing", "Pasted", "Error" — in the Mac's +/// tracked uppercase, scaled from the pill's 9 pt to 11 pt for a phone held at +/// arm's length. Brand green, except the error word's orange. +struct StatusLineText: View { + let text: String + var color: Color = BlurtBrand.greenOnDark + + init(_ text: String, color: Color = BlurtBrand.greenOnDark) { + self.text = text + self.color = color + } + + var body: some View { + Text(text) + .font(.system(size: 11, weight: .semibold)) + .textCase(.uppercase) + .tracking(1.1) + .lineLimit(1) + .minimumScaleFactor(0.7) + .foregroundStyle(color) + } +} diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift b/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift index 216de928..725e0083 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift @@ -3,7 +3,8 @@ import SwiftUI /// A complete keyboard with the mic as the main key. Letters, shift, a symbols /// page, space and return — enough to fix a typo without leaving Blurt; no /// autocorrect or suggestions yet. iOS swaps in its own keyboard for password -/// and phone-number fields, so those never reach here. +/// and phone-number fields, so those never reach here. 252 pt: the pill, three +/// rows of letters and the bottom row, each row `KeyCap.height`. struct FullKeyboardView: View { var model: KeyboardModel @@ -11,23 +12,24 @@ struct FullKeyboardView: View { private static let symbols = ["1234567890", "-/:;()$&@\"", ".,?!'"] var body: some View { - VStack(spacing: 8) { + VStack(spacing: KeyboardRootView.rowGap) { StatusPill(model: model) + .frame(maxWidth: 260) ForEach(Array(rows.enumerated()), id: \.offset) { index, row in HStack(spacing: 5) { if index == 2 { modifierKey } ForEach(Array(row), id: \.self) { character in LetterKey(label: label(for: character)) { model.type(label(for: character)) } } - if index == 2 { KeyCap(systemImage: "delete.left") { model.deleteBackward() } } + if index == 2 { KeyCap(systemImage: "delete.left", dark: true) { model.deleteBackward() } } } } HStack(spacing: 6) { - if model.needsGlobe { KeyCap(systemImage: "globe") { model.globe() } } - KeyCap(title: model.symbolsPage ? "ABC" : "123") { model.toggleSymbols() } + if model.needsGlobe { KeyCap(systemImage: "globe", dark: true) { model.globe() } } + KeyCap(title: model.symbolsPage ? "ABC" : "123", dark: true) { model.toggleSymbols() } KeyCap(title: "space", flexible: true) { model.space() } - MicKey(model: model, size: 44) - KeyCap(systemImage: "return") { model.newline() } + MicKey(model: model, size: KeyCap.height) + KeyCap(systemImage: "return", dark: true) { model.newline() } } } } @@ -41,14 +43,15 @@ struct FullKeyboardView: View { @ViewBuilder private var modifierKey: some View { if model.symbolsPage { - KeyCap(title: "#+=") { model.toggleSymbols() } + KeyCap(title: "#+=", dark: true) { model.toggleSymbols() } } else { - KeyCap(systemImage: model.shifted ? "shift.fill" : "shift") { model.toggleShift() } + KeyCap(systemImage: model.shifted ? "shift.fill" : "shift", dark: true) { model.toggleShift() } } } } -/// A letter key: narrower than `KeyCap` so ten fit across a phone. +/// A letter key: narrower than `KeyCap` so ten fit across a phone, with the +/// system keyboard's 22 pt legend. private struct LetterKey: View { let label: String let action: () -> Void @@ -56,11 +59,13 @@ private struct LetterKey: View { var body: some View { Button(action: action) { Text(label) - .font(.system(size: 21)) - .foregroundStyle(.primary) - .frame(maxWidth: .infinity, minHeight: 40) - .background(Color(uiColor: .secondarySystemGroupedBackground), in: RoundedRectangle(cornerRadius: 6)) + .font(.system(size: 22)) + .foregroundStyle(BlurtBrand.keyText) + .frame(maxWidth: .infinity, minHeight: KeyCap.height) + .background(BlurtBrand.key, in: RoundedRectangle(cornerRadius: KeyCap.cornerRadius)) + .overlay( + RoundedRectangle(cornerRadius: KeyCap.cornerRadius).strokeBorder(Color.white.opacity(0.06), lineWidth: 1)) } - .buttonStyle(.plain) + .buttonStyle(KeyPressStyle()) } } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift index 8a05a33d..7e09b20b 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift @@ -1,10 +1,17 @@ import SwiftUI -/// Picks the layout the user chose. All three share `MicKey`, `StatusPill` and -/// the same model underneath; they differ in how much keyboard surrounds the mic. +/// Picks the layout the user chose. All three share `StatusPill`, `MicKey` and +/// `KeyCap`, and the same model underneath; they differ in how much keyboard +/// surrounds the mic. The surface is the brand ink in every appearance, for the +/// reason the Mac pill is: it floats over whichever app the user is typing in. struct KeyboardRootView: View { var model: KeyboardModel + /// The keyboard's outer margin and the gap between rows: the arithmetic in + /// `KeyboardLayout.height` is built on these. + static let margin: CGFloat = 8 + static let rowGap: CGFloat = 8 + var body: some View { Group { switch model.layout { @@ -13,132 +20,89 @@ struct KeyboardRootView: View { case .full: FullKeyboardView(model: model) } } - .padding(.horizontal, 6) - .padding(.vertical, 6) + .padding(Self.margin) .frame(maxWidth: .infinity, maxHeight: .infinity) - .background(Color(uiColor: .systemGroupedBackground)) + .background(BlurtBrand.ink) } } -/// A slim strip: the mic, delete, return and the globe. +/// One row: the globe, the pill, the mic, delete and return. 60 pt. struct SlimBarView: View { var model: KeyboardModel var body: some View { HStack(spacing: 8) { - if model.needsGlobe { KeyCap(systemImage: "globe") { model.globe() } } - StatusPill(model: model) - MicKey(model: model, size: 48) - KeyCap(systemImage: "delete.left") { model.deleteBackward() } - KeyCap(systemImage: "return") { model.newline() } + if model.needsGlobe { KeyCap(systemImage: "globe", dark: true) { model.globe() } } + StatusPill(model: model, compact: true) + MicKey(model: model, size: 44) + KeyCap(systemImage: "delete.left", dark: true) { model.deleteBackward() } + KeyCap(systemImage: "return", dark: true) { model.newline() } } } } -/// A mic panel: big mic, the status pill, cancel, and a row of keys. +/// The pill, a big mic with cancel beside it while something is in flight, +/// and one row of keys. 216 pt. struct PanelView: View { var model: KeyboardModel var body: some View { - VStack(spacing: 10) { + VStack(spacing: 12) { StatusPill(model: model) - HStack(spacing: 24) { - Spacer() - MicKey(model: model, size: 84) + .frame(maxWidth: 260) + ZStack { + MicKey(model: model, size: 96) if !model.isSettledState { - KeyCap(systemImage: "xmark", tint: BlurtBrand.errorOrange) { model.cancel() } + // Beside the orb, a hand's width off centre, rather than at the edge. + KeyCap(systemImage: "xmark", tint: BlurtBrand.errorOrange, dark: true) { model.cancel() } + .accessibilityLabel("Cancel dictation") + .offset(x: 96) } - Spacer() } + .frame(height: 96) HStack(spacing: 8) { - if model.needsGlobe { KeyCap(systemImage: "globe") { model.globe() } } + if model.needsGlobe { KeyCap(systemImage: "globe", dark: true) { model.globe() } } KeyCap(title: "space", flexible: true) { model.space() } - KeyCap(systemImage: "delete.left") { model.deleteBackward() } - KeyCap(systemImage: "return") { model.newline() } + KeyCap(systemImage: "delete.left", dark: true) { model.deleteBackward() } + KeyCap(systemImage: "return", dark: true) { model.newline() } } } } } -/// The phase line: what the app is doing, with a live meter while it records. -struct StatusPill: View { - var model: KeyboardModel - - var body: some View { - HStack(spacing: 8) { - if model.snapshot.state == .recording { - MeterBars(level: model.snapshot.level) - } - Text(text) - .font(.footnote.weight(.medium)) - .foregroundStyle(tint) - .lineLimit(1) - .minimumScaleFactor(0.7) - } - .frame(maxWidth: .infinity) - .padding(.horizontal, 12) - .padding(.vertical, 8) - .background(BlurtBrand.ink, in: Capsule()) - } - - private var text: String { - guard model.hasFullAccess else { return "Allow Full Access for Blurt in Settings → Keyboards" } - guard model.isListening else { return "Tap the mic to start Blurt" } - switch model.snapshot.state { - case .idle: return "Tap to talk, or hold to talk" - case .connecting: return "Connecting…" - case .recording: return "Listening…" - case .processing: return "Transcribing…" - case .pasted: return "Pasted" - case .copied: return "Copied" - case .error: return model.snapshot.message ?? "Something went wrong" - } - } - - private var tint: Color { - model.snapshot.state == .error ? BlurtBrand.errorOrange : BlurtBrand.greenOnDark - } -} - -/// A handful of bars that follow the microphone level. -struct MeterBars: View { - let level: Double - - var body: some View { - HStack(spacing: 2) { - ForEach(0..<5, id: \.self) { index in - Capsule() - .fill(BlurtBrand.greenOnDark) - .frame(width: 3, height: 4 + 12 * CGFloat(max(0, level - Double(index) * 0.15))) - } - } - .frame(height: 16) - .animation(.easeOut(duration: 0.08), value: level) - } -} - -/// The mic. Finger down starts, finger up decides tap (latched) or hold -/// (push-to-talk) — `KeyboardModel` runs the engine's gate. When the app isn't -/// listening the key reads "Start" and opens the app instead. +/// The mic key is the brand orb. Finger down starts, finger up decides tap +/// (latched) or hold (push-to-talk) — `KeyboardModel` runs the engine's gate. +/// The Mac's orb carries no glyph; here it is a key, so a mic sits on it, and +/// while recording the ring sweeps and the disc glows with the voice level. +/// When the app isn't listening the orb sits dimmed and the tap opens Blurt. struct MicKey: View { var model: KeyboardModel var size: CGFloat @State private var pressed = false + @Environment(\.accessibilityReduceMotion) private var reduceMotion var body: some View { + let level = CGFloat(model.snapshot.level) ZStack { - Circle().fill(fill) - if model.snapshot.state == .recording { - Circle().strokeBorder(BlurtBrand.greenOnDark, lineWidth: 3).scaleEffect(1.12) - } - Image(systemName: model.isListening || !model.hasFullAccess ? "mic.fill" : "play.fill") - .font(.system(size: size * 0.42, weight: .semibold)) + BrandOrb(diameter: size, animated: isWorking && !reduceMotion, ringWidth: isWorking ? 2 : 1) + .saturation(isReady ? 1 : 0.35) + .opacity(isReady ? 1 : 0.8) + Image(systemName: glyph) + .font(.system(size: size * 0.36, weight: .semibold)) .foregroundStyle(.white) + .shadow(color: .black.opacity(0.3), radius: 2, y: 1) } .frame(width: size, height: size) + .shadow( + color: BlurtBrand.greenOnDark.opacity(isRecording ? 0.35 + 0.45 * level : 0), + radius: isRecording ? size * 0.1 + level * size * 0.25 : 0 + ) + .animation(.easeOut(duration: 0.08), value: level) .scaleEffect(pressed ? 0.94 : 1) .animation(.easeOut(duration: 0.1), value: pressed) - .accessibilityLabel(model.isListening ? "Dictate" : "Start Blurt") + .contentShape(Circle()) + .accessibilityLabel(isReady ? (isRecording ? "Stop dictation" : "Dictate") : "Start Blurt") + .accessibilityAddTraits(.isButton) .simultaneousGesture( DragGesture(minimumDistance: 0) .onChanged { _ in @@ -153,32 +117,41 @@ struct MicKey: View { ) } - private var fill: Color { + private var isReady: Bool { model.hasFullAccess && model.isListening } + private var isRecording: Bool { model.snapshot.state == .recording } + private var isWorking: Bool { switch model.snapshot.state { - case .recording: BlurtBrand.errorOrange - case .connecting, .processing: BlurtBrand.ink - case .idle, .pasted, .copied, .error: BlurtBrand.green + case .connecting, .recording, .processing: isReady + case .idle, .pasted, .copied, .error: false } } + + private var glyph: String { isRecording ? "stop.fill" : "mic.fill" } } -/// One ordinary key. `flexible` keys (the space bar) take the width they're -/// given; the rest are square. +/// One ordinary key: a warm-white legend on a raised ink cap; `dark` for the +/// modifier keys, a step darker as on the system keyboard. `flexible` keys (the +/// space bar) take the width they're given; the rest are 44 wide. struct KeyCap: View { var title: String? var systemImage: String? - var tint: Color = .primary + var tint: Color = BlurtBrand.keyText var flexible = false + var dark = false var action: () -> Void + static let height: CGFloat = 42 + static let cornerRadius: CGFloat = 6 + init( - title: String? = nil, systemImage: String? = nil, tint: Color = .primary, flexible: Bool = false, - action: @escaping () -> Void + title: String? = nil, systemImage: String? = nil, tint: Color = BlurtBrand.keyText, flexible: Bool = false, + dark: Bool = false, action: @escaping () -> Void ) { self.title = title self.systemImage = systemImage self.tint = tint self.flexible = flexible + self.dark = dark self.action = action } @@ -191,13 +164,25 @@ struct KeyCap: View { Text(title ?? "") } } - .font(.system(size: 17, weight: .medium)) + .font(.system(size: 16, weight: .medium)) .foregroundStyle(tint) - .frame(maxWidth: flexible ? .infinity : 44, minHeight: 40) - .frame(minWidth: 44) - .background(Color(uiColor: .secondarySystemGroupedBackground), in: RoundedRectangle(cornerRadius: 8)) + .frame(maxWidth: flexible ? .infinity : nil) + .frame(minWidth: 44, minHeight: Self.height) + .padding(.horizontal, flexible ? 0 : 4) + .background(dark ? BlurtBrand.keyDark : BlurtBrand.key, in: RoundedRectangle(cornerRadius: Self.cornerRadius)) + .overlay(RoundedRectangle(cornerRadius: Self.cornerRadius).strokeBorder(Color.white.opacity(0.06), lineWidth: 1)) } - .buttonStyle(.plain) + .buttonStyle(KeyPressStyle()) + } +} + +/// A key lightens while the finger is on it, the way the system's do, instead +/// of the default button dimming. +struct KeyPressStyle: ButtonStyle { + func makeBody(configuration: Configuration) -> some View { + configuration.label + .brightness(configuration.isPressed ? 0.15 : 0) + .animation(.easeOut(duration: 0.08), value: configuration.isPressed) } } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/StatusPill.swift b/App/BlurtiOS/BlurtKeyboard/Sources/StatusPill.swift new file mode 100644 index 00000000..9ea9e0f6 --- /dev/null +++ b/App/BlurtiOS/BlurtKeyboard/Sources/StatusPill.swift @@ -0,0 +1,135 @@ +import BlurtEngine +import SwiftUI + +/// The Mac's overlay pill, on the keyboard: an ink capsule with the orb fixed +/// at its left and, beside it, whatever the moment calls for — the live meter +/// while recording, a status word while waiting, the word alone for a notice. +/// One body for every state, the error included: the alarm is the orange +/// word, never a red capsule. Same inset (12), gap (8), rim and shadow as +/// `App/Blurt/Blurt/Overlay/OverlayView.swift`, at 36 pt instead of 28. +/// +/// Unlike the Mac's, this pill is on screen at rest, so it also has things to +/// say before a dictation: that Full Access is missing, that the app isn't +/// listening, and how to start. +struct StatusPill: View { + var model: KeyboardModel + /// Shorter resting words, for the slim bar's narrow pill. + var compact = false + @Environment(\.accessibilityReduceMotion) private var reduceMotion + + static let height: CGFloat = 36 + /// The Mac's disc-to-pill ratio (24 in 40). + static let orbDiameter: CGFloat = height * 0.6 + private static let inset: CGFloat = 12 + private static let spacing: CGFloat = 8 + + var body: some View { + content + .frame(maxWidth: .infinity) + .frame(height: Self.height) + .background(Capsule().fill(BlurtBrand.ink)) + // The rim is what draws the capsule's edge on a dark surface like the + // keyboard's own; the shadow carries it over light content. + .overlay(Capsule().strokeBorder(Color.white.opacity(0.12), lineWidth: 1)) + .compositingGroup() + .shadow(color: .black.opacity(0.25), radius: 10, y: 3) + .animation(reduceMotion ? nil : .easeInOut(duration: 0.15), value: model.snapshot.state) + .accessibilityElement(children: .ignore) + .accessibilityLabel(accessibilityLabel) + } + + @ViewBuilder private var content: some View { + if !model.hasFullAccess { + word("Allow Full Access", color: BlurtBrand.errorOrange) + } else if !model.isListening { + orbLine(compact ? "Tap to start" : "Tap the mic to start", working: false) + } else { + switch model.snapshot.state { + case .idle: orbLine(compact ? "Tap or hold" : "Tap or hold to talk", working: false) + case .connecting: orbLine("Connecting", working: true) + case .recording: + HStack(spacing: Self.spacing) { + BrandOrb(diameter: Self.orbDiameter, animated: !reduceMotion) + WaveformMeter(level: Float(model.snapshot.level), animated: !reduceMotion, color: BlurtBrand.greenOnDark) + } + .padding(.horizontal, Self.inset) + .transition(.opacity) + case .processing: orbLine("Transcribing", working: true) + case .pasted: word("Pasted") + case .copied: word("Copied") + case .error: word("Error", color: BlurtBrand.errorOrange) + } + } + } + + /// The shape both waits share, and the resting line: orb, then the word. + private func orbLine(_ text: String, working: Bool) -> some View { + HStack(spacing: Self.spacing) { + BrandOrb(diameter: Self.orbDiameter, animated: working && !reduceMotion) + StatusLineText(text) + Spacer(minLength: 0) + } + .padding(.horizontal, Self.inset) + .transition(.opacity) + } + + /// A notice: the word alone, centred. + private func word(_ text: String, color: Color = BlurtBrand.greenOnDark) -> some View { + StatusLineText(text, color: color) + .padding(.horizontal, Self.inset) + .transition(.opacity) + } + + private var accessibilityLabel: String { + guard model.hasFullAccess else { return "Blurt needs Full Access. Allow it in Settings, Keyboards." } + guard model.isListening else { return "Blurt isn't listening. Tap the mic to open Blurt." } + switch model.snapshot.state { + case .idle: return "Tap the mic to talk, or hold it." + case .connecting: return "Connecting to the microphone." + case .recording: return "Recording." + case .processing: return "Transcribing." + case .pasted: return "Your dictation was inserted." + case .copied: return "Your dictation was copied to the clipboard." + case .error: return model.snapshot.message ?? "Dictation failed." + } + } +} + +/// The Mac pill's live meter: a row of bars that fills the width it is given +/// and tracks the current level, with the engine's envelope and idle wave +/// (`MeterBarGeometry`, unit-tested there). The keyboard hears the level from +/// the app at ~12 Hz; the wave keeps the row alive between ticks. +struct WaveformMeter: View { + let level: Float + let animated: Bool + let color: Color + + var body: some View { + GeometryReader { geo in + let layout = MeterBarRow(availableSize: geo.size) + Group { + if animated { + TimelineView(.animation(minimumInterval: keyboardAnimationInterval)) { timeline in + bars(layout: layout, time: timeline.date.timeIntervalSinceReferenceDate) + } + } else { + bars(layout: layout, time: 0) + } + } + .frame(width: geo.size.width, height: geo.size.height) + } + } + + private func bars(layout: MeterBarRow, time: TimeInterval) -> some View { + HStack(spacing: MeterBarGeometry.barSpacing) { + ForEach(0.. [,…] + /// + /// where a state is `off` (no Full Access), `start` (app not listening), + /// `idle`, `connecting`, `recording`, `processing`, `pasted`, `copied` or + /// `error`. `scripts/ios-sim.sh` passes `BLURT_LAUNCH_ARGS` through, so + /// + /// BLURT_LAUNCH_ARGS="-BlurtGallery panel idle,recording,processing" \ + /// scripts/ios-sim.sh --screenshot panel.png + /// + /// is the whole loop. The keyboard's sources are compiled into the app for + /// this (see project.yml); the keyboard itself never runs here. + struct KeyboardGalleryView: View { + struct Row: Identifiable { + let id = UUID() + let layout: KeyboardLayout + let caption: String + let model: KeyboardModel + } + + let rows: [Row] + + var body: some View { + ScrollView { + VStack(alignment: .leading, spacing: 16) { + ForEach(rows) { row in + VStack(alignment: .leading, spacing: 4) { + Text(row.caption).font(.caption.weight(.medium)).foregroundStyle(.secondary).padding(.horizontal) + KeyboardRootView(model: row.model) + .frame(height: row.layout.height) + .clipped() + } + } + } + .padding(.vertical, 12) + } + .background(Color(uiColor: .systemBackground)) + } + + /// The rows named by the launch arguments; empty when they don't ask for + /// the gallery at all. + static func rows(from arguments: [String]) -> [Row] { + guard let flag = arguments.firstIndex(of: "-BlurtGallery"), arguments.count > flag + 2, + let layout = KeyboardLayout(rawValue: arguments[flag + 1]) + else { return [] } + return arguments[flag + 2].split(separator: ",").map { name in + Row(layout: layout, caption: "\(layout.rawValue) · \(name)", model: model(layout: layout, state: String(name))) + } + } + + private static func model(layout: KeyboardLayout, state: String) -> KeyboardModel { + let model = KeyboardModel() + model.layout = layout + model.hasFullAccess = state != "off" + model.isListening = state != "off" && state != "start" + let phase: PhaseSnapshot.State = + switch state { + case "connecting": .connecting + case "recording": .recording + case "processing": .processing + case "pasted": .pasted + case "copied": .copied + case "error": .error + default: .idle + } + model.snapshot = PhaseSnapshot( + state: phase, message: phase == .error ? "The microphone didn't start." : nil, + level: phase == .recording ? 0.62 : 0, at: Date()) + return model + } + } +#endif diff --git a/App/BlurtiOS/DESIGN.md b/App/BlurtiOS/DESIGN.md new file mode 100644 index 00000000..c149215e --- /dev/null +++ b/App/BlurtiOS/DESIGN.md @@ -0,0 +1,132 @@ +# Blurt for iPhone — design + +The iPhone app and its keyboard are the Mac app's design on a phone: the same +ink, the same two greens, the same orb, the same status pill. Nothing here was +invented; every number traces to a Mac source file, and where the phone needed +something the Mac has no equivalent for, this file says what was decided and +why. The keyboard is done; the app's own screens are next (see the end). + +Source of truth on the Mac side: `App/Blurt/Blurt/Branding/BlurtBrand.swift` +(tokens, orb gradient), `App/Blurt/Blurt/Overlay/OverlayView.swift` and +`OverlayPillContent.swift` (the pill), `BrandOrb.swift` (the orb), +`Sources/BlurtEngine/Pipeline/MeterBarGeometry.swift` (the meter, unit-tested). +The phone reads the meter and the ring's rotation straight from the engine, so +they cannot drift from the Mac's. + +## Reproducing it + +Every layout and state renders inside the app, from a launch argument, so a +screenshot never depends on tapping through Notes: + +```bash +BLURT_LAUNCH_ARGS="-BlurtGallery panel idle,recording,processing" scripts/ios-sim.sh --screenshot panel.png +BLURT_LAUNCH_ARGS="-BlurtGallery slimBar off,start,idle,connecting,recording,processing,pasted,copied,error" scripts/ios-sim.sh --screenshot slim.png +BLURT_LAUNCH_ARGS="-BlurtGallery full idle,recording,error" scripts/ios-sim.sh --screenshot full.png +``` + +Layouts: `slimBar`, `panel`, `full`. States: `off` (no Full Access), `start` +(the app isn't listening), then the pipeline's `idle`, `connecting`, +`recording` (level 0.62), `processing`, `pasted`, `copied`, `error`. The +gallery is `BlurtiOS/Sources/KeyboardGalleryView.swift`, debug builds only; +the keyboard's sources are compiled into the app for it (`project.yml`). + +## Tokens (`Shared/BlurtBrand.swift`) + +| Token | Value | Use | +| ----------------- | ----------- | ----------------------------------------------------------- | +| `green` | `#01762F` | the wordmark green, light chrome (the app's accent) | +| `greenOnDark` | `#67AD82` | pill text and meter, the ring, anything green on ink | +| `ink` | `#1D1B16` | the pill's body in every state; the keyboard's surface | +| `errorOrange` | `#E67F36` | the error word — never a red body | +| `key` | `#33302A` | an ordinary key on the ink surface (one step up) | +| `keyDark` | `#26231E` | modifier keys: shift, delete, globe, return, 123, cancel | +| `keyText` | `#F2EEE6` | key legends: warm white on warm ink | +| `orbGradient` | 8 stops | the design's own (`App elements/Recording.svg`), bottom→top | +| `orbRingGradient` | green→white | the ring, top-leading to bottom-trailing | + +The keyboard is a **fixed dark surface** in both appearances, for the reason +the Mac pill is: it floats over whichever app the user is typing in, so it +cannot take a cue from that app, and it must read the same over a white Notes +page and a black Messages thread. Nothing on it uses `accent`. + +## Type + +Status line: 11 pt semibold, uppercase, tracking 1.1 (the Mac's 9 pt / 0.9, +scaled for a phone at arm's length). Key legends: letters 22 pt regular, +everything else 16 pt medium. System font throughout. + +## Components (`BlurtKeyboard/Sources/`) + +**Status pill** (`StatusPill.swift`) — 36 pt capsule (Mac: 28), ink body, 12 % +white 1 pt rim, shadow black 25 % radius 10 offset y 3; inset 12, gap 8; orb +21.6 pt (the Mac's 24-in-40 ratio). Content by state: + +| State | Pill | Mic key | +| ---------------------- | ---------------------------------------------- | ------------------------------- | +| no Full Access (`off`) | `ALLOW FULL ACCESS` in orange, alone | orb dimmed (saturation 0.35) | +| app not listening | orb still · `TAP THE MIC TO START` | orb dimmed; a tap opens Blurt | +| idle | orb still · `TAP OR HOLD TO TALK` | orb, mic glyph | +| connecting | orb sweeping · `CONNECTING` | ring 2 pt sweeping | +| recording | orb sweeping · live meter | ring sweeping, stop glyph, glow | +| processing | orb sweeping · `TRANSCRIBING` | ring sweeping | +| pasted / copied | `PASTED` / `COPIED` alone | orb | +| error | `ERROR` in orange, alone; message on VoiceOver | orb | + +The slim bar uses `TAP TO START` / `TAP OR HOLD` (`compact`), since its pill is +a third of the width. One body for every state; cross-fade 0.15 s. + +**Orb** (`BrandOrb.swift`) — the gradient disc with a hairline ring that sweeps +one turn per 1.6 s while something is happening, still otherwise. The disc +never moves. Under Reduce Motion the ring is drawn but holds still. + +**Meter** (`WaveformMeter` in `StatusPill.swift`) — bars 3 pt wide, 3 pt apart, +count from the width, heights from `MeterBarRow` (envelope, gamma, idle wave). +The app publishes the level at ~12 Hz; the wave keeps the row alive between. + +**Mic key** (`MicKey` in `KeyboardViews.swift`) — the orb _is_ the key: 96 pt +in the panel, 44 in the slim bar, 42 in the full keyboard's bottom row. The +Mac's orb carries no glyph; a key needs one, so a white `mic.fill` (0.36 × size) +sits on it, becoming `stop.fill` while recording. Recording adds a green glow +(`greenOnDark` at 35–80 % with the level, radius 0.1–0.35 × size). Ring 2 pt +while working, 1 pt otherwise. Pressed: scale 0.94, 0.1 s. Finger down / up +drive the engine's `DictationKeyGate`, so a tap latches and a hold is +push-to-talk exactly as on the Mac. + +**Keys** (`KeyCap`, `LetterKey`) — 42 pt tall, radius 6, 6 % white hairline; +`key` for letters and space, `keyDark` for modifiers; a key brightens 15 % +while pressed rather than dimming. + +## Layouts and their heights (`KeyboardLayout.height`) + +Margin 8, row gap 8 (`KeyboardRootView`). + +| Layout | Rows | Height | +| --------- | --------------------------------------------------------------------------- | ------ | +| `slimBar` | globe · pill · mic 44 · delete · return | 60 | +| `panel` | pill 36 · mic 96 (cancel beside it while in flight) · space row 42, gaps 12 | 216 | +| `full` | pill 36 · three letter rows 42 · globe/123/space/mic/return 42 | 252 | + +The pill is capped at 260 pt wide in the panel and full layouts, flexible in +the slim bar. The globe key appears only when iOS says another keyboard is +installed (`needsInputModeSwitchKey`). + +## Feedback + +Haptics (`KeyboardModel.haptics`): medium impact on `recording`, light on the +stop, `.success` on pasted/copied, `.error` on error. The DX7 start/stop cues +play in the app, not the keyboard (a keyboard plays audio only with Full +Access, and the app already owns the audio session). + +## Accessibility + +The pill is one element carrying the state's label (the Mac's wording where +the states match); the mic key is a button labelled Dictate / Stop dictation / +Start Blurt. Reduce Motion stops the ring and the meter's idle wave; heights +still follow the level. + +## Next: the app's screens + +Setup (sign in · microphone · keyboard) as a stepped flow; a home screen with +the orb as the hero, the listening state and window, recent dictations as +cards (`cardFill`/`cardBorder` from the Mac); styles as a chip row; settings +grouped as on the Mac. Same tokens, appearance-adaptive there (`accent`). diff --git a/App/BlurtiOS/README.md b/App/BlurtiOS/README.md index 66340897..f2a1e626 100644 --- a/App/BlurtiOS/README.md +++ b/App/BlurtiOS/README.md @@ -37,6 +37,12 @@ on a phone needs Xcode with a team that can provision the App Group; every id in `project.yml` (`dev.alex.blurt.ios`, `group.dev.alex.blurt`) is a placeholder inherited from the Mac app and must become org-owned before the App Store. +## Design + +`DESIGN.md` — the tokens, the pill, the orb, the meter, the three layouts and their +heights, all traced to the Mac app's sources, plus the gallery that renders every layout and +state for a screenshot. + ## Getting Xcode Any Xcode from 26.6 (what CI builds with) works; a phone on iOS 27 needs Xcode 27, which diff --git a/App/BlurtiOS/Shared/BlurtBrand.swift b/App/BlurtiOS/Shared/BlurtBrand.swift new file mode 100644 index 00000000..faf808ea --- /dev/null +++ b/App/BlurtiOS/Shared/BlurtBrand.swift @@ -0,0 +1,54 @@ +import SwiftUI + +/// Blurt's brand, as the Mac app defines it (`App/Blurt/Blurt/Branding/BlurtBrand.swift`, +/// from the 2026-08-31 comps), plus the handful of shades the keyboard needs +/// for a surface the Mac never draws. Compiled into the app and the keyboard. +/// +/// The keyboard is a fixed dark surface the way the Mac's overlay pill is: it +/// floats over whatever app the user is typing in, so it cannot take its cue +/// from that app's appearance, and it must read the same on a white Notes page +/// and a black Messages thread. Everything on it therefore names the raw +/// shades — `greenOnDark`, `ink` — and never `accent`. +enum BlurtBrand { + /// `#01762F` — the wordmark green, for light chrome. + nonisolated static let green = Color(red: 1 / 255, green: 118 / 255, blue: 47 / 255) + /// `#67AD82` — the brand hue lifted for dark chrome: the pill's text and + /// meter, the ring, the wordmark on the icon. + nonisolated static let greenOnDark = Color(red: 103 / 255, green: 173 / 255, blue: 130 / 255) + /// `#1D1B16` — the brand ink: the pill's body in every state, and the + /// keyboard's surface. + nonisolated static let ink = Color(red: 29 / 255, green: 27 / 255, blue: 22 / 255) + /// `#E67F36` — the error word. The body stays ink; the word carries the alarm. + nonisolated static let errorOrange = Color(red: 230 / 255, green: 127 / 255, blue: 54 / 255) + + // MARK: Keyboard surface — the ink family, one and two steps up + + /// `#33302A` — an ordinary key on the ink surface. + nonisolated static let key = Color(red: 51 / 255, green: 48 / 255, blue: 42 / 255) + /// `#26231E` — a modifier key (shift, delete, globe, return): a step darker + /// than a letter, as the system keyboard does it. The Mac's dark card fill. + nonisolated static let keyDark = Color(red: 38 / 255, green: 35 / 255, blue: 30 / 255) + /// `#F2EEE6` — key legends: a warm white, not a cold one, on the warm ink. + nonisolated static let keyText = Color(red: 242 / 255, green: 238 / 255, blue: 230 / 255) + + /// The orb's fill: the design's own stops (`App elements/Recording.svg`), + /// swept bottom to top. + nonisolated static let orbGradient = LinearGradient( + stops: [ + .init(color: Color(red: 215 / 255, green: 211 / 255, blue: 244 / 255), location: 0), + .init(color: Color(red: 176 / 255, green: 167 / 255, blue: 233 / 255), location: 0.0673), + .init(color: greenOnDark, location: 0.1442), + .init(color: green, location: 0.3029), + .init(color: Color(red: 57 / 255, green: 35 / 255, blue: 199 / 255), location: 0.5962), + .init(color: Color(red: 136 / 255, green: 123 / 255, blue: 221 / 255), location: 0.75), + .init(color: Color(red: 215 / 255, green: 211 / 255, blue: 244 / 255), location: 0.8942), + .init(color: .white, location: 1), + ], + startPoint: .bottom, + endPoint: .top) + + /// The ring round the orb: green into white, corner to corner; spun while + /// something is happening. + nonisolated static let orbRingGradient = LinearGradient( + colors: [green, .white], startPoint: .topLeading, endPoint: .bottomTrailing) +} diff --git a/App/BlurtiOS/Shared/SharedState.swift b/App/BlurtiOS/Shared/SharedState.swift index dc6a8c39..d96b272d 100644 --- a/App/BlurtiOS/Shared/SharedState.swift +++ b/App/BlurtiOS/Shared/SharedState.swift @@ -1,5 +1,4 @@ import Foundation -import SwiftUI // MARK: - The App Group contract @@ -76,11 +75,13 @@ nonisolated enum KeyboardLayout: String, CaseIterable, Codable, Sendable, Identi /// The keyboard's height in points. Fixed per layout; the system keyboard is /// about 216 on a phone, which is what `panel` matches. + /// The keyboard's height on screen, from the layout's own rows: see + /// `App/BlurtiOS/DESIGN.md` for the arithmetic. var height: CGFloat { switch self { - case .slimBar: 72 + case .slimBar: 60 case .panel: 216 - case .full: 264 + case .full: 252 } } } @@ -284,12 +285,3 @@ nonisolated final class DarwinObserver: Sendable { } // MARK: - Brand - -/// The Mac app's palette (`App/Blurt/Blurt/Branding/BlurtBrand.swift`), for the -/// two iOS targets. Values, not assets, so the keyboard needs no catalog. -enum BlurtBrand { - static let green = Color(red: 1 / 255, green: 118 / 255, blue: 47 / 255) - static let greenOnDark = Color(red: 103 / 255, green: 173 / 255, blue: 130 / 255) - static let ink = Color(red: 29 / 255, green: 27 / 255, blue: 22 / 255) - static let errorOrange = Color(red: 230 / 255, green: 127 / 255, blue: 54 / 255) -} diff --git a/App/BlurtiOS/project.yml b/App/BlurtiOS/project.yml index 13d653ca..a6222f2c 100644 --- a/App/BlurtiOS/project.yml +++ b/App/BlurtiOS/project.yml @@ -48,6 +48,12 @@ targets: # extension can't import the app's module) — one source, no duplication, # the same shape as App/Blurt/Shared. - path: Shared + # The keyboard's views and model, so debug builds can render every layout + # and state in-app (KeyboardGalleryView) for design work and screenshots. + # Only the extension's entry point stays out; the keyboard never runs here. + - path: BlurtKeyboard/Sources + excludes: + - KeyboardViewController.swift settings: base: PRODUCT_BUNDLE_IDENTIFIER: dev.alex.blurt.ios diff --git a/scripts/ios-sim.sh b/scripts/ios-sim.sh index a3f66327..4a5c357d 100755 --- a/scripts/ios-sim.sh +++ b/scripts/ios-sim.sh @@ -8,6 +8,7 @@ # scripts/ios-sim.sh # build, boot, install, launch # scripts/ios-sim.sh --screenshot out.png # …then capture the screen # BLURT_SIM_DEVICE="iPhone 17" scripts/ios-sim.sh +# BLURT_LAUNCH_ARGS="-BlurtGallery panel idle,recording" scripts/ios-sim.sh --screenshot panel.png # # Xcode 27 replaced Simulator.app with Device Hub; either is opened if found. # In Device Hub, turn off "Always simulate hardware keyboard" or no on-screen @@ -58,7 +59,8 @@ APP="$DERIVED/Build/Products/Debug-iphonesimulator/BlurtiOS.app" xcrun simctl install "$UDID" "$APP" xcrun simctl privacy "$UDID" grant microphone "$BUNDLE_ID" xcrun simctl terminate "$UDID" "$BUNDLE_ID" 2>/dev/null || true -xcrun simctl launch "$UDID" "$BUNDLE_ID" +read -ra LAUNCH_ARGS <<<"${BLURT_LAUNCH_ARGS:-}" +xcrun simctl launch "$UDID" "$BUNDLE_ID" "${LAUNCH_ARGS[@]}" if [ -n "$SHOT" ]; then sleep 3 From 44d137370f2bcdcadbed940c660a0fe9c863e170 Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Thu, 24 Sep 2026 21:00:01 -0400 Subject: [PATCH 17/79] Keyboard: an iPhone look, hands-free start, auto-capitalisation, the double-space period MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The keys can look exactly like the iPhone's own: a second look beside the layout, following the app being typed in between the system keyboard's light and dark palettes, with its spacing and a 1 pt drop under each key. The full layout now follows the iPhone's geometry in both looks — ten letters at one width, the middle row centred, shift and delete flanking, return two modifiers wide — with letter pop-ups on press, shift that comes on by itself where the field asks, and a quick double space that ends a sentence. Hands-free: with the toggle on, a dictation starts the moment the keyboard appears, as a synthetic tap through the engine's gate, so the next real tap stops it. The design doc records the palettes, the geometry and the rules. Co-Authored-By: Claude Fable 5.1 --- .../Sources/FullKeyboardView.swift | 113 ++++++++++++------ .../BlurtKeyboard/Sources/KeyboardModel.swift | 76 +++++++++++- .../Sources/KeyboardPalette.swift | 57 +++++++++ .../Sources/KeyboardViewController.swift | 4 +- .../BlurtKeyboard/Sources/KeyboardViews.swift | 71 +++++++---- App/BlurtiOS/BlurtiOS/Sources/HomeView.swift | 14 ++- .../Sources/KeyboardGalleryView.swift | 15 ++- App/BlurtiOS/Shared/SharedState.swift | 54 ++++++++- 8 files changed, 332 insertions(+), 72 deletions(-) create mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift b/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift index 725e0083..68f4fea3 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift @@ -1,10 +1,12 @@ import SwiftUI -/// A complete keyboard with the mic as the main key. Letters, shift, a symbols -/// page, space and return — enough to fix a typo without leaving Blurt; no -/// autocorrect or suggestions yet. iOS swaps in its own keyboard for password -/// and phone-number fields, so those never reach here. 252 pt: the pill, three -/// rows of letters and the bottom row, each row `KeyCap.height`. +/// A complete keyboard with the mic as the main key, laid out as the iPhone's +/// own: ten letter keys across at one width, the middle row centred, shift +/// and delete flanking the bottom letters, then 123 · globe · space · mic · +/// return. Every key is 42 pt tall; the look sets the gaps. Letters pop up +/// while pressed, sentences capitalise themselves, a double space ends one. +/// No autocorrect or suggestions yet. iOS swaps in its own keyboard for +/// password and phone-number fields, so those never reach here. struct FullKeyboardView: View { var model: KeyboardModel @@ -12,24 +14,38 @@ struct FullKeyboardView: View { private static let symbols = ["1234567890", "-/:;()$&@\"", ".,?!'"] var body: some View { - VStack(spacing: KeyboardRootView.rowGap) { - StatusPill(model: model) - .frame(maxWidth: 260) - ForEach(Array(rows.enumerated()), id: \.offset) { index, row in - HStack(spacing: 5) { - if index == 2 { modifierKey } - ForEach(Array(row), id: \.self) { character in - LetterKey(label: label(for: character)) { model.type(label(for: character)) } + GeometryReader { geo in + let gap = model.theme.keyGap + // Ten keys and nine gaps across the row. + let keyWidth = (geo.size.width - 9 * gap) / 10 + // Shift and delete take what seven letters leave, standing a little + // further from them than letters stand from each other. + let sideGap = gap * 2 + let sideWidth = (geo.size.width - 7 * keyWidth - 6 * gap - 2 * sideGap) / 2 + VStack(spacing: model.theme.rowGap) { + StatusPill(model: model) + .frame(maxWidth: 260) + ForEach(Array(rows.enumerated()), id: \.offset) { index, row in + HStack(spacing: index == 2 ? sideGap : gap) { + if index == 2 { modifierKey(width: sideWidth) } + HStack(spacing: gap) { + ForEach(Array(row), id: \.self) { character in + LetterKey(label: label(for: character), width: keyWidth) { model.type(label(for: character)) } + } + } + if index == 2 { + KeyCap(systemImage: "delete.left", dark: true, width: sideWidth) { model.deleteBackward() } + } } - if index == 2 { KeyCap(systemImage: "delete.left", dark: true) { model.deleteBackward() } } + .frame(maxWidth: .infinity) + } + HStack(spacing: gap) { + if model.needsGlobe { KeyCap(systemImage: "globe", dark: true, width: sideWidth) { model.globe() } } + KeyCap(title: model.symbolsPage ? "ABC" : "123", dark: true, width: sideWidth) { model.toggleSymbols() } + KeyCap(title: "space", flexible: true) { model.space() } + MicKey(model: model, size: KeyCap.height) + KeyCap(systemImage: "return", dark: true, width: sideWidth * 2 + gap) { model.newline() } } - } - HStack(spacing: 6) { - if model.needsGlobe { KeyCap(systemImage: "globe", dark: true) { model.globe() } } - KeyCap(title: model.symbolsPage ? "ABC" : "123", dark: true) { model.toggleSymbols() } - KeyCap(title: "space", flexible: true) { model.space() } - MicKey(model: model, size: KeyCap.height) - KeyCap(systemImage: "return", dark: true) { model.newline() } } } } @@ -41,31 +57,56 @@ struct FullKeyboardView: View { return model.shifted && !model.symbolsPage ? text.uppercased() : text } - @ViewBuilder private var modifierKey: some View { + @ViewBuilder private func modifierKey(width: CGFloat) -> some View { if model.symbolsPage { - KeyCap(title: "#+=", dark: true) { model.toggleSymbols() } + KeyCap(title: "#+=", dark: true, width: width) { model.toggleSymbols() } } else { - KeyCap(systemImage: model.shifted ? "shift.fill" : "shift", dark: true) { model.toggleShift() } + KeyCap(systemImage: model.shifted ? "shift.fill" : "shift", dark: true, width: width) { model.toggleShift() } } } } -/// A letter key: narrower than `KeyCap` so ten fit across a phone, with the -/// system keyboard's 22 pt legend. +/// A letter key with the system keyboard's 22 pt legend and its pop-up: a +/// larger copy of the letter above the key while the finger is down, so the +/// finger doesn't hide what it's pressing. Typed on release, as iOS does. private struct LetterKey: View { let label: String + let width: CGFloat let action: () -> Void + @State private var pressed = false + @Environment(\.keyboardPalette) private var palette var body: some View { - Button(action: action) { - Text(label) - .font(.system(size: 22)) - .foregroundStyle(BlurtBrand.keyText) - .frame(maxWidth: .infinity, minHeight: KeyCap.height) - .background(BlurtBrand.key, in: RoundedRectangle(cornerRadius: KeyCap.cornerRadius)) - .overlay( - RoundedRectangle(cornerRadius: KeyCap.cornerRadius).strokeBorder(Color.white.opacity(0.06), lineWidth: 1)) - } - .buttonStyle(KeyPressStyle()) + Text(label) + .font(.system(size: 22)) + .foregroundStyle(palette.keyText) + .frame(width: width, height: KeyCap.height) + .keyCap(palette.key, palette: palette) + .overlay(alignment: .top) { + if pressed { popup } + } + .zIndex(pressed ? 1 : 0) + .contentShape(Rectangle()) + .accessibilityLabel(label) + .accessibilityAddTraits(.isButton) + .simultaneousGesture( + DragGesture(minimumDistance: 0) + .onChanged { _ in pressed = true } + .onEnded { _ in + pressed = false + action() + } + ) + } + + private var popup: some View { + Text(label) + .font(.system(size: 32)) + .foregroundStyle(palette.keyText) + .frame(width: width + 18, height: 56) + .background(palette.popupFill, in: RoundedRectangle(cornerRadius: 9)) + .shadow(color: .black.opacity(0.25), radius: 4, y: 2) + .offset(y: -58) + .allowsHitTesting(false) } } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift index 207b968b..bb230c06 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift @@ -25,6 +25,9 @@ final class KeyboardModel { static let lexiconRefreshInterval: TimeInterval = 60 * 60 var layout: KeyboardLayout = .panel + var theme: KeyboardTheme = .blurt + /// Whether the app being typed in wants a dark keyboard, for the iPhone look. + var isDark = false var snapshot = PhaseSnapshot.idle var isListening = false var hasFullAccess = false @@ -38,9 +41,12 @@ final class KeyboardModel { @ObservationIgnored private let clockStart = ContinuousClock.now @ObservationIgnored private var lastResultID: UUID? @ObservationIgnored private var heartbeat: Task? + @ObservationIgnored private var lastSpaceAt: ContinuousClock.Instant? var proxy: (any UITextDocumentProxy)? { controller?.textDocumentProxy } + var palette: KeyboardPalette { .resolve(theme: theme, dark: isDark) } + /// Whether the phase leaves nothing in flight — the moments the gate has to /// be reset, since a dictation can end with no finger event to close it. private var isSettled: Bool { @@ -67,15 +73,39 @@ final class KeyboardModel { func appeared() { hasFullAccess = controller?.hasFullAccess ?? false needsGlobe = controller?.needsInputModeSwitchKey ?? true + readAppearance() + updateShift() // Without Full Access the App Group is out of reach: the keyboard still // types, and says what it needs (see `KeyboardRootView`), but nothing below // can run. guard hasFullAccess else { return } layout = SharedStore.layout + theme = SharedStore.theme SharedStore.keyboardEverSeen = true refresh() startHeartbeat() requestLexicon() + if SharedStore.autoDictate { autoStart() } + } + + /// Hands-free: a dictation begins the moment the keyboard is up, as if the + /// mic had been tapped — the same synthetic tap through the engine's gate, + /// so it latches and the next real tap stops it. Only when the app is + /// listening and nothing is in flight; otherwise the pill says what to do. + private func autoStart() { + guard isListening, isSettled, gate.isIdle else { return } + perform(gate.modifierDown(at: elapsed)) + perform(gate.modifierUp(at: elapsed)) + } + + /// The iPhone look follows the app being typed in: what its text field asks + /// for, or failing that the app's own light or dark appearance. + private func readAppearance() { + switch proxy?.keyboardAppearance { + case .dark: isDark = true + case .light: isDark = false + default: isDark = controller?.traitCollection.userInterfaceStyle == .dark + } } func disappeared() { @@ -86,7 +116,33 @@ final class KeyboardModel { SharedStore.keyboardSeenAt = nil } - func contextChanged() {} + /// The cursor moved or the text around it changed, including by our own + /// typing: re-read what the field wants and where the sentence stands. + func contextChanged() { + readAppearance() + updateShift() + } + + /// Auto-capitalisation, as the system keyboard does it: shift comes on at + /// the start of a sentence (or of every word, or always) according to what + /// the field asks for, and goes off after one letter. + private func updateShift() { + guard let proxy else { return } + let before = proxy.documentContextBeforeInput ?? "" + switch proxy.autocapitalizationType ?? .sentences { + case .none: break + case .allCharacters: shifted = true + case .words: shifted = before.isEmpty || before.last?.isWhitespace == true + case .sentences: shifted = Self.isSentenceStart(before) + @unknown default: break + } + } + + private static func isSentenceStart(_ before: String) -> Bool { + let trimmed = before.reversed().drop { $0 == " " } + guard let last = trimmed.first else { return true } + return last == "\n" || ".?!".contains(last) + } private func refresh() { isListening = SharedStore.isListening @@ -241,7 +297,23 @@ extension KeyboardModel { func newline() { proxy?.insertText("\n") } - func space() { proxy?.insertText(" ") } + /// A space — or, tapped twice quickly after a word, the system keyboard's + /// "." shortcut: the first space becomes a full stop and a space. + func space() { + let now = ContinuousClock.now + let before = proxy?.documentContextBeforeInput ?? "" + if let last = lastSpaceAt, now - last < .milliseconds(450), before.hasSuffix(" "), !before.hasSuffix(" "), + let previous = before.dropLast().last, previous.isLetter || previous.isNumber + { + proxy?.deleteBackward() + proxy?.insertText(". ") + lastSpaceAt = nil + } else { + proxy?.insertText(" ") + lastSpaceAt = now + } + updateShift() + } func toggleShift() { shifted.toggle() } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift new file mode 100644 index 00000000..c0bd00ad --- /dev/null +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift @@ -0,0 +1,57 @@ +import SwiftUI + +/// The colors a layout draws its surface and keys with. Two looks: Blurt's +/// own (the ink surface, `BlurtBrand`) and the iPhone's default keyboard, +/// which follows the app being typed in between its light and dark palettes. +/// The status pill and the orb are Blurt's in both; the look is about the +/// keys. Spacing lives on `KeyboardTheme`, shared with the app for the +/// layout heights. +struct KeyboardPalette: Equatable { + var surface: Color + var key: Color + var keyDark: Color + var keyText: Color + /// The 1 pt drop the system keyboard gives every key; nil for the flat ink look. + var keyShadow: Color? + var keyRadius: CGFloat + var popupFill: Color + + static let blurt = KeyboardPalette( + surface: BlurtBrand.ink, key: BlurtBrand.key, keyDark: BlurtBrand.keyDark, keyText: BlurtBrand.keyText, + keyShadow: nil, keyRadius: 6, popupFill: BlurtBrand.key) + + /// The iPhone's light keyboard: `#D1D5DB` surface, white keys, `#ADB3BC` + /// modifiers, a `#898A8D` drop under each key. + static let systemLight = KeyboardPalette( + surface: Color(red: 209 / 255, green: 213 / 255, blue: 219 / 255), key: .white, + keyDark: Color(red: 173 / 255, green: 179 / 255, blue: 188 / 255), keyText: .black, + keyShadow: Color(red: 137 / 255, green: 138 / 255, blue: 141 / 255), keyRadius: 5, popupFill: .white) + + /// The iPhone's dark keyboard: `#2B2B2B` surface, `#6B6B6B` keys, `#464646` + /// modifiers, a near-black drop. + static let systemDark = KeyboardPalette( + surface: Color(red: 43 / 255, green: 43 / 255, blue: 43 / 255), + key: Color(red: 107 / 255, green: 107 / 255, blue: 107 / 255), + keyDark: Color(red: 70 / 255, green: 70 / 255, blue: 70 / 255), keyText: .white, + keyShadow: Color(red: 13 / 255, green: 13 / 255, blue: 13 / 255), keyRadius: 5, + popupFill: Color(red: 107 / 255, green: 107 / 255, blue: 107 / 255)) + + static func resolve(theme: KeyboardTheme, dark: Bool) -> KeyboardPalette { + switch theme { + case .blurt: .blurt + case .system: dark ? .systemDark : .systemLight + } + } +} + +private struct KeyboardPaletteKey: EnvironmentKey { + static let defaultValue = KeyboardPalette.blurt +} + +extension EnvironmentValues { + /// The palette the keys draw with, set once at the root from the model. + var keyboardPalette: KeyboardPalette { + get { self[KeyboardPaletteKey.self] } + set { self[KeyboardPaletteKey.self] = newValue } + } +} diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift index fd63fdf1..9976c59c 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift @@ -27,7 +27,7 @@ final class KeyboardViewController: UIInputViewController { host.didMove(toParent: self) // The keyboard's height is ours to declare; iOS honours a constraint on the // input view at just under required priority. - let height = view.heightAnchor.constraint(equalToConstant: model.layout.height) + let height = view.heightAnchor.constraint(equalToConstant: model.layout.height(theme: model.theme)) height.priority = UILayoutPriority(999) height.isActive = true heightConstraint = height @@ -36,7 +36,7 @@ final class KeyboardViewController: UIInputViewController { override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) model.appeared() - heightConstraint?.constant = model.layout.height + heightConstraint?.constant = model.layout.height(theme: model.theme) } override func viewWillDisappear(_ animated: Bool) { diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift index 7e09b20b..2b2f7ad5 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift @@ -2,15 +2,16 @@ import SwiftUI /// Picks the layout the user chose. All three share `StatusPill`, `MicKey` and /// `KeyCap`, and the same model underneath; they differ in how much keyboard -/// surrounds the mic. The surface is the brand ink in every appearance, for the -/// reason the Mac pill is: it floats over whichever app the user is typing in. +/// surrounds the mic. The look (`KeyboardTheme`) decides the surface and the +/// keys: Blurt's ink in every appearance — it floats over whichever app the +/// user is typing in, like the Mac pill — or the iPhone's own keyboard, light +/// or dark with that app. struct KeyboardRootView: View { var model: KeyboardModel - /// The keyboard's outer margin and the gap between rows: the arithmetic in - /// `KeyboardLayout.height` is built on these. - static let margin: CGFloat = 8 - static let rowGap: CGFloat = 8 + /// The keyboard's top and bottom margin: the arithmetic in + /// `KeyboardLayout.height` is built on it and the theme's row gap. + static let verticalMargin: CGFloat = 8 var body: some View { Group { @@ -20,9 +21,11 @@ struct KeyboardRootView: View { case .full: FullKeyboardView(model: model) } } - .padding(Self.margin) + .padding(.horizontal, model.theme.margin) + .padding(.vertical, Self.verticalMargin) .frame(maxWidth: .infinity, maxHeight: .infinity) - .background(BlurtBrand.ink) + .background(model.palette.surface) + .environment(\.keyboardPalette, model.palette) } } @@ -129,29 +132,32 @@ struct MicKey: View { private var glyph: String { isRecording ? "stop.fill" : "mic.fill" } } -/// One ordinary key: a warm-white legend on a raised ink cap; `dark` for the -/// modifier keys, a step darker as on the system keyboard. `flexible` keys (the -/// space bar) take the width they're given; the rest are 44 wide. +/// One ordinary key: a legend on a cap in the current palette; `dark` for the +/// modifier keys, a step darker as on the system keyboard. `flexible` keys +/// (the space bar) take the width they're given, `width` fixes one, and the +/// rest are 44 wide. struct KeyCap: View { var title: String? var systemImage: String? - var tint: Color = BlurtBrand.keyText + var tint: Color? var flexible = false var dark = false + var width: CGFloat? var action: () -> Void + @Environment(\.keyboardPalette) private var palette static let height: CGFloat = 42 - static let cornerRadius: CGFloat = 6 init( - title: String? = nil, systemImage: String? = nil, tint: Color = BlurtBrand.keyText, flexible: Bool = false, - dark: Bool = false, action: @escaping () -> Void + title: String? = nil, systemImage: String? = nil, tint: Color? = nil, flexible: Bool = false, + dark: Bool = false, width: CGFloat? = nil, action: @escaping () -> Void ) { self.title = title self.systemImage = systemImage self.tint = tint self.flexible = flexible self.dark = dark + self.width = width self.action = action } @@ -165,23 +171,42 @@ struct KeyCap: View { } } .font(.system(size: 16, weight: .medium)) - .foregroundStyle(tint) + .foregroundStyle(tint ?? palette.keyText) .frame(maxWidth: flexible ? .infinity : nil) - .frame(minWidth: 44, minHeight: Self.height) - .padding(.horizontal, flexible ? 0 : 4) - .background(dark ? BlurtBrand.keyDark : BlurtBrand.key, in: RoundedRectangle(cornerRadius: Self.cornerRadius)) - .overlay(RoundedRectangle(cornerRadius: Self.cornerRadius).strokeBorder(Color.white.opacity(0.06), lineWidth: 1)) + .frame(width: width) + .frame(minWidth: width == nil ? 44 : nil, minHeight: Self.height) + .padding(.horizontal, flexible || width != nil ? 0 : 4) + .keyCap(dark ? palette.keyDark : palette.key, palette: palette) } .buttonStyle(KeyPressStyle()) } } -/// A key lightens while the finger is on it, the way the system's do, instead -/// of the default button dimming. +extension View { + /// The cap under a key's legend: the palette's fill and radius, the system + /// look's 1 pt drop, and the ink look's hairline. + func keyCap(_ fill: Color, palette: KeyboardPalette) -> some View { + background { + RoundedRectangle(cornerRadius: palette.keyRadius) + .fill(fill) + .shadow(color: palette.keyShadow ?? .clear, radius: 0, y: palette.keyShadow == nil ? 0 : 1) + } + .overlay { + if palette.keyShadow == nil { + RoundedRectangle(cornerRadius: palette.keyRadius).strokeBorder(Color.white.opacity(0.06), lineWidth: 1) + } + } + } +} + +/// A modifier key darkens while the finger is on it, the way the system's do, +/// instead of the default button dimming; on the ink look it lightens. struct KeyPressStyle: ButtonStyle { + @Environment(\.keyboardPalette) private var palette + func makeBody(configuration: Configuration) -> some View { configuration.label - .brightness(configuration.isPressed ? 0.15 : 0) + .brightness(configuration.isPressed ? (palette.keyShadow == nil ? 0.15 : -0.12) : 0) .animation(.easeOut(duration: 0.08), value: configuration.isPressed) } } diff --git a/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift b/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift index 542d6d8d..d835c0a3 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift @@ -13,6 +13,8 @@ struct HomeView: View { @State private var microphoneGranted = AVAudioApplication.shared.recordPermission == .granted @State private var keyboardSeen = SharedStore.keyboardEverSeen @State private var layout = SharedStore.layout + @State private var theme = SharedStore.theme + @State private var autoDictate = SharedStore.autoDictate @State private var windowMinutes = SharedStore.windowMinutes @State private var showsKeyEntry = false @AppStorage(KeyTermsStore.defaultsKey) private var keyTerms = "" @@ -143,10 +145,20 @@ struct HomeView: View { .pickerStyle(.segmented) .onChange(of: layout) { _, value in SharedStore.layout = value } Text(layout.summary).font(.footnote).foregroundStyle(.secondary) + Picker("Look", selection: $theme) { + ForEach(KeyboardTheme.allCases) { Text($0.title).tag($0) } + } + .pickerStyle(.segmented) + .onChange(of: theme) { _, value in SharedStore.theme = value } + Text(theme.summary).font(.footnote).foregroundStyle(.secondary) + Toggle("Hands-free", isOn: $autoDictate) + .onChange(of: autoDictate) { _, value in SharedStore.autoDictate = value } + Text("Start dictating the moment the Blurt keyboard comes up in a text field. Tap the mic to stop.") + .font(.footnote).foregroundStyle(.secondary) } header: { Text("Keyboard") } footer: { - Text("Any of the three works the same underneath; pick the one that fits how you type.") + Text("Any layout and look works the same underneath; pick what fits how you type.") } } diff --git a/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift b/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift index b2985d16..a161597c 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift @@ -5,8 +5,10 @@ /// reference, and the way a screenshot of the keyboard is taken without /// tapping through Notes. Debug builds only, reached by launch argument: /// - /// -BlurtGallery [,…] + /// -BlurtGallery [,…] [blurt|light|dark] /// + /// The last word picks the look: Blurt's ink (the default), or the iPhone + /// keyboard in its light or dark palette. /// where a state is `off` (no Full Access), `start` (app not listening), /// `idle`, `connecting`, `recording`, `processing`, `pasted`, `copied` or /// `error`. `scripts/ios-sim.sh` passes `BLURT_LAUNCH_ARGS` through, so @@ -33,7 +35,7 @@ VStack(alignment: .leading, spacing: 4) { Text(row.caption).font(.caption.weight(.medium)).foregroundStyle(.secondary).padding(.horizontal) KeyboardRootView(model: row.model) - .frame(height: row.layout.height) + .frame(height: row.layout.height(theme: row.model.theme)) .clipped() } } @@ -49,14 +51,19 @@ guard let flag = arguments.firstIndex(of: "-BlurtGallery"), arguments.count > flag + 2, let layout = KeyboardLayout(rawValue: arguments[flag + 1]) else { return [] } + let look = arguments.count > flag + 3 ? arguments[flag + 3] : "blurt" return arguments[flag + 2].split(separator: ",").map { name in - Row(layout: layout, caption: "\(layout.rawValue) · \(name)", model: model(layout: layout, state: String(name))) + Row( + layout: layout, caption: "\(layout.rawValue) · \(name) · \(look)", + model: model(layout: layout, state: String(name), look: look)) } } - private static func model(layout: KeyboardLayout, state: String) -> KeyboardModel { + private static func model(layout: KeyboardLayout, state: String, look: String) -> KeyboardModel { let model = KeyboardModel() model.layout = layout + model.theme = look == "blurt" ? .blurt : .system + model.isDark = look == "dark" model.hasFullAccess = state != "off" model.isListening = state != "off" && state != "start" let phase: PhaseSnapshot.State = diff --git a/App/BlurtiOS/Shared/SharedState.swift b/App/BlurtiOS/Shared/SharedState.swift index d96b272d..fee7dfe2 100644 --- a/App/BlurtiOS/Shared/SharedState.swift +++ b/App/BlurtiOS/Shared/SharedState.swift @@ -20,6 +20,8 @@ nonisolated enum BlurtShared { nonisolated enum Key { static let layout = "keyboardLayout" + static let theme = "keyboardTheme" + static let autoDictate = "autoDictate" static let listeningUntil = "listeningUntil" static let windowMinutes = "listeningWindowMinutes" static let phase = "phase" @@ -75,17 +77,49 @@ nonisolated enum KeyboardLayout: String, CaseIterable, Codable, Sendable, Identi /// The keyboard's height in points. Fixed per layout; the system keyboard is /// about 216 on a phone, which is what `panel` matches. - /// The keyboard's height on screen, from the layout's own rows: see - /// `App/BlurtiOS/DESIGN.md` for the arithmetic. - var height: CGFloat { + /// The keyboard's height on screen, from the layout's rows and the look's + /// spacing: see `App/BlurtiOS/DESIGN.md` for the arithmetic. + func height(theme: KeyboardTheme) -> CGFloat { switch self { case .slimBar: 60 case .panel: 216 - case .full: 252 + case .full: 220 + 4 * theme.rowGap } } } +/// How the keys look. The status pill and the orb are Blurt's in both; this is +/// about the surface and the keys around them. +nonisolated enum KeyboardTheme: String, CaseIterable, Codable, Sendable, Identifiable { + /// Blurt's own: the ink surface, warm-white legends. + case blurt + /// The iPhone's default keyboard, light or dark with the app being typed in, + /// for people who want nothing to change but the mic. + case system + + var id: String { rawValue } + + var title: String { + switch self { + case .blurt: "Blurt" + case .system: "iPhone" + } + } + + var summary: String { + switch self { + case .blurt: "Blurt's ink and green." + case .system: "The keyboard you already know, light or dark with the app you're in. Only the mic is new." + } + } + + /// The system keyboard's spacing (6 between keys, 11 between rows, 3 at the + /// edges) versus Blurt's tighter, flatter grid. + var keyGap: CGFloat { self == .system ? 6 : 5 } + var rowGap: CGFloat { self == .system ? 11 : 8 } + var margin: CGFloat { self == .system ? 3 : 8 } +} + // MARK: - Payloads // // Every type below is `nonisolated`: both targets default their declarations to @@ -195,6 +229,18 @@ nonisolated enum SharedStore { set { defaults.set(newValue.rawValue, forKey: BlurtShared.Key.layout) } } + static var theme: KeyboardTheme { + get { KeyboardTheme(rawValue: defaults.string(forKey: BlurtShared.Key.theme) ?? "") ?? .blurt } + set { defaults.set(newValue.rawValue, forKey: BlurtShared.Key.theme) } + } + + /// Hands-free: the keyboard starts a dictation the moment it appears in a + /// text field, so there is nothing to tap before talking. + static var autoDictate: Bool { + get { defaults.bool(forKey: BlurtShared.Key.autoDictate) } + set { defaults.set(newValue, forKey: BlurtShared.Key.autoDictate) } + } + /// How long a listening window stays open with nobody dictating, in minutes. /// 0 means until the user closes it. static var windowMinutes: Int { From 22694921f73b9e634939fe7e79c7885fe01d969b Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Thu, 24 Sep 2026 21:00:41 -0400 Subject: [PATCH 18/79] =?UTF-8?q?docs:=20DESIGN.md=20=E2=80=94=20the=20two?= =?UTF-8?q?=20looks,=20the=20iPhone=20geometry,=20hands-free?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5.1 --- App/BlurtiOS/DESIGN.md | 47 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/App/BlurtiOS/DESIGN.md b/App/BlurtiOS/DESIGN.md index c149215e..0c3f435c 100644 --- a/App/BlurtiOS/DESIGN.md +++ b/App/BlurtiOS/DESIGN.md @@ -30,6 +30,41 @@ Layouts: `slimBar`, `panel`, `full`. States: `off` (no Full Access), `start` gallery is `BlurtiOS/Sources/KeyboardGalleryView.swift`, debug builds only; the keyboard's sources are compiled into the app for it (`project.yml`). +## Two looks (`KeyboardTheme`, `BlurtKeyboard/Sources/KeyboardPalette.swift`) + +People are used to the iPhone's keyboard, so the keys can look exactly like it. +The **look** is a setting beside the layout, in the app's Keyboard section: + +| Look | Surface and keys | +| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `blurt` | The ink surface and tokens below, in every appearance. Gaps 5, rows 8, margin 8. | +| `system` | The iPhone keyboard's own palette, light or dark with the app being typed in (its field's `keyboardAppearance`, else the app's style). Gaps 6, rows 11, margin 3, a 1 pt drop under every key. | + +System light: surface `#D1D5DB`, letter keys white, modifiers `#ADB3BC`, drop +`#898A8D`, black legends. System dark: surface `#2B2B2B`, keys `#6B6B6B`, +modifiers `#464646`, drop `#0D0D0D`, white legends. Radius 5 (Blurt: 6). The +status pill and the orb stay Blurt's in both — the look is about the keys. +The gallery's last argument picks it: `blurt` (default), `light`, `dark`. + +The full layout follows the iPhone's geometry in both looks: ten letter keys +across at one width (`(width − 9·gap) / 10`), the middle row centred, shift +and delete taking what seven letters leave (twice the gap away from them), +then 123 · globe · space · mic · return, return two modifiers wide. Letters +pop up while pressed (a 32 pt copy 58 pt above the key, typed on release); +shift comes on by itself at the start of a sentence — or of every word, or +always — as the field's `autocapitalizationType` asks, and goes off after +one letter; a second space within 450 ms of the first, after a word, becomes +". ". Not yet: autocorrect and the suggestion bar. + +## Hands-free + +A toggle in the same section: with it on, a dictation starts the moment the +keyboard comes up in a text field — the same synthetic tap through the +engine's gate, so it latches and the next tap of the mic stops it. Only when +the app is listening and nothing is in flight; otherwise the pill says what to +do, and the first tap opens Blurt as usual. It fires on the keyboard's +appearance, not on every field change while it stays up. + ## Tokens (`Shared/BlurtBrand.swift`) | Token | Value | Use | @@ -98,13 +133,13 @@ while pressed rather than dimming. ## Layouts and their heights (`KeyboardLayout.height`) -Margin 8, row gap 8 (`KeyboardRootView`). +Top and bottom margin 8 (`KeyboardRootView`); the look sets the row gap and side margin. -| Layout | Rows | Height | -| --------- | --------------------------------------------------------------------------- | ------ | -| `slimBar` | globe · pill · mic 44 · delete · return | 60 | -| `panel` | pill 36 · mic 96 (cancel beside it while in flight) · space row 42, gaps 12 | 216 | -| `full` | pill 36 · three letter rows 42 · globe/123/space/mic/return 42 | 252 | +| Layout | Rows | Height | +| --------- | -------------------------------------------------------------------------------- | --------------------- | +| `slimBar` | globe · pill · mic 44 · delete · return | 60 | +| `panel` | pill 36 · mic 96 (cancel beside it while in flight) · space row 42, gaps 12 | 216 | +| `full` | pill 36 · three letter rows 42 · globe/123/space/mic/return 42; `220 + 4·rowGap` | 252 Blurt, 264 iPhone | The pill is capped at 260 pt wide in the panel and full layouts, flexible in the slim bar. The globe key appears only when iOS says another keyboard is From 93421f17828349318608ee2a10459dc601f4a8b1 Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Thu, 24 Sep 2026 21:03:59 -0400 Subject: [PATCH 19/79] Keyboard: a notice settles back to idle after its dwell Pasted, copied and error stayed on the pill until the next dictation; the Mac pill fades out after 0.8 s / 1.6 s. The keyboard now returns to its resting line after 1.2 s / 2 s. Co-Authored-By: Claude Fable 5.1 --- .../BlurtKeyboard/Sources/KeyboardModel.swift | 11 +++++++++++ App/BlurtiOS/Shared/SharedState.swift | 11 +++++++++++ 2 files changed, 22 insertions(+) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift index bb230c06..7998aa22 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift @@ -42,6 +42,7 @@ final class KeyboardModel { @ObservationIgnored private var lastResultID: UUID? @ObservationIgnored private var heartbeat: Task? @ObservationIgnored private var lastSpaceAt: ContinuousClock.Instant? + @ObservationIgnored private var noticeDwell: Task? var proxy: (any UITextDocumentProxy)? { controller?.textDocumentProxy } @@ -252,6 +253,16 @@ final class KeyboardModel { // would leave the gate latched and swallow the next tap — the same sync the // Mac shell does on every terminal phase. if isSettled, !gate.isIdle { gate.reset() } + // A notice is over after its dwell: the Mac pill fades out, this one goes + // back to saying how to start. + noticeDwell?.cancel() + if let seconds = current.noticeDwellSeconds { + noticeDwell = Task { [weak self] in + try? await Task.sleep(for: .seconds(seconds)) + guard !Task.isCancelled else { return } + self?.apply(.idle) + } + } } private func resultArrived() { diff --git a/App/BlurtiOS/Shared/SharedState.swift b/App/BlurtiOS/Shared/SharedState.swift index fee7dfe2..93a0ec09 100644 --- a/App/BlurtiOS/Shared/SharedState.swift +++ b/App/BlurtiOS/Shared/SharedState.swift @@ -172,6 +172,17 @@ nonisolated struct PhaseSnapshot: Codable, Sendable, Equatable { static let idle = PhaseSnapshot(state: .idle, message: nil, level: 0, at: .distantPast) + /// How long a notice stays on the pill before it settles back to idle — the + /// Mac's 0.8 s / 1.6 s dwell, a little longer since a phone has no hover to + /// reveal more. Nil for the states that end on their own. + var noticeDwellSeconds: Double? { + switch state { + case .pasted: 1.2 + case .copied, .error: 2.0 + case .idle, .connecting, .recording, .processing: nil + } + } + /// Whether this is too old to show. A notice (pasted, copied, error) dwells /// for a moment and is then over; an in-flight state older than the longest /// possible dictation belongs to an app that was killed under it. The From c217f57bbd7d624b8727d08665210a02b39fef2f Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Thu, 24 Sep 2026 21:46:24 -0400 Subject: [PATCH 20/79] App: the Mac's ready screen on a phone, and Settings behind the gear The wordmark, the orb as the hero with the listening state under it (ring sweeping while the mic is open, glowing with the level while recording), the style chips, the recent dictations as the design's cards, the setup checklist in a card only while something is missing. Settings move to a sheet, grouped as on the Mac. The Mac's accent and card colours come in through the asset catalog, its icon and wordmark are shared from App/Blurt rather than copied. A debug launch flag opens the mic at launch so that state can be captured. Co-Authored-By: Claude Fable 5.1 --- .../AccentColor.colorset/Contents.json | 38 ++ .../CardBorder.colorset/Contents.json | 38 ++ .../CardFill.colorset/Contents.json | 38 ++ .../BlurtiOS/Assets.xcassets/Contents.json | 6 + .../BlurtiOS/Sources/BlurtBrand+App.swift | 43 ++ .../BlurtiOS/Sources/BlurtiOSApp.swift | 9 +- App/BlurtiOS/BlurtiOS/Sources/HomeView.swift | 370 +++++++++++------- .../BlurtiOS/Sources/SettingsView.swift | 116 ++++++ App/BlurtiOS/DESIGN.md | 41 +- App/BlurtiOS/README.md | 6 +- App/BlurtiOS/project.yml | 12 + scripts/ios-sim.sh | 3 +- 12 files changed, 557 insertions(+), 163 deletions(-) create mode 100644 App/BlurtiOS/BlurtiOS/Assets.xcassets/AccentColor.colorset/Contents.json create mode 100644 App/BlurtiOS/BlurtiOS/Assets.xcassets/CardBorder.colorset/Contents.json create mode 100644 App/BlurtiOS/BlurtiOS/Assets.xcassets/CardFill.colorset/Contents.json create mode 100644 App/BlurtiOS/BlurtiOS/Assets.xcassets/Contents.json create mode 100644 App/BlurtiOS/BlurtiOS/Sources/BlurtBrand+App.swift create mode 100644 App/BlurtiOS/BlurtiOS/Sources/SettingsView.swift diff --git a/App/BlurtiOS/BlurtiOS/Assets.xcassets/AccentColor.colorset/Contents.json b/App/BlurtiOS/BlurtiOS/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 00000000..ecf45080 --- /dev/null +++ b/App/BlurtiOS/BlurtiOS/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x2F", + "green" : "0x76", + "red" : "0x01" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x82", + "green" : "0xAD", + "red" : "0x67" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/App/BlurtiOS/BlurtiOS/Assets.xcassets/CardBorder.colorset/Contents.json b/App/BlurtiOS/BlurtiOS/Assets.xcassets/CardBorder.colorset/Contents.json new file mode 100644 index 00000000..0c5b7df4 --- /dev/null +++ b/App/BlurtiOS/BlurtiOS/Assets.xcassets/CardBorder.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xDB", + "green" : "0xDB", + "red" : "0xDE" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x2F", + "green" : "0x36", + "red" : "0x3A" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/App/BlurtiOS/BlurtiOS/Assets.xcassets/CardFill.colorset/Contents.json b/App/BlurtiOS/BlurtiOS/Assets.xcassets/CardFill.colorset/Contents.json new file mode 100644 index 00000000..8c14171d --- /dev/null +++ b/App/BlurtiOS/BlurtiOS/Assets.xcassets/CardFill.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xE8", + "green" : "0xE8", + "red" : "0xEB" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x1E", + "green" : "0x23", + "red" : "0x26" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/App/BlurtiOS/BlurtiOS/Assets.xcassets/Contents.json b/App/BlurtiOS/BlurtiOS/Assets.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/App/BlurtiOS/BlurtiOS/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/App/BlurtiOS/BlurtiOS/Sources/BlurtBrand+App.swift b/App/BlurtiOS/BlurtiOS/Sources/BlurtBrand+App.swift new file mode 100644 index 00000000..43db5d41 --- /dev/null +++ b/App/BlurtiOS/BlurtiOS/Sources/BlurtBrand+App.swift @@ -0,0 +1,43 @@ +import SwiftUI + +/// The app's own additions to the brand: the appearance-adaptive pieces the +/// keyboard never needs, resolved from the asset catalog exactly as on the Mac +/// (`Assets.xcassets`, copied from `App/Blurt/Blurt/Assets.xcassets`). +extension BlurtBrand { + /// `green` in light, `greenOnDark` in dark — the catalog's `AccentColor`, + /// which is also the app-level accent (`project.yml`), so system-drawn + /// chrome and our views agree. + nonisolated static let accent = Color.accentColor + /// The warm card the design draws its containers with: `#EBE8E8` on + /// `#DEDBDB` in light, `#26231E` on `#3A362F` in dark. + nonisolated static let cardFill = Color("CardFill") + nonisolated static let cardBorder = Color("CardBorder") +} + +extension View { + /// The design's card: warm fill, 16 pt corners, a hairline border. + func card() -> some View { + background(BlurtBrand.cardFill, in: RoundedRectangle(cornerRadius: 16)) + .overlay(RoundedRectangle(cornerRadius: 16).strokeBorder(BlurtBrand.cardBorder, lineWidth: 1)) + } +} + +/// The lowercase wordmark from the Mac's ready screen, tinted with the accent +/// (`blurt-ready-logo.png`, shared from `App/Blurt/Blurt/Branding`). +struct Wordmark: View { + var height: CGFloat = 22 + + var body: some View { + if let image = UIImage(named: "blurt-ready-logo") { + Image(uiImage: image) + .renderingMode(.template) + .resizable() + .scaledToFit() + .frame(height: height) + .foregroundStyle(BlurtBrand.accent) + .accessibilityLabel("Blurt") + } else { + Text("blurt").font(.title2.weight(.bold)).foregroundStyle(BlurtBrand.accent) + } + } +} diff --git a/App/BlurtiOS/BlurtiOS/Sources/BlurtiOSApp.swift b/App/BlurtiOS/BlurtiOS/Sources/BlurtiOSApp.swift index a1f53a6c..f7233d9b 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/BlurtiOSApp.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/BlurtiOSApp.swift @@ -43,6 +43,13 @@ struct BlurtiOSApp: App { private var home: some View { HomeView(coordinator: coordinator) .onOpenURL { coordinator.handle($0) } - .task { coordinator.start() } + .task { + coordinator.start() + #if DEBUG + // `-BlurtStartListening` opens the mic at launch, so the listening + // state can be screenshotted without a tap (see scripts/ios-sim.sh). + if CommandLine.arguments.contains("-BlurtStartListening") { await coordinator.startListening() } + #endif + } } } diff --git a/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift b/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift index d835c0a3..73de6f9d 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift @@ -3,43 +3,60 @@ import BlurtEngine import SwiftUI import UIKit -/// The app's one screen: setup while anything is missing, then the listening -/// window, a way to try a dictation right here, the keyboard choice, and the -/// settings the request reads. Plain SwiftUI on purpose — the design pass comes -/// once the loop works on a phone. +/// The app's one screen, in the shape of the Mac's ready screen: the wordmark, +/// the orb as the hero with the listening state under it, the style chips, +/// and the recent dictations as cards. Setup sits on top while anything is +/// missing; everything adjustable lives behind the gear. struct HomeView: View { var coordinator: DictationCoordinator @Environment(\.scenePhase) private var scenePhase + @Environment(\.accessibilityReduceMotion) private var reduceMotion @State private var microphoneGranted = AVAudioApplication.shared.recordPermission == .granted @State private var keyboardSeen = SharedStore.keyboardEverSeen - @State private var layout = SharedStore.layout - @State private var theme = SharedStore.theme - @State private var autoDictate = SharedStore.autoDictate - @State private var windowMinutes = SharedStore.windowMinutes @State private var showsKeyEntry = false - @AppStorage(KeyTermsStore.defaultsKey) private var keyTerms = "" - @AppStorage(EnhancedTranscriptsStore.defaultsKey) private var enhancedTranscripts = - EnhancedTranscriptsStore.defaultValue + @State private var showsSettings = false + @AppStorage(StyleProfileStore.defaultsKey) private var profilesRaw = "" + @AppStorage(StyleProfileStore.activeDefaultsKey) private var activeRaw = "" + private let styles = StyleProfileStore() private var isSetUp: Bool { coordinator.apiKey.hasAPIKey && microphoneGranted && keyboardSeen } + private var profiles: [StyleProfile] { styles.profiles(decoding: profilesRaw) } + private var activeStyle: StyleProfile? { StyleProfileStore.active(in: profiles, id: activeRaw) } var body: some View { NavigationStack { - List { - if !isSetUp { setupSection } - listeningSection - tryItSection - keyboardSection - settingsSection - recentSection - } - .navigationTitle("Blurt") + ScrollView { + VStack(spacing: 20) { + if !isSetUp { setupCard } + hero + styleChips + recent + poweredBy + } + .padding(.horizontal, 20) + .padding(.top, 8) + .padding(.bottom, 24) + } + .background(Color(uiColor: .systemGroupedBackground)) + .navigationBarTitleDisplayMode(.inline) + .toolbar { + ToolbarItem(placement: .principal) { Wordmark() } + ToolbarItem(placement: .topBarTrailing) { + Button { + showsSettings = true + } label: { + Image(systemName: "gearshape") + } + .accessibilityLabel("Settings") + } + } + .sheet(isPresented: $showsKeyEntry) { KeyEntryView(apiKey: coordinator.apiKey) } + .sheet(isPresented: $showsSettings) { SettingsView(coordinator: coordinator) } .onChange(of: scenePhase) { _, phase in if phase == .active { refreshStatus() } } - .sheet(isPresented: $showsKeyEntry) { KeyEntryView(apiKey: coordinator.apiKey) } } - .tint(BlurtBrand.green) + .tint(BlurtBrand.accent) } private func refreshStatus() { @@ -48,10 +65,166 @@ struct HomeView: View { coordinator.apiKey.refreshStatus() } + // MARK: - The orb and the listening state + + private var level: CGFloat { CGFloat(coordinator.level) } + private var isRecording: Bool { coordinator.phase == .recording } + private var orbWorking: Bool { coordinator.window.isOpen || coordinator.phase.isCapturing } + + private var hero: some View { + VStack(spacing: 18) { + BrandOrb(diameter: 112, animated: orbWorking && !reduceMotion, ringWidth: 2) + .shadow( + color: BlurtBrand.greenOnDark.opacity(isRecording ? 0.35 + 0.45 * level : 0), + radius: isRecording ? 14 + 30 * level : 0 + ) + .animation(.easeOut(duration: 0.08), value: level) + .padding(.top, 6) + VStack(spacing: 4) { + Text(heroTitle).font(.title2.weight(.semibold)).multilineTextAlignment(.center) + Text(heroSubtitle).font(.callout).foregroundStyle(.secondary).multilineTextAlignment(.center) + } + if isRecording { + WaveformMeter(level: coordinator.level, animated: !reduceMotion, color: BlurtBrand.accent) + .frame(width: 180, height: 28) + } + if coordinator.window.isOpen { + Button(role: .destructive) { + coordinator.stopListening() + } label: { + Text("Stop listening").frame(maxWidth: .infinity) + } + .buttonStyle(.bordered) + .controlSize(.large) + } else { + Button { + Task { await coordinator.startListening() } + } label: { + Text("Start listening").frame(maxWidth: .infinity) + } + .buttonStyle(.borderedProminent) + .controlSize(.large) + .disabled(!coordinator.apiKey.hasAPIKey) + } + Button(coordinator.phase.isCapturing ? "Stop and transcribe" : "Dictate here, to the clipboard") { + coordinator.toggleDictation() + } + .font(.callout) + .disabled(!coordinator.window.isOpen) + if let error = coordinator.window.lastError { + Text(error).font(.footnote).foregroundStyle(BlurtBrand.errorOrange).multilineTextAlignment(.center) + } + if coordinator.microphoneDenied { + Text("Blurt needs the microphone. Allow it in Settings.") + .font(.footnote).foregroundStyle(BlurtBrand.errorOrange) + } + } + .padding(20) + .frame(maxWidth: .infinity) + .card() + } + + private var heroTitle: String { + switch coordinator.phase.overlayState { + case .connecting: return "Connecting…" + case .recording: return "Listening…" + case .processing: return "Transcribing…" + case .pasted: return "Pasted" + case .noTarget: return "Copied" + case .error(let message): return message + case .idle: return coordinator.window.isOpen ? "Ready to dictate" : "Not listening" + } + } + + private var heroSubtitle: String { + guard coordinator.window.isOpen else { + return "Open the mic so the Blurt keyboard can dictate anywhere you type." + } + if let until = coordinator.window.until, until != .distantFuture { + return "Until \(until.formatted(date: .omitted, time: .shortened)) · tap the mic on the Blurt keyboard." + } + return "Until you stop it · tap the mic on the Blurt keyboard." + } + + // MARK: - Styles + + private var styleChips: some View { + VStack(alignment: .leading, spacing: 10) { + Text("Style").font(.headline) + ScrollView(.horizontal, showsIndicators: false) { + HStack(spacing: 8) { + StyleChip(name: StyleProfileStore.defaultStyleName, selected: activeStyle == nil) { styles.activateDefault() } + ForEach(profiles) { profile in + StyleChip(name: profile.name, selected: activeStyle?.id == profile.id) { styles.activate(profile) } + } + NavigationLink { + StylesView() + } label: { + Label("Edit", systemImage: "slider.horizontal.3") + .font(.subheadline.weight(.medium)) + .padding(.horizontal, 14) + .padding(.vertical, 8) + .background(Capsule().strokeBorder(BlurtBrand.cardBorder, lineWidth: 1)) + } + } + .padding(.vertical, 2) + } + } + } + + // MARK: - Recent + + private var recent: some View { + VStack(alignment: .leading, spacing: 10) { + Text("Recent").font(.headline) + if coordinator.recent.displayed.isEmpty { + Text("Your recent blurts will appear here.") + .font(.callout).foregroundStyle(.secondary) + .frame(maxWidth: .infinity, alignment: .leading) + .padding(16) + .card() + } + ForEach(coordinator.recent.displayed) { entry in + VStack(alignment: .leading, spacing: 8) { + Text(entry.text).font(.body).lineLimit(3) + HStack(spacing: 8) { + if let style = entry.style { + Text(style) + .font(.caption.weight(.medium)) + .padding(.horizontal, 8).padding(.vertical, 3) + .background(Capsule().fill(BlurtBrand.accent.opacity(0.15))) + } + Text(entry.relativeLabel(now: Date())).font(.caption).foregroundStyle(.secondary) + Spacer() + Button { + UIPasteboard.general.string = entry.text + } label: { + Image(systemName: "doc.on.doc") + } + .buttonStyle(.borderless) + .accessibilityLabel("Copy") + } + } + .padding(16) + .card() + } + } + } + + private var poweredBy: some View { + HStack(spacing: 3) { + Text("Powered by").foregroundStyle(.secondary) + Text("AssemblyAI").fontWeight(.medium) + } + .font(.caption) + .padding(.top, 4) + } + // MARK: - Setup - private var setupSection: some View { - Section("Set up") { + private var setupCard: some View { + VStack(alignment: .leading, spacing: 14) { + Text("Set up Blurt").font(.headline) SetupRow(done: coordinator.apiKey.hasAPIKey, title: "Sign in with AssemblyAI") { VStack(alignment: .leading, spacing: 6) { Text("Coming soon — sign-in needs the AssemblyAI login service.") @@ -80,127 +253,35 @@ struct HomeView: View { } } } + .padding(20) + .frame(maxWidth: .infinity, alignment: .leading) + .card() } private func openAppSettings() { guard let url = URL(string: UIApplication.openSettingsURLString) else { return } UIApplication.shared.open(url) } +} - // MARK: - Listening - - private var listeningSection: some View { - Section("Listening") { - if coordinator.window.isOpen { - VStack(alignment: .leading, spacing: 6) { - Label(listeningLabel, systemImage: "mic.fill").foregroundStyle(BlurtBrand.green) - Text("Go back to the app you're typing in and tap the mic on the Blurt keyboard.") - .font(.footnote).foregroundStyle(.secondary) - } - Button("Stop listening", role: .destructive) { coordinator.stopListening() } - } else { - Button("Start listening") { Task { await coordinator.startListening() } } - .disabled(!coordinator.apiKey.hasAPIKey) - Text("Opens the mic for \(windowLabel) so the keyboard can dictate without opening Blurt each time.") - .font(.footnote).foregroundStyle(.secondary) - } - if let error = coordinator.window.lastError { - Text(error).font(.footnote).foregroundStyle(BlurtBrand.errorOrange) - } - if coordinator.microphoneDenied { - Text("Blurt needs the microphone. Allow it in Settings.").font(.footnote) - .foregroundStyle(BlurtBrand.errorOrange) - } - } - } - - private var listeningLabel: String { - guard let until = coordinator.window.until, until != .distantFuture else { return "Listening" } - return "Listening until \(until.formatted(date: .omitted, time: .shortened))" - } - - private var windowLabel: String { - windowMinutes == 0 ? "as long as you like" : "\(windowMinutes) minutes at a time" - } - - // MARK: - Try it - - private var tryItSection: some View { - Section("Try it here") { - Button(coordinator.phase.isCapturing ? "Stop and transcribe" : "Dictate to the clipboard") { - coordinator.toggleDictation() - } - .disabled(!coordinator.window.isOpen) - PhaseLine(phase: coordinator.phase, level: coordinator.level) - } - } - - // MARK: - Keyboard - - private var keyboardSection: some View { - Section { - Picker("Layout", selection: $layout) { - ForEach(KeyboardLayout.allCases) { Text($0.title).tag($0) } - } - .pickerStyle(.segmented) - .onChange(of: layout) { _, value in SharedStore.layout = value } - Text(layout.summary).font(.footnote).foregroundStyle(.secondary) - Picker("Look", selection: $theme) { - ForEach(KeyboardTheme.allCases) { Text($0.title).tag($0) } - } - .pickerStyle(.segmented) - .onChange(of: theme) { _, value in SharedStore.theme = value } - Text(theme.summary).font(.footnote).foregroundStyle(.secondary) - Toggle("Hands-free", isOn: $autoDictate) - .onChange(of: autoDictate) { _, value in SharedStore.autoDictate = value } - Text("Start dictating the moment the Blurt keyboard comes up in a text field. Tap the mic to stop.") - .font(.footnote).foregroundStyle(.secondary) - } header: { - Text("Keyboard") - } footer: { - Text("Any layout and look works the same underneath; pick what fits how you type.") - } - } - - // MARK: - Settings - - private var settingsSection: some View { - Section("Dictation") { - Picker("Keep listening for", selection: $windowMinutes) { - Text("5 minutes").tag(5) - Text("15 minutes").tag(15) - Text("1 hour").tag(60) - Text("Until I stop it").tag(0) - } - .onChange(of: windowMinutes) { _, value in SharedStore.windowMinutes = value } - Toggle("Enhanced transcripts", isOn: $enhancedTranscripts) - NavigationLink("Output styles") { StylesView() } - TextField("Key terms, comma-separated", text: $keyTerms, axis: .vertical) - .autocorrectionDisabled() - Text( - "Names and jargon to spell right. \(coordinator.lexiconNameCount) contact names come along automatically." - ) - .font(.footnote).foregroundStyle(.secondary) - } - } - - // MARK: - Recent +/// One style, as a chip: filled with the accent while active. +private struct StyleChip: View { + let name: String + let selected: Bool + let activate: () -> Void - private var recentSection: some View { - Section("Recent") { - if coordinator.recent.entries.isEmpty { - Text("Your recent blurts will appear here").foregroundStyle(.secondary) - } - ForEach(coordinator.recent.displayed) { entry in - VStack(alignment: .leading, spacing: 4) { - Text(entry.text).lineLimit(3) - Text(entry.relativeLabel(now: Date())).font(.caption).foregroundStyle(.secondary) - } - .contextMenu { - Button("Copy") { UIPasteboard.general.string = entry.text } - } - } + var body: some View { + Button(action: activate) { + Text(name) + .font(.subheadline.weight(.medium)) + .padding(.horizontal, 14) + .padding(.vertical, 8) + .foregroundStyle(selected ? Color.white : Color.primary) + .background(Capsule().fill(selected ? BlurtBrand.accent : BlurtBrand.cardFill)) + .overlay(Capsule().strokeBorder(selected ? Color.clear : BlurtBrand.cardBorder, lineWidth: 1)) } + .buttonStyle(.plain) + .accessibilityAddTraits(selected ? .isSelected : []) } } @@ -214,7 +295,7 @@ private struct SetupRow: View { var body: some View { HStack(alignment: .top, spacing: 12) { Image(systemName: done ? "checkmark.circle.fill" : "circle") - .foregroundStyle(done ? BlurtBrand.green : Color.secondary) + .foregroundStyle(done ? BlurtBrand.accent : Color.secondary) VStack(alignment: .leading, spacing: 6) { Text(title) if !done { action() } @@ -222,18 +303,3 @@ private struct SetupRow: View { } } } - -/// The pipeline phase as one line, with a small level meter while recording. -private struct PhaseLine: View { - let phase: PipelinePhase - let level: Float - - var body: some View { - HStack(spacing: 10) { - Text(phase.overlayState.accessibilityLabel).font(.footnote).foregroundStyle(.secondary) - if phase == .recording { - ProgressView(value: Double(level)).tint(BlurtBrand.green).frame(width: 80) - } - } - } -} diff --git a/App/BlurtiOS/BlurtiOS/Sources/SettingsView.swift b/App/BlurtiOS/BlurtiOS/Sources/SettingsView.swift new file mode 100644 index 00000000..6be401f9 --- /dev/null +++ b/App/BlurtiOS/BlurtiOS/Sources/SettingsView.swift @@ -0,0 +1,116 @@ +import BlurtEngine +import SwiftUI + +/// Everything adjustable, grouped the way the Mac's Settings are: the keyboard +/// (layout, look, hands-free), listening, transcription, the account, and +/// about. Presented from the home screen's gear. +struct SettingsView: View { + var coordinator: DictationCoordinator + @Environment(\.dismiss) private var dismiss + @State private var layout = SharedStore.layout + @State private var theme = SharedStore.theme + @State private var autoDictate = SharedStore.autoDictate + @State private var windowMinutes = SharedStore.windowMinutes + @State private var showsKeyEntry = false + @AppStorage(KeyTermsStore.defaultsKey) private var keyTerms = "" + @AppStorage(EnhancedTranscriptsStore.defaultsKey) private var enhancedTranscripts = + EnhancedTranscriptsStore.defaultValue + + var body: some View { + NavigationStack { + Form { + keyboardSection + listeningSection + transcriptionSection + accountSection + aboutSection + } + .navigationTitle("Settings") + .navigationBarTitleDisplayMode(.inline) + .toolbar { + ToolbarItem(placement: .confirmationAction) { Button("Done") { dismiss() } } + } + .sheet(isPresented: $showsKeyEntry) { KeyEntryView(apiKey: coordinator.apiKey) } + } + .tint(BlurtBrand.accent) + } + + private var keyboardSection: some View { + Section { + Picker("Layout", selection: $layout) { + ForEach(KeyboardLayout.allCases) { Text($0.title).tag($0) } + } + .pickerStyle(.segmented) + .onChange(of: layout) { _, value in SharedStore.layout = value } + Text(layout.summary).font(.footnote).foregroundStyle(.secondary) + Picker("Look", selection: $theme) { + ForEach(KeyboardTheme.allCases) { Text($0.title).tag($0) } + } + .pickerStyle(.segmented) + .onChange(of: theme) { _, value in SharedStore.theme = value } + Text(theme.summary).font(.footnote).foregroundStyle(.secondary) + Toggle("Hands-free", isOn: $autoDictate) + .onChange(of: autoDictate) { _, value in SharedStore.autoDictate = value } + } header: { + Text("Keyboard") + } footer: { + Text( + "Hands-free starts dictating the moment the Blurt keyboard comes up in a text field; tap the mic to stop. " + + "The keyboard picks up changes the next time it appears.") + } + } + + private var listeningSection: some View { + Section { + Picker("Keep listening for", selection: $windowMinutes) { + Text("5 minutes").tag(5) + Text("15 minutes").tag(15) + Text("1 hour").tag(60) + Text("Until I stop it").tag(0) + } + .onChange(of: windowMinutes) { _, value in SharedStore.windowMinutes = value } + } header: { + Text("Listening") + } footer: { + Text("How long the mic stays open with nobody dictating, so the keyboard can start without opening Blurt.") + } + } + + private var transcriptionSection: some View { + Section { + Toggle("Enhanced transcripts", isOn: $enhancedTranscripts) + NavigationLink("Output styles") { StylesView() } + TextField("Key terms, comma-separated", text: $keyTerms, axis: .vertical) + .autocorrectionDisabled() + } header: { + Text("Transcription") + } footer: { + Text( + "Enhanced transcripts clean up punctuation and wording. Key terms are names and jargon to spell right; " + + "\(coordinator.lexiconNameCount) contact names come along automatically.") + } + } + + private var accountSection: some View { + Section("Account") { + LabeledContent("Sign in with AssemblyAI", value: "Coming soon") + #if DEBUG + Button(coordinator.apiKey.hasAPIKey ? "Replace the API key" : "Use an API key") { showsKeyEntry = true } + #endif + } + } + + private var aboutSection: some View { + Section("About") { + LabeledContent("Version", value: Self.version) + Link("Blurt on GitHub", destination: URL(string: "https://github.com/AssemblyAI/blurt") ?? URL(filePath: "/")) + Text("Powered by AssemblyAI").foregroundStyle(.secondary) + } + } + + private static var version: String { + let short = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String ?? "?" + let build = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as? String ?? "?" + return "\(short) (\(build))" + } +} diff --git a/App/BlurtiOS/DESIGN.md b/App/BlurtiOS/DESIGN.md index 0c3f435c..c41d9775 100644 --- a/App/BlurtiOS/DESIGN.md +++ b/App/BlurtiOS/DESIGN.md @@ -159,9 +159,38 @@ the states match); the mic key is a button labelled Dictate / Stop dictation / Start Blurt. Reduce Motion stops the ring and the meter's idle wave; heights still follow the level. -## Next: the app's screens - -Setup (sign in · microphone · keyboard) as a stepped flow; a home screen with -the orb as the hero, the listening state and window, recent dictations as -cards (`cardFill`/`cardBorder` from the Mac); styles as a chip row; settings -grouped as on the Mac. Same tokens, appearance-adaptive there (`accent`). +## The app's screens (`BlurtiOS/Sources/`) + +Appearance-adaptive, unlike the keyboard: `accent` (the catalog's +`AccentColor`, `green` in light and `greenOnDark` in dark), `cardFill` / +`cardBorder` (the Mac's card, `#EBE8E8` on `#DEDBDB` light, `#26231E` on +`#3A362F` dark, 16 pt corners, 1 pt hairline), system grouped background, +system fonts. The Mac's Icon Composer icon and its ready-screen wordmark are +shared, not copied (`project.yml`). + +**Home** (`HomeView.swift`) — the Mac's ready screen, stacked for a phone: + +| Piece | What | +| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Bar | the wordmark (tinted accent, 22 pt tall) centred; the gear → Settings | +| Setup card | only while something is missing: sign in (stub; debug builds take a key), microphone, keyboard + Full Access | +| Hero card | the orb, 112 pt, ring 2 pt sweeping while the mic is open or a dictation is in flight, glowing with the level while recording; a title2 line (Not listening · Ready to dictate · Listening… · Transcribing… · Pasted · Copied · the error) and a callout under it; the meter while recording; **Start listening** (prominent) or **Stop listening** (bordered, destructive); "Dictate here, to the clipboard" as a text button | +| Style | chips: Default and each profile, the active one filled with the accent; Edit → the styles editor | +| Recent | cards: three lines of text, the style as a tinted capsule, the relative time, a copy button; an empty-state card | +| Footer | "Powered by AssemblyAI", caption | + +**Settings** (`SettingsView.swift`) — a sheet, grouped as the Mac's: Keyboard +(layout, look, hands-free), Listening (the window), Transcription (enhanced +transcripts, output styles, key terms with the contact-name count), Account +(sign-in stub; the API key in debug builds), About (version, GitHub, Powered +by AssemblyAI). + +Screenshots: `scripts/ios-sim.sh --screenshot home.png` for the resting +screen; `BLURT_LAUNCH_ARGS=-BlurtStartListening` opens the mic at launch for +the listening state (debug builds); `xcrun simctl ui booted appearance dark` +before either for dark mode. + +## Next + +Onboarding as a stepped flow once sign-in exists; the keyboard's autocorrect +and suggestion bar; the app's cues and haptics on the phase edges. diff --git a/App/BlurtiOS/README.md b/App/BlurtiOS/README.md index f2a1e626..22ef364f 100644 --- a/App/BlurtiOS/README.md +++ b/App/BlurtiOS/README.md @@ -39,9 +39,9 @@ inherited from the Mac app and must become org-owned before the App Store. ## Design -`DESIGN.md` — the tokens, the pill, the orb, the meter, the three layouts and their -heights, all traced to the Mac app's sources, plus the gallery that renders every layout and -state for a screenshot. +`DESIGN.md` — the tokens, the pill, the orb, the meter, the three layouts and two looks, the +app's screens, all traced to the Mac app's sources, plus the gallery that renders every layout +and state for a screenshot and the launch flags that reach every app state. ## Getting Xcode diff --git a/App/BlurtiOS/project.yml b/App/BlurtiOS/project.yml index a6222f2c..0301fe5d 100644 --- a/App/BlurtiOS/project.yml +++ b/App/BlurtiOS/project.yml @@ -44,6 +44,14 @@ targets: platform: iOS sources: - path: BlurtiOS/Sources + # The Mac's brand colours (accent, card fill and border), copied verbatim + # from App/Blurt/Blurt/Assets.xcassets — JSON can't reference JSON. + - path: BlurtiOS/Assets.xcassets + # The Mac's app icon and ready-screen wordmark, shared rather than copied: + # the Icon Composer file targets iOS too (`squares: shared`). + - path: ../Blurt/Blurt/AppIcon.icon + - path: ../Blurt/Blurt/Branding/blurt-ready-logo.png + buildPhase: resources # The App Group contract, compiled into BOTH the app and the keyboard (an # extension can't import the app's module) — one source, no duplication, # the same shape as App/Blurt/Shared. @@ -57,6 +65,10 @@ targets: settings: base: PRODUCT_BUNDLE_IDENTIFIER: dev.alex.blurt.ios + ASSETCATALOG_COMPILER_APPICON_NAME: AppIcon + # The app-level accent, from the catalog, so system-drawn chrome and our + # views agree (see the Mac's project.yml and BlurtBrand). + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME: AccentColor # Warnings are failures for our own code, scoped to the target for the # reason App/Blurt/project.yml gives (the project base collides with the # -suppress-warnings Xcode applies to SPM packages). diff --git a/scripts/ios-sim.sh b/scripts/ios-sim.sh index 4a5c357d..c524ec17 100755 --- a/scripts/ios-sim.sh +++ b/scripts/ios-sim.sh @@ -59,8 +59,9 @@ APP="$DERIVED/Build/Products/Debug-iphonesimulator/BlurtiOS.app" xcrun simctl install "$UDID" "$APP" xcrun simctl privacy "$UDID" grant microphone "$BUNDLE_ID" xcrun simctl terminate "$UDID" "$BUNDLE_ID" 2>/dev/null || true +# The `+` expansion keeps an empty array from tripping `set -u` on macOS's bash 3.2. read -ra LAUNCH_ARGS <<<"${BLURT_LAUNCH_ARGS:-}" -xcrun simctl launch "$UDID" "$BUNDLE_ID" "${LAUNCH_ARGS[@]}" +xcrun simctl launch "$UDID" "$BUNDLE_ID" ${LAUNCH_ARGS[@]+"${LAUNCH_ARGS[@]}"} if [ -n "$SHOT" ]; then sleep 3 From cf919d50183764c5d417fd43c839dce127d064ba Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Thu, 24 Sep 2026 22:05:58 -0400 Subject: [PATCH 21/79] Keyboard: the mic panel is a two-page carousel with the full keyboard A horizontal swipe in either direction, as often as you like, flips between the mic panel and the letter keyboard; the page slides the way the finger went, two dots mark which is up, the keyboard resizes with it, and it is back to the mic each time the keyboard appears. Letter keys ignore a touch that travelled, and the mic cancels one, so a swipe never types or dictates. Co-Authored-By: Claude Fable 5.1 --- .../Sources/FullKeyboardView.swift | 4 +- .../BlurtKeyboard/Sources/KeyboardModel.swift | 22 ++++++ .../Sources/KeyboardViewController.swift | 12 +++- .../BlurtKeyboard/Sources/KeyboardViews.swift | 67 +++++++++++++++++-- .../Sources/KeyboardGalleryView.swift | 4 +- App/BlurtiOS/DESIGN.md | 10 +-- App/BlurtiOS/Shared/SharedState.swift | 2 +- 7 files changed, 106 insertions(+), 15 deletions(-) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift b/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift index 68f4fea3..b496d41d 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift @@ -92,8 +92,10 @@ private struct LetterKey: View { .simultaneousGesture( DragGesture(minimumDistance: 0) .onChanged { _ in pressed = true } - .onEnded { _ in + .onEnded { value in pressed = false + // A touch that travelled was a swipe (the panel's carousel), not a tap. + guard abs(value.translation.width) < 12, abs(value.translation.height) < 12 else { return } action() } ) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift index 7998aa22..d7e36124 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift @@ -25,6 +25,12 @@ final class KeyboardModel { static let lexiconRefreshInterval: TimeInterval = 60 * 60 var layout: KeyboardLayout = .panel + /// The panel is a two-page carousel — the mic panel and the full keyboard — + /// flipped by a swipe in either direction, as often as you like. Which page + /// is up; back to the mic each time the keyboard appears. + var panelShowsKeys = false + /// The direction of the last flip, so the pages slide the way the finger went. + var flipTowardsLeading = false var theme: KeyboardTheme = .blurt /// Whether the app being typed in wants a dark keyboard, for the iPhone look. var isDark = false @@ -48,6 +54,21 @@ final class KeyboardModel { var palette: KeyboardPalette { .resolve(theme: theme, dark: isDark) } + /// What is actually on screen: the panel's carousel may be showing its keys. + var effectiveLayout: KeyboardLayout { layout == .panel && panelShowsKeys ? .full : layout } + + /// Told when `effectiveLayout` changes, so the host can resize the keyboard. + @ObservationIgnored var onLayoutChange: (() -> Void)? + + /// A horizontal swipe on the panel: flip to the other page, sliding the way + /// the finger went. + func flipPanel(towardsLeading: Bool) { + guard layout == .panel else { return } + flipTowardsLeading = towardsLeading + panelShowsKeys.toggle() + onLayoutChange?() + } + /// Whether the phase leaves nothing in flight — the moments the gate has to /// be reset, since a dictation can end with no finger event to close it. private var isSettled: Bool { @@ -82,6 +103,7 @@ final class KeyboardModel { guard hasFullAccess else { return } layout = SharedStore.layout theme = SharedStore.theme + panelShowsKeys = false SharedStore.keyboardEverSeen = true refresh() startHeartbeat() diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift index 9976c59c..e2a79766 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift @@ -27,16 +27,24 @@ final class KeyboardViewController: UIInputViewController { host.didMove(toParent: self) // The keyboard's height is ours to declare; iOS honours a constraint on the // input view at just under required priority. - let height = view.heightAnchor.constraint(equalToConstant: model.layout.height(theme: model.theme)) + let height = view.heightAnchor.constraint(equalToConstant: model.effectiveLayout.height(theme: model.theme)) height.priority = UILayoutPriority(999) height.isActive = true heightConstraint = height + // The panel's carousel changes the keyboard's height when it flips. + model.onLayoutChange = { [weak self] in self?.updateHeight(animated: true) } } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) model.appeared() - heightConstraint?.constant = model.layout.height(theme: model.theme) + updateHeight(animated: false) + } + + private func updateHeight(animated: Bool) { + heightConstraint?.constant = model.effectiveLayout.height(theme: model.theme) + guard animated else { return } + UIView.animate(withDuration: 0.25) { self.view.superview?.layoutIfNeeded() } } override func viewWillDisappear(_ animated: Bool) { diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift index 2b2f7ad5..0692f3d8 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift @@ -15,17 +15,68 @@ struct KeyboardRootView: View { var body: some View { Group { - switch model.layout { + switch model.effectiveLayout { case .slimBar: SlimBarView(model: model) - case .panel: PanelView(model: model) - case .full: FullKeyboardView(model: model) + case .panel: + PanelView(model: model) + .id("panel") + .transition(flip) + case .full: + FullKeyboardView(model: model) + .id(model.layout == .panel ? "panel-keys" : "full") + .transition(flip) } } .padding(.horizontal, model.theme.margin) .padding(.vertical, Self.verticalMargin) .frame(maxWidth: .infinity, maxHeight: .infinity) .background(model.palette.surface) + .overlay(alignment: .bottom) { + if model.layout == .panel { PageDots(count: 2, current: model.panelShowsKeys ? 1 : 0).padding(.bottom, 2) } + } + .clipped() .environment(\.keyboardPalette, model.palette) + .simultaneousGesture(swipe, including: model.layout == .panel ? .all : .subviews) + .animation(reduceMotion ? nil : .easeInOut(duration: 0.25), value: model.panelShowsKeys) + } + + @Environment(\.accessibilityReduceMotion) private var reduceMotion + + /// The carousel's slide: the incoming page arrives from the side the finger + /// moved towards, the outgoing one leaves the other way. + private var flip: AnyTransition { + model.flipTowardsLeading + ? .asymmetric(insertion: .move(edge: .trailing), removal: .move(edge: .leading)) + : .asymmetric(insertion: .move(edge: .leading), removal: .move(edge: .trailing)) + } + + /// A horizontal swipe anywhere on the panel flips it; taps and holds on keys + /// never travel this far, and the keys ignore a touch that did. + private var swipe: some Gesture { + DragGesture(minimumDistance: 24) + .onEnded { value in + let dx = value.translation.width + guard abs(dx) > 48, abs(dx) > abs(value.translation.height) * 1.5 else { return } + model.flipPanel(towardsLeading: dx < 0) + } + } +} + +/// The carousel's page indicator. +struct PageDots: View { + let count: Int + let current: Int + @Environment(\.keyboardPalette) private var palette + + var body: some View { + HStack(spacing: 6) { + ForEach(0.. 24 || abs(value.translation.height) > 24 { + model.cancel() + } else { + model.micUp() + } } ) } diff --git a/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift b/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift index a161597c..4cc9cc14 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift @@ -35,7 +35,7 @@ VStack(alignment: .leading, spacing: 4) { Text(row.caption).font(.caption.weight(.medium)).foregroundStyle(.secondary).padding(.horizontal) KeyboardRootView(model: row.model) - .frame(height: row.layout.height(theme: row.model.theme)) + .frame(height: row.model.effectiveLayout.height(theme: row.model.theme)) .clipped() } } @@ -64,6 +64,8 @@ model.layout = layout model.theme = look == "blurt" ? .blurt : .system model.isDark = look == "dark" + // `keys` shows the panel's carousel flipped to its keyboard page. + model.panelShowsKeys = state == "keys" model.hasFullAccess = state != "off" model.isListening = state != "off" && state != "start" let phase: PhaseSnapshot.State = diff --git a/App/BlurtiOS/DESIGN.md b/App/BlurtiOS/DESIGN.md index c41d9775..8c8d4556 100644 --- a/App/BlurtiOS/DESIGN.md +++ b/App/BlurtiOS/DESIGN.md @@ -135,11 +135,11 @@ while pressed rather than dimming. Top and bottom margin 8 (`KeyboardRootView`); the look sets the row gap and side margin. -| Layout | Rows | Height | -| --------- | -------------------------------------------------------------------------------- | --------------------- | -| `slimBar` | globe · pill · mic 44 · delete · return | 60 | -| `panel` | pill 36 · mic 96 (cancel beside it while in flight) · space row 42, gaps 12 | 216 | -| `full` | pill 36 · three letter rows 42 · globe/123/space/mic/return 42; `220 + 4·rowGap` | 252 Blurt, 264 iPhone | +| Layout | Rows | Height | +| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- | +| `slimBar` | globe · pill · mic 44 · delete · return | 60 | +| `panel` | pill 36 · mic 96 (cancel beside it while in flight) · space row 42, gaps 12. A two-page carousel: a horizontal swipe in either direction, as often as you like, flips between the mic panel and the full keyboard (the page slides the way the finger went; two page dots at the bottom; the keyboard resizes with it; back to the mic each time the keyboard appears). Keys ignore a touch that travelled more than 12 pt, the mic cancels one that travelled more than 24 pt. | 216, or the full layout's when flipped | +| `full` | pill 36 · three letter rows 42 · globe/123/space/mic/return 42; `220 + 4·rowGap` | 252 Blurt, 264 iPhone | The pill is capped at 260 pt wide in the panel and full layouts, flexible in the slim bar. The globe key appears only when iOS says another keyboard is diff --git a/App/BlurtiOS/Shared/SharedState.swift b/App/BlurtiOS/Shared/SharedState.swift index 93a0ec09..79ff789d 100644 --- a/App/BlurtiOS/Shared/SharedState.swift +++ b/App/BlurtiOS/Shared/SharedState.swift @@ -70,7 +70,7 @@ nonisolated enum KeyboardLayout: String, CaseIterable, Codable, Sendable, Identi var summary: String { switch self { case .slimBar: "Just the mic and a few keys. Switch keyboards to type." - case .panel: "A big mic with status and cancel. Switch keyboards to type." + case .panel: "A big mic with status and cancel. Swipe sideways for the full keyboard, and back." case .full: "Every letter key, with the mic as the main key." } } From cc9faad9ac3ec0020dd29f58264f6d28dbade864 Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Thu, 24 Sep 2026 22:16:51 -0400 Subject: [PATCH 22/79] =?UTF-8?q?Keyboard:=20one=20look=20=E2=80=94=20Blur?= =?UTF-8?q?t's=20colours=20at=20the=20iPhone's=20exact=20spacing;=20no=20p?= =?UTF-8?q?age=20dots?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The look setting is gone: the keys sit exactly where the iPhone keyboard's do (6 between keys, 11 between rows, 3 at the edges, 5 pt corners, a 1 pt drop) in Blurt's colours, in every appearance. Themes come later, through the same palette seam; the iPhone's own palettes are recorded in DESIGN.md as the first to offer. The carousel keeps its swipe and loses its dots. Co-Authored-By: Claude Fable 5.1 --- .../Sources/FullKeyboardView.swift | 6 +- .../BlurtKeyboard/Sources/KeyboardModel.swift | 21 +------ .../Sources/KeyboardPalette.swift | 46 ++++---------- .../Sources/KeyboardViewController.swift | 4 +- .../BlurtKeyboard/Sources/KeyboardViews.swift | 52 ++++------------ .../Sources/KeyboardGalleryView.swift | 15 ++--- .../BlurtiOS/Sources/SettingsView.swift | 9 +-- App/BlurtiOS/DESIGN.md | 60 +++++++++---------- App/BlurtiOS/README.md | 2 +- App/BlurtiOS/Shared/SharedState.swift | 46 ++------------ 10 files changed, 74 insertions(+), 187 deletions(-) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift b/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift index b496d41d..c3cefcfa 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift @@ -3,7 +3,7 @@ import SwiftUI /// A complete keyboard with the mic as the main key, laid out as the iPhone's /// own: ten letter keys across at one width, the middle row centred, shift /// and delete flanking the bottom letters, then 123 · globe · space · mic · -/// return. Every key is 42 pt tall; the look sets the gaps. Letters pop up +/// return, at the system keyboard's spacing. Every key is 42 pt tall. Letters pop up /// while pressed, sentences capitalise themselves, a double space ends one. /// No autocorrect or suggestions yet. iOS swaps in its own keyboard for /// password and phone-number fields, so those never reach here. @@ -15,14 +15,14 @@ struct FullKeyboardView: View { var body: some View { GeometryReader { geo in - let gap = model.theme.keyGap + let gap = KeyboardPalette.keyGap // Ten keys and nine gaps across the row. let keyWidth = (geo.size.width - 9 * gap) / 10 // Shift and delete take what seven letters leave, standing a little // further from them than letters stand from each other. let sideGap = gap * 2 let sideWidth = (geo.size.width - 7 * keyWidth - 6 * gap - 2 * sideGap) / 2 - VStack(spacing: model.theme.rowGap) { + VStack(spacing: KeyboardPalette.rowGap) { StatusPill(model: model) .frame(maxWidth: 260) ForEach(Array(rows.enumerated()), id: \.offset) { index, row in diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift index d7e36124..1df3b994 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift @@ -31,9 +31,6 @@ final class KeyboardModel { var panelShowsKeys = false /// The direction of the last flip, so the pages slide the way the finger went. var flipTowardsLeading = false - var theme: KeyboardTheme = .blurt - /// Whether the app being typed in wants a dark keyboard, for the iPhone look. - var isDark = false var snapshot = PhaseSnapshot.idle var isListening = false var hasFullAccess = false @@ -52,7 +49,8 @@ final class KeyboardModel { var proxy: (any UITextDocumentProxy)? { controller?.textDocumentProxy } - var palette: KeyboardPalette { .resolve(theme: theme, dark: isDark) } + /// One palette for now; themes are a later feature. + var palette: KeyboardPalette { .blurt } /// What is actually on screen: the panel's carousel may be showing its keys. var effectiveLayout: KeyboardLayout { layout == .panel && panelShowsKeys ? .full : layout } @@ -95,14 +93,12 @@ final class KeyboardModel { func appeared() { hasFullAccess = controller?.hasFullAccess ?? false needsGlobe = controller?.needsInputModeSwitchKey ?? true - readAppearance() updateShift() // Without Full Access the App Group is out of reach: the keyboard still // types, and says what it needs (see `KeyboardRootView`), but nothing below // can run. guard hasFullAccess else { return } layout = SharedStore.layout - theme = SharedStore.theme panelShowsKeys = false SharedStore.keyboardEverSeen = true refresh() @@ -121,16 +117,6 @@ final class KeyboardModel { perform(gate.modifierUp(at: elapsed)) } - /// The iPhone look follows the app being typed in: what its text field asks - /// for, or failing that the app's own light or dark appearance. - private func readAppearance() { - switch proxy?.keyboardAppearance { - case .dark: isDark = true - case .light: isDark = false - default: isDark = controller?.traitCollection.userInterfaceStyle == .dark - } - } - func disappeared() { heartbeat?.cancel() heartbeat = nil @@ -140,9 +126,8 @@ final class KeyboardModel { } /// The cursor moved or the text around it changed, including by our own - /// typing: re-read what the field wants and where the sentence stands. + /// typing: re-read where the sentence stands. func contextChanged() { - readAppearance() updateShift() } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift index c0bd00ad..d51f32ee 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift @@ -1,47 +1,27 @@ import SwiftUI -/// The colors a layout draws its surface and keys with. Two looks: Blurt's -/// own (the ink surface, `BlurtBrand`) and the iPhone's default keyboard, -/// which follows the app being typed in between its light and dark palettes. -/// The status pill and the orb are Blurt's in both; the look is about the -/// keys. Spacing lives on `KeyboardTheme`, shared with the app for the -/// layout heights. +/// The colors and spacing the keys draw with. The spacing is the iPhone +/// keyboard's own — 6 pt between keys, 11 pt between rows, 3 pt at the +/// edges, 5 pt corners, a 1 pt drop under every key — so nobody's fingers +/// are thrown off; the colours are Blurt's (`BlurtBrand`). One palette for +/// now; themes are a later feature, and this is the seam they plug into. struct KeyboardPalette: Equatable { var surface: Color var key: Color var keyDark: Color var keyText: Color - /// The 1 pt drop the system keyboard gives every key; nil for the flat ink look. - var keyShadow: Color? - var keyRadius: CGFloat + /// The drop under each key, as the system keyboard draws it. + var keyShadow: Color var popupFill: Color + static let keyGap: CGFloat = 6 + static let rowGap: CGFloat = 11 + static let margin: CGFloat = 3 + static let keyRadius: CGFloat = 5 + static let blurt = KeyboardPalette( surface: BlurtBrand.ink, key: BlurtBrand.key, keyDark: BlurtBrand.keyDark, keyText: BlurtBrand.keyText, - keyShadow: nil, keyRadius: 6, popupFill: BlurtBrand.key) - - /// The iPhone's light keyboard: `#D1D5DB` surface, white keys, `#ADB3BC` - /// modifiers, a `#898A8D` drop under each key. - static let systemLight = KeyboardPalette( - surface: Color(red: 209 / 255, green: 213 / 255, blue: 219 / 255), key: .white, - keyDark: Color(red: 173 / 255, green: 179 / 255, blue: 188 / 255), keyText: .black, - keyShadow: Color(red: 137 / 255, green: 138 / 255, blue: 141 / 255), keyRadius: 5, popupFill: .white) - - /// The iPhone's dark keyboard: `#2B2B2B` surface, `#6B6B6B` keys, `#464646` - /// modifiers, a near-black drop. - static let systemDark = KeyboardPalette( - surface: Color(red: 43 / 255, green: 43 / 255, blue: 43 / 255), - key: Color(red: 107 / 255, green: 107 / 255, blue: 107 / 255), - keyDark: Color(red: 70 / 255, green: 70 / 255, blue: 70 / 255), keyText: .white, - keyShadow: Color(red: 13 / 255, green: 13 / 255, blue: 13 / 255), keyRadius: 5, - popupFill: Color(red: 107 / 255, green: 107 / 255, blue: 107 / 255)) - - static func resolve(theme: KeyboardTheme, dark: Bool) -> KeyboardPalette { - switch theme { - case .blurt: .blurt - case .system: dark ? .systemDark : .systemLight - } - } + keyShadow: Color.black.opacity(0.45), popupFill: BlurtBrand.key) } private struct KeyboardPaletteKey: EnvironmentKey { diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift index e2a79766..698c8c93 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift @@ -27,7 +27,7 @@ final class KeyboardViewController: UIInputViewController { host.didMove(toParent: self) // The keyboard's height is ours to declare; iOS honours a constraint on the // input view at just under required priority. - let height = view.heightAnchor.constraint(equalToConstant: model.effectiveLayout.height(theme: model.theme)) + let height = view.heightAnchor.constraint(equalToConstant: model.effectiveLayout.height) height.priority = UILayoutPriority(999) height.isActive = true heightConstraint = height @@ -42,7 +42,7 @@ final class KeyboardViewController: UIInputViewController { } private func updateHeight(animated: Bool) { - heightConstraint?.constant = model.effectiveLayout.height(theme: model.theme) + heightConstraint?.constant = model.effectiveLayout.height guard animated else { return } UIView.animate(withDuration: 0.25) { self.view.superview?.layoutIfNeeded() } } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift index 0692f3d8..e4aed15b 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift @@ -2,15 +2,14 @@ import SwiftUI /// Picks the layout the user chose. All three share `StatusPill`, `MicKey` and /// `KeyCap`, and the same model underneath; they differ in how much keyboard -/// surrounds the mic. The look (`KeyboardTheme`) decides the surface and the -/// keys: Blurt's ink in every appearance — it floats over whichever app the -/// user is typing in, like the Mac pill — or the iPhone's own keyboard, light -/// or dark with that app. +/// surrounds the mic. The surface is Blurt's ink in every appearance — it +/// floats over whichever app the user is typing in, like the Mac pill — at +/// the iPhone keyboard's own spacing. struct KeyboardRootView: View { var model: KeyboardModel /// The keyboard's top and bottom margin: the arithmetic in - /// `KeyboardLayout.height` is built on it and the theme's row gap. + /// `KeyboardLayout.height` is built on it and the palette's row gap. static let verticalMargin: CGFloat = 8 var body: some View { @@ -27,13 +26,10 @@ struct KeyboardRootView: View { .transition(flip) } } - .padding(.horizontal, model.theme.margin) + .padding(.horizontal, KeyboardPalette.margin) .padding(.vertical, Self.verticalMargin) .frame(maxWidth: .infinity, maxHeight: .infinity) .background(model.palette.surface) - .overlay(alignment: .bottom) { - if model.layout == .panel { PageDots(count: 2, current: model.panelShowsKeys ? 1 : 0).padding(.bottom, 2) } - } .clipped() .environment(\.keyboardPalette, model.palette) .simultaneousGesture(swipe, including: model.layout == .panel ? .all : .subviews) @@ -62,24 +58,6 @@ struct KeyboardRootView: View { } } -/// The carousel's page indicator. -struct PageDots: View { - let count: Int - let current: Int - @Environment(\.keyboardPalette) private var palette - - var body: some View { - HStack(spacing: 6) { - ForEach(0.. some View { background { - RoundedRectangle(cornerRadius: palette.keyRadius) + RoundedRectangle(cornerRadius: KeyboardPalette.keyRadius) .fill(fill) - .shadow(color: palette.keyShadow ?? .clear, radius: 0, y: palette.keyShadow == nil ? 0 : 1) + .shadow(color: palette.keyShadow, radius: 0, y: 1) } .overlay { - if palette.keyShadow == nil { - RoundedRectangle(cornerRadius: palette.keyRadius).strokeBorder(Color.white.opacity(0.06), lineWidth: 1) - } + RoundedRectangle(cornerRadius: KeyboardPalette.keyRadius).strokeBorder(Color.white.opacity(0.06), lineWidth: 1) } } } -/// A modifier key darkens while the finger is on it, the way the system's do, -/// instead of the default button dimming; on the ink look it lightens. +/// A key lightens while the finger is on it, the way the system's change +/// shade, instead of the default button dimming. struct KeyPressStyle: ButtonStyle { - @Environment(\.keyboardPalette) private var palette - func makeBody(configuration: Configuration) -> some View { configuration.label - .brightness(configuration.isPressed ? (palette.keyShadow == nil ? 0.15 : -0.12) : 0) + .brightness(configuration.isPressed ? 0.15 : 0) .animation(.easeOut(duration: 0.08), value: configuration.isPressed) } } diff --git a/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift b/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift index 4cc9cc14..3ef1fbe1 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift @@ -5,10 +5,8 @@ /// reference, and the way a screenshot of the keyboard is taken without /// tapping through Notes. Debug builds only, reached by launch argument: /// - /// -BlurtGallery [,…] [blurt|light|dark] + /// -BlurtGallery [,…] /// - /// The last word picks the look: Blurt's ink (the default), or the iPhone - /// keyboard in its light or dark palette. /// where a state is `off` (no Full Access), `start` (app not listening), /// `idle`, `connecting`, `recording`, `processing`, `pasted`, `copied` or /// `error`. `scripts/ios-sim.sh` passes `BLURT_LAUNCH_ARGS` through, so @@ -35,7 +33,7 @@ VStack(alignment: .leading, spacing: 4) { Text(row.caption).font(.caption.weight(.medium)).foregroundStyle(.secondary).padding(.horizontal) KeyboardRootView(model: row.model) - .frame(height: row.model.effectiveLayout.height(theme: row.model.theme)) + .frame(height: row.model.effectiveLayout.height) .clipped() } } @@ -51,19 +49,14 @@ guard let flag = arguments.firstIndex(of: "-BlurtGallery"), arguments.count > flag + 2, let layout = KeyboardLayout(rawValue: arguments[flag + 1]) else { return [] } - let look = arguments.count > flag + 3 ? arguments[flag + 3] : "blurt" return arguments[flag + 2].split(separator: ",").map { name in - Row( - layout: layout, caption: "\(layout.rawValue) · \(name) · \(look)", - model: model(layout: layout, state: String(name), look: look)) + Row(layout: layout, caption: "\(layout.rawValue) · \(name)", model: model(layout: layout, state: String(name))) } } - private static func model(layout: KeyboardLayout, state: String, look: String) -> KeyboardModel { + private static func model(layout: KeyboardLayout, state: String) -> KeyboardModel { let model = KeyboardModel() model.layout = layout - model.theme = look == "blurt" ? .blurt : .system - model.isDark = look == "dark" // `keys` shows the panel's carousel flipped to its keyboard page. model.panelShowsKeys = state == "keys" model.hasFullAccess = state != "off" diff --git a/App/BlurtiOS/BlurtiOS/Sources/SettingsView.swift b/App/BlurtiOS/BlurtiOS/Sources/SettingsView.swift index 6be401f9..c7c58032 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/SettingsView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/SettingsView.swift @@ -2,13 +2,12 @@ import BlurtEngine import SwiftUI /// Everything adjustable, grouped the way the Mac's Settings are: the keyboard -/// (layout, look, hands-free), listening, transcription, the account, and +/// (layout, hands-free), listening, transcription, the account, and /// about. Presented from the home screen's gear. struct SettingsView: View { var coordinator: DictationCoordinator @Environment(\.dismiss) private var dismiss @State private var layout = SharedStore.layout - @State private var theme = SharedStore.theme @State private var autoDictate = SharedStore.autoDictate @State private var windowMinutes = SharedStore.windowMinutes @State private var showsKeyEntry = false @@ -43,12 +42,6 @@ struct SettingsView: View { .pickerStyle(.segmented) .onChange(of: layout) { _, value in SharedStore.layout = value } Text(layout.summary).font(.footnote).foregroundStyle(.secondary) - Picker("Look", selection: $theme) { - ForEach(KeyboardTheme.allCases) { Text($0.title).tag($0) } - } - .pickerStyle(.segmented) - .onChange(of: theme) { _, value in SharedStore.theme = value } - Text(theme.summary).font(.footnote).foregroundStyle(.secondary) Toggle("Hands-free", isOn: $autoDictate) .onChange(of: autoDictate) { _, value in SharedStore.autoDictate = value } } header: { diff --git a/App/BlurtiOS/DESIGN.md b/App/BlurtiOS/DESIGN.md index 8c8d4556..e00c36dd 100644 --- a/App/BlurtiOS/DESIGN.md +++ b/App/BlurtiOS/DESIGN.md @@ -30,32 +30,32 @@ Layouts: `slimBar`, `panel`, `full`. States: `off` (no Full Access), `start` gallery is `BlurtiOS/Sources/KeyboardGalleryView.swift`, debug builds only; the keyboard's sources are compiled into the app for it (`project.yml`). -## Two looks (`KeyboardTheme`, `BlurtKeyboard/Sources/KeyboardPalette.swift`) - -People are used to the iPhone's keyboard, so the keys can look exactly like it. -The **look** is a setting beside the layout, in the app's Keyboard section: - -| Look | Surface and keys | -| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `blurt` | The ink surface and tokens below, in every appearance. Gaps 5, rows 8, margin 8. | -| `system` | The iPhone keyboard's own palette, light or dark with the app being typed in (its field's `keyboardAppearance`, else the app's style). Gaps 6, rows 11, margin 3, a 1 pt drop under every key. | - -System light: surface `#D1D5DB`, letter keys white, modifiers `#ADB3BC`, drop -`#898A8D`, black legends. System dark: surface `#2B2B2B`, keys `#6B6B6B`, -modifiers `#464646`, drop `#0D0D0D`, white legends. Radius 5 (Blurt: 6). The -status pill and the orb stay Blurt's in both — the look is about the keys. -The gallery's last argument picks it: `blurt` (default), `light`, `dark`. - -The full layout follows the iPhone's geometry in both looks: ten letter keys -across at one width (`(width − 9·gap) / 10`), the middle row centred, shift -and delete taking what seven letters leave (twice the gap away from them), -then 123 · globe · space · mic · return, return two modifiers wide. Letters -pop up while pressed (a 32 pt copy 58 pt above the key, typed on release); -shift comes on by itself at the start of a sentence — or of every word, or -always — as the field's `autocapitalizationType` asks, and goes off after -one letter; a second space within 450 ms of the first, after a word, becomes +## One look, the iPhone's spacing (`BlurtKeyboard/Sources/KeyboardPalette.swift`) + +The keys sit exactly where the iPhone keyboard's do, so nobody's fingers are +thrown off: 6 pt between keys, 11 pt between rows, 3 pt at the edges, 5 pt +corners, a 1 pt drop under every key. The colours are Blurt's — the ink +surface and the tokens below — in every appearance, for the reason the Mac +pill is: the keyboard floats over whichever app the user is typing in. +`KeyboardPalette` is one value for now and the seam themes plug into later. + +The full layout follows the iPhone's geometry: ten letter keys across at one +width (`(width − 9·gap) / 10`), the middle row centred, shift and delete +taking what seven letters leave (twice the gap away from them), then 123 · +globe · space · mic · return, return two modifiers wide. Letters pop up +while pressed (a 32 pt copy 58 pt above the key, typed on release); shift +comes on by itself at the start of a sentence — or of every word, or always +— as the field's `autocapitalizationType` asks, and goes off after one +letter; a second space within 450 ms of the first, after a word, becomes ". ". Not yet: autocorrect and the suggestion bar. +**Later: themes.** Users will pick their own. The iPhone keyboard's own +palettes are the first two to offer, and were measured for it: light — +surface `#D1D5DB`, letter keys white, modifiers `#ADB3BC`, drop `#898A8D`, +black legends; dark — surface `#2B2B2B`, keys `#6B6B6B`, modifiers +`#464646`, drop `#0D0D0D`, white legends; both follow the field's +`keyboardAppearance`, else the app's style. + ## Hands-free A toggle in the same section: with it on, a dictation starts the moment the @@ -133,13 +133,13 @@ while pressed rather than dimming. ## Layouts and their heights (`KeyboardLayout.height`) -Top and bottom margin 8 (`KeyboardRootView`); the look sets the row gap and side margin. +Top and bottom margin 8 (`KeyboardRootView`); 11 between rows and 3 at the sides (`KeyboardPalette`). -| Layout | Rows | Height | -| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- | -| `slimBar` | globe · pill · mic 44 · delete · return | 60 | -| `panel` | pill 36 · mic 96 (cancel beside it while in flight) · space row 42, gaps 12. A two-page carousel: a horizontal swipe in either direction, as often as you like, flips between the mic panel and the full keyboard (the page slides the way the finger went; two page dots at the bottom; the keyboard resizes with it; back to the mic each time the keyboard appears). Keys ignore a touch that travelled more than 12 pt, the mic cancels one that travelled more than 24 pt. | 216, or the full layout's when flipped | -| `full` | pill 36 · three letter rows 42 · globe/123/space/mic/return 42; `220 + 4·rowGap` | 252 Blurt, 264 iPhone | +| Layout | Rows | Height | +| --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | +| `slimBar` | globe · pill · mic 44 · delete · return | 60 | +| `panel` | pill 36 · mic 96 (cancel beside it while in flight) · space row 42, gaps 12. A two-page carousel: a horizontal swipe in either direction, as often as you like, flips between the mic panel and the full keyboard; the page slides the way the finger went, the keyboard resizes with it, and it is back to the mic each time the keyboard appears. Keys ignore a touch that travelled more than 12 pt, the mic cancels one that travelled more than 24 pt. | 216, or 264 when flipped | +| `full` | pill 36 · three letter rows 42 · globe/123/space/mic/return 42; `220 + 4·11` | 264 | The pill is capped at 260 pt wide in the panel and full layouts, flexible in the slim bar. The globe key appears only when iOS says another keyboard is diff --git a/App/BlurtiOS/README.md b/App/BlurtiOS/README.md index 22ef364f..29b2d60b 100644 --- a/App/BlurtiOS/README.md +++ b/App/BlurtiOS/README.md @@ -39,7 +39,7 @@ inherited from the Mac app and must become org-owned before the App Store. ## Design -`DESIGN.md` — the tokens, the pill, the orb, the meter, the three layouts and two looks, the +`DESIGN.md` — the tokens, the pill, the orb, the meter, the three layouts, the app's screens, all traced to the Mac app's sources, plus the gallery that renders every layout and state for a screenshot and the launch flags that reach every app state. diff --git a/App/BlurtiOS/Shared/SharedState.swift b/App/BlurtiOS/Shared/SharedState.swift index 79ff789d..46ed24e6 100644 --- a/App/BlurtiOS/Shared/SharedState.swift +++ b/App/BlurtiOS/Shared/SharedState.swift @@ -20,7 +20,6 @@ nonisolated enum BlurtShared { nonisolated enum Key { static let layout = "keyboardLayout" - static let theme = "keyboardTheme" static let autoDictate = "autoDictate" static let listeningUntil = "listeningUntil" static let windowMinutes = "listeningWindowMinutes" @@ -77,49 +76,17 @@ nonisolated enum KeyboardLayout: String, CaseIterable, Codable, Sendable, Identi /// The keyboard's height in points. Fixed per layout; the system keyboard is /// about 216 on a phone, which is what `panel` matches. - /// The keyboard's height on screen, from the layout's rows and the look's - /// spacing: see `App/BlurtiOS/DESIGN.md` for the arithmetic. - func height(theme: KeyboardTheme) -> CGFloat { + /// The keyboard's height on screen, from the layout's rows at the iPhone + /// keyboard's own spacing: see `App/BlurtiOS/DESIGN.md` for the arithmetic. + var height: CGFloat { switch self { case .slimBar: 60 case .panel: 216 - case .full: 220 + 4 * theme.rowGap + case .full: 264 } } } -/// How the keys look. The status pill and the orb are Blurt's in both; this is -/// about the surface and the keys around them. -nonisolated enum KeyboardTheme: String, CaseIterable, Codable, Sendable, Identifiable { - /// Blurt's own: the ink surface, warm-white legends. - case blurt - /// The iPhone's default keyboard, light or dark with the app being typed in, - /// for people who want nothing to change but the mic. - case system - - var id: String { rawValue } - - var title: String { - switch self { - case .blurt: "Blurt" - case .system: "iPhone" - } - } - - var summary: String { - switch self { - case .blurt: "Blurt's ink and green." - case .system: "The keyboard you already know, light or dark with the app you're in. Only the mic is new." - } - } - - /// The system keyboard's spacing (6 between keys, 11 between rows, 3 at the - /// edges) versus Blurt's tighter, flatter grid. - var keyGap: CGFloat { self == .system ? 6 : 5 } - var rowGap: CGFloat { self == .system ? 11 : 8 } - var margin: CGFloat { self == .system ? 3 : 8 } -} - // MARK: - Payloads // // Every type below is `nonisolated`: both targets default their declarations to @@ -240,11 +207,6 @@ nonisolated enum SharedStore { set { defaults.set(newValue.rawValue, forKey: BlurtShared.Key.layout) } } - static var theme: KeyboardTheme { - get { KeyboardTheme(rawValue: defaults.string(forKey: BlurtShared.Key.theme) ?? "") ?? .blurt } - set { defaults.set(newValue.rawValue, forKey: BlurtShared.Key.theme) } - } - /// Hands-free: the keyboard starts a dictation the moment it appears in a /// text field, so there is nothing to tap before talking. static var autoDictate: Bool { From ec20a121defd06cb10ee0a867b5b457645176234 Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Thu, 24 Sep 2026 23:16:10 -0400 Subject: [PATCH 23/79] Keyboard: no words, the orb is the whole voice control; the mic leaves the letter rows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The status pill is gone. Voice lives in one place, the bar above the keys where the system puts its suggestions: the orb, tap or hold, with the live meter on either side while recording. State is the orb's own — dimmed when Blurt isn't ready, the ring sweeping while working, a stop glyph and a glow while recording, a check, a clipboard or an orange exclamation for a moment after — and every transition has its haptic. The bottom row is the stock one: 123 · globe · space · return. Hands-free is on by default, so a dictation is under way the moment the keyboard comes up. Co-Authored-By: Claude Fable 5.1 --- .../BlurtKeyboard/Sources/BrandOrb.swift | 33 ++--- .../Sources/FullKeyboardView.swift | 15 +- .../BlurtKeyboard/Sources/KeyboardViews.swift | 75 +++++++--- .../BlurtKeyboard/Sources/StatusPill.swift | 135 ------------------ .../BlurtKeyboard/Sources/VoiceBar.swift | 71 +++++++++ App/BlurtiOS/DESIGN.md | 75 +++++----- App/BlurtiOS/Shared/SharedState.swift | 11 +- 7 files changed, 190 insertions(+), 225 deletions(-) delete mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/StatusPill.swift create mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/BrandOrb.swift b/App/BlurtiOS/BlurtKeyboard/Sources/BrandOrb.swift index de98e3b8..605ae1fc 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/BrandOrb.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/BrandOrb.swift @@ -20,6 +20,8 @@ struct BrandOrb: View { /// drawn — it is part of the mark — but holds still. var animated: Bool var ringWidth: CGFloat = 1 + /// A solid ring in place of the green-to-white gradient — the error's orange. + var ringColor: Color? /// One turn every 1.6 s: the Mac's cadence. static let period: Double = 1.6 @@ -48,30 +50,11 @@ struct BrandOrb: View { } /// `strokeBorder` so the ring sits inside the disc instead of fringing it. - private var ringShape: some View { - Circle().strokeBorder(BlurtBrand.orbRingGradient, lineWidth: ringWidth) - } -} - -/// The pill's status word — "Transcribing", "Pasted", "Error" — in the Mac's -/// tracked uppercase, scaled from the pill's 9 pt to 11 pt for a phone held at -/// arm's length. Brand green, except the error word's orange. -struct StatusLineText: View { - let text: String - var color: Color = BlurtBrand.greenOnDark - - init(_ text: String, color: Color = BlurtBrand.greenOnDark) { - self.text = text - self.color = color - } - - var body: some View { - Text(text) - .font(.system(size: 11, weight: .semibold)) - .textCase(.uppercase) - .tracking(1.1) - .lineLimit(1) - .minimumScaleFactor(0.7) - .foregroundStyle(color) + @ViewBuilder private var ringShape: some View { + if let ringColor { + Circle().strokeBorder(ringColor, lineWidth: ringWidth) + } else { + Circle().strokeBorder(BlurtBrand.orbRingGradient, lineWidth: ringWidth) + } } } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift b/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift index c3cefcfa..fc93ed55 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift @@ -1,9 +1,9 @@ import SwiftUI -/// A complete keyboard with the mic as the main key, laid out as the iPhone's -/// own: ten letter keys across at one width, the middle row centred, shift -/// and delete flanking the bottom letters, then 123 · globe · space · mic · -/// return, at the system keyboard's spacing. Every key is 42 pt tall. Letters pop up +/// A complete keyboard laid out as the iPhone's own — ten letter keys across +/// at one width, the middle row centred, shift and delete flanking the bottom +/// letters, then 123 · globe · space · return, at the system keyboard's +/// spacing — with the voice bar where the suggestion bar would be. Every key is 42 pt tall. Letters pop up /// while pressed, sentences capitalise themselves, a double space ends one. /// No autocorrect or suggestions yet. iOS swaps in its own keyboard for /// password and phone-number fields, so those never reach here. @@ -23,8 +23,7 @@ struct FullKeyboardView: View { let sideGap = gap * 2 let sideWidth = (geo.size.width - 7 * keyWidth - 6 * gap - 2 * sideGap) / 2 VStack(spacing: KeyboardPalette.rowGap) { - StatusPill(model: model) - .frame(maxWidth: 260) + VoiceBar(model: model) ForEach(Array(rows.enumerated()), id: \.offset) { index, row in HStack(spacing: index == 2 ? sideGap : gap) { if index == 2 { modifierKey(width: sideWidth) } @@ -39,11 +38,11 @@ struct FullKeyboardView: View { } .frame(maxWidth: .infinity) } + // The stock bottom row; voice lives only in the bar above. HStack(spacing: gap) { - if model.needsGlobe { KeyCap(systemImage: "globe", dark: true, width: sideWidth) { model.globe() } } KeyCap(title: model.symbolsPage ? "ABC" : "123", dark: true, width: sideWidth) { model.toggleSymbols() } + if model.needsGlobe { KeyCap(systemImage: "globe", dark: true, width: sideWidth) { model.globe() } } KeyCap(title: "space", flexible: true) { model.space() } - MicKey(model: model, size: KeyCap.height) KeyCap(systemImage: "return", dark: true, width: sideWidth * 2 + gap) { model.newline() } } } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift index e4aed15b..738cd829 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift @@ -1,6 +1,6 @@ import SwiftUI -/// Picks the layout the user chose. All three share `StatusPill`, `MicKey` and +/// Picks the layout the user chose. All three share `VoiceBar`/`MicKey` and /// `KeyCap`, and the same model underneath; they differ in how much keyboard /// surrounds the mic. The surface is Blurt's ink in every appearance — it /// floats over whichever app the user is typing in, like the Mac pill — at @@ -58,30 +58,29 @@ struct KeyboardRootView: View { } } -/// One row: the globe, the pill, the mic, delete and return. 60 pt. +/// One row: the globe, the voice bar, delete and return. 60 pt. struct SlimBarView: View { var model: KeyboardModel var body: some View { HStack(spacing: 8) { if model.needsGlobe { KeyCap(systemImage: "globe", dark: true) { model.globe() } } - StatusPill(model: model, compact: true) - MicKey(model: model, size: 44) + VoiceBar(model: model) KeyCap(systemImage: "delete.left", dark: true) { model.deleteBackward() } KeyCap(systemImage: "return", dark: true) { model.newline() } } } } -/// The pill, a big mic with cancel beside it while something is in flight, -/// and one row of keys. 216 pt. +/// A big orb with cancel beside it while something is in flight, the meter +/// under it while recording, and one row of keys. 216 pt. struct PanelView: View { var model: KeyboardModel + @Environment(\.accessibilityReduceMotion) private var reduceMotion var body: some View { VStack(spacing: 12) { - StatusPill(model: model) - .frame(maxWidth: 260) + Spacer(minLength: 0) ZStack { MicKey(model: model, size: 96) if !model.isSettledState { @@ -92,7 +91,13 @@ struct PanelView: View { } } .frame(height: 96) - HStack(spacing: 8) { + WaveformMeter(level: Float(model.snapshot.level), animated: !reduceMotion, color: BlurtBrand.greenOnDark) + .frame(width: 180, height: 24) + .opacity(model.snapshot.state == .recording ? 1 : 0) + .animation(.easeInOut(duration: 0.15), value: model.snapshot.state) + .accessibilityHidden(true) + Spacer(minLength: 0) + HStack(spacing: KeyboardPalette.keyGap) { if model.needsGlobe { KeyCap(systemImage: "globe", dark: true) { model.globe() } } KeyCap(title: "space", flexible: true) { model.space() } KeyCap(systemImage: "delete.left", dark: true) { model.deleteBackward() } @@ -102,11 +107,16 @@ struct PanelView: View { } } -/// The mic key is the brand orb. Finger down starts, finger up decides tap -/// (latched) or hold (push-to-talk) — `KeyboardModel` runs the engine's gate. -/// The Mac's orb carries no glyph; here it is a key, so a mic sits on it, and -/// while recording the ring sweeps and the disc glows with the voice level. -/// When the app isn't listening the orb sits dimmed and the tap opens Blurt. +/// The mic key is the brand orb, and it says everything without a word. +/// Finger down starts, finger up decides tap (latched) or hold (push-to-talk) +/// — `KeyboardModel` runs the engine's gate. The Mac's orb carries no glyph; +/// here it is a key, so a mic sits on it. Then: dimmed when Blurt isn't ready +/// (no Full Access, or the app isn't listening — the tap opens Blurt); the +/// ring sweeping while connecting and transcribing; a stop glyph, the sweep +/// and a glow with the voice level while recording; a check for a moment +/// after the words landed, a clipboard when they went to the clipboard +/// instead, an orange ring and an exclamation mark when something failed. +/// Each of those also has its haptic. struct MicKey: View { var model: KeyboardModel var size: CGFloat @@ -116,14 +126,19 @@ struct MicKey: View { var body: some View { let level = CGFloat(model.snapshot.level) ZStack { - BrandOrb(diameter: size, animated: isWorking && !reduceMotion, ringWidth: isWorking ? 2 : 1) - .saturation(isReady ? 1 : 0.35) - .opacity(isReady ? 1 : 0.8) + BrandOrb( + diameter: size, animated: isWorking && !reduceMotion, ringWidth: isWorking || isNotice ? 2 : 1, + ringColor: ringColor + ) + .saturation(isReady ? 1 : 0.35) + .opacity(isReady ? 1 : 0.8) Image(systemName: glyph) .font(.system(size: size * 0.36, weight: .semibold)) .foregroundStyle(.white) .shadow(color: .black.opacity(0.3), radius: 2, y: 1) + .contentTransition(.symbolEffect(.replace)) } + .animation(.easeInOut(duration: 0.15), value: model.snapshot.state) .frame(width: size, height: size) .shadow( color: BlurtBrand.greenOnDark.opacity(isRecording ? 0.35 + 0.45 * level : 0), @@ -164,7 +179,31 @@ struct MicKey: View { } } - private var glyph: String { isRecording ? "stop.fill" : "mic.fill" } + private var isNotice: Bool { + switch model.snapshot.state { + case .pasted, .copied, .error: true + case .idle, .connecting, .recording, .processing: false + } + } + + private var ringColor: Color? { + switch model.snapshot.state { + case .error: BlurtBrand.errorOrange + case .pasted, .copied: BlurtBrand.greenOnDark + case .idle, .connecting, .recording, .processing: nil + } + } + + private var glyph: String { + guard isReady else { return "mic.fill" } + switch model.snapshot.state { + case .recording: return "stop.fill" + case .pasted: return "checkmark" + case .copied: return "doc.on.clipboard" + case .error: return "exclamationmark" + case .idle, .connecting, .processing: return "mic.fill" + } + } } /// One ordinary key: a legend on a cap in the current palette; `dark` for the diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/StatusPill.swift b/App/BlurtiOS/BlurtKeyboard/Sources/StatusPill.swift deleted file mode 100644 index 9ea9e0f6..00000000 --- a/App/BlurtiOS/BlurtKeyboard/Sources/StatusPill.swift +++ /dev/null @@ -1,135 +0,0 @@ -import BlurtEngine -import SwiftUI - -/// The Mac's overlay pill, on the keyboard: an ink capsule with the orb fixed -/// at its left and, beside it, whatever the moment calls for — the live meter -/// while recording, a status word while waiting, the word alone for a notice. -/// One body for every state, the error included: the alarm is the orange -/// word, never a red capsule. Same inset (12), gap (8), rim and shadow as -/// `App/Blurt/Blurt/Overlay/OverlayView.swift`, at 36 pt instead of 28. -/// -/// Unlike the Mac's, this pill is on screen at rest, so it also has things to -/// say before a dictation: that Full Access is missing, that the app isn't -/// listening, and how to start. -struct StatusPill: View { - var model: KeyboardModel - /// Shorter resting words, for the slim bar's narrow pill. - var compact = false - @Environment(\.accessibilityReduceMotion) private var reduceMotion - - static let height: CGFloat = 36 - /// The Mac's disc-to-pill ratio (24 in 40). - static let orbDiameter: CGFloat = height * 0.6 - private static let inset: CGFloat = 12 - private static let spacing: CGFloat = 8 - - var body: some View { - content - .frame(maxWidth: .infinity) - .frame(height: Self.height) - .background(Capsule().fill(BlurtBrand.ink)) - // The rim is what draws the capsule's edge on a dark surface like the - // keyboard's own; the shadow carries it over light content. - .overlay(Capsule().strokeBorder(Color.white.opacity(0.12), lineWidth: 1)) - .compositingGroup() - .shadow(color: .black.opacity(0.25), radius: 10, y: 3) - .animation(reduceMotion ? nil : .easeInOut(duration: 0.15), value: model.snapshot.state) - .accessibilityElement(children: .ignore) - .accessibilityLabel(accessibilityLabel) - } - - @ViewBuilder private var content: some View { - if !model.hasFullAccess { - word("Allow Full Access", color: BlurtBrand.errorOrange) - } else if !model.isListening { - orbLine(compact ? "Tap to start" : "Tap the mic to start", working: false) - } else { - switch model.snapshot.state { - case .idle: orbLine(compact ? "Tap or hold" : "Tap or hold to talk", working: false) - case .connecting: orbLine("Connecting", working: true) - case .recording: - HStack(spacing: Self.spacing) { - BrandOrb(diameter: Self.orbDiameter, animated: !reduceMotion) - WaveformMeter(level: Float(model.snapshot.level), animated: !reduceMotion, color: BlurtBrand.greenOnDark) - } - .padding(.horizontal, Self.inset) - .transition(.opacity) - case .processing: orbLine("Transcribing", working: true) - case .pasted: word("Pasted") - case .copied: word("Copied") - case .error: word("Error", color: BlurtBrand.errorOrange) - } - } - } - - /// The shape both waits share, and the resting line: orb, then the word. - private func orbLine(_ text: String, working: Bool) -> some View { - HStack(spacing: Self.spacing) { - BrandOrb(diameter: Self.orbDiameter, animated: working && !reduceMotion) - StatusLineText(text) - Spacer(minLength: 0) - } - .padding(.horizontal, Self.inset) - .transition(.opacity) - } - - /// A notice: the word alone, centred. - private func word(_ text: String, color: Color = BlurtBrand.greenOnDark) -> some View { - StatusLineText(text, color: color) - .padding(.horizontal, Self.inset) - .transition(.opacity) - } - - private var accessibilityLabel: String { - guard model.hasFullAccess else { return "Blurt needs Full Access. Allow it in Settings, Keyboards." } - guard model.isListening else { return "Blurt isn't listening. Tap the mic to open Blurt." } - switch model.snapshot.state { - case .idle: return "Tap the mic to talk, or hold it." - case .connecting: return "Connecting to the microphone." - case .recording: return "Recording." - case .processing: return "Transcribing." - case .pasted: return "Your dictation was inserted." - case .copied: return "Your dictation was copied to the clipboard." - case .error: return model.snapshot.message ?? "Dictation failed." - } - } -} - -/// The Mac pill's live meter: a row of bars that fills the width it is given -/// and tracks the current level, with the engine's envelope and idle wave -/// (`MeterBarGeometry`, unit-tested there). The keyboard hears the level from -/// the app at ~12 Hz; the wave keeps the row alive between ticks. -struct WaveformMeter: View { - let level: Float - let animated: Bool - let color: Color - - var body: some View { - GeometryReader { geo in - let layout = MeterBarRow(availableSize: geo.size) - Group { - if animated { - TimelineView(.animation(minimumInterval: keyboardAnimationInterval)) { timeline in - bars(layout: layout, time: timeline.date.timeIntervalSinceReferenceDate) - } - } else { - bars(layout: layout, time: 0) - } - } - .frame(width: geo.size.width, height: geo.size.height) - } - } - - private func bars(layout: MeterBarRow, time: TimeInterval) -> some View { - HStack(spacing: MeterBarGeometry.barSpacing) { - ForEach(0.. some View { + HStack(spacing: MeterBarGeometry.barSpacing) { + ForEach(0.. Date: Thu, 24 Sep 2026 23:16:23 -0400 Subject: [PATCH 24/79] =?UTF-8?q?docs:=20DESIGN.md=20=E2=80=94=20no=20pill?= =?UTF-8?q?=20on=20the=20keyboard?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5.1 --- App/BlurtiOS/DESIGN.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/App/BlurtiOS/DESIGN.md b/App/BlurtiOS/DESIGN.md index 890436e6..231bb950 100644 --- a/App/BlurtiOS/DESIGN.md +++ b/App/BlurtiOS/DESIGN.md @@ -1,7 +1,7 @@ # Blurt for iPhone — design The iPhone app and its keyboard are the Mac app's design on a phone: the same -ink, the same two greens, the same orb, the same status pill. Nothing here was +ink, the same two greens, the same orb, the Mac pill's meter and ring. Nothing here was invented; every number traces to a Mac source file, and where the phone needed something the Mac has no equivalent for, this file says what was decided and why. The keyboard is done; the app's own screens are next (see the end). @@ -61,8 +61,8 @@ black legends; dark — surface `#2B2B2B`, keys `#6B6B6B`, modifiers On by default, with a toggle in Settings: a dictation starts the moment the keyboard comes up in a text field — the same synthetic tap through the engine's gate, so it latches and the next tap of the mic stops it. Only when -the app is listening and nothing is in flight; otherwise the pill says what to -do — the orb sits dimmed and the first tap opens Blurt. It fires on the keyboard's +the app is listening and nothing is in flight; otherwise the orb sits dimmed +and the first tap opens Blurt. It fires on the keyboard's appearance, not on every field change while it stays up. ## Tokens (`Shared/BlurtBrand.swift`) @@ -70,7 +70,7 @@ appearance, not on every field change while it stays up. | Token | Value | Use | | ----------------- | ----------- | ----------------------------------------------------------- | | `green` | `#01762F` | the wordmark green, light chrome (the app's accent) | -| `greenOnDark` | `#67AD82` | pill text and meter, the ring, anything green on ink | +| `greenOnDark` | `#67AD82` | the meter, the ring, anything green on ink | | `ink` | `#1D1B16` | the pill's body in every state; the keyboard's surface | | `errorOrange` | `#E67F36` | the error word — never a red body | | `key` | `#33302A` | an ordinary key on the ink surface (one step up) | From bbc3cff0b9f0be5e0ccdb321cd0c8495d307058f Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Thu, 24 Sep 2026 23:16:35 -0400 Subject: [PATCH 25/79] docs: DESIGN.md accessibility section matches the wordless keyboard Co-Authored-By: Claude Fable 5.1 --- App/BlurtiOS/DESIGN.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/App/BlurtiOS/DESIGN.md b/App/BlurtiOS/DESIGN.md index 231bb950..2d852737 100644 --- a/App/BlurtiOS/DESIGN.md +++ b/App/BlurtiOS/DESIGN.md @@ -71,7 +71,7 @@ appearance, not on every field change while it stays up. | ----------------- | ----------- | ----------------------------------------------------------- | | `green` | `#01762F` | the wordmark green, light chrome (the app's accent) | | `greenOnDark` | `#67AD82` | the meter, the ring, anything green on ink | -| `ink` | `#1D1B16` | the pill's body in every state; the keyboard's surface | +| `ink` | `#1D1B16` | the Mac pill's body; the keyboard's surface | | `errorOrange` | `#E67F36` | the error word — never a red body | | `key` | `#33302A` | an ordinary key on the ink surface (one step up) | | `keyDark` | `#26231E` | modifier keys: shift, delete, globe, return, 123, cancel | @@ -159,10 +159,10 @@ Access, and the app already owns the audio session). ## Accessibility -The pill is one element carrying the state's label (the Mac's wording where -the states match); the mic key is a button labelled Dictate / Stop dictation / -Start Blurt. Reduce Motion stops the ring and the meter's idle wave; heights -still follow the level. +The mic key is a button labelled Dictate / Stop dictation / Start Blurt, and +speaks the error message; the meters are hidden from VoiceOver. Reduce +Motion stops the ring and the meter's idle wave; heights still follow the +level. ## The app's screens (`BlurtiOS/Sources/`) From b471056624f48aeeffcf284af2b5ebfea3bfd7a6 Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Fri, 25 Sep 2026 11:16:38 -0400 Subject: [PATCH 26/79] Keyboard: the orb, centred and bare, spins then grows into the wave MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No glyph on the orb — the Mac's carries none. Tap it: the ring sweeps as the app's orb does while the mic comes up, then the circle grows sideways into a capsule holding the live wave for as long as you talk, and shrinks back with the ring sweeping while the words come. The panel's orb sits in the true centre of the space above the keys (the reserved meter row that pushed it up is gone); cancel moved to the corner so the capsule has room. Co-Authored-By: Claude Fable 5.1 --- .../BlurtKeyboard/Sources/KeyboardViews.swift | 119 +++++++++++------- .../BlurtKeyboard/Sources/VoiceBar.swift | 26 +--- App/BlurtiOS/DESIGN.md | 61 +++++---- 3 files changed, 107 insertions(+), 99 deletions(-) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift index 738cd829..cace889e 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift @@ -1,3 +1,4 @@ +import BlurtEngine import SwiftUI /// Picks the layout the user chose. All three share `VoiceBar`/`MicKey` and @@ -72,30 +73,15 @@ struct SlimBarView: View { } } -/// A big orb with cancel beside it while something is in flight, the meter -/// under it while recording, and one row of keys. 216 pt. +/// A big orb, centred, that grows into the wave while recording; cancel in +/// the corner while something is in flight; one row of keys. 216 pt. struct PanelView: View { var model: KeyboardModel - @Environment(\.accessibilityReduceMotion) private var reduceMotion var body: some View { VStack(spacing: 12) { Spacer(minLength: 0) - ZStack { - MicKey(model: model, size: 96) - if !model.isSettledState { - // Beside the orb, a hand's width off centre, rather than at the edge. - KeyCap(systemImage: "xmark", tint: BlurtBrand.errorOrange, dark: true) { model.cancel() } - .accessibilityLabel("Cancel dictation") - .offset(x: 96) - } - } - .frame(height: 96) - WaveformMeter(level: Float(model.snapshot.level), animated: !reduceMotion, color: BlurtBrand.greenOnDark) - .frame(width: 180, height: 24) - .opacity(model.snapshot.state == .recording ? 1 : 0) - .animation(.easeInOut(duration: 0.15), value: model.snapshot.state) - .accessibilityHidden(true) + MicKey(model: model, size: 96, expandedWidth: 260) Spacer(minLength: 0) HStack(spacing: KeyboardPalette.keyGap) { if model.needsGlobe { KeyCap(systemImage: "globe", dark: true) { model.globe() } } @@ -104,50 +90,67 @@ struct PanelView: View { KeyCap(systemImage: "return", dark: true) { model.newline() } } } + .overlay(alignment: .topTrailing) { + if !model.isSettledState { + KeyCap(systemImage: "xmark", tint: BlurtBrand.errorOrange, dark: true) { model.cancel() } + .accessibilityLabel("Cancel dictation") + } + } } } -/// The mic key is the brand orb, and it says everything without a word. -/// Finger down starts, finger up decides tap (latched) or hold (push-to-talk) -/// — `KeyboardModel` runs the engine's gate. The Mac's orb carries no glyph; -/// here it is a key, so a mic sits on it. Then: dimmed when Blurt isn't ready -/// (no Full Access, or the app isn't listening — the tap opens Blurt); the -/// ring sweeping while connecting and transcribing; a stop glyph, the sweep -/// and a glow with the voice level while recording; a check for a moment -/// after the words landed, a clipboard when they went to the clipboard -/// instead, an orange ring and an exclamation mark when something failed. -/// Each of those also has its haptic. +/// The mic key is the brand orb, and it says everything without a word or a +/// glyph. Finger down starts, finger up decides tap (latched) or hold +/// (push-to-talk) — `KeyboardModel` runs the engine's gate. What it does: +/// dimmed when Blurt isn't ready (no Full Access, or the app isn't listening; +/// the tap opens Blurt); on a tap the ring sweeps as the app's orb does while +/// the mic comes up; then the orb grows sideways into a capsule holding the +/// live wave for as long as you talk, glowing with your voice; on the stop it +/// shrinks back to the circle with the ring sweeping while the words come; +/// then a green ring for a moment when they landed, a clipboard on a green +/// ring when they went to the clipboard instead, an orange ring and an +/// exclamation mark when something failed. Each also has its haptic. struct MicKey: View { var model: KeyboardModel var size: CGFloat + /// How wide the orb grows while recording, to hold the wave. + var expandedWidth: CGFloat @State private var pressed = false @Environment(\.accessibilityReduceMotion) private var reduceMotion var body: some View { let level = CGFloat(model.snapshot.level) + let width = isRecording ? expandedWidth : size ZStack { - BrandOrb( - diameter: size, animated: isWorking && !reduceMotion, ringWidth: isWorking || isNotice ? 2 : 1, - ringColor: ringColor - ) - .saturation(isReady ? 1 : 0.35) - .opacity(isReady ? 1 : 0.8) - Image(systemName: glyph) - .font(.system(size: size * 0.36, weight: .semibold)) - .foregroundStyle(.white) - .shadow(color: .black.opacity(0.3), radius: 2, y: 1) - .contentTransition(.symbolEffect(.replace)) + Capsule() + .fill(BlurtBrand.orbGradient) + .overlay { ring } + .saturation(isReady ? 1 : 0.35) + .opacity(isReady ? 1 : 0.8) + if isRecording { + WaveformMeter(level: Float(model.snapshot.level), animated: !reduceMotion, color: .white.opacity(0.92)) + .frame(width: expandedWidth - size * 0.7, height: size * 0.5) + .transition(.opacity) + } + if let glyph { + Image(systemName: glyph) + .font(.system(size: size * 0.34, weight: .semibold)) + .foregroundStyle(.white) + .shadow(color: .black.opacity(0.3), radius: 2, y: 1) + .transition(.opacity) + } } - .animation(.easeInOut(duration: 0.15), value: model.snapshot.state) - .frame(width: size, height: size) + .frame(width: width, height: size) .shadow( color: BlurtBrand.greenOnDark.opacity(isRecording ? 0.35 + 0.45 * level : 0), radius: isRecording ? size * 0.1 + level * size * 0.25 : 0 ) .animation(.easeOut(duration: 0.08), value: level) + .animation(reduceMotion ? nil : .spring(duration: 0.35, bounce: 0.15), value: isRecording) + .animation(.easeInOut(duration: 0.15), value: model.snapshot.state) .scaleEffect(pressed ? 0.94 : 1) .animation(.easeOut(duration: 0.1), value: pressed) - .contentShape(Circle()) + .contentShape(Capsule()) .accessibilityLabel(isReady ? (isRecording ? "Stop dictation" : "Dictate") : "Start Blurt") .accessibilityAddTraits(.isButton) .simultaneousGesture( @@ -170,8 +173,29 @@ struct MicKey: View { ) } + /// The ring: the app orb's sweep (one turn per 1.6 s, engine geometry) + /// while the mic comes up and while the words come; still, and solid green + /// or orange, for a notice; still on the capsule while recording. + @ViewBuilder private var ring: some View { + let width: CGFloat = isWorking || isNotice ? 2 : 1 + if isWorking, !isRecording, !reduceMotion { + TimelineView(.animation(minimumInterval: keyboardAnimationInterval)) { timeline in + Capsule() + .strokeBorder(BlurtBrand.orbRingGradient, lineWidth: width) + .rotationEffect( + .degrees( + MeterBarGeometry.rotationDegrees( + time: timeline.date.timeIntervalSinceReferenceDate, period: BrandOrb.period))) + } + } else if let ringColor { + Capsule().strokeBorder(ringColor, lineWidth: width) + } else { + Capsule().strokeBorder(BlurtBrand.orbRingGradient, lineWidth: width) + } + } + private var isReady: Bool { model.hasFullAccess && model.isListening } - private var isRecording: Bool { model.snapshot.state == .recording } + private var isRecording: Bool { isReady && model.snapshot.state == .recording } private var isWorking: Bool { switch model.snapshot.state { case .connecting, .recording, .processing: isReady @@ -194,14 +218,13 @@ struct MicKey: View { } } - private var glyph: String { - guard isReady else { return "mic.fill" } + /// Only the two notices that need saying carry a glyph. + private var glyph: String? { + guard isReady else { return nil } switch model.snapshot.state { - case .recording: return "stop.fill" - case .pasted: return "checkmark" case .copied: return "doc.on.clipboard" case .error: return "exclamationmark" - case .idle, .connecting, .processing: return "mic.fill" + case .idle, .connecting, .recording, .processing, .pasted: return nil } } } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift index 28a852ab..1e93fc15 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift @@ -2,32 +2,18 @@ import BlurtEngine import SwiftUI /// The keyboard's voice row, and the only place voice lives: the orb, which -/// is the mic key — tap to start and stop, hold to talk — with the live meter -/// on either side of it while recording. No words: the orb's ring, glyph and -/// glow say what is happening, and the haptics confirm it (see `MicKey`). +/// is the mic key — tap to start and stop, hold to talk — growing into the +/// wave while recording. No words: the orb's ring, shape and glow say what is +/// happening, and the haptics confirm it (see `MicKey`). struct VoiceBar: View { var model: KeyboardModel - @Environment(\.accessibilityReduceMotion) private var reduceMotion static let height: CGFloat = 44 - private static let meterWidth: CGFloat = 110 var body: some View { - HStack(spacing: 14) { - meter - MicKey(model: model, size: 40) - meter - } - .frame(maxWidth: .infinity) - .frame(height: Self.height) - } - - private var meter: some View { - WaveformMeter(level: Float(model.snapshot.level), animated: !reduceMotion, color: BlurtBrand.greenOnDark) - .frame(width: Self.meterWidth, height: 28) - .opacity(model.snapshot.state == .recording ? 1 : 0) - .animation(.easeInOut(duration: 0.15), value: model.snapshot.state) - .accessibilityHidden(true) + MicKey(model: model, size: 40, expandedWidth: 200) + .frame(maxWidth: .infinity) + .frame(height: Self.height) } } diff --git a/App/BlurtiOS/DESIGN.md b/App/BlurtiOS/DESIGN.md index 2d852737..15dab746 100644 --- a/App/BlurtiOS/DESIGN.md +++ b/App/BlurtiOS/DESIGN.md @@ -92,27 +92,26 @@ everything else 16 pt medium. System font throughout. ## Components (`BlurtKeyboard/Sources/`) -**Voice bar** (`VoiceBar.swift`) — the only place voice lives, and it has -no words: the orb is the mic key, 40 pt in a 44 pt row where the system -keyboard puts its suggestion bar, with the live meter on either side of it -(110 × 28) while recording. The panel has the orb at 96 pt with the meter -under it; the slim bar has the bar between the globe and delete. State is -the orb's own: - -| State | Orb | Haptic | -| ---------------------------------- | ------------------------------------------------------------------- | ------------- | -| no Full Access / app not listening | dimmed (saturation 0.35, opacity 0.8), mic glyph; a tap opens Blurt | — | -| idle | mic glyph, ring still | — | -| connecting | ring 2 pt sweeping | — | -| recording | stop glyph, ring sweeping, green glow with the level, meter beside | medium impact | -| processing | ring sweeping | light impact | -| pasted | green solid ring, check glyph, 1.2 s | success | -| copied (no field) | green solid ring, clipboard glyph, 2 s | success | -| error | orange solid ring, exclamation glyph, 2 s; the message on VoiceOver | error | - -Glyph changes cross-fade (`symbolEffect(.replace)`); every state transition -0.15 s. VoiceOver keeps the words: Dictate / Stop dictation / Start Blurt on -the key, and the error message. +**Voice bar** (`VoiceBar.swift`) — the only place voice lives, and it has no +words and no glyph: the orb is the mic key, 40 pt in a 44 pt row where the +system keyboard puts its suggestion bar. The panel has it at 96 pt, centred +in the space above the keys; the slim bar has it between the globe and +delete. State is the orb's own shape and ring: + +| State | Orb | Haptic | +| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------- | +| no Full Access / app not listening | dimmed (saturation 0.35, opacity 0.8); a tap opens Blurt | — | +| idle | the circle, ring still | — | +| connecting | ring 2 pt sweeping, as the app's orb does (one turn per 1.6 s) | — | +| recording | the circle grows sideways into a capsule (200 wide in the bar, 260 in the panel; spring 0.35 s) holding the live wave in white, glowing green with the level | medium impact | +| processing | back to the circle, ring sweeping | light impact | +| pasted | green solid ring, 1.2 s | success | +| copied (no field) | green solid ring with a clipboard glyph, 2 s | success | +| error | orange solid ring with an exclamation mark, 2 s; the message on VoiceOver | error | + +Every transition 0.15 s; the grow and shrink a spring. VoiceOver keeps the +words: Dictate / Stop dictation / Start Blurt on the key, and the error +message. **Orb** (`BrandOrb.swift`) — the gradient disc with a hairline ring that sweeps one turn per 1.6 s while something is happening, still otherwise. The disc @@ -122,15 +121,15 @@ never moves. Under Reduce Motion the ring is drawn but holds still. count from the width, heights from `MeterBarRow` (envelope, gamma, idle wave). The app publishes the level at ~12 Hz; the wave keeps the row alive between. -**Mic key** (`MicKey` in `KeyboardViews.swift`) — the orb _is_ the key: -40 pt in the voice bar, 96 pt in the panel. The Mac's orb carries no glyph; a -key needs one, so a white `mic.fill` (0.36 × size) sits on it and changes -with the state as in the table above. Recording adds a green glow +**Mic key** (`MicKey` in `KeyboardViews.swift`) — the orb _is_ the key, one +capsule shape whose width is its height until recording. No glyph: the Mac's +orb carries none and neither does this. Recording adds a green glow (`greenOnDark` at 35–80 % with the level, radius 0.1–0.35 × size). Ring 2 pt while working or noticing, 1 pt otherwise. Pressed: scale 0.94, 0.1 s. Finger down / up drive the engine's `DictationKeyGate`, so a tap latches and a hold is push-to-talk exactly as on the Mac; a touch that travelled more -than 24 pt cancels instead (it was a swipe). +than 24 pt cancels instead (it was a swipe). Cancel is the orange × in the +panel's top-right corner while something is in flight. **Keys** (`KeyCap`, `LetterKey`) — 42 pt tall, radius 6, 6 % white hairline; `key` for letters and space, `keyDark` for modifiers; a key brightens 15 % @@ -140,11 +139,11 @@ while pressed rather than dimming. Top and bottom margin 8 (`KeyboardRootView`); 11 between rows and 3 at the sides (`KeyboardPalette`). -| Layout | Rows | Height | -| --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | -| `slimBar` | globe · voice bar · delete · return | 60 | -| `panel` | orb 96 (cancel beside it while in flight) · meter 24 · space row 42. A two-page carousel: a horizontal swipe in either direction, as often as you like, flips between the mic panel and the full keyboard; the page slides the way the finger went, the keyboard resizes with it, and it is back to the orb each time the keyboard appears. Keys ignore a touch that travelled more than 12 pt, the orb cancels one that travelled more than 24 pt. | 216, or 272 when flipped | -| `full` | voice bar 44 · three letter rows 42 · 123/globe/space/return 42; `8·2 + 44 + 4·11 + 4·42` | 272 | +| Layout | Rows | Height | +| --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | +| `slimBar` | globe · voice bar · delete · return | 60 | +| `panel` | orb 96, centred (cancel in the top-right corner while in flight) · space row 42. A two-page carousel: a horizontal swipe in either direction, as often as you like, flips between the mic panel and the full keyboard; the page slides the way the finger went, the keyboard resizes with it, and it is back to the orb each time the keyboard appears. Keys ignore a touch that travelled more than 12 pt, the orb cancels one that travelled more than 24 pt. | 216, or 272 when flipped | +| `full` | voice bar 44 · three letter rows 42 · 123/globe/space/return 42; `8·2 + 44 + 4·11 + 4·42` | 272 | The globe key appears only when iOS says another keyboard is installed (`needsInputModeSwitchKey`). From a5bc0da0db31638e8c23bff9c2ea71b5845962af Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Fri, 25 Sep 2026 12:04:54 -0400 Subject: [PATCH 27/79] Keyboard: quick-add a key term in seconds, without leaving the app you're in MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Select the misheard word (or nothing), tap the + beside the orb, and the voice bar becomes a field the keys type into, pre-filled with the selection; return or ✓ saves it to Blurt's key terms in the App Group, where the app reads it on the very next dictation, and replaces the misheard word in the text with what was typed. Key terms move from the app's own defaults to the App Group for this; Settings binds to the same place and shows the count. Also, with no setting to make: key clicks follow the phone's own keyboard setting, the return key says what the field asks (send, search, go…), number fields open on the symbols page, and the letter rows follow the phone's first language (AZERTY, QWERTZ, QWERTY). Co-Authored-By: Claude Fable 5.1 --- .../Sources/FullKeyboardView.swift | 8 +- .../BlurtKeyboard/Sources/KeyboardModel.swift | 148 +++++++++++++++++- .../Sources/KeyboardViewController.swift | 11 ++ .../BlurtKeyboard/Sources/KeyboardViews.swift | 1 + .../BlurtKeyboard/Sources/VoiceBar.swift | 108 ++++++++++++- .../Sources/DictationCoordinator.swift | 14 +- .../Sources/KeyboardGalleryView.swift | 4 +- .../BlurtiOS/Sources/SettingsView.swift | 8 +- App/BlurtiOS/DESIGN.md | 32 ++++ App/BlurtiOS/Shared/SharedState.swift | 53 ++++++- 10 files changed, 361 insertions(+), 26 deletions(-) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift b/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift index fc93ed55..3b2ad3fe 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift @@ -10,7 +10,6 @@ import SwiftUI struct FullKeyboardView: View { var model: KeyboardModel - private static let letters = ["qwertyuiop", "asdfghjkl", "zxcvbnm"] private static let symbols = ["1234567890", "-/:;()$&@\"", ".,?!'"] var body: some View { @@ -43,13 +42,16 @@ struct FullKeyboardView: View { KeyCap(title: model.symbolsPage ? "ABC" : "123", dark: true, width: sideWidth) { model.toggleSymbols() } if model.needsGlobe { KeyCap(systemImage: "globe", dark: true, width: sideWidth) { model.globe() } } KeyCap(title: "space", flexible: true) { model.space() } - KeyCap(systemImage: "return", dark: true, width: sideWidth * 2 + gap) { model.newline() } + KeyCap( + title: model.returnLabel, systemImage: model.returnLabel == nil ? "return" : nil, dark: true, + width: sideWidth * 2 + gap + ) { model.newline() } } } } } - private var rows: [String] { model.symbolsPage ? Self.symbols : Self.letters } + private var rows: [String] { model.symbolsPage ? Self.symbols : model.letterRows } private func label(for character: Character) -> String { let text = String(character) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift index 1df3b994..1fe28530 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift @@ -32,6 +32,16 @@ final class KeyboardModel { /// The direction of the last flip, so the pages slide the way the finger went. var flipTowardsLeading = false var snapshot = PhaseSnapshot.idle + /// The key term being typed on the keys, while the voice bar is a field; + /// nil otherwise. See `beginAddingTerm`. + var termDraft: String? + /// When the last term was saved, so the bar can show a check for a moment. + var termSavedAt: Date? + /// The field's own return key, as iOS labels it: "send", "search", "go"… + var returnLabel: String? + /// The letter rows for the user's first keyboard language (AZERTY for + /// French, QWERTZ for German and its neighbours, QWERTY otherwise). + var letterRows = LetterLayout.qwerty var isListening = false var hasFullAccess = false var needsGlobe = true @@ -46,14 +56,20 @@ final class KeyboardModel { @ObservationIgnored private var heartbeat: Task? @ObservationIgnored private var lastSpaceAt: ContinuousClock.Instant? @ObservationIgnored private var noticeDwell: Task? + @ObservationIgnored private var termDraftFromSelection: String? + @ObservationIgnored private var termNotice: Task? var proxy: (any UITextDocumentProxy)? { controller?.textDocumentProxy } /// One palette for now; themes are a later feature. var palette: KeyboardPalette { .blurt } - /// What is actually on screen: the panel's carousel may be showing its keys. - var effectiveLayout: KeyboardLayout { layout == .panel && panelShowsKeys ? .full : layout } + /// What is actually on screen: the panel's carousel may be showing its + /// keys, and typing a key term needs them whatever the layout. + var effectiveLayout: KeyboardLayout { + if termDraft != nil { return .full } + return layout == .panel && panelShowsKeys ? .full : layout + } /// Told when `effectiveLayout` changes, so the host can resize the keyboard. @ObservationIgnored var onLayoutChange: (() -> Void)? @@ -93,6 +109,8 @@ final class KeyboardModel { func appeared() { hasFullAccess = controller?.hasFullAccess ?? false needsGlobe = controller?.needsInputModeSwitchKey ?? true + letterRows = LetterLayout.forPreferredLanguages() + readField() updateShift() // Without Full Access the App Group is out of reach: the keyboard still // types, and says what it needs (see `KeyboardRootView`), but nothing below @@ -126,15 +144,47 @@ final class KeyboardModel { } /// The cursor moved or the text around it changed, including by our own - /// typing: re-read where the sentence stands. + /// typing: re-read where the sentence stands and what the field wants. func contextChanged() { + readField() updateShift() } + /// What the field asked for, the way the system keyboard honours it: the + /// return key's own word, and the symbols page first for a number field. + private func readField() { + returnLabel = proxy?.returnKeyType.flatMap(Self.returnLabel) + switch proxy?.keyboardType { + case .numberPad, .decimalPad, .phonePad, .numbersAndPunctuation, .asciiCapableNumberPad: symbolsPage = true + default: break + } + } + + private static func returnLabel(_ type: UIReturnKeyType) -> String? { + switch type { + case .go: "go" + case .google, .yahoo, .search: "search" + case .join: "join" + case .next: "next" + case .route: "route" + case .send: "send" + case .done: "done" + case .emergencyCall: "call" + case .continue: "continue" + case .default: nil + @unknown default: nil + } + } + /// Auto-capitalisation, as the system keyboard does it: shift comes on at /// the start of a sentence (or of every word, or always) according to what /// the field asks for, and goes off after one letter. private func updateShift() { + if let termDraft { + // A key term is usually a name: capitalised to start, then as typed. + shifted = termDraft.isEmpty + return + } guard let proxy else { return } let before = proxy.documentContextBeforeInput ?? "" switch proxy.autocapitalizationType ?? .sentences { @@ -307,17 +357,90 @@ final class KeyboardModel { extension KeyboardModel { func type(_ text: String) { + UIDevice.current.playInputClick() + if termDraft != nil { + termDraft?.append(text) + updateShift() + return + } proxy?.insertText(text) if shifted, !symbolsPage { shifted = false } } - func deleteBackward() { proxy?.deleteBackward() } + func deleteBackward() { + UIDevice.current.playInputClick() + if termDraft != nil { + _ = termDraft?.popLast() + updateShift() + return + } + proxy?.deleteBackward() + } + + func newline() { + UIDevice.current.playInputClick() + if termDraft != nil { + saveTerm() + return + } + proxy?.insertText("\n") + } - func newline() { proxy?.insertText("\n") } + // MARK: Quick-add key term + + /// The voice bar becomes a field and the keys type into it. If the user + /// had selected a word — the one Blurt got wrong — it is the starting + /// point, and saving also replaces it in the text with what they typed. + func beginAddingTerm() { + let selected = proxy?.selectedText?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" + let seed = selected.count <= 48 && !selected.contains("\n") ? selected : "" + termDraftFromSelection = seed.isEmpty ? nil : seed + termDraft = seed + updateShift() + onLayoutChange?() + } + + func cancelAddingTerm() { + termDraft = nil + termDraftFromSelection = nil + updateShift() + onLayoutChange?() + } + + /// Saves the term to Blurt's key terms — read on the very next dictation — + /// and, when it began as a selection, puts it into the text in place of the + /// misheard word. + func saveTerm() { + guard let draft = termDraft?.trimmingCharacters(in: .whitespacesAndNewlines), !draft.isEmpty else { + cancelAddingTerm() + return + } + SharedStore.addKeyTerm(draft) + if let original = termDraftFromSelection, original != draft, proxy?.selectedText == original { + proxy?.insertText(draft) + } + termDraft = nil + termDraftFromSelection = nil + if hasFullAccess { UINotificationFeedbackGenerator().notificationOccurred(.success) } + termSavedAt = Date() + termNotice?.cancel() + termNotice = Task { [weak self] in + try? await Task.sleep(for: .seconds(1.2)) + guard !Task.isCancelled else { return } + self?.termSavedAt = nil + } + updateShift() + onLayoutChange?() + } /// A space — or, tapped twice quickly after a word, the system keyboard's /// "." shortcut: the first space becomes a full stop and a space. func space() { + UIDevice.current.playInputClick() + if termDraft != nil { + if termDraft?.isEmpty == false, termDraft?.hasSuffix(" ") == false { termDraft?.append(" ") } + return + } let now = ContinuousClock.now let before = proxy?.documentContextBeforeInput ?? "" if let last = lastSpaceAt, now - last < .milliseconds(450), before.hasSuffix(" "), !before.hasSuffix(" "), @@ -358,3 +481,18 @@ extension KeyboardModel { } } } + +/// The three letter rows, by the language the user types in most. +nonisolated enum LetterLayout { + static let qwerty = ["qwertyuiop", "asdfghjkl", "zxcvbnm"] + static let azerty = ["azertyuiop", "qsdfghjklm", "wxcvbn"] + static let qwertz = ["qwertzuiop", "asdfghjkl", "yxcvbnm"] + + /// From the phone's own language order — no setting to make. + static func forPreferredLanguages(_ languages: [String] = Locale.preferredLanguages) -> [String] { + guard let first = languages.first?.lowercased() else { return qwerty } + if first.hasPrefix("fr") { return azerty } + if ["de", "cs", "sk", "hu"].contains(where: { first.hasPrefix($0) }) { return qwertz } + return qwerty + } +} diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift index 698c8c93..16bdaec4 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift @@ -10,6 +10,17 @@ final class KeyboardViewController: UIInputViewController { private let model = KeyboardModel() private var heightConstraint: NSLayoutConstraint? + /// The input view says it wants clicks, so `UIDevice.playInputClick()` on + /// each key press plays the system's keyboard click — and only if the + /// user has keyboard clicks on in Settings. Their setting, not ours. + private final class ClickingInputView: UIInputView, UIInputViewAudioFeedback { + var enableInputClicksWhenVisible: Bool { true } + } + + override func loadView() { + view = ClickingInputView(frame: .zero, inputViewStyle: .keyboard) + } + override func viewDidLoad() { super.viewDidLoad() model.attach(to: self) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift index cace889e..94a590b7 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift @@ -96,6 +96,7 @@ struct PanelView: View { .accessibilityLabel("Cancel dictation") } } + .overlay(alignment: .topLeading) { AddTermKey(model: model).padding(6) } } } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift index 1e93fc15..24cd5347 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift @@ -4,16 +4,118 @@ import SwiftUI /// The keyboard's voice row, and the only place voice lives: the orb, which /// is the mic key — tap to start and stop, hold to talk — growing into the /// wave while recording. No words: the orb's ring, shape and glow say what is -/// happening, and the haptics confirm it (see `MicKey`). +/// happening, and the haptics confirm it (see `MicKey`). Beside it, a small +/// + for the one thing people want the instant Blurt mishears a word: add it +/// as a key term. The bar then becomes the field the keys type into. struct VoiceBar: View { var model: KeyboardModel static let height: CGFloat = 44 var body: some View { - MicKey(model: model, size: 40, expandedWidth: 200) + ZStack { + if model.termDraft != nil { + TermField(model: model) + .transition(.opacity) + } else { + MicKey(model: model, size: 40, expandedWidth: 200) + .transition(.opacity) + } + } + .frame(maxWidth: .infinity) + .frame(height: Self.height) + .overlay(alignment: .trailing) { + if model.termDraft == nil { AddTermKey(model: model) } + } + .animation(.easeInOut(duration: 0.15), value: model.termDraft == nil) + } +} + +/// The small + beside the orb (and in the panel's corner): a new key term. +/// Shows a check for a moment after one was saved. +struct AddTermKey: View { + var model: KeyboardModel + @Environment(\.keyboardPalette) private var palette + + var body: some View { + Button { + model.beginAddingTerm() + } label: { + Image(systemName: model.termSavedAt == nil ? "plus" : "checkmark") + .font(.system(size: 15, weight: .semibold)) + .foregroundStyle(model.termSavedAt == nil ? palette.keyText.opacity(0.7) : BlurtBrand.greenOnDark) + .frame(width: 32, height: 32) + .background(Circle().fill(palette.keyDark)) + .overlay(Circle().strokeBorder(Color.white.opacity(0.08), lineWidth: 1)) + .contentTransition(.symbolEffect(.replace)) + } + .buttonStyle(KeyPressStyle()) + .accessibilityLabel("Add a key term") + .disabled(!model.hasFullAccess) + .opacity(model.hasFullAccess ? 1 : 0.4) + } +} + +/// The voice bar as a field: × to leave, what has been typed with a caret, +/// ✓ to save. Return saves too. +private struct TermField: View { + var model: KeyboardModel + @Environment(\.keyboardPalette) private var palette + + var body: some View { + HStack(spacing: 8) { + round("xmark", tint: palette.keyText.opacity(0.7)) { model.cancelAddingTerm() } + .accessibilityLabel("Cancel") + HStack(spacing: 0) { + if let draft = model.termDraft, !draft.isEmpty { + Text(draft).foregroundStyle(palette.keyText) + } else { + Text("New key term").foregroundStyle(palette.keyText.opacity(0.4)) + } + Caret() + Spacer(minLength: 0) + } + .font(.system(size: 17)) + .lineLimit(1) + .padding(.horizontal, 14) .frame(maxWidth: .infinity) - .frame(height: Self.height) + .frame(height: 36) + .background(Capsule().fill(palette.keyDark)) + .overlay(Capsule().strokeBorder(BlurtBrand.greenOnDark.opacity(0.6), lineWidth: 1)) + .accessibilityElement(children: .ignore) + .accessibilityLabel("Key term: \(model.termDraft ?? "")") + round("checkmark", tint: BlurtBrand.greenOnDark) { model.saveTerm() } + .accessibilityLabel("Save the key term") + .disabled(model.termDraft?.trimmingCharacters(in: .whitespaces).isEmpty ?? true) + } + .padding(.horizontal, 2) + } + + private func round(_ symbol: String, tint: Color, action: @escaping () -> Void) -> some View { + Button(action: action) { + Image(systemName: symbol) + .font(.system(size: 15, weight: .semibold)) + .foregroundStyle(tint) + .frame(width: 32, height: 32) + .background(Circle().fill(palette.keyDark)) + .overlay(Circle().strokeBorder(Color.white.opacity(0.08), lineWidth: 1)) + } + .buttonStyle(KeyPressStyle()) + } +} + +/// A blinking caret, as a text field's. +private struct Caret: View { + var body: some View { + TimelineView(.periodic(from: .now, by: 0.5)) { timeline in + let on = Int(timeline.date.timeIntervalSinceReferenceDate * 2) % 2 == 0 + RoundedRectangle(cornerRadius: 1) + .fill(BlurtBrand.greenOnDark) + .frame(width: 2, height: 20) + .opacity(on ? 1 : 0) + .padding(.leading, 1) + } + .accessibilityHidden(true) } } diff --git a/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift b/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift index 649dcb42..26717f8f 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift @@ -113,21 +113,15 @@ final class DictationCoordinator { lexiconNameCount = entries.filter(\.isName).count } - /// The user's typed key terms, then the contact names the keyboard read off - /// the phone, deduplicated case-insensitively. `KeytermsBoost` fits the list + /// The user's own key terms (from the App Group, where the keyboard adds + /// them on the spot), then the contact names the keyboard read off the + /// phone, deduplicated case-insensitively. `KeytermsBoost` fits the list /// to the request's caps (100 terms, 2048 bytes), first entries first, which /// is why the typed terms lead. nonisolated static func keyTerms() -> [String] { - let typed = UserDefaults.standard.string(forKey: KeyTermsStore.defaultsKey) ?? "" let names = (SharedStore.read([LexiconEntry].self, forKey: BlurtShared.Key.lexicon) ?? []) .filter(\.isName).map(\.documentText) - let candidates = typed.split(separator: ",").map { String($0).trimmingCharacters(in: .whitespacesAndNewlines) } - var seen = Set() - var terms: [String] = [] - for term in candidates + names where !term.isEmpty && seen.insert(term.lowercased()).inserted { - terms.append(term) - } - return terms + return KeyTermList.parse(KeyTermList.join(SharedStore.keyTerms + names)) } /// What the keyboard saw around the cursor when it sent the press. diff --git a/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift b/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift index 3ef1fbe1..3d4115c9 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift @@ -57,8 +57,10 @@ private static func model(layout: KeyboardLayout, state: String) -> KeyboardModel { let model = KeyboardModel() model.layout = layout - // `keys` shows the panel's carousel flipped to its keyboard page. + // `keys` shows the panel's carousel flipped to its keyboard page; + // `term` the voice bar as the key-term field, mid-typing. model.panelShowsKeys = state == "keys" + if state == "term" { model.termDraft = "Rizz" } model.hasFullAccess = state != "off" model.isListening = state != "off" && state != "start" let phase: PhaseSnapshot.State = diff --git a/App/BlurtiOS/BlurtiOS/Sources/SettingsView.swift b/App/BlurtiOS/BlurtiOS/Sources/SettingsView.swift index c7c58032..a33b991d 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/SettingsView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/SettingsView.swift @@ -11,7 +11,7 @@ struct SettingsView: View { @State private var autoDictate = SharedStore.autoDictate @State private var windowMinutes = SharedStore.windowMinutes @State private var showsKeyEntry = false - @AppStorage(KeyTermsStore.defaultsKey) private var keyTerms = "" + @AppStorage(SharedStore.keyTermsKey, store: SharedStore.defaults) private var keyTerms = "" @AppStorage(EnhancedTranscriptsStore.defaultsKey) private var enhancedTranscripts = EnhancedTranscriptsStore.defaultValue @@ -75,12 +75,14 @@ struct SettingsView: View { NavigationLink("Output styles") { StylesView() } TextField("Key terms, comma-separated", text: $keyTerms, axis: .vertical) .autocorrectionDisabled() + LabeledContent("Key terms", value: "\(KeyTermList.parse(keyTerms).count)") } header: { Text("Transcription") } footer: { Text( - "Enhanced transcripts clean up punctuation and wording. Key terms are names and jargon to spell right; " - + "\(coordinator.lexiconNameCount) contact names come along automatically.") + "Enhanced transcripts clean up punctuation and wording. Key terms are names and jargon to spell right — " + + "add one from the keyboard with the + beside the orb; \(coordinator.lexiconNameCount) contact names " + + "come along automatically.") } } diff --git a/App/BlurtiOS/DESIGN.md b/App/BlurtiOS/DESIGN.md index 15dab746..32d8a73b 100644 --- a/App/BlurtiOS/DESIGN.md +++ b/App/BlurtiOS/DESIGN.md @@ -56,6 +56,38 @@ black legends; dark — surface `#2B2B2B`, keys `#6B6B6B`, modifiers `#464646`, drop `#0D0D0D`, white legends; both follow the field's `keyboardAppearance`, else the app's style. +## Quick-add key term + +The most-asked-for thing: Blurt mishears a niche word, and the fix has to take +seconds, inside the app you're typing in, never a trip to Settings. + +1. Select the misheard word in your text (or select nothing). +2. Tap the small **+** beside the orb (top-right of the bar; top-left corner of + the panel). The bar becomes a field — × · what you type · ✓ — pre-filled + with the selection, and the keys type into it (the panel and slim bar flip + to the letter keys for it). Shift is on for the first letter. +3. Type the right spelling; return or ✓ saves. The term goes into Blurt's key + terms (`BlurtKeyTerms` in the App Group, `KeyTermList` rules: trimmed, + deduplicated case-insensitively) and rides `keyterms_prompt` on the very + next dictation. If it began as a selection and you changed it, the + misheard word in your text is replaced with what you typed. A success + haptic, and the + shows a check for 1.2 s. + +× or an empty save leaves the mode. The list itself is edited in Settings → +Transcription, which shows the count; the engine's caps (100 terms, 2048 +bytes) apply on the request, first terms first. + +## Adapting to the phone's own keyboard settings + +Nothing to configure: key clicks play only if the user has keyboard clicks +on (the input view adopts `UIInputViewAudioFeedback`; `playInputClick` on +every key); the return key says what the field asks — send, search, go, done, +next, join — with the glyph otherwise; a number, decimal or phone field opens +on the symbols page; capitalisation follows the field's +`autocapitalizationType`; the letter rows follow the phone's first language +(AZERTY for French, QWERTZ for German, Czech, Slovak and Hungarian, QWERTY +otherwise). + ## Hands-free On by default, with a toggle in Settings: a dictation starts the moment the diff --git a/App/BlurtiOS/Shared/SharedState.swift b/App/BlurtiOS/Shared/SharedState.swift index 979ef531..d1f89817 100644 --- a/App/BlurtiOS/Shared/SharedState.swift +++ b/App/BlurtiOS/Shared/SharedState.swift @@ -184,7 +184,10 @@ nonisolated struct LexiconEntry: Codable, Sendable, Hashable { /// keyboard writes from the main actor, the app's capture path reads from /// wherever the engine calls it. nonisolated enum SharedStore { - private static var defaults: UserDefaults { + /// The App Group's defaults — what both processes read and write. Falls + /// back to the process's own only where the group is out of reach (a + /// keyboard without Full Access), so nothing crashes; nothing is shared then. + static var defaults: UserDefaults { UserDefaults(suiteName: BlurtShared.appGroup) ?? .standard } @@ -246,6 +249,34 @@ nonisolated enum SharedStore { return Date().timeIntervalSince(appSeenAt ?? .distantPast) < appPresenceWindow } + // MARK: Key terms + + /// The user's own key terms — names and jargon the request should spell + /// right — under the engine's own key (`KeyTermsStore.defaultsKey`, + /// `BlurtKeyTerms`, comma-separated) but in the App Group, so the keyboard + /// can add one on the spot and the app reads it on the very next press. + static var keyTerms: [String] { + get { KeyTermList.parse(defaults.string(forKey: keyTermsKey) ?? "") } + set { defaults.set(KeyTermList.join(newValue), forKey: keyTermsKey) } + } + + /// `BlurtKeyTerms` — spelled out here rather than imported from the engine so + /// the keyboard, which links it too, and the app can't disagree. + static let keyTermsKey = "BlurtKeyTerms" + + /// Adds a term unless it is already there (case-insensitively). Returns + /// whether the list changed. + @discardableResult + static func addKeyTerm(_ term: String) -> Bool { + let trimmed = term.trimmingCharacters(in: .whitespacesAndNewlines) + guard !trimmed.isEmpty else { return false } + var terms = keyTerms + guard !terms.contains(where: { $0.caseInsensitiveCompare(trimmed) == .orderedSame }) else { return false } + terms.append(trimmed) + keyTerms = terms + return true + } + static var appSeenAt: Date? { get { defaults.object(forKey: BlurtShared.Key.appSeenAt) as? Date } set { defaults.set(newValue, forKey: BlurtShared.Key.appSeenAt) } @@ -307,3 +338,23 @@ nonisolated final class DarwinObserver: Sendable { } // MARK: - Brand + +/// The comma-separated key-term list, as the engine's `KeyTermsStore` reads +/// it: split, trimmed, emptied of blanks, deduplicated case-insensitively in +/// first-seen order. +nonisolated enum KeyTermList { + static func parse(_ raw: String) -> [String] { + var seen = Set() + var terms: [String] = [] + for piece in raw.split(separator: ",") { + let term = piece.trimmingCharacters(in: .whitespacesAndNewlines) + guard !term.isEmpty, seen.insert(term.lowercased()).inserted else { continue } + terms.append(term) + } + return terms + } + + static func join(_ terms: [String]) -> String { + terms.joined(separator: ", ") + } +} From b277b635339661fe8b6c0702246e2a4dc02418e5 Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Fri, 25 Sep 2026 12:05:18 -0400 Subject: [PATCH 28/79] Keyboard: split the model's typing half into its own file; return labels as a table Co-Authored-By: Claude Fable 5.1 --- .../Sources/KeyboardModel+Typing.swift | 147 ++++++++++++++++ .../BlurtKeyboard/Sources/KeyboardModel.swift | 165 +----------------- 2 files changed, 154 insertions(+), 158 deletions(-) create mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Typing.swift diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Typing.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Typing.swift new file mode 100644 index 00000000..ff9bf651 --- /dev/null +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Typing.swift @@ -0,0 +1,147 @@ +import BlurtEngine +import Foundation +import UIKit + +// MARK: - Typing and the app + +extension KeyboardModel { + func type(_ text: String) { + UIDevice.current.playInputClick() + if termDraft != nil { + termDraft?.append(text) + updateShift() + return + } + proxy?.insertText(text) + if shifted, !symbolsPage { shifted = false } + } + + func deleteBackward() { + UIDevice.current.playInputClick() + if termDraft != nil { + _ = termDraft?.popLast() + updateShift() + return + } + proxy?.deleteBackward() + } + + func newline() { + UIDevice.current.playInputClick() + if termDraft != nil { + saveTerm() + return + } + proxy?.insertText("\n") + } + + // MARK: Quick-add key term + + /// The voice bar becomes a field and the keys type into it. If the user + /// had selected a word — the one Blurt got wrong — it is the starting + /// point, and saving also replaces it in the text with what they typed. + func beginAddingTerm() { + let selected = proxy?.selectedText?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" + let seed = selected.count <= 48 && !selected.contains("\n") ? selected : "" + termDraftFromSelection = seed.isEmpty ? nil : seed + termDraft = seed + updateShift() + onLayoutChange?() + } + + func cancelAddingTerm() { + termDraft = nil + termDraftFromSelection = nil + updateShift() + onLayoutChange?() + } + + /// Saves the term to Blurt's key terms — read on the very next dictation — + /// and, when it began as a selection, puts it into the text in place of the + /// misheard word. + func saveTerm() { + guard let draft = termDraft?.trimmingCharacters(in: .whitespacesAndNewlines), !draft.isEmpty else { + cancelAddingTerm() + return + } + SharedStore.addKeyTerm(draft) + if let original = termDraftFromSelection, original != draft, proxy?.selectedText == original { + proxy?.insertText(draft) + } + termDraft = nil + termDraftFromSelection = nil + if hasFullAccess { UINotificationFeedbackGenerator().notificationOccurred(.success) } + termSavedAt = Date() + termNotice?.cancel() + termNotice = Task { [weak self] in + try? await Task.sleep(for: .seconds(1.2)) + guard !Task.isCancelled else { return } + self?.termSavedAt = nil + } + updateShift() + onLayoutChange?() + } + + /// A space — or, tapped twice quickly after a word, the system keyboard's + /// "." shortcut: the first space becomes a full stop and a space. + func space() { + UIDevice.current.playInputClick() + if termDraft != nil { + if termDraft?.isEmpty == false, termDraft?.hasSuffix(" ") == false { termDraft?.append(" ") } + return + } + let now = ContinuousClock.now + let before = proxy?.documentContextBeforeInput ?? "" + if let last = lastSpaceAt, now - last < .milliseconds(450), before.hasSuffix(" "), !before.hasSuffix(" "), + let previous = before.dropLast().last, previous.isLetter || previous.isNumber + { + proxy?.deleteBackward() + proxy?.insertText(". ") + lastSpaceAt = nil + } else { + proxy?.insertText(" ") + lastSpaceAt = now + } + updateShift() + } + + func toggleShift() { shifted.toggle() } + + func toggleSymbols() { symbolsPage.toggle() } + + func globe() { controller?.advanceToNextInputMode() } + + /// Brings the app forward to open the microphone — the one thing a keyboard + /// cannot do for itself. iOS gives extensions no `open(_:)`, so this walks the + /// responder chain to the application object and asks it, the way every + /// keyboard that opens its app does. + func openApp() { + guard let controller, + let url = URL(string: "\(BlurtShared.urlScheme)://\(BlurtShared.startHost)") + else { return } + let selector = sel_registerName("openURL:") + var responder: UIResponder? = controller + while let current = responder { + if current.responds(to: selector) { + _ = current.perform(selector, with: url) + return + } + responder = current.next + } + } +} + +/// The three letter rows, by the language the user types in most. +nonisolated enum LetterLayout { + static let qwerty = ["qwertyuiop", "asdfghjkl", "zxcvbnm"] + static let azerty = ["azertyuiop", "qsdfghjklm", "wxcvbn"] + static let qwertz = ["qwertzuiop", "asdfghjkl", "yxcvbnm"] + + /// From the phone's own language order — no setting to make. + static func forPreferredLanguages(_ languages: [String] = Locale.preferredLanguages) -> [String] { + guard let first = languages.first?.lowercased() else { return qwerty } + if first.hasPrefix("fr") { return azerty } + if ["de", "cs", "sk", "hu"].contains(where: { first.hasPrefix($0) }) { return qwertz } + return qwerty + } +} diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift index 1fe28530..7daad795 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift @@ -160,20 +160,13 @@ final class KeyboardModel { } } - private static func returnLabel(_ type: UIReturnKeyType) -> String? { - switch type { - case .go: "go" - case .google, .yahoo, .search: "search" - case .join: "join" - case .next: "next" - case .route: "route" - case .send: "send" - case .done: "done" - case .emergencyCall: "call" - case .continue: "continue" - case .default: nil - @unknown default: nil - } + /// iOS's own words for the return key, by the type the field asked for. + private static let returnLabels: [UIReturnKeyType: String] = [ + .go: "go", .google: "search", .yahoo: "search", .search: "search", .join: "join", .next: "next", + .route: "route", .send: "send", .done: "done", .emergencyCall: "call", .continue: "continue", + ] + + private static func returnLabel(_ type: UIReturnKeyType) -> String? { returnLabels[type] } } /// Auto-capitalisation, as the system keyboard does it: shift comes on at @@ -352,147 +345,3 @@ final class KeyboardModel { } } } - -// MARK: - Typing and the app - -extension KeyboardModel { - func type(_ text: String) { - UIDevice.current.playInputClick() - if termDraft != nil { - termDraft?.append(text) - updateShift() - return - } - proxy?.insertText(text) - if shifted, !symbolsPage { shifted = false } - } - - func deleteBackward() { - UIDevice.current.playInputClick() - if termDraft != nil { - _ = termDraft?.popLast() - updateShift() - return - } - proxy?.deleteBackward() - } - - func newline() { - UIDevice.current.playInputClick() - if termDraft != nil { - saveTerm() - return - } - proxy?.insertText("\n") - } - - // MARK: Quick-add key term - - /// The voice bar becomes a field and the keys type into it. If the user - /// had selected a word — the one Blurt got wrong — it is the starting - /// point, and saving also replaces it in the text with what they typed. - func beginAddingTerm() { - let selected = proxy?.selectedText?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - let seed = selected.count <= 48 && !selected.contains("\n") ? selected : "" - termDraftFromSelection = seed.isEmpty ? nil : seed - termDraft = seed - updateShift() - onLayoutChange?() - } - - func cancelAddingTerm() { - termDraft = nil - termDraftFromSelection = nil - updateShift() - onLayoutChange?() - } - - /// Saves the term to Blurt's key terms — read on the very next dictation — - /// and, when it began as a selection, puts it into the text in place of the - /// misheard word. - func saveTerm() { - guard let draft = termDraft?.trimmingCharacters(in: .whitespacesAndNewlines), !draft.isEmpty else { - cancelAddingTerm() - return - } - SharedStore.addKeyTerm(draft) - if let original = termDraftFromSelection, original != draft, proxy?.selectedText == original { - proxy?.insertText(draft) - } - termDraft = nil - termDraftFromSelection = nil - if hasFullAccess { UINotificationFeedbackGenerator().notificationOccurred(.success) } - termSavedAt = Date() - termNotice?.cancel() - termNotice = Task { [weak self] in - try? await Task.sleep(for: .seconds(1.2)) - guard !Task.isCancelled else { return } - self?.termSavedAt = nil - } - updateShift() - onLayoutChange?() - } - - /// A space — or, tapped twice quickly after a word, the system keyboard's - /// "." shortcut: the first space becomes a full stop and a space. - func space() { - UIDevice.current.playInputClick() - if termDraft != nil { - if termDraft?.isEmpty == false, termDraft?.hasSuffix(" ") == false { termDraft?.append(" ") } - return - } - let now = ContinuousClock.now - let before = proxy?.documentContextBeforeInput ?? "" - if let last = lastSpaceAt, now - last < .milliseconds(450), before.hasSuffix(" "), !before.hasSuffix(" "), - let previous = before.dropLast().last, previous.isLetter || previous.isNumber - { - proxy?.deleteBackward() - proxy?.insertText(". ") - lastSpaceAt = nil - } else { - proxy?.insertText(" ") - lastSpaceAt = now - } - updateShift() - } - - func toggleShift() { shifted.toggle() } - - func toggleSymbols() { symbolsPage.toggle() } - - func globe() { controller?.advanceToNextInputMode() } - - /// Brings the app forward to open the microphone — the one thing a keyboard - /// cannot do for itself. iOS gives extensions no `open(_:)`, so this walks the - /// responder chain to the application object and asks it, the way every - /// keyboard that opens its app does. - func openApp() { - guard let controller, - let url = URL(string: "\(BlurtShared.urlScheme)://\(BlurtShared.startHost)") - else { return } - let selector = sel_registerName("openURL:") - var responder: UIResponder? = controller - while let current = responder { - if current.responds(to: selector) { - _ = current.perform(selector, with: url) - return - } - responder = current.next - } - } -} - -/// The three letter rows, by the language the user types in most. -nonisolated enum LetterLayout { - static let qwerty = ["qwertyuiop", "asdfghjkl", "zxcvbnm"] - static let azerty = ["azertyuiop", "qsdfghjklm", "wxcvbn"] - static let qwertz = ["qwertzuiop", "asdfghjkl", "yxcvbnm"] - - /// From the phone's own language order — no setting to make. - static func forPreferredLanguages(_ languages: [String] = Locale.preferredLanguages) -> [String] { - guard let first = languages.first?.lowercased() else { return qwerty } - if first.hasPrefix("fr") { return azerty } - if ["de", "cs", "sk", "hu"].contains(where: { first.hasPrefix($0) }) { return qwertz } - return qwerty - } -} From 7e82235c53b58063bbdd94fd09c71a14d54ce3dc Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Fri, 25 Sep 2026 12:06:03 -0400 Subject: [PATCH 29/79] Keyboard: drop the brace the split left behind Co-Authored-By: Claude Fable 5.1 --- App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift index 7daad795..4b3ba165 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift @@ -167,7 +167,6 @@ final class KeyboardModel { ] private static func returnLabel(_ type: UIReturnKeyType) -> String? { returnLabels[type] } - } /// Auto-capitalisation, as the system keyboard does it: shift comes on at /// the start of a sentence (or of every word, or always) according to what From fed15b727c0edab904277b5fbb6a9345ccc0fa2b Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Fri, 25 Sep 2026 12:06:31 -0400 Subject: [PATCH 30/79] Keyboard: the model's typing half reaches its state across the file split Co-Authored-By: Claude Fable 5.1 --- .../BlurtKeyboard/Sources/KeyboardModel.swift | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift index 4b3ba165..60b248f0 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift @@ -48,16 +48,18 @@ final class KeyboardModel { var shifted = true var symbolsPage = false - @ObservationIgnored private weak var controller: UIInputViewController? + // Internal, not private: the typing half of this model lives in + // KeyboardModel+Typing.swift. + @ObservationIgnored weak var controller: UIInputViewController? @ObservationIgnored private var observers: [DarwinObserver] = [] @ObservationIgnored private var gate = DictationKeyGate() @ObservationIgnored private let clockStart = ContinuousClock.now @ObservationIgnored private var lastResultID: UUID? @ObservationIgnored private var heartbeat: Task? - @ObservationIgnored private var lastSpaceAt: ContinuousClock.Instant? + @ObservationIgnored var lastSpaceAt: ContinuousClock.Instant? @ObservationIgnored private var noticeDwell: Task? - @ObservationIgnored private var termDraftFromSelection: String? - @ObservationIgnored private var termNotice: Task? + @ObservationIgnored var termDraftFromSelection: String? + @ObservationIgnored var termNotice: Task? var proxy: (any UITextDocumentProxy)? { controller?.textDocumentProxy } @@ -171,7 +173,7 @@ final class KeyboardModel { /// Auto-capitalisation, as the system keyboard does it: shift comes on at /// the start of a sentence (or of every word, or always) according to what /// the field asks for, and goes off after one letter. - private func updateShift() { + func updateShift() { if let termDraft { // A key term is usually a name: capitalised to start, then as typed. shifted = termDraft.isEmpty From 484f068d7e388bf1c496374f66ce64050d3dcf29 Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Fri, 25 Sep 2026 12:08:18 -0400 Subject: [PATCH 31/79] App: share key terms with friends, and take theirs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Settings → Share key terms… sends the list as a .blurtterms file (JSON, a declared document type, so a tap on it in Messages offers Blurt) with the words as the message text for anyone without Blurt. Opening one — or a blurt://terms?add=… link — shows the list with every term ticked, and Add merges the chosen ones into Blurt's key terms without duplicates. Built for the group chat whose names and slang everyone's dictation should get right. Co-Authored-By: Claude Fable 5.1 --- .../Sources/DictationCoordinator.swift | 7 +++ App/BlurtiOS/BlurtiOS/Sources/HomeView.swift | 6 ++ .../BlurtiOS/Sources/ImportTermsView.swift | 50 +++++++++++++++ .../BlurtiOS/Sources/SettingsView.swift | 17 ++++- App/BlurtiOS/BlurtiOS/Sources/TermPack.swift | 63 +++++++++++++++++++ App/BlurtiOS/project.yml | 14 +++++ 6 files changed, 155 insertions(+), 2 deletions(-) create mode 100644 App/BlurtiOS/BlurtiOS/Sources/ImportTermsView.swift create mode 100644 App/BlurtiOS/BlurtiOS/Sources/TermPack.swift diff --git a/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift b/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift index 26717f8f..5ded1e8d 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift @@ -19,6 +19,9 @@ final class DictationCoordinator { /// How many contact names the keyboard last read off the phone — the key /// terms that come for free, so the home screen can say so. private(set) var lexiconNameCount = 0 + /// A shared key-term list the app was asked to open, until the user has + /// answered it (`ImportTermsView`). + var pendingTermPack: TermPack? @ObservationIgnored private let session: DictationSession @ObservationIgnored private let recents: AsyncStream @@ -83,6 +86,10 @@ final class DictationCoordinator { } func handle(_ url: URL) { + if let pack = TermPack.from(url) { + pendingTermPack = pack + return + } guard url.scheme == BlurtShared.urlScheme, url.host() == BlurtShared.startHost else { return } Task { await startListening() } } diff --git a/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift b/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift index 73de6f9d..d3e90f03 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift @@ -52,6 +52,12 @@ struct HomeView: View { } .sheet(isPresented: $showsKeyEntry) { KeyEntryView(apiKey: coordinator.apiKey) } .sheet(isPresented: $showsSettings) { SettingsView(coordinator: coordinator) } + .sheet( + isPresented: Binding( + get: { coordinator.pendingTermPack != nil }, set: { if !$0 { coordinator.pendingTermPack = nil } }) + ) { + if let pack = coordinator.pendingTermPack { ImportTermsView(pack: pack) } + } .onChange(of: scenePhase) { _, phase in if phase == .active { refreshStatus() } } diff --git a/App/BlurtiOS/BlurtiOS/Sources/ImportTermsView.swift b/App/BlurtiOS/BlurtiOS/Sources/ImportTermsView.swift new file mode 100644 index 00000000..fbe9bc9f --- /dev/null +++ b/App/BlurtiOS/BlurtiOS/Sources/ImportTermsView.swift @@ -0,0 +1,50 @@ +import SwiftUI + +/// "Add these key terms?" — what a shared list opens into. Every term is +/// ticked; untick any, and Add merges the rest into Blurt's key terms +/// without duplicates. +struct ImportTermsView: View { + let pack: TermPack + @Environment(\.dismiss) private var dismiss + @State private var excluded: Set = [] + + private var chosen: [String] { pack.terms.filter { !excluded.contains($0) } } + + var body: some View { + NavigationStack { + List { + Section { + ForEach(pack.terms, id: \.self) { term in + Toggle(term, isOn: binding(for: term)) + } + } header: { + Text(pack.from.map { "From \($0)" } ?? "Shared with you") + } footer: { + Text( + "They'll ride along with every dictation so Blurt spells them right. Terms you already have are skipped.") + } + } + .navigationTitle(pack.name) + .navigationBarTitleDisplayMode(.inline) + .toolbar { + ToolbarItem(placement: .cancellationAction) { Button("Not now") { dismiss() } } + ToolbarItem(placement: .confirmationAction) { + Button("Add \(chosen.count)") { + for term in chosen { SharedStore.addKeyTerm(term) } + dismiss() + } + .disabled(chosen.isEmpty) + } + } + } + .tint(BlurtBrand.accent) + } + + private func binding(for term: String) -> Binding { + Binding( + get: { !excluded.contains(term) }, + set: { on in + if on { excluded.remove(term) } else { excluded.insert(term) } + }) + } +} diff --git a/App/BlurtiOS/BlurtiOS/Sources/SettingsView.swift b/App/BlurtiOS/BlurtiOS/Sources/SettingsView.swift index a33b991d..93f7994d 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/SettingsView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/SettingsView.swift @@ -76,13 +76,21 @@ struct SettingsView: View { TextField("Key terms, comma-separated", text: $keyTerms, axis: .vertical) .autocorrectionDisabled() LabeledContent("Key terms", value: "\(KeyTermList.parse(keyTerms).count)") + if !KeyTermList.parse(keyTerms).isEmpty { + ShareLink( + item: termPack, subject: Text("Blurt key terms"), message: Text(termPack.plainText), + preview: SharePreview(termPack.name, icon: Image(systemName: "text.badge.plus")) + ) { + Label("Share key terms…", systemImage: "square.and.arrow.up") + } + } } header: { Text("Transcription") } footer: { Text( "Enhanced transcripts clean up punctuation and wording. Key terms are names and jargon to spell right — " - + "add one from the keyboard with the + beside the orb; \(coordinator.lexiconNameCount) contact names " - + "come along automatically.") + + "add one from the keyboard with the + beside the orb, share the list with a group chat so everyone's " + + "dictation gets the names right; \(coordinator.lexiconNameCount) contact names come along automatically.") } } @@ -103,6 +111,11 @@ struct SettingsView: View { } } + /// The whole list, for a friend: a `.blurtterms` file plus the words as text. + private var termPack: TermPack { + TermPack(name: "Key terms", from: nil, terms: KeyTermList.parse(keyTerms)) + } + private static var version: String { let short = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String ?? "?" let build = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as? String ?? "?" diff --git a/App/BlurtiOS/BlurtiOS/Sources/TermPack.swift b/App/BlurtiOS/BlurtiOS/Sources/TermPack.swift new file mode 100644 index 00000000..e1bbd25e --- /dev/null +++ b/App/BlurtiOS/BlurtiOS/Sources/TermPack.swift @@ -0,0 +1,63 @@ +import CoreTransferable +import Foundation +import UniformTypeIdentifiers + +extension UTType { + /// A shared list of Blurt key terms: JSON, `.blurtterms`, declared in + /// `project.yml` so a tap on one in Messages opens Blurt. + nonisolated static let blurtTerms = UTType(exportedAs: "dev.alex.blurt.terms", conformingTo: .json) +} + +/// A list of key terms on its way to a friend — a group chat's names and +/// slang, so everyone's dictation gets them right. Shared as a `.blurtterms` +/// file (the share sheet writes it), opened by a tap; also readable from a +/// `blurt://terms?add=a,b,c&name=…&from=…` link. +nonisolated struct TermPack: Codable, Hashable, Transferable { + var name: String + var from: String? + var terms: [String] + + static var transferRepresentation: some TransferRepresentation { + FileRepresentation(exportedContentType: .blurtTerms) { pack in + let url = FileManager.default.temporaryDirectory + .appendingPathComponent(pack.fileStem, isDirectory: false) + .appendingPathExtension("blurtterms") + let encoder = JSONEncoder() + encoder.outputFormatting = [.prettyPrinted, .sortedKeys] + try encoder.encode(pack).write(to: url, options: .atomic) + return SentTransferredFile(url) + } + } + + private var fileStem: String { + let stem = name.components(separatedBy: CharacterSet.alphanumerics.union(.whitespaces).inverted).joined() + .trimmingCharacters(in: .whitespaces) + return stem.isEmpty ? "Blurt key terms" : stem + } + + /// The list as plain text, for the message beside the file — a friend + /// without Blurt still gets the words. + var plainText: String { + let lead = from.map { "\($0)'s Blurt key terms" } ?? "Blurt key terms" + return "\(lead) (\(name)): \(KeyTermList.join(terms))" + } + + /// A pack from a file tapped in Messages or a `blurt://terms` link; nil for + /// anything else the app is asked to open. + static func from(_ url: URL) -> TermPack? { + if url.isFileURL { + guard url.pathExtension.lowercased() == "blurtterms", let data = try? Data(contentsOf: url), + var pack = try? JSONDecoder().decode(TermPack.self, from: data) + else { return nil } + pack.terms = KeyTermList.parse(KeyTermList.join(pack.terms)) + return pack.terms.isEmpty ? nil : pack + } + guard url.scheme == BlurtShared.urlScheme, url.host() == "terms", + let items = URLComponents(url: url, resolvingAgainstBaseURL: false)?.queryItems + else { return nil } + let value = { (name: String) in items.first { $0.name == name }?.value } + let terms = KeyTermList.parse(value("add") ?? "") + guard !terms.isEmpty else { return nil } + return TermPack(name: value("name") ?? "Shared key terms", from: value("from"), terms: terms) + } +} diff --git a/App/BlurtiOS/project.yml b/App/BlurtiOS/project.yml index 0301fe5d..33cfdeaf 100644 --- a/App/BlurtiOS/project.yml +++ b/App/BlurtiOS/project.yml @@ -97,6 +97,20 @@ targets: CFBundleURLTypes: - CFBundleURLName: dev.alex.blurt.ios CFBundleURLSchemes: [blurt] + # A shared key-term list (`.blurtterms`, JSON): declared so a tap on + # one in Messages offers Blurt, which opens it as an import. + CFBundleDocumentTypes: + - CFBundleTypeName: Blurt key terms + CFBundleTypeRole: Viewer + LSHandlerRank: Owner + LSItemContentTypes: [dev.alex.blurt.terms] + UTExportedTypeDeclarations: + - UTTypeIdentifier: dev.alex.blurt.terms + UTTypeDescription: Blurt key terms + UTTypeConformsTo: [public.json] + UTTypeTagSpecification: + public.filename-extension: [blurtterms] + public.mime-type: application/vnd.blurt.terms+json entitlements: path: BlurtiOS/BlurtiOS.entitlements properties: From 1bc0f7f172a849f77dc55ce93256af547bdd884b Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Fri, 25 Sep 2026 12:12:46 -0400 Subject: [PATCH 32/79] Keyboard: six curated themes, picked from live previews MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ink, Paper, Lavender, Mint, Midnight, Sunset — cut from the brand's own cloth, chosen Partiful-style from cards that draw the real keyboard small in each. A theme changes the colours and never the spacing, which stays the iPhone keyboard's own. The keyboard reads the choice from the App Group the next time it comes up; the gallery takes a theme id as its last argument. Co-Authored-By: Claude Fable 5.1 --- .../BlurtKeyboard/Sources/KeyboardModel.swift | 7 +- .../Sources/KeyboardPalette.swift | 66 ++++++++++++++--- .../Sources/KeyboardGalleryView.swift | 12 +++- .../BlurtiOS/Sources/SettingsView.swift | 5 ++ .../BlurtiOS/Sources/ThemePickerView.swift | 72 +++++++++++++++++++ App/BlurtiOS/DESIGN.md | 53 +++++++++----- App/BlurtiOS/Shared/SharedState.swift | 7 ++ 7 files changed, 191 insertions(+), 31 deletions(-) create mode 100644 App/BlurtiOS/BlurtiOS/Sources/ThemePickerView.swift diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift index 60b248f0..8533a4ea 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift @@ -63,8 +63,10 @@ final class KeyboardModel { var proxy: (any UITextDocumentProxy)? { controller?.textDocumentProxy } - /// One palette for now; themes are a later feature. - var palette: KeyboardPalette { .blurt } + /// The chosen theme's palette — or, for a preview, whatever it is told. + var palette: KeyboardPalette { paletteOverride ?? .named(themeID) } + var themeID = SharedStore.themeID + var paletteOverride: KeyboardPalette? /// What is actually on screen: the panel's carousel may be showing its /// keys, and typing a key term needs them whatever the layout. @@ -119,6 +121,7 @@ final class KeyboardModel { // can run. guard hasFullAccess else { return } layout = SharedStore.layout + themeID = SharedStore.themeID panelShowsKeys = false SharedStore.keyboardEverSeen = true refresh() diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift index d51f32ee..330688e7 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift @@ -1,11 +1,18 @@ import SwiftUI -/// The colors and spacing the keys draw with. The spacing is the iPhone -/// keyboard's own — 6 pt between keys, 11 pt between rows, 3 pt at the -/// edges, 5 pt corners, a 1 pt drop under every key — so nobody's fingers -/// are thrown off; the colours are Blurt's (`BlurtBrand`). One palette for -/// now; themes are a later feature, and this is the seam they plug into. -struct KeyboardPalette: Equatable { +/// The colors the keys draw with — a theme. Six of them, curated: Blurt's +/// ink, and five more cut from the same cloth (the orb's lavender and green, +/// a warm paper, a midnight, a sunset), each contemporary and fun and none of +/// them off-brand. People pick one in the app, Partiful-style, from live +/// previews; the spacing never changes (the iPhone keyboard's own — 6 pt +/// between keys, 11 between rows, 3 at the edges, 5 pt corners, a 1 pt drop +/// under every key), so a theme changes how the keyboard looks and never how +/// it types. +struct KeyboardPalette: Equatable, Identifiable { + let id: String + let name: String + /// One line for the picker. + let vibe: String var surface: Color var key: Color var keyDark: Color @@ -19,13 +26,56 @@ struct KeyboardPalette: Equatable { static let margin: CGFloat = 3 static let keyRadius: CGFloat = 5 - static let blurt = KeyboardPalette( + static let ink = KeyboardPalette( + id: "ink", name: "Ink", vibe: "Blurt's own", surface: BlurtBrand.ink, key: BlurtBrand.key, keyDark: BlurtBrand.keyDark, keyText: BlurtBrand.keyText, keyShadow: Color.black.opacity(0.45), popupFill: BlurtBrand.key) + + static let paper = KeyboardPalette( + id: "paper", name: "Paper", vibe: "Warm and light", + surface: Color(hex: 0xEBE8E8), key: .white, keyDark: Color(hex: 0xDEDBDB), keyText: BlurtBrand.ink, + keyShadow: Color.black.opacity(0.18), popupFill: .white) + + static let lavender = KeyboardPalette( + id: "lavender", name: "Lavender", vibe: "The orb's violet", + surface: Color(hex: 0x2C2557), key: Color(hex: 0x3F3777), keyDark: Color(hex: 0x352E68), + keyText: Color(hex: 0xF1EEFF), keyShadow: Color.black.opacity(0.4), popupFill: Color(hex: 0x3F3777)) + + static let mint = KeyboardPalette( + id: "mint", name: "Mint", vibe: "The orb's green", + surface: Color(hex: 0x10231B), key: Color(hex: 0x1E3F31), keyDark: Color(hex: 0x183429), + keyText: Color(hex: 0xE9F5EE), keyShadow: Color.black.opacity(0.4), popupFill: Color(hex: 0x1E3F31)) + + static let midnight = KeyboardPalette( + id: "midnight", name: "Midnight", vibe: "Deep blue-black", + surface: Color(hex: 0x0E1220), key: Color(hex: 0x1D2440), keyDark: Color(hex: 0x161B33), + keyText: Color(hex: 0xE8ECFF), keyShadow: Color.black.opacity(0.5), popupFill: Color(hex: 0x1D2440)) + + static let sunset = KeyboardPalette( + id: "sunset", name: "Sunset", vibe: "Warm and loud", + surface: Color(hex: 0x2B1912), key: Color(hex: 0x4B2B20), keyDark: Color(hex: 0x3B2119), + keyText: Color(hex: 0xFFEFE6), keyShadow: Color.black.opacity(0.4), popupFill: Color(hex: 0x4B2B20)) + + static let all: [KeyboardPalette] = [ink, paper, lavender, mint, midnight, sunset] + + /// The theme with this id, or Ink for one that no longer exists. + static func named(_ id: String) -> KeyboardPalette { + all.first { $0.id == id } ?? ink + } + + static func == (lhs: KeyboardPalette, rhs: KeyboardPalette) -> Bool { lhs.id == rhs.id } +} + +extension Color { + /// `Color(hex: 0x1D1B16)`. + init(hex: UInt32) { + self.init( + red: Double((hex >> 16) & 0xFF) / 255, green: Double((hex >> 8) & 0xFF) / 255, blue: Double(hex & 0xFF) / 255) + } } private struct KeyboardPaletteKey: EnvironmentKey { - static let defaultValue = KeyboardPalette.blurt + static let defaultValue = KeyboardPalette.ink } extension EnvironmentValues { diff --git a/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift b/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift index 3d4115c9..ecd76190 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift @@ -5,8 +5,10 @@ /// reference, and the way a screenshot of the keyboard is taken without /// tapping through Notes. Debug builds only, reached by launch argument: /// - /// -BlurtGallery [,…] + /// -BlurtGallery [,…] [theme] /// + /// The last word is a theme id (`ink`, `paper`, `lavender`, `mint`, + /// `midnight`, `sunset`); Ink when left out. /// where a state is `off` (no Full Access), `start` (app not listening), /// `idle`, `connecting`, `recording`, `processing`, `pasted`, `copied` or /// `error`. `scripts/ios-sim.sh` passes `BLURT_LAUNCH_ARGS` through, so @@ -49,14 +51,18 @@ guard let flag = arguments.firstIndex(of: "-BlurtGallery"), arguments.count > flag + 2, let layout = KeyboardLayout(rawValue: arguments[flag + 1]) else { return [] } + let theme = arguments.count > flag + 3 ? arguments[flag + 3] : "ink" return arguments[flag + 2].split(separator: ",").map { name in - Row(layout: layout, caption: "\(layout.rawValue) · \(name)", model: model(layout: layout, state: String(name))) + Row( + layout: layout, caption: "\(layout.rawValue) · \(name) · \(theme)", + model: model(layout: layout, state: String(name), theme: theme)) } } - private static func model(layout: KeyboardLayout, state: String) -> KeyboardModel { + private static func model(layout: KeyboardLayout, state: String, theme: String) -> KeyboardModel { let model = KeyboardModel() model.layout = layout + model.paletteOverride = .named(theme) // `keys` shows the panel's carousel flipped to its keyboard page; // `term` the voice bar as the key-term field, mid-typing. model.panelShowsKeys = state == "keys" diff --git a/App/BlurtiOS/BlurtiOS/Sources/SettingsView.swift b/App/BlurtiOS/BlurtiOS/Sources/SettingsView.swift index 93f7994d..9f6795e4 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/SettingsView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/SettingsView.swift @@ -42,6 +42,11 @@ struct SettingsView: View { .pickerStyle(.segmented) .onChange(of: layout) { _, value in SharedStore.layout = value } Text(layout.summary).font(.footnote).foregroundStyle(.secondary) + NavigationLink { + ThemePickerView() + } label: { + LabeledContent("Theme", value: KeyboardPalette.named(SharedStore.themeID).name) + } Toggle("Hands-free", isOn: $autoDictate) .onChange(of: autoDictate) { _, value in SharedStore.autoDictate = value } } header: { diff --git a/App/BlurtiOS/BlurtiOS/Sources/ThemePickerView.swift b/App/BlurtiOS/BlurtiOS/Sources/ThemePickerView.swift new file mode 100644 index 00000000..8f34bda8 --- /dev/null +++ b/App/BlurtiOS/BlurtiOS/Sources/ThemePickerView.swift @@ -0,0 +1,72 @@ +import SwiftUI + +/// Pick a keyboard theme from live previews, Partiful-style: a grid of cards, +/// each the real keyboard drawn small in that theme, the chosen one ringed +/// in the accent. The keyboard picks it up the next time it comes up. +struct ThemePickerView: View { + @State private var chosen = SharedStore.themeID + + private let columns = [GridItem(.flexible(), spacing: 14), GridItem(.flexible(), spacing: 14)] + + var body: some View { + ScrollView { + LazyVGrid(columns: columns, spacing: 14) { + ForEach(KeyboardPalette.all) { palette in + ThemeCard(palette: palette, chosen: palette.id == chosen) { + chosen = palette.id + SharedStore.themeID = palette.id + } + } + } + .padding(20) + } + .background(Color(uiColor: .systemGroupedBackground)) + .navigationTitle("Theme") + .navigationBarTitleDisplayMode(.inline) + } +} + +private struct ThemeCard: View { + let palette: KeyboardPalette + let chosen: Bool + let pick: () -> Void + + /// The preview keyboard is the full layout at a third of a phone's width. + private static let previewWidth: CGFloat = 393 + private static let scale: CGFloat = 0.42 + + var body: some View { + Button(action: pick) { + VStack(alignment: .leading, spacing: 10) { + KeyboardRootView(model: Self.model(for: palette)) + .frame(width: Self.previewWidth, height: KeyboardLayout.full.height) + .scaleEffect(Self.scale, anchor: .topLeading) + .frame(width: Self.previewWidth * Self.scale, height: KeyboardLayout.full.height * Self.scale) + .clipShape(RoundedRectangle(cornerRadius: 10)) + .allowsHitTesting(false) + VStack(alignment: .leading, spacing: 2) { + Text(palette.name).font(.headline) + Text(palette.vibe).font(.caption).foregroundStyle(.secondary) + } + } + .padding(12) + .frame(maxWidth: .infinity, alignment: .leading) + .card() + .overlay( + RoundedRectangle(cornerRadius: 16).strokeBorder(chosen ? BlurtBrand.accent : Color.clear, lineWidth: 2)) + } + .buttonStyle(.plain) + .accessibilityLabel(palette.name) + .accessibilityAddTraits(chosen ? .isSelected : []) + } + + private static func model(for palette: KeyboardPalette) -> KeyboardModel { + let model = KeyboardModel() + model.layout = .full + model.hasFullAccess = true + model.isListening = true + model.needsGlobe = true + model.paletteOverride = palette + return model + } +} diff --git a/App/BlurtiOS/DESIGN.md b/App/BlurtiOS/DESIGN.md index 32d8a73b..8cf26c47 100644 --- a/App/BlurtiOS/DESIGN.md +++ b/App/BlurtiOS/DESIGN.md @@ -30,31 +30,37 @@ Layouts: `slimBar`, `panel`, `full`. States: `off` (no Full Access), `start` gallery is `BlurtiOS/Sources/KeyboardGalleryView.swift`, debug builds only; the keyboard's sources are compiled into the app for it (`project.yml`). -## One look, the iPhone's spacing (`BlurtKeyboard/Sources/KeyboardPalette.swift`) +## Themes, at the iPhone's spacing (`BlurtKeyboard/Sources/KeyboardPalette.swift`) The keys sit exactly where the iPhone keyboard's do, so nobody's fingers are thrown off: 6 pt between keys, 11 pt between rows, 3 pt at the edges, 5 pt -corners, a 1 pt drop under every key. The colours are Blurt's — the ink -surface and the tokens below — in every appearance, for the reason the Mac -pill is: the keyboard floats over whichever app the user is typing in. -`KeyboardPalette` is one value for now and the seam themes plug into later. +corners, a 1 pt drop under every key. A theme changes how the keyboard looks +and never how it types. Six, curated, Partiful-style — pick from live +previews in Settings → Keyboard → Theme; the keyboard picks it up the next +time it comes up (`keyboardTheme` in the App Group): + +| Theme | Surface | Key | Modifier | Legend | Vibe | +| ---------- | --------- | --------- | --------- | --------- | ---------------- | +| `ink` | `#1D1B16` | `#33302A` | `#26231E` | `#F2EEE6` | Blurt's own | +| `paper` | `#EBE8E8` | white | `#DEDBDB` | `#1D1B16` | warm and light | +| `lavender` | `#2C2557` | `#3F3777` | `#352E68` | `#F1EEFF` | the orb's violet | +| `mint` | `#10231B` | `#1E3F31` | `#183429` | `#E9F5EE` | the orb's green | +| `midnight` | `#0E1220` | `#1D2440` | `#161B33` | `#E8ECFF` | deep blue-black | +| `sunset` | `#2B1912` | `#4B2B20` | `#3B2119` | `#FFEFE6` | warm and loud | + +The orb, the wave and the ring are the same in every theme. The picker +(`ThemePickerView`) draws the real full keyboard at 0.42 scale on each card. +The gallery's last argument is a theme id. The full layout follows the iPhone's geometry: ten letter keys across at one width (`(width − 9·gap) / 10`), the middle row centred, shift and delete taking what seven letters leave (twice the gap away from them), then 123 · -globe · space · mic · return, return two modifiers wide. Letters pop up -while pressed (a 32 pt copy 58 pt above the key, typed on release); shift -comes on by itself at the start of a sentence — or of every word, or always -— as the field's `autocapitalizationType` asks, and goes off after one -letter; a second space within 450 ms of the first, after a word, becomes -". ". Not yet: autocorrect and the suggestion bar. - -**Later: themes.** Users will pick their own. The iPhone keyboard's own -palettes are the first two to offer, and were measured for it: light — -surface `#D1D5DB`, letter keys white, modifiers `#ADB3BC`, drop `#898A8D`, -black legends; dark — surface `#2B2B2B`, keys `#6B6B6B`, modifiers -`#464646`, drop `#0D0D0D`, white legends; both follow the field's -`keyboardAppearance`, else the app's style. +globe · space · return, return two modifiers wide. Letters pop up while +pressed (a 32 pt copy 58 pt above the key, typed on release); shift comes on +by itself at the start of a sentence — or of every word, or always — as the +field's `autocapitalizationType` asks, and goes off after one letter; a +second space within 450 ms of the first, after a word, becomes ". ". Not +yet: autocorrect and the suggestion bar. ## Quick-add key term @@ -77,6 +83,17 @@ seconds, inside the app you're typing in, never a trip to Settings. Transcription, which shows the count; the engine's caps (100 terms, 2048 bytes) apply on the request, first terms first. +## Sharing key terms + +A group chat has names and slang everyone's dictation should get right, so a +list travels. Settings → Transcription → **Share key terms…** puts the list +in the share sheet as a `.blurtterms` file (JSON — `name`, `from`, `terms`; a +declared document type, `dev.alex.blurt.terms`) with the words as the +message text, so a friend without Blurt still gets them. A tap on the file +in Messages opens Blurt with "Add N key terms?": every term ticked, untick +any, Add merges the rest without duplicates. A `blurt://terms?add=a,b,c&name=…&from=…` +link does the same (`TermPack`, `ImportTermsView`). + ## Adapting to the phone's own keyboard settings Nothing to configure: key clicks play only if the user has keyboard clicks diff --git a/App/BlurtiOS/Shared/SharedState.swift b/App/BlurtiOS/Shared/SharedState.swift index d1f89817..68a542ab 100644 --- a/App/BlurtiOS/Shared/SharedState.swift +++ b/App/BlurtiOS/Shared/SharedState.swift @@ -21,6 +21,7 @@ nonisolated enum BlurtShared { nonisolated enum Key { static let layout = "keyboardLayout" static let autoDictate = "autoDictate" + static let theme = "keyboardTheme" static let listeningUntil = "listeningUntil" static let windowMinutes = "listeningWindowMinutes" static let phase = "phase" @@ -210,6 +211,12 @@ nonisolated enum SharedStore { set { defaults.set(newValue.rawValue, forKey: BlurtShared.Key.layout) } } + /// Which keyboard theme (`KeyboardPalette.id`); Ink until one is picked. + static var themeID: String { + get { defaults.string(forKey: BlurtShared.Key.theme) ?? "ink" } + set { defaults.set(newValue, forKey: BlurtShared.Key.theme) } + } + /// Hands-free: the keyboard starts a dictation the moment it appears in a /// text field, so there is nothing to tap before talking. On by default. static var autoDictate: Bool { From 16b06d5e5304ab8a90cc61a1bf82e34c17404b3e Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Fri, 25 Sep 2026 15:05:23 -0400 Subject: [PATCH 33/79] Keyboard: the term field claims typing that reaches the host field MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A hardware keyboard — an iPad's, a Bluetooth one, the simulator's Mac — types past the on-screen keys straight into the app's field. While the term field is open, a short run appended there right after where the cursor was is moved into the term and taken back out of the field. Co-Authored-By: Claude Fable 5.1 --- .../Sources/KeyboardModel+Typing.swift | 3 +++ .../BlurtKeyboard/Sources/KeyboardModel.swift | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Typing.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Typing.swift index ff9bf651..31d79d4a 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Typing.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Typing.swift @@ -44,6 +44,7 @@ extension KeyboardModel { let selected = proxy?.selectedText?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" let seed = selected.count <= 48 && !selected.contains("\n") ? selected : "" termDraftFromSelection = seed.isEmpty ? nil : seed + termHostBaseline = proxy?.documentContextBeforeInput ?? "" termDraft = seed updateShift() onLayoutChange?() @@ -52,6 +53,7 @@ extension KeyboardModel { func cancelAddingTerm() { termDraft = nil termDraftFromSelection = nil + termHostBaseline = nil updateShift() onLayoutChange?() } @@ -70,6 +72,7 @@ extension KeyboardModel { } termDraft = nil termDraftFromSelection = nil + termHostBaseline = nil if hasFullAccess { UINotificationFeedbackGenerator().notificationOccurred(.success) } termSavedAt = Date() termNotice?.cancel() diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift index 8533a4ea..fd73a74f 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift @@ -59,6 +59,10 @@ final class KeyboardModel { @ObservationIgnored var lastSpaceAt: ContinuousClock.Instant? @ObservationIgnored private var noticeDwell: Task? @ObservationIgnored var termDraftFromSelection: String? + /// The text before the cursor when the term field opened, so typing that + /// reaches the host field anyway (a hardware keyboard: an iPad's, a + /// Bluetooth one, the simulator's Mac) can be pulled into the term instead. + @ObservationIgnored var termHostBaseline: String? @ObservationIgnored var termNotice: Task? var proxy: (any UITextDocumentProxy)? { controller?.textDocumentProxy } @@ -152,9 +156,24 @@ final class KeyboardModel { /// typing: re-read where the sentence stands and what the field wants. func contextChanged() { readField() + claimHostTypingForTerm() updateShift() } + /// While the term field is open, characters that arrived in the host field + /// (a hardware keyboard types past the on-screen keys) belong to the term: + /// move them over and take them back out of the field. Only a short, + /// appended run right after where the cursor was; anything else is left. + private func claimHostTypingForTerm() { + guard termDraft != nil, let baseline = termHostBaseline, let proxy else { return } + let now = proxy.documentContextBeforeInput ?? "" + let delta = now.count - baseline.count + guard delta > 0, delta <= 8, now.dropLast(delta).hasSuffix(baseline.suffix(24)) else { return } + let typed = String(now.suffix(delta)) + for _ in 0.. Date: Fri, 25 Sep 2026 15:09:26 -0400 Subject: [PATCH 34/79] iOS: a unit-test target for the iPhone code, run locally and in CI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BlurtiOSTests, hosted by the app, Swift Testing: the App Group contract (the key-term list rules, stale snapshots, layout heights), the keyboard's rules against a fake text field (sentence start, the double space, the term field taking the keys and claiming hardware typing, a selection seeding and being replaced, return labels, letter rows), term packs, palettes — 22 tests. scripts/ios-test.sh runs them on whichever iPhone simulator is available; the ios-build job runs them after the build. Co-Authored-By: Claude Fable 5.1 --- .github/workflows/check.yml | 6 + AGENTS.md | 3 +- .../BlurtKeyboard/Sources/KeyboardModel.swift | 6 +- .../BlurtiOSTests/KeyboardModelTests.swift | 131 ++++++++++++++++++ .../BlurtiOSTests/SharedStateTests.swift | 87 ++++++++++++ .../BlurtiOSTests/TermPackTests.swift | 40 ++++++ App/BlurtiOS/README.md | 8 ++ App/BlurtiOS/project.yml | 25 +++- scripts/ios-test.sh | 31 +++++ 9 files changed, 333 insertions(+), 4 deletions(-) create mode 100644 App/BlurtiOS/BlurtiOSTests/KeyboardModelTests.swift create mode 100644 App/BlurtiOS/BlurtiOSTests/SharedStateTests.swift create mode 100644 App/BlurtiOS/BlurtiOSTests/TermPackTests.swift create mode 100755 scripts/ios-test.sh diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 719719ef..2bc0d39a 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -271,6 +271,12 @@ jobs: -derivedDataPath "$RUNNER_TEMP/BlurtiOS" \ CODE_SIGNING_ALLOWED=NO CODE_SIGN_IDENTITY="" \ build + - name: Run the iPhone unit tests + working-directory: blurt + # BlurtiOSTests, hosted by the app on whichever iPhone simulator the + # runner has (the script picks one). Pure logic: the App Group contract, + # the keyboard's rules, term packs. + run: BLURT_DERIVED_DATA="$RUNNER_TEMP/BlurtiOS" scripts/ios-test.sh # Always-runs summary job, so a *skipped* `check` can't be mistaken for a pass. # GitHub reports a skipped required check to branch protection as successful, so diff --git a/AGENTS.md b/AGENTS.md index 5be6a596..01f2d740 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -97,7 +97,8 @@ Tests/BlurtEngineTests/ Swift Testing suites; Stubs/ holds the seam doubles scripts/ check.sh, check-portability.sh, check-invariants.sh, bootstrap.sh, dev-build.sh, uitest.sh, leaks.sh, release*.sh, ios-typecheck.sh (the iPhone targets without an iOS SDK), - ios-sim.sh (build + run the iPhone app in the simulator) + ios-sim.sh (build + run the iPhone app in the simulator), + ios-test.sh (the iPhone unit tests, BlurtiOSTests, on a simulator) hand-run maintainer tools — no automated caller, invoked by a human, so "nothing references it" here does NOT mean dead code: screenshot.swift + beautify.swift (window imagery, capture diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift index fd73a74f..77bdd941 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift @@ -65,7 +65,9 @@ final class KeyboardModel { @ObservationIgnored var termHostBaseline: String? @ObservationIgnored var termNotice: Task? - var proxy: (any UITextDocumentProxy)? { controller?.textDocumentProxy } + /// The host's text field. Tests hand in a fake in place of a controller. + var proxy: (any UITextDocumentProxy)? { proxyOverride ?? controller?.textDocumentProxy } + @ObservationIgnored var proxyOverride: (any UITextDocumentProxy)? /// The chosen theme's palette — or, for a preview, whatever it is told. var palette: KeyboardPalette { paletteOverride ?? .named(themeID) } @@ -212,7 +214,7 @@ final class KeyboardModel { } } - private static func isSentenceStart(_ before: String) -> Bool { + static func isSentenceStart(_ before: String) -> Bool { let trimmed = before.reversed().drop { $0 == " " } guard let last = trimmed.first else { return true } return last == "\n" || ".?!".contains(last) diff --git a/App/BlurtiOS/BlurtiOSTests/KeyboardModelTests.swift b/App/BlurtiOS/BlurtiOSTests/KeyboardModelTests.swift new file mode 100644 index 00000000..e8641078 --- /dev/null +++ b/App/BlurtiOS/BlurtiOSTests/KeyboardModelTests.swift @@ -0,0 +1,131 @@ +import Foundation +import Testing +import UIKit + +@testable import BlurtiOS + +/// A host text field the model can type into, remembering what it did. +final class FakeProxy: NSObject, UITextDocumentProxy { + var before = "" + var after = "" + var selected: String? + var autocapitalizationType: UITextAutocapitalizationType = .sentences + var keyboardType: UIKeyboardType = .default + var returnKeyType: UIReturnKeyType = .default + + var documentContextBeforeInput: String? { before } + var documentContextAfterInput: String? { after } + var selectedText: String? { selected } + var documentInputMode: UITextInputMode? { nil } + var documentIdentifier: UUID { UUID() } + var hasText: Bool { !before.isEmpty || !after.isEmpty } + + func insertText(_ text: String) { + if let selected, !selected.isEmpty { + self.selected = nil + } + before += text + } + + func deleteBackward() { _ = before.popLast() } + func adjustTextPosition(byCharacterOffset offset: Int) {} + func setMarkedText(_ markedText: String, selectedRange: NSRange) {} + func unmarkText() {} +} + +@Suite("Keyboard model: typing rules") +struct KeyboardModelTypingTests { + private func model(before: String = "", selected: String? = nil) -> (KeyboardModel, FakeProxy) { + let proxy = FakeProxy() + proxy.before = before + proxy.selected = selected + let model = KeyboardModel() + model.proxyOverride = proxy + return (model, proxy) + } + + @Test("sentence start: empty, after a full stop and a space, after a newline") + func sentenceStart() { + #expect(KeyboardModel.isSentenceStart("")) + #expect(KeyboardModel.isSentenceStart("Hello. ")) + #expect(KeyboardModel.isSentenceStart("Hello?")) + #expect(KeyboardModel.isSentenceStart("Line\n")) + #expect(!KeyboardModel.isSentenceStart("Hello ")) + #expect(!KeyboardModel.isSentenceStart("Hello, ")) + } + + @Test("a letter goes to the field and lowers shift") + func typing() { + let (model, proxy) = model() + model.shifted = true + model.type("H") + #expect(proxy.before == "H") + #expect(!model.shifted) + } + + @Test("two quick spaces after a word become a full stop and a space") + func doubleSpace() { + let (model, proxy) = model(before: "hello") + model.space() + #expect(proxy.before == "hello ") + model.space() + #expect(proxy.before == "hello. ") + } + + @Test("two quick spaces after punctuation stay spaces") + func doubleSpaceAfterPunctuation() { + let (model, proxy) = model(before: "hello.") + model.space() + model.space() + #expect(proxy.before == "hello. ") + } + + @Test("the term field takes the keys instead of the host, and return saves nothing empty") + func termField() { + let (model, proxy) = model(before: "yo ") + model.beginAddingTerm() + #expect(model.termDraft == "") + #expect(model.effectiveLayout == .full) + model.type("R") + model.type("i") + model.space() + model.type("z") + model.deleteBackward() + #expect(model.termDraft == "Ri ") + #expect(proxy.before == "yo ") + model.cancelAddingTerm() + #expect(model.termDraft == nil) + } + + @Test("a selection seeds the term and is replaced on save") + func termFromSelection() { + let (model, proxy) = model(before: "he said ", selected: "riz") + model.beginAddingTerm() + #expect(model.termDraft == "riz") + model.type("z") + model.saveTerm() + #expect(model.termDraft == nil) + #expect(proxy.before == "he said rizz") + } + + @Test("typing that reached the host field while the term is open moves into the term") + func hardwareTypingClaimed() { + let (model, proxy) = model(before: "yo ") + model.beginAddingTerm() + proxy.before = "yo Ri" + model.contextChanged() + #expect(model.termDraft == "Ri") + #expect(proxy.before == "yo ") + } + + @Test("the return key wears the field's word") + func returnLabel() { + let (model, proxy) = model() + proxy.returnKeyType = .send + model.contextChanged() + #expect(model.returnLabel == "send") + proxy.returnKeyType = .default + model.contextChanged() + #expect(model.returnLabel == nil) + } +} diff --git a/App/BlurtiOS/BlurtiOSTests/SharedStateTests.swift b/App/BlurtiOS/BlurtiOSTests/SharedStateTests.swift new file mode 100644 index 00000000..36feaa35 --- /dev/null +++ b/App/BlurtiOS/BlurtiOSTests/SharedStateTests.swift @@ -0,0 +1,87 @@ +import Foundation +import Testing + +@testable import BlurtiOS + +@Suite("Key term list") +struct KeyTermListTests { + @Test("parse trims, drops blanks, and deduplicates case-insensitively in first-seen order") + func parse() { + #expect(KeyTermList.parse(" Rizz , skibidi,,RIZZ, Blurt ,") == ["Rizz", "skibidi", "Blurt"]) + } + + @Test("join is what parse reads back") + func roundTrip() { + let terms = ["Neil Bisht", "AssemblyAI", "rizz"] + #expect(KeyTermList.parse(KeyTermList.join(terms)) == terms) + } + + @Test("an empty or all-blank list is empty") + func empty() { + #expect(KeyTermList.parse("").isEmpty) + #expect(KeyTermList.parse(" , ,").isEmpty) + } +} + +@Suite("Phase snapshot staleness") +struct PhaseSnapshotTests { + private func snapshot(_ state: PhaseSnapshot.State, ageSeconds: TimeInterval) -> PhaseSnapshot { + PhaseSnapshot(state: state, message: nil, level: 0, at: Date().addingTimeInterval(-ageSeconds)) + } + + @Test("idle is never stale") + func idle() { + #expect(!snapshot(.idle, ageSeconds: 100_000).isStale) + } + + @Test("a notice is over after three seconds") + func notices() { + for state in [PhaseSnapshot.State.pasted, .copied, .error] { + #expect(!snapshot(state, ageSeconds: 2).isStale) + #expect(snapshot(state, ageSeconds: 4).isStale) + } + } + + @Test("an in-flight state outlives no dictation past 130 seconds") + func inFlight() { + for state in [PhaseSnapshot.State.connecting, .recording, .processing] { + #expect(!snapshot(state, ageSeconds: 120).isStale) + #expect(snapshot(state, ageSeconds: 131).isStale) + } + } + + @Test("the dwell matches the design: 1.2 s pasted, 2 s copied and error, none otherwise") + func dwell() { + #expect(snapshot(.pasted, ageSeconds: 0).noticeDwellSeconds == 1.2) + #expect(snapshot(.copied, ageSeconds: 0).noticeDwellSeconds == 2) + #expect(snapshot(.error, ageSeconds: 0).noticeDwellSeconds == 2) + #expect(snapshot(.recording, ageSeconds: 0).noticeDwellSeconds == nil) + } +} + +@Suite("Layouts and palettes") +struct LayoutTests { + @Test("heights are the rows at the iPhone keyboard's spacing (DESIGN.md)") + func heights() { + #expect(KeyboardLayout.slimBar.height == 60) + #expect(KeyboardLayout.panel.height == 216) + #expect(KeyboardLayout.full.height == 272) + } + + @Test("letter rows follow the phone's first language") + func letterRows() { + #expect(LetterLayout.forPreferredLanguages(["en-US", "fr-FR"]) == LetterLayout.qwerty) + #expect(LetterLayout.forPreferredLanguages(["fr-CA"]) == LetterLayout.azerty) + #expect(LetterLayout.forPreferredLanguages(["de-DE"]) == LetterLayout.qwertz) + #expect(LetterLayout.forPreferredLanguages(["cs"]) == LetterLayout.qwertz) + #expect(LetterLayout.forPreferredLanguages([]) == LetterLayout.qwerty) + } + + @Test("every theme has a distinct id and an unknown id falls back to Ink") + func palettes() { + let ids = KeyboardPalette.all.map(\.id) + #expect(Set(ids).count == ids.count) + #expect(KeyboardPalette.named("lavender").id == "lavender") + #expect(KeyboardPalette.named("nope").id == "ink") + } +} diff --git a/App/BlurtiOS/BlurtiOSTests/TermPackTests.swift b/App/BlurtiOS/BlurtiOSTests/TermPackTests.swift new file mode 100644 index 00000000..63ebddd2 --- /dev/null +++ b/App/BlurtiOS/BlurtiOSTests/TermPackTests.swift @@ -0,0 +1,40 @@ +import Foundation +import Testing + +@testable import BlurtiOS + +@Suite("Term packs") +struct TermPackTests { + @Test("a blurt://terms link carries terms, a name and a sender") + func link() throws { + let url = try #require(URL(string: "blurt://terms?add=Rizz,Skibidi,%20rizz%20&name=Group%20chat&from=Neil")) + let pack = try #require(TermPack.from(url)) + #expect(pack.terms == ["Rizz", "Skibidi"]) + #expect(pack.name == "Group chat") + #expect(pack.from == "Neil") + } + + @Test("a link with no terms, or any other link, is not a pack") + func notAPack() throws { + #expect(TermPack.from(try #require(URL(string: "blurt://terms?add="))) == nil) + #expect(TermPack.from(try #require(URL(string: "blurt://start"))) == nil) + #expect(TermPack.from(try #require(URL(string: "https://example.com/?add=a"))) == nil) + } + + @Test("a .blurtterms file round-trips and is parsed by the key-term rules") + func file() throws { + let pack = TermPack(name: "Chat", from: "Neil", terms: ["Rizz", "rizz", " Blurt "]) + let url = FileManager.default.temporaryDirectory.appendingPathComponent("test-\(UUID().uuidString).blurtterms") + try JSONEncoder().encode(pack).write(to: url) + defer { try? FileManager.default.removeItem(at: url) } + let read = try #require(TermPack.from(url)) + #expect(read.terms == ["Rizz", "Blurt"]) + #expect(read.name == "Chat") + } + + @Test("the plain text names the sender and lists the words") + func plainText() { + let pack = TermPack(name: "Chat", from: "Neil", terms: ["Rizz", "Blurt"]) + #expect(pack.plainText == "Neil's Blurt key terms (Chat): Rizz, Blurt") + } +} diff --git a/App/BlurtiOS/README.md b/App/BlurtiOS/README.md index 29b2d60b..21918e1d 100644 --- a/App/BlurtiOS/README.md +++ b/App/BlurtiOS/README.md @@ -56,6 +56,14 @@ the Apple Developer Agreement at developer.apple.com/account; a company-managed download. The archive lands in `~/Library/Application Support/com.robotsandpencils.xcodes/`; an 83 KB "xip" there is a saved error page, delete it and retry. +## Unit tests + +`scripts/ios-test.sh` runs `BlurtiOSTests` on a simulator (CI's `ios-build` job runs it after +the build): the iPhone code's pure logic — the App Group contract (`KeyTermList`, stale +snapshots, layouts), the keyboard's rules (sentence start, the double space, the term field, +return labels, letter rows) against a fake text field, term packs, palettes. The engine's own +tests stay `swift test`. Anything with a rule in `DESIGN.md` should have a test here. + ## Testing in the simulator Signing and the team don't matter here, and the App Group works, so the whole diff --git a/App/BlurtiOS/project.yml b/App/BlurtiOS/project.yml index 33cfdeaf..fcac4b32 100644 --- a/App/BlurtiOS/project.yml +++ b/App/BlurtiOS/project.yml @@ -155,12 +155,35 @@ targets: dependencies: - package: BlurtEngine product: BlurtEngine + # Unit tests for the iPhone code's pure logic — the App Group contract, the + # keyboard's rules, term packs — hosted by the app so `@testable import + # BlurtiOS` reaches everything (the keyboard's sources are compiled into the + # app too). Swift Testing; `scripts/ios-test.sh` runs them on a simulator. + BlurtiOSTests: + type: bundle.unit-test + platform: iOS + sources: + - path: BlurtiOSTests + dependencies: + - target: BlurtiOS + settings: + base: + PRODUCT_BUNDLE_IDENTIFIER: dev.alex.blurt.ios.tests + GENERATE_INFOPLIST_FILE: YES + SWIFT_TREAT_WARNINGS_AS_ERRORS: YES + SWIFT_DEFAULT_ACTOR_ISOLATION: MainActor # XcodeGen emits a scheme only where one is declared, and `xcodebuild -scheme` -# needs a shared one. Building the app builds the keyboard it embeds. +# needs a shared one. Building the app builds the keyboard it embeds; testing +# runs the unit tests against it. schemes: BlurtiOS: build: targets: BlurtiOS: all + BlurtiOSTests: [test] run: config: Debug + test: + config: Debug + targets: + - BlurtiOSTests diff --git a/scripts/ios-test.sh b/scripts/ios-test.sh new file mode 100755 index 00000000..e6138f8e --- /dev/null +++ b/scripts/ios-test.sh @@ -0,0 +1,31 @@ +#!/bin/bash +# Run the iPhone app's unit tests (BlurtiOSTests) on a simulator. +# +# scripts/ios-test.sh +# BLURT_SIM_DEVICE="iPhone 17" scripts/ios-test.sh +# +# Hosted by the app, signed ad hoc, which the simulator accepts. The engine's +# own tests are `swift test` (scripts/check.sh); these cover the iPhone code's +# pure logic — the App Group contract, the keyboard's rules, term packs. +set -euo pipefail + +REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" +DERIVED="${BLURT_DERIVED_DATA:-$REPO_ROOT/.build/ios-sim}" +# The named simulator, or whichever iPhone this Mac (or CI runner) has. +DEVICE="$(xcrun simctl list devices available -j | python3 -c ' +import json, sys +wanted = sys.argv[1] +names = [d["name"] for rt, devs in json.load(sys.stdin)["devices"].items() if "iOS" in rt for d in devs] +print(wanted if wanted in names else next((n for n in names if n.startswith("iPhone")), "")) +' "${BLURT_SIM_DEVICE:-iPhone 18 Pro}")" +if [ -z "$DEVICE" ]; then + echo "ios-test: no iPhone simulator available (xcrun simctl list devices)" >&2 + exit 1 +fi +echo "testing on $DEVICE" + +(cd "$REPO_ROOT/App/BlurtiOS" && xcodegen generate --quiet) +xcodebuild test -project "$REPO_ROOT/App/BlurtiOS/BlurtiOS.xcodeproj" -scheme BlurtiOS \ + -destination "platform=iOS Simulator,name=$DEVICE" -derivedDataPath "$DERIVED" \ + CODE_SIGN_STYLE=Manual CODE_SIGN_IDENTITY=- CODE_SIGNING_REQUIRED=NO DEVELOPMENT_TEAM= \ + -quiet From 7febbc3bbc906fc10d14cfe4afda8bfe24e3bad4 Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Fri, 25 Sep 2026 15:51:55 -0400 Subject: [PATCH 35/79] iOS foundation: the audit's fixes, the two-process contract pinned, tests and scans MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three adversarial audits (Swift 6 and extension correctness, product flows across the two processes, repo hygiene) — everything they found, fixed: - Results the keyboard never inserted are no longer lost: the app waits for the keyboard to take a result (3 s, polling), else copies it to the clipboard and says Copied, never a Pasted nobody saw; results are addressed to the keyboard instance last seen, so two live keyboards don't both insert. - A keyboard leaving the screen releases a latched recording and cancels anything earlier; a dictation started elsewhere latches the gate so one tap stops it; a press while transcribing is refused with a buzz; a press the app never answers is re-signalled once. - The term field claims only typing (text before the cursor grew, after it unchanged, nothing selected), never a cursor move; a selection with spaces around it keeps them; the mode leaves before the text is touched. - A swipe never dictates or types: the orb's press waits 90 ms, every key acts on release only if the finger didn't travel. - The microphone doesn't open without a key; a phone call closes the window; stop cancels the upload before closing the feed; capture starts and stops off the main actor, with the configuration committed on every path; the level feed reports only during an utterance. - Commands are consumed once, with a freshness window, and the press context no longer lingers in the group container; contact names with commas stay whole; the lexicon is parsed once per refresh, not per press. - Term packs are capped (64 KB, 100 terms, 80 characters) and an unreadable one is reported; Full Access is asked for on the keyboard itself; the denied-microphone path opens Settings; the theme row refreshes. - SharedStore has one defaults instance with a test override; the presence contract (heartbeats and windows) sits in one place; staleness constants are named; dead code and stale comments are gone; the model is split into its mic, phase and typing halves. - The keyboard never hears anything is invariant 14, pinned to AGENTS.md and the guardrails skill, with the platform scope of the two Mac-only rows spelled out; the invariants know the iOS tests; check.sh runs the Catalyst typecheck when it can and finds Xcode 27's test bundle; CI runs the iPhone tests and a periphery scan of the iPhone code; the scripts share ios-lib.sh. - BlurtiOSTests: 43 tests on a scratch App Group — the contract, the gate, results, the term field's guards, the feed, the layout arithmetic. - DESIGN.md carries the two-process contract and every number. Co-Authored-By: Claude Fable 5.1 --- .claude/settings.json | 3 + .claude/skills/check/SKILL.md | 8 + .claude/skills/project-guardrails/SKILL.md | 15 +- .github/workflows/check.yml | 32 +- AGENTS.md | 11 +- .../BlurtKeyboard/Sources/BrandOrb.swift | 14 +- .../Sources/FullKeyboardView.swift | 5 +- .../Sources/KeyboardModel+Mic.swift | 69 ++++ .../Sources/KeyboardModel+Phase.swift | 78 +++++ .../Sources/KeyboardModel+Typing.swift | 17 +- .../BlurtKeyboard/Sources/KeyboardModel.swift | 205 +++++------- .../Sources/KeyboardPalette.swift | 12 +- .../BlurtKeyboard/Sources/KeyboardViews.swift | 131 +++++--- .../BlurtKeyboard/Sources/VoiceBar.swift | 32 +- .../BlurtiOS/Sources/APIKeyModel.swift | 26 +- .../BlurtiOS/Sources/AudioSource.swift | 78 +++-- .../BlurtiOS/Sources/BlurtBrand+App.swift | 4 +- .../BlurtiOS/Sources/BlurtiOSApp.swift | 13 +- .../Sources/DictationCoordinator.swift | 106 ++++-- App/BlurtiOS/BlurtiOS/Sources/HomeView.swift | 2 +- .../BlurtiOS/Sources/ImportTermsView.swift | 3 +- .../Sources/KeyboardGalleryView.swift | 8 +- .../Sources/KeyboardRelayInjector.swift | 42 ++- .../BlurtiOS/Sources/ListeningSource.swift | 33 +- .../BlurtiOS/Sources/ListeningWindow.swift | 44 ++- .../Sources/SimulatorAudioSource.swift | 14 +- App/BlurtiOS/BlurtiOS/Sources/TermPack.swift | 48 ++- .../BlurtiOS/Sources/ThemePickerView.swift | 3 +- .../BlurtiOSTests/FeedAndLayoutTests.swift | 59 ++++ .../BlurtiOSTests/ProtocolTests.swift | 306 ++++++++++++++++++ App/BlurtiOS/BlurtiOSTests/TestSuite.swift | 21 ++ App/BlurtiOS/DESIGN.md | 98 ++++-- App/BlurtiOS/README.md | 13 +- App/BlurtiOS/Shared/BlurtBrand.swift | 10 +- App/BlurtiOS/Shared/DarwinObserver.swift | 30 ++ App/BlurtiOS/Shared/SharedState.swift | 105 +++--- App/BlurtiOS/project.yml | 8 +- scripts/check-invariants.sh | 14 +- scripts/check.sh | 14 +- scripts/ios-lib.sh | 41 +++ scripts/ios-sim.sh | 36 +-- scripts/ios-test.sh | 37 ++- scripts/ios-typecheck.sh | 12 +- 43 files changed, 1384 insertions(+), 476 deletions(-) create mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Mic.swift create mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Phase.swift create mode 100644 App/BlurtiOS/BlurtiOSTests/FeedAndLayoutTests.swift create mode 100644 App/BlurtiOS/BlurtiOSTests/ProtocolTests.swift create mode 100644 App/BlurtiOS/BlurtiOSTests/TestSuite.swift create mode 100644 App/BlurtiOS/Shared/DarwinObserver.swift create mode 100755 scripts/ios-lib.sh diff --git a/.claude/settings.json b/.claude/settings.json index ad55d8c9..4f1d1d5d 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -22,6 +22,9 @@ "Bash(scripts/check.sh --portable)", "Bash(./scripts/check.sh --portable)", "Bash(scripts/dev-build.sh)", + "Bash(scripts/ios-sim.sh*)", + "Bash(scripts/ios-test.sh*)", + "Bash(scripts/ios-typecheck.sh*)", "Bash(prettier *)", "Bash(actionlint)", "Bash(actionlint *)", diff --git a/.claude/skills/check/SKILL.md b/.claude/skills/check/SKILL.md index 26ce09b7..11415a39 100644 --- a/.claude/skills/check/SKILL.md +++ b/.claude/skills/check/SKILL.md @@ -123,3 +123,11 @@ hides every lint finding behind it — expect to fix a batch, not a queue. missing tool. A local run that ends `ok (UI suite + leak scan NOT run …)` is green for everything it covered — just don't claim the integration suite passed. That answer comes from `check.yml` on the PR. + +## The iPhone app + +`check.sh` covers `App/BlurtiOS` only by the dependency guard, the invariants and the linters. +Its build and tests run in CI's `ios-build` job (the authority). Locally: `scripts/ios-typecheck.sh` +typechecks both iPhone targets on a Mac with only the Command Line Tools (run by `check.sh` when +the SDK carries the Mac Catalyst frameworks), `scripts/ios-test.sh` runs `BlurtiOSTests` on a +simulator when Xcode is installed, and `scripts/ios-sim.sh` builds and launches the app there. diff --git a/.claude/skills/project-guardrails/SKILL.md b/.claude/skills/project-guardrails/SKILL.md index 56c3c9b0..0ef1a7c9 100644 --- a/.claude/skills/project-guardrails/SKILL.md +++ b/.claude/skills/project-guardrails/SKILL.md @@ -37,7 +37,7 @@ genuinely correct, and reaching for it means it's time to stop and ask. a second time inside the capture lock and held a duplicate of the whole utterance (~3.7 MB at the cap) until release. Don't reintroduce a buffered copy "just in case" — there is no retry-from-buffer path, by design. -- **Don't pre-open the mic to make presses feel faster.** `MicCapture.warmUp()` +- **(macOS shell) Don't pre-open the mic to make presses feel faster.** `MicCapture.warmUp()` is stateless on purpose — build a session, drop it — and there is no warm or prepared recorder to reuse. Measured on hardware: building a session (or the retired `prepareToRecord()`) leaves the device closed and costs ~15 ms, while @@ -125,7 +125,7 @@ only one of stt_prompt or prompt; they are the same field`, before the audio is default does not describe the behaviour. Note the plural is the documented spelling, but the singular `language_code` is accepted too (a 200, not an unknown-key 400), so both are live and `KeytermsWireTests` pins both absent. -- **Injection is always a clipboard paste** (save → write → ⌘V → settle → +- **(macOS shell) Injection is always a clipboard paste** (save → write → ⌘V → settle → restore), degrading to "left it on the clipboard" when the target is lost. No keystroke-by-keystroke typing path, no length threshold. @@ -176,3 +176,14 @@ only one of stt_prompt or prompt; they are the same field`, before the audio is hardened runtime and a **secure timestamp** (`--options runtime --timestamp`), or notarization rejects the build. `release-build.sh` re-signs frameworks for this — don't remove it. + +## iPhone (App/BlurtiOS) + +- **The keyboard never hears anything.** iOS lets no keyboard use the microphone; the app + listens and transcribes, the keyboard is a remote control over the App Group that inserts + the words. No `AVFoundation` in `BlurtKeyboard/` or `Shared/` (mechanized). +- The app's microphone is a _listening window_, opened once while the app is in front and + kept open, not a per-press capture — the two rows marked "(macOS shell)" above do not apply. +- Insertion is the keyboard's `textDocumentProxy`; the clipboard is only the fallback when no + keyboard is there to take the words, and the phase then says "Copied", never "Pasted". +- The full list, with every number, is `App/BlurtiOS/DESIGN.md`. diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 2bc0d39a..78c1389c 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -260,23 +260,25 @@ jobs: # a second before every build, so it can never go stale against its yml. run: xcodegen generate --quiet - - name: Build the iPhone app and its keyboard + - name: Build the iPhone app and its keyboard, and run its unit tests working-directory: blurt - # The app embeds the keyboard, so one scheme builds both. Signing is off: - # a simulator build needs no identity, and the App Group entitlement is - # not checked without one. - run: | - xcodebuild -project App/BlurtiOS/BlurtiOS.xcodeproj -scheme BlurtiOS \ - -destination 'generic/platform=iOS Simulator' \ - -derivedDataPath "$RUNNER_TEMP/BlurtiOS" \ - CODE_SIGNING_ALLOWED=NO CODE_SIGN_IDENTITY="" \ - build - - name: Run the iPhone unit tests - working-directory: blurt - # BlurtiOSTests, hosted by the app on whichever iPhone simulator the - # runner has (the script picks one). Pure logic: the App Group contract, - # the keyboard's rules, term packs. + # One scheme builds the app with the keyboard it embeds and runs + # BlurtiOSTests against it, on whichever iPhone simulator the runner has + # (scripts/ios-lib.sh picks). Ad hoc signing: the simulator accepts it + # and, unlike no signing, it embeds the App Group entitlement. run: BLURT_DERIVED_DATA="$RUNNER_TEMP/BlurtiOS" scripts/ios-test.sh + - name: Scan the iPhone app for unused code + working-directory: blurt + # periphery over the iOS project only — the Mac scan in check.sh can't + # see it. `--retain-public`: the engine's public API is used by the Mac + # app this scan can't see either, and the engine's own findings are + # excluded from the report, so only the iPhone code's dead declarations + # are reported. + run: | + brew install periphery + periphery scan --project App/BlurtiOS/BlurtiOS.xcodeproj --schemes BlurtiOS \ + --retain-public --retain-unused-protocol-func-params \ + --report-exclude 'Sources/**' --strict --quiet # Always-runs summary job, so a *skipped* `check` can't be mistaken for a pass. # GitHub reports a skipped required check to branch protection as successful, so diff --git a/AGENTS.md b/AGENTS.md index 01f2d740..31bebb65 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -69,7 +69,8 @@ Sources/BlurtEngine/ the engine (dependency-free Swift package) (macOS only); +Pure, the decisions that need no AX call Hotkey/ TriggerKey(+Store), DictationKeyGate, DictationKeyRouter Injection/ InsertionSeparator (the spacing rule, every platform); KeyInjector - (clipboard paste) + SystemClipboard (macOS only) + (clipboard paste) + SystemClipboard (macOS only); on iOS the + keyboard inserts through its textDocumentProxy (KeyboardRelayInjector) Permissions/ PermissionStatus + SetupReadiness (every platform); PermissionsChecker (mic + Accessibility), PermissionsReset, SigningIdentity (macOS only) @@ -110,8 +111,9 @@ evals/ offline decision support — the repo's only Python dictation-prompt/ DSPy harness for tuning the dictation API's cleanup instruction; check.sh lints (ruff), format-checks (ruff format), and tests it ruff.toml ruff config for the above — the repo's only Python config -.github/workflows/ check.yml (the gate, macos-26; its ios-build job compiles - the engine for the iOS simulator), +.github/workflows/ check.yml (the gate, macos-26; its ios-build job builds the engine for the + iOS simulator, then the iPhone app with its keyboard, and runs + BlurtiOSTests on a simulator) release-bump.yml (version bump) + release.yml (sign + publish), codeql.yml .claude/ Claude Code hooks, skills, subagents (see CLAUDE.md) @@ -389,6 +391,9 @@ rule along with the row. | Redirect the post-build install away from `/Applications` | TCC won't register apps in DerivedData/`/tmp`, so permission toggles never appear. | | Touch the real Keychain in tests | `APIKeyStore` is the production item — a test that writes it triggers Keychain prompts and corrupts the real item's ACL. Use an isolated service (see `KeychainStoreTests`) or `InMemoryAPIKeyStore`. | | Add backwards-compat shims for removed types | Deleted types stay deleted — no deprecated re-exports. | +| Give the keyboard extension a microphone or any audio type | iOS lets no keyboard use the microphone, and the design keeps every audio type out of it: the app listens and transcribes over its always-on capture, the keyboard is a remote control that inserts the words (`KeyboardRelayInjector`). An `AVFoundation` import in `App/BlurtiOS/BlurtKeyboard` or `Shared` is that decision being reversed by accident. | + +**Platform scope.** Two rows above are the Mac shell's, not the iPhone's, and the iPhone app diverges from them on purpose: "no warm recorder" — on iOS the app keeps the microphone open for a listening window (`App/BlurtiOS/BlurtiOS/Sources/AudioSource.swift`), because iOS refuses to open it from the background and the keyboard, which is where a dictation starts, is in the background of whatever app the user is typing in; and "injection is always a clipboard paste" — on iOS the keyboard inserts through its `textDocumentProxy`, and the clipboard is only the degradation when no keyboard is there to take the words. Neither changes the engine: `MicCapture` and `KeyInjector` stay as they are and are macOS-only; the iOS app supplies its own `MicCaptureProtocol` and `InjectorProtocol` conformances. `App/BlurtiOS/DESIGN.md` is the iPhone's own list. Release-side invariants (hardened runtime and a secure timestamp on every nested mach-o and embedded framework, or notarization rejects the build; roll-forward-only for a bad release) live in diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/BrandOrb.swift b/App/BlurtiOS/BlurtKeyboard/Sources/BrandOrb.swift index 605ae1fc..2d37603f 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/BrandOrb.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/BrandOrb.swift @@ -12,16 +12,14 @@ let keyboardAnimationInterval = MicCapture.meterIntervalSeconds /// is happening. It spins rather than pulses — a pulse says "alive", a sweep /// says "working, and still going" — and the disc underneath never moves. /// -/// Sized by the caller, because the keyboard draws it at two scales: inside -/// the status pill, and as the mic key itself. +/// Sized by the caller: the app's home screen draws it as the hero; the +/// keyboard's mic key draws its own capsule so it can grow into the wave. struct BrandOrb: View { var diameter: CGFloat /// Whether the ring sweeps. Off under Reduce Motion, where the ring is still /// drawn — it is part of the mark — but holds still. var animated: Bool var ringWidth: CGFloat = 1 - /// A solid ring in place of the green-to-white gradient — the error's orange. - var ringColor: Color? /// One turn every 1.6 s: the Mac's cadence. static let period: Double = 1.6 @@ -50,11 +48,7 @@ struct BrandOrb: View { } /// `strokeBorder` so the ring sits inside the disc instead of fringing it. - @ViewBuilder private var ringShape: some View { - if let ringColor { - Circle().strokeBorder(ringColor, lineWidth: ringWidth) - } else { - Circle().strokeBorder(BlurtBrand.orbRingGradient, lineWidth: ringWidth) - } + private var ringShape: some View { + Circle().strokeBorder(BlurtBrand.orbRingGradient, lineWidth: ringWidth) } } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift b/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift index 3b2ad3fe..f31cf478 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift @@ -6,7 +6,7 @@ import SwiftUI /// spacing — with the voice bar where the suggestion bar would be. Every key is 42 pt tall. Letters pop up /// while pressed, sentences capitalise themselves, a double space ends one. /// No autocorrect or suggestions yet. iOS swaps in its own keyboard for -/// password and phone-number fields, so those never reach here. +/// password fields, so those never reach here. struct FullKeyboardView: View { var model: KeyboardModel @@ -96,7 +96,8 @@ private struct LetterKey: View { .onEnded { value in pressed = false // A touch that travelled was a swipe (the panel's carousel), not a tap. - guard abs(value.translation.width) < 12, abs(value.translation.height) < 12 else { return } + guard abs(value.translation.width) < KeyPress.tapTravel, abs(value.translation.height) < KeyPress.tapTravel + else { return } action() } ) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Mic.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Mic.swift new file mode 100644 index 00000000..674719ca --- /dev/null +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Mic.swift @@ -0,0 +1,69 @@ +import BlurtEngine +import Foundation +import UIKit + +// MARK: - The mic key: the engine's gate, driven by the finger + +extension KeyboardModel { + /// Whether a tap on the orb can do anything but open the app. + var isReady: Bool { hasFullAccess && isListening } + + /// Finger down on the orb. Ignored, with a buzz, while the last dictation + /// is still being transcribed: a press then would be dropped by the engine + /// and the user would talk into nothing. + func micDown() { + guard isReady else { return } + switch snapshot.state { + case .connecting, .processing: + if hasFullAccess { UINotificationFeedbackGenerator().notificationOccurred(.warning) } + return + case .idle, .recording, .pasted, .copied, .error: + perform(gate.modifierDown(at: elapsed)) + } + } + + /// Finger up. When Blurt isn't ready — no Full Access, or the app isn't + /// listening — this is the tap that opens the app, whose checklist says what + /// is missing (opening the app needs no Full Access; everything else does). + func micUp() { + guard isReady else { + openApp() + return + } + perform(gate.modifierUp(at: elapsed)) + } + + func cancel() { + gate.reset() + send(.cancel) + } + + var elapsed: Duration { clockStart.duration(to: ContinuousClock.now) } + + func perform(_ action: DictationKeyGate.Action) { + switch action { + case .start: send(.press) + case .stop: send(.release) + case .cancel: send(.cancel) + case .none: break + } + } + + func send(_ kind: KeyboardCommand.Kind) { + let command = KeyboardCommand( + id: UUID(), kind: kind, priorText: proxy?.documentContextBeforeInput, + selectedText: proxy?.selectedText, sentAt: Date()) + transport(command) + // A press the app never answers (the notification was missed) would + // leave the gate latched over nothing; one re-signal covers it. + commandRetry?.cancel() + guard kind == .press else { return } + let stateAtSend = snapshot.state + commandRetry = Task { [weak self] in + try? await Task.sleep(for: Self.commandRetryDelay) + guard !Task.isCancelled, let self, snapshot.state == stateAtSend else { return } + SharedStore.post(BlurtShared.Signal.command) + } + } + +} diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Phase.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Phase.swift new file mode 100644 index 00000000..c763a6d0 --- /dev/null +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Phase.swift @@ -0,0 +1,78 @@ +import BlurtEngine +import Foundation +import UIKit + +// MARK: - What comes back from the app: phase, results, haptics + +extension KeyboardModel { + func phaseChanged() { + guard let current = SharedStore.read(PhaseSnapshot.self, forKey: BlurtShared.Key.phase) else { return } + apply(current.isStale ? .idle : current) + } + + func apply(_ current: PhaseSnapshot, haptics wantsHaptics: Bool = true) { + let previous = snapshot.state + snapshot = current + isListening = SharedStore.isListening + if wantsHaptics, current.state != previous { haptics(from: previous, to: current.state) } + // The gate follows the app, both ways. A dictation that ended without a + // finger event (auto-release, an error) would leave it latched and swallow + // the next tap — the same sync the Mac shell does on every terminal phase. + // And a dictation in flight that this keyboard didn't start (hands-free + // in another app, or a previous keyboard process) must latch it, so the + // next tap is the stop rather than a press the engine drops. + if isSettled, !gate.isIdle { + gate.reset() + } else if !isSettled, gate.isIdle, current.state != .processing { + // Only a recording (or one coming up) can be stopped by a tap; while + // the words are being transcribed there is nothing for the gate to hold. + _ = gate.modifierDown(at: elapsed) + _ = gate.modifierUp(at: elapsed) + } + // A notice is over after its dwell: the Mac pill fades out, this orb goes + // back to its resting circle. Only the picture settles — a gate latched by + // a tap the app hasn't answered yet is left alone. + noticeDwell?.cancel() + if let seconds = current.noticeDwellSeconds { + noticeDwell = Task { [weak self] in + try? await Task.sleep(for: .seconds(seconds)) + guard !Task.isCancelled else { return } + self?.snapshot = .idle + } + } + } + + func resultArrived() { + guard let result = SharedStore.read(DictationResult.self, forKey: BlurtShared.Key.result), + result.id != lastResultID, let proxy, + Date().timeIntervalSince(result.deliveredAt) < Self.resultFreshnessWindow, + result.recipient == nil || result.recipient == instanceID + else { return } + lastResultID = result.id + // Taken out of the store once inserted, so no other keyboard process — + // each host app runs its own — can insert the same words again; the app + // watches for this removal to know the words landed. + SharedStore.remove(forKey: BlurtShared.Key.result) + // Joined against the live text before the cursor, not the press-time + // snapshot: the user may have typed since. + proxy.insertText(InsertionSeparator.withLeadingSeparator(result.text, after: proxy.documentContextBeforeInput)) + // Not typing, so not the term field's to claim. + if termDraft != nil { termHostBaseline = proxy.documentContextBeforeInput ?? "" } + } + + func haptics(from previous: PhaseSnapshot.State, to state: PhaseSnapshot.State) { + guard hasFullAccess else { return } + switch state { + case .recording: + UIImpactFeedbackGenerator(style: .medium).impactOccurred() + case .processing where previous == .recording: + UIImpactFeedbackGenerator(style: .light).impactOccurred() + case .pasted, .copied: + UINotificationFeedbackGenerator().notificationOccurred(.success) + case .error: + UINotificationFeedbackGenerator().notificationOccurred(.error) + case .idle, .connecting, .processing: + break + } + } +} diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Typing.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Typing.swift index 31d79d4a..54fbfb1b 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Typing.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Typing.swift @@ -45,6 +45,7 @@ extension KeyboardModel { let seed = selected.count <= 48 && !selected.contains("\n") ? selected : "" termDraftFromSelection = seed.isEmpty ? nil : seed termHostBaseline = proxy?.documentContextBeforeInput ?? "" + termHostBaselineAfter = proxy?.documentContextAfterInput ?? "" termDraft = seed updateShift() onLayoutChange?() @@ -54,6 +55,7 @@ extension KeyboardModel { termDraft = nil termDraftFromSelection = nil termHostBaseline = nil + termHostBaselineAfter = nil updateShift() onLayoutChange?() } @@ -67,12 +69,21 @@ extension KeyboardModel { return } SharedStore.addKeyTerm(draft) - if let original = termDraftFromSelection, original != draft, proxy?.selectedText == original { - proxy?.insertText(draft) - } + // Out of the mode before touching the text, so the field's own change + // notification can't read the replacement as typing to claim. + let original = termDraftFromSelection termDraft = nil termDraftFromSelection = nil termHostBaseline = nil + termHostBaselineAfter = nil + if let original, original != draft, let selected = proxy?.selectedText, + selected.trimmingCharacters(in: .whitespacesAndNewlines) == original + { + // The selection may have carried the spaces around the word; keep them. + let lead = selected.prefix { $0.isWhitespace } + let trail = selected.reversed().prefix { $0.isWhitespace }.reversed() + proxy?.insertText(String(lead) + draft + String(trail)) + } if hasFullAccess { UINotificationFeedbackGenerator().notificationOccurred(.success) } termSavedAt = Date() termNotice?.cancel() diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift index 77bdd941..04f99555 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift @@ -48,21 +48,35 @@ final class KeyboardModel { var shifted = true var symbolsPage = false - // Internal, not private: the typing half of this model lives in - // KeyboardModel+Typing.swift. + // Internal, not private: the model's typing, mic and phase halves live in + // KeyboardModel+Typing/+Mic/+Phase.swift. @ObservationIgnored weak var controller: UIInputViewController? @ObservationIgnored private var observers: [DarwinObserver] = [] - @ObservationIgnored private var gate = DictationKeyGate() - @ObservationIgnored private let clockStart = ContinuousClock.now - @ObservationIgnored private var lastResultID: UUID? + @ObservationIgnored var gate = DictationKeyGate() + @ObservationIgnored let clockStart = ContinuousClock.now + @ObservationIgnored var lastResultID: UUID? @ObservationIgnored private var heartbeat: Task? @ObservationIgnored var lastSpaceAt: ContinuousClock.Instant? - @ObservationIgnored private var noticeDwell: Task? + @ObservationIgnored var noticeDwell: Task? + /// This keyboard process, for results addressed to it (`DictationResult.recipient`). + @ObservationIgnored let instanceID = UUID().uuidString + /// Where commands go: the App Group, or a test's capture. + @ObservationIgnored var transport: (KeyboardCommand) -> Void = { command in + SharedStore.write(command, forKey: BlurtShared.Key.command) + SharedStore.post(BlurtShared.Signal.command) + } + /// A press that got no phase back is re-signalled once (a Darwin + /// notification can be missed), after this long. + static let commandRetryDelay: Duration = .milliseconds(600) + @ObservationIgnored var commandRetry: Task? @ObservationIgnored var termDraftFromSelection: String? - /// The text before the cursor when the term field opened, so typing that - /// reaches the host field anyway (a hardware keyboard: an iPad's, a - /// Bluetooth one, the simulator's Mac) can be pulled into the term instead. + /// The text before and after the cursor when the term field opened, so + /// typing that reaches the host field anyway (a hardware keyboard: an + /// iPad's, a Bluetooth one, the simulator's Mac) can be pulled into the + /// term instead — and a cursor move, which changes both sides, cannot be + /// mistaken for it. @ObservationIgnored var termHostBaseline: String? + @ObservationIgnored var termHostBaselineAfter: String? @ObservationIgnored var termNotice: Task? /// The host's text field. Tests hand in a fake in place of a controller. @@ -95,7 +109,7 @@ final class KeyboardModel { /// Whether the phase leaves nothing in flight — the moments the gate has to /// be reset, since a dictation can end with no finger event to close it. - private var isSettled: Bool { + var isSettled: Bool { switch snapshot.state { case .idle, .pasted, .copied, .error: true case .connecting, .recording, .processing: false @@ -120,40 +134,66 @@ final class KeyboardModel { hasFullAccess = controller?.hasFullAccess ?? false needsGlobe = controller?.needsInputModeSwitchKey ?? true letterRows = LetterLayout.forPreferredLanguages() + // Every appearance starts on the mic page with no term half-typed, and on + // the page the field asks for: symbols for a number, letters otherwise. + panelShowsKeys = false + termDraft = nil + termDraftFromSelection = nil + termHostBaseline = nil + termHostBaselineAfter = nil + symbolsPage = Self.wantsSymbols(proxy?.keyboardType) readField() updateShift() // Without Full Access the App Group is out of reach: the keyboard still - // types, and says what it needs (see `KeyboardRootView`), but nothing below - // can run. + // types, and says what it needs (see `VoiceBar`), but nothing below can run. guard hasFullAccess else { return } layout = SharedStore.layout themeID = SharedStore.themeID - panelShowsKeys = false SharedStore.keyboardEverSeen = true - refresh() + refresh(haptics: false) startHeartbeat() requestLexicon() + // Words that landed while this keyboard was away, still fresh and meant + // for whoever is up, go in now rather than waiting for a signal nobody + // will send again. + resultArrived() if SharedStore.autoDictate { autoStart() } } /// Hands-free: a dictation begins the moment the keyboard is up, as if the /// mic had been tapped — the same synthetic tap through the engine's gate, /// so it latches and the next real tap stops it. Only when the app is - /// listening and nothing is in flight; otherwise the pill says what to do. + /// listening and nothing is in flight; otherwise the orb sits dimmed and the + /// first tap opens Blurt. private func autoStart() { guard isListening, isSettled, gate.isIdle else { return } perform(gate.modifierDown(at: elapsed)) perform(gate.modifierUp(at: elapsed)) } + /// The keyboard is leaving the screen. A dictation it started must not run + /// on without it: a latched recording is released (the words still land, on + /// the clipboard if no keyboard is there to take them), anything earlier is + /// cancelled. Presence ends, so a result that finishes after this goes to + /// the clipboard rather than to a keyboard nobody can see. func disappeared() { heartbeat?.cancel() heartbeat = nil - // Presence means on screen. A dictation that finishes after the keyboard - // is gone goes to the clipboard, not to a keyboard nobody can see. + commandRetry?.cancel() + if !gate.isIdle || !isSettled { + send(snapshot.state == .recording ? .release : .cancel) + gate.reset() + } SharedStore.keyboardSeenAt = nil } + deinit { + heartbeat?.cancel() + noticeDwell?.cancel() + termNotice?.cancel() + commandRetry?.cancel() + } + /// The cursor moved or the text around it changed, including by our own /// typing: re-read where the sentence stands and what the field wants. func contextChanged() { @@ -170,19 +210,30 @@ final class KeyboardModel { guard termDraft != nil, let baseline = termHostBaseline, let proxy else { return } let now = proxy.documentContextBeforeInput ?? "" let delta = now.count - baseline.count - guard delta > 0, delta <= 8, now.dropLast(delta).hasSuffix(baseline.suffix(24)) else { return } + // Typing lengthens the text before the cursor and leaves the text after + // it alone; a cursor move changes both; a selection is neither. + guard delta > 0, delta <= 8, proxy.selectedText == nil, + (proxy.documentContextAfterInput ?? "") == (termHostBaselineAfter ?? ""), + now.dropLast(delta).hasSuffix(baseline.suffix(24)) + else { return } let typed = String(now.suffix(delta)) for _ in 0.. Bool { + switch type { + case .numberPad, .decimalPad, .phonePad, .numbersAndPunctuation, .asciiCapableNumberPad: true + default: false } } @@ -220,10 +271,12 @@ final class KeyboardModel { return last == "\n" || ".?!".contains(last) } - private func refresh() { + /// Catches up with whatever the app last published. No haptics: nothing + /// just happened, the keyboard merely came up. + private func refresh(haptics: Bool) { isListening = SharedStore.isListening if let current = SharedStore.read(PhaseSnapshot.self, forKey: BlurtShared.Key.phase) { - apply(current.isStale ? .idle : current) + apply(current.isStale ? .idle : current, haptics: haptics) } } @@ -233,9 +286,11 @@ final class KeyboardModel { heartbeat?.cancel() heartbeat = Task { [weak self] in while !Task.isCancelled { + guard let self else { return } SharedStore.keyboardSeenAt = Date() - self?.isListening = SharedStore.isListening - try? await Task.sleep(for: .seconds(4)) + SharedStore.keyboardInstance = instanceID + isListening = SharedStore.isListening + try? await Task.sleep(for: .seconds(SharedStore.keyboardHeartbeatInterval)) } } } @@ -269,104 +324,4 @@ final class KeyboardModel { SharedStore.lexiconRefreshedAt = Date() SharedStore.post(BlurtShared.Signal.lexicon) } - - // MARK: - The mic key - - func micDown() { - // No Full Access, or the app isn't listening: the mic key's job is to get - // the user to the app, whose checklist says what is missing. Opening the - // app needs no Full Access; everything else here does. - guard hasFullAccess, isListening else { - openApp() - return - } - perform(gate.modifierDown(at: elapsed)) - } - - func micUp() { - guard hasFullAccess, isListening else { return } - perform(gate.modifierUp(at: elapsed)) - } - - func cancel() { - gate.reset() - send(.cancel) - } - - private var elapsed: Duration { clockStart.duration(to: ContinuousClock.now) } - - private func perform(_ action: DictationKeyGate.Action) { - switch action { - case .start: send(.press) - case .stop: send(.release) - case .cancel: send(.cancel) - case .none: break - } - } - - private func send(_ kind: KeyboardCommand.Kind) { - let command = KeyboardCommand( - id: UUID(), kind: kind, priorText: proxy?.documentContextBeforeInput, - selectedText: proxy?.selectedText, sentAt: Date()) - SharedStore.write(command, forKey: BlurtShared.Key.command) - SharedStore.post(BlurtShared.Signal.command) - } - - // MARK: - What comes back - - private func phaseChanged() { - guard let current = SharedStore.read(PhaseSnapshot.self, forKey: BlurtShared.Key.phase) else { return } - apply(current.isStale ? .idle : current) - } - - private func apply(_ current: PhaseSnapshot) { - let previous = snapshot.state - snapshot = current - isListening = SharedStore.isListening - if current.state != previous { haptics(from: previous, to: current.state) } - // A dictation that ended without a finger event (auto-release, an error) - // would leave the gate latched and swallow the next tap — the same sync the - // Mac shell does on every terminal phase. - if isSettled, !gate.isIdle { gate.reset() } - // A notice is over after its dwell: the Mac pill fades out, this one goes - // back to saying how to start. - noticeDwell?.cancel() - if let seconds = current.noticeDwellSeconds { - noticeDwell = Task { [weak self] in - try? await Task.sleep(for: .seconds(seconds)) - guard !Task.isCancelled else { return } - self?.apply(.idle) - } - } - } - - private func resultArrived() { - guard let result = SharedStore.read(DictationResult.self, forKey: BlurtShared.Key.result), - result.id != lastResultID, let proxy, - Date().timeIntervalSince(result.deliveredAt) < Self.resultFreshnessWindow - else { return } - lastResultID = result.id - // Taken out of the store once inserted, so no other keyboard process — - // each host app runs its own — can insert the same words again. - SharedStore.remove(forKey: BlurtShared.Key.result) - // Joined against the live text before the cursor, not the press-time - // snapshot: the user may have typed since. - proxy.insertText(InsertionSeparator.withLeadingSeparator(result.text, after: proxy.documentContextBeforeInput)) - } - - private func haptics(from previous: PhaseSnapshot.State, to state: PhaseSnapshot.State) { - guard hasFullAccess else { return } - switch state { - case .recording: - UIImpactFeedbackGenerator(style: .medium).impactOccurred() - case .processing where previous == .recording: - UIImpactFeedbackGenerator(style: .light).impactOccurred() - case .pasted, .copied: - UINotificationFeedbackGenerator().notificationOccurred(.success) - case .error: - UINotificationFeedbackGenerator().notificationOccurred(.error) - case .idle, .connecting, .processing: - break - } - } } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift index 330688e7..dde190f4 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift @@ -13,13 +13,13 @@ struct KeyboardPalette: Equatable, Identifiable { let name: String /// One line for the picker. let vibe: String - var surface: Color - var key: Color - var keyDark: Color - var keyText: Color + let surface: Color + let key: Color + let keyDark: Color + let keyText: Color /// The drop under each key, as the system keyboard draws it. - var keyShadow: Color - var popupFill: Color + let keyShadow: Color + let popupFill: Color static let keyGap: CGFloat = 6 static let rowGap: CGFloat = 11 diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift index 94a590b7..0d5395be 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift @@ -3,9 +3,9 @@ import SwiftUI /// Picks the layout the user chose. All three share `VoiceBar`/`MicKey` and /// `KeyCap`, and the same model underneath; they differ in how much keyboard -/// surrounds the mic. The surface is Blurt's ink in every appearance — it -/// floats over whichever app the user is typing in, like the Mac pill — at -/// the iPhone keyboard's own spacing. +/// surrounds the mic. The surface is the theme's, fixed whatever the host +/// app's appearance — the keyboard floats over whichever app the user is +/// typing in, like the Mac pill — at the iPhone keyboard's own spacing. struct KeyboardRootView: View { var model: KeyboardModel @@ -91,7 +91,7 @@ struct PanelView: View { } } .overlay(alignment: .topTrailing) { - if !model.isSettledState { + if !model.isSettled { KeyCap(systemImage: "xmark", tint: BlurtBrand.errorOrange, dark: true) { model.cancel() } .accessibilityLabel("Cancel dictation") } @@ -153,27 +153,54 @@ struct MicKey: View { .animation(.easeOut(duration: 0.1), value: pressed) .contentShape(Capsule()) .accessibilityLabel(isReady ? (isRecording ? "Stop dictation" : "Dictate") : "Start Blurt") + .accessibilityValue(model.snapshot.state == .error ? model.snapshot.message ?? "Dictation failed." : "") .accessibilityAddTraits(.isButton) .simultaneousGesture( DragGesture(minimumDistance: 0) - .onChanged { _ in - guard !pressed else { return } - pressed = true - model.micDown() + .onChanged { value in + if !pressed { + pressed = true + // The press waits a beat, so a swipe that starts on the orb (the + // panel's carousel) never starts a dictation it must then cancel. + pressTask = Task { [model] in + try? await Task.sleep(for: Self.pressDelay) + guard !Task.isCancelled else { return } + pressSent = true + model.micDown() + } + } + if Self.travelled(value), !pressSent { + pressTask?.cancel() + pressTask = nil + } } .onEnded { value in pressed = false - // A finger that swiped across the orb was flipping the panel, not - // releasing a hold: undo the press instead of ending a dictation. - if abs(value.translation.width) > 24 || abs(value.translation.height) > 24 { - model.cancel() - } else { - model.micUp() + pressTask?.cancel() + pressTask = nil + defer { pressSent = false } + if Self.travelled(value) { + // A swipe: undo a press that did go out, otherwise nothing. + if pressSent { model.cancel() } + return } + // A tap quicker than the delay is still a tap. + if !pressSent { model.micDown() } + model.micUp() } ) } + /// How long a touch must stay before it counts as a press rather than the + /// start of a swipe — well under a tap's own duration for a hold. + static let pressDelay: Duration = .milliseconds(90) + @State private var pressTask: Task? + @State private var pressSent = false + + private static func travelled(_ value: DragGesture.Value) -> Bool { + abs(value.translation.width) > 24 || abs(value.translation.height) > 24 + } + /// The ring: the app orb's sweep (one turn per 1.6 s, engine geometry) /// while the mic comes up and while the words come; still, and solid green /// or orange, for a notice; still on the capsule while recording. @@ -195,7 +222,7 @@ struct MicKey: View { } } - private var isReady: Bool { model.hasFullAccess && model.isListening } + private var isReady: Bool { model.isReady } private var isRecording: Bool { isReady && model.snapshot.state == .recording } private var isWorking: Bool { switch model.snapshot.state { @@ -260,23 +287,57 @@ struct KeyCap: View { } var body: some View { - Button(action: action) { - Group { - if let systemImage { - Image(systemName: systemImage) - } else { - Text(title ?? "") - } + Group { + if let systemImage { + Image(systemName: systemImage) + } else { + Text(title ?? "") } - .font(.system(size: 16, weight: .medium)) - .foregroundStyle(tint ?? palette.keyText) - .frame(maxWidth: flexible ? .infinity : nil) - .frame(width: width) - .frame(minWidth: width == nil ? 44 : nil, minHeight: Self.height) - .padding(.horizontal, flexible || width != nil ? 0 : 4) - .keyCap(dark ? palette.keyDark : palette.key, palette: palette) } - .buttonStyle(KeyPressStyle()) + .font(.system(size: 16, weight: .medium)) + .foregroundStyle(tint ?? palette.keyText) + .frame(maxWidth: flexible ? .infinity : nil) + .frame(width: width) + .frame(minWidth: width == nil ? 44 : nil, minHeight: Self.height) + .padding(.horizontal, flexible || width != nil ? 0 : 4) + .keyCap(dark ? palette.keyDark : palette.key, palette: palette) + .keyPress(action) + .accessibilityLabel(title ?? systemImage ?? "") + } +} + +extension View { + /// A key's touch: lights while the finger is down, acts on release — and + /// only if the finger didn't travel, so a swipe across a key (the panel's + /// carousel) never types. The system keyboard's own rule. + func keyPress(_ action: @escaping () -> Void) -> some View { + modifier(KeyPress(action: action)) + } +} + +struct KeyPress: ViewModifier { + let action: () -> Void + @State private var pressed = false + + /// The most a touch may travel and still be a tap. + static let tapTravel: CGFloat = 12 + + func body(content: Content) -> some View { + content + .brightness(pressed ? 0.15 : 0) + .animation(.easeOut(duration: 0.08), value: pressed) + .contentShape(Rectangle()) + .accessibilityAddTraits(.isButton) + .simultaneousGesture( + DragGesture(minimumDistance: 0) + .onChanged { _ in pressed = true } + .onEnded { value in + pressed = false + guard abs(value.translation.width) < Self.tapTravel, abs(value.translation.height) < Self.tapTravel + else { return } + action() + } + ) } } @@ -304,13 +365,3 @@ struct KeyPressStyle: ButtonStyle { .animation(.easeOut(duration: 0.08), value: configuration.isPressed) } } - -extension KeyboardModel { - /// Whether nothing is in flight, for the views that hide the cancel key. - var isSettledState: Bool { - switch snapshot.state { - case .idle, .pasted, .copied, .error: true - case .connecting, .recording, .processing: false - } - } -} diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift index 24cd5347..1194ec07 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift @@ -13,19 +13,34 @@ struct VoiceBar: View { static let height: CGFloat = 44 var body: some View { - ZStack { - if model.termDraft != nil { - TermField(model: model) - .transition(.opacity) - } else { - MicKey(model: model, size: 40, expandedWidth: 200) + GeometryReader { geo in + ZStack { + if model.termDraft != nil { + TermField(model: model) + .transition(.opacity) + } else if !model.hasFullAccess { + // The one state the orb can't show on its own: without Full Access + // nothing here can work, and the user has to be told where to go. + HStack(spacing: 10) { + MicKey(model: model, size: 40, expandedWidth: 40) + Text("Allow Full Access in Settings → Keyboards") + .font(.footnote) + .foregroundStyle(BlurtBrand.errorOrange) + .lineLimit(1) + .minimumScaleFactor(0.8) + } .transition(.opacity) + } else { + // The wave's capsule stays clear of the + at the trailing edge. + MicKey(model: model, size: 40, expandedWidth: min(200, geo.size.width - 2 * (32 + 12))) + .transition(.opacity) + } } + .frame(maxWidth: .infinity, maxHeight: .infinity) } - .frame(maxWidth: .infinity) .frame(height: Self.height) .overlay(alignment: .trailing) { - if model.termDraft == nil { AddTermKey(model: model) } + if model.termDraft == nil, model.hasFullAccess { AddTermKey(model: model) } } .animation(.easeInOut(duration: 0.15), value: model.termDraft == nil) } @@ -142,6 +157,7 @@ struct WaveformMeter: View { } .frame(width: geo.size.width, height: geo.size.height) } + .accessibilityHidden(true) } private func bars(layout: MeterBarRow, time: TimeInterval) -> some View { diff --git a/App/BlurtiOS/BlurtiOS/Sources/APIKeyModel.swift b/App/BlurtiOS/BlurtiOS/Sources/APIKeyModel.swift index c28cfa7e..0755ad4e 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/APIKeyModel.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/APIKeyModel.swift @@ -47,19 +47,6 @@ final class APIKeyModel { self.hasAPIKey = keyStore.hasKey } - /// The key currently stored, read through the gateway. The setup/settings - /// API-key view reads this (rather than `APIKeyStore` directly) so a UI-test - /// run sees the injected in-memory store instead of the real Keychain. - var current: String? { keyStore.current } - - /// The storage seam itself, handed to the Settings window's full-install reset - /// (`InstallReset`) so the sweep deletes the key from the *injected* store — - /// the in-memory one under UI testing — rather than reaching past this model - /// to the production Keychain item. Exposed rather than wrapped in a `clear()` - /// here because the reset owns the sweep; what this model owns is - /// `refreshStatus()`, which is how `hasAPIKey` catches up afterwards. - var storage: any APIKeyGateway { keyStore } - /// A `@Sendable` snapshot of the readiness gate for `DictationSession`: a press /// with no key saved fails fast as `.failed(.apiKeyMissing)` before any capture. /// Captures the (Sendable) store, not this main-actor model, so it can cross @@ -69,19 +56,8 @@ final class APIKeyModel { return { keyStore.hasKey ? nil : .apiKeyMissing } } - /// Saves the AssemblyAI API key and refreshes `hasAPIKey` so observers — - /// including the wizard — react. Returns true only when a non-empty key is - /// actually readable from Keychain after the write (the engine's - /// `APIKeySubmission.save` owns that read-back rule). - @discardableResult - func save(_ key: String) -> Bool { - let saved = submission.save(key) - refreshStatus() - return saved - } - /// Re-reads the Keychain and updates `hasAPIKey`. The flag is otherwise only - /// set at `init` and after `save`, so it can drift out of sync with what's + /// set at `init` and after `submit`, so it can drift out of sync with what's /// actually stored — e.g. an early-launch Keychain read fails (the item's ACL /// needs re-approval after a re-sign) before a later read succeeds. Calling this /// when the API-key UI appears keeps the readiness gate honest: a key that's diff --git a/App/BlurtiOS/BlurtiOS/Sources/AudioSource.swift b/App/BlurtiOS/BlurtiOS/Sources/AudioSource.swift index e10c505d..e516cb9a 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/AudioSource.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/AudioSource.swift @@ -22,29 +22,19 @@ import Foundation /// The output's native format is converted to the 16 kHz mono 16-bit the /// dictation API wants by `PCMConverter` (`audioSettings`, which does that on /// the Mac, is not in the iOS SDK). `@unchecked Sendable` by confinement, the -/// same way the Mac recorder is: the feed and its tally live behind `UtteranceFeed`'s lock, -/// the converter is touched only on the serial delivery queue, and the session -/// is configured once and then only started and stopped. +/// same way the Mac recorder is: the feed and its tally live behind +/// `UtteranceFeed`'s lock, the converter is touched only on the serial delivery +/// queue, and the session is configured, started and stopped only on the +/// serial control queue. nonisolated final class WindowedAudioSource: NSObject, ListeningSource, @unchecked Sendable { - enum Failure: Error, LocalizedError { - /// A press arrived with no listening window open — the keyboard's job is to - /// open the app first, so this is a plumbing fault, not a user error. - case windowClosed - case noInputDevice - - var errorDescription: String? { - switch self { - case .windowClosed: "Blurt isn't listening. Open Blurt to start." - case .noInputDevice: "No microphone is available." - } - } - } - private let feed = UtteranceFeed() private let session = AVCaptureSession() private let output = AVCaptureAudioDataOutput() /// Serial, so the converter below needs no lock. private let deliveryQueue = DispatchQueue(label: "dev.alex.blurt.ios.capture") + /// Where the session is started and stopped — both block for a while on a + /// phone — so the main actor never waits on the capture stack. + private let controlQueue = DispatchQueue(label: "dev.alex.blurt.ios.capture.control") private nonisolated(unsafe) var converter: PCMConverter? var levels: AsyncStream { feed.levels } @@ -60,35 +50,63 @@ nonisolated final class WindowedAudioSource: NSObject, ListeningSource, @uncheck /// Opens the microphone. Only works from the foreground; the audio session /// must already be active (`ListeningWindow` does both, in that order). - func open() throws { + func open() async throws { + try await withCheckedThrowingContinuation { (continuation: CheckedContinuation) in + controlQueue.async { + do { + try self.openOnControlQueue() + continuation.resume() + } catch { + continuation.resume(throwing: error) + } + } + } + } + + private func openOnControlQueue() throws { + // A session left "running" through an interruption resumes on its own + // terms; stopping it first makes the reopen deterministic. + if session.isRunning, session.isInterrupted { session.stopRunning() } guard !session.isRunning else { return } + try configure() + session.startRunning() + guard session.isRunning else { throw ListeningSourceFailure.noInputDevice } + } + + /// Adds the input and output once. `commitConfiguration` runs on every + /// path out, including a throw, so a failed attempt never leaves the + /// session mid-configuration for the next one. + private func configure() throws { session.beginConfiguration() + defer { session.commitConfiguration() } session.automaticallyConfiguresApplicationAudioSession = false if session.inputs.isEmpty { - guard let device = AVCaptureDevice.default(for: .audio) else { - session.commitConfiguration() - throw Failure.noInputDevice - } + guard let device = AVCaptureDevice.default(for: .audio) else { throw ListeningSourceFailure.noInputDevice } let input = try AVCaptureDeviceInput(device: device) if session.canAddInput(input) { session.addInput(input) } } if session.outputs.isEmpty, session.canAddOutput(output) { session.addOutput(output) } - session.commitConfiguration() - session.startRunning() - guard session.isRunning else { throw Failure.noInputDevice } } /// Releases the microphone and ends any utterance in flight. - func close() { - if session.isRunning { session.stopRunning() } - feed.end() + func close() async { + await withCheckedContinuation { (continuation: CheckedContinuation) in + controlQueue.async { + if self.session.isRunning { self.session.stopRunning() } + self.feed.end() + continuation.resume() + } + } } // MARK: MicCaptureProtocol func start() throws -> AsyncStream { - guard session.isRunning else { - throw BlurtError.audioCaptureFailed(underlying: Failure.windowClosed) + // An interrupted session is "running" and delivering nothing: a feed from + // it would claim `.recording` over a dead mic, which the engine's timing + // contract forbids. + guard session.isRunning, !session.isInterrupted else { + throw BlurtError.audioCaptureFailed(underlying: ListeningSourceFailure.windowClosed) } return feed.begin() } diff --git a/App/BlurtiOS/BlurtiOS/Sources/BlurtBrand+App.swift b/App/BlurtiOS/BlurtiOS/Sources/BlurtBrand+App.swift index 43db5d41..13f78738 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/BlurtBrand+App.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/BlurtBrand+App.swift @@ -25,7 +25,7 @@ extension View { /// The lowercase wordmark from the Mac's ready screen, tinted with the accent /// (`blurt-ready-logo.png`, shared from `App/Blurt/Blurt/Branding`). struct Wordmark: View { - var height: CGFloat = 22 + private static let height: CGFloat = 22 var body: some View { if let image = UIImage(named: "blurt-ready-logo") { @@ -33,7 +33,7 @@ struct Wordmark: View { .renderingMode(.template) .resizable() .scaledToFit() - .frame(height: height) + .frame(height: Self.height) .foregroundStyle(BlurtBrand.accent) .accessibilityLabel("Blurt") } else { diff --git a/App/BlurtiOS/BlurtiOS/Sources/BlurtiOSApp.swift b/App/BlurtiOS/BlurtiOS/Sources/BlurtiOSApp.swift index f7233d9b..9feafcfc 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/BlurtiOSApp.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/BlurtiOSApp.swift @@ -22,7 +22,17 @@ struct BlurtiOSApp: App { defaultsPrefix: "Blurt", logDirectoryName: "Blurt", releaseURL: HostIdentity.blurt.releaseURL)) - _coordinator = State(initialValue: DictationCoordinator()) + // The unit tests are hosted by this app: they get a coordinator that + // touches neither the Keychain nor the App Group (the Mac's UITestSupport + // does the same for its harness), and `start()` below never runs. + let coordinator = + Self.isTestHost + ? DictationCoordinator(apiKey: APIKeyModel(keyStore: InMemoryAPIKeyStore())) : DictationCoordinator() + _coordinator = State(initialValue: coordinator) + } + + private static var isTestHost: Bool { + ProcessInfo.processInfo.environment["XCTestConfigurationFilePath"] != nil } var body: some Scene { @@ -44,6 +54,7 @@ struct BlurtiOSApp: App { HomeView(coordinator: coordinator) .onOpenURL { coordinator.handle($0) } .task { + guard !Self.isTestHost else { return } coordinator.start() #if DEBUG // `-BlurtStartListening` opens the mic at launch, so the listening diff --git a/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift b/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift index 5ded1e8d..54020cfd 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift @@ -2,11 +2,17 @@ import AVFoundation import BlurtEngine import Foundation import Observation +import Synchronization /// The one place the engine is composed for the iPhone app — the role /// `AppCoordinator` plays in the Mac shell. It owns the listening window (the /// microphone), the session, and the two channels to the keyboard: commands /// coming in over the App Group, phase and results going back out. +/// +/// Key terms live in the App Group (`SharedStore.keyTerms`) rather than the +/// engine's `KeyTermsStore` (which reads the process's own defaults), so the +/// keyboard can add one on the spot; `keyTermsProvider` is how they reach the +/// request. @MainActor @Observable final class DictationCoordinator { @@ -22,6 +28,10 @@ final class DictationCoordinator { /// A shared key-term list the app was asked to open, until the user has /// answered it (`ImportTermsView`). var pendingTermPack: TermPack? + /// A file or link that claimed to be a key-term list and wasn't. + var termPackUnreadable = false + /// The window can't open without a key: the last "Start listening" said so. + var needsKey = false @ObservationIgnored private let session: DictationSession @ObservationIgnored private let recents: AsyncStream @@ -30,6 +40,15 @@ final class DictationCoordinator { @ObservationIgnored private var lastCommandID: UUID? @ObservationIgnored private var lastLevelPublish = ContinuousClock.now + /// What the keyboard saw around the cursor on the press that started the + /// dictation in flight, read by the engine's context seam — and cleared once + /// used, so nothing from another app's field primes a later request. + nonisolated private static let pressContext = Mutex(.empty) + /// Contact names, parsed once per lexicon refresh rather than on the press. + nonisolated private static let lexiconNames = Mutex<[String]>([]) + /// A press command older than this was held while the app was suspended. + static let commandFreshnessWindow: TimeInterval = 10 + init(apiKey: APIKeyModel = APIKeyModel()) { let window = ListeningWindow() self.window = window @@ -52,6 +71,9 @@ final class DictationCoordinator { } func start() { + // `.task` on the root view runs this once; a scene reconnect must not + // start a second set of observers publishing every phase twice. + guard tasks.isEmpty else { return } observers = [ DarwinObserver(name: BlurtShared.Signal.command) { [weak self] in Task { @MainActor in self?.handleCommand() } @@ -69,25 +91,36 @@ final class DictationCoordinator { // MARK: - The listening window /// Opens the microphone for the keyboard. Foreground only — this is what - /// `blurt://start` arrives to do. + /// `blurt://start` arrives to do. Not without a key: an open window whose + /// every press fails quietly would look like a keyboard that ignores taps. func startListening() async { + apiKey.refreshStatus() + needsKey = !apiKey.hasAPIKey + guard !needsKey else { return } guard await AVAudioApplication.requestRecordPermission() else { microphoneDenied = true return } microphoneDenied = false - window.open() + await window.open() } - func stopListening() { - if phase.isCapturing { session.submit(.cancel) } - window.close() + /// Closes the window. A dictation in flight is cancelled first, upload and + /// all — closing the feed alone would end the utterance and let the request + /// complete, transcribing (and billing) audio nobody asked for. + func stopListening() async { + if !phase.isTerminal { await session.cancel() } + await window.close() publish(.idle) } func handle(_ url: URL) { - if let pack = TermPack.from(url) { - pendingTermPack = pack + if TermPack.looksLikePack(url) { + if let pack = TermPack.from(url) { + pendingTermPack = pack + } else { + termPackUnreadable = true + } return } guard url.scheme == BlurtShared.urlScheme, url.host() == BlurtShared.startHost else { return } @@ -96,8 +129,10 @@ final class DictationCoordinator { /// A dictation started from the app itself, with no keyboard to land in — /// the words go to the clipboard. The way to try Blurt before the keyboard is - /// set up, and the way to test the pipeline without one. + /// set up, and the way to test the pipeline without one. No field, so no + /// prior text primes it. func toggleDictation() { + Self.pressContext.withLock { $0 = .empty } session.submit(phase.isCapturing ? .release : .press) } @@ -108,8 +143,19 @@ final class DictationCoordinator { command.id != lastCommandID else { return } lastCommandID = command.id + // The command is consumed: nothing re-reads it, and the text it carried + // from the user's field doesn't sit in the group container. + SharedStore.remove(forKey: BlurtShared.Key.command) + // A notification held while the app was suspended delivers a press from + // minutes ago; the user has long since moved on. + guard Date().timeIntervalSince(command.sentAt) < Self.commandFreshnessWindow else { return } switch command.kind { - case .press: session.submit(.press) + case .press: + Self.pressContext.withLock { + $0 = FocusedFieldContext( + priorText: command.priorText, selectedText: command.selectedText, windowTitle: nil, fieldLabel: nil) + } + session.submit(.press) case .release: session.submit(.release) case .cancel: session.submit(.cancel) } @@ -117,7 +163,9 @@ final class DictationCoordinator { private func reloadLexicon() { let entries = SharedStore.read([LexiconEntry].self, forKey: BlurtShared.Key.lexicon) ?? [] - lexiconNameCount = entries.filter(\.isName).count + let names = entries.filter(\.isName).map(\.documentText) + Self.lexiconNames.withLock { $0 = names } + lexiconNameCount = names.count } /// The user's own key terms (from the App Group, where the keyboard adds @@ -126,18 +174,24 @@ final class DictationCoordinator { /// to the request's caps (100 terms, 2048 bytes), first entries first, which /// is why the typed terms lead. nonisolated static func keyTerms() -> [String] { - let names = (SharedStore.read([LexiconEntry].self, forKey: BlurtShared.Key.lexicon) ?? []) - .filter(\.isName).map(\.documentText) - return KeyTermList.parse(KeyTermList.join(SharedStore.keyTerms + names)) + // Not through the comma-separated form: a contact called "Smith, John" + // is one name, and the engine takes an array. + var seen = Set() + var terms: [String] = [] + for term in SharedStore.keyTerms + lexiconNames.withLock({ $0 }) { + let trimmed = term.trimmingCharacters(in: .whitespacesAndNewlines) + guard !trimmed.isEmpty, seen.insert(trimmed.lowercased()).inserted else { continue } + terms.append(trimmed) + } + return terms } - /// What the keyboard saw around the cursor when it sent the press. + /// What the keyboard saw around the cursor on the press in flight, once. nonisolated static func fieldContext() -> FocusedFieldContext { - guard let command = SharedStore.read(KeyboardCommand.self, forKey: BlurtShared.Key.command), - command.kind == .press - else { return .empty } - return FocusedFieldContext( - priorText: command.priorText, selectedText: command.selectedText, windowTitle: nil, fieldLabel: nil) + pressContext.withLock { context in + defer { context = .empty } + return context + } } // MARK: - Phase, level and results out to the keyboard @@ -155,6 +209,12 @@ final class DictationCoordinator { private func render(_ phase: PipelinePhase) { self.phase = phase if phase == .recording { window.extend() } + // The Mac shows a setup blocker as calm idle beside a settings button; + // the keyboard has no such button, so it hears an error and the orb says so. + if phase.setupBlocker != nil { + publish(.error(message: "Blurt needs an API key. Open Blurt to add one.")) + return + } publish(phase.overlayState) } @@ -163,12 +223,14 @@ final class DictationCoordinator { return Task { [weak self] in for await value in levels { guard let self else { return } + // Only while recording: the feed reports levels only for an open + // utterance, and the home screen's hero shouldn't redraw for a + // window sitting idle in the background. + guard self.phase == .recording else { continue } self.level = value // The keyboard redraws its meter from these; ~12 Hz is plenty for a pill // and keeps the shared-defaults writes off the capture path's back. - guard self.phase == .recording, - self.lastLevelPublish.duration(to: ContinuousClock.now) > .milliseconds(80) - else { continue } + guard self.lastLevelPublish.duration(to: ContinuousClock.now) > .milliseconds(80) else { continue } self.lastLevelPublish = ContinuousClock.now self.publish(.recording) } diff --git a/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift b/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift index d3e90f03..f89c846c 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift @@ -96,7 +96,7 @@ struct HomeView: View { } if coordinator.window.isOpen { Button(role: .destructive) { - coordinator.stopListening() + Task { await coordinator.stopListening() } } label: { Text("Stop listening").frame(maxWidth: .infinity) } diff --git a/App/BlurtiOS/BlurtiOS/Sources/ImportTermsView.swift b/App/BlurtiOS/BlurtiOS/Sources/ImportTermsView.swift index fbe9bc9f..7e6d408b 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/ImportTermsView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/ImportTermsView.swift @@ -21,7 +21,8 @@ struct ImportTermsView: View { Text(pack.from.map { "From \($0)" } ?? "Shared with you") } footer: { Text( - "They'll ride along with every dictation so Blurt spells them right. Terms you already have are skipped.") + "They'll ride along with every dictation so Blurt spells them right. Terms you already have are skipped; " + + "the first \(TermPack.termCap) terms ride each request, so keep the list to what matters.") } } .navigationTitle(pack.name) diff --git a/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift b/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift index ecd76190..ad088ef0 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift @@ -16,12 +16,12 @@ /// BLURT_LAUNCH_ARGS="-BlurtGallery panel idle,recording,processing" \ /// scripts/ios-sim.sh --screenshot panel.png /// - /// is the whole loop. The keyboard's sources are compiled into the app for - /// this (see project.yml); the keyboard itself never runs here. + /// is the whole loop. The keyboard's sources are compiled into the app (see + /// project.yml: the theme picker and the home screen draw the real keyboard + /// and orb too); the keyboard itself never runs here. struct KeyboardGalleryView: View { struct Row: Identifiable { let id = UUID() - let layout: KeyboardLayout let caption: String let model: KeyboardModel } @@ -54,7 +54,7 @@ let theme = arguments.count > flag + 3 ? arguments[flag + 3] : "ink" return arguments[flag + 2].split(separator: ",").map { name in Row( - layout: layout, caption: "\(layout.rawValue) · \(name) · \(theme)", + caption: "\(layout.rawValue) · \(name) · \(theme)", model: model(layout: layout, state: String(name), theme: theme)) } } diff --git a/App/BlurtiOS/BlurtiOS/Sources/KeyboardRelayInjector.swift b/App/BlurtiOS/BlurtiOS/Sources/KeyboardRelayInjector.swift index 4d962fbb..2c005e2d 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/KeyboardRelayInjector.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/KeyboardRelayInjector.swift @@ -3,30 +3,44 @@ import Foundation import UIKit /// The engine's paste seam on iPhone. Nothing here can type into another app; -/// only the keyboard can, so "insert" means hand the words to the keyboard and -/// ping it. When no keyboard is around to take them — it was dismissed, or the -/// dictation was started from the app itself — the words go to the clipboard -/// instead and the pipeline shows its quiet "Copied" notice, exactly the -/// degradation the Mac uses when nothing editable is focused. +/// only the keyboard can, so "insert" means hand the words to the keyboard +/// and ping it — then make sure they arrived. The keyboard takes the result +/// out of the App Group once it has inserted it; if it hasn't within a few +/// seconds (it was dismissed, suspended with its app, or killed), or if no +/// keyboard is on screen at all, the words go to the clipboard instead and +/// the pipeline shows its quiet "Copied" — the degradation the Mac uses when +/// nothing editable is focused — rather than a "Pasted" nobody saw. /// /// The text goes over as returned: the keyboard applies /// `InsertionSeparator.withLeadingSeparator` against the *live* text before the /// cursor, which may have moved since the press. nonisolated struct KeyboardRelayInjector: InjectorProtocol { - /// How recently the keyboard must have checked in to count as present. Its - /// heartbeat is every few seconds while it is on screen. - static let keyboardPresenceWindow: TimeInterval = 15 + /// How long the keyboard gets to insert before the clipboard takes over. + static let deliveryTimeout: TimeInterval = 3 + static let deliveryPoll: Duration = .milliseconds(250) func setTarget(_ focus: CapturedFocus?) async {} func insert(_ text: String, after priorText: String?, windowTitle: String?) async throws { - let seen = SharedStore.keyboardSeenAt ?? .distantPast - guard Date().timeIntervalSince(seen) < Self.keyboardPresenceWindow else { - await MainActor.run { UIPasteboard.general.string = text } - throw BlurtError.noEditableTarget - } - let result = DictationResult(id: UUID(), text: text, deliveredAt: Date()) + guard SharedStore.isKeyboardPresent else { try await copyOut(text) } + let result = DictationResult( + id: UUID(), text: text, deliveredAt: Date(), recipient: SharedStore.keyboardInstance) SharedStore.write(result, forKey: BlurtShared.Key.result) SharedStore.post(BlurtShared.Signal.result) + let deadline = Date().addingTimeInterval(Self.deliveryTimeout) + while Date() < deadline { + try await Task.sleep(for: Self.deliveryPoll) + guard let pending = SharedStore.read(DictationResult.self, forKey: BlurtShared.Key.result), + pending.id == result.id + else { return } + } + SharedStore.remove(forKey: BlurtShared.Key.result) + try await copyOut(text) + } + + /// The words to the clipboard, and the quiet "Copied" outcome. + private func copyOut(_ text: String) async throws -> Never { + await MainActor.run { UIPasteboard.general.string = text } + throw BlurtError.noEditableTarget } } diff --git a/App/BlurtiOS/BlurtiOS/Sources/ListeningSource.swift b/App/BlurtiOS/BlurtiOS/Sources/ListeningSource.swift index e24bc6b2..6c61333b 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/ListeningSource.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/ListeningSource.swift @@ -8,10 +8,28 @@ import Synchronization /// where the simulator has no capture session. nonisolated protocol ListeningSource: MicCaptureProtocol { var isOpen: Bool { get } - /// The 0…1 meter the keyboard pill renders, one value per chunk. + /// The 0…1 meter the orb and the home screen render, one value per chunk + /// of an open utterance. var levels: AsyncStream { get } - func open() throws - func close() + /// Opens the microphone. Async because opening a capture session blocks for + /// hundreds of milliseconds on a phone and must not do so on the main actor. + func open() async throws + func close() async +} + +/// Why a microphone couldn't open or start. +nonisolated enum ListeningSourceFailure: Error, LocalizedError { + /// A press arrived with no listening window open — the keyboard's job is to + /// open the app first, so this is a plumbing fault, not a user error. + case windowClosed + case noInputDevice + + var errorDescription: String? { + switch self { + case .windowClosed: "Blurt isn't listening. Open Blurt to start." + case .noInputDevice: "No microphone is available." + } + } } /// The per-utterance feed both microphones push into: the engine gets one @@ -61,12 +79,15 @@ nonisolated final class UtteranceFeed: Sendable { /// thread the microphone delivers on. func deliver(_ chunk: Data) { guard !chunk.isEmpty else { return } - levelsContinuation.yield(Self.level(of: chunk)) - state.withLock { state in - guard let sink = state.sink else { return } + // Nothing to report between utterances: a window sits open for minutes, + // and a level a dozen times a second would only keep views redrawing. + let delivered = state.withLock { state -> Bool in + guard let sink = state.sink else { return false } state.bytes += chunk.count sink.yield(chunk) + return true } + if delivered { levelsContinuation.yield(Self.level(of: chunk)) } } /// dBFS of a chunk of 16-bit PCM, mapped to 0…1 with the Mac meter's -50 dB diff --git a/App/BlurtiOS/BlurtiOS/Sources/ListeningWindow.swift b/App/BlurtiOS/BlurtiOS/Sources/ListeningWindow.swift index 001a14b9..74ecf235 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/ListeningWindow.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/ListeningWindow.swift @@ -11,7 +11,9 @@ import Observation /// no window is open. Once open, `UIBackgroundModes: audio` plus the active /// audio session keep it alive after the user swipes back. Every dictation /// extends the window; it closes on its own after `SharedStore.windowMinutes` -/// of silence (0 means never), or when the user closes it in the app. +/// of silence (0 means never), when the user closes it in the app, or when a +/// phone call, Siri or another app takes the microphone: the window is over +/// then, and saying so beats a mic that looks open and hears nothing. @MainActor @Observable final class ListeningWindow { @@ -25,11 +27,12 @@ final class ListeningWindow { private(set) var lastError: String? @ObservationIgnored private var expiry: Task? @ObservationIgnored private var heartbeat: Task? + @ObservationIgnored private var interruptions: Task? var isOpen: Bool { source.isOpen && (until.map { $0 > Date() } ?? false) } /// Opens the microphone for `SharedStore.windowMinutes`. Foreground only. - func open() { + func open() async { do { let audioSession = AVAudioSession.sharedInstance() // `.mixWithOthers` so the window doesn't silence whatever the user is @@ -39,13 +42,14 @@ final class ListeningWindow { try audioSession.setCategory( .playAndRecord, mode: .default, options: [.allowBluetoothHFP, .mixWithOthers, .defaultToSpeaker]) try audioSession.setActive(true) - try source.open() + try await source.open() lastError = nil extend() startHeartbeat() + watchInterruptions() } catch { lastError = error.localizedDescription - close() + await close() } } @@ -61,31 +65,51 @@ final class ListeningWindow { expiry = Task { [weak self] in try? await Task.sleep(for: .seconds(end.timeIntervalSinceNow)) guard !Task.isCancelled else { return } - self?.close() + await self?.close() } } /// Tells the keyboard the app is alive and the microphone really is open — /// `SharedStore.isListening` needs both. Stops reporting the moment capture - /// is interrupted (a phone call), so the keyboard's next tap reopens the app - /// instead of sending a press into silence. + /// is interrupted, so the keyboard's next tap reopens the app instead of + /// sending a press into silence. private func startHeartbeat() { heartbeat?.cancel() heartbeat = Task { [weak self] in while !Task.isCancelled { guard let self else { return } SharedStore.appSeenAt = source.isOpen ? Date() : nil - try? await Task.sleep(for: .seconds(5)) + try? await Task.sleep(for: .seconds(SharedStore.appHeartbeatInterval)) } } } - func close() { + /// A phone call, Siri, an alarm: iOS takes the microphone and tells us. The + /// window closes rather than pretending; the user reopens it in Blurt. + private func watchInterruptions() { + interruptions?.cancel() + interruptions = Task { [weak self] in + let began = NotificationCenter.default.notifications(named: AVAudioSession.interruptionNotification) + .filter { notification in + let raw = notification.userInfo?[AVAudioSessionInterruptionTypeKey] as? UInt + return raw.flatMap(AVAudioSession.InterruptionType.init(rawValue:)) == .began + } + for await _ in began { + guard !Task.isCancelled else { return } + await self?.close() + return + } + } + } + + func close() async { expiry?.cancel() expiry = nil heartbeat?.cancel() heartbeat = nil - source.close() + interruptions?.cancel() + interruptions = nil + await source.close() until = nil SharedStore.listeningUntil = nil SharedStore.appSeenAt = nil diff --git a/App/BlurtiOS/BlurtiOS/Sources/SimulatorAudioSource.swift b/App/BlurtiOS/BlurtiOS/Sources/SimulatorAudioSource.swift index 0c7efda5..20c72f03 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/SimulatorAudioSource.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/SimulatorAudioSource.swift @@ -20,9 +20,9 @@ var levels: AsyncStream { feed.levels } - deinit { close() } + deinit { closeNow() } - func open() throws { + func open() async throws { guard queue == nil else { return } var format = AudioStreamBasicDescription( mSampleRate: Double(SyncSTTLimits.sampleRate), mFormatID: kAudioFormatLinearPCM, @@ -33,7 +33,7 @@ let unmanagedSelf = Unmanaged.passUnretained(self).toOpaque() guard AudioQueueNewInput(&format, Self.deliver, unmanagedSelf, nil, nil, 0, &created) == noErr, let created - else { throw WindowedAudioSource.Failure.noInputDevice } + else { throw ListeningSourceFailure.noInputDevice } for _ in 0.. AsyncStream { guard isOpen else { - throw BlurtError.audioCaptureFailed(underlying: WindowedAudioSource.Failure.windowClosed) + throw BlurtError.audioCaptureFailed(underlying: ListeningSourceFailure.windowClosed) } return feed.begin() } diff --git a/App/BlurtiOS/BlurtiOS/Sources/TermPack.swift b/App/BlurtiOS/BlurtiOS/Sources/TermPack.swift index e1bbd25e..be28fd8d 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/TermPack.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/TermPack.swift @@ -12,11 +12,20 @@ extension UTType { /// slang, so everyone's dictation gets them right. Shared as a `.blurtterms` /// file (the share sheet writes it), opened by a tap; also readable from a /// `blurt://terms?add=a,b,c&name=…&from=…` link. -nonisolated struct TermPack: Codable, Hashable, Transferable { +nonisolated struct TermPack: Codable, Identifiable, Transferable { var name: String var from: String? var terms: [String] + var id: String { "\(name)|\(from ?? "")|\(terms.joined(separator: ","))" } + + /// The request's own cap on key terms (`keyterms_prompt`, 100), which is + /// also as many as a list is worth; a file over this size, or a term, name + /// or sender longer than a line, is refused. + static let termCap = 100 + static let fileCap = 64 * 1024 + static let lengthCap = 80 + static var transferRepresentation: some TransferRepresentation { FileRepresentation(exportedContentType: .blurtTerms) { pack in let url = FileManager.default.temporaryDirectory @@ -42,22 +51,39 @@ nonisolated struct TermPack: Codable, Hashable, Transferable { return "\(lead) (\(name)): \(KeyTermList.join(terms))" } + /// Whether a URL is meant to be a pack at all — a `.blurtterms` file or a + /// `blurt://terms` link — so a broken one can be reported rather than + /// ignored. + static func looksLikePack(_ url: URL) -> Bool { + if url.isFileURL { return url.pathExtension.lowercased() == "blurtterms" } + return url.scheme == BlurtShared.urlScheme && url.host() == "terms" + } + /// A pack from a file tapped in Messages or a `blurt://terms` link; nil for - /// anything else the app is asked to open. + /// anything else the app is asked to open, or a pack over the caps. A file + /// iOS handed over in the app's Inbox is deleted once read. static func from(_ url: URL) -> TermPack? { + guard looksLikePack(url) else { return nil } if url.isFileURL { - guard url.pathExtension.lowercased() == "blurtterms", let data = try? Data(contentsOf: url), - var pack = try? JSONDecoder().decode(TermPack.self, from: data) + defer { if url.path.contains("/Inbox/") { try? FileManager.default.removeItem(at: url) } } + guard let size = (try? url.resourceValues(forKeys: [.fileSizeKey]))?.fileSize, size <= fileCap, + let data = try? Data(contentsOf: url), let pack = try? JSONDecoder().decode(TermPack.self, from: data) else { return nil } - pack.terms = KeyTermList.parse(KeyTermList.join(pack.terms)) - return pack.terms.isEmpty ? nil : pack + return pack.capped() } - guard url.scheme == BlurtShared.urlScheme, url.host() == "terms", - let items = URLComponents(url: url, resolvingAgainstBaseURL: false)?.queryItems - else { return nil } + guard let items = URLComponents(url: url, resolvingAgainstBaseURL: false)?.queryItems else { return nil } let value = { (name: String) in items.first { $0.name == name }?.value } - let terms = KeyTermList.parse(value("add") ?? "") + return TermPack( + name: value("name") ?? "Shared key terms", from: value("from"), terms: KeyTermList.parse(value("add") ?? "") + ).capped() + } + + /// The pack within the caps, or nil when nothing usable is left. + private func capped() -> TermPack? { + let kept = KeyTermList.parse(KeyTermList.join(terms)).filter { $0.count <= Self.lengthCap } + let terms = Array(kept.prefix(Self.termCap)) guard !terms.isEmpty else { return nil } - return TermPack(name: value("name") ?? "Shared key terms", from: value("from"), terms: terms) + return TermPack( + name: String(name.prefix(Self.lengthCap)), from: from.map { String($0.prefix(Self.lengthCap)) }, terms: terms) } } diff --git a/App/BlurtiOS/BlurtiOS/Sources/ThemePickerView.swift b/App/BlurtiOS/BlurtiOS/Sources/ThemePickerView.swift index 8f34bda8..7019c2fb 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/ThemePickerView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/ThemePickerView.swift @@ -31,7 +31,8 @@ private struct ThemeCard: View { let chosen: Bool let pick: () -> Void - /// The preview keyboard is the full layout at a third of a phone's width. + /// The preview keyboard is the full layout, drawn at a phone's width and + /// scaled down to fit two cards across. private static let previewWidth: CGFloat = 393 private static let scale: CGFloat = 0.42 diff --git a/App/BlurtiOS/BlurtiOSTests/FeedAndLayoutTests.swift b/App/BlurtiOS/BlurtiOSTests/FeedAndLayoutTests.swift new file mode 100644 index 00000000..6bb5c172 --- /dev/null +++ b/App/BlurtiOS/BlurtiOSTests/FeedAndLayoutTests.swift @@ -0,0 +1,59 @@ +import Foundation +import Testing + +@testable import BlurtiOS + +@Suite("Utterance feed") +struct UtteranceFeedTests { + private func pcm(_ samples: [Int16]) -> Data { + samples.withUnsafeBufferPointer { Data(buffer: $0) } + } + + @Test("level: silence is 0, full scale is 1, room ambient under the floor is 0") + func level() { + #expect(UtteranceFeed.level(of: pcm([0, 0, 0, 0])) == 0) + #expect(UtteranceFeed.level(of: pcm([Int16.max, Int16.max, -Int16.max, -Int16.max])) == 1) + #expect(UtteranceFeed.level(of: pcm([3, -3, 2, -2])) == 0) + #expect(UtteranceFeed.level(of: Data()) == 0) + let mid = UtteranceFeed.level(of: pcm([8000, -8000, 8000, -8000])) + #expect(mid > 0 && mid < 1) + } + + @Test("chunks reach the utterance between begin and end, the tally counts them, and nothing outside") + func tally() async { + let feed = UtteranceFeed() + feed.deliver(pcm([1000, -1000])) + let stream = feed.begin() + feed.deliver(pcm([1000, -1000])) + feed.deliver(pcm([1000, -1000, 1000])) + let bytes = feed.end() + #expect(bytes == 10) + var received = 0 + for await chunk in stream { received += chunk.count } + #expect(received == 10) + feed.deliver(pcm([1])) + #expect(feed.end() == 0) + } +} + +@Suite("Layout arithmetic") +struct LayoutArithmeticTests { + @Test("the full layout's height is its rows at the theme spacing (DESIGN.md)") + func fullHeight() { + let expected = + 2 * KeyboardRootView.verticalMargin + VoiceBar.height + 4 * KeyboardPalette.rowGap + 4 * KeyCap.height + #expect(KeyboardLayout.full.height == expected) + } + + @Test("the gallery reads a layout, states and an optional theme from the launch arguments") + func galleryRows() { + #expect(KeyboardGalleryView.rows(from: ["app"]).isEmpty) + #expect(KeyboardGalleryView.rows(from: ["app", "-BlurtGallery", "panel"]).isEmpty) + #expect(KeyboardGalleryView.rows(from: ["app", "-BlurtGallery", "nope", "idle"]).isEmpty) + let rows = KeyboardGalleryView.rows(from: ["app", "-BlurtGallery", "panel", "idle,keys,term", "mint"]) + #expect(rows.count == 3) + #expect(rows[1].model.effectiveLayout == .full) + #expect(rows[2].model.termDraft == "Rizz") + #expect(rows[0].model.palette.id == "mint") + } +} diff --git a/App/BlurtiOS/BlurtiOSTests/ProtocolTests.swift b/App/BlurtiOS/BlurtiOSTests/ProtocolTests.swift new file mode 100644 index 00000000..8c451d96 --- /dev/null +++ b/App/BlurtiOS/BlurtiOSTests/ProtocolTests.swift @@ -0,0 +1,306 @@ +import BlurtEngine +import Foundation +import Testing +import UIKit + +@testable import BlurtiOS + +@Suite("The two-process contract", .serialized) +@MainActor +struct ProtocolTests { + @Test("the key-term key is the engine's own, so the app's and the keyboard's readers agree") + func keyTermsKey() { + #expect(SharedStore.keyTermsKey == KeyTermsStore.defaultsKey) + } + + @Test("listening needs both a live window and a live app") + func isListening() { + let suite = ScratchSuite() + defer { suite.tearDown() } + let now = Date() + SharedStore.listeningUntil = now.addingTimeInterval(600) + SharedStore.appSeenAt = now.addingTimeInterval(-2) + #expect(SharedStore.isListening(now: now)) + SharedStore.appSeenAt = now.addingTimeInterval(-(SharedStore.presenceWindow + 1)) + #expect(!SharedStore.isListening(now: now)) + SharedStore.appSeenAt = now + SharedStore.listeningUntil = now.addingTimeInterval(-1) + #expect(!SharedStore.isListening(now: now)) + } + + @Test("the presence windows outlast two missed heartbeats") + func presenceRatio() { + #expect(SharedStore.presenceWindow > 2 * SharedStore.appHeartbeatInterval) + #expect(SharedStore.presenceWindow > 2 * SharedStore.keyboardHeartbeatInterval) + } + + @Test("addKeyTerm trims and refuses a duplicate in any case") + func addKeyTerm() { + let suite = ScratchSuite() + defer { suite.tearDown() } + #expect(SharedStore.addKeyTerm(" Rizz ")) + #expect(!SharedStore.addKeyTerm("rizz")) + #expect(!SharedStore.addKeyTerm(" ")) + #expect(SharedStore.keyTerms == ["Rizz"]) + } + + @Test("with no keyboard on screen the words go to the clipboard and the phase is the quiet one") + func relayFallsBackToClipboard() async { + let suite = ScratchSuite() + defer { suite.tearDown() } + SharedStore.keyboardSeenAt = nil + UIPasteboard.general.string = "" + let injector = KeyboardRelayInjector() + await #expect(throws: BlurtError.noEditableTarget) { + try await injector.insert("hello there", after: nil, windowTitle: nil) + } + #expect(UIPasteboard.general.string == "hello there") + #expect(SharedStore.read(DictationResult.self, forKey: BlurtShared.Key.result) == nil) + } + + @Test("a result the keyboard never takes is copied out after the delivery timeout") + func relayTimesOut() async { + let suite = ScratchSuite() + defer { suite.tearDown() } + SharedStore.keyboardSeenAt = Date() + SharedStore.keyboardInstance = "kb-1" + UIPasteboard.general.string = "" + let injector = KeyboardRelayInjector() + let started = Date() + await #expect(throws: BlurtError.noEditableTarget) { + try await injector.insert("late words", after: nil, windowTitle: nil) + } + #expect(Date().timeIntervalSince(started) >= KeyboardRelayInjector.deliveryTimeout - 0.5) + #expect(UIPasteboard.general.string == "late words") + #expect(SharedStore.read(DictationResult.self, forKey: BlurtShared.Key.result) == nil) + } + + @Test("a result taken by the keyboard counts as delivered") + func relayDelivered() async throws { + let suite = ScratchSuite() + defer { suite.tearDown() } + SharedStore.keyboardSeenAt = Date() + SharedStore.keyboardInstance = "kb-1" + let injector = KeyboardRelayInjector() + let taker = Task { + try? await Task.sleep(for: .milliseconds(300)) + let pending = SharedStore.read(DictationResult.self, forKey: BlurtShared.Key.result) + SharedStore.remove(forKey: BlurtShared.Key.result) + return pending + } + try await injector.insert("on time", after: nil, windowTitle: nil) + let taken = await taker.value + #expect(taken?.text == "on time") + #expect(taken?.recipient == "kb-1") + } +} + +@Suite("Keyboard model: the mic, the phase and results", .serialized) +@MainActor +struct KeyboardModelProtocolTests { + /// A keyboard that is ready to dictate, wired to a fake field and a + /// capture of the commands it sends. + struct Rig { + let model: KeyboardModel + let proxy: FakeProxy + let commands: Commands + } + + private func ready() -> Rig { + let proxy = FakeProxy() + let model = KeyboardModel() + model.proxyOverride = proxy + model.hasFullAccess = true + let now = Date() + SharedStore.listeningUntil = now.addingTimeInterval(600) + SharedStore.appSeenAt = now + model.isListening = true + let commands = Commands() + model.transport = { commands.sent.append($0) } + return Rig(model: model, proxy: proxy, commands: commands) + } + + final class Commands { + var sent: [KeyboardCommand] = [] + } + + private func snapshot(_ state: PhaseSnapshot.State, level: Double = 0) -> PhaseSnapshot { + PhaseSnapshot(state: state, message: nil, level: level, at: Date()) + } + + @Test("a tap presses and latches; the next tap releases") + func tapThenTap() { + let suite = ScratchSuite() + defer { suite.tearDown() } + let rig = ready() + let model = rig.model + let commands = rig.commands + model.micDown() + model.micUp() + #expect(commands.sent.map(\.kind) == [.press]) + model.apply(snapshot(.recording)) + model.micDown() + model.micUp() + #expect(commands.sent.map(\.kind) == [.press, .release]) + } + + @Test("a dictation started elsewhere latches the gate, so one tap stops it") + func latchOnInFlight() { + let suite = ScratchSuite() + defer { suite.tearDown() } + let rig = ready() + let model = rig.model + let commands = rig.commands + model.apply(snapshot(.recording)) + #expect(!model.gate.isIdle) + model.micDown() + model.micUp() + #expect(commands.sent.map(\.kind) == [.release]) + } + + @Test("a press while transcribing is refused rather than dropped by the engine") + func noPressWhileProcessing() { + let suite = ScratchSuite() + defer { suite.tearDown() } + let rig = ready() + let model = rig.model + let commands = rig.commands + model.apply(snapshot(.processing)) + model.micDown() + model.micUp() + #expect(commands.sent.isEmpty) + #expect(model.gate.isIdle) + } + + @Test("a settled phase resets a latched gate") + func resetOnSettled() { + let suite = ScratchSuite() + defer { suite.tearDown() } + let model = ready().model + model.micDown() + model.micUp() + #expect(!model.gate.isIdle) + model.apply(snapshot(.pasted)) + #expect(model.gate.isIdle) + } + + @Test("leaving the screen releases a latched recording and cancels anything earlier") + func disappearEndsDictation() { + let suite = ScratchSuite() + defer { suite.tearDown() } + let rig = ready() + let model = rig.model + let commands = rig.commands + model.micDown() + model.micUp() + model.apply(snapshot(.recording)) + model.disappeared() + #expect(commands.sent.map(\.kind) == [.press, .release]) + #expect(model.gate.isIdle) + #expect(SharedStore.keyboardSeenAt == nil) + } + + @Test("a result is inserted once, only while fresh, only if addressed here") + func results() { + let suite = ScratchSuite() + defer { suite.tearDown() } + let rig = ready() + let model = rig.model + let proxy = rig.proxy + proxy.before = "Hi" + func deliver(_ text: String, age: TimeInterval = 0, to recipient: String?) { + SharedStore.write( + DictationResult(id: UUID(), text: text, deliveredAt: Date().addingTimeInterval(-age), recipient: recipient), + forKey: BlurtShared.Key.result) + } + deliver("one", to: nil) + model.resultArrived() + #expect(proxy.before == "Hi one") + #expect(SharedStore.read(DictationResult.self, forKey: BlurtShared.Key.result) == nil) + deliver("two", age: 20, to: nil) + model.resultArrived() + #expect(proxy.before == "Hi one") + deliver("three", to: "someone-else") + model.resultArrived() + #expect(proxy.before == "Hi one") + deliver("four", to: model.instanceID) + model.resultArrived() + #expect(proxy.before == "Hi one four") + } + + @Test("the term field never claims a cursor move or a selection") + func termFieldIgnoresCursorMoves() { + let suite = ScratchSuite() + defer { suite.tearDown() } + let rig = ready() + let model = rig.model + let proxy = rig.proxy + proxy.before = "Hello wor" + proxy.after = "ld" + model.beginAddingTerm() + // The cursor moved two to the right: both sides changed. + proxy.before = "Hello world" + proxy.after = "" + model.contextChanged() + #expect(model.termDraft == "") + #expect(proxy.before == "Hello world") + // A selection appeared with the same growth. + proxy.before = "Hello wor" + proxy.after = "ld" + model.beginAddingTerm() + proxy.before = "Hello world" + proxy.selected = "ld" + model.contextChanged() + #expect(model.termDraft == "") + } + + @Test("a selection with spaces around it is replaced with the spaces kept") + func termReplaceKeepsSpaces() { + let suite = ScratchSuite() + defer { suite.tearDown() } + let rig = ready() + let model = rig.model + let proxy = rig.proxy + proxy.before = "he said" + proxy.selected = " riz " + model.beginAddingTerm() + #expect(model.termDraft == "riz") + model.type("z") + model.saveTerm() + #expect(proxy.before == "he said rizz ") + #expect(SharedStore.keyTerms == ["rizz"]) + } + + @Test("shift follows the field: words, all characters, none") + func shiftModes() { + let suite = ScratchSuite() + defer { suite.tearDown() } + let rig = ready() + let model = rig.model + let proxy = rig.proxy + proxy.before = "hello " + proxy.autocapitalizationType = .words + model.contextChanged() + #expect(model.shifted) + proxy.before = "hello w" + model.contextChanged() + #expect(!model.shifted) + proxy.autocapitalizationType = .allCharacters + model.contextChanged() + #expect(model.shifted) + proxy.autocapitalizationType = .none + model.shifted = false + proxy.before = "" + model.contextChanged() + #expect(!model.shifted) + } + + @Test("number fields open on the symbols page") + func symbolsForNumbers() { + #expect(KeyboardModel.wantsSymbols(.numberPad)) + #expect(KeyboardModel.wantsSymbols(.phonePad)) + #expect(KeyboardModel.wantsSymbols(.decimalPad)) + #expect(!KeyboardModel.wantsSymbols(.default)) + #expect(!KeyboardModel.wantsSymbols(nil)) + } +} diff --git a/App/BlurtiOS/BlurtiOSTests/TestSuite.swift b/App/BlurtiOS/BlurtiOSTests/TestSuite.swift new file mode 100644 index 00000000..77370e88 --- /dev/null +++ b/App/BlurtiOS/BlurtiOSTests/TestSuite.swift @@ -0,0 +1,21 @@ +import Foundation + +@testable import BlurtiOS + +/// A throwaway App Group for one test: nothing a test writes reaches the real +/// suite the installed app and keyboard share (the engine's own rule about +/// never touching the real Keychain in tests, applied here). +@MainActor +struct ScratchSuite { + let name: String + + init() { + name = "test-\(UUID().uuidString)" + SharedStore.override = UserDefaults(suiteName: name) + } + + func tearDown() { + SharedStore.override?.removePersistentDomain(forName: name) + SharedStore.override = nil + } +} diff --git a/App/BlurtiOS/DESIGN.md b/App/BlurtiOS/DESIGN.md index 8cf26c47..41ed16d7 100644 --- a/App/BlurtiOS/DESIGN.md +++ b/App/BlurtiOS/DESIGN.md @@ -4,7 +4,7 @@ The iPhone app and its keyboard are the Mac app's design on a phone: the same ink, the same two greens, the same orb, the Mac pill's meter and ring. Nothing here was invented; every number traces to a Mac source file, and where the phone needed something the Mac has no equivalent for, this file says what was decided and -why. The keyboard is done; the app's own screens are next (see the end). +why. Source of truth on the Mac side: `App/Blurt/Blurt/Branding/BlurtBrand.swift` (tokens, orb gradient), `App/Blurt/Blurt/Overlay/OverlayView.swift` and @@ -26,7 +26,9 @@ BLURT_LAUNCH_ARGS="-BlurtGallery full idle,recording,error" scripts/ios-sim.sh - Layouts: `slimBar`, `panel`, `full`. States: `off` (no Full Access), `start` (the app isn't listening), then the pipeline's `idle`, `connecting`, -`recording` (level 0.62), `processing`, `pasted`, `copied`, `error`. The +`recording` (level 0.62), `processing`, `pasted`, `copied`, `error`; and two +of the keyboard's own: `keys` (the panel flipped to its keyboard page) and +`term` (the key-term field mid-typing, e.g. `-BlurtGallery panel keys,term`). The gallery is `BlurtiOS/Sources/KeyboardGalleryView.swift`, debug builds only; the keyboard's sources are compiled into the app for it (`project.yml`). @@ -79,9 +81,17 @@ seconds, inside the app you're typing in, never a trip to Settings. misheard word in your text is replaced with what you typed. A success haptic, and the + shows a check for 1.2 s. -× or an empty save leaves the mode. The list itself is edited in Settings → -Transcription, which shows the count; the engine's caps (100 terms, 2048 -bytes) apply on the request, first terms first. +× or an empty save leaves the mode, and so does the keyboard going away. A +hardware keyboard (an iPad's, a Bluetooth one, the simulator's Mac) types +past the on-screen keys into the app's field; while the term field is open a +short run that appears there right after where the cursor was — the text +before the cursor grew, the text after it didn't, nothing is selected — is +moved into the term and taken back out of the field; a cursor move changes +both sides and is left alone. A selection that carried spaces around the +word keeps them on replacement. The list itself is edited in Settings → +Transcription, which shows the count against the request's cap of 100 terms +(`KeytermsBoost`); the engine applies the caps on the request, first terms +first. ## Sharing key terms @@ -92,13 +102,17 @@ declared document type, `dev.alex.blurt.terms`) with the words as the message text, so a friend without Blurt still gets them. A tap on the file in Messages opens Blurt with "Add N key terms?": every term ticked, untick any, Add merges the rest without duplicates. A `blurt://terms?add=a,b,c&name=…&from=…` -link does the same (`TermPack`, `ImportTermsView`). +link does the same (`TermPack`, `ImportTermsView`). A pack is refused over +64 KB, past 100 terms (the request's own cap; the rest are dropped) or with a +term, name or sender over 80 characters; a file or link that claims to be a +pack and isn't gets "Couldn't read that list". A file iOS handed over in the +app's Inbox is deleted once read. ## Adapting to the phone's own keyboard settings Nothing to configure: key clicks play only if the user has keyboard clicks on (the input view adopts `UIInputViewAudioFeedback`; `playInputClick` on -every key); the return key says what the field asks — send, search, go, done, +letters, space, delete and return); the return key says what the field asks — send, search, go, done, next, join — with the glyph otherwise; a number, decimal or phone field opens on the symbols page; capitalisation follows the field's `autocapitalizationType`; the letter rows follow the phone's first language @@ -111,8 +125,11 @@ On by default, with a toggle in Settings: a dictation starts the moment the keyboard comes up in a text field — the same synthetic tap through the engine's gate, so it latches and the next tap of the mic stops it. Only when the app is listening and nothing is in flight; otherwise the orb sits dimmed -and the first tap opens Blurt. It fires on the keyboard's -appearance, not on every field change while it stays up. +and the first tap opens Blurt. It fires on the keyboard's appearance, not on +every field change while it stays up. When the keyboard leaves the screen +with a dictation it started, it releases a recording (the words still land, +on the clipboard if no keyboard is there) and cancels anything earlier, so +nothing records on without it. ## Tokens (`Shared/BlurtBrand.swift`) @@ -128,15 +145,15 @@ appearance, not on every field change while it stays up. | `orbGradient` | 8 stops | the design's own (`App elements/Recording.svg`), bottom→top | | `orbRingGradient` | green→white | the ring, top-leading to bottom-trailing | -The keyboard is a **fixed dark surface** in both appearances, for the reason -the Mac pill is: it floats over whichever app the user is typing in, so it -cannot take a cue from that app, and it must read the same over a white Notes -page and a black Messages thread. Nothing on it uses `accent`. +The keyboard's surface is **fixed per theme**, whatever the host app's +appearance, for the reason the Mac pill is: it floats over whichever app the +user is typing in, so it cannot take a cue from that app, and it must read the +same over a white Notes page and a black Messages thread. Nothing on it uses +`accent`. ## Type -Status line: 11 pt semibold, uppercase, tracking 1.1 (the Mac's 9 pt / 0.9, -scaled for a phone at arm's length). Key legends: letters 22 pt regular, +Key legends: letters 22 pt regular, everything else 16 pt medium. System font throughout. ## Components (`BlurtKeyboard/Sources/`) @@ -180,7 +197,7 @@ a hold is push-to-talk exactly as on the Mac; a touch that travelled more than 24 pt cancels instead (it was a swipe). Cancel is the orange × in the panel's top-right corner while something is in flight. -**Keys** (`KeyCap`, `LetterKey`) — 42 pt tall, radius 6, 6 % white hairline; +**Keys** (`KeyCap`, `LetterKey`) — 42 pt tall, radius 5, 6 % white hairline; `key` for letters and space, `keyDark` for modifiers; a key brightens 15 % while pressed rather than dimming. @@ -212,6 +229,37 @@ speaks the error message; the meters are hidden from VoiceOver. Reduce Motion stops the ring and the meter's idle wave; heights still follow the level. +## The two processes, and every number + +The app listens and transcribes; the keyboard is a remote control. They talk +over the App Group's `UserDefaults` (payloads as JSON) plus Darwin +notifications that carry nothing and just say "look" (`SharedState.swift`). + +| Rule | Value | Why | +| ---------------------- | ---------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | +| presence | heartbeat 5 s (app), 4 s (keyboard); window 15 s | more than twice a heartbeat, so one missed beat isn't absence; a killed process is absent within seconds | +| listening | window not lapsed **and** app seen within 15 s | a killed app, or a phone call, with the window's end still in the future | +| result freshness | 10 s | a notification held for a suspended keyboard arrives minutes late | +| result addressing | `recipient` = the keyboard instance last seen | two live keyboards (two host apps) must not both insert | +| result delivery | the app waits 3 s (poll 250 ms) for the keyboard to take the result; else clipboard + "Copied" | "Pasted" is never a guess | +| command freshness | 10 s | a held press from minutes ago must not start a dictation on resume | +| command retry | one re-signal after 600 ms with no phase change | a missed Darwin notification would leave the gate latched over nothing | +| phase staleness | notices 3 s (max dwell 2 s + 1); in flight 130 s (the 120 s cap + 10) | the keyboard reads the snapshot on every appearance | +| notice dwell | pasted 1.2 s; copied, error 2 s | the Mac's 0.8 / 1.6 s, a little longer with no hover | +| press delay on the orb | 90 ms | a swipe that starts on the orb never starts a dictation it must then cancel | +| tap travel | 12 pt (keys), 24 pt (orb), swipe ≥ 48 pt horizontal and 1.5× the vertical | the carousel's swipe never types or dictates | +| level publish | every 80 ms while recording | the orb's meter, off the capture path's back | +| lexicon refresh | hourly | thousands of contacts on a keyboard memory budget | +| height change | 0.25 s; constraint priority 999 | iOS honours a keyboard's height at just under required | +| hero glow | `greenOnDark` 35–80 % with the level; radius 0.1–0.35 × the orb's size | one formula for the keyboard and the home screen | +| letter pop-up | 32 pt glyph, key width + 18 × 56, radius 9, 58 pt above | the system keyboard's | +| term field | 36 pt, 17 pt text, caret 0.5 s; the + is 32 pt | — | +| term packs | ≤ 64 KB, ≤ 100 terms, ≤ 80 characters each | the request's cap; unbounded input from a stranger | + +Tests pin the rules that can be pinned (`BlurtiOSTests`: the contract, the +gate, results, the term field, the feed, the layout arithmetic); anything +that gains a number here should gain a line there. + ## The app's screens (`BlurtiOS/Sources/`) Appearance-adaptive, unlike the keyboard: `accent` (the catalog's @@ -223,17 +271,17 @@ shared, not copied (`project.yml`). **Home** (`HomeView.swift`) — the Mac's ready screen, stacked for a phone: -| Piece | What | -| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| Bar | the wordmark (tinted accent, 22 pt tall) centred; the gear → Settings | -| Setup card | only while something is missing: sign in (stub; debug builds take a key), microphone, keyboard + Full Access | -| Hero card | the orb, 112 pt, ring 2 pt sweeping while the mic is open or a dictation is in flight, glowing with the level while recording; a title2 line (Not listening · Ready to dictate · Listening… · Transcribing… · Pasted · Copied · the error) and a callout under it; the meter while recording; **Start listening** (prominent) or **Stop listening** (bordered, destructive); "Dictate here, to the clipboard" as a text button | -| Style | chips: Default and each profile, the active one filled with the accent; Edit → the styles editor | -| Recent | cards: three lines of text, the style as a tinted capsule, the relative time, a copy button; an empty-state card | -| Footer | "Powered by AssemblyAI", caption | +| Piece | What | +| ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Bar | the wordmark (tinted accent, 22 pt tall) centred; the gear → Settings | +| Setup card | only while something is missing: sign in (stub; debug builds take a key), microphone, keyboard + Full Access | +| Hero card | the orb, 112 pt, ring 2 pt sweeping while the mic is open or a dictation is in flight, glowing with the level while recording (the keyboard orb's formula); a title2 line (Not listening · Ready to dictate · Connecting… · Listening… · Transcribing… · Pasted · Copied · the error) and a callout under it; the meter while recording; **Start listening** (prominent; refused without a key, with a line saying so) or **Stop listening** (bordered, destructive; cancels a dictation in flight before closing, so nothing is transcribed for nobody); "Dictate here, to the clipboard" as a text button | +| Style | chips: Default and each profile, the active one filled with the accent; Edit → the styles editor | +| Recent | cards: three lines of text, the style as a tinted capsule, the relative time, a copy button; an empty-state card | +| Footer | "Powered by AssemblyAI", caption | **Settings** (`SettingsView.swift`) — a sheet, grouped as the Mac's: Keyboard -(layout, look, hands-free), Listening (the window), Transcription (enhanced +(layout, theme, hands-free), Listening (the window), Transcription (enhanced transcripts, output styles, key terms with the contact-name count), Account (sign-in stub; the API key in debug builds), About (version, GitHub, Powered by AssemblyAI). diff --git a/App/BlurtiOS/README.md b/App/BlurtiOS/README.md index 21918e1d..7770339e 100644 --- a/App/BlurtiOS/README.md +++ b/App/BlurtiOS/README.md @@ -39,13 +39,13 @@ inherited from the Mac app and must become org-owned before the App Store. ## Design -`DESIGN.md` — the tokens, the pill, the orb, the meter, the three layouts, the +`DESIGN.md` — the tokens, the orb, the meter, the three layouts, the app's screens, all traced to the Mac app's sources, plus the gallery that renders every layout and state for a screenshot and the launch flags that reach every app state. ## Getting Xcode -Any Xcode from 26.6 (what CI builds with) works; a phone on iOS 27 needs Xcode 27, which +Any Xcode from 26.6 (CI's macos-26 runner has it) works; a phone on iOS 27 needs Xcode 27, which needs macOS 26.6. The Mac App Store is one way. The other is Apple's developer site through [`xcodes`](https://github.com/XcodesOrg/xcodes): Homebrew cannot build it without Xcode already present (chicken and egg), so take the prebuilt binary — @@ -67,7 +67,7 @@ tests stay `swift test`. Anything with a rule in `DESIGN.md` should have a test ## Testing in the simulator Signing and the team don't matter here, and the App Group works, so the whole -loop runs. `AVCaptureSession` carries no audio in the simulator, so the app uses +loop runs (`scripts/ios-lib.sh` holds the one signing recipe and the simulator pick). `AVCaptureSession` carries no audio in the simulator, so the app uses `SimulatorAudioSource` (an Audio Queue on the Mac's microphone) there and `WindowedAudioSource` on a phone. @@ -86,7 +86,7 @@ shows its console. ## Testing on a phone -1. Install Xcode 26.6 or newer — the version CI builds with (`xcodes install 26.6 --select`, or +1. Install Xcode 26.6 or newer — CI's runner has 26.6 (`xcodes install 26.6 --select`, or the Mac App Store). A phone on iOS 27 needs Xcode 27, which needs macOS 26.6. Then once: ```bash @@ -117,17 +117,18 @@ shows its console. ## What is still a stub +- **Autocorrect and the suggestion bar** on the full keyboard. + - **Sign in with AssemblyAI.** The shipping app signs the user in and gets a key behind the scenes; that service does not exist yet. Debug builds show "Use an API key instead" (`KeyEntryView`) so the pipeline can be tested now. - **Returning to the host app.** After "Start Blurt" the user swipes back; iOS 26.4 ended automatic switch-back for everyone. - **The full keyboard** has no autocorrect or suggestions yet. -- **Interruptions** (a phone call) close the listening window; the user reopens it. ## What to verify on a phone first The listening window's life in the background (capture keeps flowing after the swipe back; battery over an hour); keyboard → app → back on iOS 26 and 27; the -keyboard's memory with the pill animating; how long the lexicon takes on a phone +keyboard's memory with the orb growing into the wave; how long the lexicon takes on a phone with thousands of contacts; and, once the service exists, sign-in end to end. diff --git a/App/BlurtiOS/Shared/BlurtBrand.swift b/App/BlurtiOS/Shared/BlurtBrand.swift index faf808ea..5d09eaf1 100644 --- a/App/BlurtiOS/Shared/BlurtBrand.swift +++ b/App/BlurtiOS/Shared/BlurtBrand.swift @@ -4,11 +4,11 @@ import SwiftUI /// from the 2026-08-31 comps), plus the handful of shades the keyboard needs /// for a surface the Mac never draws. Compiled into the app and the keyboard. /// -/// The keyboard is a fixed dark surface the way the Mac's overlay pill is: it -/// floats over whatever app the user is typing in, so it cannot take its cue -/// from that app's appearance, and it must read the same on a white Notes page -/// and a black Messages thread. Everything on it therefore names the raw -/// shades — `greenOnDark`, `ink` — and never `accent`. +/// The keyboard's surface is fixed per theme, the way the Mac's overlay pill is +/// fixed: it floats over whatever app the user is typing in, so it cannot take +/// its cue from that app's appearance, and it must read the same on a white +/// Notes page and a black Messages thread. Everything on it therefore names +/// the raw shades — `greenOnDark`, `ink` — and never `accent`. enum BlurtBrand { /// `#01762F` — the wordmark green, for light chrome. nonisolated static let green = Color(red: 1 / 255, green: 118 / 255, blue: 47 / 255) diff --git a/App/BlurtiOS/Shared/DarwinObserver.swift b/App/BlurtiOS/Shared/DarwinObserver.swift new file mode 100644 index 00000000..97aaa495 --- /dev/null +++ b/App/BlurtiOS/Shared/DarwinObserver.swift @@ -0,0 +1,30 @@ +import Foundation + +/// A Darwin-notification subscription that lives as long as this object does. +/// +/// The handler runs on whichever thread the system delivers on and is +/// `@Sendable` for that reason; hop to the main actor inside it when the work +/// is UI. A class rather than a token so `deinit` can deregister — a listener +/// left behind outlives its owner, since the system holds the callback. +nonisolated final class DarwinObserver: Sendable { + private let name: String + private let handler: @Sendable () -> Void + + init(name: String, handler: @escaping @Sendable () -> Void) { + self.name = name + self.handler = handler + let observer = Unmanaged.passUnretained(self).toOpaque() + CFNotificationCenterAddObserver( + CFNotificationCenterGetDarwinNotifyCenter(), observer, + { _, observer, _, _, _ in + guard let observer else { return } + Unmanaged.fromOpaque(observer).takeUnretainedValue().handler() + }, name as CFString, nil, .deliverImmediately) + } + + deinit { + CFNotificationCenterRemoveObserver( + CFNotificationCenterGetDarwinNotifyCenter(), Unmanaged.passUnretained(self).toOpaque(), + CFNotificationName(name as CFString), nil) + } +} diff --git a/App/BlurtiOS/Shared/SharedState.swift b/App/BlurtiOS/Shared/SharedState.swift index 68a542ab..a7e407a6 100644 --- a/App/BlurtiOS/Shared/SharedState.swift +++ b/App/BlurtiOS/Shared/SharedState.swift @@ -28,6 +28,7 @@ nonisolated enum BlurtShared { static let command = "command" static let result = "result" static let keyboardSeenAt = "keyboardSeenAt" + static let keyboardInstance = "keyboardInstance" static let appSeenAt = "appSeenAt" static let keyboardEverSeen = "keyboardEverSeen" static let lexicon = "lexicon" @@ -50,8 +51,8 @@ nonisolated enum KeyboardLayout: String, CaseIterable, Codable, Sendable, Identi /// A slim strip: the mic, delete, return and the globe. Typing letters means /// switching back to the system keyboard. case slimBar - /// A mic panel with the status pill, a cancel button and a few keys — the - /// shape Wispr and Aqua ship. + /// A big orb with cancel beside it and a few keys — the shape Wispr and + /// Aqua ship — that swipes to the full keyboard. case panel /// A complete keyboard with the mic as the main key, so nobody has to switch /// keyboards to fix a typo. @@ -75,8 +76,6 @@ nonisolated enum KeyboardLayout: String, CaseIterable, Codable, Sendable, Identi } } - /// The keyboard's height in points. Fixed per layout; the system keyboard is - /// about 216 on a phone, which is what `panel` matches. /// The keyboard's height on screen, from the layout's rows at the iPhone /// keyboard's own spacing: see `App/BlurtiOS/DESIGN.md` for the arithmetic. var height: CGFloat { @@ -118,10 +117,14 @@ nonisolated struct DictationResult: Codable, Sendable { let id: UUID let text: String let deliveredAt: Date + /// The keyboard instance the words are for — the one whose heartbeat the + /// app last saw — so a second live keyboard in another app doesn't also + /// insert them. Nil means whoever is up. + let recipient: String? } /// What the keyboard shows while the app works: the pipeline's phase, flattened -/// to what a pill can render, plus the live microphone level. +/// to what the orb can show, plus the live microphone level. nonisolated struct PhaseSnapshot: Codable, Sendable, Equatable { nonisolated enum State: String, Codable, Sendable { case idle @@ -140,7 +143,7 @@ nonisolated struct PhaseSnapshot: Codable, Sendable, Equatable { static let idle = PhaseSnapshot(state: .idle, message: nil, level: 0, at: .distantPast) - /// How long a notice stays on the pill before it settles back to idle — the + /// How long a notice stays on the orb before it settles back to idle — the /// Mac's 0.8 s / 1.6 s dwell, a little longer since a phone has no hover to /// reveal more. Nil for the states that end on their own. var noticeDwellSeconds: Double? { @@ -157,20 +160,28 @@ nonisolated struct PhaseSnapshot: Codable, Sendable, Equatable { /// keyboard reads the snapshot back on every appearance and on every signal, /// including signals held while it was suspended, so it must decide for /// itself. - var isStale: Bool { - let age = Date().timeIntervalSince(at) + var isStale: Bool { isStale(now: Date()) } + + func isStale(now: Date) -> Bool { + let age = now.timeIntervalSince(at) switch state { case .idle: return false - case .pasted, .copied, .error: return age > 3 - case .connecting, .recording, .processing: return age > 130 + case .pasted, .copied, .error: return age > Self.noticeStaleAfter + case .connecting, .recording, .processing: return age > Self.inFlightStaleAfter } } + + /// The longest notice dwell (2 s) plus a second of slack. + static let noticeStaleAfter: TimeInterval = 3 + /// The engine's 120 s cap on one dictation, plus ten seconds for the + /// transcript to come back. + static let inFlightStaleAfter: TimeInterval = 130 } /// One entry of the phone's own word list (`UILexicon`): contact names and the /// user's text replacements. Names go to the request as key terms so they come /// back spelled right; replacements are the phone's own text shortcuts. -nonisolated struct LexiconEntry: Codable, Sendable, Hashable { +nonisolated struct LexiconEntry: Codable, Sendable { let userInput: String let documentText: String @@ -188,9 +199,12 @@ nonisolated enum SharedStore { /// The App Group's defaults — what both processes read and write. Falls /// back to the process's own only where the group is out of reach (a /// keyboard without Full Access), so nothing crashes; nothing is shared then. - static var defaults: UserDefaults { - UserDefaults(suiteName: BlurtShared.appGroup) ?? .standard - } + /// Tests point this at a throwaway suite (`override`) so they never touch + /// the real one. + static var defaults: UserDefaults { override ?? shared } + nonisolated(unsafe) static var override: UserDefaults? + // `UserDefaults` is thread-safe by contract; the type just isn't marked Sendable. + nonisolated(unsafe) private static let shared = UserDefaults(suiteName: BlurtShared.appGroup) ?? .standard static func write(_ value: Value, forKey key: String) { guard let data = try? JSONEncoder().encode(value) else { return } @@ -242,18 +256,40 @@ nonisolated enum SharedStore { set { defaults.set(newValue, forKey: BlurtShared.Key.listeningUntil) } } - /// How recently the app must have checked in to count as alive. Its - /// heartbeat is every few seconds while the microphone is open. - static let appPresenceWindow: TimeInterval = 15 + // MARK: Presence — the contract between the two processes + + /// Each side writes a timestamp every few seconds while it is there (the app + /// while its microphone is open, the keyboard while it is on screen), and + /// the other side counts it present while that timestamp is younger than + /// the window. The window is more than twice the heartbeat, so one missed + /// beat — a busy main thread, a suspended process resuming — doesn't read + /// as absence, while a killed process reads as absent within seconds. + static let appHeartbeatInterval: TimeInterval = 5 + static let keyboardHeartbeatInterval: TimeInterval = 4 + static let presenceWindow: TimeInterval = 15 /// Whether the app currently has the microphone open for the keyboard: the /// window has not lapsed, and the app is still there to hear — iOS may have /// killed it, or a phone call taken the microphone, with the window's end /// still in the future. The keyboard then opens the app rather than sending /// a press nobody would answer. - static var isListening: Bool { - guard (listeningUntil ?? .distantPast) > Date() else { return false } - return Date().timeIntervalSince(appSeenAt ?? .distantPast) < appPresenceWindow + static var isListening: Bool { isListening(now: Date()) } + + static func isListening(now: Date) -> Bool { + guard (listeningUntil ?? .distantPast) > now else { return false } + return now.timeIntervalSince(appSeenAt ?? .distantPast) < presenceWindow + } + + /// Whether a keyboard is on screen to take the words (see `presenceWindow`). + static var isKeyboardPresent: Bool { + Date().timeIntervalSince(keyboardSeenAt ?? .distantPast) < presenceWindow + } + + /// Which keyboard process is on screen — a fresh id per process, written + /// with its heartbeat — so a result can be addressed to it. + static var keyboardInstance: String? { + get { defaults.string(forKey: BlurtShared.Key.keyboardInstance) } + set { defaults.set(newValue, forKey: BlurtShared.Key.keyboardInstance) } } // MARK: Key terms @@ -315,35 +351,6 @@ nonisolated enum SharedStore { } } -/// A Darwin-notification subscription that lives as long as this object does. -/// -/// The handler runs on whichever thread the system delivers on and is -/// `@Sendable` for that reason; hop to the main actor inside it when the work -/// is UI. A class rather than a token so `deinit` can deregister — a listener -/// left behind outlives its owner, since the system holds the callback. -nonisolated final class DarwinObserver: Sendable { - private let name: String - private let handler: @Sendable () -> Void - - init(name: String, handler: @escaping @Sendable () -> Void) { - self.name = name - self.handler = handler - let observer = Unmanaged.passUnretained(self).toOpaque() - CFNotificationCenterAddObserver( - CFNotificationCenterGetDarwinNotifyCenter(), observer, - { _, observer, _, _, _ in - guard let observer else { return } - Unmanaged.fromOpaque(observer).takeUnretainedValue().handler() - }, name as CFString, nil, .deliverImmediately) - } - - deinit { - CFNotificationCenterRemoveObserver( - CFNotificationCenterGetDarwinNotifyCenter(), Unmanaged.passUnretained(self).toOpaque(), - CFNotificationName(name as CFString), nil) - } -} - // MARK: - Brand /// The comma-separated key-term list, as the engine's `KeyTermsStore` reads diff --git a/App/BlurtiOS/project.yml b/App/BlurtiOS/project.yml index fcac4b32..97871133 100644 --- a/App/BlurtiOS/project.yml +++ b/App/BlurtiOS/project.yml @@ -56,9 +56,11 @@ targets: # extension can't import the app's module) — one source, no duplication, # the same shape as App/Blurt/Shared. - path: Shared - # The keyboard's views and model, so debug builds can render every layout - # and state in-app (KeyboardGalleryView) for design work and screenshots. - # Only the extension's entry point stays out; the keyboard never runs here. + # The keyboard's views and model: the theme picker draws the real keyboard + # on its cards, the home screen draws the orb and the meter, and debug + # builds render every layout and state (KeyboardGalleryView) for design + # work and screenshots. Only the extension's entry point stays out; the + # keyboard itself never runs here. - path: BlurtKeyboard/Sources excludes: - KeyboardViewController.swift diff --git a/scripts/check-invariants.sh b/scripts/check-invariants.sh index 8ec67642..d9c4717e 100755 --- a/scripts/check-invariants.sh +++ b/scripts/check-invariants.sh @@ -78,8 +78,12 @@ ENGINE="Sources/*.swift" # The app scope is `App/`, not `App/Blurt/`: there is a second app spec now # (the iOS app), and a scope pinned to one app silently stops covering the # next one. -APP="App/*.swift App/*.yml App/*.plist :!App/Blurt/Blurt.xcodeproj" -TESTS="Tests/*.swift App/Blurt/BlurtUITests/*.swift" +APP="App/*.swift App/*.yml App/*.plist :!App/Blurt/Blurt.xcodeproj :!App/BlurtiOS/BlurtiOSTests" +TESTS="Tests/*.swift App/Blurt/BlurtUITests/*.swift App/BlurtiOS/BlurtiOSTests/*.swift" +# The keyboard extension and what it compiles: iOS lets no keyboard use the +# microphone, and the design keeps every audio type out of it, so an import +# there is a decision being reversed by accident. +KEYBOARD="App/BlurtiOS/BlurtKeyboard/*.swift App/BlurtiOS/Shared/*.swift" # Four parallel arrays rather than one delimited list, for the reason # check-portability.sh gives: the patterns contain `|`, so splitting on it @@ -99,6 +103,7 @@ PATTERNS=( "AppUpdater|Sparkle|SPUUpdater" "KeychainStore\\(service: *(HostIdentity\\.current\\.keychainService|\"blurt\")" "@available\\(\\*, *deprecated" + "import AVFoundation|import AVFAudio|AVCaptureSession|AVAudioSession|AVAudioApplication|AudioQueueNewInput" ) SCOPES=( "$ENGINE $APP" @@ -114,6 +119,7 @@ SCOPES=( "$ENGINE $APP" "$TESTS" "$ENGINE $APP" + "$KEYBOARD" ) ADVICE=( "MicCapture builds a fresh AVCaptureSession recorder per capture — a long-lived engine goes stale on a device switch" @@ -129,6 +135,7 @@ ADVICE=( "updates are download-only; extend UpdateCheckModel, don't install for the user" "use an isolated service (see KeychainStoreTests) or InMemoryAPIKeyStore" "deleted types stay deleted — no deprecated re-exports" + "the keyboard never hears anything: the app listens and transcribes, the keyboard inserts (KeyboardRelayInjector)" ) # One known-bad line per rule, same order. `--self-test` asserts each pattern @@ -149,6 +156,7 @@ PROBES=( "let updater = AppUpdater(owner: \"assemblyai\", repo: \"blurt\")" "let store = KeychainStore(service: HostIdentity.current.keychainService, account: \"AssemblyAIAPIKey\")" "@available(*, deprecated, renamed: \"NewName\")" + "let session = AVCaptureSession()" ) # A verbatim slice of the row in AGENTS.md's "Settled decisions" table that each @@ -171,6 +179,7 @@ TABLE_ANCHORS=( "Add a self-replacing install or background auto-updater" "Touch the real Keychain in tests" "Add backwards-compat shims for removed types" + "Give the keyboard extension a microphone or any audio type" ) # The same rule as the guardrails skill words it. Deliberately not the table's @@ -192,6 +201,7 @@ SKILL_ANCHORS=( "Updates are download-only" "the real Keychain in tests" "Don't add backwards-compat shims for removed types." + "The keyboard never hears anything." ) if [ "${#SCOPES[@]}" -ne "${#PATTERNS[@]}" ] \ diff --git a/scripts/check.sh b/scripts/check.sh index bb473508..625ee3ae 100755 --- a/scripts/check.sh +++ b/scripts/check.sh @@ -259,6 +259,16 @@ check_no_external_deps() { } run_check "no-external-dependencies guard" check_no_external_deps +# The iPhone targets, typechecked against the Mac Catalyst frameworks — the +# closest thing to an iOS SDK a Mac without Xcode has (scripts/ios-typecheck.sh +# explains). Skipped, not failed, where those frameworks are absent; CI's +# ios-build job builds and tests the real thing. +if [ -d "$(xcrun --show-sdk-path 2>/dev/null)/System/iOSSupport/System/Library/Frameworks/UIKit.framework" ]; then + run_check "ios-typecheck (App/BlurtiOS, Mac Catalyst stand-in)" "$REPO_ROOT/scripts/ios-typecheck.sh" +else + echo "==> ios-typecheck skipped: no Mac Catalyst frameworks in the selected SDK" +fi + # Ignore rules must not shadow tracked files. A .gitignore pattern only suppresses # files that are *untracked* — one that also matches something already committed # leaves it tracked but invisible to `git status`, so later edits to it stop @@ -575,7 +585,9 @@ else echo "==> coverage gate (>= ${MIN_COVERAGE}% engine lines)" BIN="$(swift build --show-bin-path)" PROFDATA="$BIN/codecov/default.profdata" - XCTEST_BUNDLE="$(find "$BIN" -maxdepth 1 -name '*PackageTests.xctest' -print -quit)" + # `BlurtPackageTests.xctest` from SwiftPM's own build system; Xcode 27's + # SwiftPM names the bundle after the test target, `BlurtEngineTests.xctest`. + XCTEST_BUNDLE="$(find "$BIN" -maxdepth 1 -name '*Tests.xctest' -print -quit)" XCTEST_BIN="$XCTEST_BUNDLE/Contents/MacOS/$(basename "$XCTEST_BUNDLE" .xctest)" # These must exist after `swift test --enable-code-coverage`. Previously a # missing one (a renamed test bundle, a coverage build that didn't happen) diff --git a/scripts/ios-lib.sh b/scripts/ios-lib.sh new file mode 100755 index 00000000..7ea51613 --- /dev/null +++ b/scripts/ios-lib.sh @@ -0,0 +1,41 @@ +#!/bin/bash +# Shared by scripts/ios-*.sh: the one simulator signing recipe, and picking a +# simulator. Sourced, not run. Needs python3 (the CLT stub on a bare Mac). +# +# Ad hoc signing (identity "-") is what the simulator accepts without a team, +# and unlike CODE_SIGNING_ALLOWED=NO it embeds the entitlements, so the App +# Group the app and keyboard share works in the simulator too. +# shellcheck disable=SC2034 # used by the scripts that source this file +IOS_SIM_SIGNING=(CODE_SIGN_STYLE=Manual CODE_SIGN_IDENTITY=- CODE_SIGNING_REQUIRED=NO DEVELOPMENT_TEAM=) + +# ios_pick_device NAME → prints "udidname" for the available simulator +# called NAME on the newest iOS runtime, else for whichever iPhone this Mac +# (or CI runner) has; prints nothing if there is none. +ios_pick_device() { + xcrun simctl list devices available -j | python3 -c ' +import json, re, sys +wanted = sys.argv[1] +runtimes = json.load(sys.stdin)["devices"] +def version(rt): + m = re.search(r"iOS-(\d+)-(\d+)", rt) + return (int(m.group(1)), int(m.group(2))) if m else (0, 0) +found = [] +for rt, devs in runtimes.items(): + if "iOS" not in rt: + continue + for d in devs: + if d["name"].startswith("iPhone"): + found.append((version(rt), d["name"] == wanted, d["name"], d["udid"])) +if not found: + sys.exit(0) +found.sort(key=lambda f: (f[1], f[0])) +best = found[-1] +print(best[3] + "\t" + best[2]) +' "$1" +} + +# ios_wait_booted UDID → boots the simulator if needed and waits for it. +ios_wait_booted() { + xcrun simctl boot "$1" 2>/dev/null || true + xcrun simctl bootstatus "$1" -b >/dev/null +} diff --git a/scripts/ios-sim.sh b/scripts/ios-sim.sh index c524ec17..5ebfc18b 100755 --- a/scripts/ios-sim.sh +++ b/scripts/ios-sim.sh @@ -9,15 +9,19 @@ # scripts/ios-sim.sh --screenshot out.png # …then capture the screen # BLURT_SIM_DEVICE="iPhone 17" scripts/ios-sim.sh # BLURT_LAUNCH_ARGS="-BlurtGallery panel idle,recording" scripts/ios-sim.sh --screenshot panel.png +# BLURT_SHOT_DELAY=5 … # seconds before the screenshot (default 3) # -# Xcode 27 replaced Simulator.app with Device Hub; either is opened if found. -# In Device Hub, turn off "Always simulate hardware keyboard" or no on-screen -# keyboard ever appears. +# The named simulator, or whichever iPhone this Mac has. Xcode 27 replaced +# Simulator.app with Device Hub; either is opened if found (neither is, with +# only the Command Line Tools selected). In Device Hub, turn off "Always +# simulate hardware keyboard" or no on-screen keyboard ever appears. set -euo pipefail REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" -DEVICE="${BLURT_SIM_DEVICE:-iPhone 18 Pro}" +# shellcheck source=scripts/ios-lib.sh +source "$REPO_ROOT/scripts/ios-lib.sh" DERIVED="${BLURT_DERIVED_DATA:-$REPO_ROOT/.build/ios-sim}" +# PRODUCT_BUNDLE_IDENTIFIER in App/BlurtiOS/project.yml. BUNDLE_ID=dev.alex.blurt.ios SHOT="" if [ "${1:-}" = "--screenshot" ]; then @@ -28,24 +32,18 @@ echo "generate + build" (cd "$REPO_ROOT/App/BlurtiOS" && xcodegen generate --quiet) xcodebuild -project "$REPO_ROOT/App/BlurtiOS/BlurtiOS.xcodeproj" -scheme BlurtiOS \ -destination 'generic/platform=iOS Simulator' -derivedDataPath "$DERIVED" \ - CODE_SIGN_STYLE=Manual CODE_SIGN_IDENTITY=- CODE_SIGNING_REQUIRED=NO DEVELOPMENT_TEAM= \ - -quiet build + "${IOS_SIM_SIGNING[@]}" -quiet build -UDID="$(xcrun simctl list devices available -j | python3 -c ' -import json, sys -name = sys.argv[1] -runtimes = json.load(sys.stdin)["devices"] -found = [(rt, d["udid"]) for rt, devs in runtimes.items() if "iOS" in rt for d in devs if d["name"] == name] -found.sort() -print(found[-1][1] if found else "") -' "$DEVICE")" -if [ -z "$UDID" ]; then - echo "ios-sim: no available simulator named '$DEVICE' (xcrun simctl list devices)" >&2 +PICKED="$(ios_pick_device "${BLURT_SIM_DEVICE:-iPhone 18 Pro}")" +if [ -z "$PICKED" ]; then + echo "ios-sim: no iPhone simulator available (xcrun simctl list devices)" >&2 exit 1 fi +UDID="${PICKED%% *}" +NAME="${PICKED#* }" -echo "boot $DEVICE ($UDID)" -xcrun simctl boot "$UDID" 2>/dev/null || true +echo "boot $NAME ($UDID)" +ios_wait_booted "$UDID" DEVELOPER_DIR="$(xcode-select -p)" for app in "$DEVELOPER_DIR/../Applications/DeviceHub.app" "$DEVELOPER_DIR/Applications/Simulator.app"; do if [ -d "$app" ]; then @@ -64,6 +62,6 @@ read -ra LAUNCH_ARGS <<<"${BLURT_LAUNCH_ARGS:-}" xcrun simctl launch "$UDID" "$BUNDLE_ID" ${LAUNCH_ARGS[@]+"${LAUNCH_ARGS[@]}"} if [ -n "$SHOT" ]; then - sleep 3 + sleep "${BLURT_SHOT_DELAY:-3}" xcrun simctl io "$UDID" screenshot "$SHOT" fi diff --git a/scripts/ios-test.sh b/scripts/ios-test.sh index e6138f8e..e4627257 100755 --- a/scripts/ios-test.sh +++ b/scripts/ios-test.sh @@ -4,28 +4,35 @@ # scripts/ios-test.sh # BLURT_SIM_DEVICE="iPhone 17" scripts/ios-test.sh # -# Hosted by the app, signed ad hoc, which the simulator accepts. The engine's -# own tests are `swift test` (scripts/check.sh); these cover the iPhone code's -# pure logic — the App Group contract, the keyboard's rules, term packs. +# Hosted by the app, signed ad hoc, on the named simulator or whichever iPhone +# this Mac (or CI runner) has. The engine's own tests are `swift test` +# (scripts/check.sh); these cover the iPhone code's pure logic — the App Group +# contract, the keyboard's rules, term packs. The per-test log is in the +# result bundle the last line names. set -euo pipefail REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" +# shellcheck source=scripts/ios-lib.sh +source "$REPO_ROOT/scripts/ios-lib.sh" DERIVED="${BLURT_DERIVED_DATA:-$REPO_ROOT/.build/ios-sim}" -# The named simulator, or whichever iPhone this Mac (or CI runner) has. -DEVICE="$(xcrun simctl list devices available -j | python3 -c ' -import json, sys -wanted = sys.argv[1] -names = [d["name"] for rt, devs in json.load(sys.stdin)["devices"].items() if "iOS" in rt for d in devs] -print(wanted if wanted in names else next((n for n in names if n.startswith("iPhone")), "")) -' "${BLURT_SIM_DEVICE:-iPhone 18 Pro}")" -if [ -z "$DEVICE" ]; then + +PICKED="$(ios_pick_device "${BLURT_SIM_DEVICE:-iPhone 18 Pro}")" +if [ -z "$PICKED" ]; then echo "ios-test: no iPhone simulator available (xcrun simctl list devices)" >&2 exit 1 fi -echo "testing on $DEVICE" +UDID="${PICKED%% *}" +echo "testing on ${PICKED#* }" +ios_wait_booted "$UDID" (cd "$REPO_ROOT/App/BlurtiOS" && xcodegen generate --quiet) +RESULTS="$DERIVED/BlurtiOSTests-$(date +%Y%m%d-%H%M%S).xcresult" xcodebuild test -project "$REPO_ROOT/App/BlurtiOS/BlurtiOS.xcodeproj" -scheme BlurtiOS \ - -destination "platform=iOS Simulator,name=$DEVICE" -derivedDataPath "$DERIVED" \ - CODE_SIGN_STYLE=Manual CODE_SIGN_IDENTITY=- CODE_SIGNING_REQUIRED=NO DEVELOPMENT_TEAM= \ - -quiet + -destination "platform=iOS Simulator,id=$UDID" -derivedDataPath "$DERIVED" \ + -resultBundlePath "$RESULTS" "${IOS_SIM_SIGNING[@]}" -quiet +xcrun xcresulttool get test-results summary --path "$RESULTS" 2>/dev/null | python3 -c ' +import json, sys +d = json.load(sys.stdin) +print("ios-test:", d.get("passedTests", "?"), "passed,", d.get("failedTests", "?"), "failed,", d.get("skippedTests", 0), "skipped") +' || true +echo "results: $RESULTS" diff --git a/scripts/ios-typecheck.sh b/scripts/ios-typecheck.sh index 27c94793..1ba77d4c 100755 --- a/scripts/ios-typecheck.sh +++ b/scripts/ios-typecheck.sh @@ -11,7 +11,8 @@ # # What it cannot see: APIs that differ between Catalyst and iOS proper, code # signing, linking, and the generated project itself. CI stays the authority; -# this is the fast local loop for the App/BlurtiOS sources. +# this is the fast local loop for the App/BlurtiOS sources. The unit tests +# (`@testable import`) need the real build: scripts/ios-test.sh. set -euo pipefail REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" @@ -25,6 +26,7 @@ fi WORK="$(mktemp -d)" trap 'rm -rf "$WORK"' EXIT +# The 18.0 is the deployment target App/BlurtiOS/project.yml sets. TARGET=arm64-apple-ios18.0-macabi COMMON=( -target "$TARGET" -sdk "$SDK" @@ -43,9 +45,13 @@ TARGET_FLAGS=( -Xfrontend -default-isolation -Xfrontend MainActor ) +# The app also compiles the keyboard's sources, all but its entry point +# (project.yml: the theme picker and the home screen draw the real keyboard +# and orb), and CI builds Debug, so `#if DEBUG` code is checked too. echo "BlurtiOS" -xcrun swiftc "${TARGET_FLAGS[@]}" -module-name BlurtiOS \ - "$IOS"/BlurtiOS/Sources/*.swift "$IOS"/Shared/*.swift +find "$IOS/BlurtKeyboard/Sources" -name '*.swift' ! -name KeyboardViewController.swift -print0 \ + | xargs -0 xcrun swiftc "${TARGET_FLAGS[@]}" -D DEBUG -module-name BlurtiOS \ + "$IOS"/BlurtiOS/Sources/*.swift "$IOS"/Shared/*.swift echo "BlurtKeyboard" xcrun swiftc "${TARGET_FLAGS[@]}" -application-extension -module-name BlurtKeyboard \ From a039f0e48894bb2bbab9f1e1473432f330dbb8fe Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Fri, 25 Sep 2026 18:04:52 -0400 Subject: [PATCH 36/79] Flat: a matte two-tone orb with a circling perimeter, the wave bare, keys without edge or drop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit What read as plastic — the Mac gradient's white crown on a phone-sized disc, a drop and a hairline under every key, a glow, the recording capsule — is gone. The orb is a flat two-tone disc (the palette's violet into its green) whose perimeter is a soft comet of the palette turned continuously: one turn every 4 s at rest, so it is never still, and the Mac pill's 1.6 s while the app works. Recording is the wave, flat on the surface with no container. Keys are one colour at 7 pt corners; pop-ups, the +, the term field are flat too. The home screen's hero is the same orb. Also fixed on the way: the listening window's isOpen read the microphone before the observable end time, so a view rendered before the mic opened never registered the end time and never redrew — the home screen said Not listening with the mic open. The end time is read first now. Co-Authored-By: Claude Fable 5.1 --- .../BlurtKeyboard/Sources/BrandOrb.swift | 54 ++++--- .../Sources/FullKeyboardView.swift | 1 - .../Sources/KeyboardPalette.swift | 23 ++- .../BlurtKeyboard/Sources/KeyboardViews.swift | 75 +++------- .../BlurtKeyboard/Sources/VoiceBar.swift | 3 - App/BlurtiOS/BlurtiOS/Sources/HomeView.swift | 133 ++++++++++-------- .../BlurtiOS/Sources/ListeningWindow.swift | 9 +- App/BlurtiOS/DESIGN.md | 87 +++++++----- App/BlurtiOS/Shared/BlurtBrand.swift | 22 +++ 9 files changed, 220 insertions(+), 187 deletions(-) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/BrandOrb.swift b/App/BlurtiOS/BlurtKeyboard/Sources/BrandOrb.swift index 2d37603f..4e721a49 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/BrandOrb.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/BrandOrb.swift @@ -1,54 +1,62 @@ import BlurtEngine import SwiftUI -/// The redraw cap for the keyboard's continuous motion — the ring's sweep, the -/// meter's idle wave. The Mac pill reads the same number from the engine: the -/// level feed moves at this cadence, so drawing faster only burns the -/// keyboard's tight energy and memory budget. +/// The redraw cap for the keyboard's continuous motion — the perimeter's +/// sweep, the meter's idle wave. The Mac pill reads the same number from the +/// engine: the level feed moves at this cadence, so drawing faster only burns +/// the keyboard's tight energy and memory budget. let keyboardAnimationInterval = MicCapture.meterIntervalSeconds -/// The brand orb, as the Mac pill draws it (`App/Blurt/Blurt/Overlay/BrandOrb.swift`): -/// the gradient disc, and a hairline ring that sweeps round it while something -/// is happening. It spins rather than pulses — a pulse says "alive", a sweep -/// says "working, and still going" — and the disc underneath never moves. +/// The brand orb as the phone draws it: a flat two-tone disc, and a soft +/// comet of the palette circling its perimeter — slowly at rest, so the orb +/// is never still, at the Mac pill's pace while the app works. The disc +/// underneath never moves. No glyph, no gloss, no shadow. /// -/// Sized by the caller: the app's home screen draws it as the hero; the -/// keyboard's mic key draws its own capsule so it can grow into the wave. +/// Sized by the caller: the app's home screen draws it as the hero, the +/// keyboard as the mic key. struct BrandOrb: View { var diameter: CGFloat - /// Whether the ring sweeps. Off under Reduce Motion, where the ring is still - /// drawn — it is part of the mark — but holds still. - var animated: Bool - var ringWidth: CGFloat = 1 + /// Seconds per turn of the perimeter. + var period: Double = BrandOrb.restPeriod + var ringWidth: CGFloat = 2 + /// A solid ring in place of the sweep — a notice's green or orange. + var ringColor: Color? + /// Whether the perimeter moves. Off under Reduce Motion, where the sweep is + /// still drawn but holds still. + var animated = true - /// One turn every 1.6 s: the Mac's cadence. - static let period: Double = 1.6 + /// At rest: one slow turn every 4 s, alive but not busy. + static let restPeriod: Double = 4 + /// While the app works: the Mac pill's 1.6 s. + static let workingPeriod: Double = 1.6 var body: some View { Circle() - .fill(BlurtBrand.orbGradient) + .fill(BlurtBrand.orbFlat) .frame(width: diameter, height: diameter) .overlay { ring } .accessibilityHidden(true) } @ViewBuilder private var ring: some View { - if animated { + if let ringColor { + Circle().strokeBorder(ringColor, lineWidth: ringWidth) + } else if animated { // The angle is a pure function of the clock (engine geometry), so the // sweep can't drift or restart mid-turn when the state beside it changes. TimelineView(.animation(minimumInterval: keyboardAnimationInterval)) { timeline in - ringShape.rotationEffect( + sweep.rotationEffect( .degrees( MeterBarGeometry.rotationDegrees( - time: timeline.date.timeIntervalSinceReferenceDate, period: Self.period))) + time: timeline.date.timeIntervalSinceReferenceDate, period: period))) } } else { - ringShape + sweep } } /// `strokeBorder` so the ring sits inside the disc instead of fringing it. - private var ringShape: some View { - Circle().strokeBorder(BlurtBrand.orbRingGradient, lineWidth: ringWidth) + private var sweep: some View { + Circle().strokeBorder(BlurtBrand.orbSweep, lineWidth: ringWidth) } } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift b/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift index f31cf478..7bb2e4de 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift @@ -109,7 +109,6 @@ private struct LetterKey: View { .foregroundStyle(palette.keyText) .frame(width: width + 18, height: 56) .background(palette.popupFill, in: RoundedRectangle(cornerRadius: 9)) - .shadow(color: .black.opacity(0.25), radius: 4, y: 2) .offset(y: -58) .allowsHitTesting(false) } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift index dde190f4..6b4b22c5 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift @@ -5,9 +5,9 @@ import SwiftUI /// a warm paper, a midnight, a sunset), each contemporary and fun and none of /// them off-brand. People pick one in the app, Partiful-style, from live /// previews; the spacing never changes (the iPhone keyboard's own — 6 pt -/// between keys, 11 between rows, 3 at the edges, 5 pt corners, a 1 pt drop -/// under every key), so a theme changes how the keyboard looks and never how -/// it types. +/// between keys, 11 between rows, 3 at the edges), so a theme changes how the +/// keyboard looks and never how it types. Everything is flat: no drop under a +/// key, no edge, no gloss — a matte surface with matte keys on it. struct KeyboardPalette: Equatable, Identifiable { let id: String let name: String @@ -17,44 +17,43 @@ struct KeyboardPalette: Equatable, Identifiable { let key: Color let keyDark: Color let keyText: Color - /// The drop under each key, as the system keyboard draws it. - let keyShadow: Color let popupFill: Color static let keyGap: CGFloat = 6 static let rowGap: CGFloat = 11 static let margin: CGFloat = 3 - static let keyRadius: CGFloat = 5 + /// A touch rounder than the system's 5: flat shapes want it. + static let keyRadius: CGFloat = 7 static let ink = KeyboardPalette( id: "ink", name: "Ink", vibe: "Blurt's own", surface: BlurtBrand.ink, key: BlurtBrand.key, keyDark: BlurtBrand.keyDark, keyText: BlurtBrand.keyText, - keyShadow: Color.black.opacity(0.45), popupFill: BlurtBrand.key) + popupFill: BlurtBrand.key) static let paper = KeyboardPalette( id: "paper", name: "Paper", vibe: "Warm and light", surface: Color(hex: 0xEBE8E8), key: .white, keyDark: Color(hex: 0xDEDBDB), keyText: BlurtBrand.ink, - keyShadow: Color.black.opacity(0.18), popupFill: .white) + popupFill: .white) static let lavender = KeyboardPalette( id: "lavender", name: "Lavender", vibe: "The orb's violet", surface: Color(hex: 0x2C2557), key: Color(hex: 0x3F3777), keyDark: Color(hex: 0x352E68), - keyText: Color(hex: 0xF1EEFF), keyShadow: Color.black.opacity(0.4), popupFill: Color(hex: 0x3F3777)) + keyText: Color(hex: 0xF1EEFF), popupFill: Color(hex: 0x3F3777)) static let mint = KeyboardPalette( id: "mint", name: "Mint", vibe: "The orb's green", surface: Color(hex: 0x10231B), key: Color(hex: 0x1E3F31), keyDark: Color(hex: 0x183429), - keyText: Color(hex: 0xE9F5EE), keyShadow: Color.black.opacity(0.4), popupFill: Color(hex: 0x1E3F31)) + keyText: Color(hex: 0xE9F5EE), popupFill: Color(hex: 0x1E3F31)) static let midnight = KeyboardPalette( id: "midnight", name: "Midnight", vibe: "Deep blue-black", surface: Color(hex: 0x0E1220), key: Color(hex: 0x1D2440), keyDark: Color(hex: 0x161B33), - keyText: Color(hex: 0xE8ECFF), keyShadow: Color.black.opacity(0.5), popupFill: Color(hex: 0x1D2440)) + keyText: Color(hex: 0xE8ECFF), popupFill: Color(hex: 0x1D2440)) static let sunset = KeyboardPalette( id: "sunset", name: "Sunset", vibe: "Warm and loud", surface: Color(hex: 0x2B1912), key: Color(hex: 0x4B2B20), keyDark: Color(hex: 0x3B2119), - keyText: Color(hex: 0xFFEFE6), keyShadow: Color.black.opacity(0.4), popupFill: Color(hex: 0x4B2B20)) + keyText: Color(hex: 0xFFEFE6), popupFill: Color(hex: 0x4B2B20)) static let all: [KeyboardPalette] = [ink, paper, lavender, mint, midnight, sunset] diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift index 0d5395be..c03215cd 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift @@ -103,13 +103,13 @@ struct PanelView: View { /// The mic key is the brand orb, and it says everything without a word or a /// glyph. Finger down starts, finger up decides tap (latched) or hold /// (push-to-talk) — `KeyboardModel` runs the engine's gate. What it does: -/// dimmed when Blurt isn't ready (no Full Access, or the app isn't listening; -/// the tap opens Blurt); on a tap the ring sweeps as the app's orb does while -/// the mic comes up; then the orb grows sideways into a capsule holding the -/// live wave for as long as you talk, glowing with your voice; on the stop it -/// shrinks back to the circle with the ring sweeping while the words come; -/// then a green ring for a moment when they landed, a clipboard on a green -/// ring when they went to the clipboard instead, an orange ring and an +/// its perimeter circles slowly at rest; dimmed when Blurt isn't ready (no +/// Full Access, or the app isn't listening; the tap opens Blurt); on a tap +/// the perimeter quickens while the mic comes up; then the orb gives way to +/// the live wave, flat on the surface, for as long as you talk; on the stop +/// the orb returns with its perimeter quick while the words come; then a +/// green ring for a moment when they landed, a clipboard on a green ring +/// when they went to the clipboard instead, an orange ring and an /// exclamation mark when something failed. Each also has its haptic. struct MicKey: View { var model: KeyboardModel @@ -120,33 +120,30 @@ struct MicKey: View { @Environment(\.accessibilityReduceMotion) private var reduceMotion var body: some View { - let level = CGFloat(model.snapshot.level) let width = isRecording ? expandedWidth : size ZStack { - Capsule() - .fill(BlurtBrand.orbGradient) - .overlay { ring } - .saturation(isReady ? 1 : 0.35) - .opacity(isReady ? 1 : 0.8) if isRecording { - WaveformMeter(level: Float(model.snapshot.level), animated: !reduceMotion, color: .white.opacity(0.92)) - .frame(width: expandedWidth - size * 0.7, height: size * 0.5) - .transition(.opacity) + // The wave, flat on the surface: no container, no gloss. + WaveformMeter(level: Float(model.snapshot.level), animated: !reduceMotion, color: BlurtBrand.greenOnDark) + .frame(width: expandedWidth, height: size * 0.55) + .transition(.opacity.combined(with: .scale(scale: 0.6))) + } else { + BrandOrb( + diameter: size, period: isWorking ? BrandOrb.workingPeriod : BrandOrb.restPeriod, + ringWidth: max(2, size * 0.04), ringColor: ringColor, animated: !reduceMotion + ) + .saturation(isReady ? 1 : 0.3) + .opacity(isReady ? 1 : 0.7) + .transition(.opacity.combined(with: .scale(scale: 0.8))) } if let glyph { Image(systemName: glyph) .font(.system(size: size * 0.34, weight: .semibold)) .foregroundStyle(.white) - .shadow(color: .black.opacity(0.3), radius: 2, y: 1) .transition(.opacity) } } .frame(width: width, height: size) - .shadow( - color: BlurtBrand.greenOnDark.opacity(isRecording ? 0.35 + 0.45 * level : 0), - radius: isRecording ? size * 0.1 + level * size * 0.25 : 0 - ) - .animation(.easeOut(duration: 0.08), value: level) .animation(reduceMotion ? nil : .spring(duration: 0.35, bounce: 0.15), value: isRecording) .animation(.easeInOut(duration: 0.15), value: model.snapshot.state) .scaleEffect(pressed ? 0.94 : 1) @@ -201,27 +198,6 @@ struct MicKey: View { abs(value.translation.width) > 24 || abs(value.translation.height) > 24 } - /// The ring: the app orb's sweep (one turn per 1.6 s, engine geometry) - /// while the mic comes up and while the words come; still, and solid green - /// or orange, for a notice; still on the capsule while recording. - @ViewBuilder private var ring: some View { - let width: CGFloat = isWorking || isNotice ? 2 : 1 - if isWorking, !isRecording, !reduceMotion { - TimelineView(.animation(minimumInterval: keyboardAnimationInterval)) { timeline in - Capsule() - .strokeBorder(BlurtBrand.orbRingGradient, lineWidth: width) - .rotationEffect( - .degrees( - MeterBarGeometry.rotationDegrees( - time: timeline.date.timeIntervalSinceReferenceDate, period: BrandOrb.period))) - } - } else if let ringColor { - Capsule().strokeBorder(ringColor, lineWidth: width) - } else { - Capsule().strokeBorder(BlurtBrand.orbRingGradient, lineWidth: width) - } - } - private var isReady: Bool { model.isReady } private var isRecording: Bool { isReady && model.snapshot.state == .recording } private var isWorking: Bool { @@ -342,17 +318,10 @@ struct KeyPress: ViewModifier { } extension View { - /// The cap under a key's legend: the palette's fill, the system keyboard's - /// corner radius and 1 pt drop, and a hairline so the cap reads on ink. + /// The cap under a key's legend: the palette's fill and the corner radius, + /// nothing else — flat. func keyCap(_ fill: Color, palette: KeyboardPalette) -> some View { - background { - RoundedRectangle(cornerRadius: KeyboardPalette.keyRadius) - .fill(fill) - .shadow(color: palette.keyShadow, radius: 0, y: 1) - } - .overlay { - RoundedRectangle(cornerRadius: KeyboardPalette.keyRadius).strokeBorder(Color.white.opacity(0.06), lineWidth: 1) - } + background(fill, in: RoundedRectangle(cornerRadius: KeyboardPalette.keyRadius)) } } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift index 1194ec07..ec926854 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift @@ -61,7 +61,6 @@ struct AddTermKey: View { .foregroundStyle(model.termSavedAt == nil ? palette.keyText.opacity(0.7) : BlurtBrand.greenOnDark) .frame(width: 32, height: 32) .background(Circle().fill(palette.keyDark)) - .overlay(Circle().strokeBorder(Color.white.opacity(0.08), lineWidth: 1)) .contentTransition(.symbolEffect(.replace)) } .buttonStyle(KeyPressStyle()) @@ -96,7 +95,6 @@ private struct TermField: View { .frame(maxWidth: .infinity) .frame(height: 36) .background(Capsule().fill(palette.keyDark)) - .overlay(Capsule().strokeBorder(BlurtBrand.greenOnDark.opacity(0.6), lineWidth: 1)) .accessibilityElement(children: .ignore) .accessibilityLabel("Key term: \(model.termDraft ?? "")") round("checkmark", tint: BlurtBrand.greenOnDark) { model.saveTerm() } @@ -113,7 +111,6 @@ private struct TermField: View { .foregroundStyle(tint) .frame(width: 32, height: 32) .background(Circle().fill(palette.keyDark)) - .overlay(Circle().strokeBorder(Color.white.opacity(0.08), lineWidth: 1)) } .buttonStyle(KeyPressStyle()) } diff --git a/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift b/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift index f89c846c..f47ff895 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift @@ -19,6 +19,8 @@ struct HomeView: View { @AppStorage(StyleProfileStore.activeDefaultsKey) private var activeRaw = "" private let styles = StyleProfileStore() + private static let orbSize: CGFloat = 112 + private var isSetUp: Bool { coordinator.apiKey.hasAPIKey && microphoneGranted && keyboardSeen } private var profiles: [StyleProfile] { styles.profiles(decoding: profilesRaw) } private var activeStyle: StyleProfile? { StyleProfileStore.active(in: profiles, id: activeRaw) } @@ -52,11 +54,16 @@ struct HomeView: View { } .sheet(isPresented: $showsKeyEntry) { KeyEntryView(apiKey: coordinator.apiKey) } .sheet(isPresented: $showsSettings) { SettingsView(coordinator: coordinator) } - .sheet( - isPresented: Binding( - get: { coordinator.pendingTermPack != nil }, set: { if !$0 { coordinator.pendingTermPack = nil } }) + .sheet(item: Binding(get: { coordinator.pendingTermPack }, set: { coordinator.pendingTermPack = $0 })) { + ImportTermsView(pack: $0) + } + .alert( + "Couldn't read that list", + isPresented: Binding(get: { coordinator.termPackUnreadable }, set: { coordinator.termPackUnreadable = $0 }) ) { - if let pack = coordinator.pendingTermPack { ImportTermsView(pack: pack) } + Button("OK") {} + } message: { + Text("It isn't a Blurt key-term list, or it's too big.") } .onChange(of: scenePhase) { _, phase in if phase == .active { refreshStatus() } @@ -73,19 +80,18 @@ struct HomeView: View { // MARK: - The orb and the listening state - private var level: CGFloat { CGFloat(coordinator.level) } private var isRecording: Bool { coordinator.phase == .recording } private var orbWorking: Bool { coordinator.window.isOpen || coordinator.phase.isCapturing } private var hero: some View { VStack(spacing: 18) { - BrandOrb(diameter: 112, animated: orbWorking && !reduceMotion, ringWidth: 2) - .shadow( - color: BlurtBrand.greenOnDark.opacity(isRecording ? 0.35 + 0.45 * level : 0), - radius: isRecording ? 14 + 30 * level : 0 - ) - .animation(.easeOut(duration: 0.08), value: level) - .padding(.top, 6) + // The keyboard's orb, larger: its perimeter circles slowly at rest and + // quickens while the mic is open or a dictation is in flight. + BrandOrb( + diameter: Self.orbSize, period: orbWorking ? BrandOrb.workingPeriod : BrandOrb.restPeriod, ringWidth: 4, + animated: !reduceMotion + ) + .padding(.top, 6) VStack(spacing: 4) { Text(heroTitle).font(.title2.weight(.semibold)).multilineTextAlignment(.center) Text(heroSubtitle).font(.callout).foregroundStyle(.secondary).multilineTextAlignment(.center) @@ -124,6 +130,10 @@ struct HomeView: View { Text("Blurt needs the microphone. Allow it in Settings.") .font(.footnote).foregroundStyle(BlurtBrand.errorOrange) } + if coordinator.needsKey { + Text("Add your API key first (Settings → Account).") + .font(.footnote).foregroundStyle(BlurtBrand.errorOrange) + } } .padding(20) .frame(maxWidth: .infinity) @@ -147,11 +157,63 @@ struct HomeView: View { return "Open the mic so the Blurt keyboard can dictate anywhere you type." } if let until = coordinator.window.until, until != .distantFuture { - return "Until \(until.formatted(date: .omitted, time: .shortened)) · tap the mic on the Blurt keyboard." + return "Until \(until.formatted(date: .omitted, time: .shortened)) · tap the orb on the Blurt keyboard." + } + return "Until you stop it · tap the orb on the Blurt keyboard." + } + + // MARK: - Setup + + private var setupCard: some View { + VStack(alignment: .leading, spacing: 14) { + Text("Set up Blurt").font(.headline) + SetupRow(done: coordinator.apiKey.hasAPIKey, title: "Sign in with AssemblyAI") { + VStack(alignment: .leading, spacing: 6) { + Text("Coming soon — sign-in needs the AssemblyAI login service.") + .font(.footnote).foregroundStyle(.secondary) + #if DEBUG + Button("Use an API key instead") { showsKeyEntry = true } + #endif + } + } + SetupRow(done: microphoneGranted, title: "Allow the microphone") { + if AVAudioApplication.shared.recordPermission == .denied { + // iOS asks once; after a refusal only Settings can change it. + Button("Allow in Settings") { openAppSettings() } + } else { + Button("Allow") { + Task { + _ = await AVAudioApplication.requestRecordPermission() + refreshStatus() + } + } + } + } + SetupRow(done: keyboardSeen, title: "Add the Blurt keyboard") { + VStack(alignment: .leading, spacing: 6) { + Text( + "Settings → Keyboards: turn on Blurt and Allow Full Access. " + + "Full Access is what lets the keyboard send your words to Blurt." + ) + .font(.footnote).foregroundStyle(.secondary) + Button("Open Settings") { openAppSettings() } + } + } } - return "Until you stop it · tap the mic on the Blurt keyboard." + .padding(20) + .frame(maxWidth: .infinity, alignment: .leading) + .card() + } + + private func openAppSettings() { + guard let url = URL(string: UIApplication.openSettingsURLString) else { return } + UIApplication.shared.open(url) } +} +// The style chips, the recent cards and the footer, as an extension so the +// struct's own body stays within the lint budget. +extension HomeView { // MARK: - Styles private var styleChips: some View { @@ -225,49 +287,6 @@ struct HomeView: View { .font(.caption) .padding(.top, 4) } - - // MARK: - Setup - - private var setupCard: some View { - VStack(alignment: .leading, spacing: 14) { - Text("Set up Blurt").font(.headline) - SetupRow(done: coordinator.apiKey.hasAPIKey, title: "Sign in with AssemblyAI") { - VStack(alignment: .leading, spacing: 6) { - Text("Coming soon — sign-in needs the AssemblyAI login service.") - .font(.footnote).foregroundStyle(.secondary) - #if DEBUG - Button("Use an API key instead") { showsKeyEntry = true } - #endif - } - } - SetupRow(done: microphoneGranted, title: "Allow the microphone") { - Button("Allow") { - Task { - await coordinator.startListening() - refreshStatus() - } - } - } - SetupRow(done: keyboardSeen, title: "Add the Blurt keyboard") { - VStack(alignment: .leading, spacing: 6) { - Text( - "Settings → Keyboards: turn on Blurt and Allow Full Access. " - + "Full Access is what lets the keyboard send your words to Blurt." - ) - .font(.footnote).foregroundStyle(.secondary) - Button("Open Settings") { openAppSettings() } - } - } - } - .padding(20) - .frame(maxWidth: .infinity, alignment: .leading) - .card() - } - - private func openAppSettings() { - guard let url = URL(string: UIApplication.openSettingsURLString) else { return } - UIApplication.shared.open(url) - } } /// One style, as a chip: filled with the accent while active. diff --git a/App/BlurtiOS/BlurtiOS/Sources/ListeningWindow.swift b/App/BlurtiOS/BlurtiOS/Sources/ListeningWindow.swift index 74ecf235..233b6584 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/ListeningWindow.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/ListeningWindow.swift @@ -29,7 +29,14 @@ final class ListeningWindow { @ObservationIgnored private var heartbeat: Task? @ObservationIgnored private var interruptions: Task? - var isOpen: Bool { source.isOpen && (until.map { $0 > Date() } ?? false) } + /// Whether the microphone is open and the window hasn't lapsed. `until` + /// is read first, unconditionally: it is the observable half, and a view + /// that read it only after `source.isOpen` came true would never have + /// registered it and never redraw when the window opened. + var isOpen: Bool { + let lapsed = until.map { $0 <= Date() } ?? true + return !lapsed && source.isOpen + } /// Opens the microphone for `SharedStore.windowMinutes`. Foreground only. func open() async { diff --git a/App/BlurtiOS/DESIGN.md b/App/BlurtiOS/DESIGN.md index 41ed16d7..d7d5deed 100644 --- a/App/BlurtiOS/DESIGN.md +++ b/App/BlurtiOS/DESIGN.md @@ -6,6 +6,13 @@ invented; every number traces to a Mac source file, and where the phone needed something the Mac has no equivalent for, this file says what was decided and why. +**Flat, matte, quiet.** Nothing on the phone is glossy, bevelled or dropped: +no gradient with a highlight, no shadow under a key, no edge line, no glow. +Surfaces are one colour, keys are one colour on it, the orb is a two-tone disc +with a moving edge. The reference for the principle (not the look) is what +the best dictation keyboards get right: generous space, few shapes, one +dark control that means "speak". + Source of truth on the Mac side: `App/Blurt/Blurt/Branding/BlurtBrand.swift` (tokens, orb gradient), `App/Blurt/Blurt/Overlay/OverlayView.swift` and `OverlayPillContent.swift` (the pill), `BrandOrb.swift` (the orb), @@ -35,9 +42,8 @@ the keyboard's sources are compiled into the app for it (`project.yml`). ## Themes, at the iPhone's spacing (`BlurtKeyboard/Sources/KeyboardPalette.swift`) The keys sit exactly where the iPhone keyboard's do, so nobody's fingers are -thrown off: 6 pt between keys, 11 pt between rows, 3 pt at the edges, 5 pt -corners, a 1 pt drop under every key. A theme changes how the keyboard looks -and never how it types. Six, curated, Partiful-style — pick from live +thrown off: 6 pt between keys, 11 pt between rows, 3 pt at the edges; 7 pt +corners, flat. A theme changes how the keyboard looks and never how it types. Six, curated, Partiful-style — pick from live previews in Settings → Keyboard → Theme; the keyboard picks it up the next time it comes up (`keyboardTheme` in the App Group): @@ -164,42 +170,49 @@ system keyboard puts its suggestion bar. The panel has it at 96 pt, centred in the space above the keys; the slim bar has it between the globe and delete. State is the orb's own shape and ring: -| State | Orb | Haptic | -| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------- | -| no Full Access / app not listening | dimmed (saturation 0.35, opacity 0.8); a tap opens Blurt | — | -| idle | the circle, ring still | — | -| connecting | ring 2 pt sweeping, as the app's orb does (one turn per 1.6 s) | — | -| recording | the circle grows sideways into a capsule (200 wide in the bar, 260 in the panel; spring 0.35 s) holding the live wave in white, glowing green with the level | medium impact | -| processing | back to the circle, ring sweeping | light impact | -| pasted | green solid ring, 1.2 s | success | -| copied (no field) | green solid ring with a clipboard glyph, 2 s | success | -| error | orange solid ring with an exclamation mark, 2 s; the message on VoiceOver | error | +| State | Orb | Haptic | +| ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | ------------- | +| no Full Access / app not listening | dimmed (saturation 0.35, opacity 0.8); a tap opens Blurt | — | +| idle | the circle, ring still | — | +| connecting | ring 2 pt sweeping, as the app's orb does (one turn per 1.6 s) | — | +| recording | the orb gives way to the wave, flat on the surface (200 wide in the bar, 260 in the panel; spring 0.35 s), in `greenOnDark` | medium impact | +| processing | back to the circle, ring sweeping | light impact | +| pasted | green solid ring, 1.2 s | success | +| copied (no field) | green solid ring with a clipboard glyph, 2 s | success | +| error | orange solid ring with an exclamation mark, 2 s; the message on VoiceOver | error | Every transition 0.15 s; the grow and shrink a spring. VoiceOver keeps the words: Dictate / Stop dictation / Start Blurt on the key, and the error message. -**Orb** (`BrandOrb.swift`) — the gradient disc with a hairline ring that sweeps -one turn per 1.6 s while something is happening, still otherwise. The disc -never moves. Under Reduce Motion the ring is drawn but holds still. +**Orb** (`BrandOrb.swift`) — a flat two-tone disc (the palette's violet into +its green, corner to corner: `BlurtBrand.orbFlat`, none of the Mac gradient's +white crown, which read as a glossy sphere on a phone) and, round its +perimeter, a soft comet of the palette — green, lavender, violet, fading to +nothing (`orbSweep`) — turned continuously, so the orb is never still: one +turn every 4 s at rest, the Mac pill's 1.6 s while the app works (connecting, +transcribing, the window open on the home screen). Ring width 4 % of the +diameter, at least 2 pt; a notice replaces the sweep with a solid green or +orange ring. Under Reduce Motion the sweep is drawn but holds still. **Meter** (`WaveformMeter` in `VoiceBar.swift`) — bars 3 pt wide, 3 pt apart, count from the width, heights from `MeterBarRow` (envelope, gamma, idle wave). The app publishes the level at ~12 Hz; the wave keeps the row alive between. -**Mic key** (`MicKey` in `KeyboardViews.swift`) — the orb _is_ the key, one -capsule shape whose width is its height until recording. No glyph: the Mac's -orb carries none and neither does this. Recording adds a green glow -(`greenOnDark` at 35–80 % with the level, radius 0.1–0.35 × size). Ring 2 pt -while working or noticing, 1 pt otherwise. Pressed: scale 0.94, 0.1 s. -Finger down / up drive the engine's `DictationKeyGate`, so a tap latches and -a hold is push-to-talk exactly as on the Mac; a touch that travelled more -than 24 pt cancels instead (it was a swipe). Cancel is the orange × in the -panel's top-right corner while something is in flight. - -**Keys** (`KeyCap`, `LetterKey`) — 42 pt tall, radius 5, 6 % white hairline; +**Mic key** (`MicKey` in `KeyboardViews.swift`) — the orb _is_ the key, +40 pt in the voice bar, 96 pt in the panel. No glyph: the Mac's carries none +and neither does this. While recording the orb gives way to the wave, flat on +the surface with no container (200 pt wide in the bar, 260 in the panel, 55 % +of the orb's height), and returns when the words are on their way; the +hand-off is a spring (0.35 s) with a fade and a small scale. Pressed: scale +0.94, 0.1 s. Finger down / up drive the engine's `DictationKeyGate`, so a tap +latches and a hold is push-to-talk exactly as on the Mac; a touch that +travelled more than 24 pt cancels instead (it was a swipe). Cancel is the +orange × in the panel's top-right corner while something is in flight. + +**Keys** (`KeyCap`, `LetterKey`) — 42 pt tall, radius 7, one flat colour: `key` for letters and space, `keyDark` for modifiers; a key brightens 15 % -while pressed rather than dimming. +while pressed rather than dimming; the letter pop-up is flat too. ## Layouts and their heights (`KeyboardLayout.height`) @@ -251,7 +264,7 @@ notifications that carry nothing and just say "look" (`SharedState.swift`). | level publish | every 80 ms while recording | the orb's meter, off the capture path's back | | lexicon refresh | hourly | thousands of contacts on a keyboard memory budget | | height change | 0.25 s; constraint priority 999 | iOS honours a keyboard's height at just under required | -| hero glow | `greenOnDark` 35–80 % with the level; radius 0.1–0.35 × the orb's size | one formula for the keyboard and the home screen | +| orb perimeter | one turn per 4 s at rest, 1.6 s working; width 4 % of the diameter, at least 2 pt | never still; the Mac pill's pace when busy | | letter pop-up | 32 pt glyph, key width + 18 × 56, radius 9, 58 pt above | the system keyboard's | | term field | 36 pt, 17 pt text, caret 0.5 s; the + is 32 pt | — | | term packs | ≤ 64 KB, ≤ 100 terms, ≤ 80 characters each | the request's cap; unbounded input from a stranger | @@ -271,14 +284,14 @@ shared, not copied (`project.yml`). **Home** (`HomeView.swift`) — the Mac's ready screen, stacked for a phone: -| Piece | What | -| ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Bar | the wordmark (tinted accent, 22 pt tall) centred; the gear → Settings | -| Setup card | only while something is missing: sign in (stub; debug builds take a key), microphone, keyboard + Full Access | -| Hero card | the orb, 112 pt, ring 2 pt sweeping while the mic is open or a dictation is in flight, glowing with the level while recording (the keyboard orb's formula); a title2 line (Not listening · Ready to dictate · Connecting… · Listening… · Transcribing… · Pasted · Copied · the error) and a callout under it; the meter while recording; **Start listening** (prominent; refused without a key, with a line saying so) or **Stop listening** (bordered, destructive; cancels a dictation in flight before closing, so nothing is transcribed for nobody); "Dictate here, to the clipboard" as a text button | -| Style | chips: Default and each profile, the active one filled with the accent; Edit → the styles editor | -| Recent | cards: three lines of text, the style as a tinted capsule, the relative time, a copy button; an empty-state card | -| Footer | "Powered by AssemblyAI", caption | +| Piece | What | +| ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Bar | the wordmark (tinted accent, 22 pt tall) centred; the gear → Settings | +| Setup card | only while something is missing: sign in (stub; debug builds take a key), microphone, keyboard + Full Access | +| Hero card | the orb, 112 pt, its perimeter circling slowly at rest and at the working pace while the mic is open or a dictation is in flight; a title2 line (Not listening · Ready to dictate · Connecting… · Listening… · Transcribing… · Pasted · Copied · the error) and a callout under it; the meter while recording; **Start listening** (prominent; refused without a key, with a line saying so) or **Stop listening** (bordered, destructive; cancels a dictation in flight before closing, so nothing is transcribed for nobody); "Dictate here, to the clipboard" as a text button | +| Style | chips: Default and each profile, the active one filled with the accent; Edit → the styles editor | +| Recent | cards: three lines of text, the style as a tinted capsule, the relative time, a copy button; an empty-state card | +| Footer | "Powered by AssemblyAI", caption | **Settings** (`SettingsView.swift`) — a sheet, grouped as the Mac's: Keyboard (layout, theme, hands-free), Listening (the window), Transcription (enhanced diff --git a/App/BlurtiOS/Shared/BlurtBrand.swift b/App/BlurtiOS/Shared/BlurtBrand.swift index 5d09eaf1..fa51ec7d 100644 --- a/App/BlurtiOS/Shared/BlurtBrand.swift +++ b/App/BlurtiOS/Shared/BlurtBrand.swift @@ -51,4 +51,26 @@ enum BlurtBrand { /// something is happening. nonisolated static let orbRingGradient = LinearGradient( colors: [green, .white], startPoint: .topLeading, endPoint: .bottomTrailing) + + // MARK: The flat orb — the phone's rendering of the same mark + + /// The disc, flat: the palette's violet into its green, corner to corner, + /// with none of the Mac gradient's white crown — on a phone that crown read + /// as a glossy sphere, and the design wants matte. + nonisolated static let orbFlat = LinearGradient( + colors: [Color(red: 57 / 255, green: 35 / 255, blue: 199 / 255), green], + startPoint: .topLeading, endPoint: .bottomTrailing) + + /// The perimeter: a soft comet of the palette — green, lavender, violet — + /// fading to nothing round the rest of the circle, and turned continuously, + /// so the orb is never still. + nonisolated static let orbSweep = AngularGradient( + stops: [ + .init(color: greenOnDark, location: 0), + .init(color: Color(red: 176 / 255, green: 167 / 255, blue: 233 / 255), location: 0.3), + .init(color: Color(red: 136 / 255, green: 123 / 255, blue: 221 / 255), location: 0.55), + .init(color: .clear, location: 0.8), + .init(color: .clear, location: 1), + ], + center: .center) } From 485b1cd130e315cea91d58f5ebbc10dede8a69c1 Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Fri, 25 Sep 2026 18:12:25 -0400 Subject: [PATCH 37/79] Revert "Flat: a matte two-tone orb with a circling perimeter, the wave bare, keys without edge or drop" This reverts commit a039f0e48894bb2bbab9f1e1473432f330dbb8fe. --- .../BlurtKeyboard/Sources/BrandOrb.swift | 54 +++---- .../Sources/FullKeyboardView.swift | 1 + .../Sources/KeyboardPalette.swift | 23 +-- .../BlurtKeyboard/Sources/KeyboardViews.swift | 75 +++++++--- .../BlurtKeyboard/Sources/VoiceBar.swift | 3 + App/BlurtiOS/BlurtiOS/Sources/HomeView.swift | 133 ++++++++---------- .../BlurtiOS/Sources/ListeningWindow.swift | 9 +- App/BlurtiOS/DESIGN.md | 87 +++++------- App/BlurtiOS/Shared/BlurtBrand.swift | 22 --- 9 files changed, 187 insertions(+), 220 deletions(-) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/BrandOrb.swift b/App/BlurtiOS/BlurtKeyboard/Sources/BrandOrb.swift index 4e721a49..2d37603f 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/BrandOrb.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/BrandOrb.swift @@ -1,62 +1,54 @@ import BlurtEngine import SwiftUI -/// The redraw cap for the keyboard's continuous motion — the perimeter's -/// sweep, the meter's idle wave. The Mac pill reads the same number from the -/// engine: the level feed moves at this cadence, so drawing faster only burns -/// the keyboard's tight energy and memory budget. +/// The redraw cap for the keyboard's continuous motion — the ring's sweep, the +/// meter's idle wave. The Mac pill reads the same number from the engine: the +/// level feed moves at this cadence, so drawing faster only burns the +/// keyboard's tight energy and memory budget. let keyboardAnimationInterval = MicCapture.meterIntervalSeconds -/// The brand orb as the phone draws it: a flat two-tone disc, and a soft -/// comet of the palette circling its perimeter — slowly at rest, so the orb -/// is never still, at the Mac pill's pace while the app works. The disc -/// underneath never moves. No glyph, no gloss, no shadow. +/// The brand orb, as the Mac pill draws it (`App/Blurt/Blurt/Overlay/BrandOrb.swift`): +/// the gradient disc, and a hairline ring that sweeps round it while something +/// is happening. It spins rather than pulses — a pulse says "alive", a sweep +/// says "working, and still going" — and the disc underneath never moves. /// -/// Sized by the caller: the app's home screen draws it as the hero, the -/// keyboard as the mic key. +/// Sized by the caller: the app's home screen draws it as the hero; the +/// keyboard's mic key draws its own capsule so it can grow into the wave. struct BrandOrb: View { var diameter: CGFloat - /// Seconds per turn of the perimeter. - var period: Double = BrandOrb.restPeriod - var ringWidth: CGFloat = 2 - /// A solid ring in place of the sweep — a notice's green or orange. - var ringColor: Color? - /// Whether the perimeter moves. Off under Reduce Motion, where the sweep is - /// still drawn but holds still. - var animated = true + /// Whether the ring sweeps. Off under Reduce Motion, where the ring is still + /// drawn — it is part of the mark — but holds still. + var animated: Bool + var ringWidth: CGFloat = 1 - /// At rest: one slow turn every 4 s, alive but not busy. - static let restPeriod: Double = 4 - /// While the app works: the Mac pill's 1.6 s. - static let workingPeriod: Double = 1.6 + /// One turn every 1.6 s: the Mac's cadence. + static let period: Double = 1.6 var body: some View { Circle() - .fill(BlurtBrand.orbFlat) + .fill(BlurtBrand.orbGradient) .frame(width: diameter, height: diameter) .overlay { ring } .accessibilityHidden(true) } @ViewBuilder private var ring: some View { - if let ringColor { - Circle().strokeBorder(ringColor, lineWidth: ringWidth) - } else if animated { + if animated { // The angle is a pure function of the clock (engine geometry), so the // sweep can't drift or restart mid-turn when the state beside it changes. TimelineView(.animation(minimumInterval: keyboardAnimationInterval)) { timeline in - sweep.rotationEffect( + ringShape.rotationEffect( .degrees( MeterBarGeometry.rotationDegrees( - time: timeline.date.timeIntervalSinceReferenceDate, period: period))) + time: timeline.date.timeIntervalSinceReferenceDate, period: Self.period))) } } else { - sweep + ringShape } } /// `strokeBorder` so the ring sits inside the disc instead of fringing it. - private var sweep: some View { - Circle().strokeBorder(BlurtBrand.orbSweep, lineWidth: ringWidth) + private var ringShape: some View { + Circle().strokeBorder(BlurtBrand.orbRingGradient, lineWidth: ringWidth) } } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift b/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift index 7bb2e4de..f31cf478 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift @@ -109,6 +109,7 @@ private struct LetterKey: View { .foregroundStyle(palette.keyText) .frame(width: width + 18, height: 56) .background(palette.popupFill, in: RoundedRectangle(cornerRadius: 9)) + .shadow(color: .black.opacity(0.25), radius: 4, y: 2) .offset(y: -58) .allowsHitTesting(false) } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift index 6b4b22c5..dde190f4 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift @@ -5,9 +5,9 @@ import SwiftUI /// a warm paper, a midnight, a sunset), each contemporary and fun and none of /// them off-brand. People pick one in the app, Partiful-style, from live /// previews; the spacing never changes (the iPhone keyboard's own — 6 pt -/// between keys, 11 between rows, 3 at the edges), so a theme changes how the -/// keyboard looks and never how it types. Everything is flat: no drop under a -/// key, no edge, no gloss — a matte surface with matte keys on it. +/// between keys, 11 between rows, 3 at the edges, 5 pt corners, a 1 pt drop +/// under every key), so a theme changes how the keyboard looks and never how +/// it types. struct KeyboardPalette: Equatable, Identifiable { let id: String let name: String @@ -17,43 +17,44 @@ struct KeyboardPalette: Equatable, Identifiable { let key: Color let keyDark: Color let keyText: Color + /// The drop under each key, as the system keyboard draws it. + let keyShadow: Color let popupFill: Color static let keyGap: CGFloat = 6 static let rowGap: CGFloat = 11 static let margin: CGFloat = 3 - /// A touch rounder than the system's 5: flat shapes want it. - static let keyRadius: CGFloat = 7 + static let keyRadius: CGFloat = 5 static let ink = KeyboardPalette( id: "ink", name: "Ink", vibe: "Blurt's own", surface: BlurtBrand.ink, key: BlurtBrand.key, keyDark: BlurtBrand.keyDark, keyText: BlurtBrand.keyText, - popupFill: BlurtBrand.key) + keyShadow: Color.black.opacity(0.45), popupFill: BlurtBrand.key) static let paper = KeyboardPalette( id: "paper", name: "Paper", vibe: "Warm and light", surface: Color(hex: 0xEBE8E8), key: .white, keyDark: Color(hex: 0xDEDBDB), keyText: BlurtBrand.ink, - popupFill: .white) + keyShadow: Color.black.opacity(0.18), popupFill: .white) static let lavender = KeyboardPalette( id: "lavender", name: "Lavender", vibe: "The orb's violet", surface: Color(hex: 0x2C2557), key: Color(hex: 0x3F3777), keyDark: Color(hex: 0x352E68), - keyText: Color(hex: 0xF1EEFF), popupFill: Color(hex: 0x3F3777)) + keyText: Color(hex: 0xF1EEFF), keyShadow: Color.black.opacity(0.4), popupFill: Color(hex: 0x3F3777)) static let mint = KeyboardPalette( id: "mint", name: "Mint", vibe: "The orb's green", surface: Color(hex: 0x10231B), key: Color(hex: 0x1E3F31), keyDark: Color(hex: 0x183429), - keyText: Color(hex: 0xE9F5EE), popupFill: Color(hex: 0x1E3F31)) + keyText: Color(hex: 0xE9F5EE), keyShadow: Color.black.opacity(0.4), popupFill: Color(hex: 0x1E3F31)) static let midnight = KeyboardPalette( id: "midnight", name: "Midnight", vibe: "Deep blue-black", surface: Color(hex: 0x0E1220), key: Color(hex: 0x1D2440), keyDark: Color(hex: 0x161B33), - keyText: Color(hex: 0xE8ECFF), popupFill: Color(hex: 0x1D2440)) + keyText: Color(hex: 0xE8ECFF), keyShadow: Color.black.opacity(0.5), popupFill: Color(hex: 0x1D2440)) static let sunset = KeyboardPalette( id: "sunset", name: "Sunset", vibe: "Warm and loud", surface: Color(hex: 0x2B1912), key: Color(hex: 0x4B2B20), keyDark: Color(hex: 0x3B2119), - keyText: Color(hex: 0xFFEFE6), popupFill: Color(hex: 0x4B2B20)) + keyText: Color(hex: 0xFFEFE6), keyShadow: Color.black.opacity(0.4), popupFill: Color(hex: 0x4B2B20)) static let all: [KeyboardPalette] = [ink, paper, lavender, mint, midnight, sunset] diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift index c03215cd..0d5395be 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift @@ -103,13 +103,13 @@ struct PanelView: View { /// The mic key is the brand orb, and it says everything without a word or a /// glyph. Finger down starts, finger up decides tap (latched) or hold /// (push-to-talk) — `KeyboardModel` runs the engine's gate. What it does: -/// its perimeter circles slowly at rest; dimmed when Blurt isn't ready (no -/// Full Access, or the app isn't listening; the tap opens Blurt); on a tap -/// the perimeter quickens while the mic comes up; then the orb gives way to -/// the live wave, flat on the surface, for as long as you talk; on the stop -/// the orb returns with its perimeter quick while the words come; then a -/// green ring for a moment when they landed, a clipboard on a green ring -/// when they went to the clipboard instead, an orange ring and an +/// dimmed when Blurt isn't ready (no Full Access, or the app isn't listening; +/// the tap opens Blurt); on a tap the ring sweeps as the app's orb does while +/// the mic comes up; then the orb grows sideways into a capsule holding the +/// live wave for as long as you talk, glowing with your voice; on the stop it +/// shrinks back to the circle with the ring sweeping while the words come; +/// then a green ring for a moment when they landed, a clipboard on a green +/// ring when they went to the clipboard instead, an orange ring and an /// exclamation mark when something failed. Each also has its haptic. struct MicKey: View { var model: KeyboardModel @@ -120,30 +120,33 @@ struct MicKey: View { @Environment(\.accessibilityReduceMotion) private var reduceMotion var body: some View { + let level = CGFloat(model.snapshot.level) let width = isRecording ? expandedWidth : size ZStack { + Capsule() + .fill(BlurtBrand.orbGradient) + .overlay { ring } + .saturation(isReady ? 1 : 0.35) + .opacity(isReady ? 1 : 0.8) if isRecording { - // The wave, flat on the surface: no container, no gloss. - WaveformMeter(level: Float(model.snapshot.level), animated: !reduceMotion, color: BlurtBrand.greenOnDark) - .frame(width: expandedWidth, height: size * 0.55) - .transition(.opacity.combined(with: .scale(scale: 0.6))) - } else { - BrandOrb( - diameter: size, period: isWorking ? BrandOrb.workingPeriod : BrandOrb.restPeriod, - ringWidth: max(2, size * 0.04), ringColor: ringColor, animated: !reduceMotion - ) - .saturation(isReady ? 1 : 0.3) - .opacity(isReady ? 1 : 0.7) - .transition(.opacity.combined(with: .scale(scale: 0.8))) + WaveformMeter(level: Float(model.snapshot.level), animated: !reduceMotion, color: .white.opacity(0.92)) + .frame(width: expandedWidth - size * 0.7, height: size * 0.5) + .transition(.opacity) } if let glyph { Image(systemName: glyph) .font(.system(size: size * 0.34, weight: .semibold)) .foregroundStyle(.white) + .shadow(color: .black.opacity(0.3), radius: 2, y: 1) .transition(.opacity) } } .frame(width: width, height: size) + .shadow( + color: BlurtBrand.greenOnDark.opacity(isRecording ? 0.35 + 0.45 * level : 0), + radius: isRecording ? size * 0.1 + level * size * 0.25 : 0 + ) + .animation(.easeOut(duration: 0.08), value: level) .animation(reduceMotion ? nil : .spring(duration: 0.35, bounce: 0.15), value: isRecording) .animation(.easeInOut(duration: 0.15), value: model.snapshot.state) .scaleEffect(pressed ? 0.94 : 1) @@ -198,6 +201,27 @@ struct MicKey: View { abs(value.translation.width) > 24 || abs(value.translation.height) > 24 } + /// The ring: the app orb's sweep (one turn per 1.6 s, engine geometry) + /// while the mic comes up and while the words come; still, and solid green + /// or orange, for a notice; still on the capsule while recording. + @ViewBuilder private var ring: some View { + let width: CGFloat = isWorking || isNotice ? 2 : 1 + if isWorking, !isRecording, !reduceMotion { + TimelineView(.animation(minimumInterval: keyboardAnimationInterval)) { timeline in + Capsule() + .strokeBorder(BlurtBrand.orbRingGradient, lineWidth: width) + .rotationEffect( + .degrees( + MeterBarGeometry.rotationDegrees( + time: timeline.date.timeIntervalSinceReferenceDate, period: BrandOrb.period))) + } + } else if let ringColor { + Capsule().strokeBorder(ringColor, lineWidth: width) + } else { + Capsule().strokeBorder(BlurtBrand.orbRingGradient, lineWidth: width) + } + } + private var isReady: Bool { model.isReady } private var isRecording: Bool { isReady && model.snapshot.state == .recording } private var isWorking: Bool { @@ -318,10 +342,17 @@ struct KeyPress: ViewModifier { } extension View { - /// The cap under a key's legend: the palette's fill and the corner radius, - /// nothing else — flat. + /// The cap under a key's legend: the palette's fill, the system keyboard's + /// corner radius and 1 pt drop, and a hairline so the cap reads on ink. func keyCap(_ fill: Color, palette: KeyboardPalette) -> some View { - background(fill, in: RoundedRectangle(cornerRadius: KeyboardPalette.keyRadius)) + background { + RoundedRectangle(cornerRadius: KeyboardPalette.keyRadius) + .fill(fill) + .shadow(color: palette.keyShadow, radius: 0, y: 1) + } + .overlay { + RoundedRectangle(cornerRadius: KeyboardPalette.keyRadius).strokeBorder(Color.white.opacity(0.06), lineWidth: 1) + } } } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift index ec926854..1194ec07 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift @@ -61,6 +61,7 @@ struct AddTermKey: View { .foregroundStyle(model.termSavedAt == nil ? palette.keyText.opacity(0.7) : BlurtBrand.greenOnDark) .frame(width: 32, height: 32) .background(Circle().fill(palette.keyDark)) + .overlay(Circle().strokeBorder(Color.white.opacity(0.08), lineWidth: 1)) .contentTransition(.symbolEffect(.replace)) } .buttonStyle(KeyPressStyle()) @@ -95,6 +96,7 @@ private struct TermField: View { .frame(maxWidth: .infinity) .frame(height: 36) .background(Capsule().fill(palette.keyDark)) + .overlay(Capsule().strokeBorder(BlurtBrand.greenOnDark.opacity(0.6), lineWidth: 1)) .accessibilityElement(children: .ignore) .accessibilityLabel("Key term: \(model.termDraft ?? "")") round("checkmark", tint: BlurtBrand.greenOnDark) { model.saveTerm() } @@ -111,6 +113,7 @@ private struct TermField: View { .foregroundStyle(tint) .frame(width: 32, height: 32) .background(Circle().fill(palette.keyDark)) + .overlay(Circle().strokeBorder(Color.white.opacity(0.08), lineWidth: 1)) } .buttonStyle(KeyPressStyle()) } diff --git a/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift b/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift index f47ff895..f89c846c 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift @@ -19,8 +19,6 @@ struct HomeView: View { @AppStorage(StyleProfileStore.activeDefaultsKey) private var activeRaw = "" private let styles = StyleProfileStore() - private static let orbSize: CGFloat = 112 - private var isSetUp: Bool { coordinator.apiKey.hasAPIKey && microphoneGranted && keyboardSeen } private var profiles: [StyleProfile] { styles.profiles(decoding: profilesRaw) } private var activeStyle: StyleProfile? { StyleProfileStore.active(in: profiles, id: activeRaw) } @@ -54,16 +52,11 @@ struct HomeView: View { } .sheet(isPresented: $showsKeyEntry) { KeyEntryView(apiKey: coordinator.apiKey) } .sheet(isPresented: $showsSettings) { SettingsView(coordinator: coordinator) } - .sheet(item: Binding(get: { coordinator.pendingTermPack }, set: { coordinator.pendingTermPack = $0 })) { - ImportTermsView(pack: $0) - } - .alert( - "Couldn't read that list", - isPresented: Binding(get: { coordinator.termPackUnreadable }, set: { coordinator.termPackUnreadable = $0 }) + .sheet( + isPresented: Binding( + get: { coordinator.pendingTermPack != nil }, set: { if !$0 { coordinator.pendingTermPack = nil } }) ) { - Button("OK") {} - } message: { - Text("It isn't a Blurt key-term list, or it's too big.") + if let pack = coordinator.pendingTermPack { ImportTermsView(pack: pack) } } .onChange(of: scenePhase) { _, phase in if phase == .active { refreshStatus() } @@ -80,18 +73,19 @@ struct HomeView: View { // MARK: - The orb and the listening state + private var level: CGFloat { CGFloat(coordinator.level) } private var isRecording: Bool { coordinator.phase == .recording } private var orbWorking: Bool { coordinator.window.isOpen || coordinator.phase.isCapturing } private var hero: some View { VStack(spacing: 18) { - // The keyboard's orb, larger: its perimeter circles slowly at rest and - // quickens while the mic is open or a dictation is in flight. - BrandOrb( - diameter: Self.orbSize, period: orbWorking ? BrandOrb.workingPeriod : BrandOrb.restPeriod, ringWidth: 4, - animated: !reduceMotion - ) - .padding(.top, 6) + BrandOrb(diameter: 112, animated: orbWorking && !reduceMotion, ringWidth: 2) + .shadow( + color: BlurtBrand.greenOnDark.opacity(isRecording ? 0.35 + 0.45 * level : 0), + radius: isRecording ? 14 + 30 * level : 0 + ) + .animation(.easeOut(duration: 0.08), value: level) + .padding(.top, 6) VStack(spacing: 4) { Text(heroTitle).font(.title2.weight(.semibold)).multilineTextAlignment(.center) Text(heroSubtitle).font(.callout).foregroundStyle(.secondary).multilineTextAlignment(.center) @@ -130,10 +124,6 @@ struct HomeView: View { Text("Blurt needs the microphone. Allow it in Settings.") .font(.footnote).foregroundStyle(BlurtBrand.errorOrange) } - if coordinator.needsKey { - Text("Add your API key first (Settings → Account).") - .font(.footnote).foregroundStyle(BlurtBrand.errorOrange) - } } .padding(20) .frame(maxWidth: .infinity) @@ -157,63 +147,11 @@ struct HomeView: View { return "Open the mic so the Blurt keyboard can dictate anywhere you type." } if let until = coordinator.window.until, until != .distantFuture { - return "Until \(until.formatted(date: .omitted, time: .shortened)) · tap the orb on the Blurt keyboard." - } - return "Until you stop it · tap the orb on the Blurt keyboard." - } - - // MARK: - Setup - - private var setupCard: some View { - VStack(alignment: .leading, spacing: 14) { - Text("Set up Blurt").font(.headline) - SetupRow(done: coordinator.apiKey.hasAPIKey, title: "Sign in with AssemblyAI") { - VStack(alignment: .leading, spacing: 6) { - Text("Coming soon — sign-in needs the AssemblyAI login service.") - .font(.footnote).foregroundStyle(.secondary) - #if DEBUG - Button("Use an API key instead") { showsKeyEntry = true } - #endif - } - } - SetupRow(done: microphoneGranted, title: "Allow the microphone") { - if AVAudioApplication.shared.recordPermission == .denied { - // iOS asks once; after a refusal only Settings can change it. - Button("Allow in Settings") { openAppSettings() } - } else { - Button("Allow") { - Task { - _ = await AVAudioApplication.requestRecordPermission() - refreshStatus() - } - } - } - } - SetupRow(done: keyboardSeen, title: "Add the Blurt keyboard") { - VStack(alignment: .leading, spacing: 6) { - Text( - "Settings → Keyboards: turn on Blurt and Allow Full Access. " - + "Full Access is what lets the keyboard send your words to Blurt." - ) - .font(.footnote).foregroundStyle(.secondary) - Button("Open Settings") { openAppSettings() } - } - } + return "Until \(until.formatted(date: .omitted, time: .shortened)) · tap the mic on the Blurt keyboard." } - .padding(20) - .frame(maxWidth: .infinity, alignment: .leading) - .card() - } - - private func openAppSettings() { - guard let url = URL(string: UIApplication.openSettingsURLString) else { return } - UIApplication.shared.open(url) + return "Until you stop it · tap the mic on the Blurt keyboard." } -} -// The style chips, the recent cards and the footer, as an extension so the -// struct's own body stays within the lint budget. -extension HomeView { // MARK: - Styles private var styleChips: some View { @@ -287,6 +225,49 @@ extension HomeView { .font(.caption) .padding(.top, 4) } + + // MARK: - Setup + + private var setupCard: some View { + VStack(alignment: .leading, spacing: 14) { + Text("Set up Blurt").font(.headline) + SetupRow(done: coordinator.apiKey.hasAPIKey, title: "Sign in with AssemblyAI") { + VStack(alignment: .leading, spacing: 6) { + Text("Coming soon — sign-in needs the AssemblyAI login service.") + .font(.footnote).foregroundStyle(.secondary) + #if DEBUG + Button("Use an API key instead") { showsKeyEntry = true } + #endif + } + } + SetupRow(done: microphoneGranted, title: "Allow the microphone") { + Button("Allow") { + Task { + await coordinator.startListening() + refreshStatus() + } + } + } + SetupRow(done: keyboardSeen, title: "Add the Blurt keyboard") { + VStack(alignment: .leading, spacing: 6) { + Text( + "Settings → Keyboards: turn on Blurt and Allow Full Access. " + + "Full Access is what lets the keyboard send your words to Blurt." + ) + .font(.footnote).foregroundStyle(.secondary) + Button("Open Settings") { openAppSettings() } + } + } + } + .padding(20) + .frame(maxWidth: .infinity, alignment: .leading) + .card() + } + + private func openAppSettings() { + guard let url = URL(string: UIApplication.openSettingsURLString) else { return } + UIApplication.shared.open(url) + } } /// One style, as a chip: filled with the accent while active. diff --git a/App/BlurtiOS/BlurtiOS/Sources/ListeningWindow.swift b/App/BlurtiOS/BlurtiOS/Sources/ListeningWindow.swift index 233b6584..74ecf235 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/ListeningWindow.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/ListeningWindow.swift @@ -29,14 +29,7 @@ final class ListeningWindow { @ObservationIgnored private var heartbeat: Task? @ObservationIgnored private var interruptions: Task? - /// Whether the microphone is open and the window hasn't lapsed. `until` - /// is read first, unconditionally: it is the observable half, and a view - /// that read it only after `source.isOpen` came true would never have - /// registered it and never redraw when the window opened. - var isOpen: Bool { - let lapsed = until.map { $0 <= Date() } ?? true - return !lapsed && source.isOpen - } + var isOpen: Bool { source.isOpen && (until.map { $0 > Date() } ?? false) } /// Opens the microphone for `SharedStore.windowMinutes`. Foreground only. func open() async { diff --git a/App/BlurtiOS/DESIGN.md b/App/BlurtiOS/DESIGN.md index d7d5deed..41ed16d7 100644 --- a/App/BlurtiOS/DESIGN.md +++ b/App/BlurtiOS/DESIGN.md @@ -6,13 +6,6 @@ invented; every number traces to a Mac source file, and where the phone needed something the Mac has no equivalent for, this file says what was decided and why. -**Flat, matte, quiet.** Nothing on the phone is glossy, bevelled or dropped: -no gradient with a highlight, no shadow under a key, no edge line, no glow. -Surfaces are one colour, keys are one colour on it, the orb is a two-tone disc -with a moving edge. The reference for the principle (not the look) is what -the best dictation keyboards get right: generous space, few shapes, one -dark control that means "speak". - Source of truth on the Mac side: `App/Blurt/Blurt/Branding/BlurtBrand.swift` (tokens, orb gradient), `App/Blurt/Blurt/Overlay/OverlayView.swift` and `OverlayPillContent.swift` (the pill), `BrandOrb.swift` (the orb), @@ -42,8 +35,9 @@ the keyboard's sources are compiled into the app for it (`project.yml`). ## Themes, at the iPhone's spacing (`BlurtKeyboard/Sources/KeyboardPalette.swift`) The keys sit exactly where the iPhone keyboard's do, so nobody's fingers are -thrown off: 6 pt between keys, 11 pt between rows, 3 pt at the edges; 7 pt -corners, flat. A theme changes how the keyboard looks and never how it types. Six, curated, Partiful-style — pick from live +thrown off: 6 pt between keys, 11 pt between rows, 3 pt at the edges, 5 pt +corners, a 1 pt drop under every key. A theme changes how the keyboard looks +and never how it types. Six, curated, Partiful-style — pick from live previews in Settings → Keyboard → Theme; the keyboard picks it up the next time it comes up (`keyboardTheme` in the App Group): @@ -170,49 +164,42 @@ system keyboard puts its suggestion bar. The panel has it at 96 pt, centred in the space above the keys; the slim bar has it between the globe and delete. State is the orb's own shape and ring: -| State | Orb | Haptic | -| ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | ------------- | -| no Full Access / app not listening | dimmed (saturation 0.35, opacity 0.8); a tap opens Blurt | — | -| idle | the circle, ring still | — | -| connecting | ring 2 pt sweeping, as the app's orb does (one turn per 1.6 s) | — | -| recording | the orb gives way to the wave, flat on the surface (200 wide in the bar, 260 in the panel; spring 0.35 s), in `greenOnDark` | medium impact | -| processing | back to the circle, ring sweeping | light impact | -| pasted | green solid ring, 1.2 s | success | -| copied (no field) | green solid ring with a clipboard glyph, 2 s | success | -| error | orange solid ring with an exclamation mark, 2 s; the message on VoiceOver | error | +| State | Orb | Haptic | +| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------- | +| no Full Access / app not listening | dimmed (saturation 0.35, opacity 0.8); a tap opens Blurt | — | +| idle | the circle, ring still | — | +| connecting | ring 2 pt sweeping, as the app's orb does (one turn per 1.6 s) | — | +| recording | the circle grows sideways into a capsule (200 wide in the bar, 260 in the panel; spring 0.35 s) holding the live wave in white, glowing green with the level | medium impact | +| processing | back to the circle, ring sweeping | light impact | +| pasted | green solid ring, 1.2 s | success | +| copied (no field) | green solid ring with a clipboard glyph, 2 s | success | +| error | orange solid ring with an exclamation mark, 2 s; the message on VoiceOver | error | Every transition 0.15 s; the grow and shrink a spring. VoiceOver keeps the words: Dictate / Stop dictation / Start Blurt on the key, and the error message. -**Orb** (`BrandOrb.swift`) — a flat two-tone disc (the palette's violet into -its green, corner to corner: `BlurtBrand.orbFlat`, none of the Mac gradient's -white crown, which read as a glossy sphere on a phone) and, round its -perimeter, a soft comet of the palette — green, lavender, violet, fading to -nothing (`orbSweep`) — turned continuously, so the orb is never still: one -turn every 4 s at rest, the Mac pill's 1.6 s while the app works (connecting, -transcribing, the window open on the home screen). Ring width 4 % of the -diameter, at least 2 pt; a notice replaces the sweep with a solid green or -orange ring. Under Reduce Motion the sweep is drawn but holds still. +**Orb** (`BrandOrb.swift`) — the gradient disc with a hairline ring that sweeps +one turn per 1.6 s while something is happening, still otherwise. The disc +never moves. Under Reduce Motion the ring is drawn but holds still. **Meter** (`WaveformMeter` in `VoiceBar.swift`) — bars 3 pt wide, 3 pt apart, count from the width, heights from `MeterBarRow` (envelope, gamma, idle wave). The app publishes the level at ~12 Hz; the wave keeps the row alive between. -**Mic key** (`MicKey` in `KeyboardViews.swift`) — the orb _is_ the key, -40 pt in the voice bar, 96 pt in the panel. No glyph: the Mac's carries none -and neither does this. While recording the orb gives way to the wave, flat on -the surface with no container (200 pt wide in the bar, 260 in the panel, 55 % -of the orb's height), and returns when the words are on their way; the -hand-off is a spring (0.35 s) with a fade and a small scale. Pressed: scale -0.94, 0.1 s. Finger down / up drive the engine's `DictationKeyGate`, so a tap -latches and a hold is push-to-talk exactly as on the Mac; a touch that -travelled more than 24 pt cancels instead (it was a swipe). Cancel is the -orange × in the panel's top-right corner while something is in flight. - -**Keys** (`KeyCap`, `LetterKey`) — 42 pt tall, radius 7, one flat colour: +**Mic key** (`MicKey` in `KeyboardViews.swift`) — the orb _is_ the key, one +capsule shape whose width is its height until recording. No glyph: the Mac's +orb carries none and neither does this. Recording adds a green glow +(`greenOnDark` at 35–80 % with the level, radius 0.1–0.35 × size). Ring 2 pt +while working or noticing, 1 pt otherwise. Pressed: scale 0.94, 0.1 s. +Finger down / up drive the engine's `DictationKeyGate`, so a tap latches and +a hold is push-to-talk exactly as on the Mac; a touch that travelled more +than 24 pt cancels instead (it was a swipe). Cancel is the orange × in the +panel's top-right corner while something is in flight. + +**Keys** (`KeyCap`, `LetterKey`) — 42 pt tall, radius 5, 6 % white hairline; `key` for letters and space, `keyDark` for modifiers; a key brightens 15 % -while pressed rather than dimming; the letter pop-up is flat too. +while pressed rather than dimming. ## Layouts and their heights (`KeyboardLayout.height`) @@ -264,7 +251,7 @@ notifications that carry nothing and just say "look" (`SharedState.swift`). | level publish | every 80 ms while recording | the orb's meter, off the capture path's back | | lexicon refresh | hourly | thousands of contacts on a keyboard memory budget | | height change | 0.25 s; constraint priority 999 | iOS honours a keyboard's height at just under required | -| orb perimeter | one turn per 4 s at rest, 1.6 s working; width 4 % of the diameter, at least 2 pt | never still; the Mac pill's pace when busy | +| hero glow | `greenOnDark` 35–80 % with the level; radius 0.1–0.35 × the orb's size | one formula for the keyboard and the home screen | | letter pop-up | 32 pt glyph, key width + 18 × 56, radius 9, 58 pt above | the system keyboard's | | term field | 36 pt, 17 pt text, caret 0.5 s; the + is 32 pt | — | | term packs | ≤ 64 KB, ≤ 100 terms, ≤ 80 characters each | the request's cap; unbounded input from a stranger | @@ -284,14 +271,14 @@ shared, not copied (`project.yml`). **Home** (`HomeView.swift`) — the Mac's ready screen, stacked for a phone: -| Piece | What | -| ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Bar | the wordmark (tinted accent, 22 pt tall) centred; the gear → Settings | -| Setup card | only while something is missing: sign in (stub; debug builds take a key), microphone, keyboard + Full Access | -| Hero card | the orb, 112 pt, its perimeter circling slowly at rest and at the working pace while the mic is open or a dictation is in flight; a title2 line (Not listening · Ready to dictate · Connecting… · Listening… · Transcribing… · Pasted · Copied · the error) and a callout under it; the meter while recording; **Start listening** (prominent; refused without a key, with a line saying so) or **Stop listening** (bordered, destructive; cancels a dictation in flight before closing, so nothing is transcribed for nobody); "Dictate here, to the clipboard" as a text button | -| Style | chips: Default and each profile, the active one filled with the accent; Edit → the styles editor | -| Recent | cards: three lines of text, the style as a tinted capsule, the relative time, a copy button; an empty-state card | -| Footer | "Powered by AssemblyAI", caption | +| Piece | What | +| ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Bar | the wordmark (tinted accent, 22 pt tall) centred; the gear → Settings | +| Setup card | only while something is missing: sign in (stub; debug builds take a key), microphone, keyboard + Full Access | +| Hero card | the orb, 112 pt, ring 2 pt sweeping while the mic is open or a dictation is in flight, glowing with the level while recording (the keyboard orb's formula); a title2 line (Not listening · Ready to dictate · Connecting… · Listening… · Transcribing… · Pasted · Copied · the error) and a callout under it; the meter while recording; **Start listening** (prominent; refused without a key, with a line saying so) or **Stop listening** (bordered, destructive; cancels a dictation in flight before closing, so nothing is transcribed for nobody); "Dictate here, to the clipboard" as a text button | +| Style | chips: Default and each profile, the active one filled with the accent; Edit → the styles editor | +| Recent | cards: three lines of text, the style as a tinted capsule, the relative time, a copy button; an empty-state card | +| Footer | "Powered by AssemblyAI", caption | **Settings** (`SettingsView.swift`) — a sheet, grouped as the Mac's: Keyboard (layout, theme, hands-free), Listening (the window), Transcription (enhanced diff --git a/App/BlurtiOS/Shared/BlurtBrand.swift b/App/BlurtiOS/Shared/BlurtBrand.swift index fa51ec7d..5d09eaf1 100644 --- a/App/BlurtiOS/Shared/BlurtBrand.swift +++ b/App/BlurtiOS/Shared/BlurtBrand.swift @@ -51,26 +51,4 @@ enum BlurtBrand { /// something is happening. nonisolated static let orbRingGradient = LinearGradient( colors: [green, .white], startPoint: .topLeading, endPoint: .bottomTrailing) - - // MARK: The flat orb — the phone's rendering of the same mark - - /// The disc, flat: the palette's violet into its green, corner to corner, - /// with none of the Mac gradient's white crown — on a phone that crown read - /// as a glossy sphere, and the design wants matte. - nonisolated static let orbFlat = LinearGradient( - colors: [Color(red: 57 / 255, green: 35 / 255, blue: 199 / 255), green], - startPoint: .topLeading, endPoint: .bottomTrailing) - - /// The perimeter: a soft comet of the palette — green, lavender, violet — - /// fading to nothing round the rest of the circle, and turned continuously, - /// so the orb is never still. - nonisolated static let orbSweep = AngularGradient( - stops: [ - .init(color: greenOnDark, location: 0), - .init(color: Color(red: 176 / 255, green: 167 / 255, blue: 233 / 255), location: 0.3), - .init(color: Color(red: 136 / 255, green: 123 / 255, blue: 221 / 255), location: 0.55), - .init(color: .clear, location: 0.8), - .init(color: .clear, location: 1), - ], - center: .center) } From b63201afff446f769f0bad5e9b76005bd266b9ff Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Fri, 25 Sep 2026 19:06:31 -0400 Subject: [PATCH 38/79] App: the home screen's half of the audit fixes The import sheet by item; an alert for an unreadable list; a line when the microphone can't open without a key; the denied-microphone step opens Settings; the orb's size named. Co-Authored-By: Claude Fable 5.1 --- App/BlurtiOS/BlurtiOS/Sources/HomeView.swift | 31 +++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift b/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift index f89c846c..dc868c4c 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift @@ -52,11 +52,16 @@ struct HomeView: View { } .sheet(isPresented: $showsKeyEntry) { KeyEntryView(apiKey: coordinator.apiKey) } .sheet(isPresented: $showsSettings) { SettingsView(coordinator: coordinator) } - .sheet( - isPresented: Binding( - get: { coordinator.pendingTermPack != nil }, set: { if !$0 { coordinator.pendingTermPack = nil } }) + .sheet(item: Binding(get: { coordinator.pendingTermPack }, set: { coordinator.pendingTermPack = $0 })) { + ImportTermsView(pack: $0) + } + .alert( + "Couldn't read that list", + isPresented: Binding(get: { coordinator.termPackUnreadable }, set: { coordinator.termPackUnreadable = $0 }) ) { - if let pack = coordinator.pendingTermPack { ImportTermsView(pack: pack) } + Button("OK") {} + } message: { + Text("It isn't a Blurt key-term list, or it's too big.") } .onChange(of: scenePhase) { _, phase in if phase == .active { refreshStatus() } @@ -73,6 +78,7 @@ struct HomeView: View { // MARK: - The orb and the listening state + private static let orbSize: CGFloat = 112 private var level: CGFloat { CGFloat(coordinator.level) } private var isRecording: Bool { coordinator.phase == .recording } private var orbWorking: Bool { coordinator.window.isOpen || coordinator.phase.isCapturing } @@ -124,6 +130,10 @@ struct HomeView: View { Text("Blurt needs the microphone. Allow it in Settings.") .font(.footnote).foregroundStyle(BlurtBrand.errorOrange) } + if coordinator.needsKey { + Text("Add your API key first (Settings → Account).") + .font(.footnote).foregroundStyle(BlurtBrand.errorOrange) + } } .padding(20) .frame(maxWidth: .infinity) @@ -241,10 +251,15 @@ struct HomeView: View { } } SetupRow(done: microphoneGranted, title: "Allow the microphone") { - Button("Allow") { - Task { - await coordinator.startListening() - refreshStatus() + if AVAudioApplication.shared.recordPermission == .denied { + // iOS asks once; after a refusal only Settings can change it. + Button("Allow in Settings") { openAppSettings() } + } else { + Button("Allow") { + Task { + _ = await AVAudioApplication.requestRecordPermission() + refreshStatus() + } } } } From c1d8feeb43ed8003ec8e10f9bddf2daa12a26cfe Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Fri, 25 Sep 2026 19:07:28 -0400 Subject: [PATCH 39/79] =?UTF-8?q?Prototype:=20the=20prism=20orb=20?= =?UTF-8?q?=E2=80=94=20green=20in,=20violet=20out,=20sparkles=20when=20the?= =?UTF-8?q?=20words=20land?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The brand artwork's story as the orb: a mesh gradient that drifts like liquid and swells with the voice, leaning green while you talk and turning violet while the words are made, finishing violet and light with a scatter of sparkles; a soft upper-left light and animated film grain for the matte, airy look. Fills the keyboard's mic key and the home hero; the ring stays. On its own branch, to be judged on the simulator. Co-Authored-By: Claude Fable 5.1 --- .../BlurtKeyboard/Sources/KeyboardViews.swift | 16 +- .../BlurtKeyboard/Sources/PrismOrb.swift | 166 ++++++++++++++++++ App/BlurtiOS/BlurtiOS/Sources/HomeView.swift | 40 ++++- App/BlurtiOS/DESIGN.md | 14 ++ 4 files changed, 232 insertions(+), 4 deletions(-) create mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/PrismOrb.swift diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift index 0d5395be..37f2fda6 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift @@ -123,8 +123,8 @@ struct MicKey: View { let level = CGFloat(model.snapshot.level) let width = isRecording ? expandedWidth : size ZStack { - Capsule() - .fill(BlurtBrand.orbGradient) + PrismOrb(mood: mood, animated: !reduceMotion) + .clipShape(Capsule()) .overlay { ring } .saturation(isReady ? 1 : 0.35) .opacity(isReady ? 1 : 0.8) @@ -223,6 +223,18 @@ struct MicKey: View { } private var isReady: Bool { model.isReady } + + /// The orb's story from the phase: green going in, violet coming out. + private var mood: PrismOrb.Mood { + guard isReady else { return .off } + switch model.snapshot.state { + case .idle, .error: return .idle + case .connecting: return .listening(level: 0) + case .recording: return .listening(level: Float(model.snapshot.level)) + case .processing: return .working + case .pasted, .copied: return .done + } + } private var isRecording: Bool { isReady && model.snapshot.state == .recording } private var isWorking: Bool { switch model.snapshot.state { diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/PrismOrb.swift b/App/BlurtiOS/BlurtKeyboard/Sources/PrismOrb.swift new file mode 100644 index 00000000..5486e148 --- /dev/null +++ b/App/BlurtiOS/BlurtKeyboard/Sources/PrismOrb.swift @@ -0,0 +1,166 @@ +import BlurtEngine +import SwiftUI + +/// The brand's artwork in motion. In the illustration a green beam goes into +/// the prism and a violet, starlit one comes out: green is the input, the +/// voice; violet is the magic, the words. The orb tells that story as it +/// works — leaning green and swelling with the voice while you talk, turning +/// violet while the words are made, finishing violet with a scatter of +/// sparkles when they land. Liquid in its motion (a mesh gradient whose +/// points drift, more with the voice), airy in its look (soft light, low +/// contrast), and matte under film grain, as the artwork is. +/// +/// A fill: the caller clips it to a circle or a capsule and puts the ring on +/// top. Under Reduce Motion the fluid holds still and the grain is fixed. +struct PrismOrb: View { + enum Mood: Equatable { + /// Blurt is not ready: the brand mix, dimmed by the caller. + case off + /// Resting: the brand mix, breathing. + case idle + /// The voice going in: green, moving with the level (0…1). + case listening(level: Float) + /// The words being made: violet, working. + case working + /// The words landed: violet and light, with sparkles. + case done + } + + var mood: Mood + var animated: Bool + + var body: some View { + TimelineView(.animation(minimumInterval: keyboardAnimationInterval, paused: !animated)) { timeline in + let time = animated ? timeline.date.timeIntervalSinceReferenceDate : 0 + ZStack { + Rectangle().fill(mesh(at: time)) + // A soft light from the upper left, so the disc reads as a body, not + // a flat swatch — airy, not glossy. + Rectangle().fill( + RadialGradient( + colors: [.white.opacity(0.32), .clear], center: UnitPoint(x: 0.3, y: 0.22), startRadius: 0, + endRadius: 110)) + Grain(seed: animated ? Int(time * 24) : 7).opacity(0.5).blendMode(.overlay) + if case .done = mood { Sparkles(time: time) } + } + } + .animation(.easeInOut(duration: 0.7), value: mood) + } + + // MARK: The fluid + + /// A 3 × 3 mesh. The corners stay put; the edge midpoints and the centre + /// drift on slow sines, further with the voice. + private func mesh(at time: TimeInterval) -> MeshGradient { + let level = CGFloat(self.level) + let sway = 0.10 + 0.16 * level + func drift(_ base: Float, _ phase: Double, _ speed: Double) -> Float { + base + Float(sway * sin(time * speed + phase)) + } + let points: [SIMD2] = [ + [0, 0], [drift(0.5, 0.0, 0.9), 0], [1, 0], + [0, drift(0.5, 1.7, 0.7)], [drift(0.5, 3.1, 1.1), drift(0.5, 0.6, 0.8)], [1, drift(0.5, 4.2, 0.6)], + [0, 1], [drift(0.5, 2.3, 1.0), 1], [1, 1], + ] + return MeshGradient(width: 3, height: 3, points: points, colors: colors) + } + + private var level: Float { + if case .listening(let level) = mood { return level } + return 0 + } + + /// Row-major, top to bottom. The brand gradient's own stops + /// (`BlurtBrand.orbGradient`), dealt differently per mood. + private var colors: [Color] { + switch mood { + case .off, .idle: + return [ + Palette.white, Palette.lavender, Palette.periwinkle, + Palette.periwinkle, Palette.greenLight, Palette.violet, + Palette.green, Palette.greenLight, Palette.violet, + ] + case .listening(let level): + // More green the louder: the beam going in. + let bright = Color( + red: 0.40 + 0.3 * Double(level), green: 0.68 + 0.25 * Double(level), blue: 0.51 + 0.1 * Double(level)) + return [ + Palette.lavender, Palette.greenLight, Palette.lavender, + Palette.greenLight, bright, Palette.greenLight, + Palette.green, Palette.greenLight, Palette.green, + ] + case .working: + return [ + Palette.lavender, Palette.periwinkle, Palette.lavender, + Palette.periwinkle, Palette.violet, Palette.periwinkle, + Palette.violet, Palette.periwinkle, Palette.violet, + ] + case .done: + return [ + Palette.white, Palette.lavender, Palette.white, + Palette.lavender, Palette.periwinkle, Palette.lavender, + Palette.violet, Palette.periwinkle, Palette.violet, + ] + } + } + + private enum Palette { + static let white = Color(red: 0.97, green: 0.96, blue: 1) + static let lavender = Color(red: 215 / 255, green: 211 / 255, blue: 244 / 255) + static let periwinkle = Color(red: 176 / 255, green: 167 / 255, blue: 233 / 255) + static let violet = Color(red: 57 / 255, green: 35 / 255, blue: 199 / 255) + static let green = BlurtBrand.green + static let greenLight = BlurtBrand.greenOnDark + } +} + +/// Film grain: a scatter of faint dots, a new scatter each frame so it +/// shimmers the way grain does, drawn from a seed so a frame is reproducible. +private struct Grain: View { + let seed: Int + + var body: some View { + Canvas(rendersAsynchronously: true) { context, size in + var state = UInt64(truncatingIfNeeded: seed &* 6_364_136_223_846_793_005 &+ 1) + func next() -> CGFloat { + state = state &* 6_364_136_223_846_793_005 &+ 1_442_695_040_888_963_407 + return CGFloat(state >> 40) / CGFloat(1 << 24) + } + let count = Int(size.width * size.height / 26) + for _ in 0.. 0.5 ? .white.opacity(0.18) : .black.opacity(0.22))) + } + } + .accessibilityHidden(true) + } +} + +/// The artwork's stars: a handful of four-point sparkles that twinkle round +/// the orb while the words are landing. +private struct Sparkles: View { + let time: TimeInterval + + private static let spots: [(x: CGFloat, y: CGFloat, size: CGFloat, phase: Double)] = [ + (0.18, 0.28, 0.16, 0.0), (0.76, 0.2, 0.11, 1.3), (0.82, 0.62, 0.14, 2.6), (0.3, 0.74, 0.1, 3.7), + (0.58, 0.44, 0.08, 4.9), (0.5, 0.86, 0.12, 1.9), + ] + + var body: some View { + GeometryReader { geo in + ForEach(Array(Self.spots.enumerated()), id: \.offset) { _, spot in + let pulse = max(0, sin(time * 2.4 + spot.phase)) + Image(systemName: "sparkle") + .font(.system(size: min(geo.size.width, geo.size.height) * spot.size, weight: .regular)) + .foregroundStyle(.white) + .opacity(0.35 + 0.65 * pulse) + .scaleEffect(0.7 + 0.5 * pulse) + .position(x: geo.size.width * spot.x, y: geo.size.height * spot.y) + } + } + .accessibilityHidden(true) + } +} diff --git a/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift b/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift index dc868c4c..5e24b03f 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift @@ -85,10 +85,14 @@ struct HomeView: View { private var hero: some View { VStack(spacing: 18) { - BrandOrb(diameter: 112, animated: orbWorking && !reduceMotion, ringWidth: 2) + PrismOrb(mood: heroMood, animated: !reduceMotion) + .frame(width: Self.orbSize, height: Self.orbSize) + .clipShape(Circle()) + .overlay { HeroRing(animated: orbWorking && !reduceMotion) } + .saturation(coordinator.window.isOpen ? 1 : 0.45) .shadow( color: BlurtBrand.greenOnDark.opacity(isRecording ? 0.35 + 0.45 * level : 0), - radius: isRecording ? 14 + 30 * level : 0 + radius: isRecording ? Self.orbSize * 0.1 + level * Self.orbSize * 0.25 : 0 ) .animation(.easeOut(duration: 0.08), value: level) .padding(.top, 6) @@ -140,6 +144,17 @@ struct HomeView: View { .card() } + private var heroMood: PrismOrb.Mood { + guard coordinator.window.isOpen else { return .off } + switch coordinator.phase.overlayState { + case .idle, .error: return .idle + case .connecting: return .listening(level: 0) + case .recording: return .listening(level: coordinator.level) + case .processing: return .working + case .pasted, .noTarget: return .done + } + } + private var heroTitle: String { switch coordinator.phase.overlayState { case .connecting: return "Connecting…" @@ -324,3 +339,24 @@ private struct SetupRow: View { } } } + +/// The hero orb's ring: the brand orb's sweep, on its own so the prism can +/// be the fill. +private struct HeroRing: View { + let animated: Bool + + var body: some View { + if animated { + TimelineView(.animation(minimumInterval: keyboardAnimationInterval)) { timeline in + Circle() + .strokeBorder(BlurtBrand.orbRingGradient, lineWidth: 2) + .rotationEffect( + .degrees( + MeterBarGeometry.rotationDegrees( + time: timeline.date.timeIntervalSinceReferenceDate, period: BrandOrb.period))) + } + } else { + Circle().strokeBorder(BlurtBrand.orbRingGradient, lineWidth: 2) + } + } +} diff --git a/App/BlurtiOS/DESIGN.md b/App/BlurtiOS/DESIGN.md index 41ed16d7..723b4cfe 100644 --- a/App/BlurtiOS/DESIGN.md +++ b/App/BlurtiOS/DESIGN.md @@ -32,6 +32,20 @@ of the keyboard's own: `keys` (the panel flipped to its keyboard page) and gallery is `BlurtiOS/Sources/KeyboardGalleryView.swift`, debug builds only; the keyboard's sources are compiled into the app for it (`project.yml`). +## Prototype on this branch: the prism orb (`PrismOrb.swift`) + +The brand artwork — a green beam into the prism, a violet, starlit one out — +as the orb's own story. The mic key and the home hero are filled by a 3 × 3 +`MeshGradient` whose edge and centre points drift on slow sines (further +with the voice level), under a soft upper-left light, animated film grain (a +seeded scatter of faint dots, new each frame at 20 Hz) and, when the words +land, six four-point sparkles twinkling. Moods: `off` and `idle` (the brand +mix), `listening(level:)` (green, brighter with the voice), `working` +(violet), `done` (violet and light, sparkles). Mood changes cross-fade over +0.7 s. Under Reduce Motion everything holds still. The ring stays the Mac +orb's. Not merged: judge it on the simulator (`-BlurtGallery panel +idle,recording,processing,pasted`, `-BlurtStartListening` for the hero). + ## Themes, at the iPhone's spacing (`BlurtKeyboard/Sources/KeyboardPalette.swift`) The keys sit exactly where the iPhone keyboard's do, so nobody's fingers are From d8f426a33ebe87d3d307a71ef6771a87f40d39e1 Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Fri, 25 Sep 2026 19:06:31 -0400 Subject: [PATCH 40/79] App: the home screen's half of the audit fixes The import sheet by item; an alert for an unreadable list; a line when the microphone can't open without a key; the denied-microphone step opens Settings; the orb's size named. Co-Authored-By: Claude Fable 5.1 (cherry picked from commit b63201afff446f769f0bad5e9b76005bd266b9ff) --- App/BlurtiOS/BlurtiOS/Sources/HomeView.swift | 31 +++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift b/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift index f89c846c..dc868c4c 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift @@ -52,11 +52,16 @@ struct HomeView: View { } .sheet(isPresented: $showsKeyEntry) { KeyEntryView(apiKey: coordinator.apiKey) } .sheet(isPresented: $showsSettings) { SettingsView(coordinator: coordinator) } - .sheet( - isPresented: Binding( - get: { coordinator.pendingTermPack != nil }, set: { if !$0 { coordinator.pendingTermPack = nil } }) + .sheet(item: Binding(get: { coordinator.pendingTermPack }, set: { coordinator.pendingTermPack = $0 })) { + ImportTermsView(pack: $0) + } + .alert( + "Couldn't read that list", + isPresented: Binding(get: { coordinator.termPackUnreadable }, set: { coordinator.termPackUnreadable = $0 }) ) { - if let pack = coordinator.pendingTermPack { ImportTermsView(pack: pack) } + Button("OK") {} + } message: { + Text("It isn't a Blurt key-term list, or it's too big.") } .onChange(of: scenePhase) { _, phase in if phase == .active { refreshStatus() } @@ -73,6 +78,7 @@ struct HomeView: View { // MARK: - The orb and the listening state + private static let orbSize: CGFloat = 112 private var level: CGFloat { CGFloat(coordinator.level) } private var isRecording: Bool { coordinator.phase == .recording } private var orbWorking: Bool { coordinator.window.isOpen || coordinator.phase.isCapturing } @@ -124,6 +130,10 @@ struct HomeView: View { Text("Blurt needs the microphone. Allow it in Settings.") .font(.footnote).foregroundStyle(BlurtBrand.errorOrange) } + if coordinator.needsKey { + Text("Add your API key first (Settings → Account).") + .font(.footnote).foregroundStyle(BlurtBrand.errorOrange) + } } .padding(20) .frame(maxWidth: .infinity) @@ -241,10 +251,15 @@ struct HomeView: View { } } SetupRow(done: microphoneGranted, title: "Allow the microphone") { - Button("Allow") { - Task { - await coordinator.startListening() - refreshStatus() + if AVAudioApplication.shared.recordPermission == .denied { + // iOS asks once; after a refusal only Settings can change it. + Button("Allow in Settings") { openAppSettings() } + } else { + Button("Allow") { + Task { + _ = await AVAudioApplication.requestRecordPermission() + refreshStatus() + } } } } From 584dc025796be5d0aba15c3370cf5ca110f161fd Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Fri, 25 Sep 2026 19:19:16 -0400 Subject: [PATCH 41/79] Prototype: the orb lives green; a violet drop pulses in when the words land, then flows back MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Green is home — calm at rest, greener and swelling with the voice — and the moment the words go into the field a violet, glittering drop blooms from the centre with the haptic, held a beat, then flows back out into the green over a second. Keyed to the landing itself (the keyboard's insert; the phase on the home screen), not to a state, so it reads as an event. The gallery's 'landed' state times it for a screenshot. Co-Authored-By: Claude Fable 5.1 --- .../Sources/KeyboardModel+Phase.swift | 1 + .../BlurtKeyboard/Sources/KeyboardModel.swift | 2 + .../BlurtKeyboard/Sources/KeyboardViews.swift | 8 +- .../BlurtKeyboard/Sources/PrismOrb.swift | 137 +++++++++++------- App/BlurtiOS/BlurtiOS/Sources/HomeView.swift | 13 +- .../Sources/KeyboardGalleryView.swift | 3 + App/BlurtiOS/DESIGN.md | 20 ++- 7 files changed, 118 insertions(+), 66 deletions(-) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Phase.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Phase.swift index c763a6d0..9145cb74 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Phase.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Phase.swift @@ -56,6 +56,7 @@ extension KeyboardModel { // Joined against the live text before the cursor, not the press-time // snapshot: the user may have typed since. proxy.insertText(InsertionSeparator.withLeadingSeparator(result.text, after: proxy.documentContextBeforeInput)) + resultLandedAt = Date() // Not typing, so not the term field's to claim. if termDraft != nil { termHostBaseline = proxy.documentContextBeforeInput ?? "" } } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift index 04f99555..3b1066e6 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift @@ -32,6 +32,8 @@ final class KeyboardModel { /// The direction of the last flip, so the pages slide the way the finger went. var flipTowardsLeading = false var snapshot = PhaseSnapshot.idle + /// When this keyboard last put the words into the field — the orb's drop. + var resultLandedAt: Date? /// The key term being typed on the keys, while the voice bar is a field; /// nil otherwise. See `beginAddingTerm`. var termDraft: String? diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift index 37f2fda6..5061611c 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift @@ -123,7 +123,7 @@ struct MicKey: View { let level = CGFloat(model.snapshot.level) let width = isRecording ? expandedWidth : size ZStack { - PrismOrb(mood: mood, animated: !reduceMotion) + PrismOrb(mood: mood, landedAt: model.resultLandedAt, animated: !reduceMotion) .clipShape(Capsule()) .overlay { ring } .saturation(isReady ? 1 : 0.35) @@ -224,15 +224,15 @@ struct MicKey: View { private var isReady: Bool { model.isReady } - /// The orb's story from the phase: green going in, violet coming out. + /// The orb's story from the phase: green, greener with the voice; the + /// violet drop is keyed to the moment the words landed, not to a phase. private var mood: PrismOrb.Mood { guard isReady else { return .off } switch model.snapshot.state { - case .idle, .error: return .idle + case .idle, .error, .pasted, .copied: return .idle case .connecting: return .listening(level: 0) case .recording: return .listening(level: Float(model.snapshot.level)) case .processing: return .working - case .pasted, .copied: return .done } } private var isRecording: Bool { isReady && model.snapshot.state == .recording } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/PrismOrb.swift b/App/BlurtiOS/BlurtKeyboard/Sources/PrismOrb.swift index 5486e148..e82dd2df 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/PrismOrb.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/PrismOrb.swift @@ -3,55 +3,76 @@ import SwiftUI /// The brand's artwork in motion. In the illustration a green beam goes into /// the prism and a violet, starlit one comes out: green is the input, the -/// voice; violet is the magic, the words. The orb tells that story as it -/// works — leaning green and swelling with the voice while you talk, turning -/// violet while the words are made, finishing violet with a scatter of -/// sparkles when they land. Liquid in its motion (a mesh gradient whose -/// points drift, more with the voice), airy in its look (soft light, low -/// contrast), and matte under film grain, as the artwork is. +/// voice; violet is the magic, the words. The orb lives green — calm at rest, +/// swelling with the voice while you talk — and the moment the words land in +/// the field a violet drop falls into it: a glittering pulse that blooms from +/// the centre with the haptic, then flows back out into the green. Liquid in +/// its motion (a mesh gradient whose points drift), airy in its look (soft +/// light, low contrast), matte under film grain, as the artwork is. /// /// A fill: the caller clips it to a circle or a capsule and puts the ring on -/// top. Under Reduce Motion the fluid holds still and the grain is fixed. +/// top. Under Reduce Motion the fluid holds still and the drop simply fades. struct PrismOrb: View { enum Mood: Equatable { - /// Blurt is not ready: the brand mix, dimmed by the caller. + /// Blurt is not ready: the calm green, dimmed by the caller. case off - /// Resting: the brand mix, breathing. + /// Resting: the calm green, breathing. case idle - /// The voice going in: green, moving with the level (0…1). + /// The voice going in: greener and moving with the level (0…1). case listening(level: Float) - /// The words being made: violet, working. + /// The words being made: the calm green, working. case working - /// The words landed: violet and light, with sparkles. - case done } var mood: Mood + /// When the words landed — the drop falls then and is gone 1.6 s later. + var landedAt: Date? var animated: Bool + /// The drop's life: up in 0.35 s, held to 0.6 s, gone by 1.6 s. + static let dropDuration: TimeInterval = 1.6 + var body: some View { TimelineView(.animation(minimumInterval: keyboardAnimationInterval, paused: !animated)) { timeline in let time = animated ? timeline.date.timeIntervalSinceReferenceDate : 0 + let elapsed = landedAt.map { timeline.date.timeIntervalSince($0) } ?? .infinity + let drop = Self.dropAmount(at: elapsed) ZStack { - Rectangle().fill(mesh(at: time)) + Rectangle().fill(mesh(at: time, drop: drop)) // A soft light from the upper left, so the disc reads as a body, not // a flat swatch — airy, not glossy. Rectangle().fill( RadialGradient( - colors: [.white.opacity(0.32), .clear], center: UnitPoint(x: 0.3, y: 0.22), startRadius: 0, + colors: [.white.opacity(0.3), .clear], center: UnitPoint(x: 0.3, y: 0.22), startRadius: 0, endRadius: 110)) + if drop > 0 { + Drop(amount: drop, elapsed: elapsed) + Sparkles(elapsed: elapsed) + } Grain(seed: animated ? Int(time * 24) : 7).opacity(0.5).blendMode(.overlay) - if case .done = mood { Sparkles(time: time) } } } - .animation(.easeInOut(duration: 0.7), value: mood) + .animation(.easeInOut(duration: 0.6), value: mood) + } + + /// How much violet is in the orb `elapsed` seconds after the words landed: + /// a quick bloom, a moment held, a slow flow back to green. + static func dropAmount(at elapsed: TimeInterval) -> Double { + guard elapsed >= 0, elapsed < dropDuration else { return 0 } + func smooth(_ x: Double) -> Double { + let t = min(max(x, 0), 1) + return t * t * (3 - 2 * t) + } + if elapsed < 0.35 { return smooth(elapsed / 0.35) } + if elapsed < 0.6 { return 1 } + return 1 - smooth((elapsed - 0.6) / (dropDuration - 0.6)) } // MARK: The fluid /// A 3 × 3 mesh. The corners stay put; the edge midpoints and the centre /// drift on slow sines, further with the voice. - private func mesh(at time: TimeInterval) -> MeshGradient { + private func mesh(at time: TimeInterval, drop: Double) -> MeshGradient { let level = CGFloat(self.level) let sway = 0.10 + 0.16 * level func drift(_ base: Float, _ phase: Double, _ speed: Double) -> Float { @@ -62,6 +83,11 @@ struct PrismOrb: View { [0, drift(0.5, 1.7, 0.7)], [drift(0.5, 3.1, 1.1), drift(0.5, 0.6, 0.8)], [1, drift(0.5, 4.2, 0.6)], [0, 1], [drift(0.5, 2.3, 1.0), 1], [1, 1], ] + // The drop soaks the centre first and the corners least. + let soak: [Double] = [0.45, 0.75, 0.45, 0.75, 1, 0.75, 0.45, 0.75, 0.45] + let colors = zip(green, soak).map { base, weight in + base.mix(with: Palette.violet, by: drop * weight) + } return MeshGradient(width: 3, height: 3, points: points, colors: colors) } @@ -70,48 +96,55 @@ struct PrismOrb: View { return 0 } - /// Row-major, top to bottom. The brand gradient's own stops - /// (`BlurtBrand.orbGradient`), dealt differently per mood. - private var colors: [Color] { + /// Row-major, top to bottom: the green the orb lives in, with the brand's + /// pale lavender as the light on top so it stays airy. + private var green: [Color] { switch mood { - case .off, .idle: + case .off, .idle, .working: return [ - Palette.white, Palette.lavender, Palette.periwinkle, - Palette.periwinkle, Palette.greenLight, Palette.violet, - Palette.green, Palette.greenLight, Palette.violet, + Palette.lavender, Palette.mist, Palette.lavender, + Palette.greenLight, Palette.greenLight, Palette.greenLight, + Palette.green, Palette.greenLight, Palette.green, ] case .listening(let level): - // More green the louder: the beam going in. - let bright = Color( - red: 0.40 + 0.3 * Double(level), green: 0.68 + 0.25 * Double(level), blue: 0.51 + 0.1 * Double(level)) + // Greener and brighter the louder: the beam going in. + let bright = Palette.greenLight.mix(with: Palette.mist, by: 0.25 + 0.45 * Double(level)) return [ - Palette.lavender, Palette.greenLight, Palette.lavender, + Palette.mist, bright, Palette.mist, Palette.greenLight, bright, Palette.greenLight, Palette.green, Palette.greenLight, Palette.green, ] - case .working: - return [ - Palette.lavender, Palette.periwinkle, Palette.lavender, - Palette.periwinkle, Palette.violet, Palette.periwinkle, - Palette.violet, Palette.periwinkle, Palette.violet, - ] - case .done: - return [ - Palette.white, Palette.lavender, Palette.white, - Palette.lavender, Palette.periwinkle, Palette.lavender, - Palette.violet, Palette.periwinkle, Palette.violet, - ] } } private enum Palette { - static let white = Color(red: 0.97, green: 0.96, blue: 1) + static let mist = Color(red: 0.86, green: 0.96, blue: 0.9) static let lavender = Color(red: 215 / 255, green: 211 / 255, blue: 244 / 255) static let periwinkle = Color(red: 176 / 255, green: 167 / 255, blue: 233 / 255) static let violet = Color(red: 57 / 255, green: 35 / 255, blue: 199 / 255) static let green = BlurtBrand.green static let greenLight = BlurtBrand.greenOnDark } + + /// The drop itself: a violet bloom that grows from the centre and thins as + /// it spreads, so the colour reads as poured in rather than switched. + private struct Drop: View { + let amount: Double + let elapsed: TimeInterval + + var body: some View { + let spread = min(1, elapsed / 0.7) + Circle() + .fill( + RadialGradient( + colors: [Palette.violet.opacity(0.9), Palette.periwinkle.opacity(0.55), .clear], + center: .center, startRadius: 0, endRadius: 90) + ) + .scaleEffect(0.15 + 1.6 * spread) + .opacity(amount * (1 - 0.5 * spread)) + .blendMode(.plusLighter) + } + } } /// Film grain: a scatter of faint dots, a new scatter each frame so it @@ -139,25 +172,27 @@ private struct Grain: View { } } -/// The artwork's stars: a handful of four-point sparkles that twinkle round -/// the orb while the words are landing. +/// The artwork's stars: six four-point sparkles that burst once with the +/// drop — each a beat after the last — and are gone with it. private struct Sparkles: View { - let time: TimeInterval + let elapsed: TimeInterval - private static let spots: [(x: CGFloat, y: CGFloat, size: CGFloat, phase: Double)] = [ - (0.18, 0.28, 0.16, 0.0), (0.76, 0.2, 0.11, 1.3), (0.82, 0.62, 0.14, 2.6), (0.3, 0.74, 0.1, 3.7), - (0.58, 0.44, 0.08, 4.9), (0.5, 0.86, 0.12, 1.9), + private static let spots: [(x: CGFloat, y: CGFloat, size: CGFloat, delay: Double)] = [ + (0.5, 0.5, 0.14, 0.05), (0.24, 0.3, 0.16, 0.15), (0.76, 0.22, 0.11, 0.25), (0.8, 0.64, 0.14, 0.32), + (0.3, 0.74, 0.1, 0.4), (0.56, 0.84, 0.12, 0.48), ] var body: some View { GeometryReader { geo in ForEach(Array(Self.spots.enumerated()), id: \.offset) { _, spot in - let pulse = max(0, sin(time * 2.4 + spot.phase)) + let life = (elapsed - spot.delay) / 0.9 + let up = min(max(life, 0), 1) + let shine = up < 0.3 ? up / 0.3 : max(0, 1 - (up - 0.3) / 0.7) Image(systemName: "sparkle") .font(.system(size: min(geo.size.width, geo.size.height) * spot.size, weight: .regular)) .foregroundStyle(.white) - .opacity(0.35 + 0.65 * pulse) - .scaleEffect(0.7 + 0.5 * pulse) + .opacity(shine) + .scaleEffect(0.4 + 0.9 * shine) .position(x: geo.size.width * spot.x, y: geo.size.height * spot.y) } } diff --git a/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift b/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift index 5e24b03f..046bf527 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift @@ -15,6 +15,8 @@ struct HomeView: View { @State private var keyboardSeen = SharedStore.keyboardEverSeen @State private var showsKeyEntry = false @State private var showsSettings = false + /// When the last dictation's words landed — the hero's drop. + @State private var landedAt: Date? @AppStorage(StyleProfileStore.defaultsKey) private var profilesRaw = "" @AppStorage(StyleProfileStore.activeDefaultsKey) private var activeRaw = "" private let styles = StyleProfileStore() @@ -66,6 +68,12 @@ struct HomeView: View { .onChange(of: scenePhase) { _, phase in if phase == .active { refreshStatus() } } + .onChange(of: coordinator.phase) { _, phase in + switch phase.overlayState { + case .pasted, .noTarget: landedAt = Date() + default: break + } + } } .tint(BlurtBrand.accent) } @@ -85,7 +93,7 @@ struct HomeView: View { private var hero: some View { VStack(spacing: 18) { - PrismOrb(mood: heroMood, animated: !reduceMotion) + PrismOrb(mood: heroMood, landedAt: landedAt, animated: !reduceMotion) .frame(width: Self.orbSize, height: Self.orbSize) .clipShape(Circle()) .overlay { HeroRing(animated: orbWorking && !reduceMotion) } @@ -147,11 +155,10 @@ struct HomeView: View { private var heroMood: PrismOrb.Mood { guard coordinator.window.isOpen else { return .off } switch coordinator.phase.overlayState { - case .idle, .error: return .idle + case .idle, .error, .pasted, .noTarget: return .idle case .connecting: return .listening(level: 0) case .recording: return .listening(level: coordinator.level) case .processing: return .working - case .pasted, .noTarget: return .done } } diff --git a/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift b/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift index ad088ef0..fdc955a3 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift @@ -67,6 +67,9 @@ // `term` the voice bar as the key-term field, mid-typing. model.panelShowsKeys = state == "keys" if state == "term" { model.termDraft = "Rizz" } + // `landed`: the words go in 2.6 s after launch, so a screenshot taken 3 s + // in (scripts/ios-sim.sh) catches the drop at its fullest. + if state == "landed" { model.resultLandedAt = Date().addingTimeInterval(2.6) } model.hasFullAccess = state != "off" model.isListening = state != "off" && state != "start" let phase: PhaseSnapshot.State = diff --git a/App/BlurtiOS/DESIGN.md b/App/BlurtiOS/DESIGN.md index 723b4cfe..2fc3ecc4 100644 --- a/App/BlurtiOS/DESIGN.md +++ b/App/BlurtiOS/DESIGN.md @@ -37,14 +37,18 @@ the keyboard's sources are compiled into the app for it (`project.yml`). The brand artwork — a green beam into the prism, a violet, starlit one out — as the orb's own story. The mic key and the home hero are filled by a 3 × 3 `MeshGradient` whose edge and centre points drift on slow sines (further -with the voice level), under a soft upper-left light, animated film grain (a -seeded scatter of faint dots, new each frame at 20 Hz) and, when the words -land, six four-point sparkles twinkling. Moods: `off` and `idle` (the brand -mix), `listening(level:)` (green, brighter with the voice), `working` -(violet), `done` (violet and light, sparkles). Mood changes cross-fade over -0.7 s. Under Reduce Motion everything holds still. The ring stays the Mac -orb's. Not merged: judge it on the simulator (`-BlurtGallery panel -idle,recording,processing,pasted`, `-BlurtStartListening` for the hero). +with the voice level), under a soft upper-left light and animated film grain +(a seeded scatter of faint dots, new each frame at 20 Hz). The orb lives +**green**: calm at rest (`idle`, `working`, `off`), greener and brighter with +the voice (`listening(level:)`). The moment the words land in the field — +`resultLandedAt` on the keyboard, the phase reaching pasted or copied on the +home screen — a **violet drop** falls in: a bloom that grows from the centre +(the mesh soaks violet centre-first, corners least), six four-point sparkles +bursting a beat apart, up in 0.35 s, held to 0.6 s, flowing back out into the +green by 1.6 s. It lands with the success haptic. Under Reduce Motion the +fluid holds still and the drop simply fades. The ring stays the Mac orb's. +Not merged: judge it on the simulator (`-BlurtGallery panel +idle,recording,landed`; `-BlurtStartListening` for the hero). ## Themes, at the iPhone's spacing (`BlurtKeyboard/Sources/KeyboardPalette.swift`) From d4e581b8f48e18beb2cf532d1c5358ac176d7dae Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Fri, 25 Sep 2026 19:34:16 -0400 Subject: [PATCH 42/79] Keyboard: the iPhone's own look is the default theme, light or dark with the app A violet slab sitting on Apple's grey globe-and-mic bar read as two keyboards. The default is now the iPhone keyboard's own palette, following the field's keyboardAppearance or the app's style, so Blurt's keys and Apple's bar are one keyboard and the brand lives in the orb. Ink and the five colour themes stay as choices; the picker shows the iPhone theme in its own appearance; the gallery takes system / system-dark. The dark palettes keep their faint key edge, the light ones don't need it. Co-Authored-By: Claude Fable 5.1 --- .../BlurtKeyboard/Sources/KeyboardModel.swift | 18 +++- .../Sources/KeyboardPalette.swift | 55 +++++++++---- .../BlurtKeyboard/Sources/KeyboardViews.swift | 7 +- App/BlurtiOS/BlurtiOS/Sources/HomeView.swift | 82 ++++++++++--------- .../Sources/KeyboardGalleryView.swift | 10 ++- .../BlurtiOS/Sources/SettingsView.swift | 3 +- .../BlurtiOS/Sources/ThemePickerView.swift | 8 +- .../BlurtiOSTests/FeedAndLayoutTests.swift | 2 + .../BlurtiOSTests/SharedStateTests.swift | 8 +- App/BlurtiOS/DESIGN.md | 49 ++++++----- App/BlurtiOS/Shared/SharedState.swift | 5 +- 11 files changed, 157 insertions(+), 90 deletions(-) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift index 04f99555..2c8aa63f 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift @@ -83,10 +83,14 @@ final class KeyboardModel { var proxy: (any UITextDocumentProxy)? { proxyOverride ?? controller?.textDocumentProxy } @ObservationIgnored var proxyOverride: (any UITextDocumentProxy)? - /// The chosen theme's palette — or, for a preview, whatever it is told. - var palette: KeyboardPalette { paletteOverride ?? .named(themeID) } + /// The chosen theme's palette in the host's appearance — or, for a + /// preview, whatever it is told. + var palette: KeyboardPalette { paletteOverride ?? .resolve(themeID, dark: isDark) } var themeID = SharedStore.themeID var paletteOverride: KeyboardPalette? + /// Whether the app being typed in wants a dark keyboard: what its field + /// asks for, else the app's own light or dark appearance. + var isDark = false /// What is actually on screen: the panel's carousel may be showing its /// keys, and typing a key term needs them whatever the layout. @@ -142,6 +146,7 @@ final class KeyboardModel { termHostBaseline = nil termHostBaselineAfter = nil symbolsPage = Self.wantsSymbols(proxy?.keyboardType) + readAppearance() readField() updateShift() // Without Full Access the App Group is out of reach: the keyboard still @@ -197,6 +202,7 @@ final class KeyboardModel { /// The cursor moved or the text around it changed, including by our own /// typing: re-read where the sentence stands and what the field wants. func contextChanged() { + readAppearance() readField() claimHostTypingForTerm() updateShift() @@ -228,6 +234,14 @@ final class KeyboardModel { returnLabel = proxy?.returnKeyType.flatMap(Self.returnLabel) } + private func readAppearance() { + switch proxy?.keyboardAppearance { + case .dark: isDark = true + case .light: isDark = false + default: isDark = controller?.traitCollection.userInterfaceStyle == .dark + } + } + /// Number, decimal and phone fields open on the symbols page, as the system /// keyboard would show a number pad. static func wantsSymbols(_ type: UIKeyboardType?) -> Bool { diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift index dde190f4..daaa3101 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift @@ -1,10 +1,12 @@ import SwiftUI -/// The colors the keys draw with — a theme. Six of them, curated: Blurt's -/// ink, and five more cut from the same cloth (the orb's lavender and green, -/// a warm paper, a midnight, a sunset), each contemporary and fun and none of -/// them off-brand. People pick one in the app, Partiful-style, from live -/// previews; the spacing never changes (the iPhone keyboard's own — 6 pt +/// The colors the keys draw with — a theme. The default is the iPhone +/// keyboard's own, light or dark with the app being typed in, so Blurt's keys +/// sit on Apple's globe-and-mic bar as one keyboard and the brand lives in the +/// orb. Then Blurt's ink and five more cut from the same cloth (the orb's +/// lavender and green, a warm paper, a midnight, a sunset), each contemporary +/// and fun and none off-brand, picked in the app Partiful-style from live +/// previews. The spacing never changes (the iPhone keyboard's own — 6 pt /// between keys, 11 between rows, 3 at the edges, 5 pt corners, a 1 pt drop /// under every key), so a theme changes how the keyboard looks and never how /// it types. @@ -20,47 +22,68 @@ struct KeyboardPalette: Equatable, Identifiable { /// The drop under each key, as the system keyboard draws it. let keyShadow: Color let popupFill: Color + /// A faint light edge on each key — what lifts a key off a dark surface; + /// the light palettes have their drop for that and no edge. + let keyEdge: Bool static let keyGap: CGFloat = 6 static let rowGap: CGFloat = 11 static let margin: CGFloat = 3 static let keyRadius: CGFloat = 5 + /// The iPhone's light keyboard: `#D1D5DB` surface, white keys, `#ADB3BC` + /// modifiers, a `#898A8D` drop, black legends. + static let systemLight = KeyboardPalette( + id: "system", name: "iPhone", vibe: "Matches the iPhone keyboard, light or dark with the app you're in", + surface: Color(hex: 0xD1D5DB), key: .white, keyDark: Color(hex: 0xADB3BC), keyText: .black, + keyShadow: Color(hex: 0x898A8D), popupFill: .white, keyEdge: false) + + /// The iPhone's dark keyboard: `#2B2B2B` surface, `#6B6B6B` keys, `#464646` + /// modifiers, a near-black drop, white legends. + static let systemDark = KeyboardPalette( + id: "system", name: "iPhone", vibe: "Matches the iPhone keyboard, light or dark with the app you're in", + surface: Color(hex: 0x2B2B2B), key: Color(hex: 0x6B6B6B), keyDark: Color(hex: 0x464646), keyText: .white, + keyShadow: Color(hex: 0x0D0D0D), popupFill: Color(hex: 0x6B6B6B), keyEdge: false) + static let ink = KeyboardPalette( id: "ink", name: "Ink", vibe: "Blurt's own", surface: BlurtBrand.ink, key: BlurtBrand.key, keyDark: BlurtBrand.keyDark, keyText: BlurtBrand.keyText, - keyShadow: Color.black.opacity(0.45), popupFill: BlurtBrand.key) + keyShadow: Color.black.opacity(0.45), popupFill: BlurtBrand.key, keyEdge: true) static let paper = KeyboardPalette( id: "paper", name: "Paper", vibe: "Warm and light", surface: Color(hex: 0xEBE8E8), key: .white, keyDark: Color(hex: 0xDEDBDB), keyText: BlurtBrand.ink, - keyShadow: Color.black.opacity(0.18), popupFill: .white) + keyShadow: Color.black.opacity(0.18), popupFill: .white, keyEdge: true) static let lavender = KeyboardPalette( id: "lavender", name: "Lavender", vibe: "The orb's violet", surface: Color(hex: 0x2C2557), key: Color(hex: 0x3F3777), keyDark: Color(hex: 0x352E68), - keyText: Color(hex: 0xF1EEFF), keyShadow: Color.black.opacity(0.4), popupFill: Color(hex: 0x3F3777)) + keyText: Color(hex: 0xF1EEFF), keyShadow: Color.black.opacity(0.4), popupFill: Color(hex: 0x3F3777), keyEdge: true) static let mint = KeyboardPalette( id: "mint", name: "Mint", vibe: "The orb's green", surface: Color(hex: 0x10231B), key: Color(hex: 0x1E3F31), keyDark: Color(hex: 0x183429), - keyText: Color(hex: 0xE9F5EE), keyShadow: Color.black.opacity(0.4), popupFill: Color(hex: 0x1E3F31)) + keyText: Color(hex: 0xE9F5EE), keyShadow: Color.black.opacity(0.4), popupFill: Color(hex: 0x1E3F31), keyEdge: true) static let midnight = KeyboardPalette( id: "midnight", name: "Midnight", vibe: "Deep blue-black", surface: Color(hex: 0x0E1220), key: Color(hex: 0x1D2440), keyDark: Color(hex: 0x161B33), - keyText: Color(hex: 0xE8ECFF), keyShadow: Color.black.opacity(0.5), popupFill: Color(hex: 0x1D2440)) + keyText: Color(hex: 0xE8ECFF), keyShadow: Color.black.opacity(0.5), popupFill: Color(hex: 0x1D2440), keyEdge: true) static let sunset = KeyboardPalette( id: "sunset", name: "Sunset", vibe: "Warm and loud", surface: Color(hex: 0x2B1912), key: Color(hex: 0x4B2B20), keyDark: Color(hex: 0x3B2119), - keyText: Color(hex: 0xFFEFE6), keyShadow: Color.black.opacity(0.4), popupFill: Color(hex: 0x4B2B20)) + keyText: Color(hex: 0xFFEFE6), keyShadow: Color.black.opacity(0.4), popupFill: Color(hex: 0x4B2B20), keyEdge: true) - static let all: [KeyboardPalette] = [ink, paper, lavender, mint, midnight, sunset] + /// The picker's order: the iPhone's own first (shown in the picker's own + /// appearance), then Blurt's. + static let all: [KeyboardPalette] = [systemLight, ink, paper, lavender, mint, midnight, sunset] - /// The theme with this id, or Ink for one that no longer exists. - static func named(_ id: String) -> KeyboardPalette { - all.first { $0.id == id } ?? ink + /// The theme with this id in the given appearance — only the iPhone theme + /// has two faces — or the iPhone's for an id that no longer exists. + static func resolve(_ id: String, dark: Bool) -> KeyboardPalette { + if id == systemLight.id { return dark ? systemDark : systemLight } + return all.first { $0.id == id } ?? (dark ? systemDark : systemLight) } static func == (lhs: KeyboardPalette, rhs: KeyboardPalette) -> Bool { lhs.id == rhs.id } @@ -75,7 +98,7 @@ extension Color { } private struct KeyboardPaletteKey: EnvironmentKey { - static let defaultValue = KeyboardPalette.ink + static let defaultValue = KeyboardPalette.systemLight } extension EnvironmentValues { diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift index 0d5395be..0601b0c1 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift @@ -343,7 +343,8 @@ struct KeyPress: ViewModifier { extension View { /// The cap under a key's legend: the palette's fill, the system keyboard's - /// corner radius and 1 pt drop, and a hairline so the cap reads on ink. + /// corner radius and 1 pt drop, and on the dark palettes a hairline so the + /// cap reads on ink. func keyCap(_ fill: Color, palette: KeyboardPalette) -> some View { background { RoundedRectangle(cornerRadius: KeyboardPalette.keyRadius) @@ -351,7 +352,9 @@ extension View { .shadow(color: palette.keyShadow, radius: 0, y: 1) } .overlay { - RoundedRectangle(cornerRadius: KeyboardPalette.keyRadius).strokeBorder(Color.white.opacity(0.06), lineWidth: 1) + if palette.keyEdge { + RoundedRectangle(cornerRadius: KeyboardPalette.keyRadius).strokeBorder(Color.white.opacity(0.06), lineWidth: 1) + } } } } diff --git a/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift b/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift index dc868c4c..03570b6b 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift @@ -188,44 +188,7 @@ struct HomeView: View { } } - // MARK: - Recent - - private var recent: some View { - VStack(alignment: .leading, spacing: 10) { - Text("Recent").font(.headline) - if coordinator.recent.displayed.isEmpty { - Text("Your recent blurts will appear here.") - .font(.callout).foregroundStyle(.secondary) - .frame(maxWidth: .infinity, alignment: .leading) - .padding(16) - .card() - } - ForEach(coordinator.recent.displayed) { entry in - VStack(alignment: .leading, spacing: 8) { - Text(entry.text).font(.body).lineLimit(3) - HStack(spacing: 8) { - if let style = entry.style { - Text(style) - .font(.caption.weight(.medium)) - .padding(.horizontal, 8).padding(.vertical, 3) - .background(Capsule().fill(BlurtBrand.accent.opacity(0.15))) - } - Text(entry.relativeLabel(now: Date())).font(.caption).foregroundStyle(.secondary) - Spacer() - Button { - UIPasteboard.general.string = entry.text - } label: { - Image(systemName: "doc.on.doc") - } - .buttonStyle(.borderless) - .accessibilityLabel("Copy") - } - } - .padding(16) - .card() - } - } - } + private var recent: some View { RecentSection(coordinator: coordinator) } private var poweredBy: some View { HStack(spacing: 3) { @@ -324,3 +287,46 @@ private struct SetupRow: View { } } } + +/// The recent dictations as cards, with a copy button each. +private struct RecentSection: View { + var coordinator: DictationCoordinator + + var body: some View { + VStack(alignment: .leading, spacing: 10) { + Text("Recent").font(.headline) + if coordinator.recent.displayed.isEmpty { + Text("Your recent blurts will appear here.") + .font(.callout).foregroundStyle(.secondary) + .frame(maxWidth: .infinity, alignment: .leading) + .padding(16) + .card() + } + ForEach(coordinator.recent.displayed) { entry in + VStack(alignment: .leading, spacing: 8) { + Text(entry.text).font(.body).lineLimit(3) + HStack(spacing: 8) { + if let style = entry.style { + Text(style) + .font(.caption.weight(.medium)) + .padding(.horizontal, 8).padding(.vertical, 3) + .background(Capsule().fill(BlurtBrand.accent.opacity(0.15))) + } + Text(entry.relativeLabel(now: Date())).font(.caption).foregroundStyle(.secondary) + Spacer() + Button { + UIPasteboard.general.string = entry.text + } label: { + Image(systemName: "doc.on.doc") + } + .buttonStyle(.borderless) + .accessibilityLabel("Copy") + } + } + .padding(16) + .card() + } + } + } + +} diff --git a/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift b/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift index ad088ef0..533129b5 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift @@ -7,8 +7,9 @@ /// /// -BlurtGallery [,…] [theme] /// - /// The last word is a theme id (`ink`, `paper`, `lavender`, `mint`, - /// `midnight`, `sunset`); Ink when left out. + /// The last word is a theme id (`system`, `system-dark`, `ink`, `paper`, + /// `lavender`, `mint`, `midnight`, `sunset`); the iPhone's light face when + /// left out. /// where a state is `off` (no Full Access), `start` (app not listening), /// `idle`, `connecting`, `recording`, `processing`, `pasted`, `copied` or /// `error`. `scripts/ios-sim.sh` passes `BLURT_LAUNCH_ARGS` through, so @@ -51,7 +52,7 @@ guard let flag = arguments.firstIndex(of: "-BlurtGallery"), arguments.count > flag + 2, let layout = KeyboardLayout(rawValue: arguments[flag + 1]) else { return [] } - let theme = arguments.count > flag + 3 ? arguments[flag + 3] : "ink" + let theme = arguments.count > flag + 3 ? arguments[flag + 3] : "system" return arguments[flag + 2].split(separator: ",").map { name in Row( caption: "\(layout.rawValue) · \(name) · \(theme)", @@ -62,7 +63,8 @@ private static func model(layout: KeyboardLayout, state: String, theme: String) -> KeyboardModel { let model = KeyboardModel() model.layout = layout - model.paletteOverride = .named(theme) + // `system` is the iPhone's light face, `system-dark` its dark one. + model.paletteOverride = .resolve(theme == "system-dark" ? "system" : theme, dark: theme == "system-dark") // `keys` shows the panel's carousel flipped to its keyboard page; // `term` the voice bar as the key-term field, mid-typing. model.panelShowsKeys = state == "keys" diff --git a/App/BlurtiOS/BlurtiOS/Sources/SettingsView.swift b/App/BlurtiOS/BlurtiOS/Sources/SettingsView.swift index 9f6795e4..123740b5 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/SettingsView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/SettingsView.swift @@ -10,6 +10,7 @@ struct SettingsView: View { @State private var layout = SharedStore.layout @State private var autoDictate = SharedStore.autoDictate @State private var windowMinutes = SharedStore.windowMinutes + @AppStorage(BlurtShared.Key.theme, store: SharedStore.defaults) private var themeID = "system" @State private var showsKeyEntry = false @AppStorage(SharedStore.keyTermsKey, store: SharedStore.defaults) private var keyTerms = "" @AppStorage(EnhancedTranscriptsStore.defaultsKey) private var enhancedTranscripts = @@ -45,7 +46,7 @@ struct SettingsView: View { NavigationLink { ThemePickerView() } label: { - LabeledContent("Theme", value: KeyboardPalette.named(SharedStore.themeID).name) + LabeledContent("Theme", value: KeyboardPalette.resolve(themeID, dark: false).name) } Toggle("Hands-free", isOn: $autoDictate) .onChange(of: autoDictate) { _, value in SharedStore.autoDictate = value } diff --git a/App/BlurtiOS/BlurtiOS/Sources/ThemePickerView.swift b/App/BlurtiOS/BlurtiOS/Sources/ThemePickerView.swift index 7019c2fb..ea7495eb 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/ThemePickerView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/ThemePickerView.swift @@ -5,6 +5,7 @@ import SwiftUI /// in the accent. The keyboard picks it up the next time it comes up. struct ThemePickerView: View { @State private var chosen = SharedStore.themeID + @Environment(\.colorScheme) private var colorScheme private let columns = [GridItem(.flexible(), spacing: 14), GridItem(.flexible(), spacing: 14)] @@ -12,7 +13,12 @@ struct ThemePickerView: View { ScrollView { LazyVGrid(columns: columns, spacing: 14) { ForEach(KeyboardPalette.all) { palette in - ThemeCard(palette: palette, chosen: palette.id == chosen) { + // The iPhone theme has two faces; the card shows the one this + // screen is in, which is the one the keyboard would show in an app + // that looks like it. + ThemeCard( + palette: KeyboardPalette.resolve(palette.id, dark: colorScheme == .dark), chosen: palette.id == chosen + ) { chosen = palette.id SharedStore.themeID = palette.id } diff --git a/App/BlurtiOS/BlurtiOSTests/FeedAndLayoutTests.swift b/App/BlurtiOS/BlurtiOSTests/FeedAndLayoutTests.swift index 6bb5c172..e88d492d 100644 --- a/App/BlurtiOS/BlurtiOSTests/FeedAndLayoutTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/FeedAndLayoutTests.swift @@ -55,5 +55,7 @@ struct LayoutArithmeticTests { #expect(rows[1].model.effectiveLayout == .full) #expect(rows[2].model.termDraft == "Rizz") #expect(rows[0].model.palette.id == "mint") + let dark = KeyboardGalleryView.rows(from: ["app", "-BlurtGallery", "full", "idle", "system-dark"]) + #expect(dark[0].model.palette.keyText == .white) } } diff --git a/App/BlurtiOS/BlurtiOSTests/SharedStateTests.swift b/App/BlurtiOS/BlurtiOSTests/SharedStateTests.swift index 36feaa35..ebc26d44 100644 --- a/App/BlurtiOS/BlurtiOSTests/SharedStateTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/SharedStateTests.swift @@ -77,11 +77,13 @@ struct LayoutTests { #expect(LetterLayout.forPreferredLanguages([]) == LetterLayout.qwerty) } - @Test("every theme has a distinct id and an unknown id falls back to Ink") + @Test("every theme has a distinct id; the iPhone theme has two faces; an unknown id is the iPhone's") func palettes() { let ids = KeyboardPalette.all.map(\.id) #expect(Set(ids).count == ids.count) - #expect(KeyboardPalette.named("lavender").id == "lavender") - #expect(KeyboardPalette.named("nope").id == "ink") + #expect(KeyboardPalette.resolve("lavender", dark: true).id == "lavender") + #expect(KeyboardPalette.resolve("system", dark: false).keyText == .black) + #expect(KeyboardPalette.resolve("system", dark: true).keyText == .white) + #expect(KeyboardPalette.resolve("nope", dark: false).id == "system") } } diff --git a/App/BlurtiOS/DESIGN.md b/App/BlurtiOS/DESIGN.md index 41ed16d7..f87abf9f 100644 --- a/App/BlurtiOS/DESIGN.md +++ b/App/BlurtiOS/DESIGN.md @@ -37,22 +37,29 @@ the keyboard's sources are compiled into the app for it (`project.yml`). The keys sit exactly where the iPhone keyboard's do, so nobody's fingers are thrown off: 6 pt between keys, 11 pt between rows, 3 pt at the edges, 5 pt corners, a 1 pt drop under every key. A theme changes how the keyboard looks -and never how it types. Six, curated, Partiful-style — pick from live -previews in Settings → Keyboard → Theme; the keyboard picks it up the next -time it comes up (`keyboardTheme` in the App Group): - -| Theme | Surface | Key | Modifier | Legend | Vibe | -| ---------- | --------- | --------- | --------- | --------- | ---------------- | -| `ink` | `#1D1B16` | `#33302A` | `#26231E` | `#F2EEE6` | Blurt's own | -| `paper` | `#EBE8E8` | white | `#DEDBDB` | `#1D1B16` | warm and light | -| `lavender` | `#2C2557` | `#3F3777` | `#352E68` | `#F1EEFF` | the orb's violet | -| `mint` | `#10231B` | `#1E3F31` | `#183429` | `#E9F5EE` | the orb's green | -| `midnight` | `#0E1220` | `#1D2440` | `#161B33` | `#E8ECFF` | deep blue-black | -| `sunset` | `#2B1912` | `#4B2B20` | `#3B2119` | `#FFEFE6` | warm and loud | - -The orb, the wave and the ring are the same in every theme. The picker -(`ThemePickerView`) draws the real full keyboard at 0.42 scale on each card. -The gallery's last argument is a theme id. +and never how it types. The **default is the iPhone keyboard's own** look, +light or dark with the app being typed in (its field's `keyboardAppearance`, +else the app's style), so Blurt's keys sit on Apple's globe-and-mic bar as +one keyboard and the brand lives in the orb. Six more, curated, +Partiful-style — pick from live previews in Settings → Keyboard → Theme; the +keyboard picks it up the next time it comes up (`keyboardTheme` in the App +Group): + +| Theme | Surface | Key | Modifier | Legend | Vibe | +| ---------- | --------------------- | ----------------- | --------------------- | ------------- | ------------------------------------------- | +| `system` | `#D1D5DB` / `#2B2B2B` | white / `#6B6B6B` | `#ADB3BC` / `#464646` | black / white | the iPhone keyboard, light / dark (default) | +| `ink` | `#1D1B16` | `#33302A` | `#26231E` | `#F2EEE6` | Blurt's own | +| `paper` | `#EBE8E8` | white | `#DEDBDB` | `#1D1B16` | warm and light | +| `lavender` | `#2C2557` | `#3F3777` | `#352E68` | `#F1EEFF` | the orb's violet | +| `mint` | `#10231B` | `#1E3F31` | `#183429` | `#E9F5EE` | the orb's green | +| `midnight` | `#0E1220` | `#1D2440` | `#161B33` | `#E8ECFF` | deep blue-black | +| `sunset` | `#2B1912` | `#4B2B20` | `#3B2119` | `#FFEFE6` | warm and loud | + +The orb, the wave and the ring are the same in every theme. The dark palettes +give each key a faint light edge; the light ones have their drop for that. +The picker (`ThemePickerView`) draws the real full keyboard at 0.42 scale on +each card, the iPhone theme in the picker's own appearance. The gallery's +last argument is a theme id (`system-dark` for the iPhone's dark face). The full layout follows the iPhone's geometry: ten letter keys across at one width (`(width − 9·gap) / 10`), the middle row centred, shift and delete @@ -145,11 +152,11 @@ nothing records on without it. | `orbGradient` | 8 stops | the design's own (`App elements/Recording.svg`), bottom→top | | `orbRingGradient` | green→white | the ring, top-leading to bottom-trailing | -The keyboard's surface is **fixed per theme**, whatever the host app's -appearance, for the reason the Mac pill is: it floats over whichever app the -user is typing in, so it cannot take a cue from that app, and it must read the -same over a white Notes page and a black Messages thread. Nothing on it uses -`accent`. +The default theme follows the host app's light or dark appearance, as the +iPhone keyboard does; Blurt's own themes are **fixed**, whatever the host +app's appearance, for the reason the Mac pill is: the keyboard floats over +whichever app the user is typing in and must read the same over a white Notes +page and a black Messages thread. Nothing on it uses `accent`. ## Type diff --git a/App/BlurtiOS/Shared/SharedState.swift b/App/BlurtiOS/Shared/SharedState.swift index a7e407a6..438752e8 100644 --- a/App/BlurtiOS/Shared/SharedState.swift +++ b/App/BlurtiOS/Shared/SharedState.swift @@ -225,9 +225,10 @@ nonisolated enum SharedStore { set { defaults.set(newValue.rawValue, forKey: BlurtShared.Key.layout) } } - /// Which keyboard theme (`KeyboardPalette.id`); Ink until one is picked. + /// Which keyboard theme (`KeyboardPalette.id`); the iPhone's own until one + /// is picked. static var themeID: String { - get { defaults.string(forKey: BlurtShared.Key.theme) ?? "ink" } + get { defaults.string(forKey: BlurtShared.Key.theme) ?? "system" } set { defaults.set(newValue, forKey: BlurtShared.Key.theme) } } From dcd6595c72c24e76f9a2f2982689ae445fd77567 Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Mon, 28 Sep 2026 20:35:19 -0400 Subject: [PATCH 43/79] =?UTF-8?q?Prototype:=20no=20pill=20=E2=80=94=20the?= =?UTF-8?q?=20wave=20passes=20through=20the=20orb;=20soft,=20slow=20fades?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The recording capsule is gone: the orb is a circle in every state, and while you talk the meter's wave fades in through it, flat on the surface with no container, gone at the orb's edge and whole a little way out, the orb's film grain over the bars so they are the same matte material. The stretch from circle to capsule read as a loading bar filling; nothing stretches now. The home hero draws the same wave; the level-driven glow is gone from both. Motion principle: the wave fades over 0.7 s, every other change on the key over 0.5 s, the term field over 0.4 s, and the violet drop rises in 0.5 s and flows back over 2.4 s. Nothing springs or snaps; only the press answers at once. Themes gain a `signal` colour so the wave reads on light surfaces. The gallery gains `live`: a whole dictation walked on a clock, over and over, for watching or recording the fades. Verified on the iOS 27 simulator across the three layouts on the light, dark, paper and ink themes; 43 tests pass. Co-Authored-By: Claude Fable 5.1 --- .../Sources/KeyboardPalette.swift | 23 ++-- .../BlurtKeyboard/Sources/KeyboardViews.swift | 71 +++++----- .../BlurtKeyboard/Sources/PrismOrb.swift | 38 ++++-- .../BlurtKeyboard/Sources/VoiceBar.swift | 56 ++++++-- App/BlurtiOS/BlurtiOS/Sources/HomeView.swift | 38 +++--- .../Sources/KeyboardGalleryView.swift | 44 +++++- App/BlurtiOS/DESIGN.md | 129 ++++++++++-------- 7 files changed, 263 insertions(+), 136 deletions(-) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift index daaa3101..bcd7a16d 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift @@ -19,6 +19,9 @@ struct KeyboardPalette: Equatable, Identifiable { let key: Color let keyDark: Color let keyText: Color + /// The voice on this surface: the wave while recording. The brand green + /// that reads on it — the wordmark's on light, the lifted one on dark. + let signal: Color /// The drop under each key, as the system keyboard draws it. let keyShadow: Color let popupFill: Color @@ -36,44 +39,48 @@ struct KeyboardPalette: Equatable, Identifiable { static let systemLight = KeyboardPalette( id: "system", name: "iPhone", vibe: "Matches the iPhone keyboard, light or dark with the app you're in", surface: Color(hex: 0xD1D5DB), key: .white, keyDark: Color(hex: 0xADB3BC), keyText: .black, - keyShadow: Color(hex: 0x898A8D), popupFill: .white, keyEdge: false) + signal: BlurtBrand.green, keyShadow: Color(hex: 0x898A8D), popupFill: .white, keyEdge: false) /// The iPhone's dark keyboard: `#2B2B2B` surface, `#6B6B6B` keys, `#464646` /// modifiers, a near-black drop, white legends. static let systemDark = KeyboardPalette( id: "system", name: "iPhone", vibe: "Matches the iPhone keyboard, light or dark with the app you're in", surface: Color(hex: 0x2B2B2B), key: Color(hex: 0x6B6B6B), keyDark: Color(hex: 0x464646), keyText: .white, - keyShadow: Color(hex: 0x0D0D0D), popupFill: Color(hex: 0x6B6B6B), keyEdge: false) + signal: BlurtBrand.greenOnDark, keyShadow: Color(hex: 0x0D0D0D), popupFill: Color(hex: 0x6B6B6B), keyEdge: false) static let ink = KeyboardPalette( id: "ink", name: "Ink", vibe: "Blurt's own", surface: BlurtBrand.ink, key: BlurtBrand.key, keyDark: BlurtBrand.keyDark, keyText: BlurtBrand.keyText, - keyShadow: Color.black.opacity(0.45), popupFill: BlurtBrand.key, keyEdge: true) + signal: BlurtBrand.greenOnDark, keyShadow: Color.black.opacity(0.45), popupFill: BlurtBrand.key, keyEdge: true) static let paper = KeyboardPalette( id: "paper", name: "Paper", vibe: "Warm and light", surface: Color(hex: 0xEBE8E8), key: .white, keyDark: Color(hex: 0xDEDBDB), keyText: BlurtBrand.ink, - keyShadow: Color.black.opacity(0.18), popupFill: .white, keyEdge: true) + signal: BlurtBrand.green, keyShadow: Color.black.opacity(0.18), popupFill: .white, keyEdge: true) static let lavender = KeyboardPalette( id: "lavender", name: "Lavender", vibe: "The orb's violet", surface: Color(hex: 0x2C2557), key: Color(hex: 0x3F3777), keyDark: Color(hex: 0x352E68), - keyText: Color(hex: 0xF1EEFF), keyShadow: Color.black.opacity(0.4), popupFill: Color(hex: 0x3F3777), keyEdge: true) + keyText: Color(hex: 0xF1EEFF), signal: BlurtBrand.greenOnDark, keyShadow: Color.black.opacity(0.4), + popupFill: Color(hex: 0x3F3777), keyEdge: true) static let mint = KeyboardPalette( id: "mint", name: "Mint", vibe: "The orb's green", surface: Color(hex: 0x10231B), key: Color(hex: 0x1E3F31), keyDark: Color(hex: 0x183429), - keyText: Color(hex: 0xE9F5EE), keyShadow: Color.black.opacity(0.4), popupFill: Color(hex: 0x1E3F31), keyEdge: true) + keyText: Color(hex: 0xE9F5EE), signal: BlurtBrand.greenOnDark, keyShadow: Color.black.opacity(0.4), + popupFill: Color(hex: 0x1E3F31), keyEdge: true) static let midnight = KeyboardPalette( id: "midnight", name: "Midnight", vibe: "Deep blue-black", surface: Color(hex: 0x0E1220), key: Color(hex: 0x1D2440), keyDark: Color(hex: 0x161B33), - keyText: Color(hex: 0xE8ECFF), keyShadow: Color.black.opacity(0.5), popupFill: Color(hex: 0x1D2440), keyEdge: true) + keyText: Color(hex: 0xE8ECFF), signal: BlurtBrand.greenOnDark, keyShadow: Color.black.opacity(0.5), + popupFill: Color(hex: 0x1D2440), keyEdge: true) static let sunset = KeyboardPalette( id: "sunset", name: "Sunset", vibe: "Warm and loud", surface: Color(hex: 0x2B1912), key: Color(hex: 0x4B2B20), keyDark: Color(hex: 0x3B2119), - keyText: Color(hex: 0xFFEFE6), keyShadow: Color.black.opacity(0.4), popupFill: Color(hex: 0x4B2B20), keyEdge: true) + keyText: Color(hex: 0xFFEFE6), signal: BlurtBrand.greenOnDark, keyShadow: Color.black.opacity(0.4), + popupFill: Color(hex: 0x4B2B20), keyEdge: true) /// The picker's order: the iPhone's own first (shown in the picker's own /// appearance), then Blurt's. diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift index 8faab919..f13928be 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift @@ -73,7 +73,7 @@ struct SlimBarView: View { } } -/// A big orb, centred, that grows into the wave while recording; cancel in +/// A big orb, centred, with the wave through it while recording; cancel in /// the corner while something is in flight; one row of keys. 216 pt. struct PanelView: View { var model: KeyboardModel @@ -81,7 +81,7 @@ struct PanelView: View { var body: some View { VStack(spacing: 12) { Spacer(minLength: 0) - MicKey(model: model, size: 96, expandedWidth: 260) + MicKey(model: model, size: 96, waveReach: 320) Spacer(minLength: 0) HStack(spacing: KeyboardPalette.keyGap) { if model.needsGlobe { KeyCap(systemImage: "globe", dark: true) { model.globe() } } @@ -105,53 +105,60 @@ struct PanelView: View { /// (push-to-talk) — `KeyboardModel` runs the engine's gate. What it does: /// dimmed when Blurt isn't ready (no Full Access, or the app isn't listening; /// the tap opens Blurt); on a tap the ring sweeps as the app's orb does while -/// the mic comes up; then the orb grows sideways into a capsule holding the -/// live wave for as long as you talk, glowing with your voice; on the stop it -/// shrinks back to the circle with the ring sweeping while the words come; -/// then a green ring for a moment when they landed, a clipboard on a green -/// ring when they went to the clipboard instead, an orange ring and an -/// exclamation mark when something failed. Each also has its haptic. +/// the mic comes up; then the voice fades in as a wave passing through the +/// orb, flat on the keyboard's surface, for as long as you talk — the orb +/// stays a circle and greens with the voice; on the stop the wave fades out +/// and the ring sweeps while the words come; then a green ring for a moment +/// when they landed (the violet drop with it), a clipboard on a green ring +/// when they went to the clipboard instead, an orange ring and an exclamation +/// mark when something failed. Each also has its haptic. +/// +/// Nothing snaps or springs: the wave fades over `waveFade`, every other +/// change over `stateFade`. Only the press itself answers at once. struct MicKey: View { var model: KeyboardModel var size: CGFloat - /// How wide the orb grows while recording, to hold the wave. - var expandedWidth: CGFloat + /// How wide the wave reaches while recording, centred on the orb; 0 for + /// none. It draws past the key's own frame and is never tappable. + var waveReach: CGFloat @State private var pressed = false @Environment(\.accessibilityReduceMotion) private var reduceMotion + @Environment(\.keyboardPalette) private var palette + + /// The wave's fade, in and out. + static let waveFade: Double = 0.7 + /// Every other change on the key: the ring, a glyph, the dimming. + static let stateFade: Double = 0.5 var body: some View { - let level = CGFloat(model.snapshot.level) - let width = isRecording ? expandedWidth : size ZStack { + if isRecording, waveReach > 0 { + SignalWave( + level: Float(model.snapshot.level), animated: !reduceMotion, color: palette.signal, orbDiameter: size + ) + .frame(width: waveReach, height: size * 0.5) + .allowsHitTesting(false) + .transition(.opacity) + } PrismOrb(mood: mood, landedAt: model.resultLandedAt, animated: !reduceMotion) - .clipShape(Capsule()) + .clipShape(Circle()) .overlay { ring } .saturation(isReady ? 1 : 0.35) .opacity(isReady ? 1 : 0.8) - if isRecording { - WaveformMeter(level: Float(model.snapshot.level), animated: !reduceMotion, color: .white.opacity(0.92)) - .frame(width: expandedWidth - size * 0.7, height: size * 0.5) - .transition(.opacity) - } if let glyph { Image(systemName: glyph) .font(.system(size: size * 0.34, weight: .semibold)) .foregroundStyle(.white) - .shadow(color: .black.opacity(0.3), radius: 2, y: 1) .transition(.opacity) } } - .frame(width: width, height: size) - .shadow( - color: BlurtBrand.greenOnDark.opacity(isRecording ? 0.35 + 0.45 * level : 0), - radius: isRecording ? size * 0.1 + level * size * 0.25 : 0 - ) - .animation(.easeOut(duration: 0.08), value: level) - .animation(reduceMotion ? nil : .spring(duration: 0.35, bounce: 0.15), value: isRecording) - .animation(.easeInOut(duration: 0.15), value: model.snapshot.state) + .frame(width: size, height: size) + .animation(.easeInOut(duration: Self.waveFade), value: isRecording) + .animation(.easeInOut(duration: Self.stateFade), value: model.snapshot.state) + .animation(.easeInOut(duration: Self.stateFade), value: isReady) .scaleEffect(pressed ? 0.94 : 1) .animation(.easeOut(duration: 0.1), value: pressed) - .contentShape(Capsule()) + .contentShape(Circle()) .accessibilityLabel(isReady ? (isRecording ? "Stop dictation" : "Dictate") : "Start Blurt") .accessibilityValue(model.snapshot.state == .error ? model.snapshot.message ?? "Dictation failed." : "") .accessibilityAddTraits(.isButton) @@ -203,12 +210,12 @@ struct MicKey: View { /// The ring: the app orb's sweep (one turn per 1.6 s, engine geometry) /// while the mic comes up and while the words come; still, and solid green - /// or orange, for a notice; still on the capsule while recording. + /// or orange, for a notice; still while recording. @ViewBuilder private var ring: some View { let width: CGFloat = isWorking || isNotice ? 2 : 1 if isWorking, !isRecording, !reduceMotion { TimelineView(.animation(minimumInterval: keyboardAnimationInterval)) { timeline in - Capsule() + Circle() .strokeBorder(BlurtBrand.orbRingGradient, lineWidth: width) .rotationEffect( .degrees( @@ -216,9 +223,9 @@ struct MicKey: View { time: timeline.date.timeIntervalSinceReferenceDate, period: BrandOrb.period))) } } else if let ringColor { - Capsule().strokeBorder(ringColor, lineWidth: width) + Circle().strokeBorder(ringColor, lineWidth: width) } else { - Capsule().strokeBorder(BlurtBrand.orbRingGradient, lineWidth: width) + Circle().strokeBorder(BlurtBrand.orbRingGradient, lineWidth: width) } } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/PrismOrb.swift b/App/BlurtiOS/BlurtKeyboard/Sources/PrismOrb.swift index e82dd2df..2ead8cdb 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/PrismOrb.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/PrismOrb.swift @@ -25,12 +25,15 @@ struct PrismOrb: View { } var mood: Mood - /// When the words landed — the drop falls then and is gone 1.6 s later. + /// When the words landed — the drop falls then and is gone 2.4 s later. var landedAt: Date? var animated: Bool - /// The drop's life: up in 0.35 s, held to 0.6 s, gone by 1.6 s. - static let dropDuration: TimeInterval = 1.6 + /// The drop's life: up in 0.5 s, held to 0.9 s, gone by 2.4 s — an event, + /// but a soft one. + static let dropDuration: TimeInterval = 2.4 + static let dropRise: TimeInterval = 0.5 + static let dropHold: TimeInterval = 0.9 var body: some View { TimelineView(.animation(minimumInterval: keyboardAnimationInterval, paused: !animated)) { timeline in @@ -52,7 +55,7 @@ struct PrismOrb: View { Grain(seed: animated ? Int(time * 24) : 7).opacity(0.5).blendMode(.overlay) } } - .animation(.easeInOut(duration: 0.6), value: mood) + .animation(.easeInOut(duration: 0.8), value: mood) } /// How much violet is in the orb `elapsed` seconds after the words landed: @@ -63,9 +66,9 @@ struct PrismOrb: View { let t = min(max(x, 0), 1) return t * t * (3 - 2 * t) } - if elapsed < 0.35 { return smooth(elapsed / 0.35) } - if elapsed < 0.6 { return 1 } - return 1 - smooth((elapsed - 0.6) / (dropDuration - 0.6)) + if elapsed < dropRise { return smooth(elapsed / dropRise) } + if elapsed < dropHold { return 1 } + return 1 - smooth((elapsed - dropHold) / (dropDuration - dropHold)) } // MARK: The fluid @@ -133,7 +136,7 @@ struct PrismOrb: View { let elapsed: TimeInterval var body: some View { - let spread = min(1, elapsed / 0.7) + let spread = min(1, elapsed / 1.0) Circle() .fill( RadialGradient( @@ -149,7 +152,8 @@ struct PrismOrb: View { /// Film grain: a scatter of faint dots, a new scatter each frame so it /// shimmers the way grain does, drawn from a seed so a frame is reproducible. -private struct Grain: View { +/// The orb's, and the wave's. +struct Grain: View { let seed: Int var body: some View { @@ -177,15 +181,23 @@ private struct Grain: View { private struct Sparkles: View { let elapsed: TimeInterval - private static let spots: [(x: CGFloat, y: CGFloat, size: CGFloat, delay: Double)] = [ - (0.5, 0.5, 0.14, 0.05), (0.24, 0.3, 0.16, 0.15), (0.76, 0.22, 0.11, 0.25), (0.8, 0.64, 0.14, 0.32), - (0.3, 0.74, 0.1, 0.4), (0.56, 0.84, 0.12, 0.48), + private struct Spot { + let x: CGFloat + let y: CGFloat + let size: CGFloat + let delay: Double + } + + private static let spots: [Spot] = [ + Spot(x: 0.5, y: 0.5, size: 0.14, delay: 0.08), Spot(x: 0.24, y: 0.3, size: 0.16, delay: 0.24), + Spot(x: 0.76, y: 0.22, size: 0.11, delay: 0.4), Spot(x: 0.8, y: 0.64, size: 0.14, delay: 0.5), + Spot(x: 0.3, y: 0.74, size: 0.1, delay: 0.64), Spot(x: 0.56, y: 0.84, size: 0.12, delay: 0.77), ] var body: some View { GeometryReader { geo in ForEach(Array(Self.spots.enumerated()), id: \.offset) { _, spot in - let life = (elapsed - spot.delay) / 0.9 + let life = (elapsed - spot.delay) / 1.3 let up = min(max(life, 0), 1) let shine = up < 0.3 ? up / 0.3 : max(0, 1 - (up - 0.3) / 0.7) Image(systemName: "sparkle") diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift index 1194ec07..7554b19b 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift @@ -2,9 +2,10 @@ import BlurtEngine import SwiftUI /// The keyboard's voice row, and the only place voice lives: the orb, which -/// is the mic key — tap to start and stop, hold to talk — growing into the -/// wave while recording. No words: the orb's ring, shape and glow say what is -/// happening, and the haptics confirm it (see `MicKey`). Beside it, a small +/// is the mic key — tap to start and stop, hold to talk — with the wave +/// passing through it while recording. No words: the orb's ring and colour +/// and the wave say what is happening, and the haptics confirm it (see +/// `MicKey`). Beside it, a small /// + for the one thing people want the instant Blurt mishears a word: add it /// as a key term. The bar then becomes the field the keys type into. struct VoiceBar: View { @@ -22,7 +23,7 @@ struct VoiceBar: View { // The one state the orb can't show on its own: without Full Access // nothing here can work, and the user has to be told where to go. HStack(spacing: 10) { - MicKey(model: model, size: 40, expandedWidth: 40) + MicKey(model: model, size: 40, waveReach: 0) Text("Allow Full Access in Settings → Keyboards") .font(.footnote) .foregroundStyle(BlurtBrand.errorOrange) @@ -31,8 +32,8 @@ struct VoiceBar: View { } .transition(.opacity) } else { - // The wave's capsule stays clear of the + at the trailing edge. - MicKey(model: model, size: 40, expandedWidth: min(200, geo.size.width - 2 * (32 + 12))) + // The wave stays clear of the + at the trailing edge. + MicKey(model: model, size: 40, waveReach: min(240, geo.size.width - 2 * (32 + 12))) .transition(.opacity) } } @@ -42,7 +43,7 @@ struct VoiceBar: View { .overlay(alignment: .trailing) { if model.termDraft == nil, model.hasFullAccess { AddTermKey(model: model) } } - .animation(.easeInOut(duration: 0.15), value: model.termDraft == nil) + .animation(.easeInOut(duration: 0.4), value: model.termDraft == nil) } } @@ -137,11 +138,14 @@ private struct Caret: View { /// The Mac pill's live meter: a row of bars that fills the width it is given /// and tracks the current level, with the engine's envelope and idle wave /// (`MeterBarGeometry`, unit-tested there). The keyboard hears the level from -/// the app at ~12 Hz; the wave keeps the row alive between ticks. +/// the app at ~12 Hz; the wave keeps the row alive between ticks. With +/// `grain`, the orb's film grain shimmers over the bars, so the wave is the +/// orb's own material and not a flat swatch. struct WaveformMeter: View { let level: Float let animated: Bool let color: Color + var grain = false var body: some View { GeometryReader { geo in @@ -161,7 +165,7 @@ struct WaveformMeter: View { } private func bars(layout: MeterBarRow, time: TimeInterval) -> some View { - HStack(spacing: MeterBarGeometry.barSpacing) { + let row = HStack(spacing: MeterBarGeometry.barSpacing) { ForEach(0.. Date: Mon, 28 Sep 2026 20:47:41 -0400 Subject: [PATCH 44/79] Prototype: the orb dissipates into a thin wave; flat, contemporary chrome MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While you talk there is no circle: the orb swells a little, softens to a haze and is gone, and in its place the voice is a thin wave — 2 pt bars 2 pt apart, dense and slim, flat on the surface — which is the key until the stop, when it fades and the orb condenses back the same way. The key's frame is the wave's width throughout so nothing shifts while the two cross. The home hero does the same. The engine's MeterBarRow gains an initializer for a caller with its own pitch, so the wave keeps the Mac's envelope and idle wave. The keyboard's chrome is flat and modern: one colour per key at 8 pt corners, no drop, no edge; the +, the cancel ×, the term field's × and ✓ are bare glyphs; the term field a flat capsule; the pop-up keeps a whisper of shadow. The palette loses keyShadow and keyEdge. A first cut on this branch kept the orb standing with the wave through it and was rejected on sight. Verified on the iOS 27 simulator across the three layouts on the light, dark, paper and ink themes; engine and iOS tests pass. Co-Authored-By: Claude Fable 5.1 --- .../BlurtKeyboard/Sources/Dissipate.swift | 22 +++ .../Sources/FullKeyboardView.swift | 6 +- .../Sources/KeyboardPalette.swift | 37 ++--- .../BlurtKeyboard/Sources/KeyboardViews.swift | 98 +++++------ .../BlurtKeyboard/Sources/PrismOrb.swift | 7 +- .../BlurtKeyboard/Sources/VoiceBar.swift | 92 ++++------- App/BlurtiOS/BlurtiOS/Sources/HomeView.swift | 29 ++-- App/BlurtiOS/DESIGN.md | 156 +++++++++--------- .../Pipeline/MeterBarGeometry.swift | 14 +- 9 files changed, 235 insertions(+), 226 deletions(-) create mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/Dissipate.swift diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/Dissipate.swift b/App/BlurtiOS/BlurtKeyboard/Sources/Dissipate.swift new file mode 100644 index 00000000..c6c59378 --- /dev/null +++ b/App/BlurtiOS/BlurtKeyboard/Sources/Dissipate.swift @@ -0,0 +1,22 @@ +import SwiftUI + +/// The orb dissipating: it swells a little, softens to a haze and is gone — +/// mist, not a pop — and condenses back the same way. `size` scales the haze. +private struct Dissipate: ViewModifier { + let amount: Double + let size: CGFloat + + func body(content: Content) -> some View { + content + .scaleEffect(1 + 0.25 * amount) + .blur(radius: size * 0.16 * amount) + .opacity(1 - amount) + } +} + +extension AnyTransition { + /// See `Dissipate`. + static func dissipate(size: CGFloat) -> AnyTransition { + .modifier(active: Dissipate(amount: 1, size: size), identity: Dissipate(amount: 0, size: size)) + } +} diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift b/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift index f31cf478..87a271e7 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift @@ -82,7 +82,7 @@ private struct LetterKey: View { .font(.system(size: 22)) .foregroundStyle(palette.keyText) .frame(width: width, height: KeyCap.height) - .keyCap(palette.key, palette: palette) + .keyCap(palette.key) .overlay(alignment: .top) { if pressed { popup } } @@ -108,8 +108,8 @@ private struct LetterKey: View { .font(.system(size: 32)) .foregroundStyle(palette.keyText) .frame(width: width + 18, height: 56) - .background(palette.popupFill, in: RoundedRectangle(cornerRadius: 9)) - .shadow(color: .black.opacity(0.25), radius: 4, y: 2) + .background(palette.popupFill, in: RoundedRectangle(cornerRadius: 10)) + .shadow(color: .black.opacity(0.12), radius: 8, y: 2) .offset(y: -58) .allowsHitTesting(false) } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift index bcd7a16d..367fdaf3 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift @@ -7,9 +7,9 @@ import SwiftUI /// lavender and green, a warm paper, a midnight, a sunset), each contemporary /// and fun and none off-brand, picked in the app Partiful-style from live /// previews. The spacing never changes (the iPhone keyboard's own — 6 pt -/// between keys, 11 between rows, 3 at the edges, 5 pt corners, a 1 pt drop -/// under every key), so a theme changes how the keyboard looks and never how -/// it types. +/// between keys, 11 between rows, 3 at the edges), so a theme changes how +/// the keyboard looks and never how it types. The keys are flat: one colour +/// at 8 pt corners, no drop, no edge, no gloss. struct KeyboardPalette: Equatable, Identifiable { let id: String let name: String @@ -22,65 +22,56 @@ struct KeyboardPalette: Equatable, Identifiable { /// The voice on this surface: the wave while recording. The brand green /// that reads on it — the wordmark's on light, the lifted one on dark. let signal: Color - /// The drop under each key, as the system keyboard draws it. - let keyShadow: Color let popupFill: Color - /// A faint light edge on each key — what lifts a key off a dark surface; - /// the light palettes have their drop for that and no edge. - let keyEdge: Bool static let keyGap: CGFloat = 6 static let rowGap: CGFloat = 11 static let margin: CGFloat = 3 - static let keyRadius: CGFloat = 5 + static let keyRadius: CGFloat = 8 /// The iPhone's light keyboard: `#D1D5DB` surface, white keys, `#ADB3BC` - /// modifiers, a `#898A8D` drop, black legends. + /// modifiers, black legends. static let systemLight = KeyboardPalette( id: "system", name: "iPhone", vibe: "Matches the iPhone keyboard, light or dark with the app you're in", surface: Color(hex: 0xD1D5DB), key: .white, keyDark: Color(hex: 0xADB3BC), keyText: .black, - signal: BlurtBrand.green, keyShadow: Color(hex: 0x898A8D), popupFill: .white, keyEdge: false) + signal: BlurtBrand.green, popupFill: .white) /// The iPhone's dark keyboard: `#2B2B2B` surface, `#6B6B6B` keys, `#464646` - /// modifiers, a near-black drop, white legends. + /// modifiers, white legends. static let systemDark = KeyboardPalette( id: "system", name: "iPhone", vibe: "Matches the iPhone keyboard, light or dark with the app you're in", surface: Color(hex: 0x2B2B2B), key: Color(hex: 0x6B6B6B), keyDark: Color(hex: 0x464646), keyText: .white, - signal: BlurtBrand.greenOnDark, keyShadow: Color(hex: 0x0D0D0D), popupFill: Color(hex: 0x6B6B6B), keyEdge: false) + signal: BlurtBrand.greenOnDark, popupFill: Color(hex: 0x6B6B6B)) static let ink = KeyboardPalette( id: "ink", name: "Ink", vibe: "Blurt's own", surface: BlurtBrand.ink, key: BlurtBrand.key, keyDark: BlurtBrand.keyDark, keyText: BlurtBrand.keyText, - signal: BlurtBrand.greenOnDark, keyShadow: Color.black.opacity(0.45), popupFill: BlurtBrand.key, keyEdge: true) + signal: BlurtBrand.greenOnDark, popupFill: BlurtBrand.key) static let paper = KeyboardPalette( id: "paper", name: "Paper", vibe: "Warm and light", surface: Color(hex: 0xEBE8E8), key: .white, keyDark: Color(hex: 0xDEDBDB), keyText: BlurtBrand.ink, - signal: BlurtBrand.green, keyShadow: Color.black.opacity(0.18), popupFill: .white, keyEdge: true) + signal: BlurtBrand.green, popupFill: .white) static let lavender = KeyboardPalette( id: "lavender", name: "Lavender", vibe: "The orb's violet", surface: Color(hex: 0x2C2557), key: Color(hex: 0x3F3777), keyDark: Color(hex: 0x352E68), - keyText: Color(hex: 0xF1EEFF), signal: BlurtBrand.greenOnDark, keyShadow: Color.black.opacity(0.4), - popupFill: Color(hex: 0x3F3777), keyEdge: true) + keyText: Color(hex: 0xF1EEFF), signal: BlurtBrand.greenOnDark, popupFill: Color(hex: 0x3F3777)) static let mint = KeyboardPalette( id: "mint", name: "Mint", vibe: "The orb's green", surface: Color(hex: 0x10231B), key: Color(hex: 0x1E3F31), keyDark: Color(hex: 0x183429), - keyText: Color(hex: 0xE9F5EE), signal: BlurtBrand.greenOnDark, keyShadow: Color.black.opacity(0.4), - popupFill: Color(hex: 0x1E3F31), keyEdge: true) + keyText: Color(hex: 0xE9F5EE), signal: BlurtBrand.greenOnDark, popupFill: Color(hex: 0x1E3F31)) static let midnight = KeyboardPalette( id: "midnight", name: "Midnight", vibe: "Deep blue-black", surface: Color(hex: 0x0E1220), key: Color(hex: 0x1D2440), keyDark: Color(hex: 0x161B33), - keyText: Color(hex: 0xE8ECFF), signal: BlurtBrand.greenOnDark, keyShadow: Color.black.opacity(0.5), - popupFill: Color(hex: 0x1D2440), keyEdge: true) + keyText: Color(hex: 0xE8ECFF), signal: BlurtBrand.greenOnDark, popupFill: Color(hex: 0x1D2440)) static let sunset = KeyboardPalette( id: "sunset", name: "Sunset", vibe: "Warm and loud", surface: Color(hex: 0x2B1912), key: Color(hex: 0x4B2B20), keyDark: Color(hex: 0x3B2119), - keyText: Color(hex: 0xFFEFE6), signal: BlurtBrand.greenOnDark, keyShadow: Color.black.opacity(0.4), - popupFill: Color(hex: 0x4B2B20), keyEdge: true) + keyText: Color(hex: 0xFFEFE6), signal: BlurtBrand.greenOnDark, popupFill: Color(hex: 0x4B2B20)) /// The picker's order: the iPhone's own first (shown in the picker's own /// appearance), then Blurt's. diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift index f13928be..1eeb585e 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift @@ -73,15 +73,15 @@ struct SlimBarView: View { } } -/// A big orb, centred, with the wave through it while recording; cancel in -/// the corner while something is in flight; one row of keys. 216 pt. +/// A big orb, centred, that dissipates into the wave while recording; cancel +/// in the corner while something is in flight; one row of keys. 216 pt. struct PanelView: View { var model: KeyboardModel var body: some View { VStack(spacing: 12) { Spacer(minLength: 0) - MicKey(model: model, size: 96, waveReach: 320) + MicKey(model: model, size: 96, wave: CGSize(width: 300, height: 40)) Spacer(minLength: 0) HStack(spacing: KeyboardPalette.keyGap) { if model.needsGlobe { KeyCap(systemImage: "globe", dark: true) { model.globe() } } @@ -92,8 +92,9 @@ struct PanelView: View { } .overlay(alignment: .topTrailing) { if !model.isSettled { - KeyCap(systemImage: "xmark", tint: BlurtBrand.errorOrange, dark: true) { model.cancel() } + KeyCap(systemImage: "xmark", tint: BlurtBrand.errorOrange, bare: true) { model.cancel() } .accessibilityLabel("Cancel dictation") + .transition(.opacity) } } .overlay(alignment: .topLeading) { AddTermKey(model: model).padding(6) } @@ -105,46 +106,53 @@ struct PanelView: View { /// (push-to-talk) — `KeyboardModel` runs the engine's gate. What it does: /// dimmed when Blurt isn't ready (no Full Access, or the app isn't listening; /// the tap opens Blurt); on a tap the ring sweeps as the app's orb does while -/// the mic comes up; then the voice fades in as a wave passing through the -/// orb, flat on the keyboard's surface, for as long as you talk — the orb -/// stays a circle and greens with the voice; on the stop the wave fades out -/// and the ring sweeps while the words come; then a green ring for a moment -/// when they landed (the violet drop with it), a clipboard on a green ring -/// when they went to the clipboard instead, an orange ring and an exclamation -/// mark when something failed. Each also has its haptic. +/// the mic comes up; then the orb dissipates — swells a little, softens to a +/// haze, is gone — and in its place the voice is a thin wave, flat on the +/// surface, for as long as you talk, and the wave is the key; on the stop +/// the wave fades and the orb condenses back with the ring sweeping while +/// the words come; then a green ring for a moment when they landed (the +/// violet drop with it), a clipboard on a green ring when they went to the +/// clipboard instead, an orange ring and an exclamation mark when something +/// failed. Each also has its haptic. /// -/// Nothing snaps or springs: the wave fades over `waveFade`, every other -/// change over `stateFade`. Only the press itself answers at once. +/// Nothing snaps or springs: the orb and the wave cross over `waveFade`, +/// every other change over `stateFade`. Only the press itself answers at +/// once. struct MicKey: View { var model: KeyboardModel var size: CGFloat - /// How wide the wave reaches while recording, centred on the orb; 0 for - /// none. It draws past the key's own frame and is never tappable. - var waveReach: CGFloat + /// The wave the orb dissipates into while recording — wide and slim — + /// or nil for none (the orb stays). The key's frame is the wave's width + /// throughout, so nothing moves while the two cross; only the circle + /// answers a touch until the wave is up, then the wave's band does. + var wave: CGSize? @State private var pressed = false @Environment(\.accessibilityReduceMotion) private var reduceMotion @Environment(\.keyboardPalette) private var palette - /// The wave's fade, in and out. + /// The orb and the wave crossing, either way. static let waveFade: Double = 0.7 /// Every other change on the key: the ring, a glyph, the dimming. static let stateFade: Double = 0.5 var body: some View { ZStack { - if isRecording, waveReach > 0 { - SignalWave( - level: Float(model.snapshot.level), animated: !reduceMotion, color: palette.signal, orbDiameter: size + if let wave, isRecording { + WaveformMeter( + level: Float(model.snapshot.level), animated: !reduceMotion, color: palette.signal, + barWidth: WaveformMeter.slimBar, barSpacing: WaveformMeter.slimGap ) - .frame(width: waveReach, height: size * 0.5) - .allowsHitTesting(false) + .frame(width: wave.width, height: wave.height) .transition(.opacity) + } else { + PrismOrb(mood: mood, landedAt: model.resultLandedAt, animated: !reduceMotion) + .clipShape(Circle()) + .overlay { ring } + .frame(width: size, height: size) + .saturation(isReady ? 1 : 0.35) + .opacity(isReady ? 1 : 0.8) + .transition(reduceMotion ? .opacity : .dissipate(size: size)) } - PrismOrb(mood: mood, landedAt: model.resultLandedAt, animated: !reduceMotion) - .clipShape(Circle()) - .overlay { ring } - .saturation(isReady ? 1 : 0.35) - .opacity(isReady ? 1 : 0.8) if let glyph { Image(systemName: glyph) .font(.system(size: size * 0.34, weight: .semibold)) @@ -152,13 +160,13 @@ struct MicKey: View { .transition(.opacity) } } - .frame(width: size, height: size) + .frame(width: wave.map { max($0.width, size) } ?? size, height: size) .animation(.easeInOut(duration: Self.waveFade), value: isRecording) .animation(.easeInOut(duration: Self.stateFade), value: model.snapshot.state) .animation(.easeInOut(duration: Self.stateFade), value: isReady) .scaleEffect(pressed ? 0.94 : 1) .animation(.easeOut(duration: 0.1), value: pressed) - .contentShape(Circle()) + .contentShape(showsWave ? AnyShape(Capsule()) : AnyShape(Circle())) .accessibilityLabel(isReady ? (isRecording ? "Stop dictation" : "Dictate") : "Start Blurt") .accessibilityValue(model.snapshot.state == .error ? model.snapshot.message ?? "Dictation failed." : "") .accessibilityAddTraits(.isButton) @@ -230,6 +238,8 @@ struct MicKey: View { } private var isReady: Bool { model.isReady } + /// The wave is up, and is the key. + private var showsWave: Bool { isRecording && wave != nil } /// The orb's story from the phase: green, greener with the voice; the /// violet drop is keyed to the moment the words landed, not to a phase. @@ -277,15 +287,16 @@ struct MicKey: View { } /// One ordinary key: a legend on a cap in the current palette; `dark` for the -/// modifier keys, a step darker as on the system keyboard. `flexible` keys -/// (the space bar) take the width they're given, `width` fixes one, and the -/// rest are 44 wide. +/// modifier keys, a step darker as on the system keyboard; `bare` for a glyph +/// with no cap at all (the panel's cancel). `flexible` keys (the space bar) +/// take the width they're given, `width` fixes one, and the rest are 44 wide. struct KeyCap: View { var title: String? var systemImage: String? var tint: Color? var flexible = false var dark = false + var bare = false var width: CGFloat? var action: () -> Void @Environment(\.keyboardPalette) private var palette @@ -294,13 +305,14 @@ struct KeyCap: View { init( title: String? = nil, systemImage: String? = nil, tint: Color? = nil, flexible: Bool = false, - dark: Bool = false, width: CGFloat? = nil, action: @escaping () -> Void + dark: Bool = false, bare: Bool = false, width: CGFloat? = nil, action: @escaping () -> Void ) { self.title = title self.systemImage = systemImage self.tint = tint self.flexible = flexible self.dark = dark + self.bare = bare self.width = width self.action = action } @@ -319,7 +331,7 @@ struct KeyCap: View { .frame(width: width) .frame(minWidth: width == nil ? 44 : nil, minHeight: Self.height) .padding(.horizontal, flexible || width != nil ? 0 : 4) - .keyCap(dark ? palette.keyDark : palette.key, palette: palette) + .keyCap(bare ? .clear : dark ? palette.keyDark : palette.key) .keyPress(action) .accessibilityLabel(title ?? systemImage ?? "") } @@ -361,20 +373,10 @@ struct KeyPress: ViewModifier { } extension View { - /// The cap under a key's legend: the palette's fill, the system keyboard's - /// corner radius and 1 pt drop, and on the dark palettes a hairline so the - /// cap reads on ink. - func keyCap(_ fill: Color, palette: KeyboardPalette) -> some View { - background { - RoundedRectangle(cornerRadius: KeyboardPalette.keyRadius) - .fill(fill) - .shadow(color: palette.keyShadow, radius: 0, y: 1) - } - .overlay { - if palette.keyEdge { - RoundedRectangle(cornerRadius: KeyboardPalette.keyRadius).strokeBorder(Color.white.opacity(0.06), lineWidth: 1) - } - } + /// The cap under a key's legend: the palette's fill at the corner radius and + /// nothing else — flat. No drop, no edge, no gloss. + func keyCap(_ fill: Color) -> some View { + background(fill, in: RoundedRectangle(cornerRadius: KeyboardPalette.keyRadius)) } } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/PrismOrb.swift b/App/BlurtiOS/BlurtKeyboard/Sources/PrismOrb.swift index 2ead8cdb..aa99cea7 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/PrismOrb.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/PrismOrb.swift @@ -50,7 +50,7 @@ struct PrismOrb: View { endRadius: 110)) if drop > 0 { Drop(amount: drop, elapsed: elapsed) - Sparkles(elapsed: elapsed) + Sparkles(elapsed: elapsed) // invariant-ok: the orb's star glyphs, not the Sparkle updater } Grain(seed: animated ? Int(time * 24) : 7).opacity(0.5).blendMode(.overlay) } @@ -152,8 +152,7 @@ struct PrismOrb: View { /// Film grain: a scatter of faint dots, a new scatter each frame so it /// shimmers the way grain does, drawn from a seed so a frame is reproducible. -/// The orb's, and the wave's. -struct Grain: View { +private struct Grain: View { let seed: Int var body: some View { @@ -178,7 +177,7 @@ struct Grain: View { /// The artwork's stars: six four-point sparkles that burst once with the /// drop — each a beat after the last — and are gone with it. -private struct Sparkles: View { +private struct Sparkles: View { // invariant-ok: the orb's star glyphs, not the Sparkle updater let elapsed: TimeInterval private struct Spot { diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift index 7554b19b..b3606819 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift @@ -2,10 +2,10 @@ import BlurtEngine import SwiftUI /// The keyboard's voice row, and the only place voice lives: the orb, which -/// is the mic key — tap to start and stop, hold to talk — with the wave -/// passing through it while recording. No words: the orb's ring and colour -/// and the wave say what is happening, and the haptics confirm it (see -/// `MicKey`). Beside it, a small +/// is the mic key — tap to start and stop, hold to talk — dissipating into +/// the wave while recording. No words: the orb's ring and colour, or the +/// wave, say what is happening, and the haptics confirm it (see `MicKey`). +/// Beside it, a small /// + for the one thing people want the instant Blurt mishears a word: add it /// as a key term. The bar then becomes the field the keys type into. struct VoiceBar: View { @@ -23,7 +23,7 @@ struct VoiceBar: View { // The one state the orb can't show on its own: without Full Access // nothing here can work, and the user has to be told where to go. HStack(spacing: 10) { - MicKey(model: model, size: 40, waveReach: 0) + MicKey(model: model, size: 40, wave: nil) Text("Allow Full Access in Settings → Keyboards") .font(.footnote) .foregroundStyle(BlurtBrand.errorOrange) @@ -33,7 +33,7 @@ struct VoiceBar: View { .transition(.opacity) } else { // The wave stays clear of the + at the trailing edge. - MicKey(model: model, size: 40, waveReach: min(240, geo.size.width - 2 * (32 + 12))) + MicKey(model: model, size: 40, wave: CGSize(width: min(240, geo.size.width - 2 * (32 + 12)), height: 24)) .transition(.opacity) } } @@ -48,7 +48,8 @@ struct VoiceBar: View { } /// The small + beside the orb (and in the panel's corner): a new key term. -/// Shows a check for a moment after one was saved. +/// A bare glyph, quiet until it is needed; a check for a moment after one +/// was saved. struct AddTermKey: View { var model: KeyboardModel @Environment(\.keyboardPalette) private var palette @@ -58,11 +59,10 @@ struct AddTermKey: View { model.beginAddingTerm() } label: { Image(systemName: model.termSavedAt == nil ? "plus" : "checkmark") - .font(.system(size: 15, weight: .semibold)) - .foregroundStyle(model.termSavedAt == nil ? palette.keyText.opacity(0.7) : BlurtBrand.greenOnDark) + .font(.system(size: 17, weight: .medium)) + .foregroundStyle(model.termSavedAt == nil ? palette.keyText.opacity(0.5) : palette.signal) .frame(width: 32, height: 32) - .background(Circle().fill(palette.keyDark)) - .overlay(Circle().strokeBorder(Color.white.opacity(0.08), lineWidth: 1)) + .contentShape(Circle()) .contentTransition(.symbolEffect(.replace)) } .buttonStyle(KeyPressStyle()) @@ -97,24 +97,23 @@ private struct TermField: View { .frame(maxWidth: .infinity) .frame(height: 36) .background(Capsule().fill(palette.keyDark)) - .overlay(Capsule().strokeBorder(BlurtBrand.greenOnDark.opacity(0.6), lineWidth: 1)) .accessibilityElement(children: .ignore) .accessibilityLabel("Key term: \(model.termDraft ?? "")") - round("checkmark", tint: BlurtBrand.greenOnDark) { model.saveTerm() } + round("checkmark", tint: palette.signal) { model.saveTerm() } .accessibilityLabel("Save the key term") .disabled(model.termDraft?.trimmingCharacters(in: .whitespaces).isEmpty ?? true) } .padding(.horizontal, 2) } + /// × and ✓: bare glyphs, as the + is. private func round(_ symbol: String, tint: Color, action: @escaping () -> Void) -> some View { Button(action: action) { Image(systemName: symbol) - .font(.system(size: 15, weight: .semibold)) + .font(.system(size: 17, weight: .medium)) .foregroundStyle(tint) .frame(width: 32, height: 32) - .background(Circle().fill(palette.keyDark)) - .overlay(Circle().strokeBorder(Color.white.opacity(0.08), lineWidth: 1)) + .contentShape(Circle()) } .buttonStyle(KeyPressStyle()) } @@ -122,11 +121,13 @@ private struct TermField: View { /// A blinking caret, as a text field's. private struct Caret: View { + @Environment(\.keyboardPalette) private var palette + var body: some View { TimelineView(.periodic(from: .now, by: 0.5)) { timeline in let on = Int(timeline.date.timeIntervalSinceReferenceDate * 2) % 2 == 0 RoundedRectangle(cornerRadius: 1) - .fill(BlurtBrand.greenOnDark) + .fill(palette.signal) .frame(width: 2, height: 20) .opacity(on ? 1 : 0) .padding(.leading, 1) @@ -138,18 +139,25 @@ private struct Caret: View { /// The Mac pill's live meter: a row of bars that fills the width it is given /// and tracks the current level, with the engine's envelope and idle wave /// (`MeterBarGeometry`, unit-tested there). The keyboard hears the level from -/// the app at ~12 Hz; the wave keeps the row alive between ticks. With -/// `grain`, the orb's film grain shimmers over the bars, so the wave is the -/// orb's own material and not a flat swatch. +/// the app at ~12 Hz; the wave keeps the row alive between ticks. The pitch +/// is the Mac's unless the caller sets its own: the keyboard's wave is thin — +/// `slimBar` wide, `slimGap` apart — and dense, a fine signal rather than a +/// bank of bars. struct WaveformMeter: View { let level: Float let animated: Bool let color: Color - var grain = false + var barWidth: CGFloat = MeterBarGeometry.barWidth + var barSpacing: CGFloat = MeterBarGeometry.barSpacing + + /// The keyboard's pitch: 2 pt bars, 2 pt apart. + static let slimBar: CGFloat = 2 + static let slimGap: CGFloat = 2 var body: some View { GeometryReader { geo in - let layout = MeterBarRow(availableSize: geo.size) + let count = Int((geo.size.width + barSpacing) / (barWidth + barSpacing)) + let layout = MeterBarRow(count: count, availableHeight: geo.size.height) Group { if animated { TimelineView(.animation(minimumInterval: keyboardAnimationInterval)) { timeline in @@ -165,49 +173,13 @@ struct WaveformMeter: View { } private func bars(layout: MeterBarRow, time: TimeInterval) -> some View { - let row = HStack(spacing: MeterBarGeometry.barSpacing) { + HStack(spacing: barSpacing) { ForEach(0.. Date: Mon, 28 Sep 2026 22:19:56 -0400 Subject: [PATCH 45/79] iOS: design tokens as the one source, and deterministic gallery captures MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Design/tokens.json now holds every colour and number the keyboard's views draw with; scripts/design-tokens.swift fans it out to Shared/DesignTokens.swift, the marked tables in DESIGN.md and the three asset-catalog colour sets, and scripts/design-sync.sh --check (wired into check.sh) fails on drift or on a design literal left in a view. BlurtBrand and KeyboardPalette keep their names as aliases; KeyboardLayout.height is derived from the tokens; DesignTokensTests pins the compiled values to the file, the heights to the arithmetic, the 402 pt widths to the Figma frames, the palettes to their theme tokens. The gallery grows two capture switches — -BlurtGalleryStill (motion held at time zero through a keyboardMotionHeld environment key) and -BlurtGalleryBare (one row inside a #FF00FF registration border) — and -BlurtOrb for orb stills. scripts/design-capture.sh builds once and crops each still to the keyboard's own pixels (scripts/design-diff.swift: crop, diff with masks and AE/RMSE, contact sheet); scripts/ios-record.sh cuts one loop of the live walk; ios-sim.sh gets --no-build. No visual change: the idle crop is byte-identical across runs and the catalog JSON is byte-identical to before. Co-Authored-By: Claude Fable 5.1 --- .../BlurtKeyboard/Sources/BrandOrb.swift | 4 +- .../BlurtKeyboard/Sources/Dissipate.swift | 4 +- .../Sources/FullKeyboardView.swift | 23 +- .../Sources/KeyboardPalette.swift | 47 +- .../Sources/KeyboardViewController.swift | 2 +- .../BlurtKeyboard/Sources/KeyboardViews.swift | 58 +- .../BlurtKeyboard/Sources/MotionHeld.swift | 18 + .../BlurtKeyboard/Sources/PrismOrb.swift | 30 +- .../BlurtKeyboard/Sources/VoiceBar.swift | 65 +- .../BlurtiOS/Sources/BlurtBrand+App.swift | 8 +- .../BlurtiOS/Sources/BlurtiOSApp.swift | 6 +- App/BlurtiOS/BlurtiOS/Sources/HomeView.swift | 12 +- .../Sources/KeyboardGalleryView.swift | 113 ++- .../BlurtiOS/Sources/ThemePickerView.swift | 9 +- .../BlurtiOSTests/DesignTokensTests.swift | 184 +++++ .../BlurtiOSTests/FeedAndLayoutTests.swift | 16 +- .../BlurtiOSTests/SharedStateTests.swift | 4 +- App/BlurtiOS/DESIGN.md | 350 +++++++-- App/BlurtiOS/Design/tokens.json | 668 ++++++++++++++++++ App/BlurtiOS/Shared/BlurtBrand.swift | 36 +- App/BlurtiOS/Shared/DesignTokens.swift | 589 +++++++++++++++ App/BlurtiOS/Shared/SharedState.swift | 9 +- App/BlurtiOS/project.yml | 4 + scripts/check.sh | 13 + scripts/design-capture.sh | 104 +++ scripts/design-diff.swift | 297 ++++++++ scripts/design-sync.sh | 123 ++++ scripts/design-tokens.swift | 438 ++++++++++++ scripts/ios-record.sh | 97 +++ scripts/ios-sim.sh | 38 +- 30 files changed, 3150 insertions(+), 219 deletions(-) create mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/MotionHeld.swift create mode 100644 App/BlurtiOS/BlurtiOSTests/DesignTokensTests.swift create mode 100644 App/BlurtiOS/Design/tokens.json create mode 100644 App/BlurtiOS/Shared/DesignTokens.swift create mode 100755 scripts/design-capture.sh create mode 100755 scripts/design-diff.swift create mode 100755 scripts/design-sync.sh create mode 100755 scripts/design-tokens.swift create mode 100755 scripts/ios-record.sh diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/BrandOrb.swift b/App/BlurtiOS/BlurtKeyboard/Sources/BrandOrb.swift index 2d37603f..24b55872 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/BrandOrb.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/BrandOrb.swift @@ -19,10 +19,10 @@ struct BrandOrb: View { /// Whether the ring sweeps. Off under Reduce Motion, where the ring is still /// drawn — it is part of the mark — but holds still. var animated: Bool - var ringWidth: CGFloat = 1 + var ringWidth = DesignTokens.Metrics.ringStill /// One turn every 1.6 s: the Mac's cadence. - static let period: Double = 1.6 + static let period = DesignTokens.Motion.ringPeriod var body: some View { Circle() diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/Dissipate.swift b/App/BlurtiOS/BlurtKeyboard/Sources/Dissipate.swift index c6c59378..db100283 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/Dissipate.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/Dissipate.swift @@ -8,8 +8,8 @@ private struct Dissipate: ViewModifier { func body(content: Content) -> some View { content - .scaleEffect(1 + 0.25 * amount) - .blur(radius: size * 0.16 * amount) + .scaleEffect(1 + (DesignTokens.Metrics.orbDissipateScale - 1) * amount) + .blur(radius: size * DesignTokens.Metrics.orbDissipateBlur * amount) .opacity(1 - amount) } } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift b/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift index 87a271e7..1f0f0d84 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift @@ -19,13 +19,13 @@ struct FullKeyboardView: View { let keyWidth = (geo.size.width - 9 * gap) / 10 // Shift and delete take what seven letters leave, standing a little // further from them than letters stand from each other. - let sideGap = gap * 2 + let sideGap = gap * DesignTokens.Metrics.keySideGapFactor let sideWidth = (geo.size.width - 7 * keyWidth - 6 * gap - 2 * sideGap) / 2 VStack(spacing: KeyboardPalette.rowGap) { VoiceBar(model: model) ForEach(Array(rows.enumerated()), id: \.offset) { index, row in - HStack(spacing: index == 2 ? sideGap : gap) { - if index == 2 { modifierKey(width: sideWidth) } + HStack(spacing: index == 2 ? sideGap : gap) { // literal-ok: the third row carries shift and delete + if index == 2 { modifierKey(width: sideWidth) } // literal-ok: the third row HStack(spacing: gap) { ForEach(Array(row), id: \.self) { character in LetterKey(label: label(for: character), width: keyWidth) { model.type(label(for: character)) } @@ -44,7 +44,7 @@ struct FullKeyboardView: View { KeyCap(title: "space", flexible: true) { model.space() } KeyCap( title: model.returnLabel, systemImage: model.returnLabel == nil ? "return" : nil, dark: true, - width: sideWidth * 2 + gap + width: sideWidth * 2 + gap // literal-ok: return is two modifiers wide ) { model.newline() } } } @@ -79,7 +79,7 @@ private struct LetterKey: View { var body: some View { Text(label) - .font(.system(size: 22)) + .font(.system(size: DesignTokens.Typography.sizeLetter, weight: DesignTokens.Typography.weightLetter)) .foregroundStyle(palette.keyText) .frame(width: width, height: KeyCap.height) .keyCap(palette.key) @@ -105,12 +105,15 @@ private struct LetterKey: View { private var popup: some View { Text(label) - .font(.system(size: 32)) + .font(.system(size: DesignTokens.Typography.sizePopup, weight: DesignTokens.Typography.weightPopup)) .foregroundStyle(palette.keyText) - .frame(width: width + 18, height: 56) - .background(palette.popupFill, in: RoundedRectangle(cornerRadius: 10)) - .shadow(color: .black.opacity(0.12), radius: 8, y: 2) - .offset(y: -58) + .frame(width: width + DesignTokens.Metrics.popupExtraWidth, height: DesignTokens.Metrics.popupHeight) + .background(palette.popupFill, in: RoundedRectangle(cornerRadius: DesignTokens.Metrics.popupRadius)) + .shadow( + color: .black.opacity(DesignTokens.Metrics.opacityPopupShadow), radius: DesignTokens.Metrics.popupShadowRadius, + y: DesignTokens.Metrics.popupShadowY + ) + .offset(y: -DesignTokens.Metrics.popupOffset) .allowsHitTesting(false) } } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift index 367fdaf3..dbf7358d 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift @@ -24,54 +24,56 @@ struct KeyboardPalette: Equatable, Identifiable { let signal: Color let popupFill: Color - static let keyGap: CGFloat = 6 - static let rowGap: CGFloat = 11 - static let margin: CGFloat = 3 - static let keyRadius: CGFloat = 8 + static let keyGap = DesignTokens.Metrics.keyGap + static let rowGap = DesignTokens.Metrics.rowGap + static let margin = DesignTokens.Metrics.marginSide + static let keyRadius = DesignTokens.Metrics.keyRadius + + private typealias Themes = DesignTokens.Themes /// The iPhone's light keyboard: `#D1D5DB` surface, white keys, `#ADB3BC` /// modifiers, black legends. static let systemLight = KeyboardPalette( id: "system", name: "iPhone", vibe: "Matches the iPhone keyboard, light or dark with the app you're in", - surface: Color(hex: 0xD1D5DB), key: .white, keyDark: Color(hex: 0xADB3BC), keyText: .black, - signal: BlurtBrand.green, popupFill: .white) + surface: Themes.systemLightSurface, key: Themes.systemLightKey, keyDark: Themes.systemLightKeyModifier, + keyText: Themes.systemLightLegend, signal: Themes.systemLightSignal, popupFill: Themes.systemLightPopup) /// The iPhone's dark keyboard: `#2B2B2B` surface, `#6B6B6B` keys, `#464646` /// modifiers, white legends. static let systemDark = KeyboardPalette( id: "system", name: "iPhone", vibe: "Matches the iPhone keyboard, light or dark with the app you're in", - surface: Color(hex: 0x2B2B2B), key: Color(hex: 0x6B6B6B), keyDark: Color(hex: 0x464646), keyText: .white, - signal: BlurtBrand.greenOnDark, popupFill: Color(hex: 0x6B6B6B)) + surface: Themes.systemDarkSurface, key: Themes.systemDarkKey, keyDark: Themes.systemDarkKeyModifier, + keyText: Themes.systemDarkLegend, signal: Themes.systemDarkSignal, popupFill: Themes.systemDarkPopup) static let ink = KeyboardPalette( id: "ink", name: "Ink", vibe: "Blurt's own", - surface: BlurtBrand.ink, key: BlurtBrand.key, keyDark: BlurtBrand.keyDark, keyText: BlurtBrand.keyText, - signal: BlurtBrand.greenOnDark, popupFill: BlurtBrand.key) + surface: Themes.inkSurface, key: Themes.inkKey, keyDark: Themes.inkKeyModifier, keyText: Themes.inkLegend, + signal: Themes.inkSignal, popupFill: Themes.inkPopup) static let paper = KeyboardPalette( id: "paper", name: "Paper", vibe: "Warm and light", - surface: Color(hex: 0xEBE8E8), key: .white, keyDark: Color(hex: 0xDEDBDB), keyText: BlurtBrand.ink, - signal: BlurtBrand.green, popupFill: .white) + surface: Themes.paperSurface, key: Themes.paperKey, keyDark: Themes.paperKeyModifier, keyText: Themes.paperLegend, + signal: Themes.paperSignal, popupFill: Themes.paperPopup) static let lavender = KeyboardPalette( id: "lavender", name: "Lavender", vibe: "The orb's violet", - surface: Color(hex: 0x2C2557), key: Color(hex: 0x3F3777), keyDark: Color(hex: 0x352E68), - keyText: Color(hex: 0xF1EEFF), signal: BlurtBrand.greenOnDark, popupFill: Color(hex: 0x3F3777)) + surface: Themes.lavenderSurface, key: Themes.lavenderKey, keyDark: Themes.lavenderKeyModifier, + keyText: Themes.lavenderLegend, signal: Themes.lavenderSignal, popupFill: Themes.lavenderPopup) static let mint = KeyboardPalette( id: "mint", name: "Mint", vibe: "The orb's green", - surface: Color(hex: 0x10231B), key: Color(hex: 0x1E3F31), keyDark: Color(hex: 0x183429), - keyText: Color(hex: 0xE9F5EE), signal: BlurtBrand.greenOnDark, popupFill: Color(hex: 0x1E3F31)) + surface: Themes.mintSurface, key: Themes.mintKey, keyDark: Themes.mintKeyModifier, + keyText: Themes.mintLegend, signal: Themes.mintSignal, popupFill: Themes.mintPopup) static let midnight = KeyboardPalette( id: "midnight", name: "Midnight", vibe: "Deep blue-black", - surface: Color(hex: 0x0E1220), key: Color(hex: 0x1D2440), keyDark: Color(hex: 0x161B33), - keyText: Color(hex: 0xE8ECFF), signal: BlurtBrand.greenOnDark, popupFill: Color(hex: 0x1D2440)) + surface: Themes.midnightSurface, key: Themes.midnightKey, keyDark: Themes.midnightKeyModifier, + keyText: Themes.midnightLegend, signal: Themes.midnightSignal, popupFill: Themes.midnightPopup) static let sunset = KeyboardPalette( id: "sunset", name: "Sunset", vibe: "Warm and loud", - surface: Color(hex: 0x2B1912), key: Color(hex: 0x4B2B20), keyDark: Color(hex: 0x3B2119), - keyText: Color(hex: 0xFFEFE6), signal: BlurtBrand.greenOnDark, popupFill: Color(hex: 0x4B2B20)) + surface: Themes.sunsetSurface, key: Themes.sunsetKey, keyDark: Themes.sunsetKeyModifier, + keyText: Themes.sunsetLegend, signal: Themes.sunsetSignal, popupFill: Themes.sunsetPopup) /// The picker's order: the iPhone's own first (shown in the picker's own /// appearance), then Blurt's. @@ -88,8 +90,9 @@ struct KeyboardPalette: Equatable, Identifiable { } extension Color { - /// `Color(hex: 0x1D1B16)`. - init(hex: UInt32) { + /// `Color(hex: 0x1D1B16)`. `nonisolated` so the generated `DesignTokens` + /// statics, which are nonisolated too, can call it. + nonisolated init(hex: UInt32) { self.init( red: Double((hex >> 16) & 0xFF) / 255, green: Double((hex >> 8) & 0xFF) / 255, blue: Double(hex & 0xFF) / 255) } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift index 16bdaec4..3a8d3497 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift @@ -55,7 +55,7 @@ final class KeyboardViewController: UIInputViewController { private func updateHeight(animated: Bool) { heightConstraint?.constant = model.effectiveLayout.height guard animated else { return } - UIView.animate(withDuration: 0.25) { self.view.superview?.layoutIfNeeded() } + UIView.animate(withDuration: DesignTokens.Motion.heightChange) { self.view.superview?.layoutIfNeeded() } } override func viewWillDisappear(_ animated: Bool) { diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift index 1eeb585e..aa6650f1 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift @@ -11,7 +11,7 @@ struct KeyboardRootView: View { /// The keyboard's top and bottom margin: the arithmetic in /// `KeyboardLayout.height` is built on it and the palette's row gap. - static let verticalMargin: CGFloat = 8 + static let verticalMargin = DesignTokens.Metrics.marginVertical var body: some View { Group { @@ -34,10 +34,12 @@ struct KeyboardRootView: View { .clipped() .environment(\.keyboardPalette, model.palette) .simultaneousGesture(swipe, including: model.layout == .panel ? .all : .subviews) - .animation(reduceMotion ? nil : .easeInOut(duration: 0.25), value: model.panelShowsKeys) + .animation(reduceMotion ? nil : .easeInOut(duration: DesignTokens.Motion.flip), value: model.panelShowsKeys) } - @Environment(\.accessibilityReduceMotion) private var reduceMotion + @Environment(\.accessibilityReduceMotion) private var systemReduceMotion + @Environment(\.keyboardMotionHeld) private var motionHeld + private var reduceMotion: Bool { systemReduceMotion || motionHeld } /// The carousel's slide: the incoming page arrives from the side the finger /// moved towards, the outgoing one leaves the other way. @@ -50,7 +52,7 @@ struct KeyboardRootView: View { /// A horizontal swipe anywhere on the panel flips it; taps and holds on keys /// never travel this far, and the keys ignore a touch that did. private var swipe: some Gesture { - DragGesture(minimumDistance: 24) + DragGesture(minimumDistance: DesignTokens.Metrics.gestureSwipeMin) .onEnded { value in let dx = value.translation.width guard abs(dx) > 48, abs(dx) > abs(value.translation.height) * 1.5 else { return } @@ -64,7 +66,7 @@ struct SlimBarView: View { var model: KeyboardModel var body: some View { - HStack(spacing: 8) { + HStack(spacing: DesignTokens.Metrics.slimSpacing) { if model.needsGlobe { KeyCap(systemImage: "globe", dark: true) { model.globe() } } VoiceBar(model: model) KeyCap(systemImage: "delete.left", dark: true) { model.deleteBackward() } @@ -79,9 +81,11 @@ struct PanelView: View { var model: KeyboardModel var body: some View { - VStack(spacing: 12) { + VStack(spacing: DesignTokens.Metrics.panelSpacing) { Spacer(minLength: 0) - MicKey(model: model, size: 96, wave: CGSize(width: 300, height: 40)) + MicKey( + model: model, size: DesignTokens.Metrics.orbPanel, + wave: CGSize(width: DesignTokens.Metrics.wavePanelWidth, height: DesignTokens.Metrics.wavePanelHeight)) Spacer(minLength: 0) HStack(spacing: KeyboardPalette.keyGap) { if model.needsGlobe { KeyCap(systemImage: "globe", dark: true) { model.globe() } } @@ -97,7 +101,7 @@ struct PanelView: View { .transition(.opacity) } } - .overlay(alignment: .topLeading) { AddTermKey(model: model).padding(6) } + .overlay(alignment: .topLeading) { AddTermKey(model: model).padding(DesignTokens.Metrics.addtermInset) } } } @@ -127,13 +131,15 @@ struct MicKey: View { /// answers a touch until the wave is up, then the wave's band does. var wave: CGSize? @State private var pressed = false - @Environment(\.accessibilityReduceMotion) private var reduceMotion + @Environment(\.accessibilityReduceMotion) private var systemReduceMotion + @Environment(\.keyboardMotionHeld) private var motionHeld @Environment(\.keyboardPalette) private var palette + private var reduceMotion: Bool { systemReduceMotion || motionHeld } /// The orb and the wave crossing, either way. - static let waveFade: Double = 0.7 + static let waveFade = DesignTokens.Motion.waveFade /// Every other change on the key: the ring, a glyph, the dimming. - static let stateFade: Double = 0.5 + static let stateFade = DesignTokens.Motion.stateFade var body: some View { ZStack { @@ -149,13 +155,15 @@ struct MicKey: View { .clipShape(Circle()) .overlay { ring } .frame(width: size, height: size) - .saturation(isReady ? 1 : 0.35) - .opacity(isReady ? 1 : 0.8) + .saturation(isReady ? 1 : DesignTokens.Metrics.opacityDimSaturation) + .opacity(isReady ? 1 : DesignTokens.Metrics.opacityDim) .transition(reduceMotion ? .opacity : .dissipate(size: size)) } if let glyph { Image(systemName: glyph) - .font(.system(size: size * 0.34, weight: .semibold)) + .font( + .system(size: size * DesignTokens.Typography.ratioOrbGlyph, weight: DesignTokens.Typography.weightOrbGlyph) + ) .foregroundStyle(.white) .transition(.opacity) } @@ -164,8 +172,8 @@ struct MicKey: View { .animation(.easeInOut(duration: Self.waveFade), value: isRecording) .animation(.easeInOut(duration: Self.stateFade), value: model.snapshot.state) .animation(.easeInOut(duration: Self.stateFade), value: isReady) - .scaleEffect(pressed ? 0.94 : 1) - .animation(.easeOut(duration: 0.1), value: pressed) + .scaleEffect(pressed ? DesignTokens.Metrics.pressScale : 1) + .animation(.easeOut(duration: DesignTokens.Motion.press), value: pressed) .contentShape(showsWave ? AnyShape(Capsule()) : AnyShape(Circle())) .accessibilityLabel(isReady ? (isRecording ? "Stop dictation" : "Dictate") : "Start Blurt") .accessibilityValue(model.snapshot.state == .error ? model.snapshot.message ?? "Dictation failed." : "") @@ -220,7 +228,7 @@ struct MicKey: View { /// while the mic comes up and while the words come; still, and solid green /// or orange, for a notice; still while recording. @ViewBuilder private var ring: some View { - let width: CGFloat = isWorking || isNotice ? 2 : 1 + let width = isWorking || isNotice ? DesignTokens.Metrics.ringActive : DesignTokens.Metrics.ringStill if isWorking, !isRecording, !reduceMotion { TimelineView(.animation(minimumInterval: keyboardAnimationInterval)) { timeline in Circle() @@ -301,7 +309,7 @@ struct KeyCap: View { var action: () -> Void @Environment(\.keyboardPalette) private var palette - static let height: CGFloat = 42 + static let height = DesignTokens.Metrics.keyHeight init( title: String? = nil, systemImage: String? = nil, tint: Color? = nil, flexible: Bool = false, @@ -325,12 +333,12 @@ struct KeyCap: View { Text(title ?? "") } } - .font(.system(size: 16, weight: .medium)) + .font(.system(size: DesignTokens.Typography.sizeLegend, weight: DesignTokens.Typography.weightLegend)) .foregroundStyle(tint ?? palette.keyText) .frame(maxWidth: flexible ? .infinity : nil) .frame(width: width) - .frame(minWidth: width == nil ? 44 : nil, minHeight: Self.height) - .padding(.horizontal, flexible || width != nil ? 0 : 4) + .frame(minWidth: width == nil ? DesignTokens.Metrics.keyMinWidth : nil, minHeight: Self.height) + .padding(.horizontal, flexible || width != nil ? 0 : DesignTokens.Metrics.keyPad) .keyCap(bare ? .clear : dark ? palette.keyDark : palette.key) .keyPress(action) .accessibilityLabel(title ?? systemImage ?? "") @@ -355,8 +363,8 @@ struct KeyPress: ViewModifier { func body(content: Content) -> some View { content - .brightness(pressed ? 0.15 : 0) - .animation(.easeOut(duration: 0.08), value: pressed) + .brightness(pressed ? DesignTokens.Metrics.opacityPressBrighten : 0) + .animation(.easeOut(duration: DesignTokens.Motion.keyPress), value: pressed) .contentShape(Rectangle()) .accessibilityAddTraits(.isButton) .simultaneousGesture( @@ -385,7 +393,7 @@ extension View { struct KeyPressStyle: ButtonStyle { func makeBody(configuration: Configuration) -> some View { configuration.label - .brightness(configuration.isPressed ? 0.15 : 0) - .animation(.easeOut(duration: 0.08), value: configuration.isPressed) + .brightness(configuration.isPressed ? DesignTokens.Metrics.opacityPressBrighten : 0) + .animation(.easeOut(duration: DesignTokens.Motion.keyPress), value: configuration.isPressed) } } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/MotionHeld.swift b/App/BlurtiOS/BlurtKeyboard/Sources/MotionHeld.swift new file mode 100644 index 00000000..ec7f5fa0 --- /dev/null +++ b/App/BlurtiOS/BlurtKeyboard/Sources/MotionHeld.swift @@ -0,0 +1,18 @@ +import SwiftUI + +/// Whether the keyboard's continuous motion — the ring's sweep, the meter's +/// idle wave, the orb's fluid and grain, the caret's blink — is held at time +/// zero. Reduce Motion holds it for the user; the gallery's +/// `-BlurtGalleryStill` holds it for a capture, so the same state is the same +/// pixels every time (DESIGN.md › Figma). The system value is read-only, so +/// this is the switch the views combine it with. +private struct KeyboardMotionHeldKey: EnvironmentKey { + static let defaultValue = false +} + +extension EnvironmentValues { + var keyboardMotionHeld: Bool { + get { self[KeyboardMotionHeldKey.self] } + set { self[KeyboardMotionHeldKey.self] = newValue } + } +} diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/PrismOrb.swift b/App/BlurtiOS/BlurtKeyboard/Sources/PrismOrb.swift index aa99cea7..3beb10ff 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/PrismOrb.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/PrismOrb.swift @@ -31,9 +31,9 @@ struct PrismOrb: View { /// The drop's life: up in 0.5 s, held to 0.9 s, gone by 2.4 s — an event, /// but a soft one. - static let dropDuration: TimeInterval = 2.4 - static let dropRise: TimeInterval = 0.5 - static let dropHold: TimeInterval = 0.9 + static let dropDuration: TimeInterval = DesignTokens.Motion.drop + static let dropRise: TimeInterval = DesignTokens.Motion.dropRise + static let dropHold: TimeInterval = DesignTokens.Motion.dropHold var body: some View { TimelineView(.animation(minimumInterval: keyboardAnimationInterval, paused: !animated)) { timeline in @@ -46,16 +46,17 @@ struct PrismOrb: View { // a flat swatch — airy, not glossy. Rectangle().fill( RadialGradient( - colors: [.white.opacity(0.3), .clear], center: UnitPoint(x: 0.3, y: 0.22), startRadius: 0, - endRadius: 110)) + colors: [.white.opacity(DesignTokens.Metrics.opacityOrbLight), .clear], + center: UnitPoint(x: DesignTokens.Metrics.orbLightX, y: DesignTokens.Metrics.orbLightY), startRadius: 0, + endRadius: DesignTokens.Metrics.orbLightRadius)) if drop > 0 { Drop(amount: drop, elapsed: elapsed) Sparkles(elapsed: elapsed) // invariant-ok: the orb's star glyphs, not the Sparkle updater } - Grain(seed: animated ? Int(time * 24) : 7).opacity(0.5).blendMode(.overlay) + Grain(seed: animated ? Int(time * 24) : 7).opacity(DesignTokens.Metrics.opacityGrain).blendMode(.overlay) } } - .animation(.easeInOut(duration: 0.8), value: mood) + .animation(.easeInOut(duration: DesignTokens.Motion.mood), value: mood) } /// How much violet is in the orb `elapsed` seconds after the words landed: @@ -120,13 +121,14 @@ struct PrismOrb: View { } } + /// The orb's colours, by the part they play; the values are the brand's. private enum Palette { - static let mist = Color(red: 0.86, green: 0.96, blue: 0.9) - static let lavender = Color(red: 215 / 255, green: 211 / 255, blue: 244 / 255) - static let periwinkle = Color(red: 176 / 255, green: 167 / 255, blue: 233 / 255) - static let violet = Color(red: 57 / 255, green: 35 / 255, blue: 199 / 255) - static let green = BlurtBrand.green - static let greenLight = BlurtBrand.greenOnDark + static let mist = DesignTokens.Brand.greenMist + static let lavender = DesignTokens.Brand.violetLavender + static let periwinkle = DesignTokens.Brand.violetPeriwinkle + static let violet = DesignTokens.Brand.cobolt + static let green = DesignTokens.Brand.green700 + static let greenLight = DesignTokens.Brand.green400 } /// The drop itself: a violet bloom that grows from the centre and thins as @@ -136,7 +138,7 @@ struct PrismOrb: View { let elapsed: TimeInterval var body: some View { - let spread = min(1, elapsed / 1.0) + let spread = min(1, elapsed / DesignTokens.Motion.dropSpread) Circle() .fill( RadialGradient( diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift index b3606819..8adb9ca6 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift @@ -11,7 +11,7 @@ import SwiftUI struct VoiceBar: View { var model: KeyboardModel - static let height: CGFloat = 44 + static let height = DesignTokens.Metrics.voicebarHeight var body: some View { GeometryReader { geo in @@ -22,8 +22,8 @@ struct VoiceBar: View { } else if !model.hasFullAccess { // The one state the orb can't show on its own: without Full Access // nothing here can work, and the user has to be told where to go. - HStack(spacing: 10) { - MicKey(model: model, size: 40, wave: nil) + HStack(spacing: DesignTokens.Metrics.voicebarNoteGap) { + MicKey(model: model, size: DesignTokens.Metrics.orbBar, wave: nil) Text("Allow Full Access in Settings → Keyboards") .font(.footnote) .foregroundStyle(BlurtBrand.errorOrange) @@ -32,9 +32,15 @@ struct VoiceBar: View { } .transition(.opacity) } else { - // The wave stays clear of the + at the trailing edge. - MicKey(model: model, size: 40, wave: CGSize(width: min(240, geo.size.width - 2 * (32 + 12)), height: 24)) - .transition(.opacity) + // The wave stays clear of the + at the trailing edge, on both sides so it stays centred. + let clearance = DesignTokens.Metrics.glyphHit + DesignTokens.Metrics.voicebarAddtermClearance + MicKey( + model: model, size: DesignTokens.Metrics.orbBar, + wave: CGSize( + width: min(DesignTokens.Metrics.waveBarWidth, geo.size.width - 2 * clearance), // literal-ok: both sides + height: DesignTokens.Metrics.waveBarHeight) + ) + .transition(.opacity) } } .frame(maxWidth: .infinity, maxHeight: .infinity) @@ -43,7 +49,7 @@ struct VoiceBar: View { .overlay(alignment: .trailing) { if model.termDraft == nil, model.hasFullAccess { AddTermKey(model: model) } } - .animation(.easeInOut(duration: 0.4), value: model.termDraft == nil) + .animation(.easeInOut(duration: DesignTokens.Motion.termSwap), value: model.termDraft == nil) } } @@ -59,16 +65,18 @@ struct AddTermKey: View { model.beginAddingTerm() } label: { Image(systemName: model.termSavedAt == nil ? "plus" : "checkmark") - .font(.system(size: 17, weight: .medium)) - .foregroundStyle(model.termSavedAt == nil ? palette.keyText.opacity(0.5) : palette.signal) - .frame(width: 32, height: 32) + .font(.system(size: DesignTokens.Typography.sizeGlyph, weight: DesignTokens.Typography.weightGlyph)) + .foregroundStyle( + model.termSavedAt == nil ? palette.keyText.opacity(DesignTokens.Metrics.opacityLegendMuted) : palette.signal + ) + .frame(width: DesignTokens.Metrics.glyphHit, height: DesignTokens.Metrics.glyphHit) .contentShape(Circle()) .contentTransition(.symbolEffect(.replace)) } .buttonStyle(KeyPressStyle()) .accessibilityLabel("Add a key term") .disabled(!model.hasFullAccess) - .opacity(model.hasFullAccess ? 1 : 0.4) + .opacity(model.hasFullAccess ? 1 : DesignTokens.Metrics.opacityDisabled) } } @@ -79,23 +87,23 @@ private struct TermField: View { @Environment(\.keyboardPalette) private var palette var body: some View { - HStack(spacing: 8) { - round("xmark", tint: palette.keyText.opacity(0.7)) { model.cancelAddingTerm() } + HStack(spacing: DesignTokens.Metrics.termGap) { + round("xmark", tint: palette.keyText.opacity(DesignTokens.Metrics.opacityTermCancel)) { model.cancelAddingTerm() } .accessibilityLabel("Cancel") HStack(spacing: 0) { if let draft = model.termDraft, !draft.isEmpty { Text(draft).foregroundStyle(palette.keyText) } else { - Text("New key term").foregroundStyle(palette.keyText.opacity(0.4)) + Text("New key term").foregroundStyle(palette.keyText.opacity(DesignTokens.Metrics.opacityPlaceholder)) } Caret() Spacer(minLength: 0) } - .font(.system(size: 17)) + .font(.system(size: DesignTokens.Typography.sizeTerm, weight: DesignTokens.Typography.weightTerm)) .lineLimit(1) - .padding(.horizontal, 14) + .padding(.horizontal, DesignTokens.Metrics.termPad) .frame(maxWidth: .infinity) - .frame(height: 36) + .frame(height: DesignTokens.Metrics.termHeight) .background(Capsule().fill(palette.keyDark)) .accessibilityElement(children: .ignore) .accessibilityLabel("Key term: \(model.termDraft ?? "")") @@ -103,34 +111,35 @@ private struct TermField: View { .accessibilityLabel("Save the key term") .disabled(model.termDraft?.trimmingCharacters(in: .whitespaces).isEmpty ?? true) } - .padding(.horizontal, 2) + .padding(.horizontal, DesignTokens.Metrics.termInset) } /// × and ✓: bare glyphs, as the + is. private func round(_ symbol: String, tint: Color, action: @escaping () -> Void) -> some View { Button(action: action) { Image(systemName: symbol) - .font(.system(size: 17, weight: .medium)) + .font(.system(size: DesignTokens.Typography.sizeGlyph, weight: DesignTokens.Typography.weightGlyph)) .foregroundStyle(tint) - .frame(width: 32, height: 32) + .frame(width: DesignTokens.Metrics.glyphHit, height: DesignTokens.Metrics.glyphHit) .contentShape(Circle()) } .buttonStyle(KeyPressStyle()) } } -/// A blinking caret, as a text field's. +/// A blinking caret, as a text field's; held on while motion is held. private struct Caret: View { @Environment(\.keyboardPalette) private var palette + @Environment(\.keyboardMotionHeld) private var motionHeld var body: some View { - TimelineView(.periodic(from: .now, by: 0.5)) { timeline in - let on = Int(timeline.date.timeIntervalSinceReferenceDate * 2) % 2 == 0 - RoundedRectangle(cornerRadius: 1) + TimelineView(.periodic(from: .now, by: DesignTokens.Motion.caret)) { timeline in + let on = motionHeld || Int(timeline.date.timeIntervalSinceReferenceDate / DesignTokens.Motion.caret) % 2 == 0 + RoundedRectangle(cornerRadius: DesignTokens.Metrics.caretRadius) .fill(palette.signal) - .frame(width: 2, height: 20) + .frame(width: DesignTokens.Metrics.caretWidth, height: DesignTokens.Metrics.caretHeight) .opacity(on ? 1 : 0) - .padding(.leading, 1) + .padding(.leading, DesignTokens.Metrics.caretLead) } .accessibilityHidden(true) } @@ -151,8 +160,8 @@ struct WaveformMeter: View { var barSpacing: CGFloat = MeterBarGeometry.barSpacing /// The keyboard's pitch: 2 pt bars, 2 pt apart. - static let slimBar: CGFloat = 2 - static let slimGap: CGFloat = 2 + static let slimBar = DesignTokens.Metrics.waveBar + static let slimGap = DesignTokens.Metrics.waveGap var body: some View { GeometryReader { geo in diff --git a/App/BlurtiOS/BlurtiOS/Sources/BlurtBrand+App.swift b/App/BlurtiOS/BlurtiOS/Sources/BlurtBrand+App.swift index 13f78738..c8d40536 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/BlurtBrand+App.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/BlurtBrand+App.swift @@ -17,15 +17,17 @@ extension BlurtBrand { extension View { /// The design's card: warm fill, 16 pt corners, a hairline border. func card() -> some View { - background(BlurtBrand.cardFill, in: RoundedRectangle(cornerRadius: 16)) - .overlay(RoundedRectangle(cornerRadius: 16).strokeBorder(BlurtBrand.cardBorder, lineWidth: 1)) + background(BlurtBrand.cardFill, in: RoundedRectangle(cornerRadius: DesignTokens.Metrics.cardRadius)) + .overlay( + RoundedRectangle(cornerRadius: DesignTokens.Metrics.cardRadius) + .strokeBorder(BlurtBrand.cardBorder, lineWidth: DesignTokens.Metrics.cardBorder)) } } /// The lowercase wordmark from the Mac's ready screen, tinted with the accent /// (`blurt-ready-logo.png`, shared from `App/Blurt/Blurt/Branding`). struct Wordmark: View { - private static let height: CGFloat = 22 + private static let height = DesignTokens.Metrics.wordmarkHeight var body: some View { if let image = UIImage(named: "blurt-ready-logo") { diff --git a/App/BlurtiOS/BlurtiOS/Sources/BlurtiOSApp.swift b/App/BlurtiOS/BlurtiOS/Sources/BlurtiOSApp.swift index 9feafcfc..f56384fd 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/BlurtiOSApp.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/BlurtiOSApp.swift @@ -39,10 +39,12 @@ struct BlurtiOSApp: App { WindowGroup { #if DEBUG let rows = KeyboardGalleryView.rows(from: CommandLine.arguments) - if rows.isEmpty { + if let orb = KeyboardGalleryView.OrbStillView.parse(CommandLine.arguments) { + orb + } else if rows.isEmpty { home } else { - KeyboardGalleryView(rows: rows) + KeyboardGalleryView(rows: rows, options: .parse(CommandLine.arguments)) } #else home diff --git a/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift b/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift index eb1621a1..66fe8ec1 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift @@ -86,10 +86,10 @@ struct HomeView: View { // MARK: - The orb and the listening state - private static let orbSize: CGFloat = 112 + private static let orbSize = DesignTokens.Metrics.orbHome /// The wave at hero size: wide and slim, inside the card at any phone width. - private static let waveReach: CGFloat = 280 - private static let waveHeight: CGFloat = 44 + private static let waveReach = DesignTokens.Metrics.waveHomeWidth + private static let waveHeight = DesignTokens.Metrics.waveHomeHeight private var isRecording: Bool { coordinator.phase == .recording } private var orbWorking: Bool { coordinator.window.isOpen || coordinator.phase.isCapturing } @@ -110,7 +110,7 @@ struct HomeView: View { .frame(width: Self.orbSize, height: Self.orbSize) .clipShape(Circle()) .overlay { HeroRing(animated: orbWorking && !reduceMotion) } - .saturation(coordinator.window.isOpen ? 1 : 0.45) + .saturation(coordinator.window.isOpen ? 1 : DesignTokens.Metrics.opacityHomeDimSaturation) .transition(reduceMotion ? .opacity : .dissipate(size: Self.orbSize)) } } @@ -330,14 +330,14 @@ private struct HeroRing: View { if animated { TimelineView(.animation(minimumInterval: keyboardAnimationInterval)) { timeline in Circle() - .strokeBorder(BlurtBrand.orbRingGradient, lineWidth: 2) + .strokeBorder(BlurtBrand.orbRingGradient, lineWidth: DesignTokens.Metrics.ringActive) .rotationEffect( .degrees( MeterBarGeometry.rotationDegrees( time: timeline.date.timeIntervalSinceReferenceDate, period: BrandOrb.period))) } } else { - Circle().strokeBorder(BlurtBrand.orbRingGradient, lineWidth: 2) + Circle().strokeBorder(BlurtBrand.orbRingGradient, lineWidth: DesignTokens.Metrics.ringActive) } } } diff --git a/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift b/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift index 5aaa2cad..04976840 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift @@ -5,11 +5,17 @@ /// reference, and the way a screenshot of the keyboard is taken without /// tapping through Notes. Debug builds only, reached by launch argument: /// - /// -BlurtGallery [,…] [theme] + /// -BlurtGallery [,…] [theme] [-BlurtGalleryStill] [-BlurtGalleryBare] /// /// The last word is a theme id (`system`, `system-dark`, `ink`, `paper`, /// `lavender`, `mint`, `midnight`, `sunset`); the iPhone's light face when - /// left out. + /// left out. Two switches make a capture reproducible for the design loop + /// (DESIGN.md › Figma): `-BlurtGalleryStill` holds every motion at time + /// zero — the ring, the meter's wave, the orb's fluid and grain — so two + /// captures of one state are the same pixels; `-BlurtGalleryBare` draws the + /// first row alone, no caption, inside a 2 pt `#FF00FF` registration border + /// that `scripts/design-diff.swift crop` cuts to. `-BlurtOrb ` + /// renders one orb fill by itself the same way, for Figma's image fills. /// where a state is `off` (no Full Access), `start` (app not listening), /// `idle`, `connecting`, `recording`, `processing`, `pasted`, `copied`, /// `error`, `landed` (the drop, timed for a screenshot) or `live` (a whole @@ -29,23 +35,63 @@ let model: KeyboardModel } + /// The capture switches, read from the launch arguments. + struct Options: Equatable { + /// Hold every motion at time zero, as Reduce Motion does, so a capture + /// is the same pixels every time. + var still = false + /// One row, no caption, a registration border round the keyboard. + var bare = false + + static func parse(_ arguments: [String]) -> Options { + Options(still: arguments.contains("-BlurtGalleryStill"), bare: arguments.contains("-BlurtGalleryBare")) + } + } + let rows: [Row] + var options = Options() + + /// The registration colour and width `scripts/design-diff.swift crop` looks + /// for. Drawn outside the keyboard's frame, so what is inside the border + /// is exactly the keyboard's pixels — above and below only, so the + /// keyboard keeps the phone's full width (the crop reads a missing side + /// border as "the edge of the screen"). + static let registration = Color(red: 1, green: 0, blue: 1) + static let registrationWidth: CGFloat = 2 var body: some View { - ScrollView { - VStack(alignment: .leading, spacing: 16) { - ForEach(rows) { row in - VStack(alignment: .leading, spacing: 4) { - Text(row.caption).font(.caption.weight(.medium)).foregroundStyle(.secondary).padding(.horizontal) - KeyboardRootView(model: row.model) - .frame(height: row.model.effectiveLayout.height) - .clipped() + if options.bare, let row = rows.first { + VStack { + Spacer(minLength: 0) + keyboard(row) + .padding(.vertical, Self.registrationWidth) + .background(Self.registration) + Spacer(minLength: 0) + } + .frame(maxWidth: .infinity, maxHeight: .infinity) + .background(Color(uiColor: .systemBackground)) + .ignoresSafeArea() + } else { + ScrollView { + VStack(alignment: .leading, spacing: 16) { + ForEach(rows) { row in + VStack(alignment: .leading, spacing: 4) { + Text(row.caption).font(.caption.weight(.medium)).foregroundStyle(.secondary).padding(.horizontal) + keyboard(row) + } } } + .padding(.vertical, 12) } - .padding(.vertical, 12) + .background(Color(uiColor: .systemBackground)) } - .background(Color(uiColor: .systemBackground)) + } + + private func keyboard(_ row: Row) -> some View { + KeyboardRootView(model: row.model) + .frame(height: row.model.effectiveLayout.height) + .clipped() + .environment(\.keyboardMotionHeld, options.still) } /// The rows named by the launch arguments; empty when they don't ask for @@ -54,7 +100,8 @@ guard let flag = arguments.firstIndex(of: "-BlurtGallery"), arguments.count > flag + 2, let layout = KeyboardLayout(rawValue: arguments[flag + 1]) else { return [] } - let theme = arguments.count > flag + 3 ? arguments[flag + 3] : "system" + // The theme is the next word unless it is a switch. + let theme = arguments.count > flag + 3 && !arguments[flag + 3].hasPrefix("-") ? arguments[flag + 3] : "system" return arguments[flag + 2].split(separator: ",").map { name in Row( caption: "\(layout.rawValue) · \(name) · \(theme)", @@ -125,5 +172,45 @@ } } } + + /// `-BlurtOrb `: one orb fill, + /// still, on the ink surface, inside the registration border — the image + /// Figma's `Orb/Disc` component uses, since a mesh gradient under grain is + /// nothing Figma can draw natively (DESIGN.md › Figma). `landed` is the + /// drop at its peak; `listening` is the gallery's level, 0.62. + struct OrbStillView: View { + let size: CGFloat + let mood: PrismOrb.Mood + let landedAt: Date? + + var body: some View { + VStack { + Spacer(minLength: 0) + PrismOrb(mood: mood, landedAt: landedAt, animated: false) + .frame(width: size, height: size) + .clipShape(Circle()) + .padding(KeyboardGalleryView.registrationWidth) + .background(KeyboardGalleryView.registration) + Spacer(minLength: 0) + } + .frame(maxWidth: .infinity, maxHeight: .infinity) + .background(DesignTokens.Brand.ink) + .ignoresSafeArea() + } + + static func parse(_ arguments: [String]) -> OrbStillView? { + guard let flag = arguments.firstIndex(of: "-BlurtOrb"), arguments.count > flag + 2, + let size = Double(arguments[flag + 1]) + else { return nil } + switch arguments[flag + 2] { + case "off": return OrbStillView(size: size, mood: .off, landedAt: nil) + case "idle": return OrbStillView(size: size, mood: .idle, landedAt: nil) + case "listening": return OrbStillView(size: size, mood: .listening(level: 0.62), landedAt: nil) + case "working": return OrbStillView(size: size, mood: .working, landedAt: nil) + case "landed": return OrbStillView(size: size, mood: .idle, landedAt: Date().addingTimeInterval(-0.6)) + default: return nil + } + } + } } #endif diff --git a/App/BlurtiOS/BlurtiOS/Sources/ThemePickerView.swift b/App/BlurtiOS/BlurtiOS/Sources/ThemePickerView.swift index ea7495eb..a3f58c02 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/ThemePickerView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/ThemePickerView.swift @@ -39,8 +39,8 @@ private struct ThemeCard: View { /// The preview keyboard is the full layout, drawn at a phone's width and /// scaled down to fit two cards across. - private static let previewWidth: CGFloat = 393 - private static let scale: CGFloat = 0.42 + private static let previewWidth = DesignTokens.Metrics.pickerPreviewWidth + private static let scale = DesignTokens.Metrics.pickerScale var body: some View { Button(action: pick) { @@ -49,7 +49,7 @@ private struct ThemeCard: View { .frame(width: Self.previewWidth, height: KeyboardLayout.full.height) .scaleEffect(Self.scale, anchor: .topLeading) .frame(width: Self.previewWidth * Self.scale, height: KeyboardLayout.full.height * Self.scale) - .clipShape(RoundedRectangle(cornerRadius: 10)) + .clipShape(RoundedRectangle(cornerRadius: DesignTokens.Metrics.pickerRadius)) .allowsHitTesting(false) VStack(alignment: .leading, spacing: 2) { Text(palette.name).font(.headline) @@ -60,7 +60,8 @@ private struct ThemeCard: View { .frame(maxWidth: .infinity, alignment: .leading) .card() .overlay( - RoundedRectangle(cornerRadius: 16).strokeBorder(chosen ? BlurtBrand.accent : Color.clear, lineWidth: 2)) + RoundedRectangle(cornerRadius: DesignTokens.Metrics.cardRadius) + .strokeBorder(chosen ? BlurtBrand.accent : Color.clear, lineWidth: 2)) } .buttonStyle(.plain) .accessibilityLabel(palette.name) diff --git a/App/BlurtiOS/BlurtiOSTests/DesignTokensTests.swift b/App/BlurtiOS/BlurtiOSTests/DesignTokensTests.swift new file mode 100644 index 00000000..19295da0 --- /dev/null +++ b/App/BlurtiOS/BlurtiOSTests/DesignTokensTests.swift @@ -0,0 +1,184 @@ +import Foundation +import SwiftUI +import Testing + +@testable import BlurtiOS + +/// The compiled tokens against the file they were generated from. check.sh's +/// `design-sync.sh --check` catches drift in the tree; this catches it in the +/// binary, so a hand edit to `DesignTokens.swift` that slipped past both the +/// header and the check still fails somewhere. +@Suite("Design tokens") +struct DesignTokensTests { + private final class BundleToken {} + + private static func tokensJSON() throws -> [String: Any] { + let url = try #require(Bundle(for: BundleToken.self).url(forResource: "tokens", withExtension: "json")) + return try #require(JSONSerialization.jsonObject(with: Data(contentsOf: url)) as? [String: Any]) + } + + /// A number the way scripts/design-tokens.swift prints it: `42`, `0.7`. + private static func format(_ number: Double) -> String { + number == number.rounded() ? String(Int(number)) : String(number) + } + + /// tokens.json flattened to `group.name: value`, aliases followed — the same + /// rendering the generator writes into `DesignTokens.manifest`. + private static func expectedManifest() throws -> [String: String] { + let json = try tokensJSON() + let groups = ["brand", "themes", "keyboard", "metrics", "type", "motion"] + var raw: [String: Any] = [:] + for group in groups { + let entries = try #require(json[group] as? [String: Any]) + for (name, entry) in entries { + raw["\(group).\(name)"] = (entry as? [String: Any])?["value"] ?? entry + } + } + func render(_ qualified: String, depth: Int = 0) throws -> String { + let value = try #require(raw[qualified], "\(qualified) is not a token") + try #require(depth < 8, "alias cycle at \(qualified)") + if let number = value as? NSNumber { return format(number.doubleValue) } + let string = try #require(value as? String) + if string.hasPrefix("{"), string.hasSuffix("}") { + return try render(String(string.dropFirst().dropLast()), depth: depth + 1) + } + return string.hasPrefix("#") ? string.uppercased() : string + } + var manifest: [String: String] = [:] + for qualified in raw.keys { manifest[qualified] = try render(qualified) } + let gradients = try #require(json["gradients"] as? [String: Any]) + for (name, entry) in gradients { + let gradient = try #require(entry as? [String: Any]) + let stops = try #require(gradient["stops"] as? [[String: Any]]) + let rendered = try stops.map { stop -> String in + let color = try #require(stop["color"] as? String) + let location = try #require(stop["location"] as? NSNumber) + let hex = + color.hasPrefix("{") ? try render(String(color.dropFirst().dropLast())) : color.uppercased() + return "\(hex)@\(format(location.doubleValue))" + } + let start = try #require(gradient["start"] as? String) + let end = try #require(gradient["end"] as? String) + manifest["gradients.\(name)"] = "\(rendered.joined(separator: " ")) \(start)>\(end)" + } + return manifest + } + + @Test("every compiled token equals tokens.json (run scripts/design-sync.sh)") + func manifest() throws { + let expected = try Self.expectedManifest() + let compiled = DesignTokens.manifest + let missing = Set(expected.keys).subtracting(compiled.keys).sorted() + let extra = Set(compiled.keys).subtracting(expected.keys).sorted() + let changed = expected.keys.filter { compiled[$0] != nil && compiled[$0] != expected[$0] }.sorted() + #expect(missing.isEmpty, "tokens in tokens.json but not compiled: \(missing)") + #expect(extra.isEmpty, "tokens compiled but not in tokens.json: \(extra)") + #expect( + changed.isEmpty, + "tokens whose value differs: \(changed.map { "\($0): \(compiled[$0] ?? "?") vs \(expected[$0] ?? "?")" })") + } + + @Test("the layout heights are the rows at the token spacing, and the layout/* tokens agree") + func heights() { + let metrics = DesignTokens.Metrics.self + #expect(KeyboardLayout.slimBar.height == 2 * metrics.marginVertical + metrics.voicebarHeight) + #expect(KeyboardLayout.slimBar.height == metrics.layoutSlim) + #expect(KeyboardLayout.panel.height == metrics.layoutPanel) + #expect( + KeyboardLayout.full.height + == 2 * metrics.marginVertical + metrics.voicebarHeight + 4 * metrics.rowGap + 4 * metrics.keyHeight) + #expect(KeyboardLayout.full.height == metrics.layoutFull) + } + + @Test("the full layout at 402 pt matches the @402 tokens the Figma frames are drawn with") + func fullLayoutAt402() { + let width: CGFloat = 402 + let gap = DesignTokens.Metrics.keyGap + // The same arithmetic as FullKeyboardView. + let keyWidth = (width - 9 * gap) / 10 + let sideGap = gap * DesignTokens.Metrics.keySideGapFactor + let sideWidth = (width - 7 * keyWidth - 6 * gap - 2 * sideGap) / 2 + #expect(abs(keyWidth - DesignTokens.Metrics.keyLetterWidth402) < 0.001) + #expect(abs(sideWidth - DesignTokens.Metrics.keySideWidth402) < 0.001) + #expect(abs(sideWidth * 2 + gap - DesignTokens.Metrics.keyReturnWidth402) < 0.001) + } + + /// Each palette beside the six theme tokens it must equal, in role order: + /// surface, key, modifier, legend, signal, pop-up. + private static let paletteTokens: [(KeyboardPalette, [Color])] = { + typealias Themes = DesignTokens.Themes + return [ + ( + .systemLight, + [ + Themes.systemLightSurface, Themes.systemLightKey, Themes.systemLightKeyModifier, Themes.systemLightLegend, + Themes.systemLightSignal, Themes.systemLightPopup, + ] + ), + ( + .systemDark, + [ + Themes.systemDarkSurface, Themes.systemDarkKey, Themes.systemDarkKeyModifier, Themes.systemDarkLegend, + Themes.systemDarkSignal, Themes.systemDarkPopup, + ] + ), + ( + .ink, + [Themes.inkSurface, Themes.inkKey, Themes.inkKeyModifier, Themes.inkLegend, Themes.inkSignal, Themes.inkPopup] + ), + ( + .paper, + [ + Themes.paperSurface, Themes.paperKey, Themes.paperKeyModifier, Themes.paperLegend, Themes.paperSignal, + Themes.paperPopup, + ] + ), + ( + .lavender, + [ + Themes.lavenderSurface, Themes.lavenderKey, Themes.lavenderKeyModifier, Themes.lavenderLegend, + Themes.lavenderSignal, Themes.lavenderPopup, + ] + ), + ( + .mint, + [ + Themes.mintSurface, Themes.mintKey, Themes.mintKeyModifier, Themes.mintLegend, Themes.mintSignal, + Themes.mintPopup, + ] + ), + ( + .midnight, + [ + Themes.midnightSurface, Themes.midnightKey, Themes.midnightKeyModifier, Themes.midnightLegend, + Themes.midnightSignal, Themes.midnightPopup, + ] + ), + ( + .sunset, + [ + Themes.sunsetSurface, Themes.sunsetKey, Themes.sunsetKeyModifier, Themes.sunsetLegend, Themes.sunsetSignal, + Themes.sunsetPopup, + ] + ), + ] + }() + + @Test("every palette is its theme's tokens, role by role") + func palettes() { + #expect(Self.paletteTokens.count == KeyboardPalette.all.count + 1) + for (palette, colors) in Self.paletteTokens { + let roles = [palette.surface, palette.key, palette.keyDark, palette.keyText, palette.signal, palette.popupFill] + #expect(roles == colors, "\(palette.id)") + } + } + + @Test("the drop is up at drop-rise, held to drop-hold, gone at drop") + func drop() { + #expect(PrismOrb.dropAmount(at: 0) == 0) + #expect(PrismOrb.dropAmount(at: DesignTokens.Motion.dropRise) == 1) + #expect(PrismOrb.dropAmount(at: DesignTokens.Motion.dropHold) == 1) + #expect(PrismOrb.dropAmount(at: DesignTokens.Motion.drop) == 0) + #expect(PrismOrb.dropAmount(at: -1) == 0) + } +} diff --git a/App/BlurtiOS/BlurtiOSTests/FeedAndLayoutTests.swift b/App/BlurtiOS/BlurtiOSTests/FeedAndLayoutTests.swift index e88d492d..3e1a9862 100644 --- a/App/BlurtiOS/BlurtiOSTests/FeedAndLayoutTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/FeedAndLayoutTests.swift @@ -56,6 +56,20 @@ struct LayoutArithmeticTests { #expect(rows[2].model.termDraft == "Rizz") #expect(rows[0].model.palette.id == "mint") let dark = KeyboardGalleryView.rows(from: ["app", "-BlurtGallery", "full", "idle", "system-dark"]) - #expect(dark[0].model.palette.keyText == .white) + #expect(dark[0].model.palette.keyText == DesignTokens.Brand.white) + } + + @Test("the capture switches ride along, and a switch where the theme would be is not a theme") + func galleryOptions() { + let args = ["app", "-BlurtGallery", "panel", "idle", "-BlurtGalleryStill", "-BlurtGalleryBare"] + #expect(KeyboardGalleryView.rows(from: args)[0].model.palette.id == "system") + #expect(KeyboardGalleryView.Options.parse(args) == .init(still: true, bare: true)) + #expect(KeyboardGalleryView.Options.parse(["app", "-BlurtGallery", "panel", "idle", "ink"]) == .init()) + #expect(KeyboardGalleryView.OrbStillView.parse(args) == nil) + let orb = KeyboardGalleryView.OrbStillView.parse(["app", "-BlurtOrb", "96", "landed"]) + #expect(orb?.size == 96) + #expect(orb?.landedAt != nil) + #expect(KeyboardGalleryView.OrbStillView.parse(["app", "-BlurtOrb", "96", "nope"]) == nil) + #expect(KeyboardGalleryView.OrbStillView.parse(["app", "-BlurtOrb", "big", "idle"]) == nil) } } diff --git a/App/BlurtiOS/BlurtiOSTests/SharedStateTests.swift b/App/BlurtiOS/BlurtiOSTests/SharedStateTests.swift index ebc26d44..151d7a49 100644 --- a/App/BlurtiOS/BlurtiOSTests/SharedStateTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/SharedStateTests.swift @@ -82,8 +82,8 @@ struct LayoutTests { let ids = KeyboardPalette.all.map(\.id) #expect(Set(ids).count == ids.count) #expect(KeyboardPalette.resolve("lavender", dark: true).id == "lavender") - #expect(KeyboardPalette.resolve("system", dark: false).keyText == .black) - #expect(KeyboardPalette.resolve("system", dark: true).keyText == .white) + #expect(KeyboardPalette.resolve("system", dark: false).keyText == DesignTokens.Brand.black) + #expect(KeyboardPalette.resolve("system", dark: true).keyText == DesignTokens.Brand.white) #expect(KeyboardPalette.resolve("nope", dark: false).id == "system") } } diff --git a/App/BlurtiOS/DESIGN.md b/App/BlurtiOS/DESIGN.md index 0ce0cd99..4abbfa26 100644 --- a/App/BlurtiOS/DESIGN.md +++ b/App/BlurtiOS/DESIGN.md @@ -13,6 +13,16 @@ Source of truth on the Mac side: `App/Blurt/Blurt/Branding/BlurtBrand.swift` The phone reads the meter and the ring's rotation straight from the engine, so they cannot drift from the Mac's. +On the phone, every colour and number the views draw with lives once, in +`Design/tokens.json`, and is fanned out from there: `Shared/DesignTokens.swift` +(what the views read), the tables in this file marked `tokens:begin` / +`tokens:end`, and the app's three asset-catalog colour sets are all generated +by `scripts/design-tokens.swift`. Edit the JSON (or export it from Figma, see +below), run `scripts/design-sync.sh`, commit; `scripts/check.sh` runs +`design-sync.sh --check` and fails on drift. The views carry no design +literals — the same script lints them — so a number that changes in Figma +changes everywhere or nowhere. + ## Reproducing it Every layout and state renders inside the app, from a launch argument, so a @@ -34,6 +44,54 @@ of the keyboard's own: `keys` (the panel flipped to its keyboard page) and gallery is `BlurtiOS/Sources/KeyboardGalleryView.swift`, debug builds only; the keyboard's sources are compiled into the app for it (`project.yml`). +For the design loop the capture has to be the same pixels every time, and it +has to be the keyboard's pixels alone. Two switches do that: +`-BlurtGalleryStill` holds every motion at time zero (the ring, the meter's +wave, the orb's fluid and its grain — what Reduce Motion does) and +`-BlurtGalleryBare` draws the first row by itself inside a 2 pt `#FF00FF` +registration border. `-BlurtOrb ` +renders one orb fill the same way, for Figma's image fills. The scripts on +top: + +```bash +scripts/design-capture.sh --layout panel --states idle,recording,error,term --themes system,system-dark,ink + # builds once, captures each still, crops it → .build/design/captures/--@3x.png +scripts/ios-record.sh --layout panel --theme ink --frames 0,0.35,0.7 + # one 11.7 s loop of the `live` walk, cropped, plus stills at those seconds +swift scripts/design-diff.swift diff figma.png sim.png --out triptych.png --json metrics.json --mask x,y,w,h + # both to sRGB, then AE (pixels over the threshold) and RMSE, outside the masks and per mask +swift scripts/design-diff.swift sheet --out sheet.png --columns 4 "panel · idle · ink=a.png" … +scripts/design-sync.sh # tokens.json → DesignTokens.swift, these tables, the colour sets +scripts/design-sync.sh --check # what check.sh runs: drift and design literals +``` + +`ios-sim.sh --no-build` reuses the last build, so a loop of forty captures +builds once. The capture device is the iPhone 18 Pro (402 pt → 1206 px at 3×, +the Figma frames' width), pinned in `scripts/ios-sim.sh`; a crop that is not +the layout's height × the scale fails rather than being resampled. + +## Figma + +The keyboard is designed in Figma and built from the export. The file is +**Blurt Keyboard** (Neil's personal Figma space until the design moves into the +AssemblyAI org; key and approved version in `Design/tokens.json` › `figma`), +three pages: `01 Foundations` (the variables below as six collections, text and +effect styles, specimens), `02 Components` (Key, LetterPopup, Orb, MicKey, +WaveformMeter, TermField, AddTermKey, CancelKey, VoiceBar), `03 Layouts` (the +three layouts at 402 pt — iPhone 18 Pro, the simulator this repo captures on — +as state rows named `//` exactly as the gallery captions +them, an Apple-keyboard reference overlay, redlines, the motion table, and the +review boards). The file is rebuilt from the scripts in `Design/figma/`, so the +scripts, not the file, are the durable record. + +The loop: design and approve in Figma (a named version) → export the variables +to `Design/tokens.json` → `scripts/design-sync.sh` → the views → captures from +the gallery compared against the Figma exports. The orb is the one exception +that goes the other way: `MeshGradient` plus grain cannot be drawn natively in +Figma, so the app renders deterministic stills that Figma uses as image fills, +and Figma holds the parameters (`orb/*`, `opacity/orb-light`, `opacity/grain`, +the drop timings). + ## Prototype on this branch: the prism orb (`PrismOrb.swift`) The brand artwork — a green beam into the prism, a violet, starlit one out — @@ -82,17 +140,24 @@ Partiful-style — pick from live previews in Settings → Keyboard → Theme; t keyboard picks it up the next time it comes up (`keyboardTheme` in the App Group): -| Theme | Surface | Key | Modifier | Legend | Vibe | -| ---------- | --------------------- | ----------------- | --------------------- | ------------- | ------------------------------------------- | -| `system` | `#D1D5DB` / `#2B2B2B` | white / `#6B6B6B` | `#ADB3BC` / `#464646` | black / white | the iPhone keyboard, light / dark (default) | -| `ink` | `#1D1B16` | `#33302A` | `#26231E` | `#F2EEE6` | Blurt's own | -| `paper` | `#EBE8E8` | white | `#DEDBDB` | `#1D1B16` | warm and light | -| `lavender` | `#2C2557` | `#3F3777` | `#352E68` | `#F1EEFF` | the orb's violet | -| `mint` | `#10231B` | `#1E3F31` | `#183429` | `#E9F5EE` | the orb's green | -| `midnight` | `#0E1220` | `#1D2440` | `#161B33` | `#E8ECFF` | deep blue-black | -| `sunset` | `#2B1912` | `#4B2B20` | `#3B2119` | `#FFEFE6` | warm and loud | - -The orb and the ring are the same in every theme; the wave takes the + + +| Theme | Surface | Key | Modifier | Legend | Signal | Pop-up | +| -------------- | --------- | --------- | --------- | --------- | --------- | --------- | +| `system-light` | `#D1D5DB` | `#FFFFFF` | `#ADB3BC` | `#000000` | `#01762F` | `#FFFFFF` | +| `system-dark` | `#2B2B2B` | `#6B6B6B` | `#464646` | `#FFFFFF` | `#67AD82` | `#6B6B6B` | +| `ink` | `#1D1B16` | `#33302A` | `#26231E` | `#F2EEE6` | `#67AD82` | `#33302A` | +| `paper` | `#EBE8E8` | `#FFFFFF` | `#DEDBDB` | `#1D1B16` | `#01762F` | `#FFFFFF` | +| `lavender` | `#2C2557` | `#3F3777` | `#352E68` | `#F1EEFF` | `#67AD82` | `#3F3777` | +| `mint` | `#10231B` | `#1E3F31` | `#183429` | `#E9F5EE` | `#67AD82` | `#1E3F31` | +| `midnight` | `#0E1220` | `#1D2440` | `#161B33` | `#E8ECFF` | `#67AD82` | `#1D2440` | +| `sunset` | `#2B1912` | `#4B2B20` | `#3B2119` | `#FFEFE6` | `#67AD82` | `#4B2B20` | + + + +The picker's one-liners (the vibes) live with the palettes in +`KeyboardPalette.swift`; the colours are the tokens above. The orb and the ring +are the same in every theme; the wave takes the palette's `signal` green — the wordmark's on the light surfaces, the lifted one on the dark. The picker (`ThemePickerView`) draws the real full keyboard at 0.42 scale on each card, the iPhone theme in the picker's own appearance. The gallery's @@ -175,19 +240,81 @@ with a dictation it started, it releases a recording (the words still land, on the clipboard if no keyboard is there) and cancels anything earlier, so nothing records on without it. -## Tokens (`Shared/BlurtBrand.swift`) - -| Token | Value | Use | -| ----------------- | ----------- | ----------------------------------------------------------- | -| `green` | `#01762F` | the wordmark green, light chrome (the app's accent) | -| `greenOnDark` | `#67AD82` | the meter, the ring, anything green on ink | -| `ink` | `#1D1B16` | the Mac pill's body; the keyboard's surface | -| `errorOrange` | `#E67F36` | the error word — never a red body | -| `key` | `#33302A` | an ordinary key on the ink surface (one step up) | -| `keyDark` | `#26231E` | modifier keys: shift, delete, globe, return, 123, cancel | -| `keyText` | `#F2EEE6` | key legends: warm white on warm ink | -| `orbGradient` | 8 stops | the design's own (`App elements/Recording.svg`), bottom→top | -| `orbRingGradient` | green→white | the ring, top-leading to bottom-trailing | +## Tokens (`Design/tokens.json` → `Shared/DesignTokens.swift`) + +The brand's colours, as the Mac defines them and as the phone extends them. +`BlurtBrand` keeps its names (`green`, `greenOnDark`, `ink`, …) as aliases of +these, so the Mac's vocabulary still reads at the call sites. + + + +| Token | Value | Swift | Use | +| ---------------------- | --------- | -------------------------- | -------------------------------------------------------------------------- | +| `apple/dark-key` | `#6B6B6B` | `Brand.appleDarkKey` | the iPhone keyboard's dark key | +| `apple/dark-modifier` | `#464646` | `Brand.appleDarkModifier` | the iPhone keyboard's dark modifier key | +| `apple/dark-surface` | `#2B2B2B` | `Brand.appleDarkSurface` | the iPhone keyboard's dark surface | +| `apple/light-modifier` | `#ADB3BC` | `Brand.appleLightModifier` | the iPhone keyboard's light modifier key | +| `apple/light-surface` | `#D1D5DB` | `Brand.appleLightSurface` | the iPhone keyboard's light surface | +| `black` | `#000000` | `Brand.black` | — | +| `card` | `#EBE8E8` | `Brand.card` | the warm card fill; the paper theme's surface | +| `card-border` | `#DEDBDB` | `Brand.cardBorder` | the card's hairline; the paper theme's modifier key | +| `cobolt` | `#3923C7` | `Brand.cobolt` | AssemblyAI's primary violet: the drop, never a key or a surface | +| `green/100` | `#CCE4D5` | `Brand.green100` | the design system's UI-and-code green fill (unused on the phone yet) | +| `green/200` | `#99C8AC` | `Brand.green200` | the design system's UI-and-code green highlight (unused on the phone yet) | +| `green/400` | `#67AD82` | `Brand.green400` | the brand hue lifted for dark chrome: the meter, the ring, the wave on ink | +| `green/700` | `#01762F` | `Brand.green700` | the wordmark green, light chrome (the app's accent in light) | +| `green/mist` | `#DBF5E6` | `Brand.greenMist` | the pale green the orb lightens into | +| `ink` | `#1D1B16` | `Brand.ink` | the brand ink: the Mac pill's body, the ink theme's surface | +| `ink/600` | `#3A362F` | `Brand.ink600` | the Mac's dark card border | +| `ink/700` | `#33302A` | `Brand.ink700` | an ordinary key on ink, one step up | +| `ink/800` | `#26231E` | `Brand.ink800` | a modifier key on ink; the Mac's dark card fill | +| `orange` | `#E67F36` | `Brand.orange` | the error word and ring, cancel, the Full Access note; never a red body | +| `page` | `#FDFCF8` | `Brand.page` | the design system's page background (unused on the phone) | +| `violet/iris` | `#887BDD` | `Brand.violetIris` | the orb gradient's upper violet stop | +| `violet/lavender` | `#D7D3F4` | `Brand.violetLavender` | the orb's lightest violet: its top and the gradient's ends | +| `violet/periwinkle` | `#B0A7E9` | `Brand.violetPeriwinkle` | the orb's mid violet: the drop's halo | +| `warm-white` | `#F2EEE6` | `Brand.warmWhite` | key legends on ink: warm white on warm ink | +| `white` | `#FFFFFF` | `Brand.white` | — | + + + +The keyboard's semantic colours — what a Figma component binds to. In Swift +the keys read the chosen theme's palette at run time; these are the design +theme's (ink) values, and the app's catalog colours. + + + +| Token | Value | Swift | Use | +| ----------------------- | ------------------------------------- | ----------------------------- | ------------------------------------------------------------------------- | +| `app/accent-dark` | `#67AD82` (`brand.green/400`) | `Keyboard.appAccentDark` | the catalog's AccentColor in dark | +| `app/accent-light` | `#01762F` (`brand.green/700`) | `Keyboard.appAccentLight` | the catalog's AccentColor in light | +| `app/card-border-dark` | `#3A362F` (`brand.ink/600`) | `Keyboard.appCardBorderDark` | the catalog's CardBorder in dark | +| `app/card-border-light` | `#DEDBDB` (`brand.card-border`) | `Keyboard.appCardBorderLight` | the catalog's CardBorder in light | +| `app/card-fill-dark` | `#26231E` (`brand.ink/800`) | `Keyboard.appCardFillDark` | the catalog's CardFill in dark | +| `app/card-fill-light` | `#EBE8E8` (`brand.card`) | `Keyboard.appCardFillLight` | the catalog's CardFill in light | +| `kb/cancel` | `#E67F36` (`brand.orange`) | `Keyboard.kbCancel` | the panel's cancel × | +| `kb/full-access-note` | `#E67F36` (`brand.orange`) | `Keyboard.kbFullAccessNote` | the one line of words the keyboard ever shows | +| `kb/key` | `#33302A` (`themes.ink/key`) | `Keyboard.kbKey` | an ordinary key | +| `kb/key-modifier` | `#26231E` (`themes.ink/key-modifier`) | `Keyboard.kbKeyModifier` | shift, delete, globe, return, 123, cancel | +| `kb/legend` | `#F2EEE6` (`themes.ink/legend`) | `Keyboard.kbLegend` | key legends and bare glyphs | +| `kb/notice-error` | `#E67F36` (`brand.orange`) | `Keyboard.kbNoticeError` | the solid ring and glyph for an error | +| `kb/notice-ok` | `#67AD82` (`brand.green/400`) | `Keyboard.kbNoticeOk` | the solid ring for pasted and copied | +| `kb/orb-ring-end` | `#FFFFFF` (`brand.white`) | `Keyboard.kbOrbRingEnd` | the sweeping ring's gradient, bottom-trailing | +| `kb/orb-ring-start` | `#01762F` (`brand.green/700`) | `Keyboard.kbOrbRingStart` | the sweeping ring's gradient, top-leading | +| `kb/popup` | `#33302A` (`themes.ink/popup`) | `Keyboard.kbPopup` | the letter pop-up | +| `kb/signal` | `#67AD82` (`themes.ink/signal`) | `Keyboard.kbSignal` | the wave, the caret, the saved check | +| `kb/surface` | `#1D1B16` (`themes.ink/surface`) | `Keyboard.kbSurface` | the design theme's surface (Figma binds to kb/*; Swift reads the palette) | + + + +Gradients: + + + +- `orb` (`Gradients.orb`, bottom → top): `#D7D3F4` at 0, `#B0A7E9` at 0.0673, `#67AD82` at 0.1442, `#01762F` at 0.3029, `#3923C7` at 0.5962, `#887BDD` at 0.75, `#D7D3F4` at 0.8942, `#FFFFFF` at 1 — the Mac orb's fill, the design's own stops (App elements/Recording.svg), swept bottom to top +- `orb-ring` (`Gradients.orbRing`, topLeading → bottomTrailing): `#01762F` at 0, `#FFFFFF` at 1 — the ring round the orb: green into white, corner to corner; spun while something is happening + + The default theme follows the host app's light or dark appearance, as the iPhone keyboard does; Blurt's own themes are **fixed**, whatever the host @@ -197,8 +324,27 @@ page and a black Messages thread. Nothing on it uses `accent`. ## Type -Key legends: letters 22 pt regular, -everything else 16 pt medium. System font throughout. +System font throughout (SF Pro; the Figma file must have it installed, never +Inter). Sizes are fixed points, not Dynamic Type, as the system keyboard's are. + + + +| Token | Value | Swift | Use | +| ------------------ | ---------- | --------------------------- | -------------------------------------------------------------- | +| `ratio/orb-glyph` | `0.34` | `Typography.ratioOrbGlyph` | the clipboard and exclamation glyphs, as a fraction of the orb | +| `size/glyph` | `17` | `Typography.sizeGlyph` | the +, × and ✓ | +| `size/legend` | `16` | `Typography.sizeLegend` | every other key | +| `size/letter` | `22` | `Typography.sizeLetter` | letter keys | +| `size/popup` | `32` | `Typography.sizePopup` | the letter pop-up | +| `size/term` | `17` | `Typography.sizeTerm` | the key-term field | +| `weight/glyph` | `medium` | `Typography.weightGlyph` | — | +| `weight/legend` | `medium` | `Typography.weightLegend` | — | +| `weight/letter` | `regular` | `Typography.weightLetter` | — | +| `weight/orb-glyph` | `semibold` | `Typography.weightOrbGlyph` | — | +| `weight/popup` | `regular` | `Typography.weightPopup` | — | +| `weight/term` | `regular` | `Typography.weightTerm` | — | + + ## Components (`BlurtKeyboard/Sources/`) @@ -265,6 +411,117 @@ Top and bottom margin 8 (`KeyboardRootView`); 11 between rows and 3 at the sides The globe key appears only when iOS says another keyboard is installed (`needsInputModeSwitchKey`). +## Metrics and motion + +Every size, gap, radius, opacity and duration the keyboard's views use. The +heights in `KeyboardLayout.height` are derived from these (slim = 2 × +`margin/vertical` + `voicebar/height`; full adds 4 × `row/gap` + 4 × +`key/height`; the panel's is chosen), and `LayoutArithmeticTests` pins the +derivation. + + + +| Token | Points | Swift | Use | +| ----------------------------- | ------- | ---------------------------------- | ------------------------------------------------------------------------ | +| `addterm/inset` | `6` | `Metrics.addtermInset` | the + from the panel's corner | +| `card/border` | `1` | `Metrics.cardBorder` | the card's hairline | +| `card/radius` | `16` | `Metrics.cardRadius` | the app's cards | +| `caret/height` | `20` | `Metrics.caretHeight` | — | +| `caret/lead` | `1` | `Metrics.caretLead` | the caret's gap from the text | +| `caret/radius` | `1` | `Metrics.caretRadius` | — | +| `caret/width` | `2` | `Metrics.caretWidth` | — | +| `gesture/swipe-min` | `24` | `Metrics.gestureSwipeMin` | the carousel gesture's minimum distance | +| `glyph/hit` | `32` | `Metrics.glyphHit` | the +, × and ✓ touch targets | +| `key/gap` | `6` | `Metrics.keyGap` | between keys, the iPhone's | +| `key/height` | `42` | `Metrics.keyHeight` | every key | +| `key/letter-width-402` | `34.8` | `Metrics.keyLetterWidth402` | a letter key at 402 pt (iPhone 18 Pro): (width − 9 × key/gap) / 10 | +| `key/min-width` | `44` | `Metrics.keyMinWidth` | a key that isn't given a width | +| `key/pad` | `4` | `Metrics.keyPad` | a legend's side padding on a min-width key | +| `key/radius` | `8` | `Metrics.keyRadius` | flat keys, one colour at this corner | +| `key/return-width-402` | `104.4` | `Metrics.keyReturnWidth402` | return at 402 pt: two side keys and a gap | +| `key/side-gap-factor` | `2` | `Metrics.keySideGapFactor` | shift and delete stand this many key gaps from the letters | +| `key/side-width-402` | `49.2` | `Metrics.keySideWidth402` | shift, delete, 123 and globe at 402 pt: what seven letters leave, halved | +| `layout/full` | `272` | `Metrics.layoutFull` | 2 × margin/vertical + voicebar/height + 4 × row/gap + 4 × key/height | +| `layout/panel` | `216` | `Metrics.layoutPanel` | chosen: room for the 96 orb over one key row | +| `layout/slim` | `60` | `Metrics.layoutSlim` | 2 × margin/vertical + voicebar/height | +| `margin/side` | `3` | `Metrics.marginSide` | at the keyboard's sides | +| `margin/vertical` | `8` | `Metrics.marginVertical` | the keyboard's top and bottom | +| `opacity/dim` | `0.8` | `Metrics.opacityDim` | the orb when Blurt isn't ready | +| `opacity/dim-saturation` | `0.35` | `Metrics.opacityDimSaturation` | and its saturation | +| `opacity/disabled` | `0.4` | `Metrics.opacityDisabled` | the + without Full Access | +| `opacity/grain` | `0.5` | `Metrics.opacityGrain` | — | +| `opacity/home-dim-saturation` | `0.45` | `Metrics.opacityHomeDimSaturation` | the home hero's saturation when not listening | +| `opacity/legend-muted` | `0.5` | `Metrics.opacityLegendMuted` | the + at rest | +| `opacity/orb-light` | `0.3` | `Metrics.opacityOrbLight` | — | +| `opacity/placeholder` | `0.4` | `Metrics.opacityPlaceholder` | the field's placeholder | +| `opacity/popup-shadow` | `0.12` | `Metrics.opacityPopupShadow` | — | +| `opacity/press-brighten` | `0.15` | `Metrics.opacityPressBrighten` | a key lightens this much while pressed | +| `opacity/term-cancel` | `0.7` | `Metrics.opacityTermCancel` | the field's × | +| `orb/bar` | `40` | `Metrics.orbBar` | the orb in the voice bar | +| `orb/dissipate-blur` | `0.16` | `Metrics.orbDissipateBlur` | and blurs to this fraction of its size | +| `orb/dissipate-scale` | `1.25` | `Metrics.orbDissipateScale` | the orb swells to this while dissipating | +| `orb/home` | `112` | `Metrics.orbHome` | the orb on the home screen | +| `orb/light-radius` | `110` | `Metrics.orbLightRadius` | the light's reach in points (fixed, not proportional — open) | +| `orb/light-x` | `0.3` | `Metrics.orbLightX` | the soft light's centre, as a fraction of the orb | +| `orb/light-y` | `0.22` | `Metrics.orbLightY` | — | +| `orb/panel` | `96` | `Metrics.orbPanel` | the orb in the panel | +| `panel/spacing` | `12` | `Metrics.panelSpacing` | between the panel's orb and its key row | +| `picker/preview-width` | `393` | `Metrics.pickerPreviewWidth` | the theme card draws the keyboard at this width | +| `picker/radius` | `10` | `Metrics.pickerRadius` | the theme card's preview corners | +| `picker/scale` | `0.42` | `Metrics.pickerScale` | then scales it to fit two across | +| `popup/extra-width` | `18` | `Metrics.popupExtraWidth` | the letter pop-up is the key width plus this | +| `popup/height` | `56` | `Metrics.popupHeight` | — | +| `popup/offset` | `58` | `Metrics.popupOffset` | the pop-up sits this far above the key | +| `popup/radius` | `10` | `Metrics.popupRadius` | — | +| `popup/shadow-radius` | `8` | `Metrics.popupShadowRadius` | the one thing that floats | +| `popup/shadow-y` | `2` | `Metrics.popupShadowY` | — | +| `press/scale` | `0.94` | `Metrics.pressScale` | the orb while pressed | +| `ring/active` | `2` | `Metrics.ringActive` | the ring while working or noticing; the home ring | +| `ring/still` | `1` | `Metrics.ringStill` | the ring at rest | +| `row/gap` | `11` | `Metrics.rowGap` | between rows, the iPhone's | +| `slim/spacing` | `8` | `Metrics.slimSpacing` | between the slim bar's keys | +| `term/gap` | `8` | `Metrics.termGap` | × · field · ✓ | +| `term/height` | `36` | `Metrics.termHeight` | the key-term field's capsule | +| `term/inset` | `2` | `Metrics.termInset` | the field row's side inset | +| `term/pad` | `14` | `Metrics.termPad` | the field's side padding | +| `voicebar/addterm-clearance` | `12` | `Metrics.voicebarAddtermClearance` | the wave stays this clear of the + at the trailing edge | +| `voicebar/height` | `44` | `Metrics.voicebarHeight` | the voice row, where the system puts its suggestion bar | +| `voicebar/note-gap` | `10` | `Metrics.voicebarNoteGap` | between the orb and the Full Access note | +| `wave/bar` | `2` | `Metrics.waveBar` | a wave bar's width | +| `wave/bar-height` | `24` | `Metrics.waveBarHeight` | — | +| `wave/bar-width` | `240` | `Metrics.waveBarWidth` | the wave in the voice bar, at most | +| `wave/gap` | `2` | `Metrics.waveGap` | between wave bars | +| `wave/home-height` | `44` | `Metrics.waveHomeHeight` | — | +| `wave/home-width` | `280` | `Metrics.waveHomeWidth` | — | +| `wave/panel-height` | `40` | `Metrics.wavePanelHeight` | — | +| `wave/panel-width` | `300` | `Metrics.wavePanelWidth` | — | +| `wordmark/height` | `22` | `Metrics.wordmarkHeight` | — | + + + +Motion, in seconds. Nothing springs or snaps; only the press answers at once. + + + +| Token | Seconds | Swift | Use | +| --------------- | ------- | --------------------- | ------------------------------------------------------------- | +| `caret` | `0.5` | `Motion.caret` | the caret's blink | +| `drop` | `2.4` | `Motion.drop` | the violet drop is gone by | +| `drop-hold` | `0.9` | `Motion.dropHold` | and held to | +| `drop-rise` | `0.5` | `Motion.dropRise` | the drop is up in | +| `drop-spread` | `1` | `Motion.dropSpread` | the bloom reaches its full spread in | +| `flip` | `0.25` | `Motion.flip` | the panel's carousel | +| `height-change` | `0.25` | `Motion.heightChange` | the keyboard resizing | +| `key-press` | `0.08` | `Motion.keyPress` | a key lighting | +| `mood` | `0.8` | `Motion.mood` | the orb's colour moving between moods | +| `press` | `0.1` | `Motion.press` | the orb's press; the one thing that answers at once | +| `ring-period` | `1.6` | `Motion.ringPeriod` | one turn of the ring, the Mac's cadence | +| `state-fade` | `0.5` | `Motion.stateFade` | every other change on the key: the ring, a glyph, the dimming | +| `term-swap` | `0.4` | `Motion.termSwap` | the voice bar becoming the field | +| `wave-fade` | `0.7` | `Motion.waveFade` | the orb and the wave crossing, either way | + + + ## Feedback Haptics (`KeyboardModel.haptics`): medium impact on `recording`, light on the @@ -286,29 +543,24 @@ The app listens and transcribes; the keyboard is a remote control. They talk over the App Group's `UserDefaults` (payloads as JSON) plus Darwin notifications that carry nothing and just say "look" (`SharedState.swift`). -| Rule | Value | Why | -| ---------------------- | --------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | -| presence | heartbeat 5 s (app), 4 s (keyboard); window 15 s | more than twice a heartbeat, so one missed beat isn't absence; a killed process is absent within seconds | -| listening | window not lapsed **and** app seen within 15 s | a killed app, or a phone call, with the window's end still in the future | -| result freshness | 10 s | a notification held for a suspended keyboard arrives minutes late | -| result addressing | `recipient` = the keyboard instance last seen | two live keyboards (two host apps) must not both insert | -| result delivery | the app waits 3 s (poll 250 ms) for the keyboard to take the result; else clipboard + "Copied" | "Pasted" is never a guess | -| command freshness | 10 s | a held press from minutes ago must not start a dictation on resume | -| command retry | one re-signal after 600 ms with no phase change | a missed Darwin notification would leave the gate latched over nothing | -| phase staleness | notices 3 s (max dwell 2 s + 1); in flight 130 s (the 120 s cap + 10) | the keyboard reads the snapshot on every appearance | -| notice dwell | pasted 1.2 s; copied, error 2 s | the Mac's 0.8 / 1.6 s, a little longer with no hover | -| press delay on the orb | 90 ms | a swipe that starts on the orb never starts a dictation it must then cancel | -| tap travel | 12 pt (keys), 24 pt (orb), swipe ≥ 48 pt horizontal and 1.5× the vertical | the carousel's swipe never types or dictates | -| level publish | every 80 ms while recording | the orb's meter, off the capture path's back | -| lexicon refresh | hourly | thousands of contacts on a keyboard memory budget | -| height change | 0.25 s; constraint priority 999 | iOS honours a keyboard's height at just under required | -| wave | 2 pt bars 2 pt apart; 240 × 24 (bar), 300 × 40 (panel), 280 × 44 (home) | thin, dense, slim; one component for the keyboard and the home screen | -| dissipate | scale to 1.25, blur 0.16 × the orb, opacity to 0, over the 0.7 s crossing | mist, not a pop; the same in reverse | -| fades | orb ↔ wave 0.7 s; ring, glyph, dimming 0.5 s; term field 0.4 s; the drop up 0.5 s, held to 0.9 s, gone by 2.4 s | soft and slow; only the press (0.1 s) answers at once | -| keys | radius 8, no drop, no edge; pop-up radius 10 with a 12 % shadow at radius 8 | flat and contemporary; the pop-up is the one thing that floats | -| letter pop-up | 32 pt glyph, key width + 18 × 56, radius 10, 58 pt above | the system keyboard's geometry | -| term field | 36 pt, 17 pt text, caret 0.5 s; the + is 32 pt | — | -| term packs | ≤ 64 KB, ≤ 100 terms, ≤ 80 characters each | the request's cap; unbounded input from a stranger | +| Rule | Value | Why | +| ---------------------- | ---------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | +| presence | heartbeat 5 s (app), 4 s (keyboard); window 15 s | more than twice a heartbeat, so one missed beat isn't absence; a killed process is absent within seconds | +| listening | window not lapsed **and** app seen within 15 s | a killed app, or a phone call, with the window's end still in the future | +| result freshness | 10 s | a notification held for a suspended keyboard arrives minutes late | +| result addressing | `recipient` = the keyboard instance last seen | two live keyboards (two host apps) must not both insert | +| result delivery | the app waits 3 s (poll 250 ms) for the keyboard to take the result; else clipboard + "Copied" | "Pasted" is never a guess | +| command freshness | 10 s | a held press from minutes ago must not start a dictation on resume | +| command retry | one re-signal after 600 ms with no phase change | a missed Darwin notification would leave the gate latched over nothing | +| phase staleness | notices 3 s (max dwell 2 s + 1); in flight 130 s (the 120 s cap + 10) | the keyboard reads the snapshot on every appearance | +| notice dwell | pasted 1.2 s; copied, error 2 s | the Mac's 0.8 / 1.6 s, a little longer with no hover | +| press delay on the orb | 90 ms | a swipe that starts on the orb never starts a dictation it must then cancel | +| tap travel | 12 pt (keys), 24 pt (orb), swipe ≥ 48 pt horizontal and 1.5× the vertical | the carousel's swipe never types or dictates | +| level publish | every 80 ms while recording | the orb's meter, off the capture path's back | +| lexicon refresh | hourly | thousands of contacts on a keyboard memory budget | +| height change | 0.25 s; constraint priority 999 | iOS honours a keyboard's height at just under required | +| the visual numbers | see Metrics and motion above | generated from `Design/tokens.json`; the views carry no literals | +| term packs | ≤ 64 KB, ≤ 100 terms, ≤ 80 characters each | the request's cap; unbounded input from a stranger | Tests pin the rules that can be pinned (`BlurtiOSTests`: the contract, the gate, results, the term field, the feed, the layout arithmetic); anything diff --git a/App/BlurtiOS/Design/tokens.json b/App/BlurtiOS/Design/tokens.json new file mode 100644 index 00000000..47ecda90 --- /dev/null +++ b/App/BlurtiOS/Design/tokens.json @@ -0,0 +1,668 @@ +{ + "version": 1, + "figma": { + "fileKey": null, + "approvedVersion": null, + "exportedAt": null + }, + "brand": { + "green/700": { + "value": "#01762F", + "use": "the wordmark green, light chrome (the app's accent in light)" + }, + "green/400": { + "value": "#67AD82", + "use": "the brand hue lifted for dark chrome: the meter, the ring, the wave on ink" + }, + "green/200": { + "value": "#99C8AC", + "use": "the design system's UI-and-code green highlight (unused on the phone yet)" + }, + "green/100": { + "value": "#CCE4D5", + "use": "the design system's UI-and-code green fill (unused on the phone yet)" + }, + "green/mist": { + "value": "#DBF5E6", + "use": "the pale green the orb lightens into" + }, + "cobolt": { + "value": "#3923C7", + "use": "AssemblyAI's primary violet: the drop, never a key or a surface" + }, + "violet/lavender": { + "value": "#D7D3F4", + "use": "the orb's lightest violet: its top and the gradient's ends" + }, + "violet/periwinkle": { + "value": "#B0A7E9", + "use": "the orb's mid violet: the drop's halo" + }, + "violet/iris": { + "value": "#887BDD", + "use": "the orb gradient's upper violet stop" + }, + "ink": { + "value": "#1D1B16", + "use": "the brand ink: the Mac pill's body, the ink theme's surface" + }, + "ink/800": { + "value": "#26231E", + "use": "a modifier key on ink; the Mac's dark card fill" + }, + "ink/700": { + "value": "#33302A", + "use": "an ordinary key on ink, one step up" + }, + "ink/600": { + "value": "#3A362F", + "use": "the Mac's dark card border" + }, + "warm-white": { + "value": "#F2EEE6", + "use": "key legends on ink: warm white on warm ink" + }, + "page": { + "value": "#FDFCF8", + "use": "the design system's page background (unused on the phone)" + }, + "card": { + "value": "#EBE8E8", + "use": "the warm card fill; the paper theme's surface" + }, + "card-border": { + "value": "#DEDBDB", + "use": "the card's hairline; the paper theme's modifier key" + }, + "orange": { + "value": "#E67F36", + "use": "the error word and ring, cancel, the Full Access note; never a red body" + }, + "white": { + "value": "#FFFFFF" + }, + "black": { + "value": "#000000" + }, + "apple/light-surface": { + "value": "#D1D5DB", + "use": "the iPhone keyboard's light surface" + }, + "apple/light-modifier": { + "value": "#ADB3BC", + "use": "the iPhone keyboard's light modifier key" + }, + "apple/dark-surface": { + "value": "#2B2B2B", + "use": "the iPhone keyboard's dark surface" + }, + "apple/dark-key": { + "value": "#6B6B6B", + "use": "the iPhone keyboard's dark key" + }, + "apple/dark-modifier": { + "value": "#464646", + "use": "the iPhone keyboard's dark modifier key" + } + }, + "themes": { + "system-light/surface": "{brand.apple/light-surface}", + "system-light/key": "{brand.white}", + "system-light/key-modifier": "{brand.apple/light-modifier}", + "system-light/legend": "{brand.black}", + "system-light/signal": "{brand.green/700}", + "system-light/popup": "{brand.white}", + "system-dark/surface": "{brand.apple/dark-surface}", + "system-dark/key": "{brand.apple/dark-key}", + "system-dark/key-modifier": "{brand.apple/dark-modifier}", + "system-dark/legend": "{brand.white}", + "system-dark/signal": "{brand.green/400}", + "system-dark/popup": "{brand.apple/dark-key}", + "ink/surface": "{brand.ink}", + "ink/key": "{brand.ink/700}", + "ink/key-modifier": "{brand.ink/800}", + "ink/legend": "{brand.warm-white}", + "ink/signal": "{brand.green/400}", + "ink/popup": "{brand.ink/700}", + "paper/surface": "{brand.card}", + "paper/key": "{brand.white}", + "paper/key-modifier": "{brand.card-border}", + "paper/legend": "{brand.ink}", + "paper/signal": "{brand.green/700}", + "paper/popup": "{brand.white}", + "lavender/surface": "#2C2557", + "lavender/key": "#3F3777", + "lavender/key-modifier": "#352E68", + "lavender/legend": "#F1EEFF", + "lavender/signal": "{brand.green/400}", + "lavender/popup": "#3F3777", + "mint/surface": "#10231B", + "mint/key": "#1E3F31", + "mint/key-modifier": "#183429", + "mint/legend": "#E9F5EE", + "mint/signal": "{brand.green/400}", + "mint/popup": "#1E3F31", + "midnight/surface": "#0E1220", + "midnight/key": "#1D2440", + "midnight/key-modifier": "#161B33", + "midnight/legend": "#E8ECFF", + "midnight/signal": "{brand.green/400}", + "midnight/popup": "#1D2440", + "sunset/surface": "#2B1912", + "sunset/key": "#4B2B20", + "sunset/key-modifier": "#3B2119", + "sunset/legend": "#FFEFE6", + "sunset/signal": "{brand.green/400}", + "sunset/popup": "#4B2B20" + }, + "keyboard": { + "kb/surface": { + "value": "{themes.ink/surface}", + "use": "the design theme's surface (Figma binds to kb/*; Swift reads the palette)" + }, + "kb/key": { + "value": "{themes.ink/key}", + "use": "an ordinary key" + }, + "kb/key-modifier": { + "value": "{themes.ink/key-modifier}", + "use": "shift, delete, globe, return, 123, cancel" + }, + "kb/legend": { + "value": "{themes.ink/legend}", + "use": "key legends and bare glyphs" + }, + "kb/signal": { + "value": "{themes.ink/signal}", + "use": "the wave, the caret, the saved check" + }, + "kb/popup": { + "value": "{themes.ink/popup}", + "use": "the letter pop-up" + }, + "kb/notice-ok": { + "value": "{brand.green/400}", + "use": "the solid ring for pasted and copied" + }, + "kb/notice-error": { + "value": "{brand.orange}", + "use": "the solid ring and glyph for an error" + }, + "kb/cancel": { + "value": "{brand.orange}", + "use": "the panel's cancel ×" + }, + "kb/full-access-note": { + "value": "{brand.orange}", + "use": "the one line of words the keyboard ever shows" + }, + "kb/orb-ring-start": { + "value": "{brand.green/700}", + "use": "the sweeping ring's gradient, top-leading" + }, + "kb/orb-ring-end": { + "value": "{brand.white}", + "use": "the sweeping ring's gradient, bottom-trailing" + }, + "app/accent-light": { + "value": "{brand.green/700}", + "use": "the catalog's AccentColor in light" + }, + "app/accent-dark": { + "value": "{brand.green/400}", + "use": "the catalog's AccentColor in dark" + }, + "app/card-fill-light": { + "value": "{brand.card}", + "use": "the catalog's CardFill in light" + }, + "app/card-fill-dark": { + "value": "{brand.ink/800}", + "use": "the catalog's CardFill in dark" + }, + "app/card-border-light": { + "value": "{brand.card-border}", + "use": "the catalog's CardBorder in light" + }, + "app/card-border-dark": { + "value": "{brand.ink/600}", + "use": "the catalog's CardBorder in dark" + } + }, + "gradients": { + "orb": { + "use": "the Mac orb's fill, the design's own stops (App elements/Recording.svg), swept bottom to top", + "start": "bottom", + "end": "top", + "stops": [ + { + "color": "{brand.violet/lavender}", + "location": 0 + }, + { + "color": "{brand.violet/periwinkle}", + "location": 0.0673 + }, + { + "color": "{brand.green/400}", + "location": 0.1442 + }, + { + "color": "{brand.green/700}", + "location": 0.3029 + }, + { + "color": "{brand.cobolt}", + "location": 0.5962 + }, + { + "color": "{brand.violet/iris}", + "location": 0.75 + }, + { + "color": "{brand.violet/lavender}", + "location": 0.8942 + }, + { + "color": "{brand.white}", + "location": 1 + } + ] + }, + "orb-ring": { + "use": "the ring round the orb: green into white, corner to corner; spun while something is happening", + "start": "topLeading", + "end": "bottomTrailing", + "stops": [ + { + "color": "{brand.green/700}", + "location": 0 + }, + { + "color": "{brand.white}", + "location": 1 + } + ] + } + }, + "metrics": { + "key/height": { + "value": 42, + "use": "every key" + }, + "key/gap": { + "value": 6, + "use": "between keys, the iPhone's" + }, + "row/gap": { + "value": 11, + "use": "between rows, the iPhone's" + }, + "margin/side": { + "value": 3, + "use": "at the keyboard's sides" + }, + "margin/vertical": { + "value": 8, + "use": "the keyboard's top and bottom" + }, + "key/radius": { + "value": 8, + "use": "flat keys, one colour at this corner" + }, + "key/min-width": { + "value": 44, + "use": "a key that isn't given a width" + }, + "key/pad": { + "value": 4, + "use": "a legend's side padding on a min-width key" + }, + "key/side-gap-factor": { + "value": 2, + "use": "shift and delete stand this many key gaps from the letters" + }, + "key/letter-width-402": { + "value": 34.8, + "use": "a letter key at 402 pt (iPhone 18 Pro): (width − 9 × key/gap) / 10" + }, + "key/side-width-402": { + "value": 49.2, + "use": "shift, delete, 123 and globe at 402 pt: what seven letters leave, halved" + }, + "key/return-width-402": { + "value": 104.4, + "use": "return at 402 pt: two side keys and a gap" + }, + "voicebar/height": { + "value": 44, + "use": "the voice row, where the system puts its suggestion bar" + }, + "voicebar/note-gap": { + "value": 10, + "use": "between the orb and the Full Access note" + }, + "voicebar/addterm-clearance": { + "value": 12, + "use": "the wave stays this clear of the + at the trailing edge" + }, + "orb/bar": { + "value": 40, + "use": "the orb in the voice bar" + }, + "orb/panel": { + "value": 96, + "use": "the orb in the panel" + }, + "orb/home": { + "value": 112, + "use": "the orb on the home screen" + }, + "wave/bar-width": { + "value": 240, + "use": "the wave in the voice bar, at most" + }, + "wave/bar-height": { + "value": 24 + }, + "wave/panel-width": { + "value": 300 + }, + "wave/panel-height": { + "value": 40 + }, + "wave/home-width": { + "value": 280 + }, + "wave/home-height": { + "value": 44 + }, + "wave/bar": { + "value": 2, + "use": "a wave bar's width" + }, + "wave/gap": { + "value": 2, + "use": "between wave bars" + }, + "ring/still": { + "value": 1, + "use": "the ring at rest" + }, + "ring/active": { + "value": 2, + "use": "the ring while working or noticing; the home ring" + }, + "popup/extra-width": { + "value": 18, + "use": "the letter pop-up is the key width plus this" + }, + "popup/height": { + "value": 56 + }, + "popup/radius": { + "value": 10 + }, + "popup/offset": { + "value": 58, + "use": "the pop-up sits this far above the key" + }, + "popup/shadow-radius": { + "value": 8, + "use": "the one thing that floats" + }, + "popup/shadow-y": { + "value": 2 + }, + "term/height": { + "value": 36, + "use": "the key-term field's capsule" + }, + "term/pad": { + "value": 14, + "use": "the field's side padding" + }, + "term/gap": { + "value": 8, + "use": "× · field · ✓" + }, + "term/inset": { + "value": 2, + "use": "the field row's side inset" + }, + "caret/width": { + "value": 2 + }, + "caret/height": { + "value": 20 + }, + "caret/radius": { + "value": 1 + }, + "caret/lead": { + "value": 1, + "use": "the caret's gap from the text" + }, + "glyph/hit": { + "value": 32, + "use": "the +, × and ✓ touch targets" + }, + "slim/spacing": { + "value": 8, + "use": "between the slim bar's keys" + }, + "panel/spacing": { + "value": 12, + "use": "between the panel's orb and its key row" + }, + "addterm/inset": { + "value": 6, + "use": "the + from the panel's corner" + }, + "card/radius": { + "value": 16, + "use": "the app's cards" + }, + "card/border": { + "value": 1, + "use": "the card's hairline" + }, + "wordmark/height": { + "value": 22 + }, + "picker/preview-width": { + "value": 393, + "use": "the theme card draws the keyboard at this width" + }, + "picker/scale": { + "value": 0.42, + "use": "then scales it to fit two across" + }, + "picker/radius": { + "value": 10, + "use": "the theme card's preview corners" + }, + "layout/slim": { + "value": 60, + "use": "2 × margin/vertical + voicebar/height" + }, + "layout/panel": { + "value": 216, + "use": "chosen: room for the 96 orb over one key row" + }, + "layout/full": { + "value": 272, + "use": "2 × margin/vertical + voicebar/height + 4 × row/gap + 4 × key/height" + }, + "orb/light-x": { + "value": 0.3, + "use": "the soft light's centre, as a fraction of the orb" + }, + "orb/light-y": { + "value": 0.22 + }, + "orb/light-radius": { + "value": 110, + "use": "the light's reach in points (fixed, not proportional — open)" + }, + "orb/dissipate-scale": { + "value": 1.25, + "use": "the orb swells to this while dissipating" + }, + "orb/dissipate-blur": { + "value": 0.16, + "use": "and blurs to this fraction of its size" + }, + "opacity/dim": { + "value": 0.8, + "use": "the orb when Blurt isn't ready" + }, + "opacity/dim-saturation": { + "value": 0.35, + "use": "and its saturation" + }, + "opacity/home-dim-saturation": { + "value": 0.45, + "use": "the home hero's saturation when not listening" + }, + "opacity/legend-muted": { + "value": 0.5, + "use": "the + at rest" + }, + "opacity/term-cancel": { + "value": 0.7, + "use": "the field's ×" + }, + "opacity/placeholder": { + "value": 0.4, + "use": "the field's placeholder" + }, + "opacity/disabled": { + "value": 0.4, + "use": "the + without Full Access" + }, + "opacity/press-brighten": { + "value": 0.15, + "use": "a key lightens this much while pressed" + }, + "opacity/popup-shadow": { + "value": 0.12 + }, + "opacity/orb-light": { + "value": 0.3 + }, + "opacity/grain": { + "value": 0.5 + }, + "press/scale": { + "value": 0.94, + "use": "the orb while pressed" + }, + "gesture/swipe-min": { + "value": 24, + "use": "the carousel gesture's minimum distance" + } + }, + "type": { + "size/letter": { + "value": 22, + "use": "letter keys" + }, + "size/legend": { + "value": 16, + "use": "every other key" + }, + "size/popup": { + "value": 32, + "use": "the letter pop-up" + }, + "size/term": { + "value": 17, + "use": "the key-term field" + }, + "size/glyph": { + "value": 17, + "use": "the +, × and ✓" + }, + "ratio/orb-glyph": { + "value": 0.34, + "use": "the clipboard and exclamation glyphs, as a fraction of the orb" + }, + "weight/letter": { + "value": "regular" + }, + "weight/legend": { + "value": "medium" + }, + "weight/popup": { + "value": "regular" + }, + "weight/term": { + "value": "regular" + }, + "weight/glyph": { + "value": "medium" + }, + "weight/orb-glyph": { + "value": "semibold" + } + }, + "motion": { + "wave-fade": { + "value": 0.7, + "use": "the orb and the wave crossing, either way" + }, + "state-fade": { + "value": 0.5, + "use": "every other change on the key: the ring, a glyph, the dimming" + }, + "term-swap": { + "value": 0.4, + "use": "the voice bar becoming the field" + }, + "press": { + "value": 0.1, + "use": "the orb's press; the one thing that answers at once" + }, + "key-press": { + "value": 0.08, + "use": "a key lighting" + }, + "mood": { + "value": 0.8, + "use": "the orb's colour moving between moods" + }, + "ring-period": { + "value": 1.6, + "use": "one turn of the ring, the Mac's cadence" + }, + "drop": { + "value": 2.4, + "use": "the violet drop is gone by" + }, + "drop-rise": { + "value": 0.5, + "use": "the drop is up in" + }, + "drop-hold": { + "value": 0.9, + "use": "and held to" + }, + "drop-spread": { + "value": 1, + "use": "the bloom reaches its full spread in" + }, + "caret": { + "value": 0.5, + "use": "the caret's blink" + }, + "flip": { + "value": 0.25, + "use": "the panel's carousel" + }, + "height-change": { + "value": 0.25, + "use": "the keyboard resizing" + } + } +} diff --git a/App/BlurtiOS/Shared/BlurtBrand.swift b/App/BlurtiOS/Shared/BlurtBrand.swift index 5d09eaf1..24d992e0 100644 --- a/App/BlurtiOS/Shared/BlurtBrand.swift +++ b/App/BlurtiOS/Shared/BlurtBrand.swift @@ -4,6 +4,11 @@ import SwiftUI /// from the 2026-08-31 comps), plus the handful of shades the keyboard needs /// for a surface the Mac never draws. Compiled into the app and the keyboard. /// +/// The values live in `Design/tokens.json` and arrive here through the +/// generated `DesignTokens`; these are the Mac's names for them, kept so the +/// call sites still read in the Mac's vocabulary. Add a colour to the tokens, +/// not here. +/// /// The keyboard's surface is fixed per theme, the way the Mac's overlay pill is /// fixed: it floats over whatever app the user is typing in, so it cannot take /// its cue from that app's appearance, and it must read the same on a white @@ -11,44 +16,31 @@ import SwiftUI /// the raw shades — `greenOnDark`, `ink` — and never `accent`. enum BlurtBrand { /// `#01762F` — the wordmark green, for light chrome. - nonisolated static let green = Color(red: 1 / 255, green: 118 / 255, blue: 47 / 255) + nonisolated static let green = DesignTokens.Brand.green700 /// `#67AD82` — the brand hue lifted for dark chrome: the pill's text and /// meter, the ring, the wordmark on the icon. - nonisolated static let greenOnDark = Color(red: 103 / 255, green: 173 / 255, blue: 130 / 255) + nonisolated static let greenOnDark = DesignTokens.Brand.green400 /// `#1D1B16` — the brand ink: the pill's body in every state, and the /// keyboard's surface. - nonisolated static let ink = Color(red: 29 / 255, green: 27 / 255, blue: 22 / 255) + nonisolated static let ink = DesignTokens.Brand.ink /// `#E67F36` — the error word. The body stays ink; the word carries the alarm. - nonisolated static let errorOrange = Color(red: 230 / 255, green: 127 / 255, blue: 54 / 255) + nonisolated static let errorOrange = DesignTokens.Brand.orange // MARK: Keyboard surface — the ink family, one and two steps up /// `#33302A` — an ordinary key on the ink surface. - nonisolated static let key = Color(red: 51 / 255, green: 48 / 255, blue: 42 / 255) + nonisolated static let key = DesignTokens.Brand.ink700 /// `#26231E` — a modifier key (shift, delete, globe, return): a step darker /// than a letter, as the system keyboard does it. The Mac's dark card fill. - nonisolated static let keyDark = Color(red: 38 / 255, green: 35 / 255, blue: 30 / 255) + nonisolated static let keyDark = DesignTokens.Brand.ink800 /// `#F2EEE6` — key legends: a warm white, not a cold one, on the warm ink. - nonisolated static let keyText = Color(red: 242 / 255, green: 238 / 255, blue: 230 / 255) + nonisolated static let keyText = DesignTokens.Brand.warmWhite /// The orb's fill: the design's own stops (`App elements/Recording.svg`), /// swept bottom to top. - nonisolated static let orbGradient = LinearGradient( - stops: [ - .init(color: Color(red: 215 / 255, green: 211 / 255, blue: 244 / 255), location: 0), - .init(color: Color(red: 176 / 255, green: 167 / 255, blue: 233 / 255), location: 0.0673), - .init(color: greenOnDark, location: 0.1442), - .init(color: green, location: 0.3029), - .init(color: Color(red: 57 / 255, green: 35 / 255, blue: 199 / 255), location: 0.5962), - .init(color: Color(red: 136 / 255, green: 123 / 255, blue: 221 / 255), location: 0.75), - .init(color: Color(red: 215 / 255, green: 211 / 255, blue: 244 / 255), location: 0.8942), - .init(color: .white, location: 1), - ], - startPoint: .bottom, - endPoint: .top) + nonisolated static let orbGradient = DesignTokens.Gradients.orb /// The ring round the orb: green into white, corner to corner; spun while /// something is happening. - nonisolated static let orbRingGradient = LinearGradient( - colors: [green, .white], startPoint: .topLeading, endPoint: .bottomTrailing) + nonisolated static let orbRingGradient = DesignTokens.Gradients.orbRing } diff --git a/App/BlurtiOS/Shared/DesignTokens.swift b/App/BlurtiOS/Shared/DesignTokens.swift new file mode 100644 index 00000000..89e6a9a3 --- /dev/null +++ b/App/BlurtiOS/Shared/DesignTokens.swift @@ -0,0 +1,589 @@ +// Generated by scripts/design-tokens.swift from App/BlurtiOS/Design/tokens.json — do not edit. +// Regenerate with scripts/design-sync.sh; scripts/check.sh fails on drift. +// periphery:ignore:all +// swiftlint:disable file_length +import SwiftUI + +// swiftlint:disable type_body_length +/// The design's colours and numbers, from the one source Figma exports +/// (`Design/tokens.json`): what the views draw with, what DESIGN.md's tables +/// say, and what the asset catalog holds, all from the same file. Swift names +/// follow the token names by one rule (`kb/key-modifier` → `kbKeyModifier`), +/// the same rule the Figma build script uses for iOS code syntax. +enum DesignTokens { + enum Brand { + /// The iPhone keyboard's dark key. + nonisolated static let appleDarkKey: Color = Color(hex: 0x6B6B6B) + /// The iPhone keyboard's dark modifier key. + nonisolated static let appleDarkModifier: Color = Color(hex: 0x464646) + /// The iPhone keyboard's dark surface. + nonisolated static let appleDarkSurface: Color = Color(hex: 0x2B2B2B) + /// The iPhone keyboard's light modifier key. + nonisolated static let appleLightModifier: Color = Color(hex: 0xADB3BC) + /// The iPhone keyboard's light surface. + nonisolated static let appleLightSurface: Color = Color(hex: 0xD1D5DB) + nonisolated static let black: Color = Color(hex: 0x000000) + /// The warm card fill; the paper theme's surface. + nonisolated static let card: Color = Color(hex: 0xEBE8E8) + /// The card's hairline; the paper theme's modifier key. + nonisolated static let cardBorder: Color = Color(hex: 0xDEDBDB) + /// AssemblyAI's primary violet: the drop, never a key or a surface. + nonisolated static let cobolt: Color = Color(hex: 0x3923C7) + /// The design system's UI-and-code green fill (unused on the phone yet). + nonisolated static let green100: Color = Color(hex: 0xCCE4D5) + /// The design system's UI-and-code green highlight (unused on the phone yet). + nonisolated static let green200: Color = Color(hex: 0x99C8AC) + /// The brand hue lifted for dark chrome: the meter, the ring, the wave on ink. + nonisolated static let green400: Color = Color(hex: 0x67AD82) + /// The wordmark green, light chrome (the app's accent in light). + nonisolated static let green700: Color = Color(hex: 0x01762F) + /// The pale green the orb lightens into. + nonisolated static let greenMist: Color = Color(hex: 0xDBF5E6) + /// The brand ink: the Mac pill's body, the ink theme's surface. + nonisolated static let ink: Color = Color(hex: 0x1D1B16) + /// The Mac's dark card border. + nonisolated static let ink600: Color = Color(hex: 0x3A362F) + /// An ordinary key on ink, one step up. + nonisolated static let ink700: Color = Color(hex: 0x33302A) + /// A modifier key on ink; the Mac's dark card fill. + nonisolated static let ink800: Color = Color(hex: 0x26231E) + /// The error word and ring, cancel, the Full Access note; never a red body. + nonisolated static let orange: Color = Color(hex: 0xE67F36) + /// The design system's page background (unused on the phone). + nonisolated static let page: Color = Color(hex: 0xFDFCF8) + /// The orb gradient's upper violet stop. + nonisolated static let violetIris: Color = Color(hex: 0x887BDD) + /// The orb's lightest violet: its top and the gradient's ends. + nonisolated static let violetLavender: Color = Color(hex: 0xD7D3F4) + /// The orb's mid violet: the drop's halo. + nonisolated static let violetPeriwinkle: Color = Color(hex: 0xB0A7E9) + /// Key legends on ink: warm white on warm ink. + nonisolated static let warmWhite: Color = Color(hex: 0xF2EEE6) + nonisolated static let white: Color = Color(hex: 0xFFFFFF) + } + + enum Themes { + /// `brand.ink/700`. + nonisolated static let inkKey: Color = Brand.ink700 + /// `brand.ink/800`. + nonisolated static let inkKeyModifier: Color = Brand.ink800 + /// `brand.warm-white`. + nonisolated static let inkLegend: Color = Brand.warmWhite + /// `brand.ink/700`. + nonisolated static let inkPopup: Color = Brand.ink700 + /// `brand.green/400`. + nonisolated static let inkSignal: Color = Brand.green400 + /// `brand.ink`. + nonisolated static let inkSurface: Color = Brand.ink + nonisolated static let lavenderKey: Color = Color(hex: 0x3F3777) + nonisolated static let lavenderKeyModifier: Color = Color(hex: 0x352E68) + nonisolated static let lavenderLegend: Color = Color(hex: 0xF1EEFF) + nonisolated static let lavenderPopup: Color = Color(hex: 0x3F3777) + /// `brand.green/400`. + nonisolated static let lavenderSignal: Color = Brand.green400 + nonisolated static let lavenderSurface: Color = Color(hex: 0x2C2557) + nonisolated static let midnightKey: Color = Color(hex: 0x1D2440) + nonisolated static let midnightKeyModifier: Color = Color(hex: 0x161B33) + nonisolated static let midnightLegend: Color = Color(hex: 0xE8ECFF) + nonisolated static let midnightPopup: Color = Color(hex: 0x1D2440) + /// `brand.green/400`. + nonisolated static let midnightSignal: Color = Brand.green400 + nonisolated static let midnightSurface: Color = Color(hex: 0x0E1220) + nonisolated static let mintKey: Color = Color(hex: 0x1E3F31) + nonisolated static let mintKeyModifier: Color = Color(hex: 0x183429) + nonisolated static let mintLegend: Color = Color(hex: 0xE9F5EE) + nonisolated static let mintPopup: Color = Color(hex: 0x1E3F31) + /// `brand.green/400`. + nonisolated static let mintSignal: Color = Brand.green400 + nonisolated static let mintSurface: Color = Color(hex: 0x10231B) + /// `brand.white`. + nonisolated static let paperKey: Color = Brand.white + /// `brand.card-border`. + nonisolated static let paperKeyModifier: Color = Brand.cardBorder + /// `brand.ink`. + nonisolated static let paperLegend: Color = Brand.ink + /// `brand.white`. + nonisolated static let paperPopup: Color = Brand.white + /// `brand.green/700`. + nonisolated static let paperSignal: Color = Brand.green700 + /// `brand.card`. + nonisolated static let paperSurface: Color = Brand.card + nonisolated static let sunsetKey: Color = Color(hex: 0x4B2B20) + nonisolated static let sunsetKeyModifier: Color = Color(hex: 0x3B2119) + nonisolated static let sunsetLegend: Color = Color(hex: 0xFFEFE6) + nonisolated static let sunsetPopup: Color = Color(hex: 0x4B2B20) + /// `brand.green/400`. + nonisolated static let sunsetSignal: Color = Brand.green400 + nonisolated static let sunsetSurface: Color = Color(hex: 0x2B1912) + /// `brand.apple/dark-key`. + nonisolated static let systemDarkKey: Color = Brand.appleDarkKey + /// `brand.apple/dark-modifier`. + nonisolated static let systemDarkKeyModifier: Color = Brand.appleDarkModifier + /// `brand.white`. + nonisolated static let systemDarkLegend: Color = Brand.white + /// `brand.apple/dark-key`. + nonisolated static let systemDarkPopup: Color = Brand.appleDarkKey + /// `brand.green/400`. + nonisolated static let systemDarkSignal: Color = Brand.green400 + /// `brand.apple/dark-surface`. + nonisolated static let systemDarkSurface: Color = Brand.appleDarkSurface + /// `brand.white`. + nonisolated static let systemLightKey: Color = Brand.white + /// `brand.apple/light-modifier`. + nonisolated static let systemLightKeyModifier: Color = Brand.appleLightModifier + /// `brand.black`. + nonisolated static let systemLightLegend: Color = Brand.black + /// `brand.white`. + nonisolated static let systemLightPopup: Color = Brand.white + /// `brand.green/700`. + nonisolated static let systemLightSignal: Color = Brand.green700 + /// `brand.apple/light-surface`. + nonisolated static let systemLightSurface: Color = Brand.appleLightSurface + } + + enum Keyboard { + /// The catalog's AccentColor in dark. + nonisolated static let appAccentDark: Color = Brand.green400 + /// The catalog's AccentColor in light. + nonisolated static let appAccentLight: Color = Brand.green700 + /// The catalog's CardBorder in dark. + nonisolated static let appCardBorderDark: Color = Brand.ink600 + /// The catalog's CardBorder in light. + nonisolated static let appCardBorderLight: Color = Brand.cardBorder + /// The catalog's CardFill in dark. + nonisolated static let appCardFillDark: Color = Brand.ink800 + /// The catalog's CardFill in light. + nonisolated static let appCardFillLight: Color = Brand.card + /// The panel's cancel ×. + nonisolated static let kbCancel: Color = Brand.orange + /// The one line of words the keyboard ever shows. + nonisolated static let kbFullAccessNote: Color = Brand.orange + /// An ordinary key. + nonisolated static let kbKey: Color = Themes.inkKey + /// Shift, delete, globe, return, 123, cancel. + nonisolated static let kbKeyModifier: Color = Themes.inkKeyModifier + /// Key legends and bare glyphs. + nonisolated static let kbLegend: Color = Themes.inkLegend + /// The solid ring and glyph for an error. + nonisolated static let kbNoticeError: Color = Brand.orange + /// The solid ring for pasted and copied. + nonisolated static let kbNoticeOk: Color = Brand.green400 + /// The sweeping ring's gradient, bottom-trailing. + nonisolated static let kbOrbRingEnd: Color = Brand.white + /// The sweeping ring's gradient, top-leading. + nonisolated static let kbOrbRingStart: Color = Brand.green700 + /// The letter pop-up. + nonisolated static let kbPopup: Color = Themes.inkPopup + /// The wave, the caret, the saved check. + nonisolated static let kbSignal: Color = Themes.inkSignal + /// The design theme's surface (Figma binds to kb/*; Swift reads the palette). + nonisolated static let kbSurface: Color = Themes.inkSurface + } + + enum Metrics { + /// The + from the panel's corner. + nonisolated static let addtermInset: CGFloat = 6 + /// The card's hairline. + nonisolated static let cardBorder: CGFloat = 1 + /// The app's cards. + nonisolated static let cardRadius: CGFloat = 16 + nonisolated static let caretHeight: CGFloat = 20 + /// The caret's gap from the text. + nonisolated static let caretLead: CGFloat = 1 + nonisolated static let caretRadius: CGFloat = 1 + nonisolated static let caretWidth: CGFloat = 2 + /// The carousel gesture's minimum distance. + nonisolated static let gestureSwipeMin: CGFloat = 24 + /// The +, × and ✓ touch targets. + nonisolated static let glyphHit: CGFloat = 32 + /// Between keys, the iPhone's. + nonisolated static let keyGap: CGFloat = 6 + /// Every key. + nonisolated static let keyHeight: CGFloat = 42 + /// A letter key at 402 pt (iPhone 18 Pro): (width − 9 × key/gap) / 10. + nonisolated static let keyLetterWidth402: CGFloat = 34.8 + /// A key that isn't given a width. + nonisolated static let keyMinWidth: CGFloat = 44 + /// A legend's side padding on a min-width key. + nonisolated static let keyPad: CGFloat = 4 + /// Flat keys, one colour at this corner. + nonisolated static let keyRadius: CGFloat = 8 + /// Return at 402 pt: two side keys and a gap. + nonisolated static let keyReturnWidth402: CGFloat = 104.4 + /// Shift and delete stand this many key gaps from the letters. + nonisolated static let keySideGapFactor: CGFloat = 2 + /// Shift, delete, 123 and globe at 402 pt: what seven letters leave, halved. + nonisolated static let keySideWidth402: CGFloat = 49.2 + /// 2 × margin/vertical + voicebar/height + 4 × row/gap + 4 × key/height. + nonisolated static let layoutFull: CGFloat = 272 + /// Chosen: room for the 96 orb over one key row. + nonisolated static let layoutPanel: CGFloat = 216 + /// 2 × margin/vertical + voicebar/height. + nonisolated static let layoutSlim: CGFloat = 60 + /// At the keyboard's sides. + nonisolated static let marginSide: CGFloat = 3 + /// The keyboard's top and bottom. + nonisolated static let marginVertical: CGFloat = 8 + /// The orb when Blurt isn't ready. + nonisolated static let opacityDim: CGFloat = 0.8 + /// And its saturation. + nonisolated static let opacityDimSaturation: CGFloat = 0.35 + /// The + without Full Access. + nonisolated static let opacityDisabled: CGFloat = 0.4 + nonisolated static let opacityGrain: CGFloat = 0.5 + /// The home hero's saturation when not listening. + nonisolated static let opacityHomeDimSaturation: CGFloat = 0.45 + /// The + at rest. + nonisolated static let opacityLegendMuted: CGFloat = 0.5 + nonisolated static let opacityOrbLight: CGFloat = 0.3 + /// The field's placeholder. + nonisolated static let opacityPlaceholder: CGFloat = 0.4 + nonisolated static let opacityPopupShadow: CGFloat = 0.12 + /// A key lightens this much while pressed. + nonisolated static let opacityPressBrighten: CGFloat = 0.15 + /// The field's ×. + nonisolated static let opacityTermCancel: CGFloat = 0.7 + /// The orb in the voice bar. + nonisolated static let orbBar: CGFloat = 40 + /// And blurs to this fraction of its size. + nonisolated static let orbDissipateBlur: CGFloat = 0.16 + /// The orb swells to this while dissipating. + nonisolated static let orbDissipateScale: CGFloat = 1.25 + /// The orb on the home screen. + nonisolated static let orbHome: CGFloat = 112 + /// The light's reach in points (fixed, not proportional — open). + nonisolated static let orbLightRadius: CGFloat = 110 + /// The soft light's centre, as a fraction of the orb. + nonisolated static let orbLightX: CGFloat = 0.3 + nonisolated static let orbLightY: CGFloat = 0.22 + /// The orb in the panel. + nonisolated static let orbPanel: CGFloat = 96 + /// Between the panel's orb and its key row. + nonisolated static let panelSpacing: CGFloat = 12 + /// The theme card draws the keyboard at this width. + nonisolated static let pickerPreviewWidth: CGFloat = 393 + /// The theme card's preview corners. + nonisolated static let pickerRadius: CGFloat = 10 + /// Then scales it to fit two across. + nonisolated static let pickerScale: CGFloat = 0.42 + /// The letter pop-up is the key width plus this. + nonisolated static let popupExtraWidth: CGFloat = 18 + nonisolated static let popupHeight: CGFloat = 56 + /// The pop-up sits this far above the key. + nonisolated static let popupOffset: CGFloat = 58 + nonisolated static let popupRadius: CGFloat = 10 + /// The one thing that floats. + nonisolated static let popupShadowRadius: CGFloat = 8 + nonisolated static let popupShadowY: CGFloat = 2 + /// The orb while pressed. + nonisolated static let pressScale: CGFloat = 0.94 + /// The ring while working or noticing; the home ring. + nonisolated static let ringActive: CGFloat = 2 + /// The ring at rest. + nonisolated static let ringStill: CGFloat = 1 + /// Between rows, the iPhone's. + nonisolated static let rowGap: CGFloat = 11 + /// Between the slim bar's keys. + nonisolated static let slimSpacing: CGFloat = 8 + /// × · field · ✓. + nonisolated static let termGap: CGFloat = 8 + /// The key-term field's capsule. + nonisolated static let termHeight: CGFloat = 36 + /// The field row's side inset. + nonisolated static let termInset: CGFloat = 2 + /// The field's side padding. + nonisolated static let termPad: CGFloat = 14 + /// The wave stays this clear of the + at the trailing edge. + nonisolated static let voicebarAddtermClearance: CGFloat = 12 + /// The voice row, where the system puts its suggestion bar. + nonisolated static let voicebarHeight: CGFloat = 44 + /// Between the orb and the Full Access note. + nonisolated static let voicebarNoteGap: CGFloat = 10 + /// A wave bar's width. + nonisolated static let waveBar: CGFloat = 2 + nonisolated static let waveBarHeight: CGFloat = 24 + /// The wave in the voice bar, at most. + nonisolated static let waveBarWidth: CGFloat = 240 + /// Between wave bars. + nonisolated static let waveGap: CGFloat = 2 + nonisolated static let waveHomeHeight: CGFloat = 44 + nonisolated static let waveHomeWidth: CGFloat = 280 + nonisolated static let wavePanelHeight: CGFloat = 40 + nonisolated static let wavePanelWidth: CGFloat = 300 + nonisolated static let wordmarkHeight: CGFloat = 22 + } + + enum Typography { + /// The clipboard and exclamation glyphs, as a fraction of the orb. + nonisolated static let ratioOrbGlyph: CGFloat = 0.34 + /// The +, × and ✓. + nonisolated static let sizeGlyph: CGFloat = 17 + /// Every other key. + nonisolated static let sizeLegend: CGFloat = 16 + /// Letter keys. + nonisolated static let sizeLetter: CGFloat = 22 + /// The letter pop-up. + nonisolated static let sizePopup: CGFloat = 32 + /// The key-term field. + nonisolated static let sizeTerm: CGFloat = 17 + nonisolated static let weightGlyph: Font.Weight = .medium + nonisolated static let weightLegend: Font.Weight = .medium + nonisolated static let weightLetter: Font.Weight = .regular + nonisolated static let weightOrbGlyph: Font.Weight = .semibold + nonisolated static let weightPopup: Font.Weight = .regular + nonisolated static let weightTerm: Font.Weight = .regular + } + + enum Motion { + /// The caret's blink. + nonisolated static let caret: Double = 0.5 + /// The violet drop is gone by. + nonisolated static let drop: Double = 2.4 + /// And held to. + nonisolated static let dropHold: Double = 0.9 + /// The drop is up in. + nonisolated static let dropRise: Double = 0.5 + /// The bloom reaches its full spread in. + nonisolated static let dropSpread: Double = 1 + /// The panel's carousel. + nonisolated static let flip: Double = 0.25 + /// The keyboard resizing. + nonisolated static let heightChange: Double = 0.25 + /// A key lighting. + nonisolated static let keyPress: Double = 0.08 + /// The orb's colour moving between moods. + nonisolated static let mood: Double = 0.8 + /// The orb's press; the one thing that answers at once. + nonisolated static let press: Double = 0.1 + /// One turn of the ring, the Mac's cadence. + nonisolated static let ringPeriod: Double = 1.6 + /// Every other change on the key: the ring, a glyph, the dimming. + nonisolated static let stateFade: Double = 0.5 + /// The voice bar becoming the field. + nonisolated static let termSwap: Double = 0.4 + /// The orb and the wave crossing, either way. + nonisolated static let waveFade: Double = 0.7 + } + + enum Gradients { + /// The Mac orb's fill, the design's own stops (App elements/Recording.svg), swept bottom to top. + nonisolated static let orb = LinearGradient( + stops: [ + .init(color: Brand.violetLavender, location: 0), + .init(color: Brand.violetPeriwinkle, location: 0.0673), + .init(color: Brand.green400, location: 0.1442), + .init(color: Brand.green700, location: 0.3029), + .init(color: Brand.cobolt, location: 0.5962), + .init(color: Brand.violetIris, location: 0.75), + .init(color: Brand.violetLavender, location: 0.8942), + .init(color: Brand.white, location: 1), + ], + startPoint: .bottom, endPoint: .top) + /// The ring round the orb: green into white, corner to corner; spun while something is happening. + nonisolated static let orbRing = LinearGradient( + stops: [ + .init(color: Brand.green700, location: 0), + .init(color: Brand.white, location: 1), + ], + startPoint: .topLeading, endPoint: .bottomTrailing) + } + + /// Every token as `group.name: value`, the way tokens.json renders it, so a + /// test can pin the compiled values to the file (`DesignTokensTests`). + nonisolated static let manifest: [String: String] = [ + "brand.apple/dark-key": "#6B6B6B", + "brand.apple/dark-modifier": "#464646", + "brand.apple/dark-surface": "#2B2B2B", + "brand.apple/light-modifier": "#ADB3BC", + "brand.apple/light-surface": "#D1D5DB", + "brand.black": "#000000", + "brand.card": "#EBE8E8", + "brand.card-border": "#DEDBDB", + "brand.cobolt": "#3923C7", + "brand.green/100": "#CCE4D5", + "brand.green/200": "#99C8AC", + "brand.green/400": "#67AD82", + "brand.green/700": "#01762F", + "brand.green/mist": "#DBF5E6", + "brand.ink": "#1D1B16", + "brand.ink/600": "#3A362F", + "brand.ink/700": "#33302A", + "brand.ink/800": "#26231E", + "brand.orange": "#E67F36", + "brand.page": "#FDFCF8", + "brand.violet/iris": "#887BDD", + "brand.violet/lavender": "#D7D3F4", + "brand.violet/periwinkle": "#B0A7E9", + "brand.warm-white": "#F2EEE6", + "brand.white": "#FFFFFF", + "themes.ink/key": "#33302A", + "themes.ink/key-modifier": "#26231E", + "themes.ink/legend": "#F2EEE6", + "themes.ink/popup": "#33302A", + "themes.ink/signal": "#67AD82", + "themes.ink/surface": "#1D1B16", + "themes.lavender/key": "#3F3777", + "themes.lavender/key-modifier": "#352E68", + "themes.lavender/legend": "#F1EEFF", + "themes.lavender/popup": "#3F3777", + "themes.lavender/signal": "#67AD82", + "themes.lavender/surface": "#2C2557", + "themes.midnight/key": "#1D2440", + "themes.midnight/key-modifier": "#161B33", + "themes.midnight/legend": "#E8ECFF", + "themes.midnight/popup": "#1D2440", + "themes.midnight/signal": "#67AD82", + "themes.midnight/surface": "#0E1220", + "themes.mint/key": "#1E3F31", + "themes.mint/key-modifier": "#183429", + "themes.mint/legend": "#E9F5EE", + "themes.mint/popup": "#1E3F31", + "themes.mint/signal": "#67AD82", + "themes.mint/surface": "#10231B", + "themes.paper/key": "#FFFFFF", + "themes.paper/key-modifier": "#DEDBDB", + "themes.paper/legend": "#1D1B16", + "themes.paper/popup": "#FFFFFF", + "themes.paper/signal": "#01762F", + "themes.paper/surface": "#EBE8E8", + "themes.sunset/key": "#4B2B20", + "themes.sunset/key-modifier": "#3B2119", + "themes.sunset/legend": "#FFEFE6", + "themes.sunset/popup": "#4B2B20", + "themes.sunset/signal": "#67AD82", + "themes.sunset/surface": "#2B1912", + "themes.system-dark/key": "#6B6B6B", + "themes.system-dark/key-modifier": "#464646", + "themes.system-dark/legend": "#FFFFFF", + "themes.system-dark/popup": "#6B6B6B", + "themes.system-dark/signal": "#67AD82", + "themes.system-dark/surface": "#2B2B2B", + "themes.system-light/key": "#FFFFFF", + "themes.system-light/key-modifier": "#ADB3BC", + "themes.system-light/legend": "#000000", + "themes.system-light/popup": "#FFFFFF", + "themes.system-light/signal": "#01762F", + "themes.system-light/surface": "#D1D5DB", + "keyboard.app/accent-dark": "#67AD82", + "keyboard.app/accent-light": "#01762F", + "keyboard.app/card-border-dark": "#3A362F", + "keyboard.app/card-border-light": "#DEDBDB", + "keyboard.app/card-fill-dark": "#26231E", + "keyboard.app/card-fill-light": "#EBE8E8", + "keyboard.kb/cancel": "#E67F36", + "keyboard.kb/full-access-note": "#E67F36", + "keyboard.kb/key": "#33302A", + "keyboard.kb/key-modifier": "#26231E", + "keyboard.kb/legend": "#F2EEE6", + "keyboard.kb/notice-error": "#E67F36", + "keyboard.kb/notice-ok": "#67AD82", + "keyboard.kb/orb-ring-end": "#FFFFFF", + "keyboard.kb/orb-ring-start": "#01762F", + "keyboard.kb/popup": "#33302A", + "keyboard.kb/signal": "#67AD82", + "keyboard.kb/surface": "#1D1B16", + "metrics.addterm/inset": "6", + "metrics.card/border": "1", + "metrics.card/radius": "16", + "metrics.caret/height": "20", + "metrics.caret/lead": "1", + "metrics.caret/radius": "1", + "metrics.caret/width": "2", + "metrics.gesture/swipe-min": "24", + "metrics.glyph/hit": "32", + "metrics.key/gap": "6", + "metrics.key/height": "42", + "metrics.key/letter-width-402": "34.8", + "metrics.key/min-width": "44", + "metrics.key/pad": "4", + "metrics.key/radius": "8", + "metrics.key/return-width-402": "104.4", + "metrics.key/side-gap-factor": "2", + "metrics.key/side-width-402": "49.2", + "metrics.layout/full": "272", + "metrics.layout/panel": "216", + "metrics.layout/slim": "60", + "metrics.margin/side": "3", + "metrics.margin/vertical": "8", + "metrics.opacity/dim": "0.8", + "metrics.opacity/dim-saturation": "0.35", + "metrics.opacity/disabled": "0.4", + "metrics.opacity/grain": "0.5", + "metrics.opacity/home-dim-saturation": "0.45", + "metrics.opacity/legend-muted": "0.5", + "metrics.opacity/orb-light": "0.3", + "metrics.opacity/placeholder": "0.4", + "metrics.opacity/popup-shadow": "0.12", + "metrics.opacity/press-brighten": "0.15", + "metrics.opacity/term-cancel": "0.7", + "metrics.orb/bar": "40", + "metrics.orb/dissipate-blur": "0.16", + "metrics.orb/dissipate-scale": "1.25", + "metrics.orb/home": "112", + "metrics.orb/light-radius": "110", + "metrics.orb/light-x": "0.3", + "metrics.orb/light-y": "0.22", + "metrics.orb/panel": "96", + "metrics.panel/spacing": "12", + "metrics.picker/preview-width": "393", + "metrics.picker/radius": "10", + "metrics.picker/scale": "0.42", + "metrics.popup/extra-width": "18", + "metrics.popup/height": "56", + "metrics.popup/offset": "58", + "metrics.popup/radius": "10", + "metrics.popup/shadow-radius": "8", + "metrics.popup/shadow-y": "2", + "metrics.press/scale": "0.94", + "metrics.ring/active": "2", + "metrics.ring/still": "1", + "metrics.row/gap": "11", + "metrics.slim/spacing": "8", + "metrics.term/gap": "8", + "metrics.term/height": "36", + "metrics.term/inset": "2", + "metrics.term/pad": "14", + "metrics.voicebar/addterm-clearance": "12", + "metrics.voicebar/height": "44", + "metrics.voicebar/note-gap": "10", + "metrics.wave/bar": "2", + "metrics.wave/bar-height": "24", + "metrics.wave/bar-width": "240", + "metrics.wave/gap": "2", + "metrics.wave/home-height": "44", + "metrics.wave/home-width": "280", + "metrics.wave/panel-height": "40", + "metrics.wave/panel-width": "300", + "metrics.wordmark/height": "22", + "type.ratio/orb-glyph": "0.34", + "type.size/glyph": "17", + "type.size/legend": "16", + "type.size/letter": "22", + "type.size/popup": "32", + "type.size/term": "17", + "type.weight/glyph": "medium", + "type.weight/legend": "medium", + "type.weight/letter": "regular", + "type.weight/orb-glyph": "semibold", + "type.weight/popup": "regular", + "type.weight/term": "regular", + "motion.caret": "0.5", + "motion.drop": "2.4", + "motion.drop-hold": "0.9", + "motion.drop-rise": "0.5", + "motion.drop-spread": "1", + "motion.flip": "0.25", + "motion.height-change": "0.25", + "motion.key-press": "0.08", + "motion.mood": "0.8", + "motion.press": "0.1", + "motion.ring-period": "1.6", + "motion.state-fade": "0.5", + "motion.term-swap": "0.4", + "motion.wave-fade": "0.7", + "gradients.orb": + "#D7D3F4@0 #B0A7E9@0.0673 #67AD82@0.1442 #01762F@0.3029 #3923C7@0.5962 #887BDD@0.75 #D7D3F4@0.8942 #FFFFFF@1 bottom>top", + "gradients.orb-ring": "#01762F@0 #FFFFFF@1 topLeading>bottomTrailing", + ] +} +// swiftlint:enable type_body_length diff --git a/App/BlurtiOS/Shared/SharedState.swift b/App/BlurtiOS/Shared/SharedState.swift index 438752e8..65511727 100644 --- a/App/BlurtiOS/Shared/SharedState.swift +++ b/App/BlurtiOS/Shared/SharedState.swift @@ -79,10 +79,11 @@ nonisolated enum KeyboardLayout: String, CaseIterable, Codable, Sendable, Identi /// The keyboard's height on screen, from the layout's rows at the iPhone /// keyboard's own spacing: see `App/BlurtiOS/DESIGN.md` for the arithmetic. var height: CGFloat { - switch self { - case .slimBar: 60 - case .panel: 216 - case .full: 272 + let metrics = DesignTokens.Metrics.self + return switch self { + case .slimBar: 2 * metrics.marginVertical + metrics.voicebarHeight + case .panel: metrics.layoutPanel + case .full: 2 * metrics.marginVertical + metrics.voicebarHeight + 4 * metrics.rowGap + 4 * metrics.keyHeight } } } diff --git a/App/BlurtiOS/project.yml b/App/BlurtiOS/project.yml index 97871133..6c8949bb 100644 --- a/App/BlurtiOS/project.yml +++ b/App/BlurtiOS/project.yml @@ -166,6 +166,10 @@ targets: platform: iOS sources: - path: BlurtiOSTests + # The design's one source, bundled so DesignTokensTests can pin the + # compiled DesignTokens.swift to the file it was generated from. + - path: Design/tokens.json + buildPhase: resources dependencies: - target: BlurtiOS settings: diff --git a/scripts/check.sh b/scripts/check.sh index 625ee3ae..4c526c38 100755 --- a/scripts/check.sh +++ b/scripts/check.sh @@ -401,6 +401,19 @@ check_invariants() { } run_check "settled decisions (AGENTS.md invariants)" check_invariants +# The design's one source (App/BlurtiOS/Design/tokens.json) and everything +# generated from it — Shared/DesignTokens.swift, DESIGN.md's token tables, the +# app's three colour sets — must agree, and the keyboard's views must carry no +# design literal that belongs in the tokens. scripts/design-sync.sh --check +# regenerates into .build/ and diffs, the same shape as the xcodegen drift +# check further down. It runs scripts/design-tokens.swift as a `swift` script, +# which --portable mode does without. +if [ "$PORTABLE" -eq 0 ]; then + run_check "design tokens in sync (scripts/design-sync.sh --check)" bash scripts/design-sync.sh --check +else + echo "==> design-sync.sh --check skipped in portable mode (needs swift)" +fi + # --------------------------------------------------------------------------- # Source-only checks run BEFORE the Swift build below, not after it. # diff --git a/scripts/design-capture.sh b/scripts/design-capture.sh new file mode 100755 index 00000000..0a449f27 --- /dev/null +++ b/scripts/design-capture.sh @@ -0,0 +1,104 @@ +#!/bin/bash +# Capture the keyboard from the simulator, one still per layout × state × theme, +# cropped to the keyboard's own pixels — the simulator side of the design loop +# (DESIGN.md › Figma). Each capture is deterministic: the gallery's +# -BlurtGalleryStill holds the orb, the ring and the wave at time zero, and +# -BlurtGalleryBare draws one row with a magenta registration border that +# scripts/design-diff.swift crops to. +# +# scripts/design-capture.sh # panel × the golden states × three themes +# scripts/design-capture.sh --layout full --states idle,recording,error --themes ink +# scripts/design-capture.sh --out .build/design/captures --no-build +# +# Writes /--@3x.png (1206 px wide on iPhone 18 Pro, +# the same pixel size as a Figma export at 3×, so the diff never resamples) +# plus /--.raw.png, the whole screen it was cut from. +set -euo pipefail + +REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" +cd "$REPO_ROOT" + +LAYOUT=panel +STATES=idle,recording,error,term +THEMES=system,system-dark,ink +OUT="$REPO_ROOT/.build/design/captures" +BUILD=1 +while [ $# -gt 0 ]; do + case "$1" in + --layout) + LAYOUT="${2:?}" + shift 2 + ;; + --states) + STATES="${2:?}" + shift 2 + ;; + --themes) + THEMES="${2:?}" + shift 2 + ;; + --out) + OUT="${2:?}" + shift 2 + ;; + --no-build) + BUILD=0 + shift + ;; + *) + echo "usage: design-capture.sh [--layout slimBar|panel|full] [--states a,b] [--themes a,b] [--out DIR] [--no-build]" >&2 + exit 2 + ;; + esac +done +mkdir -p "$OUT" + +# The layout's height in points, from the tokens the views are built on, so +# the crop can assert it got the whole keyboard and nothing else. +height_pt() { + python3 - "$1" <<'PY' +import json, sys +m = json.load(open("App/BlurtiOS/Design/tokens.json"))["metrics"] +v = lambda k: m[k]["value"] if isinstance(m[k], dict) else m[k] +print({"slimBar": v("layout/slim"), "panel": v("layout/panel"), "full": v("layout/full")}[sys.argv[1]]) +PY +} +HEIGHT_PT="$(height_pt "$LAYOUT")" + +# Build once; every capture after the first reuses it. +first=1 +IFS=, read -ra STATE_LIST <<<"$STATES" +IFS=, read -ra THEME_LIST <<<"$THEMES" +for theme in "${THEME_LIST[@]}"; do + for state in "${STATE_LIST[@]}"; do + name="$LAYOUT-$state-$theme" + raw="$OUT/$name.raw.png" + flags=(--screenshot "$raw") + if [ "$first" -eq 0 ] || [ "$BUILD" -eq 0 ]; then flags=(--no-build "${flags[@]}"); fi + first=0 + # `landed` is a moment, not a state: the drop peaks 0.6 s after the gallery's + # 2.4 s offset, so the default 3 s delay catches it; everything else is + # still by construction and needs only the launch to settle. + delay=1.5 + still=-BlurtGalleryStill + if [ "$state" = "landed" ]; then + delay=3 + still="" + fi + echo "==> $name" + BLURT_LAUNCH_ARGS="-BlurtGallery $LAYOUT $state $theme $still -BlurtGalleryBare" \ + BLURT_SHOT_DELAY="$delay" scripts/ios-sim.sh "${flags[@]}" >/dev/null + # The capture's scale: pixels across ÷ the device's points across. + scale="$(python3 -c ' +import subprocess, sys +out = subprocess.run(["sips", "-g", "pixelWidth", sys.argv[1]], capture_output=True, text=True).stdout +px = int(out.split()[-1]) +print(3 if px > 1000 else 2) +' "$raw")" + # `term` and `keys` show the full keyboard whatever layout was asked for. + expect=$((HEIGHT_PT * scale)) + case "$state" in term | keys) expect=$(($(height_pt full) * scale)) ;; esac + swift scripts/design-diff.swift crop "$raw" "$OUT/$name@${scale}x.png" --expect-height "$expect" + done +done +echo "design-capture: ${#STATE_LIST[@]} × ${#THEME_LIST[@]} captures of $LAYOUT in $OUT" diff --git a/scripts/design-diff.swift b/scripts/design-diff.swift new file mode 100755 index 00000000..9b9f865e --- /dev/null +++ b/scripts/design-diff.swift @@ -0,0 +1,297 @@ +#!/usr/bin/env swift // Pixel tools for the design loop, with no dependencies beyond AppKit — the // same shape as beautify.swift and screenshot.swift. Three commands: +// +// swift scripts/design-diff.swift crop [--expect-height ] +// Cuts the keyboard out of a whole-screen simulator capture: finds the +// magenta (#FF00FF) registration border the gallery's -BlurtGalleryBare +// mode draws round the row and writes what is inside it. With +// --expect-height, fails unless the crop is that tall (±1 px). +// +// swift scripts/design-diff.swift diff --out --json +// [--mask x,y,w,h]... [--threshold 8] +// Compares two same-sized images pixel by pixel, both converted to sRGB +// first (a simulator capture carries the display's profile, a Figma +// export is sRGB). Reports, for the whole image and for everything +// outside the masks, the fraction of pixels whose largest channel +// difference exceeds the threshold (AE) and the root-mean-square +// difference (RMSE, 0–1); each mask is reported on its own. Writes a +// triptych: a | b | heat map (difference in red, masks tinted blue). +// Masks are in pixels of the images given. +// +// swift scripts/design-diff.swift sheet --out --columns [--scale ] =... +// A contact sheet: the images in a grid with their captions under them. +// +// Every image is read into an 8-bit sRGB RGBA buffer through CoreGraphics, so +// the numbers do not depend on how the PNG was tagged. + +import AppKit + +struct Pixels { + let width: Int + let height: Int + var bytes: [UInt8] // RGBA, sRGB, not premultiplied in any way that matters for opaque captures + + subscript(x: Int, y: Int) -> (r: Int, g: Int, b: Int) { + let i = (y * width + x) * 4 + return (Int(bytes[i]), Int(bytes[i + 1]), Int(bytes[i + 2])) + } +} + +func fail(_ message: String) -> Never { + FileHandle.standardError.write(Data("design-diff: \(message)\n".utf8)) + exit(1) +} + +func load(_ path: String) -> Pixels { + guard let image = NSImage(contentsOfFile: path), + let cgImage = image.cgImage(forProposedRect: nil, context: nil, hints: nil) + else { fail("could not read \(path)") } + let width = cgImage.width + let height = cgImage.height + var bytes = [UInt8](repeating: 0, count: width * height * 4) + guard let space = CGColorSpace(name: CGColorSpace.sRGB), + let context = CGContext( + data: &bytes, width: width, height: height, bitsPerComponent: 8, bytesPerRow: width * 4, space: space, + bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue) + else { fail("could not make an sRGB context for \(path)") } + context.draw(cgImage, in: CGRect(x: 0, y: 0, width: width, height: height)) + return Pixels(width: width, height: height, bytes: bytes) +} + +func save(_ pixels: Pixels, to path: String) { + var bytes = pixels.bytes + guard let space = CGColorSpace(name: CGColorSpace.sRGB), + let context = CGContext( + data: &bytes, width: pixels.width, height: pixels.height, bitsPerComponent: 8, bytesPerRow: pixels.width * 4, + space: space, bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue), + let image = context.makeImage() + else { fail("could not make an image for \(path)") } + let rep = NSBitmapImageRep(cgImage: image) + guard let data = rep.representation(using: .png, properties: [:]) else { fail("could not encode \(path)") } + do { try data.write(to: URL(fileURLWithPath: path)) } catch { fail("could not write \(path): \(error)") } +} + +func flag(_ name: String, in args: inout [String]) -> String? { + guard let i = args.firstIndex(of: name), i + 1 < args.count else { return nil } + let value = args[i + 1] + args.removeSubrange(i...(i + 1)) + return value +} + +func flags(_ name: String, in args: inout [String]) -> [String] { + var values: [String] = [] + while let value = flag(name, in: &args) { values.append(value) } + return values +} + +// MARK: - crop + +func isSentinel(_ p: (r: Int, g: Int, b: Int)) -> Bool { + abs(p.r - 255) <= 6 && p.g <= 6 && abs(p.b - 255) <= 6 +} + +func crop(_ args: [String]) { + var args = args + let expected = flag("--expect-height", in: &args).map { Int($0) ?? -1 } + guard args.count == 2 else { fail("crop [--expect-height ]") } + let source = load(args[0]) + var minX = Int.max + var minY = Int.max + var maxX = -1 + var maxY = -1 + for y in 0..= 0 else { fail("no #FF00FF registration border in \(args[0]) — launch with -BlurtGalleryBare") } + // The border's thickness: walk down from the top edge along the middle + // column. The sides may have no border at all — the keyboard rows are drawn + // at the phone's full width, bordered above and below only — so each side is + // inset only where the middle row does start with the sentinel. + let midX = (minX + maxX) / 2 + let midY = (minY + maxY) / 2 + var thickness = 0 + while minY + thickness <= maxY, isSentinel(source[midX, minY + thickness]) { thickness += 1 } + guard thickness > 0, thickness < 40 else { fail("registration border looks wrong (thickness \(thickness))") } + let leftInset = isSentinel(source[minX, midY]) ? thickness : 0 + let rightInset = isSentinel(source[maxX, midY]) ? thickness : 0 + let x0 = minX + leftInset + let y0 = minY + thickness + let width = maxX - minX + 1 - leftInset - rightInset + let height = maxY - minY + 1 - 2 * thickness + guard width > 0, height > 0 else { fail("registration border encloses nothing") } + if let expected, abs(height - expected) > 1 { + fail("crop is \(height) px tall, expected \(expected) (the layout height × the device scale)") + } + var out = Pixels(width: width, height: height, bytes: [UInt8](repeating: 0, count: width * height * 4)) + for y in 0.. Bool { px >= x && px < x + w && py >= y && py < y + h } +} + +func diff(_ args: [String]) { + var args = args + guard let outPath = flag("--out", in: &args), let jsonPath = flag("--json", in: &args) else { + fail("diff --out --json [--mask x,y,w,h]... [--threshold n]") + } + let threshold = Int(flag("--threshold", in: &args) ?? "8") ?? 8 + let masks = flags("--mask", in: &args).map { spec -> Rect in + let parts = spec.split(separator: ",").compactMap { Int($0) } + guard parts.count == 4 else { fail("mask must be x,y,w,h: \(spec)") } + return Rect(x: parts[0], y: parts[1], w: parts[2], h: parts[3]) + } + guard args.count == 2 else { fail("diff needs two images") } + let a = load(args[0]) + let b = load(args[1]) + guard a.width == b.width, a.height == b.height else { + fail("sizes differ: \(a.width)×\(a.height) vs \(b.width)×\(b.height) — never resample; fix the export scale") + } + var total = 0 + var differing = 0 + var squares = 0.0 + var chromeTotal = 0 + var chromeDiffering = 0 + var chromeSquares = 0.0 + var maskDiffering = [Int](repeating: 0, count: masks.count) + var maskTotal = [Int](repeating: 0, count: masks.count) + var heat = Pixels( + width: a.width * 3, height: a.height, bytes: [UInt8](repeating: 255, count: a.width * 3 * a.height * 4)) + for y in 0.. threshold + let normalized = Double(delta) / 255 + total += 1 + if over { differing += 1 } + squares += normalized * normalized + let maskIndex = masks.firstIndex { $0.contains(x, y) } + if let maskIndex { + maskTotal[maskIndex] += 1 + if over { maskDiffering[maskIndex] += 1 } + } else { + chromeTotal += 1 + if over { chromeDiffering += 1 } + chromeSquares += normalized * normalized + } + // Triptych: a, b, heat. + let ia = (y * heat.width + x) * 4 + heat.bytes[ia] = UInt8(pa.r) + heat.bytes[ia + 1] = UInt8(pa.g) + heat.bytes[ia + 2] = UInt8(pa.b) + let ib = (y * heat.width + a.width + x) * 4 + heat.bytes[ib] = UInt8(pb.r) + heat.bytes[ib + 1] = UInt8(pb.g) + heat.bytes[ib + 2] = UInt8(pb.b) + let ih = (y * heat.width + 2 * a.width + x) * 4 + let strength = UInt8(min(255, delta * 4)) + if maskIndex != nil { + heat.bytes[ih] = 230 - strength / 2 + heat.bytes[ih + 1] = 236 - strength / 2 + heat.bytes[ih + 2] = 255 + } else { + heat.bytes[ih] = 255 + heat.bytes[ih + 1] = 255 - strength + heat.bytes[ih + 2] = 255 - strength + } + } + } + save(heat, to: outPath) + func fraction(_ n: Int, _ d: Int) -> Double { d == 0 ? 0 : Double(n) / Double(d) } + var metrics: [String: Any] = [ + "width": a.width, "height": a.height, "threshold": threshold, + "all": ["ae": fraction(differing, total), "rmse": (squares / Double(max(total, 1))).squareRoot()], + "chrome": [ + "ae": fraction(chromeDiffering, chromeTotal), "rmse": (chromeSquares / Double(max(chromeTotal, 1))).squareRoot(), + "pixels": chromeTotal, + ], + ] + metrics["masks"] = masks.enumerated().map { i, rect in + ["x": rect.x, "y": rect.y, "w": rect.w, "h": rect.h, "ae": fraction(maskDiffering[i], maskTotal[i])] + } + guard let data = try? JSONSerialization.data(withJSONObject: metrics, options: [.prettyPrinted, .sortedKeys]) else { + fail("could not encode metrics") + } + do { try data.write(to: URL(fileURLWithPath: jsonPath)) } catch { fail("could not write \(jsonPath): \(error)") } + func percent(_ value: Double) -> String { String(format: "%.3f%%", value * 100) } + let chromeRMSE = String(format: "%.4f", (chromeSquares / Double(max(chromeTotal, 1))).squareRoot()) + print( + "diff: chrome AE \(percent(fraction(chromeDiffering, chromeTotal))) RMSE \(chromeRMSE)" + + " · all AE \(percent(fraction(differing, total))) · \(masks.count) masks → \(outPath)") +} + +// MARK: - sheet + +func sheet(_ args: [String]) { + var args = args + guard let outPath = flag("--out", in: &args), let columns = Int(flag("--columns", in: &args) ?? "") else { + fail("sheet --out --columns [--scale ] =...") + } + let scale = CGFloat(Double(flag("--scale", in: &args) ?? "0.5") ?? 0.5) + let entries = args.map { arg -> (String, NSImage) in + guard let eq = arg.firstIndex(of: "=") else { fail("each cell is caption=path: \(arg)") } + let path = String(arg[arg.index(after: eq)...]) + guard let image = NSImage(contentsOfFile: path) else { fail("could not read \(path)") } + return (String(arg[..` when it is +# genuinely local (a divide-by-two, a geometry derivation). +set -euo pipefail + +REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" +cd "$REPO_ROOT" + +CHECK=0 +if [ "${1:-}" = "--check" ]; then + CHECK=1 +elif [ -n "${1:-}" ]; then + echo "usage: scripts/design-sync.sh [--check]" >&2 + exit 2 +fi + +if command -v xcrun >/dev/null 2>&1 && xcrun --find swift-format >/dev/null 2>&1; then + SWIFT_FORMAT=(xcrun swift-format) +elif command -v swift-format >/dev/null 2>&1; then + SWIFT_FORMAT=(swift-format) +else + SWIFT_FORMAT=() +fi + +OUTPUTS=( + App/BlurtiOS/Shared/DesignTokens.swift + App/BlurtiOS/DESIGN.md + App/BlurtiOS/BlurtiOS/Assets.xcassets/AccentColor.colorset/Contents.json + App/BlurtiOS/BlurtiOS/Assets.xcassets/CardFill.colorset/Contents.json + App/BlurtiOS/BlurtiOS/Assets.xcassets/CardBorder.colorset/Contents.json +) + +# Format the generated files the way check.sh expects the tree to be formatted, +# so a regeneration never fails swift-format or prettier on its own output. +# `--ignore-path /dev/null`: .prettierignore excludes .build/, where --check +# writes, and an explicitly named ignored file is skipped, not formatted. +format_outputs() { + local root="$1" + if [ "${#SWIFT_FORMAT[@]}" -gt 0 ]; then + "${SWIFT_FORMAT[@]}" format --in-place "$root/App/BlurtiOS/Shared/DesignTokens.swift" + fi + if command -v prettier >/dev/null 2>&1; then + prettier --log-level warn --ignore-path /dev/null --write "$root/App/BlurtiOS/DESIGN.md" >/dev/null + fi +} + +# The design-literal lint. Scope: the keyboard's view files. PrismOrb.swift is +# deliberately out — its body is the orb's recipe (mesh drift, sparkle spots, +# grain density), documented as text in Figma, and only its parameters are +# tokens. Numbers 0 and 1 pass: `Spacer(minLength: 0)`, `.opacity(on ? 1 : 0)` +# and `scaleEffect(1 + …)` are structure, not design. +lint_literals() { + python3 - <<'PY' +import re, sys +files = [ + "App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift", + "App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift", + "App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift", + "App/BlurtiOS/BlurtKeyboard/Sources/Dissipate.swift", + "App/BlurtiOS/BlurtKeyboard/Sources/BrandOrb.swift", +] +modifiers = re.compile( + r"\.(padding|frame|font|blur|scaleEffect|offset|shadow|opacity|cornerRadius|saturation|brightness" + r"|strokeBorder|stroke|lineWidth)\(|\b(spacing|duration|minimumDistance|lineWidth|radius|size|width|height|by):" +) +number = re.compile(r"(?/dev/null +format_outputs "$STAGE" +DRIFT=0 +for file in "${OUTPUTS[@]}"; do + if ! diff -u "$file" "$STAGE/$file" >"$STAGE/diff.txt" 2>&1; then + echo "error: $file is out of sync with App/BlurtiOS/Design/tokens.json:" >&2 + head -40 "$STAGE/diff.txt" >&2 + DRIFT=1 + fi +done +if [ "$DRIFT" -ne 0 ]; then + echo " run scripts/design-sync.sh and commit the result" >&2 + exit 1 +fi +echo "design-sync: ${#OUTPUTS[@]} generated files match tokens.json" +lint_literals diff --git a/scripts/design-tokens.swift b/scripts/design-tokens.swift new file mode 100755 index 00000000..5b175975 --- /dev/null +++ b/scripts/design-tokens.swift @@ -0,0 +1,438 @@ +#!/usr/bin/env swift // The design's one source of numbers and colours, fanned out: reads +// App/BlurtiOS/Design/tokens.json (exported from the Figma file, hand-written +// before it existed) and writes everything that used to repeat those values by +// hand — `App/BlurtiOS/Shared/DesignTokens.swift`, the generated tables in +// `App/BlurtiOS/DESIGN.md`, and the app's three asset-catalog colour sets. Run +// through scripts/design-sync.sh, which also formats the output and, with +// --check, fails on drift the way check.sh fails on a stale .pbxproj. +// +// swift scripts/design-tokens.swift [--root ] +// +// Inputs are always read from the repo; `--root` redirects the outputs (the +// drift check writes into .build/ and diffs). A `swift` script run from disk +// can't import the app, so this is plain Foundation. +// +// Token values: a hex string ("#01762F"), a number, a weight name, or an alias +// to another token in braces ("{brand.green/700}", the DTCG spelling). A value +// may be wrapped as {"value": …, "use": "one line for DESIGN.md"}. Swift names +// derive from token names by one rule — `kb/key-modifier` → `kbKeyModifier`, +// `green/700` → `green700` — and the Figma build script sets the same string +// as each variable's iOS code syntax, so the two can't disagree. + +import Foundation + +// MARK: - Arguments and paths + +let scriptURL = URL(fileURLWithPath: CommandLine.arguments[0]).standardizedFileURL +let repoRoot = scriptURL.deletingLastPathComponent().deletingLastPathComponent() +var outputRoot = repoRoot +var arguments = Array(CommandLine.arguments.dropFirst()) +while !arguments.isEmpty { + let flag = arguments.removeFirst() + switch flag { + case "--root": + guard !arguments.isEmpty else { fail("--root needs a directory") } + outputRoot = URL(fileURLWithPath: arguments.removeFirst()).standardizedFileURL + default: + fail("unknown argument \(flag)") + } +} + +let tokensPath = "App/BlurtiOS/Design/tokens.json" +let swiftPath = "App/BlurtiOS/Shared/DesignTokens.swift" +let designPath = "App/BlurtiOS/DESIGN.md" +let catalogPath = "App/BlurtiOS/BlurtiOS/Assets.xcassets" + +func fail(_ message: String) -> Never { + FileHandle.standardError.write(Data("design-tokens: \(message)\n".utf8)) + exit(1) +} + +// MARK: - The model + +enum Value { + case color(String) // "#RRGGBB" + case number(Double) + case word(String) // a font weight + case alias(String) // "group.name" +} + +struct Token { + let group: String + let name: String + let value: Value + let use: String? + + var qualified: String { "\(group).\(name)" } + var swiftName: String { camel(name) } +} + +struct Stop { + let color: String // alias or hex + let location: Double +} + +struct Gradient { + let name: String + let use: String? + let start: String + let end: String + let stops: [Stop] +} + +/// `kb/key-modifier` → `kbKeyModifier`; `green/700` → `green700`. +func camel(_ name: String) -> String { + let parts = name.split(whereSeparator: { "/-.".contains($0) }).map(String.init) + guard let first = parts.first else { return name } + return ([first.lowercased()] + parts.dropFirst().map { $0.prefix(1).uppercased() + $0.dropFirst() }).joined() +} + +/// A group name to its Swift enum: `brand` → `Brand`. `type` becomes +/// `Typography`, since a member named `Type` is not allowed in Swift. +func typeName(_ group: String) -> String { + group == "type" ? "Typography" : group.prefix(1).uppercased() + group.dropFirst() +} + +func parseValue(_ raw: Any) -> Value { + if let number = raw as? NSNumber, CFGetTypeID(number) != CFBooleanGetTypeID() { + return .number(number.doubleValue) + } + guard let string = raw as? String else { fail("a token value must be a string or a number, got \(raw)") } + if string.hasPrefix("{"), string.hasSuffix("}") { return .alias(String(string.dropFirst().dropLast())) } + if string.hasPrefix("#") { + guard string.count == 7, string.dropFirst().allSatisfy(\.isHexDigit) else { fail("bad colour \(string)") } + return .color(string.uppercased()) + } + return .word(string) +} + +// MARK: - Read + +let tokensURL = repoRoot.appendingPathComponent(tokensPath) +guard let data = FileManager.default.contents(atPath: tokensURL.path), + let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] +else { fail("could not read \(tokensPath)") } + +let groups = ["brand", "themes", "keyboard", "metrics", "type", "motion"] +var tokens: [Token] = [] +var byQualified: [String: Token] = [:] +for group in groups { + guard let entries = json[group] as? [String: Any] else { fail("tokens.json has no \(group) group") } + for name in entries.keys.sorted() { + let entry = entries[name]! + let token: Token + if let wrapped = entry as? [String: Any] { + guard let raw = wrapped["value"] else { fail("\(group).\(name) has no value") } + token = Token(group: group, name: name, value: parseValue(raw), use: wrapped["use"] as? String) + } else { + token = Token(group: group, name: name, value: parseValue(entry), use: nil) + } + tokens.append(token) + byQualified[token.qualified] = token + } +} + +var gradients: [Gradient] = [] +if let entries = json["gradients"] as? [String: Any] { + for name in entries.keys.sorted() { + guard let entry = entries[name] as? [String: Any], let start = entry["start"] as? String, + let end = entry["end"] as? String, let stops = entry["stops"] as? [[String: Any]] + else { fail("gradients.\(name) needs start, end and stops") } + gradients.append( + Gradient( + name: name, use: entry["use"] as? String, start: start, end: end, + stops: stops.map { stop in + guard let color = stop["color"] as? String, let location = stop["location"] as? NSNumber else { + fail("gradients.\(name) has a stop without color and location") + } + return Stop(color: color, location: location.doubleValue) + })) + } +} + +// MARK: - Resolve + +/// Follows aliases to the concrete token, refusing cycles and dangling names. +func resolve(_ token: Token, seen: [String] = []) -> Token { + guard case .alias(let target) = token.value else { return token } + guard !seen.contains(target) else { fail("alias cycle at \(token.qualified)") } + guard let next = byQualified[target] else { fail("\(token.qualified) aliases \(target), which does not exist") } + return resolve(next, seen: seen + [token.qualified]) +} + +func resolveColor(_ reference: String) -> String { + let value = parseValue(reference) + switch value { + case .color(let hex): return hex + case .alias(let target): + guard let token = byQualified[target] else { fail("\(reference) does not exist") } + guard case .color(let hex) = resolve(token).value else { fail("\(reference) is not a colour") } + return hex + default: fail("\(reference) is not a colour") + } +} + +func format(_ number: Double) -> String { + if number == number.rounded(), abs(number) < 1e9 { return String(Int(number)) } + return String(number) +} + +/// The value as the manifest and the docs print it. +func rendered(_ token: Token) -> String { + switch resolve(token).value { + case .color(let hex): return hex + case .number(let number): return format(number) + case .word(let word): return word + case .alias: fatalError("unreachable") + } +} + +for token in tokens { _ = resolve(token) } // every alias must land + +// MARK: - Swift + +let weights = ["ultraLight", "thin", "light", "regular", "medium", "semibold", "bold", "heavy", "black"] + +func swiftLiteral(_ token: Token) -> (type: String, literal: String) { + switch token.value { + case .color(let hex): return ("Color", "Color(hex: 0x\(hex.dropFirst()))") + case .number(let number): + return (token.group == "motion" ? "Double" : "CGFloat", format(number)) + case .word(let word): + guard weights.contains(word) else { fail("\(token.qualified): \(word) is not a font weight") } + return ("Font.Weight", ".\(word)") + case .alias(let target): + guard let other = byQualified[target] else { fail("\(target) does not exist") } + return (swiftLiteral(other).type, "\(typeName(other.group)).\(other.swiftName)") + } +} + +func swiftColorReference(_ reference: String) -> String { + let value = parseValue(reference) + switch value { + case .color(let hex): return "Color(hex: 0x\(hex.dropFirst()))" + case .alias(let target): + guard let other = byQualified[target] else { fail("\(target) does not exist") } + return "\(typeName(other.group)).\(other.swiftName)" + default: fail("\(reference) is not a colour") + } +} + +func docComment(_ text: String?, indent: String) -> String { + guard let text, !text.isEmpty else { return "" } + return "\(indent)/// \(text.prefix(1).uppercased() + text.dropFirst()).\n" +} + +var swift = """ + // Generated by scripts/design-tokens.swift from App/BlurtiOS/Design/tokens.json — do not edit. + // Regenerate with scripts/design-sync.sh; scripts/check.sh fails on drift. + // periphery:ignore:all + // swiftlint:disable file_length + import SwiftUI + + // swiftlint:disable type_body_length + /// The design's colours and numbers, from the one source Figma exports + /// (`Design/tokens.json`): what the views draw with, what DESIGN.md's tables + /// say, and what the asset catalog holds, all from the same file. Swift names + /// follow the token names by one rule (`kb/key-modifier` → `kbKeyModifier`), + /// the same rule the Figma build script uses for iOS code syntax. + enum DesignTokens { + + """ + +for group in groups { + swift += " enum \(typeName(group)) {\n" + for token in tokens where token.group == group { + let (type, literal) = swiftLiteral(token) + let use = token.use.map { $0 } ?? (token.value.isAlias ? "`\(aliasTarget(token))`" : nil) + swift += docComment(use, indent: " ") + swift += " nonisolated static let \(token.swiftName): \(type) = \(literal)\n" + } + swift += " }\n\n" +} + +swift += " enum Gradients {\n" +for gradient in gradients { + swift += docComment(gradient.use, indent: " ") + swift += " nonisolated static let \(camel(gradient.name)) = LinearGradient(\n stops: [\n" + for stop in gradient.stops { + swift += " .init(color: \(swiftColorReference(stop.color)), location: \(format(stop.location))),\n" + } + swift += " ],\n startPoint: .\(gradient.start), endPoint: .\(gradient.end))\n" +} +swift += " }\n\n" + +swift += """ + /// Every token as `group.name: value`, the way tokens.json renders it, so a + /// test can pin the compiled values to the file (`DesignTokensTests`). + nonisolated static let manifest: [String: String] = [ + + """ +for token in tokens { + swift += " \"\(token.qualified)\": \"\(rendered(token))\",\n" +} +for gradient in gradients { + let stops = gradient.stops.map { "\(resolveColor($0.color))@\(format($0.location))" }.joined(separator: " ") + swift += " \"gradients.\(gradient.name)\": \"\(stops) \(gradient.start)>\(gradient.end)\",\n" +} +swift += " ]\n}\n// swiftlint:enable type_body_length\n" + +extension Value { + var isAlias: Bool { + if case .alias = self { return true } + return false + } +} + +func aliasTarget(_ token: Token) -> String { + if case .alias(let target) = token.value { return target } + return "" +} + +// MARK: - DESIGN.md + +func table(_ header: [String], _ rows: [[String]]) -> String { + var lines = ["| " + header.joined(separator: " | ") + " |"] + lines.append("| " + header.map { _ in "---" }.joined(separator: " | ") + " |") + for row in rows { lines.append("| " + row.joined(separator: " | ") + " |") } + return lines.joined(separator: "\n") +} + +func code(_ text: String) -> String { "`\(text)`" } + +func tokenRows(_ group: String, valueLabel: String) -> String { + let rows = tokens.filter { $0.group == group }.map { token -> [String] in + var value = code(rendered(token)) + if case .alias(let target) = token.value { value += " (" + code(target) + ")" } + return [code(token.name), value, code("\(typeName(group)).\(token.swiftName)"), token.use ?? "—"] + } + return table(["Token", valueLabel, "Swift", "Use"], rows) +} + +var blocks: [String: String] = [:] +blocks["brand"] = tokenRows("brand", valueLabel: "Value") +blocks["keyboard"] = tokenRows("keyboard", valueLabel: "Value") +blocks["metrics"] = tokenRows("metrics", valueLabel: "Points") +blocks["type"] = tokenRows("type", valueLabel: "Value") +blocks["motion"] = tokenRows("motion", valueLabel: "Seconds") + +let themeNames = tokens.filter { $0.group == "themes" }.map { String($0.name.split(separator: "/")[0]) } +let themeOrder = + ["system-light", "system-dark", "ink", "paper", "lavender", "mint", "midnight", "sunset"] + + Set(themeNames).subtracting([ + "system-light", "system-dark", "ink", "paper", "lavender", "mint", "midnight", "sunset", + ]) + .sorted() +let roles = ["surface", "key", "key-modifier", "legend", "signal", "popup"] +blocks["themes"] = table( + ["Theme", "Surface", "Key", "Modifier", "Legend", "Signal", "Pop-up"], + themeOrder.compactMap { theme -> [String]? in + let cells = roles.compactMap { role in byQualified["themes.\(theme)/\(role)"].map { code(rendered($0)) } } + guard cells.count == roles.count else { return nil } + return [code(theme)] + cells + }) + +blocks["gradients"] = gradients.map { gradient in + let stops = gradient.stops.map { "\(code(resolveColor($0.color))) at \(format($0.location))" } + .joined(separator: ", ") + return + "- \(code(gradient.name)) (\(code("Gradients.\(camel(gradient.name))")), \(gradient.start) → \(gradient.end)): \(stops)" + + (gradient.use.map { " — \($0)" } ?? "") +}.joined(separator: "\n") + +let designURL = repoRoot.appendingPathComponent(designPath) +guard var design = try? String(contentsOf: designURL, encoding: .utf8) else { fail("could not read \(designPath)") } +var replaced: Set = [] +for (name, body) in blocks { + let begin = "" + let end = "" + guard let beginRange = design.range(of: begin), + let endRange = design.range(of: end, range: beginRange.upperBound.. String { + // Xcode's own layout, byte for byte: eight spaces in front of the colour's + // keys, ten in front of its components. + func components(_ hex: String) -> String { + let digits = Array(hex.dropFirst()) + let red = String(digits[0...1]) + let green = String(digits[2...3]) + let blue = String(digits[4...5]) + return [ + " \"color-space\" : \"srgb\",", + " \"components\" : {", + " \"alpha\" : \"1.000\",", + " \"blue\" : \"0x\(blue)\",", + " \"green\" : \"0x\(green)\",", + " \"red\" : \"0x\(red)\"", + " }", + ].joined(separator: "\n") + } + return """ + { + "colors" : [ + { + "color" : { + \(components(light)) + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + \(components(dark)) + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } + } + + """ +} + +let colorSets: [(String, String, String)] = [ + ("AccentColor", "keyboard.app/accent-light", "keyboard.app/accent-dark"), + ("CardFill", "keyboard.app/card-fill-light", "keyboard.app/card-fill-dark"), + ("CardBorder", "keyboard.app/card-border-light", "keyboard.app/card-border-dark"), +] + +// MARK: - Write + +func write(_ text: String, to relative: String) { + let url = outputRoot.appendingPathComponent(relative) + do { + try FileManager.default.createDirectory(at: url.deletingLastPathComponent(), withIntermediateDirectories: true) + try text.write(to: url, atomically: true, encoding: .utf8) + } catch { + fail("could not write \(relative): \(error)") + } +} + +write(swift, to: swiftPath) +write(design, to: designPath) +for (set, light, dark) in colorSets { + guard let lightToken = byQualified[light], let darkToken = byQualified[dark] else { + fail("\(set) needs \(light) and \(dark)") + } + write( + catalog(light: rendered(lightToken), dark: rendered(darkToken)), to: "\(catalogPath)/\(set).colorset/Contents.json") +} +print( + "design-tokens: \(tokens.count) tokens, \(gradients.count) gradients → \(swiftPath), \(designPath) (\(replaced.count) blocks), \(colorSets.count) colour sets" +) diff --git a/scripts/ios-record.sh b/scripts/ios-record.sh new file mode 100755 index 00000000..9d2cc824 --- /dev/null +++ b/scripts/ios-record.sh @@ -0,0 +1,97 @@ +#!/bin/bash +# Record the keyboard's motion from the simulator: the gallery's `live` state +# walks a whole dictation on a clock (about 11.7 s a cycle), this records two +# cycles and cuts one clean loop, cropped to the keyboard, for the review packet +# and for the Figma motion page's keyframes (DESIGN.md › Figma). +# +# scripts/ios-record.sh # panel, ink → .build/design/loops/panel-ink.mp4 +# scripts/ios-record.sh --layout slimBar --theme system --out ~/Desktop/blurt-review +# scripts/ios-record.sh --frames 0,0.35,0.7 # also grab stills at these seconds into the loop +# +# Needs ffmpeg (Brewfile). The crop comes from a still capture of the same +# layout taken first, so the video's frame is the keyboard's own pixels. +set -euo pipefail + +REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" +cd "$REPO_ROOT" +# shellcheck source=scripts/ios-lib.sh +source "$REPO_ROOT/scripts/ios-lib.sh" + +LAYOUT=panel +THEME=ink +OUT="$REPO_ROOT/.build/design/loops" +FRAMES="" +CYCLE=11.7 +while [ $# -gt 0 ]; do + case "$1" in + --layout) + LAYOUT="${2:?}" + shift 2 + ;; + --theme) + THEME="${2:?}" + shift 2 + ;; + --out) + OUT="${2:?}" + shift 2 + ;; + --frames) + FRAMES="${2:?}" + shift 2 + ;; + *) + echo "usage: ios-record.sh [--layout L] [--theme T] [--out DIR] [--frames s,s,…]" >&2 + exit 2 + ;; + esac +done +command -v ffmpeg >/dev/null || { + echo "ios-record: ffmpeg not installed (brew bundle)" >&2 + exit 1 +} +mkdir -p "$OUT" +name="$LAYOUT-$THEME" + +# A still first: it builds, boots, and gives the crop rectangle. +scripts/design-capture.sh --layout "$LAYOUT" --states idle --themes "$THEME" --out "$OUT/.still" >/dev/null +raw="$OUT/.still/$LAYOUT-idle-$THEME.raw.png" +read -r CROP_W CROP_H CROP_X CROP_Y < <(swift scripts/design-diff.swift crop "$raw" "$OUT/.still/crop-probe.png" \ + | sed -E 's/crop: ([0-9]+)×([0-9]+) at \(([0-9]+),([0-9]+)\).*/\1 \2 \3 \4/') +[ -n "${CROP_W:-}" ] || { + echo "ios-record: could not read the crop from $raw" >&2 + exit 1 +} + +PICKED="$(ios_pick_device "${BLURT_SIM_DEVICE:-iPhone 18 Pro}")" +UDID="${PICKED%% *}" +BUNDLE_ID=dev.alex.blurt.ios + +echo "==> recording $name (two cycles)" +xcrun simctl terminate "$UDID" "$BUNDLE_ID" 2>/dev/null || true +movie="$OUT/$name.raw.mov" +rm -f "$movie" +xcrun simctl io "$UDID" recordVideo --codec h264 --force "$movie" & +REC=$! +sleep 1 +xcrun simctl launch "$UDID" "$BUNDLE_ID" -BlurtGallery "$LAYOUT" live "$THEME" -BlurtGalleryBare >/dev/null +LAUNCH_AT=1 +sleep "$(python3 -c "print(2 * $CYCLE + 3)")" +kill -INT "$REC" +wait "$REC" 2>/dev/null || true + +# Skip the launch and the first idle lead-in's start; one full cycle from +# the second idle so the loop begins and ends at rest. +start="$(python3 -c "print($LAUNCH_AT + 2.0 + $CYCLE)")" +ffmpeg -loglevel error -y -ss "$start" -t "$CYCLE" -i "$movie" \ + -vf "crop=$CROP_W:$CROP_H:$CROP_X:$CROP_Y,fps=60" -an -c:v libx264 -pix_fmt yuv420p -crf 18 \ + "$OUT/$name.mp4" +echo "loop: $OUT/$name.mp4 ($CYCLE s, ${CROP_W}×${CROP_H})" + +if [ -n "$FRAMES" ]; then + IFS=, read -ra FRAME_LIST <<<"$FRAMES" + for t in "${FRAME_LIST[@]}"; do + ffmpeg -loglevel error -y -ss "$t" -i "$OUT/$name.mp4" -frames:v 1 "$OUT/$name-${t}s.png" + echo "frame: $OUT/$name-${t}s.png" + done +fi diff --git a/scripts/ios-sim.sh b/scripts/ios-sim.sh index 5ebfc18b..728d5412 100755 --- a/scripts/ios-sim.sh +++ b/scripts/ios-sim.sh @@ -7,6 +7,7 @@ # # scripts/ios-sim.sh # build, boot, install, launch # scripts/ios-sim.sh --screenshot out.png # …then capture the screen +# scripts/ios-sim.sh --no-build … # reuse the last build (a capture loop builds once) # BLURT_SIM_DEVICE="iPhone 17" scripts/ios-sim.sh # BLURT_LAUNCH_ARGS="-BlurtGallery panel idle,recording" scripts/ios-sim.sh --screenshot panel.png # BLURT_SHOT_DELAY=5 … # seconds before the screenshot (default 3) @@ -24,15 +25,35 @@ DERIVED="${BLURT_DERIVED_DATA:-$REPO_ROOT/.build/ios-sim}" # PRODUCT_BUNDLE_IDENTIFIER in App/BlurtiOS/project.yml. BUNDLE_ID=dev.alex.blurt.ios SHOT="" -if [ "${1:-}" = "--screenshot" ]; then - SHOT="${2:?usage: ios-sim.sh --screenshot }" -fi +BUILD=1 +while [ $# -gt 0 ]; do + case "$1" in + --screenshot) + SHOT="${2:?usage: ios-sim.sh [--no-build] [--screenshot ]}" + shift 2 + ;; + --no-build) + BUILD=0 + shift + ;; + *) + echo "usage: ios-sim.sh [--no-build] [--screenshot ]" >&2 + exit 2 + ;; + esac +done -echo "generate + build" -(cd "$REPO_ROOT/App/BlurtiOS" && xcodegen generate --quiet) -xcodebuild -project "$REPO_ROOT/App/BlurtiOS/BlurtiOS.xcodeproj" -scheme BlurtiOS \ - -destination 'generic/platform=iOS Simulator' -derivedDataPath "$DERIVED" \ - "${IOS_SIM_SIGNING[@]}" -quiet build +APP="$DERIVED/Build/Products/Debug-iphonesimulator/BlurtiOS.app" +if [ "$BUILD" -eq 1 ]; then + echo "generate + build" + (cd "$REPO_ROOT/App/BlurtiOS" && xcodegen generate --quiet) + xcodebuild -project "$REPO_ROOT/App/BlurtiOS/BlurtiOS.xcodeproj" -scheme BlurtiOS \ + -destination 'generic/platform=iOS Simulator' -derivedDataPath "$DERIVED" \ + "${IOS_SIM_SIGNING[@]}" -quiet build +elif [ ! -d "$APP" ]; then + echo "ios-sim: --no-build but nothing built at $APP; run once without it" >&2 + exit 1 +fi PICKED="$(ios_pick_device "${BLURT_SIM_DEVICE:-iPhone 18 Pro}")" if [ -z "$PICKED" ]; then @@ -53,7 +74,6 @@ for app in "$DEVELOPER_DIR/../Applications/DeviceHub.app" "$DEVELOPER_DIR/Applic done echo "install + launch" -APP="$DERIVED/Build/Products/Debug-iphonesimulator/BlurtiOS.app" xcrun simctl install "$UDID" "$APP" xcrun simctl privacy "$UDID" grant microphone "$BUNDLE_ID" xcrun simctl terminate "$UDID" "$BUNDLE_ID" 2>/dev/null || true From 782635f8117c276760b7a7e7a9d779a71b4d827d Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Mon, 28 Sep 2026 22:28:04 -0400 Subject: [PATCH 46/79] iOS: the Figma file as scripts (Design/figma) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit design-tokens.swift now also emits Design/figma/tokens.js — every token with its resolved value, alias, scopes and iOS code syntax — and lib.js builds the Blurt Keyboard file from it: six one-mode variable collections, text and effect styles and specimens (01 Foundations); Key, LetterKey, AddTermKey, CancelKey, TermField, Orb/Ring, Orb/Disc (app stills as image fills, the brand gradient standing in), WaveformMeter, MicKey, VoiceBar with every fill, stroke, radius and gap bound (02 Components); the three layouts as state rows named as the gallery captions them, at 402 pt (03 Layouts); a theme sheet that re-aliases kb/* per theme and exports (a Starter file has one mode); and the exports back — tokens, bounds, the Apple reference's geometry. The same functions run through use_figma (tokens.js + lib.js + one line) or as a development plugin that design-sync.sh bundles into .build/figma-plugin. Untested against a live file: it needs Neil's personal Figma (README.md). Co-Authored-By: Claude Fable 5.1 --- App/BlurtiOS/Design/figma/README.md | 68 + App/BlurtiOS/Design/figma/lib.js | 1187 +++++++++++++ App/BlurtiOS/Design/figma/manifest.json | 18 + App/BlurtiOS/Design/figma/plugin.js | 31 + App/BlurtiOS/Design/figma/tokens.js | 2072 +++++++++++++++++++++++ scripts/design-sync.sh | 14 + scripts/design-tokens.swift | 107 +- 7 files changed, 3492 insertions(+), 5 deletions(-) create mode 100644 App/BlurtiOS/Design/figma/README.md create mode 100644 App/BlurtiOS/Design/figma/lib.js create mode 100644 App/BlurtiOS/Design/figma/manifest.json create mode 100644 App/BlurtiOS/Design/figma/plugin.js create mode 100644 App/BlurtiOS/Design/figma/tokens.js diff --git a/App/BlurtiOS/Design/figma/README.md b/App/BlurtiOS/Design/figma/README.md new file mode 100644 index 00000000..c38546a6 --- /dev/null +++ b/App/BlurtiOS/Design/figma/README.md @@ -0,0 +1,68 @@ +# The Blurt Keyboard Figma file, from scripts + +The Figma file is built from these scripts, so the scripts — not the file — are +the durable record: a fresh file can be rebuilt in minutes, and the export back +(`tokens.json`) is what the app compiles. `DESIGN.md › Figma` has the loop. + +| File | What | +| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | +| `tokens.js` | **Generated** from `../tokens.json` by `scripts/design-tokens.swift`: every token, alias, scope, iOS code syntax. | +| `lib.js` | The builders, plain Plugin API: `buildFoundations`, `buildComponents`, `buildLayouts`, `themeSheet`, `exportTokens`, `exportBounds`, `measureApple`. | +| `plugin.js` | The development-plugin entry that dispatches `manifest.json`'s menu to those builders. | +| `manifest.json` | The plugin's manifest. `scripts/design-sync.sh` bundles all three JS files into `.build/figma-plugin/code.js`. | + +## Two ways to run the same code + +**Through the Figma MCP (`use_figma`)** — the agent loads the `figma-use` skill +(and `figma-generate-library` for foundations and components, +`figma-generate-design` for layouts), then sends one call per builder whose +script is `tokens.js` + `lib.js` + one line: + +```js +return await buildFoundations(); +``` + +Calls are strictly sequential, every builder is idempotent (it finds by name +before it creates), and every call returns ids and counts. The connector must +be authenticated to the account that owns the file with an editing seat — Neil's +personal Figma, not the AssemblyAI org View seat (6 reads a month, no edits). + +**As a development plugin** (no MCP quota at all): `scripts/design-sync.sh` +writes `.build/figma-plugin/{manifest.json,code.js}`; in Figma desktop, +Plugins → Development → Import plugin from manifest…, then run the menu items +in order. Results print to the plugin console (Plugins → Development → Open console). + +## Order + +1. `buildFoundations` — the six one-mode collections (`Brand`, `Themes`, + `Keyboard`, `Metrics`, `Typography`, `Motion`) with scopes and iOS code syntax; + aliases (`Themes` → `Brand`, `Keyboard` → `Themes`/`Brand`); the five text + styles and `Shadow/Popup`; colour swatches and a token list on `01 Foundations`. + Needs SF Pro installed on the Mac running Figma — it stops if the font is missing. +2. Place the orb stills, if you want real orbs rather than the brand gradient + stand-in: `BLURT_LAUNCH_ARGS="-BlurtOrb 96 idle" scripts/ios-sim.sh --screenshot raw.png` + then `swift scripts/design-diff.swift crop raw.png orb-96-idle.png`, for each of + `40 96 112` × `off idle listening working landed`; upload them into the file + (`upload_assets`, or drag them in) and name each node `orb-still/-` + (`orb-still/Panel-Idle`) on `02 Components`. `buildComponents` picks them up. +3. `buildComponents` — `Key`, `LetterKey`, `AddTermKey`, `CancelKey`, `TermField`, + `Orb/Ring`, `Orb/Disc`, `WaveformMeter`, `MicKey`, `VoiceBar` on `02 Components`, + every fill, stroke, radius and gap bound to a variable. Re-running replaces a set in place. +4. `buildLayouts` — `03 Layouts`: sections `Panel`, `SlimBar`, `Full`, each a + column of frames named `//ink` exactly as the gallery captions + them, 402 pt wide (iPhone 18 Pro, the capture device). Re-running rebuilds the sections. +5. `themeSheet` — re-aliases `kb/*` to each theme in turn, exports the idle + frames at 3× and places them as images in a `Theme sheet` section, then + restores `ink`. This is `KeyboardPalette.resolve(_:dark:)` in Figma; a + Starter file has one variable mode, so themes are value sets, not modes. +6. Paste the Apple `Keyboard` instances (light and dark, iPhone) from the + "iOS and iPadOS 27" kit into a section named `Apple reference` on `03 Layouts`, + lock them, and run `measureApple` — the numbers go into DESIGN.md's Apple geometry table. +7. After a design pass: `exportTokens` → merge its `tokens` object into + `../tokens.json` (keep `gradients` and `figma`) → `scripts/design-sync.sh` → + the views. `exportBounds` gives every named node's rectangle per layout frame + for `scripts/design-diff.swift`'s colour and geometry gates. + +The first run against a real file will surface Plugin API details these scripts +could not be tested against (they were written before the file existed); fix the +builder, re-run it — nothing here is precious except `tokens.json`. diff --git a/App/BlurtiOS/Design/figma/lib.js b/App/BlurtiOS/Design/figma/lib.js new file mode 100644 index 00000000..72a22d03 --- /dev/null +++ b/App/BlurtiOS/Design/figma/lib.js @@ -0,0 +1,1187 @@ +// The Blurt Keyboard Figma file, built from the tokens. Plain Plugin API, so +// the same functions run two ways (README.md): pasted into a use_figma call +// behind tokens.js with `return await buildFoundations();`, or bundled by +// scripts/design-sync.sh into a development plugin (plugin.js dispatches). +// Everything is idempotent — find by name before create — and every builder +// returns the ids and counts it touched. No `figma.notify`, no console output. +/* global figma, TOKENS */ + +// --------------------------------------------------------------------------- +// Names + +const PAGES = { foundations: "01 Foundations", components: "02 Components", layouts: "03 Layouts" }; +const FONT = { family: "SF Pro", regular: "Regular", medium: "Medium", semibold: "Semibold" }; +const DEVICE_WIDTH = 402; // iPhone 18 Pro, the simulator this repo captures on +const DESIGN_THEME = "ink"; +const THEMES = ["system-light", "system-dark", "ink", "paper", "lavender", "mint", "midnight", "sunset"]; +const ROLES = ["surface", "key", "key-modifier", "legend", "signal", "popup"]; +const STATES = ["off", "start", "idle", "connecting", "recording", "processing", "pasted", "copied", "error", "term"]; + +// --------------------------------------------------------------------------- +// Helpers + +function hexToRGB(hex) { + const n = parseInt(hex.slice(1), 16); + return { r: ((n >> 16) & 255) / 255, g: ((n >> 8) & 255) / 255, b: (n & 255) / 255 }; +} + +function token(collection, name) { + const entry = TOKENS.collections[collection].variables.find((v) => v.name === name); + if (!entry) throw new Error(`no token ${collection}:${name}`); + return entry; +} + +function metric(name) { + return token("Metrics", name).value; +} + +async function getPage(name) { + let page = figma.root.children.find((p) => p.name === name); + if (!page) { + page = figma.createPage(); + page.name = name; + } + await figma.setCurrentPageAsync(page); + return page; +} + +function getSection(page, name, x, y) { + let section = page.children.find((n) => n.type === "SECTION" && n.name === name); + if (!section) { + section = figma.createSection(); + section.name = name; + section.x = x; + section.y = y; + page.appendChild(section); + } + return section; +} + +/** Every local variable, keyed "Collection:name". */ +async function variableMap() { + const collections = await figma.variables.getLocalVariableCollectionsAsync(); + const byId = new Map(collections.map((c) => [c.id, c])); + const map = new Map(); + for (const v of await figma.variables.getLocalVariablesAsync()) { + const collection = byId.get(v.variableCollectionId); + if (collection) map.set(`${collection.name}:${v.name}`, v); + } + return map; +} + +let VARS = null; +async function vars() { + if (!VARS) VARS = await variableMap(); + return VARS; +} + +async function variable(ref) { + const v = (await vars()).get(ref); + if (!v) throw new Error(`variable ${ref} is not in the file — run buildFoundations first`); + return v; +} + +/** A solid paint bound to a colour variable. */ +async function paint(ref) { + const v = await variable(ref); + return figma.variables.setBoundVariableForPaint({ type: "SOLID", color: { r: 0, g: 0, b: 0 } }, "color", v); +} + +async function bind(node, field, ref) { + node.setBoundVariable(field, await variable(ref)); +} + +async function bindRadius(node, ref) { + for (const corner of ["topLeftRadius", "topRightRadius", "bottomLeftRadius", "bottomRightRadius"]) { + await bind(node, corner, ref); + } +} + +async function loadFonts() { + const available = await figma.listAvailableFontsAsync(); + const families = new Set(available.map((f) => f.fontName.family)); + if (!families.has(FONT.family)) { + throw new Error(`${FONT.family} is not available in this file; install SF Pro from developer.apple.com/fonts`); + } + for (const style of [FONT.regular, FONT.medium, FONT.semibold]) { + await figma.loadFontAsync({ family: FONT.family, style }); + } +} + +/** An SF Symbol as a character where the runtime can (the MCP one), else a stand-in. */ +function symbolChar(name, fallback) { + try { + if (figma.util && typeof figma.util.getSfSymbolCharacter === "function") { + return figma.util.getSfSymbolCharacter(name); + } + } catch (_) { + // fall through to the stand-in + } + return fallback; +} + +async function textNode(characters, { size, weight = FONT.regular, fillRef, styleId } = {}) { + const t = figma.createText(); + t.fontName = { family: FONT.family, style: weight }; + t.characters = characters; + if (size) t.fontSize = size; + if (styleId) t.textStyleId = styleId; + if (fillRef) t.fills = [await paint(fillRef)]; + t.textAutoResize = "WIDTH_AND_HEIGHT"; + return t; +} + +function autoLayout(direction, props = {}) { + const frame = figma.createFrame(); + frame.layoutMode = direction; + frame.primaryAxisSizingMode = "AUTO"; + frame.counterAxisSizingMode = "AUTO"; + frame.fills = []; + frame.clipsContent = false; + Object.assign(frame, props); + return frame; +} + +function gradientPaint(gradientName) { + const g = TOKENS.gradients[gradientName]; + const transforms = { + "bottom>top": [ + [0, -1, 1], + [1, 0, 0], + ], + "topLeading>bottomTrailing": [ + [0.5, 0.5, 0], + [-0.5, 0.5, 0.5], + ], + }; + return { + type: "GRADIENT_LINEAR", + gradientTransform: transforms[`${g.start}>${g.end}`] || transforms["bottom>top"], + gradientStops: g.stops.map((s) => ({ position: s.location, color: { ...hexToRGB(s.value), a: 1 } })), + }; +} + +// --------------------------------------------------------------------------- +// Foundations: variables, styles, specimens + +async function buildFoundations() { + const page = await getPage(PAGES.foundations); + const existingCollections = await figma.variables.getLocalVariableCollectionsAsync(); + const created = { collections: 0, variables: 0, aliases: 0, textStyles: 0, effectStyles: 0 }; + const collections = {}; + for (const name of TOKENS.groups) { + let c = existingCollections.find((x) => x.name === name); + if (!c) { + c = figma.variables.createVariableCollection(name); + created.collections += 1; + } + c.renameMode(c.modes[0].modeId, TOKENS.collections[name].mode); + collections[name] = c; + } + VARS = await variableMap(); + // Concrete values first, aliases second, so a target always exists. + for (const pass of ["values", "aliases"]) { + for (const name of TOKENS.groups) { + const c = collections[name]; + const modeId = c.modes[0].modeId; + for (const spec of TOKENS.collections[name].variables) { + if ((pass === "aliases") !== Boolean(spec.alias)) continue; + const key = `${name}:${spec.name}`; + let v = VARS.get(key); + if (!v) { + v = figma.variables.createVariable(spec.name, c, spec.type); + VARS.set(key, v); + created.variables += 1; + } + if (spec.alias) { + const target = VARS.get(spec.alias); + if (!target) throw new Error(`${key} aliases ${spec.alias}, which is missing`); + v.setValueForMode(modeId, figma.variables.createVariableAlias(target)); + created.aliases += 1; + } else if (spec.type === "COLOR") { + v.setValueForMode(modeId, { ...hexToRGB(spec.value), a: 1 }); + } else { + v.setValueForMode(modeId, spec.value); + } + v.scopes = spec.scopes; + v.description = spec.use || ""; + v.setVariableCodeSyntax("iOS", spec.codeSyntax); + } + } + } + + await loadFonts(); + const sizes = Object.fromEntries( + TOKENS.collections.Typography.variables.filter((v) => v.name.startsWith("size/")).map((v) => [v.name.slice(5), v.value]) + ); + const weights = Object.fromEntries( + TOKENS.collections.Typography.variables.filter((v) => v.name.startsWith("weight/")).map((v) => [v.name.slice(7), v.value]) + ); + const weightStyle = { regular: FONT.regular, medium: FONT.medium, semibold: FONT.semibold }; + const textStyleSpecs = [ + ["Key/Letter", sizes.letter, weights.letter], + ["Key/Legend", sizes.legend, weights.legend], + ["Key/Popup", sizes.popup, weights.popup], + ["Term/Text", sizes.term, weights.term], + ["Glyph", sizes.glyph, weights.glyph], + ]; + const textStyles = await figma.getLocalTextStylesAsync(); + for (const [name, size, weight] of textStyleSpecs) { + let s = textStyles.find((x) => x.name === name); + if (!s) { + s = figma.createTextStyle(); + s.name = name; + created.textStyles += 1; + } + s.fontName = { family: FONT.family, style: weightStyle[weight] }; + s.fontSize = size; + } + const effectStyles = await figma.getLocalEffectStylesAsync(); + let shadow = effectStyles.find((x) => x.name === "Shadow/Popup"); + if (!shadow) { + shadow = figma.createEffectStyle(); + shadow.name = "Shadow/Popup"; + created.effectStyles += 1; + } + // Figma's blur is about twice SwiftUI's shadow radius; the generator's + // DESIGN.md note says the same, so the two stay one number apart on purpose. + shadow.effects = [ + { + type: "DROP_SHADOW", + color: { r: 0, g: 0, b: 0, a: metric("opacity/popup-shadow") }, + offset: { x: 0, y: metric("popup/shadow-y") }, + radius: metric("popup/shadow-radius") * 2, + spread: 0, + visible: true, + blendMode: "NORMAL", + }, + ]; + + // Specimens: swatches for every colour, a line per number, all bound. + const ids = []; + const colours = getSection(page, "Colour", 0, 0); + const grid = autoLayout("VERTICAL", { name: "Swatches", itemSpacing: 8 }); + for (const name of ["Brand", "Themes", "Keyboard"]) { + const row = autoLayout("VERTICAL", { name, itemSpacing: 4 }); + row.appendChild(await textNode(name, { size: 14, weight: FONT.medium, fillRef: "Brand:ink" })); + const wrap = autoLayout("HORIZONTAL", { name: `${name} swatches`, itemSpacing: 8 }); + wrap.layoutWrap = "WRAP"; + wrap.counterAxisSpacing = 8; + wrap.resize(1200, 10); + wrap.primaryAxisSizingMode = "FIXED"; + for (const spec of TOKENS.collections[name].variables) { + const cell = autoLayout("VERTICAL", { name: spec.name, itemSpacing: 2 }); + const swatch = figma.createRectangle(); + swatch.resize(64, 40); + swatch.cornerRadius = 4; + swatch.fills = [await paint(`${name}:${spec.name}`)]; + cell.appendChild(swatch); + cell.appendChild(await textNode(spec.name, { size: 9, fillRef: "Brand:ink" })); + cell.appendChild(await textNode(spec.value, { size: 9, fillRef: "Brand:ink" })); + wrap.appendChild(cell); + } + row.appendChild(wrap); + grid.appendChild(row); + } + const oldGrid = colours.children.find((n) => n.name === "Swatches"); + if (oldGrid) oldGrid.remove(); + colours.appendChild(grid); + colours.resizeWithoutConstraints(grid.width + 80, grid.height + 80); + grid.x = 40; + grid.y = 40; + ids.push(grid.id); + + const numbers = getSection(page, "Numbers", 0, colours.height + 80); + const list = autoLayout("VERTICAL", { name: "Tokens", itemSpacing: 2 }); + for (const name of ["Metrics", "Typography", "Motion"]) { + list.appendChild(await textNode(name, { size: 14, weight: FONT.medium, fillRef: "Brand:ink" })); + for (const spec of TOKENS.collections[name].variables) { + list.appendChild( + await textNode(`${spec.name} = ${spec.value} · ${spec.codeSyntax}${spec.use ? " — " + spec.use : ""}`, { + size: 10, + fillRef: "Brand:ink", + }) + ); + } + } + const oldList = numbers.children.find((n) => n.name === "Tokens"); + if (oldList) oldList.remove(); + numbers.appendChild(list); + numbers.resizeWithoutConstraints(list.width + 80, list.height + 80); + list.x = 40; + list.y = 40; + ids.push(list.id); + + const recipe = getSection(page, "Orb recipe", colours.width + 80, 0); + const note = await textNode( + [ + "The orb is the one thing Figma does not draw. It is a 3 × 3 MeshGradient whose edge midpoints and centre", + "drift on slow sines (further with the voice), under a soft upper-left light (opacity/orb-light,", + "orb/light-x, orb/light-y, orb/light-radius) and film grain (opacity/grain; a seeded scatter of 1 pt dots,", + "one per 26 pt²). The words landing pours cobolt in from the centre (drop, drop-rise, drop-hold) with six", + "four-point sparkles. Orb/Disc's fills are stills the app renders (-BlurtOrb ); the", + "parameters above are the variables. Source: App/BlurtiOS/BlurtKeyboard/Sources/PrismOrb.swift.", + ].join("\n"), + { size: 11, fillRef: "Brand:ink" } + ); + note.textAutoResize = "HEIGHT"; + note.resize(720, 10); + const oldNote = recipe.children.find((n) => n.type === "TEXT"); + if (oldNote) oldNote.remove(); + recipe.appendChild(note); + recipe.resizeWithoutConstraints(800, note.height + 80); + note.x = 40; + note.y = 40; + + return { page: page.id, created, specimenIds: ids, variables: VARS.size }; +} + +// --------------------------------------------------------------------------- +// Export: the variables back out as tokens.json's groups + +async function exportTokens() { + const collections = await figma.variables.getLocalVariableCollectionsAsync(); + const byId = new Map(collections.map((c) => [c.id, c])); + const all = await figma.variables.getLocalVariablesAsync(); + const byVarId = new Map(all.map((v) => [v.id, v])); + const groupOf = { Brand: "brand", Themes: "themes", Keyboard: "keyboard", Metrics: "metrics", Typography: "type", Motion: "motion" }; + const out = {}; + for (const v of all) { + const c = byId.get(v.variableCollectionId); + const group = c && groupOf[c.name]; + if (!group) continue; + const modeId = c.modes[0].modeId; + let raw = v.valuesByMode[modeId]; + let value; + if (raw && typeof raw === "object" && raw.type === "VARIABLE_ALIAS") { + const target = byVarId.get(raw.id); + const tc = byId.get(target.variableCollectionId); + value = `{${groupOf[tc.name]}.${target.name}}`; + } else if (raw && typeof raw === "object" && "r" in raw) { + const hex = [raw.r, raw.g, raw.b].map((x) => Math.round(x * 255).toString(16).padStart(2, "0")).join(""); + value = `#${hex.toUpperCase()}`; + } else { + value = raw; + } + out[group] = out[group] || {}; + out[group][v.name] = v.description ? { value, use: v.description } : { value }; + } + return { tokens: out, note: "merge into App/BlurtiOS/Design/tokens.json (keep gradients and figma), then scripts/design-sync.sh" }; +} + +/** The absolute bounds of every named node under the layout frames, in points. */ +async function exportBounds() { + const page = await getPage(PAGES.layouts); + const frames = page.findAll((n) => n.type === "FRAME" && /^(panel|slimBar|full)\//.test(n.name)); + const bounds = {}; + for (const frame of frames) { + const origin = frame.absoluteBoundingBox; + bounds[frame.name] = {}; + for (const node of frame.findAll((n) => n.name && n.absoluteBoundingBox)) { + const b = node.absoluteBoundingBox; + bounds[frame.name][node.name] = { + x: +(b.x - origin.x).toFixed(2), + y: +(b.y - origin.y).toFixed(2), + w: +b.width.toFixed(2), + h: +b.height.toFixed(2), + type: node.type, + }; + } + } + return { frames: frames.length, bounds }; +} + +// --------------------------------------------------------------------------- +// Components (02 Components). Every fill, stroke, radius and gap is bound to a +// variable; the orb's disc is the one image fill (see buildOrbDisc). + +const SIZES = { Bar: "orb/bar", Panel: "orb/panel", Home: "orb/home" }; +const WAVES = { + Bar: ["wave/bar-width", "wave/bar-height"], + Panel: ["wave/panel-width", "wave/panel-height"], + Home: ["wave/home-width", "wave/home-height"], +}; + +async function findComponentSet(page, name) { + return page.findOne((n) => n.type === "COMPONENT_SET" && n.name === name); +} + +async function findComponent(page, name) { + return page.findOne((n) => n.type === "COMPONENT" && n.name === name && n.parent.type !== "COMPONENT_SET"); +} + +async function textStyleId(name) { + const s = (await figma.getLocalTextStylesAsync()).find((x) => x.name === name); + if (!s) throw new Error(`text style ${name} missing — run buildFoundations first`); + return s.id; +} + +async function effectStyleId(name) { + const s = (await figma.getLocalEffectStylesAsync()).find((x) => x.name === name); + if (!s) throw new Error(`effect style ${name} missing — run buildFoundations first`); + return s.id; +} + +/** Replaces a component set (or lone component) of this name, keeping its position. */ +function replaceNamed(page, name, node) { + const old = page.findOne((n) => (n.type === "COMPONENT_SET" || n.type === "COMPONENT") && n.name === name); + if (old) { + node.x = old.x; + node.y = old.y; + old.remove(); + } +} + +/** Lays the variants of a set out in a row and names the set. */ +function finishSet(page, name, variants, x, y) { + const set = figma.combineAsVariants(variants, page); + set.name = name; + set.layoutMode = "HORIZONTAL"; + set.itemSpacing = 24; + set.paddingLeft = set.paddingRight = set.paddingTop = set.paddingBottom = 24; + set.primaryAxisSizingMode = "AUTO"; + set.counterAxisSizingMode = "AUTO"; + set.counterAxisAlignItems = "MIN"; + set.x = x; + set.y = y; + return set; +} + +async function keyCap(props) { + // props: tone "Key"|"Modifier"|"Bare", pressed, label, width (fixed) or null (min width + pad) + const c = figma.createComponent(); + c.name = `Tone=${props.tone}, State=${props.pressed ? "Pressed" : "Up"}`; + c.layoutMode = "HORIZONTAL"; + c.primaryAxisAlignItems = "CENTER"; + c.counterAxisAlignItems = "CENTER"; + c.primaryAxisSizingMode = props.width ? "FIXED" : "AUTO"; + c.counterAxisSizingMode = "FIXED"; + c.resize(props.width || metric("key/min-width"), metric("key/height")); + await bind(c, "height", "Metrics:key/height"); + if (props.width) await bind(c, "width", `Metrics:${props.widthRef}`); + else { + await bind(c, "minWidth", "Metrics:key/min-width"); + await bind(c, "paddingLeft", "Metrics:key/pad"); + await bind(c, "paddingRight", "Metrics:key/pad"); + } + c.fills = props.tone === "Bare" ? [] : [await paint(props.tone === "Modifier" ? "Keyboard:kb/key-modifier" : "Keyboard:kb/key")]; + await bindRadius(c, "Metrics:key/radius"); + const label = await textNode(props.label, { + styleId: await textStyleId(props.letter ? "Key/Letter" : "Key/Legend"), + fillRef: props.tint || "Keyboard:kb/legend", + }); + label.name = "Label"; + c.appendChild(label); + if (props.pressed) { + const shine = figma.createRectangle(); + shine.name = "Pressed"; + shine.fills = [{ type: "SOLID", color: { r: 1, g: 1, b: 1 } }]; + await bind(shine, "opacity", "Metrics:opacity/press-brighten"); + c.appendChild(shine); + shine.layoutPositioning = "ABSOLUTE"; + shine.x = 0; + shine.y = 0; + shine.resize(c.width, c.height); + shine.constraints = { horizontal: "STRETCH", vertical: "STRETCH" }; + await bindRadius(shine, "Metrics:key/radius"); + } + return c; +} + +async function buildKeySet(page, x, y) { + const variants = []; + for (const tone of ["Key", "Modifier", "Bare"]) { + for (const pressed of [false, true]) { + variants.push(await keyCap({ tone, pressed, label: tone === "Bare" ? "×" : "space" })); + } + } + replaceNamed(page, "Key", variants[0]); + const set = finishSet(page, "Key", variants, x, y); + set.description = "One ordinary key: a legend on a cap in the current palette; Modifier a step darker; Bare a glyph with no cap. Flat: no drop, no edge, no gloss."; + const labelProp = set.addComponentProperty("Label", "TEXT", "space"); + for (const v of variants) { + const t = v.findOne((n) => n.type === "TEXT" && n.name === "Label"); + t.componentPropertyReferences = { characters: labelProp }; + } + return set; +} + +async function buildLetterKeySet(page, x, y) { + const variants = []; + for (const pressed of [false, true]) { + const c = await keyCap({ + tone: "Key", + pressed, + label: "q", + letter: true, + width: metric("key/letter-width-402"), + widthRef: "key/letter-width-402", + }); + c.name = `State=${pressed ? "Pressed" : "Up"}`; + if (pressed) { + const popup = figma.createFrame(); + popup.name = "LetterPopup"; + popup.layoutMode = "HORIZONTAL"; + popup.primaryAxisAlignItems = "CENTER"; + popup.counterAxisAlignItems = "CENTER"; + popup.primaryAxisSizingMode = "FIXED"; + popup.counterAxisSizingMode = "FIXED"; + popup.resize(metric("key/letter-width-402") + metric("popup/extra-width"), metric("popup/height")); + await bind(popup, "height", "Metrics:popup/height"); + popup.fills = [await paint("Keyboard:kb/popup")]; + await bindRadius(popup, "Metrics:popup/radius"); + popup.effectStyleId = await effectStyleId("Shadow/Popup"); + const big = await textNode("q", { styleId: await textStyleId("Key/Popup"), fillRef: "Keyboard:kb/legend" }); + big.name = "Popup label"; + popup.appendChild(big); + c.appendChild(popup); + popup.layoutPositioning = "ABSOLUTE"; + popup.x = -metric("popup/extra-width") / 2; + popup.y = -metric("popup/offset"); + } + variants.push(c); + } + replaceNamed(page, "LetterKey", variants[0]); + const set = finishSet(page, "LetterKey", variants, x, y); + set.description = "A letter key with the system keyboard's 22 pt legend and its pop-up while pressed: a 32 pt copy above the key, the one thing that floats."; + const labelProp = set.addComponentProperty("Label", "TEXT", "q"); + for (const v of variants) { + for (const t of v.findAll((n) => n.type === "TEXT")) t.componentPropertyReferences = { characters: labelProp }; + } + return set; +} + +async function glyphButton(name, symbol, fallback, fillRef, opacityRef) { + const c = figma.createComponent(); + c.name = name; + c.layoutMode = "HORIZONTAL"; + c.primaryAxisAlignItems = "CENTER"; + c.counterAxisAlignItems = "CENTER"; + c.primaryAxisSizingMode = "FIXED"; + c.counterAxisSizingMode = "FIXED"; + c.resize(metric("glyph/hit"), metric("glyph/hit")); + await bind(c, "width", "Metrics:glyph/hit"); + await bind(c, "height", "Metrics:glyph/hit"); + const t = await textNode(symbolChar(symbol, fallback), { styleId: await textStyleId("Glyph"), fillRef }); + t.name = "Glyph"; + if (opacityRef) await bind(t, "opacity", opacityRef); + c.appendChild(t); + return c; +} + +async function buildAddTermKey(page, x, y) { + const off = await glyphButton("Saved=False", "plus", "+", "Keyboard:kb/legend", "Metrics:opacity/legend-muted"); + const on = await glyphButton("Saved=True", "checkmark", "✓", "Keyboard:kb/signal", null); + replaceNamed(page, "AddTermKey", off); + const set = finishSet(page, "AddTermKey", [off, on], x, y); + set.description = "The small + beside the orb: a new key term. A bare glyph, quiet until needed; a check for a moment after one was saved."; + return set; +} + +async function buildCancelKey(page, x, y) { + const c = await keyCap({ tone: "Bare", pressed: false, label: symbolChar("xmark", "×"), tint: "Keyboard:kb/cancel" }); + c.name = "CancelKey"; + c.description = "Cancel, in the panel's top-right corner while something is in flight: the orange × on no cap."; + replaceNamed(page, "CancelKey", c); + page.appendChild(c); + c.x = x; + c.y = y; + return c; +} + +async function buildTermField(page, x, y) { + const c = figma.createComponent(); + c.name = "TermField"; + c.description = "The voice bar as a field: × to leave, what has been typed with a caret, ✓ to save."; + c.layoutMode = "HORIZONTAL"; + c.counterAxisAlignItems = "CENTER"; + c.primaryAxisSizingMode = "FIXED"; + c.counterAxisSizingMode = "FIXED"; + c.resize(DEVICE_WIDTH - 2 * metric("margin/side"), metric("voicebar/height")); + await bind(c, "height", "Metrics:voicebar/height"); + await bind(c, "itemSpacing", "Metrics:term/gap"); + await bind(c, "paddingLeft", "Metrics:term/inset"); + await bind(c, "paddingRight", "Metrics:term/inset"); + const cancel = await glyphButton("Cancel", "xmark", "×", "Keyboard:kb/legend", "Metrics:opacity/term-cancel"); + cancel.name = "Cancel"; + const cancelInstance = cancel.createInstance(); + cancel.remove(); + c.appendChild(cancelInstance); + const field = figma.createFrame(); + field.name = "Field"; + field.layoutMode = "HORIZONTAL"; + field.counterAxisAlignItems = "CENTER"; + field.primaryAxisSizingMode = "FIXED"; + field.counterAxisSizingMode = "FIXED"; + field.resize(100, metric("term/height")); + await bind(field, "height", "Metrics:term/height"); + await bind(field, "paddingLeft", "Metrics:term/pad"); + await bind(field, "paddingRight", "Metrics:term/pad"); + field.fills = [await paint("Keyboard:kb/key-modifier")]; + field.cornerRadius = metric("term/height") / 2; // a capsule: half the height + const draft = await textNode("Rizz", { styleId: await textStyleId("Term/Text"), fillRef: "Keyboard:kb/legend" }); + draft.name = "Draft"; + field.appendChild(draft); + const caret = figma.createRectangle(); + caret.name = "Caret"; + caret.resize(metric("caret/width"), metric("caret/height")); + await bind(caret, "width", "Metrics:caret/width"); + await bind(caret, "height", "Metrics:caret/height"); + await bindRadius(caret, "Metrics:caret/radius"); + caret.fills = [await paint("Keyboard:kb/signal")]; + field.appendChild(caret); + c.appendChild(field); + field.layoutSizingHorizontal = "FILL"; + const save = await glyphButton("Save", "checkmark", "✓", "Keyboard:kb/signal", null); + const saveInstance = save.createInstance(); + save.remove(); + c.appendChild(saveInstance); + const draftProp = c.addComponentProperty("Draft", "TEXT", "Rizz"); + draft.componentPropertyReferences = { characters: draftProp }; + replaceNamed(page, "TermField", c); + page.appendChild(c); + c.x = x; + c.y = y; + return c; +} + +async function buildOrbRing(page, x, y) { + const variants = []; + for (const [size, ref] of Object.entries(SIZES)) { + for (const kind of ["Still", "Working", "Ok", "Error"]) { + const c = figma.createComponent(); + c.name = `Kind=${kind}, Size=${size}`; + const d = metric(ref); + c.resize(d, d); + c.fills = []; + const ring = figma.createEllipse(); + ring.name = "Ring"; + ring.resize(d, d); + ring.fills = []; + ring.strokeAlign = "INSIDE"; + if (kind === "Ok" || kind === "Error") { + ring.strokes = [await paint(kind === "Ok" ? "Keyboard:kb/notice-ok" : "Keyboard:kb/notice-error")]; + } else { + ring.strokes = [gradientPaint("orb-ring")]; + } + await bind(ring, "strokeWeight", kind === "Still" ? "Metrics:ring/still" : "Metrics:ring/active"); + c.appendChild(ring); + await bind(c, "width", `Metrics:${ref}`); + await bind(c, "height", `Metrics:${ref}`); + variants.push(c); + } + } + replaceNamed(page, "Orb/Ring", variants[0]); + const set = finishSet(page, "Orb/Ring", variants, x, y); + set.description = "The hairline ring round the orb: green into white, 1 pt at rest and 2 pt while working (it sweeps one turn per 1.6 s); solid green for pasted and copied, orange for an error."; + return set; +} + +/** An orb still the app rendered, if one has been placed in the file. */ +function orbStill(page, size, mood) { + const node = page.findOne((n) => n.name === `orb-still/${size}-${mood}`.toLowerCase()); + if (!node || !("fills" in node)) return null; + const fill = node.fills.find((f) => f.type === "IMAGE"); + return fill ? fill.imageHash : null; +} + +async function buildOrbDisc(page, x, y) { + const variants = []; + let images = 0; + for (const [size, ref] of Object.entries(SIZES)) { + for (const mood of ["Off", "Idle", "Listening", "Working", "Landed"]) { + const c = figma.createComponent(); + c.name = `Size=${size}, Mood=${mood}`; + const d = metric(ref); + c.resize(d, d); + c.fills = []; + const disc = figma.createEllipse(); + disc.name = "Disc"; + disc.resize(d, d); + const hash = orbStill(page, size, mood === "Off" ? "Idle" : mood); + if (hash) { + disc.fills = [{ type: "IMAGE", imageHash: hash, scaleMode: "FILL" }]; + images += 1; + } else { + disc.fills = [gradientPaint("orb")]; + } + if (mood === "Off") { + await bind(disc, "opacity", "Metrics:opacity/dim"); + } + c.appendChild(disc); + await bind(c, "width", `Metrics:${ref}`); + await bind(c, "height", `Metrics:${ref}`); + variants.push(c); + } + } + replaceNamed(page, "Orb/Disc", variants[0]); + const set = finishSet(page, "Orb/Disc", variants, x, y); + set.description = + "The orb's fill. A still the app renders (-BlurtOrb , placed here as orb-still/-); the brand gradient stands in until one is. Off is Idle dimmed."; + return { set, images }; +} + +async function buildWaveformMeter(page, x, y) { + const variants = []; + for (const [size, [wRef, hRef]] of Object.entries(WAVES)) { + const c = figma.createComponent(); + c.name = `Size=${size}`; + const w = metric(wRef); + const h = metric(hRef); + c.resize(w, h); + c.fills = []; + c.layoutMode = "HORIZONTAL"; + c.primaryAxisAlignItems = "CENTER"; + c.counterAxisAlignItems = "CENTER"; + c.primaryAxisSizingMode = "FIXED"; + c.counterAxisSizingMode = "FIXED"; + await bind(c, "itemSpacing", "Metrics:wave/gap"); + await bind(c, "width", `Metrics:${wRef}`); + await bind(c, "height", `Metrics:${hRef}`); + const bar = metric("wave/bar"); + const gap = metric("wave/gap"); + const count = Math.floor((w + gap) / (bar + gap)); + const level = 0.62; + for (let i = 0; i < count; i += 1) { + const t = i / Math.max(count - 1, 1); + // A schematic of the engine's envelope: a soft hump, minimum 12 %, at the gallery's level. + const envelope = 0.12 + 0.88 * level * Math.pow(Math.sin(Math.PI * t), 0.45); + const capsule = figma.createRectangle(); + capsule.name = "Bar"; + capsule.resize(bar, Math.max(bar, h * envelope)); + capsule.cornerRadius = bar / 2; + await bind(capsule, "width", "Metrics:wave/bar"); + capsule.fills = [await paint("Keyboard:kb/signal")]; + c.appendChild(capsule); + } + variants.push(c); + } + replaceNamed(page, "WaveformMeter", variants[0]); + const set = finishSet(page, "WaveformMeter", variants, x, y); + set.description = + "The thin wave: 2 pt bars 2 pt apart, flat on the surface, no container. Heights are the engine's (MeterBarGeometry); this is the schematic at level 0.62 — fidelity frames use app captures."; + return set; +} + +const MIC_STATES = ["Off", "Idle", "Working", "Recording", "Pasted", "Copied", "Error"]; + +async function buildMicKey(page, x, y) { + const disc = await findComponentSet(page, "Orb/Disc"); + const ring = await findComponentSet(page, "Orb/Ring"); + const meter = await findComponentSet(page, "WaveformMeter"); + if (!disc || !ring || !meter) throw new Error("build Orb/Disc, Orb/Ring and WaveformMeter first"); + const pick = (set, props) => + set.children.find((c) => Object.entries(props).every(([k, v]) => c.name.includes(`${k}=${v}`))); + const variants = []; + for (const [size, ref] of Object.entries(SIZES)) { + for (const state of MIC_STATES) { + const c = figma.createComponent(); + c.name = `Size=${size}, State=${state}`; + const d = metric(ref); + const [wRef] = WAVES[size]; + c.resize(Math.max(metric(wRef), d), d); + c.fills = []; + c.layoutMode = "HORIZONTAL"; + c.primaryAxisAlignItems = "CENTER"; + c.counterAxisAlignItems = "CENTER"; + c.primaryAxisSizingMode = "FIXED"; + c.counterAxisSizingMode = "FIXED"; + await bind(c, "height", `Metrics:${ref}`); + if (state === "Recording") { + c.appendChild(pick(meter, { Size: size }).createInstance()); + } else { + const stack = figma.createFrame(); + stack.name = "Orb"; + stack.resize(d, d); + stack.fills = []; + stack.clipsContent = false; + const mood = { Off: "Off", Idle: "Idle", Working: "Working", Pasted: "Landed", Copied: "Idle", Error: "Idle" }[state]; + const kind = { Off: "Still", Idle: "Still", Working: "Working", Pasted: "Ok", Copied: "Ok", Error: "Error" }[state]; + const discInstance = pick(disc, { Size: size, Mood: mood }).createInstance(); + discInstance.name = "Disc"; + stack.appendChild(discInstance); + const ringInstance = pick(ring, { Size: size, Kind: kind }).createInstance(); + ringInstance.name = "Ring"; + stack.appendChild(ringInstance); + if (state === "Copied" || state === "Error") { + const glyph = await textNode( + state === "Copied" ? symbolChar("doc.on.clipboard", "⎘") : symbolChar("exclamationmark", "!"), + { size: d * token("Typography", "ratio/orb-glyph").value, weight: FONT.semibold } + ); + glyph.name = "Glyph"; + glyph.fills = [{ type: "SOLID", color: { r: 1, g: 1, b: 1 } }]; + stack.appendChild(glyph); + glyph.x = (d - glyph.width) / 2; + glyph.y = (d - glyph.height) / 2; + } + if (state === "Off") await bind(stack, "opacity", "Metrics:opacity/dim"); + c.appendChild(stack); + } + variants.push(c); + } + } + replaceNamed(page, "MicKey", variants[0]); + const set = finishSet(page, "MicKey", variants, x, y); + set.description = + "The mic key is the orb, and it says everything without a word: dimmed when Blurt isn't ready; ring sweeping while connecting and transcribing; dissipated into the wave while recording; a green ring when the words landed (with the drop), a clipboard on green when they went to the clipboard, orange and ! for an error."; + return set; +} + +async function buildVoiceBar(page, x, y) { + const mic = await findComponentSet(page, "MicKey"); + const addTerm = await findComponentSet(page, "AddTermKey"); + const termField = await findComponent(page, "TermField"); + if (!mic || !addTerm || !termField) throw new Error("build MicKey, AddTermKey and TermField first"); + const pick = (set, props) => + set.children.find((c) => Object.entries(props).every(([k, v]) => c.name.includes(`${k}=${v}`))); + const variants = []; + for (const mode of ["Orb", "Wave", "Term", "NoFullAccess"]) { + const c = figma.createComponent(); + c.name = `Mode=${mode}`; + c.layoutMode = "HORIZONTAL"; + c.primaryAxisAlignItems = mode === "NoFullAccess" ? "MIN" : "CENTER"; + c.counterAxisAlignItems = "CENTER"; + c.primaryAxisSizingMode = "FIXED"; + c.counterAxisSizingMode = "FIXED"; + c.resize(DEVICE_WIDTH - 2 * metric("margin/side"), metric("voicebar/height")); + await bind(c, "height", "Metrics:voicebar/height"); + c.fills = []; + c.clipsContent = false; + if (mode === "Term") { + const f = termField.createInstance(); + c.appendChild(f); + f.layoutSizingHorizontal = "FILL"; + } else if (mode === "NoFullAccess") { + await bind(c, "itemSpacing", "Metrics:voicebar/note-gap"); + c.appendChild(pick(mic, { Size: "Bar", State: "Off" }).createInstance()); + const note = await textNode("Allow Full Access in Settings → Keyboards", { + size: 13, + fillRef: "Keyboard:kb/full-access-note", + }); + note.name = "Note"; + c.appendChild(note); + } else { + c.appendChild(pick(mic, { Size: "Bar", State: mode === "Wave" ? "Recording" : "Idle" }).createInstance()); + const plus = pick(addTerm, { Saved: "False" }).createInstance(); + c.appendChild(plus); + plus.layoutPositioning = "ABSOLUTE"; + plus.constraints = { horizontal: "MAX", vertical: "CENTER" }; + plus.x = c.width - plus.width; + plus.y = (c.height - plus.height) / 2; + } + variants.push(c); + } + replaceNamed(page, "VoiceBar", variants[0]); + const set = finishSet(page, "VoiceBar", variants, x, y); + set.description = + "The keyboard's voice row, and the only place voice lives: the orb (the mic key) dissipating into the wave while recording; the + for a key term; the field the keys type into; the one line of words, without Full Access."; + return set; +} + +async function buildComponents() { + const page = await getPage(PAGES.components); + VARS = await variableMap(); + await loadFonts(); + const built = {}; + let y = 0; + const step = 360; + built.key = (await buildKeySet(page, 0, y)).id; + built.letterKey = (await buildLetterKeySet(page, 0, (y += step))).id; + built.addTermKey = (await buildAddTermKey(page, 0, (y += step))).id; + built.cancelKey = (await buildCancelKey(page, 400, y)).id; + built.termField = (await buildTermField(page, 0, (y += step))).id; + built.orbRing = (await buildOrbRing(page, 0, (y += step))).id; + const disc = await buildOrbDisc(page, 0, (y += step)); + built.orbDisc = disc.set.id; + built.orbStillsUsed = disc.images; + built.waveformMeter = (await buildWaveformMeter(page, 0, (y += step))).id; + built.micKey = (await buildMicKey(page, 0, (y += step))).id; + built.voiceBar = (await buildVoiceBar(page, 0, (y += step))).id; + return { page: page.id, built }; +} + +// --------------------------------------------------------------------------- +// Layouts (03 Layouts): the three keyboards as frames of instances, one per +// state, named exactly as the gallery captions them (//) + +const STATE_TO_MIC = { + off: "Off", + start: "Off", + idle: "Idle", + connecting: "Working", + recording: "Recording", + processing: "Working", + pasted: "Pasted", + copied: "Copied", + error: "Error", + landed: "Pasted", +}; + +async function layoutRoot(name, height) { + const f = figma.createFrame(); + f.name = name; + f.layoutMode = "VERTICAL"; + f.primaryAxisSizingMode = "FIXED"; + f.counterAxisSizingMode = "FIXED"; + f.resize(DEVICE_WIDTH, height); + f.fills = [await paint("Keyboard:kb/surface")]; + f.clipsContent = true; + await bind(f, "paddingLeft", "Metrics:margin/side"); + await bind(f, "paddingRight", "Metrics:margin/side"); + await bind(f, "paddingTop", "Metrics:margin/vertical"); + await bind(f, "paddingBottom", "Metrics:margin/vertical"); + return f; +} + +async function keyInstance(sets, tone, label, widthRef) { + const variant = sets.key.children.find((c) => c.name.includes(`Tone=${tone}`) && c.name.includes("State=Up")); + const i = variant.createInstance(); + const labelKey = Object.keys(i.componentProperties).find((k) => k.startsWith("Label")); + i.setProperties({ [labelKey]: label }); + i.name = label === "space" ? "space" : `key ${label}`; + if (widthRef) { + i.layoutSizingHorizontal = "FIXED"; + i.resize(metric(widthRef), i.height); + await bind(i, "width", `Metrics:${widthRef}`); + } + return i; +} + +async function bottomRow(sets, parent, { withSymbols }) { + const row = autoLayout("HORIZONTAL", { name: "bottom row" }); + await bind(row, "itemSpacing", "Metrics:key/gap"); + row.counterAxisAlignItems = "CENTER"; + parent.appendChild(row); + row.layoutSizingHorizontal = "FILL"; + if (withSymbols) row.appendChild(await keyInstance(sets, "Modifier", "123", "key/side-width-402")); + row.appendChild(await keyInstance(sets, "Modifier", symbolChar("globe", "🌐"), withSymbols ? "key/side-width-402" : null)); + const space = await keyInstance(sets, "Key", "space", null); + row.appendChild(space); + space.layoutSizingHorizontal = "FILL"; + if (!withSymbols) row.appendChild(await keyInstance(sets, "Modifier", symbolChar("delete.left", "⌫"), null)); + row.appendChild( + await keyInstance(sets, "Modifier", symbolChar("return", "↩"), withSymbols ? "key/return-width-402" : null) + ); + return row; +} + +async function buildPanelFrame(sets, state, theme) { + const f = await layoutRoot(`panel/${state}/${theme}`, metric("layout/panel")); + await bind(f, "itemSpacing", "Metrics:panel/spacing"); + const voice = autoLayout("VERTICAL", { name: "voice" }); + voice.primaryAxisAlignItems = "CENTER"; + voice.counterAxisAlignItems = "CENTER"; + f.appendChild(voice); + voice.layoutSizingHorizontal = "FILL"; + voice.layoutSizingVertical = "FILL"; + const mic = sets.micKey.children + .find((c) => c.name.includes("Size=Panel") && c.name.includes(`State=${STATE_TO_MIC[state] || "Idle"}`)) + .createInstance(); + mic.name = "MicKey"; + voice.appendChild(mic); + await bottomRow(sets, f, { withSymbols: false }); + const plus = sets.addTermKey.children.find((c) => c.name.includes("Saved=False")).createInstance(); + plus.name = "AddTermKey"; + f.appendChild(plus); + plus.layoutPositioning = "ABSOLUTE"; + plus.x = metric("addterm/inset"); + plus.y = metric("addterm/inset"); + if (["connecting", "recording", "processing"].includes(state)) { + const cancel = sets.cancelKey.createInstance(); + cancel.name = "CancelKey"; + f.appendChild(cancel); + cancel.layoutPositioning = "ABSOLUTE"; + cancel.constraints = { horizontal: "MAX", vertical: "MIN" }; + cancel.x = DEVICE_WIDTH - metric("margin/side") - cancel.width; + cancel.y = metric("margin/vertical"); + } + return f; +} + +async function voiceBarInstance(sets, state, hasFullAccess) { + const mode = !hasFullAccess ? "NoFullAccess" : state === "term" ? "Term" : state === "recording" ? "Wave" : "Orb"; + const i = sets.voiceBar.children.find((c) => c.name.includes(`Mode=${mode}`)).createInstance(); + i.name = "VoiceBar"; + if (mode === "Orb") { + const mic = i.findOne((n) => n.type === "INSTANCE" && n.name.startsWith("Size=Bar")); + if (mic) { + const target = sets.micKey.children.find( + (c) => c.name.includes("Size=Bar") && c.name.includes(`State=${STATE_TO_MIC[state] || "Idle"}`) + ); + if (target) mic.swapComponent(target); + } + } + return i; +} + +async function buildSlimBarFrame(sets, state, theme) { + const f = await layoutRoot(`slimBar/${state}/${theme}`, metric("layout/slim")); + const row = autoLayout("HORIZONTAL", { name: "row" }); + await bind(row, "itemSpacing", "Metrics:slim/spacing"); + row.counterAxisAlignItems = "CENTER"; + f.appendChild(row); + row.layoutSizingHorizontal = "FILL"; + row.appendChild(await keyInstance(sets, "Modifier", symbolChar("globe", "🌐"), null)); + const bar = await voiceBarInstance(sets, state, state !== "off"); + row.appendChild(bar); + bar.layoutSizingHorizontal = "FILL"; + row.appendChild(await keyInstance(sets, "Modifier", symbolChar("delete.left", "⌫"), null)); + row.appendChild(await keyInstance(sets, "Modifier", symbolChar("return", "↩"), null)); + return f; +} + +async function buildFullFrame(sets, state, theme) { + const f = await layoutRoot(`full/${state}/${theme}`, metric("layout/full")); + await bind(f, "itemSpacing", "Metrics:row/gap"); + const bar = await voiceBarInstance(sets, state, state !== "off"); + f.appendChild(bar); + bar.layoutSizingHorizontal = "FILL"; + const rows = ["qwertyuiop", "asdfghjkl", "zxcvbnm"]; + const letter = (ch) => { + const v = sets.letterKey.children.find((c) => c.name.includes("State=Up")).createInstance(); + const labelKey = Object.keys(v.componentProperties).find((k) => k.startsWith("Label")); + v.setProperties({ [labelKey]: ch }); + v.name = `key ${ch}`; + return v; + }; + for (const [index, letters] of rows.entries()) { + const row = autoLayout("HORIZONTAL", { name: `row ${index + 1}` }); + row.primaryAxisAlignItems = "CENTER"; + row.counterAxisAlignItems = "CENTER"; + f.appendChild(row); + row.layoutSizingHorizontal = "FILL"; + if (index === 2) { + row.itemSpacing = metric("key/gap") * metric("key/side-gap-factor"); + row.appendChild(await keyInstance(sets, "Modifier", symbolChar("shift", "⇧"), "key/side-width-402")); + const inner = autoLayout("HORIZONTAL", { name: "letters" }); + await bind(inner, "itemSpacing", "Metrics:key/gap"); + row.appendChild(inner); + for (const ch of letters) inner.appendChild(letter(ch)); + row.appendChild(await keyInstance(sets, "Modifier", symbolChar("delete.left", "⌫"), "key/side-width-402")); + } else { + await bind(row, "itemSpacing", "Metrics:key/gap"); + for (const ch of letters) row.appendChild(letter(ch)); + } + } + await bottomRow(sets, f, { withSymbols: true }); + return f; +} + +async function buildLayouts() { + const components = await getPage(PAGES.components); + const sets = { + key: await findComponentSet(components, "Key"), + letterKey: await findComponentSet(components, "LetterKey"), + addTermKey: await findComponentSet(components, "AddTermKey"), + cancelKey: await findComponent(components, "CancelKey"), + micKey: await findComponentSet(components, "MicKey"), + voiceBar: await findComponentSet(components, "VoiceBar"), + }; + for (const [name, set] of Object.entries(sets)) if (!set) throw new Error(`component ${name} missing — run buildComponents first`); + const page = await getPage(PAGES.layouts); + VARS = await variableMap(); + await loadFonts(); + const builders = { Panel: buildPanelFrame, SlimBar: buildSlimBarFrame, Full: buildFullFrame }; + const built = {}; + let sectionX = 0; + for (const [name, build] of Object.entries(builders)) { + const section = getSection(page, name, sectionX, 0); + for (const child of [...section.children]) child.remove(); + const states = name === "Panel" ? STATES.filter((s) => s !== "term") : STATES; + let y = 40; + const ids = []; + for (const state of states) { + const caption = await textNode(`${name.charAt(0).toLowerCase() + name.slice(1)} · ${state} · ${DESIGN_THEME}`, { + size: 11, + weight: FONT.medium, + fillRef: "Brand:ink", + }); + section.appendChild(caption); + caption.x = 40; + caption.y = y; + y += 20; + const frame = await build(sets, state, DESIGN_THEME); + section.appendChild(frame); + frame.x = 40; + frame.y = y; + y += frame.height + 40; + ids.push(frame.id); + } + section.resizeWithoutConstraints(DEVICE_WIDTH + 80, y); + built[name] = ids; + sectionX += DEVICE_WIDTH + 160; + } + return { page: page.id, built }; +} + +// --------------------------------------------------------------------------- +// Themes: kb/* re-aliased to each theme's set in turn, the idle frames +// exported at 3× and placed as images, then ink restored. This is +// KeyboardPalette.resolve(_:dark:) in Figma — a Starter file has one mode. + +async function setDesignTheme(theme) { + VARS = await variableMap(); + const keyboard = (await figma.variables.getLocalVariableCollectionsAsync()).find((c) => c.name === "Keyboard"); + const modeId = keyboard.modes[0].modeId; + for (const role of ROLES) { + const kb = VARS.get(`Keyboard:kb/${role}`); + const target = VARS.get(`Themes:${theme}/${role}`); + if (!kb || !target) throw new Error(`no variable for kb/${role} → ${theme}`); + kb.setValueForMode(modeId, figma.variables.createVariableAlias(target)); + } +} + +async function themeSheet() { + const page = await getPage(PAGES.layouts); + const sheet = getSection(page, "Theme sheet", 3 * (DEVICE_WIDTH + 160), 0); + for (const child of [...sheet.children]) child.remove(); + const idle = page.findAll((n) => n.type === "FRAME" && /^(panel|slimBar|full)\/idle\//.test(n.name)); + if (idle.length === 0) throw new Error("no idle layout frames — run buildLayouts first"); + const placed = []; + let y = 40; + try { + for (const theme of THEMES) { + await setDesignTheme(theme); + let x = 40; + let rowHeight = 0; + for (const frame of idle) { + const bytes = await frame.exportAsync({ format: "PNG", constraint: { type: "SCALE", value: 3 } }); + const image = figma.createImage(bytes); + const rect = figma.createRectangle(); + rect.name = frame.name.replace(`/${DESIGN_THEME}`, `/${theme}`); + rect.resize(frame.width, frame.height); + rect.fills = [{ type: "IMAGE", imageHash: image.hash, scaleMode: "FILL" }]; + sheet.appendChild(rect); + rect.x = x; + rect.y = y; + x += frame.width + 40; + rowHeight = Math.max(rowHeight, frame.height); + placed.push(rect.id); + } + y += rowHeight + 60; + } + } finally { + await setDesignTheme(DESIGN_THEME); + } + sheet.resizeWithoutConstraints(idle.reduce((w, f) => w + f.width + 40, 40), y); + return { sheet: sheet.id, placed: placed.length, themes: THEMES.length }; +} + +/** Bounds of whatever was pasted from Apple's kit under "Apple reference". */ +async function measureApple() { + const page = await getPage(PAGES.layouts); + const section = page.children.find((n) => n.type === "SECTION" && n.name === "Apple reference"); + if (!section) throw new Error('no "Apple reference" section — paste the iOS 27 Keyboard instances into one'); + const out = {}; + for (const root of section.children) { + const origin = root.absoluteBoundingBox; + out[root.name] = root + .findAll((n) => n.absoluteBoundingBox && n.name) + .map((n) => { + const b = n.absoluteBoundingBox; + const radius = "cornerRadius" in n && typeof n.cornerRadius === "number" ? n.cornerRadius : null; + return { name: n.name, x: +(b.x - origin.x).toFixed(2), y: +(b.y - origin.y).toFixed(2), w: +b.width.toFixed(2), h: +b.height.toFixed(2), radius }; + }); + } + return out; +} diff --git a/App/BlurtiOS/Design/figma/manifest.json b/App/BlurtiOS/Design/figma/manifest.json new file mode 100644 index 00000000..a4903a3d --- /dev/null +++ b/App/BlurtiOS/Design/figma/manifest.json @@ -0,0 +1,18 @@ +{ + "name": "Blurt Keyboard — build", + "id": "blurt-keyboard-build", + "api": "1.0.0", + "main": "code.js", + "editorType": ["figma"], + "documentAccess": "dynamic-page", + "menu": [ + { "name": "1 · Foundations (variables, styles, specimens)", "command": "foundations" }, + { "name": "2 · Components", "command": "components" }, + { "name": "3 · Layouts (state rows)", "command": "layouts" }, + { "name": "4 · Theme sheet", "command": "theme-sheet" }, + { "separator": true }, + { "name": "Export tokens (console)", "command": "export-tokens" }, + { "name": "Export bounds (console)", "command": "export-bounds" }, + { "name": "Measure Apple reference (console)", "command": "measure-apple" } + ] +} diff --git a/App/BlurtiOS/Design/figma/plugin.js b/App/BlurtiOS/Design/figma/plugin.js new file mode 100644 index 00000000..0f3c5469 --- /dev/null +++ b/App/BlurtiOS/Design/figma/plugin.js @@ -0,0 +1,31 @@ +// The development-plugin entry: scripts/design-sync.sh concatenates +// tokens.js + lib.js + this file into .build/figma-plugin/code.js. Each menu +// command in manifest.json runs one builder; the result's first line is shown +// as the plugin closes, the whole thing is in the console. +/* global figma, buildFoundations, buildComponents, buildLayouts, themeSheet, exportTokens, exportBounds, measureApple */ + +const COMMANDS = { + foundations: buildFoundations, + components: buildComponents, + layouts: buildLayouts, + "theme-sheet": themeSheet, + "export-tokens": exportTokens, + "export-bounds": exportBounds, + "measure-apple": measureApple, +}; + +(async () => { + const run = COMMANDS[figma.command]; + if (!run) { + figma.closePlugin(`unknown command ${figma.command}`); + return; + } + try { + const result = await run(); + console.log(JSON.stringify(result, null, 2)); + figma.closePlugin(`${figma.command}: done (result in the console)`); + } catch (error) { + console.error(error); + figma.closePlugin(`${figma.command}: ${error.message}`); + } +})(); diff --git a/App/BlurtiOS/Design/figma/tokens.js b/App/BlurtiOS/Design/figma/tokens.js new file mode 100644 index 00000000..fb1b9e9a --- /dev/null +++ b/App/BlurtiOS/Design/figma/tokens.js @@ -0,0 +1,2072 @@ +// Generated by scripts/design-tokens.swift from App/BlurtiOS/Design/tokens.json — do not edit. +// The build scripts in this folder (lib.js) read this; a use_figma call is +// tokens.js + lib.js + one line that returns a builder's result. +const TOKENS = { + "collections" : { + "Brand" : { + "mode" : "Value", + "variables" : [ + { + "codeSyntax" : "DesignTokens.Brand.appleDarkKey", + "name" : "apple\/dark-key", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "the iPhone keyboard's dark key", + "value" : "#6B6B6B" + }, + { + "codeSyntax" : "DesignTokens.Brand.appleDarkModifier", + "name" : "apple\/dark-modifier", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "the iPhone keyboard's dark modifier key", + "value" : "#464646" + }, + { + "codeSyntax" : "DesignTokens.Brand.appleDarkSurface", + "name" : "apple\/dark-surface", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "the iPhone keyboard's dark surface", + "value" : "#2B2B2B" + }, + { + "codeSyntax" : "DesignTokens.Brand.appleLightModifier", + "name" : "apple\/light-modifier", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "the iPhone keyboard's light modifier key", + "value" : "#ADB3BC" + }, + { + "codeSyntax" : "DesignTokens.Brand.appleLightSurface", + "name" : "apple\/light-surface", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "the iPhone keyboard's light surface", + "value" : "#D1D5DB" + }, + { + "codeSyntax" : "DesignTokens.Brand.black", + "name" : "black", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#000000" + }, + { + "codeSyntax" : "DesignTokens.Brand.card", + "name" : "card", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "the warm card fill; the paper theme's surface", + "value" : "#EBE8E8" + }, + { + "codeSyntax" : "DesignTokens.Brand.cardBorder", + "name" : "card-border", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "the card's hairline; the paper theme's modifier key", + "value" : "#DEDBDB" + }, + { + "codeSyntax" : "DesignTokens.Brand.cobolt", + "name" : "cobolt", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "AssemblyAI's primary violet: the drop, never a key or a surface", + "value" : "#3923C7" + }, + { + "codeSyntax" : "DesignTokens.Brand.green100", + "name" : "green\/100", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "the design system's UI-and-code green fill (unused on the phone yet)", + "value" : "#CCE4D5" + }, + { + "codeSyntax" : "DesignTokens.Brand.green200", + "name" : "green\/200", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "the design system's UI-and-code green highlight (unused on the phone yet)", + "value" : "#99C8AC" + }, + { + "codeSyntax" : "DesignTokens.Brand.green400", + "name" : "green\/400", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "the brand hue lifted for dark chrome: the meter, the ring, the wave on ink", + "value" : "#67AD82" + }, + { + "codeSyntax" : "DesignTokens.Brand.green700", + "name" : "green\/700", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "the wordmark green, light chrome (the app's accent in light)", + "value" : "#01762F" + }, + { + "codeSyntax" : "DesignTokens.Brand.greenMist", + "name" : "green\/mist", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "the pale green the orb lightens into", + "value" : "#DBF5E6" + }, + { + "codeSyntax" : "DesignTokens.Brand.ink", + "name" : "ink", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "the brand ink: the Mac pill's body, the ink theme's surface", + "value" : "#1D1B16" + }, + { + "codeSyntax" : "DesignTokens.Brand.ink600", + "name" : "ink\/600", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "the Mac's dark card border", + "value" : "#3A362F" + }, + { + "codeSyntax" : "DesignTokens.Brand.ink700", + "name" : "ink\/700", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "an ordinary key on ink, one step up", + "value" : "#33302A" + }, + { + "codeSyntax" : "DesignTokens.Brand.ink800", + "name" : "ink\/800", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "a modifier key on ink; the Mac's dark card fill", + "value" : "#26231E" + }, + { + "codeSyntax" : "DesignTokens.Brand.orange", + "name" : "orange", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "the error word and ring, cancel, the Full Access note; never a red body", + "value" : "#E67F36" + }, + { + "codeSyntax" : "DesignTokens.Brand.page", + "name" : "page", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "the design system's page background (unused on the phone)", + "value" : "#FDFCF8" + }, + { + "codeSyntax" : "DesignTokens.Brand.violetIris", + "name" : "violet\/iris", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "the orb gradient's upper violet stop", + "value" : "#887BDD" + }, + { + "codeSyntax" : "DesignTokens.Brand.violetLavender", + "name" : "violet\/lavender", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "the orb's lightest violet: its top and the gradient's ends", + "value" : "#D7D3F4" + }, + { + "codeSyntax" : "DesignTokens.Brand.violetPeriwinkle", + "name" : "violet\/periwinkle", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "the orb's mid violet: the drop's halo", + "value" : "#B0A7E9" + }, + { + "codeSyntax" : "DesignTokens.Brand.warmWhite", + "name" : "warm-white", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "key legends on ink: warm white on warm ink", + "value" : "#F2EEE6" + }, + { + "codeSyntax" : "DesignTokens.Brand.white", + "name" : "white", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#FFFFFF" + } + ] + }, + "Keyboard" : { + "mode" : "Value", + "variables" : [ + { + "alias" : "Brand:green\/400", + "codeSyntax" : "DesignTokens.Keyboard.appAccentDark", + "name" : "app\/accent-dark", + "scopes" : [ + "FRAME_FILL", + "SHAPE_FILL" + ], + "type" : "COLOR", + "use" : "the catalog's AccentColor in dark", + "value" : "#67AD82" + }, + { + "alias" : "Brand:green\/700", + "codeSyntax" : "DesignTokens.Keyboard.appAccentLight", + "name" : "app\/accent-light", + "scopes" : [ + "FRAME_FILL", + "SHAPE_FILL" + ], + "type" : "COLOR", + "use" : "the catalog's AccentColor in light", + "value" : "#01762F" + }, + { + "alias" : "Brand:ink\/600", + "codeSyntax" : "DesignTokens.Keyboard.appCardBorderDark", + "name" : "app\/card-border-dark", + "scopes" : [ + "STROKE_COLOR" + ], + "type" : "COLOR", + "use" : "the catalog's CardBorder in dark", + "value" : "#3A362F" + }, + { + "alias" : "Brand:card-border", + "codeSyntax" : "DesignTokens.Keyboard.appCardBorderLight", + "name" : "app\/card-border-light", + "scopes" : [ + "STROKE_COLOR" + ], + "type" : "COLOR", + "use" : "the catalog's CardBorder in light", + "value" : "#DEDBDB" + }, + { + "alias" : "Brand:ink\/800", + "codeSyntax" : "DesignTokens.Keyboard.appCardFillDark", + "name" : "app\/card-fill-dark", + "scopes" : [ + "FRAME_FILL", + "SHAPE_FILL" + ], + "type" : "COLOR", + "use" : "the catalog's CardFill in dark", + "value" : "#26231E" + }, + { + "alias" : "Brand:card", + "codeSyntax" : "DesignTokens.Keyboard.appCardFillLight", + "name" : "app\/card-fill-light", + "scopes" : [ + "FRAME_FILL", + "SHAPE_FILL" + ], + "type" : "COLOR", + "use" : "the catalog's CardFill in light", + "value" : "#EBE8E8" + }, + { + "alias" : "Brand:orange", + "codeSyntax" : "DesignTokens.Keyboard.kbCancel", + "name" : "kb\/cancel", + "scopes" : [ + "FRAME_FILL", + "SHAPE_FILL" + ], + "type" : "COLOR", + "use" : "the panel's cancel ×", + "value" : "#E67F36" + }, + { + "alias" : "Brand:orange", + "codeSyntax" : "DesignTokens.Keyboard.kbFullAccessNote", + "name" : "kb\/full-access-note", + "scopes" : [ + "TEXT_FILL" + ], + "type" : "COLOR", + "use" : "the one line of words the keyboard ever shows", + "value" : "#E67F36" + }, + { + "alias" : "Themes:ink\/key", + "codeSyntax" : "DesignTokens.Keyboard.kbKey", + "name" : "kb\/key", + "scopes" : [ + "FRAME_FILL", + "SHAPE_FILL" + ], + "type" : "COLOR", + "use" : "an ordinary key", + "value" : "#33302A" + }, + { + "alias" : "Themes:ink\/key-modifier", + "codeSyntax" : "DesignTokens.Keyboard.kbKeyModifier", + "name" : "kb\/key-modifier", + "scopes" : [ + "FRAME_FILL", + "SHAPE_FILL" + ], + "type" : "COLOR", + "use" : "shift, delete, globe, return, 123, cancel", + "value" : "#26231E" + }, + { + "alias" : "Themes:ink\/legend", + "codeSyntax" : "DesignTokens.Keyboard.kbLegend", + "name" : "kb\/legend", + "scopes" : [ + "TEXT_FILL" + ], + "type" : "COLOR", + "use" : "key legends and bare glyphs", + "value" : "#F2EEE6" + }, + { + "alias" : "Brand:orange", + "codeSyntax" : "DesignTokens.Keyboard.kbNoticeError", + "name" : "kb\/notice-error", + "scopes" : [ + "STROKE_COLOR" + ], + "type" : "COLOR", + "use" : "the solid ring and glyph for an error", + "value" : "#E67F36" + }, + { + "alias" : "Brand:green\/400", + "codeSyntax" : "DesignTokens.Keyboard.kbNoticeOk", + "name" : "kb\/notice-ok", + "scopes" : [ + "STROKE_COLOR" + ], + "type" : "COLOR", + "use" : "the solid ring for pasted and copied", + "value" : "#67AD82" + }, + { + "alias" : "Brand:white", + "codeSyntax" : "DesignTokens.Keyboard.kbOrbRingEnd", + "name" : "kb\/orb-ring-end", + "scopes" : [ + "STROKE_COLOR" + ], + "type" : "COLOR", + "use" : "the sweeping ring's gradient, bottom-trailing", + "value" : "#FFFFFF" + }, + { + "alias" : "Brand:green\/700", + "codeSyntax" : "DesignTokens.Keyboard.kbOrbRingStart", + "name" : "kb\/orb-ring-start", + "scopes" : [ + "STROKE_COLOR" + ], + "type" : "COLOR", + "use" : "the sweeping ring's gradient, top-leading", + "value" : "#01762F" + }, + { + "alias" : "Themes:ink\/popup", + "codeSyntax" : "DesignTokens.Keyboard.kbPopup", + "name" : "kb\/popup", + "scopes" : [ + "FRAME_FILL", + "SHAPE_FILL" + ], + "type" : "COLOR", + "use" : "the letter pop-up", + "value" : "#33302A" + }, + { + "alias" : "Themes:ink\/signal", + "codeSyntax" : "DesignTokens.Keyboard.kbSignal", + "name" : "kb\/signal", + "scopes" : [ + "SHAPE_FILL", + "TEXT_FILL" + ], + "type" : "COLOR", + "use" : "the wave, the caret, the saved check", + "value" : "#67AD82" + }, + { + "alias" : "Themes:ink\/surface", + "codeSyntax" : "DesignTokens.Keyboard.kbSurface", + "name" : "kb\/surface", + "scopes" : [ + "FRAME_FILL", + "SHAPE_FILL" + ], + "type" : "COLOR", + "use" : "the design theme's surface (Figma binds to kb\/*; Swift reads the palette)", + "value" : "#1D1B16" + } + ] + }, + "Metrics" : { + "mode" : "Value", + "variables" : [ + { + "codeSyntax" : "DesignTokens.Metrics.addtermInset", + "name" : "addterm\/inset", + "scopes" : [ + "GAP" + ], + "type" : "FLOAT", + "use" : "the + from the panel's corner", + "value" : 6 + }, + { + "codeSyntax" : "DesignTokens.Metrics.cardBorder", + "name" : "card\/border", + "scopes" : [ + "STROKE_FLOAT", + "WIDTH_HEIGHT" + ], + "type" : "FLOAT", + "use" : "the card's hairline", + "value" : 1 + }, + { + "codeSyntax" : "DesignTokens.Metrics.cardRadius", + "name" : "card\/radius", + "scopes" : [ + "CORNER_RADIUS" + ], + "type" : "FLOAT", + "use" : "the app's cards", + "value" : 16 + }, + { + "codeSyntax" : "DesignTokens.Metrics.caretHeight", + "name" : "caret\/height", + "scopes" : [ + "WIDTH_HEIGHT" + ], + "type" : "FLOAT", + "use" : "", + "value" : 20 + }, + { + "codeSyntax" : "DesignTokens.Metrics.caretLead", + "name" : "caret\/lead", + "scopes" : [ + "GAP" + ], + "type" : "FLOAT", + "use" : "the caret's gap from the text", + "value" : 1 + }, + { + "codeSyntax" : "DesignTokens.Metrics.caretRadius", + "name" : "caret\/radius", + "scopes" : [ + "CORNER_RADIUS" + ], + "type" : "FLOAT", + "use" : "", + "value" : 1 + }, + { + "codeSyntax" : "DesignTokens.Metrics.caretWidth", + "name" : "caret\/width", + "scopes" : [ + "STROKE_FLOAT", + "WIDTH_HEIGHT" + ], + "type" : "FLOAT", + "use" : "", + "value" : 2 + }, + { + "codeSyntax" : "DesignTokens.Metrics.gestureSwipeMin", + "name" : "gesture\/swipe-min", + "scopes" : [ + + ], + "type" : "FLOAT", + "use" : "the carousel gesture's minimum distance", + "value" : 24 + }, + { + "codeSyntax" : "DesignTokens.Metrics.glyphHit", + "name" : "glyph\/hit", + "scopes" : [ + "WIDTH_HEIGHT" + ], + "type" : "FLOAT", + "use" : "the +, × and ✓ touch targets", + "value" : 32 + }, + { + "codeSyntax" : "DesignTokens.Metrics.keyGap", + "name" : "key\/gap", + "scopes" : [ + "GAP" + ], + "type" : "FLOAT", + "use" : "between keys, the iPhone's", + "value" : 6 + }, + { + "codeSyntax" : "DesignTokens.Metrics.keyHeight", + "name" : "key\/height", + "scopes" : [ + "WIDTH_HEIGHT" + ], + "type" : "FLOAT", + "use" : "every key", + "value" : 42 + }, + { + "codeSyntax" : "DesignTokens.Metrics.keyLetterWidth402", + "name" : "key\/letter-width-402", + "scopes" : [ + "WIDTH_HEIGHT" + ], + "type" : "FLOAT", + "use" : "a letter key at 402 pt (iPhone 18 Pro): (width − 9 × key\/gap) \/ 10", + "value" : 34.799999999999997 + }, + { + "codeSyntax" : "DesignTokens.Metrics.keyMinWidth", + "name" : "key\/min-width", + "scopes" : [ + "WIDTH_HEIGHT" + ], + "type" : "FLOAT", + "use" : "a key that isn't given a width", + "value" : 44 + }, + { + "codeSyntax" : "DesignTokens.Metrics.keyPad", + "name" : "key\/pad", + "scopes" : [ + "GAP" + ], + "type" : "FLOAT", + "use" : "a legend's side padding on a min-width key", + "value" : 4 + }, + { + "codeSyntax" : "DesignTokens.Metrics.keyRadius", + "name" : "key\/radius", + "scopes" : [ + "CORNER_RADIUS" + ], + "type" : "FLOAT", + "use" : "flat keys, one colour at this corner", + "value" : 8 + }, + { + "codeSyntax" : "DesignTokens.Metrics.keyReturnWidth402", + "name" : "key\/return-width-402", + "scopes" : [ + "WIDTH_HEIGHT" + ], + "type" : "FLOAT", + "use" : "return at 402 pt: two side keys and a gap", + "value" : 104.40000000000001 + }, + { + "codeSyntax" : "DesignTokens.Metrics.keySideGapFactor", + "name" : "key\/side-gap-factor", + "scopes" : [ + + ], + "type" : "FLOAT", + "use" : "shift and delete stand this many key gaps from the letters", + "value" : 2 + }, + { + "codeSyntax" : "DesignTokens.Metrics.keySideWidth402", + "name" : "key\/side-width-402", + "scopes" : [ + "WIDTH_HEIGHT" + ], + "type" : "FLOAT", + "use" : "shift, delete, 123 and globe at 402 pt: what seven letters leave, halved", + "value" : 49.200000000000003 + }, + { + "codeSyntax" : "DesignTokens.Metrics.layoutFull", + "name" : "layout\/full", + "scopes" : [ + "WIDTH_HEIGHT" + ], + "type" : "FLOAT", + "use" : "2 × margin\/vertical + voicebar\/height + 4 × row\/gap + 4 × key\/height", + "value" : 272 + }, + { + "codeSyntax" : "DesignTokens.Metrics.layoutPanel", + "name" : "layout\/panel", + "scopes" : [ + "WIDTH_HEIGHT" + ], + "type" : "FLOAT", + "use" : "chosen: room for the 96 orb over one key row", + "value" : 216 + }, + { + "codeSyntax" : "DesignTokens.Metrics.layoutSlim", + "name" : "layout\/slim", + "scopes" : [ + "WIDTH_HEIGHT" + ], + "type" : "FLOAT", + "use" : "2 × margin\/vertical + voicebar\/height", + "value" : 60 + }, + { + "codeSyntax" : "DesignTokens.Metrics.marginSide", + "name" : "margin\/side", + "scopes" : [ + "WIDTH_HEIGHT" + ], + "type" : "FLOAT", + "use" : "at the keyboard's sides", + "value" : 3 + }, + { + "codeSyntax" : "DesignTokens.Metrics.marginVertical", + "name" : "margin\/vertical", + "scopes" : [ + "WIDTH_HEIGHT" + ], + "type" : "FLOAT", + "use" : "the keyboard's top and bottom", + "value" : 8 + }, + { + "codeSyntax" : "DesignTokens.Metrics.opacityDim", + "name" : "opacity\/dim", + "scopes" : [ + "OPACITY" + ], + "type" : "FLOAT", + "use" : "the orb when Blurt isn't ready", + "value" : 0.80000000000000004 + }, + { + "codeSyntax" : "DesignTokens.Metrics.opacityDimSaturation", + "name" : "opacity\/dim-saturation", + "scopes" : [ + "OPACITY" + ], + "type" : "FLOAT", + "use" : "and its saturation", + "value" : 0.34999999999999998 + }, + { + "codeSyntax" : "DesignTokens.Metrics.opacityDisabled", + "name" : "opacity\/disabled", + "scopes" : [ + "OPACITY" + ], + "type" : "FLOAT", + "use" : "the + without Full Access", + "value" : 0.40000000000000002 + }, + { + "codeSyntax" : "DesignTokens.Metrics.opacityGrain", + "name" : "opacity\/grain", + "scopes" : [ + "OPACITY" + ], + "type" : "FLOAT", + "use" : "", + "value" : 0.5 + }, + { + "codeSyntax" : "DesignTokens.Metrics.opacityHomeDimSaturation", + "name" : "opacity\/home-dim-saturation", + "scopes" : [ + "OPACITY" + ], + "type" : "FLOAT", + "use" : "the home hero's saturation when not listening", + "value" : 0.45000000000000001 + }, + { + "codeSyntax" : "DesignTokens.Metrics.opacityLegendMuted", + "name" : "opacity\/legend-muted", + "scopes" : [ + "OPACITY" + ], + "type" : "FLOAT", + "use" : "the + at rest", + "value" : 0.5 + }, + { + "codeSyntax" : "DesignTokens.Metrics.opacityOrbLight", + "name" : "opacity\/orb-light", + "scopes" : [ + "OPACITY" + ], + "type" : "FLOAT", + "use" : "", + "value" : 0.29999999999999999 + }, + { + "codeSyntax" : "DesignTokens.Metrics.opacityPlaceholder", + "name" : "opacity\/placeholder", + "scopes" : [ + "OPACITY" + ], + "type" : "FLOAT", + "use" : "the field's placeholder", + "value" : 0.40000000000000002 + }, + { + "codeSyntax" : "DesignTokens.Metrics.opacityPopupShadow", + "name" : "opacity\/popup-shadow", + "scopes" : [ + "OPACITY" + ], + "type" : "FLOAT", + "use" : "", + "value" : 0.12 + }, + { + "codeSyntax" : "DesignTokens.Metrics.opacityPressBrighten", + "name" : "opacity\/press-brighten", + "scopes" : [ + "OPACITY" + ], + "type" : "FLOAT", + "use" : "a key lightens this much while pressed", + "value" : 0.14999999999999999 + }, + { + "codeSyntax" : "DesignTokens.Metrics.opacityTermCancel", + "name" : "opacity\/term-cancel", + "scopes" : [ + "OPACITY" + ], + "type" : "FLOAT", + "use" : "the field's ×", + "value" : 0.69999999999999996 + }, + { + "codeSyntax" : "DesignTokens.Metrics.orbBar", + "name" : "orb\/bar", + "scopes" : [ + "WIDTH_HEIGHT" + ], + "type" : "FLOAT", + "use" : "the orb in the voice bar", + "value" : 40 + }, + { + "codeSyntax" : "DesignTokens.Metrics.orbDissipateBlur", + "name" : "orb\/dissipate-blur", + "scopes" : [ + + ], + "type" : "FLOAT", + "use" : "and blurs to this fraction of its size", + "value" : 0.16 + }, + { + "codeSyntax" : "DesignTokens.Metrics.orbDissipateScale", + "name" : "orb\/dissipate-scale", + "scopes" : [ + + ], + "type" : "FLOAT", + "use" : "the orb swells to this while dissipating", + "value" : 1.25 + }, + { + "codeSyntax" : "DesignTokens.Metrics.orbHome", + "name" : "orb\/home", + "scopes" : [ + "WIDTH_HEIGHT" + ], + "type" : "FLOAT", + "use" : "the orb on the home screen", + "value" : 112 + }, + { + "codeSyntax" : "DesignTokens.Metrics.orbLightRadius", + "name" : "orb\/light-radius", + "scopes" : [ + + ], + "type" : "FLOAT", + "use" : "the light's reach in points (fixed, not proportional — open)", + "value" : 110 + }, + { + "codeSyntax" : "DesignTokens.Metrics.orbLightX", + "name" : "orb\/light-x", + "scopes" : [ + + ], + "type" : "FLOAT", + "use" : "the soft light's centre, as a fraction of the orb", + "value" : 0.29999999999999999 + }, + { + "codeSyntax" : "DesignTokens.Metrics.orbLightY", + "name" : "orb\/light-y", + "scopes" : [ + + ], + "type" : "FLOAT", + "use" : "", + "value" : 0.22 + }, + { + "codeSyntax" : "DesignTokens.Metrics.orbPanel", + "name" : "orb\/panel", + "scopes" : [ + "WIDTH_HEIGHT" + ], + "type" : "FLOAT", + "use" : "the orb in the panel", + "value" : 96 + }, + { + "codeSyntax" : "DesignTokens.Metrics.panelSpacing", + "name" : "panel\/spacing", + "scopes" : [ + "GAP" + ], + "type" : "FLOAT", + "use" : "between the panel's orb and its key row", + "value" : 12 + }, + { + "codeSyntax" : "DesignTokens.Metrics.pickerPreviewWidth", + "name" : "picker\/preview-width", + "scopes" : [ + "WIDTH_HEIGHT" + ], + "type" : "FLOAT", + "use" : "the theme card draws the keyboard at this width", + "value" : 393 + }, + { + "codeSyntax" : "DesignTokens.Metrics.pickerRadius", + "name" : "picker\/radius", + "scopes" : [ + "CORNER_RADIUS" + ], + "type" : "FLOAT", + "use" : "the theme card's preview corners", + "value" : 10 + }, + { + "codeSyntax" : "DesignTokens.Metrics.pickerScale", + "name" : "picker\/scale", + "scopes" : [ + + ], + "type" : "FLOAT", + "use" : "then scales it to fit two across", + "value" : 0.41999999999999998 + }, + { + "codeSyntax" : "DesignTokens.Metrics.popupExtraWidth", + "name" : "popup\/extra-width", + "scopes" : [ + "WIDTH_HEIGHT" + ], + "type" : "FLOAT", + "use" : "the letter pop-up is the key width plus this", + "value" : 18 + }, + { + "codeSyntax" : "DesignTokens.Metrics.popupHeight", + "name" : "popup\/height", + "scopes" : [ + "WIDTH_HEIGHT" + ], + "type" : "FLOAT", + "use" : "", + "value" : 56 + }, + { + "codeSyntax" : "DesignTokens.Metrics.popupOffset", + "name" : "popup\/offset", + "scopes" : [ + "WIDTH_HEIGHT" + ], + "type" : "FLOAT", + "use" : "the pop-up sits this far above the key", + "value" : 58 + }, + { + "codeSyntax" : "DesignTokens.Metrics.popupRadius", + "name" : "popup\/radius", + "scopes" : [ + "CORNER_RADIUS" + ], + "type" : "FLOAT", + "use" : "", + "value" : 10 + }, + { + "codeSyntax" : "DesignTokens.Metrics.popupShadowRadius", + "name" : "popup\/shadow-radius", + "scopes" : [ + "WIDTH_HEIGHT" + ], + "type" : "FLOAT", + "use" : "the one thing that floats", + "value" : 8 + }, + { + "codeSyntax" : "DesignTokens.Metrics.popupShadowY", + "name" : "popup\/shadow-y", + "scopes" : [ + "WIDTH_HEIGHT" + ], + "type" : "FLOAT", + "use" : "", + "value" : 2 + }, + { + "codeSyntax" : "DesignTokens.Metrics.pressScale", + "name" : "press\/scale", + "scopes" : [ + + ], + "type" : "FLOAT", + "use" : "the orb while pressed", + "value" : 0.93999999999999995 + }, + { + "codeSyntax" : "DesignTokens.Metrics.ringActive", + "name" : "ring\/active", + "scopes" : [ + "STROKE_FLOAT", + "WIDTH_HEIGHT" + ], + "type" : "FLOAT", + "use" : "the ring while working or noticing; the home ring", + "value" : 2 + }, + { + "codeSyntax" : "DesignTokens.Metrics.ringStill", + "name" : "ring\/still", + "scopes" : [ + "STROKE_FLOAT", + "WIDTH_HEIGHT" + ], + "type" : "FLOAT", + "use" : "the ring at rest", + "value" : 1 + }, + { + "codeSyntax" : "DesignTokens.Metrics.rowGap", + "name" : "row\/gap", + "scopes" : [ + "GAP" + ], + "type" : "FLOAT", + "use" : "between rows, the iPhone's", + "value" : 11 + }, + { + "codeSyntax" : "DesignTokens.Metrics.slimSpacing", + "name" : "slim\/spacing", + "scopes" : [ + "GAP" + ], + "type" : "FLOAT", + "use" : "between the slim bar's keys", + "value" : 8 + }, + { + "codeSyntax" : "DesignTokens.Metrics.termGap", + "name" : "term\/gap", + "scopes" : [ + "GAP" + ], + "type" : "FLOAT", + "use" : "× · field · ✓", + "value" : 8 + }, + { + "codeSyntax" : "DesignTokens.Metrics.termHeight", + "name" : "term\/height", + "scopes" : [ + "WIDTH_HEIGHT" + ], + "type" : "FLOAT", + "use" : "the key-term field's capsule", + "value" : 36 + }, + { + "codeSyntax" : "DesignTokens.Metrics.termInset", + "name" : "term\/inset", + "scopes" : [ + "GAP" + ], + "type" : "FLOAT", + "use" : "the field row's side inset", + "value" : 2 + }, + { + "codeSyntax" : "DesignTokens.Metrics.termPad", + "name" : "term\/pad", + "scopes" : [ + "GAP" + ], + "type" : "FLOAT", + "use" : "the field's side padding", + "value" : 14 + }, + { + "codeSyntax" : "DesignTokens.Metrics.voicebarAddtermClearance", + "name" : "voicebar\/addterm-clearance", + "scopes" : [ + "GAP" + ], + "type" : "FLOAT", + "use" : "the wave stays this clear of the + at the trailing edge", + "value" : 12 + }, + { + "codeSyntax" : "DesignTokens.Metrics.voicebarHeight", + "name" : "voicebar\/height", + "scopes" : [ + "WIDTH_HEIGHT" + ], + "type" : "FLOAT", + "use" : "the voice row, where the system puts its suggestion bar", + "value" : 44 + }, + { + "codeSyntax" : "DesignTokens.Metrics.voicebarNoteGap", + "name" : "voicebar\/note-gap", + "scopes" : [ + "GAP" + ], + "type" : "FLOAT", + "use" : "between the orb and the Full Access note", + "value" : 10 + }, + { + "codeSyntax" : "DesignTokens.Metrics.waveBar", + "name" : "wave\/bar", + "scopes" : [ + "STROKE_FLOAT", + "WIDTH_HEIGHT" + ], + "type" : "FLOAT", + "use" : "a wave bar's width", + "value" : 2 + }, + { + "codeSyntax" : "DesignTokens.Metrics.waveBarHeight", + "name" : "wave\/bar-height", + "scopes" : [ + "WIDTH_HEIGHT" + ], + "type" : "FLOAT", + "use" : "", + "value" : 24 + }, + { + "codeSyntax" : "DesignTokens.Metrics.waveBarWidth", + "name" : "wave\/bar-width", + "scopes" : [ + "WIDTH_HEIGHT" + ], + "type" : "FLOAT", + "use" : "the wave in the voice bar, at most", + "value" : 240 + }, + { + "codeSyntax" : "DesignTokens.Metrics.waveGap", + "name" : "wave\/gap", + "scopes" : [ + "GAP" + ], + "type" : "FLOAT", + "use" : "between wave bars", + "value" : 2 + }, + { + "codeSyntax" : "DesignTokens.Metrics.waveHomeHeight", + "name" : "wave\/home-height", + "scopes" : [ + "WIDTH_HEIGHT" + ], + "type" : "FLOAT", + "use" : "", + "value" : 44 + }, + { + "codeSyntax" : "DesignTokens.Metrics.waveHomeWidth", + "name" : "wave\/home-width", + "scopes" : [ + "WIDTH_HEIGHT" + ], + "type" : "FLOAT", + "use" : "", + "value" : 280 + }, + { + "codeSyntax" : "DesignTokens.Metrics.wavePanelHeight", + "name" : "wave\/panel-height", + "scopes" : [ + "WIDTH_HEIGHT" + ], + "type" : "FLOAT", + "use" : "", + "value" : 40 + }, + { + "codeSyntax" : "DesignTokens.Metrics.wavePanelWidth", + "name" : "wave\/panel-width", + "scopes" : [ + "WIDTH_HEIGHT" + ], + "type" : "FLOAT", + "use" : "", + "value" : 300 + }, + { + "codeSyntax" : "DesignTokens.Metrics.wordmarkHeight", + "name" : "wordmark\/height", + "scopes" : [ + "WIDTH_HEIGHT" + ], + "type" : "FLOAT", + "use" : "", + "value" : 22 + } + ] + }, + "Motion" : { + "mode" : "Value", + "variables" : [ + { + "codeSyntax" : "DesignTokens.Motion.caret", + "name" : "caret", + "scopes" : [ + + ], + "type" : "FLOAT", + "use" : "the caret's blink", + "value" : 0.5 + }, + { + "codeSyntax" : "DesignTokens.Motion.drop", + "name" : "drop", + "scopes" : [ + + ], + "type" : "FLOAT", + "use" : "the violet drop is gone by", + "value" : 2.3999999999999999 + }, + { + "codeSyntax" : "DesignTokens.Motion.dropHold", + "name" : "drop-hold", + "scopes" : [ + + ], + "type" : "FLOAT", + "use" : "and held to", + "value" : 0.90000000000000002 + }, + { + "codeSyntax" : "DesignTokens.Motion.dropRise", + "name" : "drop-rise", + "scopes" : [ + + ], + "type" : "FLOAT", + "use" : "the drop is up in", + "value" : 0.5 + }, + { + "codeSyntax" : "DesignTokens.Motion.dropSpread", + "name" : "drop-spread", + "scopes" : [ + + ], + "type" : "FLOAT", + "use" : "the bloom reaches its full spread in", + "value" : 1 + }, + { + "codeSyntax" : "DesignTokens.Motion.flip", + "name" : "flip", + "scopes" : [ + + ], + "type" : "FLOAT", + "use" : "the panel's carousel", + "value" : 0.25 + }, + { + "codeSyntax" : "DesignTokens.Motion.heightChange", + "name" : "height-change", + "scopes" : [ + + ], + "type" : "FLOAT", + "use" : "the keyboard resizing", + "value" : 0.25 + }, + { + "codeSyntax" : "DesignTokens.Motion.keyPress", + "name" : "key-press", + "scopes" : [ + + ], + "type" : "FLOAT", + "use" : "a key lighting", + "value" : 0.080000000000000002 + }, + { + "codeSyntax" : "DesignTokens.Motion.mood", + "name" : "mood", + "scopes" : [ + + ], + "type" : "FLOAT", + "use" : "the orb's colour moving between moods", + "value" : 0.80000000000000004 + }, + { + "codeSyntax" : "DesignTokens.Motion.press", + "name" : "press", + "scopes" : [ + + ], + "type" : "FLOAT", + "use" : "the orb's press; the one thing that answers at once", + "value" : 0.10000000000000001 + }, + { + "codeSyntax" : "DesignTokens.Motion.ringPeriod", + "name" : "ring-period", + "scopes" : [ + + ], + "type" : "FLOAT", + "use" : "one turn of the ring, the Mac's cadence", + "value" : 1.6000000000000001 + }, + { + "codeSyntax" : "DesignTokens.Motion.stateFade", + "name" : "state-fade", + "scopes" : [ + + ], + "type" : "FLOAT", + "use" : "every other change on the key: the ring, a glyph, the dimming", + "value" : 0.5 + }, + { + "codeSyntax" : "DesignTokens.Motion.termSwap", + "name" : "term-swap", + "scopes" : [ + + ], + "type" : "FLOAT", + "use" : "the voice bar becoming the field", + "value" : 0.40000000000000002 + }, + { + "codeSyntax" : "DesignTokens.Motion.waveFade", + "name" : "wave-fade", + "scopes" : [ + + ], + "type" : "FLOAT", + "use" : "the orb and the wave crossing, either way", + "value" : 0.69999999999999996 + } + ] + }, + "Themes" : { + "mode" : "Value", + "variables" : [ + { + "alias" : "Brand:ink\/700", + "codeSyntax" : "DesignTokens.Themes.inkKey", + "name" : "ink\/key", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#33302A" + }, + { + "alias" : "Brand:ink\/800", + "codeSyntax" : "DesignTokens.Themes.inkKeyModifier", + "name" : "ink\/key-modifier", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#26231E" + }, + { + "alias" : "Brand:warm-white", + "codeSyntax" : "DesignTokens.Themes.inkLegend", + "name" : "ink\/legend", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#F2EEE6" + }, + { + "alias" : "Brand:ink\/700", + "codeSyntax" : "DesignTokens.Themes.inkPopup", + "name" : "ink\/popup", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#33302A" + }, + { + "alias" : "Brand:green\/400", + "codeSyntax" : "DesignTokens.Themes.inkSignal", + "name" : "ink\/signal", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#67AD82" + }, + { + "alias" : "Brand:ink", + "codeSyntax" : "DesignTokens.Themes.inkSurface", + "name" : "ink\/surface", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#1D1B16" + }, + { + "codeSyntax" : "DesignTokens.Themes.lavenderKey", + "name" : "lavender\/key", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#3F3777" + }, + { + "codeSyntax" : "DesignTokens.Themes.lavenderKeyModifier", + "name" : "lavender\/key-modifier", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#352E68" + }, + { + "codeSyntax" : "DesignTokens.Themes.lavenderLegend", + "name" : "lavender\/legend", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#F1EEFF" + }, + { + "codeSyntax" : "DesignTokens.Themes.lavenderPopup", + "name" : "lavender\/popup", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#3F3777" + }, + { + "alias" : "Brand:green\/400", + "codeSyntax" : "DesignTokens.Themes.lavenderSignal", + "name" : "lavender\/signal", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#67AD82" + }, + { + "codeSyntax" : "DesignTokens.Themes.lavenderSurface", + "name" : "lavender\/surface", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#2C2557" + }, + { + "codeSyntax" : "DesignTokens.Themes.midnightKey", + "name" : "midnight\/key", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#1D2440" + }, + { + "codeSyntax" : "DesignTokens.Themes.midnightKeyModifier", + "name" : "midnight\/key-modifier", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#161B33" + }, + { + "codeSyntax" : "DesignTokens.Themes.midnightLegend", + "name" : "midnight\/legend", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#E8ECFF" + }, + { + "codeSyntax" : "DesignTokens.Themes.midnightPopup", + "name" : "midnight\/popup", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#1D2440" + }, + { + "alias" : "Brand:green\/400", + "codeSyntax" : "DesignTokens.Themes.midnightSignal", + "name" : "midnight\/signal", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#67AD82" + }, + { + "codeSyntax" : "DesignTokens.Themes.midnightSurface", + "name" : "midnight\/surface", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#0E1220" + }, + { + "codeSyntax" : "DesignTokens.Themes.mintKey", + "name" : "mint\/key", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#1E3F31" + }, + { + "codeSyntax" : "DesignTokens.Themes.mintKeyModifier", + "name" : "mint\/key-modifier", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#183429" + }, + { + "codeSyntax" : "DesignTokens.Themes.mintLegend", + "name" : "mint\/legend", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#E9F5EE" + }, + { + "codeSyntax" : "DesignTokens.Themes.mintPopup", + "name" : "mint\/popup", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#1E3F31" + }, + { + "alias" : "Brand:green\/400", + "codeSyntax" : "DesignTokens.Themes.mintSignal", + "name" : "mint\/signal", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#67AD82" + }, + { + "codeSyntax" : "DesignTokens.Themes.mintSurface", + "name" : "mint\/surface", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#10231B" + }, + { + "alias" : "Brand:white", + "codeSyntax" : "DesignTokens.Themes.paperKey", + "name" : "paper\/key", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#FFFFFF" + }, + { + "alias" : "Brand:card-border", + "codeSyntax" : "DesignTokens.Themes.paperKeyModifier", + "name" : "paper\/key-modifier", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#DEDBDB" + }, + { + "alias" : "Brand:ink", + "codeSyntax" : "DesignTokens.Themes.paperLegend", + "name" : "paper\/legend", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#1D1B16" + }, + { + "alias" : "Brand:white", + "codeSyntax" : "DesignTokens.Themes.paperPopup", + "name" : "paper\/popup", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#FFFFFF" + }, + { + "alias" : "Brand:green\/700", + "codeSyntax" : "DesignTokens.Themes.paperSignal", + "name" : "paper\/signal", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#01762F" + }, + { + "alias" : "Brand:card", + "codeSyntax" : "DesignTokens.Themes.paperSurface", + "name" : "paper\/surface", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#EBE8E8" + }, + { + "codeSyntax" : "DesignTokens.Themes.sunsetKey", + "name" : "sunset\/key", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#4B2B20" + }, + { + "codeSyntax" : "DesignTokens.Themes.sunsetKeyModifier", + "name" : "sunset\/key-modifier", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#3B2119" + }, + { + "codeSyntax" : "DesignTokens.Themes.sunsetLegend", + "name" : "sunset\/legend", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#FFEFE6" + }, + { + "codeSyntax" : "DesignTokens.Themes.sunsetPopup", + "name" : "sunset\/popup", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#4B2B20" + }, + { + "alias" : "Brand:green\/400", + "codeSyntax" : "DesignTokens.Themes.sunsetSignal", + "name" : "sunset\/signal", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#67AD82" + }, + { + "codeSyntax" : "DesignTokens.Themes.sunsetSurface", + "name" : "sunset\/surface", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#2B1912" + }, + { + "alias" : "Brand:apple\/dark-key", + "codeSyntax" : "DesignTokens.Themes.systemDarkKey", + "name" : "system-dark\/key", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#6B6B6B" + }, + { + "alias" : "Brand:apple\/dark-modifier", + "codeSyntax" : "DesignTokens.Themes.systemDarkKeyModifier", + "name" : "system-dark\/key-modifier", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#464646" + }, + { + "alias" : "Brand:white", + "codeSyntax" : "DesignTokens.Themes.systemDarkLegend", + "name" : "system-dark\/legend", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#FFFFFF" + }, + { + "alias" : "Brand:apple\/dark-key", + "codeSyntax" : "DesignTokens.Themes.systemDarkPopup", + "name" : "system-dark\/popup", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#6B6B6B" + }, + { + "alias" : "Brand:green\/400", + "codeSyntax" : "DesignTokens.Themes.systemDarkSignal", + "name" : "system-dark\/signal", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#67AD82" + }, + { + "alias" : "Brand:apple\/dark-surface", + "codeSyntax" : "DesignTokens.Themes.systemDarkSurface", + "name" : "system-dark\/surface", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#2B2B2B" + }, + { + "alias" : "Brand:white", + "codeSyntax" : "DesignTokens.Themes.systemLightKey", + "name" : "system-light\/key", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#FFFFFF" + }, + { + "alias" : "Brand:apple\/light-modifier", + "codeSyntax" : "DesignTokens.Themes.systemLightKeyModifier", + "name" : "system-light\/key-modifier", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#ADB3BC" + }, + { + "alias" : "Brand:black", + "codeSyntax" : "DesignTokens.Themes.systemLightLegend", + "name" : "system-light\/legend", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#000000" + }, + { + "alias" : "Brand:white", + "codeSyntax" : "DesignTokens.Themes.systemLightPopup", + "name" : "system-light\/popup", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#FFFFFF" + }, + { + "alias" : "Brand:green\/700", + "codeSyntax" : "DesignTokens.Themes.systemLightSignal", + "name" : "system-light\/signal", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#01762F" + }, + { + "alias" : "Brand:apple\/light-surface", + "codeSyntax" : "DesignTokens.Themes.systemLightSurface", + "name" : "system-light\/surface", + "scopes" : [ + + ], + "type" : "COLOR", + "use" : "", + "value" : "#D1D5DB" + } + ] + }, + "Typography" : { + "mode" : "Value", + "variables" : [ + { + "codeSyntax" : "DesignTokens.Typography.ratioOrbGlyph", + "name" : "ratio\/orb-glyph", + "scopes" : [ + + ], + "type" : "FLOAT", + "use" : "the clipboard and exclamation glyphs, as a fraction of the orb", + "value" : 0.34000000000000002 + }, + { + "codeSyntax" : "DesignTokens.Typography.sizeGlyph", + "name" : "size\/glyph", + "scopes" : [ + "FONT_SIZE" + ], + "type" : "FLOAT", + "use" : "the +, × and ✓", + "value" : 17 + }, + { + "codeSyntax" : "DesignTokens.Typography.sizeLegend", + "name" : "size\/legend", + "scopes" : [ + "FONT_SIZE" + ], + "type" : "FLOAT", + "use" : "every other key", + "value" : 16 + }, + { + "codeSyntax" : "DesignTokens.Typography.sizeLetter", + "name" : "size\/letter", + "scopes" : [ + "FONT_SIZE" + ], + "type" : "FLOAT", + "use" : "letter keys", + "value" : 22 + }, + { + "codeSyntax" : "DesignTokens.Typography.sizePopup", + "name" : "size\/popup", + "scopes" : [ + "FONT_SIZE" + ], + "type" : "FLOAT", + "use" : "the letter pop-up", + "value" : 32 + }, + { + "codeSyntax" : "DesignTokens.Typography.sizeTerm", + "name" : "size\/term", + "scopes" : [ + "FONT_SIZE" + ], + "type" : "FLOAT", + "use" : "the key-term field", + "value" : 17 + }, + { + "codeSyntax" : "DesignTokens.Typography.weightGlyph", + "name" : "weight\/glyph", + "scopes" : [ + "FONT_STYLE" + ], + "type" : "STRING", + "use" : "", + "value" : "medium" + }, + { + "codeSyntax" : "DesignTokens.Typography.weightLegend", + "name" : "weight\/legend", + "scopes" : [ + "FONT_STYLE" + ], + "type" : "STRING", + "use" : "", + "value" : "medium" + }, + { + "codeSyntax" : "DesignTokens.Typography.weightLetter", + "name" : "weight\/letter", + "scopes" : [ + "FONT_STYLE" + ], + "type" : "STRING", + "use" : "", + "value" : "regular" + }, + { + "codeSyntax" : "DesignTokens.Typography.weightOrbGlyph", + "name" : "weight\/orb-glyph", + "scopes" : [ + "FONT_STYLE" + ], + "type" : "STRING", + "use" : "", + "value" : "semibold" + }, + { + "codeSyntax" : "DesignTokens.Typography.weightPopup", + "name" : "weight\/popup", + "scopes" : [ + "FONT_STYLE" + ], + "type" : "STRING", + "use" : "", + "value" : "regular" + }, + { + "codeSyntax" : "DesignTokens.Typography.weightTerm", + "name" : "weight\/term", + "scopes" : [ + "FONT_STYLE" + ], + "type" : "STRING", + "use" : "", + "value" : "regular" + } + ] + } + }, + "gradients" : { + "orb" : { + "end" : "top", + "start" : "bottom", + "stops" : [ + { + "alias" : "Brand:violet\/lavender", + "location" : 0, + "value" : "#D7D3F4" + }, + { + "alias" : "Brand:violet\/periwinkle", + "location" : 0.067299999999999999, + "value" : "#B0A7E9" + }, + { + "alias" : "Brand:green\/400", + "location" : 0.14419999999999999, + "value" : "#67AD82" + }, + { + "alias" : "Brand:green\/700", + "location" : 0.3029, + "value" : "#01762F" + }, + { + "alias" : "Brand:cobolt", + "location" : 0.59619999999999995, + "value" : "#3923C7" + }, + { + "alias" : "Brand:violet\/iris", + "location" : 0.75, + "value" : "#887BDD" + }, + { + "alias" : "Brand:violet\/lavender", + "location" : 0.89419999999999999, + "value" : "#D7D3F4" + }, + { + "alias" : "Brand:white", + "location" : 1, + "value" : "#FFFFFF" + } + ], + "use" : "the Mac orb's fill, the design's own stops (App elements\/Recording.svg), swept bottom to top" + }, + "orb-ring" : { + "end" : "bottomTrailing", + "start" : "topLeading", + "stops" : [ + { + "alias" : "Brand:green\/700", + "location" : 0, + "value" : "#01762F" + }, + { + "alias" : "Brand:white", + "location" : 1, + "value" : "#FFFFFF" + } + ], + "use" : "the ring round the orb: green into white, corner to corner; spun while something is happening" + } + }, + "groups" : [ + "Brand", + "Themes", + "Keyboard", + "Metrics", + "Typography", + "Motion" + ] +}; diff --git a/scripts/design-sync.sh b/scripts/design-sync.sh index 3d25ca40..569390df 100755 --- a/scripts/design-sync.sh +++ b/scripts/design-sync.sh @@ -41,6 +41,7 @@ OUTPUTS=( App/BlurtiOS/BlurtiOS/Assets.xcassets/AccentColor.colorset/Contents.json App/BlurtiOS/BlurtiOS/Assets.xcassets/CardFill.colorset/Contents.json App/BlurtiOS/BlurtiOS/Assets.xcassets/CardBorder.colorset/Contents.json + App/BlurtiOS/Design/figma/tokens.js ) # Format the generated files the way check.sh expects the tree to be formatted, @@ -95,10 +96,23 @@ print(f"design-sync: no design literals in {len(files)} view files") PY } +# The Figma development-plugin bundle: the same scripts a use_figma call +# carries, concatenated behind a manifest, for running from Figma desktop +# without the MCP read quota (Design/figma/README.md). +bundle_plugin() { + local dir="$REPO_ROOT/.build/figma-plugin" + mkdir -p "$dir" + cp App/BlurtiOS/Design/figma/manifest.json "$dir/manifest.json" + cat App/BlurtiOS/Design/figma/tokens.js App/BlurtiOS/Design/figma/lib.js App/BlurtiOS/Design/figma/plugin.js \ + >"$dir/code.js" + echo "design-sync: Figma plugin bundled at $dir (Plugins → Development → Import plugin from manifest)" +} + if [ "$CHECK" -eq 0 ]; then swift scripts/design-tokens.swift format_outputs "$REPO_ROOT" lint_literals + bundle_plugin exit 0 fi diff --git a/scripts/design-tokens.swift b/scripts/design-tokens.swift index 5b175975..202fa342 100755 --- a/scripts/design-tokens.swift +++ b/scripts/design-tokens.swift @@ -1,6 +1,4 @@ -#!/usr/bin/env swift // The design's one source of numbers and colours, fanned out: reads -// App/BlurtiOS/Design/tokens.json (exported from the Figma file, hand-written -// before it existed) and writes everything that used to repeat those values by +#!/usr/bin/env swift // The design's one source of numbers and colours, fanned out: reads // App/BlurtiOS/Design/tokens.json (exported from the Figma file, hand-written // before it existed) and writes everything that used to repeat those values by // hand — `App/BlurtiOS/Shared/DesignTokens.swift`, the generated tables in // `App/BlurtiOS/DESIGN.md`, and the app's three asset-catalog colour sets. Run // through scripts/design-sync.sh, which also formats the output and, with @@ -42,6 +40,7 @@ let tokensPath = "App/BlurtiOS/Design/tokens.json" let swiftPath = "App/BlurtiOS/Shared/DesignTokens.swift" let designPath = "App/BlurtiOS/DESIGN.md" let catalogPath = "App/BlurtiOS/BlurtiOS/Assets.xcassets" +let figmaTokensPath = "App/BlurtiOS/Design/figma/tokens.js" func fail(_ message: String) -> Never { FileHandle.standardError.write(Data("design-tokens: \(message)\n".utf8)) @@ -412,6 +411,103 @@ let colorSets: [(String, String, String)] = [ ("CardBorder", "keyboard.app/card-border-light", "keyboard.app/card-border-dark"), ] +// MARK: - Figma + +/// What the Figma build scripts (Design/figma/lib.js) need: every token with +/// its resolved value, its alias if any, the scopes its collection gives it and +/// the iOS code syntax that is its Swift name. Scopes follow the token's role +/// by name, which is the one place that rule is written down. +func figmaScopes(_ token: Token) -> [String] { + let name = token.name + switch token.group { + case "brand", "themes", "motion": return [] + case "keyboard": + if name.hasSuffix("legend") || name.hasSuffix("full-access-note") { return ["TEXT_FILL"] } + if name.contains("notice-") || name.contains("orb-ring-") || name.contains("card-border") { + return ["STROKE_COLOR"] + } + if name.hasSuffix("signal") { return ["SHAPE_FILL", "TEXT_FILL"] } + return ["FRAME_FILL", "SHAPE_FILL"] + case "metrics": + if name.hasPrefix("opacity/") { return ["OPACITY"] } + if name.hasSuffix("/radius") { return ["CORNER_RADIUS"] } + if name.hasSuffix("/gap") || name.hasSuffix("/spacing") || name.hasSuffix("/pad") || name.hasSuffix("/inset") + || name.hasSuffix("/lead") || name.hasSuffix("-gap") || name.hasSuffix("-clearance") + { + return ["GAP"] + } + if name.hasPrefix("ring/") || name == "card/border" || name == "caret/width" || name == "wave/bar" { + return ["STROKE_FLOAT", "WIDTH_HEIGHT"] + } + if name.hasPrefix("press/") || name.hasPrefix("gesture/") || name.contains("factor") || name.contains("light-") + || name.contains("dissipate") || name == "picker/scale" + { + return [] + } + return ["WIDTH_HEIGHT"] + case "type": + if name.hasPrefix("size/") { return ["FONT_SIZE"] } + if name.hasPrefix("weight/") { return ["FONT_STYLE"] } + return [] + default: return [] + } +} + +func figmaJSON() -> String { + var collections: [String: Any] = [:] + for group in groups { + let variables: [[String: Any]] = tokens.filter { $0.group == group }.map { token in + var entry: [String: Any] = [ + "name": token.name, + "codeSyntax": "DesignTokens.\(typeName(group)).\(token.swiftName)", + "scopes": figmaScopes(token), + "use": token.use ?? "", + ] + switch resolve(token).value { + case .color(let hex): + entry["type"] = "COLOR" + entry["value"] = hex + case .number(let number): + entry["type"] = "FLOAT" + entry["value"] = number + case .word(let word): + entry["type"] = "STRING" + entry["value"] = word + case .alias: fatalError("unreachable") + } + if case .alias(let target) = token.value, let other = byQualified[target] { + entry["alias"] = "\(typeName(other.group)):\(other.name)" + } + return entry + } + collections[typeName(group)] = ["mode": "Value", "variables": variables] + } + var gradientEntries: [String: Any] = [:] + for gradient in gradients { + gradientEntries[gradient.name] = [ + "start": gradient.start, "end": gradient.end, "use": gradient.use ?? "", + "stops": gradient.stops.map { stop -> [String: Any] in + var entry: [String: Any] = ["location": stop.location, "value": resolveColor(stop.color)] + if case .alias(let target) = parseValue(stop.color), let other = byQualified[target] { + entry["alias"] = "\(typeName(other.group)):\(other.name)" + } + return entry + }, + ] + } + let root: [String: Any] = ["collections": collections, "gradients": gradientEntries, "groups": groups.map(typeName)] + guard let data = try? JSONSerialization.data(withJSONObject: root, options: [.prettyPrinted, .sortedKeys]), + let text = String(data: data, encoding: .utf8) + else { fail("could not encode the Figma token data") } + return """ + // Generated by scripts/design-tokens.swift from App/BlurtiOS/Design/tokens.json — do not edit. + // The build scripts in this folder (lib.js) read this; a use_figma call is + // tokens.js + lib.js + one line that returns a builder's result. + const TOKENS = \(text); + + """ +} + // MARK: - Write func write(_ text: String, to relative: String) { @@ -426,6 +522,7 @@ func write(_ text: String, to relative: String) { write(swift, to: swiftPath) write(design, to: designPath) +write(figmaJSON(), to: figmaTokensPath) for (set, light, dark) in colorSets { guard let lightToken = byQualified[light], let darkToken = byQualified[dark] else { fail("\(set) needs \(light) and \(dark)") @@ -434,5 +531,5 @@ for (set, light, dark) in colorSets { catalog(light: rendered(lightToken), dark: rendered(darkToken)), to: "\(catalogPath)/\(set).colorset/Contents.json") } print( - "design-tokens: \(tokens.count) tokens, \(gradients.count) gradients → \(swiftPath), \(designPath) (\(replaced.count) blocks), \(colorSets.count) colour sets" -) + "design-tokens: \(tokens.count) tokens, \(gradients.count) gradients → \(swiftPath), \(designPath) " + + "(\(replaced.count) blocks), \(colorSets.count) colour sets, \(figmaTokensPath)") From c6bb50f9dddc8cafb7eaaf7838e26b44454230b7 Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Tue, 29 Sep 2026 11:29:01 -0400 Subject: [PATCH 47/79] Design/figma: split the builders per call, carry tokens once, plugin bundle One use_figma call is capped at 50,000 characters, so lib.js becomes core.js plus a module per builder, tokens.js is one flat line per variable that only the foundations call carries, and every later builder reads the values back from the file's variables and the Gradient/* paint styles. design-sync.sh bundles the plugin; scripts/design-figma-call.sh assembles a call. First run against a live draft: foundations (190 variables) and the ten component sets landed; the View seat's tool-call cap hit before the layouts, and labels are written on the instance's text node since setProperties refuses the local SF Pro. README records both. Co-Authored-By: Claude Fable 5.1 --- App/BlurtiOS/Design/figma/README.md | 16 + App/BlurtiOS/Design/figma/components.js | 510 +++++ App/BlurtiOS/Design/figma/core.js | 244 +++ App/BlurtiOS/Design/figma/exports.js | 55 + App/BlurtiOS/Design/figma/foundations.js | 189 ++ App/BlurtiOS/Design/figma/layouts.js | 222 +++ App/BlurtiOS/Design/figma/lib.js | 1187 ----------- App/BlurtiOS/Design/figma/themes.js | 73 + App/BlurtiOS/Design/figma/tokens.js | 2267 ++-------------------- scripts/design-figma-call.sh | 49 + scripts/design-sync.sh | 6 +- scripts/design-tokens.swift | 80 +- 12 files changed, 1597 insertions(+), 3301 deletions(-) create mode 100644 App/BlurtiOS/Design/figma/components.js create mode 100644 App/BlurtiOS/Design/figma/core.js create mode 100644 App/BlurtiOS/Design/figma/exports.js create mode 100644 App/BlurtiOS/Design/figma/foundations.js create mode 100644 App/BlurtiOS/Design/figma/layouts.js delete mode 100644 App/BlurtiOS/Design/figma/lib.js create mode 100644 App/BlurtiOS/Design/figma/themes.js create mode 100755 scripts/design-figma-call.sh diff --git a/App/BlurtiOS/Design/figma/README.md b/App/BlurtiOS/Design/figma/README.md index c38546a6..d063441c 100644 --- a/App/BlurtiOS/Design/figma/README.md +++ b/App/BlurtiOS/Design/figma/README.md @@ -32,6 +32,22 @@ writes `.build/figma-plugin/{manifest.json,code.js}`; in Figma desktop, Plugins → Development → Import plugin from manifest…, then run the menu items in order. Results print to the plugin console (Plugins → Development → Open console). +## What the first run taught (2026-09-29) + +- The AssemblyAI View seat **can** write to a draft Neil created, and SF Pro + and the SF Symbol helper are there. It cannot do it for long: after roughly a + dozen `use_figma` calls Figma returned "You've reached the Figma MCP tool call + limit for your View seat on the Organization plan". Writes count. Foundations + and components landed before the cap; layouts did not. Either run the rest as + the development plugin (no quota) or re-authenticate the connector to a + personal Figma account. +- Under the MCP runtime every SF Pro text node reports `hasMissingFont`, and + `setProperties` on a TEXT property then refuses with "the component uses a + font that isn't available", while writing `characters` on the instance's text + node works. The layout builders write labels that way (`setLabel`). +- `componentPropertyDefinitions` must be read on the component **set**, never + on a variant. + ## Order 1. `buildFoundations` — the six one-mode collections (`Brand`, `Themes`, diff --git a/App/BlurtiOS/Design/figma/components.js b/App/BlurtiOS/Design/figma/components.js new file mode 100644 index 00000000..b31a2c97 --- /dev/null +++ b/App/BlurtiOS/Design/figma/components.js @@ -0,0 +1,510 @@ +/* global figma, getPage, variableMap, ensureTokens, loadFonts, FONT, metric, token, autoLayout, textNode, paint, bind, bindRadius, gradientPaint, symbolChar, DEVICE_WIDTH, VARS */ +// --------------------------------------------------------------------------- +// Components (02 Components). Every fill, stroke, radius and gap is bound to a +// variable; the orb's disc is the one image fill (see buildOrbDisc). + +const SIZES = { Bar: "orb/bar", Panel: "orb/panel", Home: "orb/home" }; +const WAVES = { + Bar: ["wave/bar-width", "wave/bar-height"], + Panel: ["wave/panel-width", "wave/panel-height"], + Home: ["wave/home-width", "wave/home-height"], +}; + +async function findComponentSet(page, name) { + return page.findOne((n) => n.type === "COMPONENT_SET" && n.name === name); +} + +async function findComponent(page, name) { + return page.findOne((n) => n.type === "COMPONENT" && n.name === name && n.parent.type !== "COMPONENT_SET"); +} + +async function textStyleId(name) { + const s = (await figma.getLocalTextStylesAsync()).find((x) => x.name === name); + if (!s) throw new Error(`text style ${name} missing — run buildFoundations first`); + return s.id; +} + +async function effectStyleId(name) { + const s = (await figma.getLocalEffectStylesAsync()).find((x) => x.name === name); + if (!s) throw new Error(`effect style ${name} missing — run buildFoundations first`); + return s.id; +} + +/** Replaces a component set (or lone component) of this name, keeping its position. */ +function replaceNamed(page, name, node) { + const old = page.findOne((n) => (n.type === "COMPONENT_SET" || n.type === "COMPONENT") && n.name === name); + if (old) { + node.x = old.x; + node.y = old.y; + old.remove(); + } +} + +/** Lays the variants of a set out in a row and names the set. */ +function finishSet(page, name, variants, x, y) { + const set = figma.combineAsVariants(variants, page); + set.name = name; + set.layoutMode = "HORIZONTAL"; + set.itemSpacing = 24; + set.paddingLeft = set.paddingRight = set.paddingTop = set.paddingBottom = 24; + set.primaryAxisSizingMode = "AUTO"; + set.counterAxisSizingMode = "AUTO"; + set.counterAxisAlignItems = "MIN"; + set.x = x; + set.y = y; + return set; +} + +async function keyCap(props) { + // props: tone "Key"|"Modifier"|"Bare", pressed, label, width (fixed) or null (min width + pad) + const c = figma.createComponent(); + c.name = `Tone=${props.tone}, State=${props.pressed ? "Pressed" : "Up"}`; + c.layoutMode = "HORIZONTAL"; + c.primaryAxisAlignItems = "CENTER"; + c.counterAxisAlignItems = "CENTER"; + c.primaryAxisSizingMode = props.width ? "FIXED" : "AUTO"; + c.counterAxisSizingMode = "FIXED"; + c.resize(props.width || metric("key/min-width"), metric("key/height")); + await bind(c, "height", "Metrics:key/height"); + if (props.width) await bind(c, "width", `Metrics:${props.widthRef}`); + else { + await bind(c, "minWidth", "Metrics:key/min-width"); + await bind(c, "paddingLeft", "Metrics:key/pad"); + await bind(c, "paddingRight", "Metrics:key/pad"); + } + c.fills = props.tone === "Bare" ? [] : [await paint(props.tone === "Modifier" ? "Keyboard:kb/key-modifier" : "Keyboard:kb/key")]; + await bindRadius(c, "Metrics:key/radius"); + const label = await textNode(props.label, { + styleId: await textStyleId(props.letter ? "Key/Letter" : "Key/Legend"), + fillRef: props.tint || "Keyboard:kb/legend", + }); + label.name = "Label"; + c.appendChild(label); + if (props.pressed) { + const shine = figma.createRectangle(); + shine.name = "Pressed"; + shine.fills = [{ type: "SOLID", color: { r: 1, g: 1, b: 1 } }]; + await bind(shine, "opacity", "Metrics:opacity/press-brighten"); + c.appendChild(shine); + shine.layoutPositioning = "ABSOLUTE"; + shine.x = 0; + shine.y = 0; + shine.resize(c.width, c.height); + shine.constraints = { horizontal: "STRETCH", vertical: "STRETCH" }; + await bindRadius(shine, "Metrics:key/radius"); + } + return c; +} + +async function buildKeySet(page, x, y) { + const variants = []; + for (const tone of ["Key", "Modifier", "Bare"]) { + for (const pressed of [false, true]) { + variants.push(await keyCap({ tone, pressed, label: tone === "Bare" ? "×" : "space" })); + } + } + replaceNamed(page, "Key", variants[0]); + const set = finishSet(page, "Key", variants, x, y); + set.description = "One ordinary key: a legend on a cap in the current palette; Modifier a step darker; Bare a glyph with no cap. Flat: no drop, no edge, no gloss."; + const labelProp = set.addComponentProperty("Label", "TEXT", "space"); + for (const v of variants) { + const t = v.findOne((n) => n.type === "TEXT" && n.name === "Label"); + t.componentPropertyReferences = { characters: labelProp }; + } + return set; +} + +async function buildLetterKeySet(page, x, y) { + const variants = []; + for (const pressed of [false, true]) { + const c = await keyCap({ + tone: "Key", + pressed, + label: "q", + letter: true, + width: metric("key/letter-width-402"), + widthRef: "key/letter-width-402", + }); + c.name = `State=${pressed ? "Pressed" : "Up"}`; + if (pressed) { + const popup = figma.createFrame(); + popup.name = "LetterPopup"; + popup.layoutMode = "HORIZONTAL"; + popup.primaryAxisAlignItems = "CENTER"; + popup.counterAxisAlignItems = "CENTER"; + popup.primaryAxisSizingMode = "FIXED"; + popup.counterAxisSizingMode = "FIXED"; + popup.resize(metric("key/letter-width-402") + metric("popup/extra-width"), metric("popup/height")); + await bind(popup, "height", "Metrics:popup/height"); + popup.fills = [await paint("Keyboard:kb/popup")]; + await bindRadius(popup, "Metrics:popup/radius"); + popup.effectStyleId = await effectStyleId("Shadow/Popup"); + const big = await textNode("q", { styleId: await textStyleId("Key/Popup"), fillRef: "Keyboard:kb/legend" }); + big.name = "Popup label"; + popup.appendChild(big); + c.appendChild(popup); + popup.layoutPositioning = "ABSOLUTE"; + popup.x = -metric("popup/extra-width") / 2; + popup.y = -metric("popup/offset"); + } + variants.push(c); + } + replaceNamed(page, "LetterKey", variants[0]); + const set = finishSet(page, "LetterKey", variants, x, y); + set.description = "A letter key with the system keyboard's 22 pt legend and its pop-up while pressed: a 32 pt copy above the key, the one thing that floats."; + const labelProp = set.addComponentProperty("Label", "TEXT", "q"); + for (const v of variants) { + for (const t of v.findAll((n) => n.type === "TEXT")) t.componentPropertyReferences = { characters: labelProp }; + } + return set; +} + +async function glyphButton(name, symbol, fallback, fillRef, opacityRef) { + const c = figma.createComponent(); + c.name = name; + c.layoutMode = "HORIZONTAL"; + c.primaryAxisAlignItems = "CENTER"; + c.counterAxisAlignItems = "CENTER"; + c.primaryAxisSizingMode = "FIXED"; + c.counterAxisSizingMode = "FIXED"; + c.resize(metric("glyph/hit"), metric("glyph/hit")); + await bind(c, "width", "Metrics:glyph/hit"); + await bind(c, "height", "Metrics:glyph/hit"); + const t = await textNode(symbolChar(symbol, fallback), { styleId: await textStyleId("Glyph"), fillRef }); + t.name = "Glyph"; + if (opacityRef) await bind(t, "opacity", opacityRef); + c.appendChild(t); + return c; +} + +async function buildAddTermKey(page, x, y) { + const off = await glyphButton("Saved=False", "plus", "+", "Keyboard:kb/legend", "Metrics:opacity/legend-muted"); + const on = await glyphButton("Saved=True", "checkmark", "✓", "Keyboard:kb/signal", null); + replaceNamed(page, "AddTermKey", off); + const set = finishSet(page, "AddTermKey", [off, on], x, y); + set.description = "The small + beside the orb: a new key term. A bare glyph, quiet until needed; a check for a moment after one was saved."; + return set; +} + +async function buildCancelKey(page, x, y) { + const c = await keyCap({ tone: "Bare", pressed: false, label: symbolChar("xmark", "×"), tint: "Keyboard:kb/cancel" }); + c.name = "CancelKey"; + c.description = "Cancel, in the panel's top-right corner while something is in flight: the orange × on no cap."; + replaceNamed(page, "CancelKey", c); + page.appendChild(c); + c.x = x; + c.y = y; + return c; +} + +async function buildTermField(page, x, y) { + const c = figma.createComponent(); + c.name = "TermField"; + c.description = "The voice bar as a field: × to leave, what has been typed with a caret, ✓ to save."; + c.layoutMode = "HORIZONTAL"; + c.counterAxisAlignItems = "CENTER"; + c.primaryAxisSizingMode = "FIXED"; + c.counterAxisSizingMode = "FIXED"; + c.resize(DEVICE_WIDTH - 2 * metric("margin/side"), metric("voicebar/height")); + await bind(c, "height", "Metrics:voicebar/height"); + await bind(c, "itemSpacing", "Metrics:term/gap"); + await bind(c, "paddingLeft", "Metrics:term/inset"); + await bind(c, "paddingRight", "Metrics:term/inset"); + const cancel = await glyphButton("Cancel", "xmark", "×", "Keyboard:kb/legend", "Metrics:opacity/term-cancel"); + cancel.name = "Cancel"; + const cancelInstance = cancel.createInstance(); + cancel.remove(); + c.appendChild(cancelInstance); + const field = figma.createFrame(); + field.name = "Field"; + field.layoutMode = "HORIZONTAL"; + field.counterAxisAlignItems = "CENTER"; + field.primaryAxisSizingMode = "FIXED"; + field.counterAxisSizingMode = "FIXED"; + field.resize(100, metric("term/height")); + await bind(field, "height", "Metrics:term/height"); + await bind(field, "paddingLeft", "Metrics:term/pad"); + await bind(field, "paddingRight", "Metrics:term/pad"); + field.fills = [await paint("Keyboard:kb/key-modifier")]; + field.cornerRadius = metric("term/height") / 2; // a capsule: half the height + const draft = await textNode("Rizz", { styleId: await textStyleId("Term/Text"), fillRef: "Keyboard:kb/legend" }); + draft.name = "Draft"; + field.appendChild(draft); + const caret = figma.createRectangle(); + caret.name = "Caret"; + caret.resize(metric("caret/width"), metric("caret/height")); + await bind(caret, "width", "Metrics:caret/width"); + await bind(caret, "height", "Metrics:caret/height"); + await bindRadius(caret, "Metrics:caret/radius"); + caret.fills = [await paint("Keyboard:kb/signal")]; + field.appendChild(caret); + c.appendChild(field); + field.layoutSizingHorizontal = "FILL"; + const save = await glyphButton("Save", "checkmark", "✓", "Keyboard:kb/signal", null); + const saveInstance = save.createInstance(); + save.remove(); + c.appendChild(saveInstance); + const draftProp = c.addComponentProperty("Draft", "TEXT", "Rizz"); + draft.componentPropertyReferences = { characters: draftProp }; + replaceNamed(page, "TermField", c); + page.appendChild(c); + c.x = x; + c.y = y; + return c; +} + +async function buildOrbRing(page, x, y) { + const variants = []; + for (const [size, ref] of Object.entries(SIZES)) { + for (const kind of ["Still", "Working", "Ok", "Error"]) { + const c = figma.createComponent(); + c.name = `Kind=${kind}, Size=${size}`; + const d = metric(ref); + c.resize(d, d); + c.fills = []; + const ring = figma.createEllipse(); + ring.name = "Ring"; + ring.resize(d, d); + ring.fills = []; + ring.strokeAlign = "INSIDE"; + if (kind === "Ok" || kind === "Error") { + ring.strokes = [await paint(kind === "Ok" ? "Keyboard:kb/notice-ok" : "Keyboard:kb/notice-error")]; + } else { + ring.strokes = [gradientPaint("orb-ring")]; + } + await bind(ring, "strokeWeight", kind === "Still" ? "Metrics:ring/still" : "Metrics:ring/active"); + c.appendChild(ring); + await bind(c, "width", `Metrics:${ref}`); + await bind(c, "height", `Metrics:${ref}`); + variants.push(c); + } + } + replaceNamed(page, "Orb/Ring", variants[0]); + const set = finishSet(page, "Orb/Ring", variants, x, y); + set.description = "The hairline ring round the orb: green into white, 1 pt at rest and 2 pt while working (it sweeps one turn per 1.6 s); solid green for pasted and copied, orange for an error."; + return set; +} + +/** An orb still the app rendered, if one has been placed in the file. */ +function orbStill(page, size, mood) { + const node = page.findOne((n) => n.name === `orb-still/${size}-${mood}`.toLowerCase()); + if (!node || !("fills" in node)) return null; + const fill = node.fills.find((f) => f.type === "IMAGE"); + return fill ? fill.imageHash : null; +} + +async function buildOrbDisc(page, x, y) { + const variants = []; + let images = 0; + for (const [size, ref] of Object.entries(SIZES)) { + for (const mood of ["Off", "Idle", "Listening", "Working", "Landed"]) { + const c = figma.createComponent(); + c.name = `Size=${size}, Mood=${mood}`; + const d = metric(ref); + c.resize(d, d); + c.fills = []; + const disc = figma.createEllipse(); + disc.name = "Disc"; + disc.resize(d, d); + const hash = orbStill(page, size, mood === "Off" ? "Idle" : mood); + if (hash) { + disc.fills = [{ type: "IMAGE", imageHash: hash, scaleMode: "FILL" }]; + images += 1; + } else { + disc.fills = [gradientPaint("orb")]; + } + if (mood === "Off") { + await bind(disc, "opacity", "Metrics:opacity/dim"); + } + c.appendChild(disc); + await bind(c, "width", `Metrics:${ref}`); + await bind(c, "height", `Metrics:${ref}`); + variants.push(c); + } + } + replaceNamed(page, "Orb/Disc", variants[0]); + const set = finishSet(page, "Orb/Disc", variants, x, y); + set.description = + "The orb's fill. A still the app renders (-BlurtOrb , placed here as orb-still/-); the brand gradient stands in until one is. Off is Idle dimmed."; + return { set, images }; +} + +async function buildWaveformMeter(page, x, y) { + const variants = []; + for (const [size, [wRef, hRef]] of Object.entries(WAVES)) { + const c = figma.createComponent(); + c.name = `Size=${size}`; + const w = metric(wRef); + const h = metric(hRef); + c.resize(w, h); + c.fills = []; + c.layoutMode = "HORIZONTAL"; + c.primaryAxisAlignItems = "CENTER"; + c.counterAxisAlignItems = "CENTER"; + c.primaryAxisSizingMode = "FIXED"; + c.counterAxisSizingMode = "FIXED"; + await bind(c, "itemSpacing", "Metrics:wave/gap"); + await bind(c, "width", `Metrics:${wRef}`); + await bind(c, "height", `Metrics:${hRef}`); + const bar = metric("wave/bar"); + const gap = metric("wave/gap"); + const count = Math.floor((w + gap) / (bar + gap)); + const level = 0.62; + for (let i = 0; i < count; i += 1) { + const t = i / Math.max(count - 1, 1); + // A schematic of the engine's envelope: a soft hump, minimum 12 %, at the gallery's level. + const envelope = 0.12 + 0.88 * level * Math.pow(Math.sin(Math.PI * t), 0.45); + const capsule = figma.createRectangle(); + capsule.name = "Bar"; + capsule.resize(bar, Math.max(bar, h * envelope)); + capsule.cornerRadius = bar / 2; + await bind(capsule, "width", "Metrics:wave/bar"); + capsule.fills = [await paint("Keyboard:kb/signal")]; + c.appendChild(capsule); + } + variants.push(c); + } + replaceNamed(page, "WaveformMeter", variants[0]); + const set = finishSet(page, "WaveformMeter", variants, x, y); + set.description = + "The thin wave: 2 pt bars 2 pt apart, flat on the surface, no container. Heights are the engine's (MeterBarGeometry); this is the schematic at level 0.62 — fidelity frames use app captures."; + return set; +} + +const MIC_STATES = ["Off", "Idle", "Working", "Recording", "Pasted", "Copied", "Error"]; + +async function buildMicKey(page, x, y) { + const disc = await findComponentSet(page, "Orb/Disc"); + const ring = await findComponentSet(page, "Orb/Ring"); + const meter = await findComponentSet(page, "WaveformMeter"); + if (!disc || !ring || !meter) throw new Error("build Orb/Disc, Orb/Ring and WaveformMeter first"); + const pick = (set, props) => + set.children.find((c) => Object.entries(props).every(([k, v]) => c.name.includes(`${k}=${v}`))); + const variants = []; + for (const [size, ref] of Object.entries(SIZES)) { + for (const state of MIC_STATES) { + const c = figma.createComponent(); + c.name = `Size=${size}, State=${state}`; + const d = metric(ref); + const [wRef] = WAVES[size]; + c.resize(Math.max(metric(wRef), d), d); + c.fills = []; + c.layoutMode = "HORIZONTAL"; + c.primaryAxisAlignItems = "CENTER"; + c.counterAxisAlignItems = "CENTER"; + c.primaryAxisSizingMode = "FIXED"; + c.counterAxisSizingMode = "FIXED"; + await bind(c, "height", `Metrics:${ref}`); + if (state === "Recording") { + c.appendChild(pick(meter, { Size: size }).createInstance()); + } else { + const stack = figma.createFrame(); + stack.name = "Orb"; + stack.resize(d, d); + stack.fills = []; + stack.clipsContent = false; + const mood = { Off: "Off", Idle: "Idle", Working: "Working", Pasted: "Landed", Copied: "Idle", Error: "Idle" }[state]; + const kind = { Off: "Still", Idle: "Still", Working: "Working", Pasted: "Ok", Copied: "Ok", Error: "Error" }[state]; + const discInstance = pick(disc, { Size: size, Mood: mood }).createInstance(); + discInstance.name = "Disc"; + stack.appendChild(discInstance); + const ringInstance = pick(ring, { Size: size, Kind: kind }).createInstance(); + ringInstance.name = "Ring"; + stack.appendChild(ringInstance); + if (state === "Copied" || state === "Error") { + const glyph = await textNode( + state === "Copied" ? symbolChar("doc.on.clipboard", "⎘") : symbolChar("exclamationmark", "!"), + { size: d * token("Typography", "ratio/orb-glyph").value, weight: FONT.semibold } + ); + glyph.name = "Glyph"; + glyph.fills = [{ type: "SOLID", color: { r: 1, g: 1, b: 1 } }]; + stack.appendChild(glyph); + glyph.x = (d - glyph.width) / 2; + glyph.y = (d - glyph.height) / 2; + } + if (state === "Off") await bind(stack, "opacity", "Metrics:opacity/dim"); + c.appendChild(stack); + } + variants.push(c); + } + } + replaceNamed(page, "MicKey", variants[0]); + const set = finishSet(page, "MicKey", variants, x, y); + set.description = + "The mic key is the orb, and it says everything without a word: dimmed when Blurt isn't ready; ring sweeping while connecting and transcribing; dissipated into the wave while recording; a green ring when the words landed (with the drop), a clipboard on green when they went to the clipboard, orange and ! for an error."; + return set; +} + +async function buildVoiceBar(page, x, y) { + const mic = await findComponentSet(page, "MicKey"); + const addTerm = await findComponentSet(page, "AddTermKey"); + const termField = await findComponent(page, "TermField"); + if (!mic || !addTerm || !termField) throw new Error("build MicKey, AddTermKey and TermField first"); + const pick = (set, props) => + set.children.find((c) => Object.entries(props).every(([k, v]) => c.name.includes(`${k}=${v}`))); + const variants = []; + for (const mode of ["Orb", "Wave", "Term", "NoFullAccess"]) { + const c = figma.createComponent(); + c.name = `Mode=${mode}`; + c.layoutMode = "HORIZONTAL"; + c.primaryAxisAlignItems = mode === "NoFullAccess" ? "MIN" : "CENTER"; + c.counterAxisAlignItems = "CENTER"; + c.primaryAxisSizingMode = "FIXED"; + c.counterAxisSizingMode = "FIXED"; + c.resize(DEVICE_WIDTH - 2 * metric("margin/side"), metric("voicebar/height")); + await bind(c, "height", "Metrics:voicebar/height"); + c.fills = []; + c.clipsContent = false; + if (mode === "Term") { + const f = termField.createInstance(); + c.appendChild(f); + f.layoutSizingHorizontal = "FILL"; + } else if (mode === "NoFullAccess") { + await bind(c, "itemSpacing", "Metrics:voicebar/note-gap"); + c.appendChild(pick(mic, { Size: "Bar", State: "Off" }).createInstance()); + const note = await textNode("Allow Full Access in Settings → Keyboards", { + size: 13, + fillRef: "Keyboard:kb/full-access-note", + }); + note.name = "Note"; + c.appendChild(note); + } else { + c.appendChild(pick(mic, { Size: "Bar", State: mode === "Wave" ? "Recording" : "Idle" }).createInstance()); + const plus = pick(addTerm, { Saved: "False" }).createInstance(); + c.appendChild(plus); + plus.layoutPositioning = "ABSOLUTE"; + plus.constraints = { horizontal: "MAX", vertical: "CENTER" }; + plus.x = c.width - plus.width; + plus.y = (c.height - plus.height) / 2; + } + variants.push(c); + } + replaceNamed(page, "VoiceBar", variants[0]); + const set = finishSet(page, "VoiceBar", variants, x, y); + set.description = + "The keyboard's voice row, and the only place voice lives: the orb (the mic key) dissipating into the wave while recording; the + for a key term; the field the keys type into; the one line of words, without Full Access."; + return set; +} + +async function buildComponents() { + await ensureTokens(); + const page = await getPage(PAGES.components); + VARS = await variableMap(); + await loadFonts(); + const built = {}; + let y = 0; + const step = 360; + built.key = (await buildKeySet(page, 0, y)).id; + built.letterKey = (await buildLetterKeySet(page, 0, (y += step))).id; + built.addTermKey = (await buildAddTermKey(page, 0, (y += step))).id; + built.cancelKey = (await buildCancelKey(page, 400, y)).id; + built.termField = (await buildTermField(page, 0, (y += step))).id; + built.orbRing = (await buildOrbRing(page, 0, (y += step))).id; + const disc = await buildOrbDisc(page, 0, (y += step)); + built.orbDisc = disc.set.id; + built.orbStillsUsed = disc.images; + built.waveformMeter = (await buildWaveformMeter(page, 0, (y += step))).id; + built.micKey = (await buildMicKey(page, 0, (y += step))).id; + built.voiceBar = (await buildVoiceBar(page, 0, (y += step))).id; + return { page: page.id, built }; +} diff --git a/App/BlurtiOS/Design/figma/core.js b/App/BlurtiOS/Design/figma/core.js new file mode 100644 index 00000000..af8f6791 --- /dev/null +++ b/App/BlurtiOS/Design/figma/core.js @@ -0,0 +1,244 @@ +// The Blurt Keyboard Figma file, built from the tokens. core.js: names and helpers every module needs. Plain Plugin API, so +// the same functions run two ways (README.md): pasted into a use_figma call +// behind tokens.js with `return await buildFoundations();`, or bundled by +// scripts/design-sync.sh into a development plugin (plugin.js dispatches). +// Everything is idempotent — find by name before create — and every builder +// returns the ids and counts it touched. No `figma.notify`, no console output. +/* global figma, TOKEN_LINES, GROUPS */ + +// --------------------------------------------------------------------------- +// Names + +const PAGES = { foundations: "01 Foundations", components: "02 Components", layouts: "03 Layouts" }; +const FONT = { family: "SF Pro", regular: "Regular", medium: "Medium", semibold: "Semibold" }; +const DEVICE_WIDTH = 402; // iPhone 18 Pro, the simulator this repo captures on +const DESIGN_THEME = "ink"; +const THEMES = ["system-light", "system-dark", "ink", "paper", "lavender", "mint", "midnight", "sunset"]; +const ROLES = ["surface", "key", "key-modifier", "legend", "signal", "popup"]; +const STATES = ["off", "start", "idle", "connecting", "recording", "processing", "pasted", "copied", "error", "term"]; + +// --------------------------------------------------------------------------- +// The tokens. buildFoundations carries them (tokens.js, one line per variable); +// every later builder reads them back from the file's variables, so a call +// stays under use_figma's 50,000-character cap. + +function parseTokenLines(text) { + const collections = {}; + const gradients = {}; + for (const line of text.split("\n")) { + if (!line) continue; + const parts = line.split("|"); + if (parts[0] === "GRADIENT") { + const [, name, start, end, stops, use] = parts; + gradients[name] = { + start, + end, + use, + stops: stops.split(",").map((s) => { + const [value, location] = s.split("@"); + return { value, location: Number(location) }; + }), + }; + continue; + } + const [collection, name, type, raw, alias, scopes, codeSyntax, use] = parts; + if (!collections[collection]) collections[collection] = { mode: "Value", variables: [] }; + collections[collection].variables.push({ + name, + type, + value: type === "FLOAT" ? Number(raw) : raw, + alias: alias || null, + scopes: scopes ? scopes.split(",") : [], + codeSyntax, + use, + }); + } + return { collections, gradients, groups: typeof GROUPS !== "undefined" ? GROUPS : Object.keys(collections) }; +} + +let TOKENS = typeof TOKEN_LINES !== "undefined" ? parseTokenLines(TOKEN_LINES) : null; +const GRADIENT_STYLES = {}; + +function rgbToHex(c) { + return "#" + [c.r, c.g, c.b].map((x) => Math.round(x * 255).toString(16).padStart(2, "0").toUpperCase()).join(""); +} + +/** Loads TOKENS from the file's variables and gradient paint styles when the call carried none. */ +async function ensureTokens() { + const styles = await figma.getLocalPaintStylesAsync(); + for (const s of styles) if (s.name.startsWith("Gradient/")) GRADIENT_STYLES[s.name.slice(9)] = s.paints[0]; + if (TOKENS) return TOKENS; + const map = await variableMap(); + if (map.size === 0) throw new Error("the file has no variables yet — run buildFoundations first"); + const collectionsById = new Map((await figma.variables.getLocalVariableCollectionsAsync()).map((c) => [c.id, c])); + const byId = new Map([...map.values()].map((v) => [v.id, v])); + function resolveValue(v, depth) { + const c = collectionsById.get(v.variableCollectionId); + const raw = v.valuesByMode[c.modes[0].modeId]; + if (raw && typeof raw === "object" && raw.type === "VARIABLE_ALIAS") { + const target = byId.get(raw.id); + return target && depth < 8 ? resolveValue(target, depth + 1) : null; + } + return raw; + } + const collections = {}; + for (const [key, v] of map) { + const i = key.indexOf(":"); + const collection = key.slice(0, i); + const name = key.slice(i + 1); + const raw = resolveValue(v, 0); + const value = v.resolvedType === "COLOR" && raw ? rgbToHex(raw) : raw; + if (!collections[collection]) collections[collection] = { mode: "Value", variables: [] }; + collections[collection].variables.push({ name, type: v.resolvedType, value, alias: null, scopes: v.scopes, use: v.description }); + } + TOKENS = { collections, gradients: {}, groups: Object.keys(collections) }; + return TOKENS; +} + +// --------------------------------------------------------------------------- +// Helpers + +function hexToRGB(hex) { + const n = parseInt(hex.slice(1), 16); + return { r: ((n >> 16) & 255) / 255, g: ((n >> 8) & 255) / 255, b: (n & 255) / 255 }; +} + +function token(collection, name) { + const entry = TOKENS.collections[collection].variables.find((v) => v.name === name); + if (!entry) throw new Error(`no token ${collection}:${name}`); + return entry; +} + +function metric(name) { + return token("Metrics", name).value; +} + +async function getPage(name) { + let page = figma.root.children.find((p) => p.name === name); + if (!page) { + page = figma.createPage(); + page.name = name; + } + await figma.setCurrentPageAsync(page); + return page; +} + +function getSection(page, name, x, y) { + let section = page.children.find((n) => n.type === "SECTION" && n.name === name); + if (!section) { + section = figma.createSection(); + section.name = name; + section.x = x; + section.y = y; + page.appendChild(section); + } + return section; +} + +/** Every local variable, keyed "Collection:name". */ +async function variableMap() { + const collections = await figma.variables.getLocalVariableCollectionsAsync(); + const byId = new Map(collections.map((c) => [c.id, c])); + const map = new Map(); + for (const v of await figma.variables.getLocalVariablesAsync()) { + const collection = byId.get(v.variableCollectionId); + if (collection) map.set(`${collection.name}:${v.name}`, v); + } + return map; +} + +let VARS = null; +async function vars() { + if (!VARS) VARS = await variableMap(); + return VARS; +} + +async function variable(ref) { + const v = (await vars()).get(ref); + if (!v) throw new Error(`variable ${ref} is not in the file — run buildFoundations first`); + return v; +} + +/** A solid paint bound to a colour variable. */ +async function paint(ref) { + const v = await variable(ref); + return figma.variables.setBoundVariableForPaint({ type: "SOLID", color: { r: 0, g: 0, b: 0 } }, "color", v); +} + +async function bind(node, field, ref) { + node.setBoundVariable(field, await variable(ref)); +} + +async function bindRadius(node, ref) { + for (const corner of ["topLeftRadius", "topRightRadius", "bottomLeftRadius", "bottomRightRadius"]) { + await bind(node, corner, ref); + } +} + +async function loadFonts() { + const available = await figma.listAvailableFontsAsync(); + const families = new Set(available.map((f) => f.fontName.family)); + if (!families.has(FONT.family)) { + throw new Error(`${FONT.family} is not available in this file; install SF Pro from developer.apple.com/fonts`); + } + for (const style of [FONT.regular, FONT.medium, FONT.semibold]) { + await figma.loadFontAsync({ family: FONT.family, style }); + } +} + +/** An SF Symbol as a character where the runtime can (the MCP one), else a stand-in. */ +function symbolChar(name, fallback) { + try { + if (figma.util && typeof figma.util.getSfSymbolCharacter === "function") { + return figma.util.getSfSymbolCharacter(name); + } + } catch (_) { + // fall through to the stand-in + } + return fallback; +} + +async function textNode(characters, { size, weight = FONT.regular, fillRef, styleId } = {}) { + const t = figma.createText(); + t.fontName = { family: FONT.family, style: weight }; + t.characters = characters; + if (size) t.fontSize = size; + if (styleId) t.textStyleId = styleId; + if (fillRef) t.fills = [await paint(fillRef)]; + t.textAutoResize = "WIDTH_AND_HEIGHT"; + return t; +} + +function autoLayout(direction, props = {}) { + const frame = figma.createFrame(); + frame.layoutMode = direction; + frame.primaryAxisSizingMode = "AUTO"; + frame.counterAxisSizingMode = "AUTO"; + frame.fills = []; + frame.clipsContent = false; + Object.assign(frame, props); + return frame; +} + +function gradientPaint(gradientName) { + const g = TOKENS && TOKENS.gradients[gradientName]; + if (!g) { + if (GRADIENT_STYLES[gradientName]) return GRADIENT_STYLES[gradientName]; + throw new Error(`no gradient ${gradientName}: run buildFoundations (it saves Gradient/* paint styles)`); + } + const transforms = { + "bottom>top": [ + [0, -1, 1], + [1, 0, 0], + ], + "topLeading>bottomTrailing": [ + [0.5, 0.5, 0], + [-0.5, 0.5, 0.5], + ], + }; + return { + type: "GRADIENT_LINEAR", + gradientTransform: transforms[`${g.start}>${g.end}`] || transforms["bottom>top"], + gradientStops: g.stops.map((s) => ({ position: s.location, color: { ...hexToRGB(s.value), a: 1 } })), + }; +} diff --git a/App/BlurtiOS/Design/figma/exports.js b/App/BlurtiOS/Design/figma/exports.js new file mode 100644 index 00000000..6a570150 --- /dev/null +++ b/App/BlurtiOS/Design/figma/exports.js @@ -0,0 +1,55 @@ +/* global figma, getPage, PAGES */ +// --------------------------------------------------------------------------- +// Export: the variables back out as tokens.json's groups + +async function exportTokens() { + const collections = await figma.variables.getLocalVariableCollectionsAsync(); + const byId = new Map(collections.map((c) => [c.id, c])); + const all = await figma.variables.getLocalVariablesAsync(); + const byVarId = new Map(all.map((v) => [v.id, v])); + const groupOf = { Brand: "brand", Themes: "themes", Keyboard: "keyboard", Metrics: "metrics", Typography: "type", Motion: "motion" }; + const out = {}; + for (const v of all) { + const c = byId.get(v.variableCollectionId); + const group = c && groupOf[c.name]; + if (!group) continue; + const modeId = c.modes[0].modeId; + let raw = v.valuesByMode[modeId]; + let value; + if (raw && typeof raw === "object" && raw.type === "VARIABLE_ALIAS") { + const target = byVarId.get(raw.id); + const tc = byId.get(target.variableCollectionId); + value = `{${groupOf[tc.name]}.${target.name}}`; + } else if (raw && typeof raw === "object" && "r" in raw) { + const hex = [raw.r, raw.g, raw.b].map((x) => Math.round(x * 255).toString(16).padStart(2, "0")).join(""); + value = `#${hex.toUpperCase()}`; + } else { + value = raw; + } + out[group] = out[group] || {}; + out[group][v.name] = v.description ? { value, use: v.description } : { value }; + } + return { tokens: out, note: "merge into App/BlurtiOS/Design/tokens.json (keep gradients and figma), then scripts/design-sync.sh" }; +} + +/** The absolute bounds of every named node under the layout frames, in points. */ +async function exportBounds() { + const page = await getPage(PAGES.layouts); + const frames = page.findAll((n) => n.type === "FRAME" && /^(panel|slimBar|full)\//.test(n.name)); + const bounds = {}; + for (const frame of frames) { + const origin = frame.absoluteBoundingBox; + bounds[frame.name] = {}; + for (const node of frame.findAll((n) => n.name && n.absoluteBoundingBox)) { + const b = node.absoluteBoundingBox; + bounds[frame.name][node.name] = { + x: +(b.x - origin.x).toFixed(2), + y: +(b.y - origin.y).toFixed(2), + w: +b.width.toFixed(2), + h: +b.height.toFixed(2), + type: node.type, + }; + } + } + return { frames: frames.length, bounds }; +} diff --git a/App/BlurtiOS/Design/figma/foundations.js b/App/BlurtiOS/Design/figma/foundations.js new file mode 100644 index 00000000..5958d8bf --- /dev/null +++ b/App/BlurtiOS/Design/figma/foundations.js @@ -0,0 +1,189 @@ +/* global figma, TOKENS, getPage, getSection, variableMap, hexToRGB, loadFonts, FONT, metric, autoLayout, textNode, paint, gradientPaint, VARS */ +// --------------------------------------------------------------------------- +// Foundations: variables, styles, specimens + +async function buildFoundations() { + if (!TOKENS) throw new Error("buildFoundations needs tokens.js in the call (scripts/design-figma-call.sh foundations)"); + const page = await getPage(PAGES.foundations); + const existingCollections = await figma.variables.getLocalVariableCollectionsAsync(); + const created = { collections: 0, variables: 0, aliases: 0, textStyles: 0, effectStyles: 0 }; + const collections = {}; + for (const name of TOKENS.groups) { + let c = existingCollections.find((x) => x.name === name); + if (!c) { + c = figma.variables.createVariableCollection(name); + created.collections += 1; + } + c.renameMode(c.modes[0].modeId, TOKENS.collections[name].mode); + collections[name] = c; + } + VARS = await variableMap(); + // Concrete values first, aliases second, so a target always exists. + for (const pass of ["values", "aliases"]) { + for (const name of TOKENS.groups) { + const c = collections[name]; + const modeId = c.modes[0].modeId; + for (const spec of TOKENS.collections[name].variables) { + if ((pass === "aliases") !== Boolean(spec.alias)) continue; + const key = `${name}:${spec.name}`; + let v = VARS.get(key); + if (!v) { + v = figma.variables.createVariable(spec.name, c, spec.type); + VARS.set(key, v); + created.variables += 1; + } + if (spec.alias) { + const target = VARS.get(spec.alias); + if (!target) throw new Error(`${key} aliases ${spec.alias}, which is missing`); + v.setValueForMode(modeId, figma.variables.createVariableAlias(target)); + created.aliases += 1; + } else if (spec.type === "COLOR") { + v.setValueForMode(modeId, { ...hexToRGB(spec.value), a: 1 }); + } else { + v.setValueForMode(modeId, spec.value); + } + v.scopes = spec.scopes; + v.description = spec.use || ""; + v.setVariableCodeSyntax("iOS", spec.codeSyntax); + } + } + } + + await loadFonts(); + const sizes = Object.fromEntries( + TOKENS.collections.Typography.variables.filter((v) => v.name.startsWith("size/")).map((v) => [v.name.slice(5), v.value]) + ); + const weights = Object.fromEntries( + TOKENS.collections.Typography.variables.filter((v) => v.name.startsWith("weight/")).map((v) => [v.name.slice(7), v.value]) + ); + const weightStyle = { regular: FONT.regular, medium: FONT.medium, semibold: FONT.semibold }; + const textStyleSpecs = [ + ["Key/Letter", sizes.letter, weights.letter], + ["Key/Legend", sizes.legend, weights.legend], + ["Key/Popup", sizes.popup, weights.popup], + ["Term/Text", sizes.term, weights.term], + ["Glyph", sizes.glyph, weights.glyph], + ]; + const textStyles = await figma.getLocalTextStylesAsync(); + for (const [name, size, weight] of textStyleSpecs) { + let s = textStyles.find((x) => x.name === name); + if (!s) { + s = figma.createTextStyle(); + s.name = name; + created.textStyles += 1; + } + s.fontName = { family: FONT.family, style: weightStyle[weight] }; + s.fontSize = size; + } + // The two gradients as paint styles, so a later call can draw them without + // carrying the token data (core.js › gradientPaint falls back to these). + const paintStyles = await figma.getLocalPaintStylesAsync(); + for (const name of Object.keys(TOKENS.gradients)) { + let ps = paintStyles.find((x) => x.name === `Gradient/${name}`); + if (!ps) { + ps = figma.createPaintStyle(); + ps.name = `Gradient/${name}`; + created.paintStyles = (created.paintStyles || 0) + 1; + } + ps.paints = [gradientPaint(name)]; + ps.description = TOKENS.gradients[name].use || ""; + } + const effectStyles = await figma.getLocalEffectStylesAsync(); + let shadow = effectStyles.find((x) => x.name === "Shadow/Popup"); + if (!shadow) { + shadow = figma.createEffectStyle(); + shadow.name = "Shadow/Popup"; + created.effectStyles += 1; + } + // Figma's blur is about twice SwiftUI's shadow radius; the generator's + // DESIGN.md note says the same, so the two stay one number apart on purpose. + shadow.effects = [ + { + type: "DROP_SHADOW", + color: { r: 0, g: 0, b: 0, a: metric("opacity/popup-shadow") }, + offset: { x: 0, y: metric("popup/shadow-y") }, + radius: metric("popup/shadow-radius") * 2, + spread: 0, + visible: true, + blendMode: "NORMAL", + }, + ]; + + // Specimens: swatches for every colour, a line per number, all bound. + const ids = []; + const colours = getSection(page, "Colour", 0, 0); + const grid = autoLayout("VERTICAL", { name: "Swatches", itemSpacing: 8 }); + for (const name of ["Brand", "Themes", "Keyboard"]) { + const row = autoLayout("VERTICAL", { name, itemSpacing: 4 }); + row.appendChild(await textNode(name, { size: 14, weight: FONT.medium, fillRef: "Brand:ink" })); + const wrap = autoLayout("HORIZONTAL", { name: `${name} swatches`, itemSpacing: 8 }); + wrap.layoutWrap = "WRAP"; + wrap.counterAxisSpacing = 8; + wrap.resize(1200, 10); + wrap.primaryAxisSizingMode = "FIXED"; + for (const spec of TOKENS.collections[name].variables) { + const cell = autoLayout("VERTICAL", { name: spec.name, itemSpacing: 2 }); + const swatch = figma.createRectangle(); + swatch.resize(64, 40); + swatch.cornerRadius = 4; + swatch.fills = [await paint(`${name}:${spec.name}`)]; + cell.appendChild(swatch); + cell.appendChild(await textNode(spec.name, { size: 9, fillRef: "Brand:ink" })); + cell.appendChild(await textNode(spec.value, { size: 9, fillRef: "Brand:ink" })); + wrap.appendChild(cell); + } + row.appendChild(wrap); + grid.appendChild(row); + } + const oldGrid = colours.children.find((n) => n.name === "Swatches"); + if (oldGrid) oldGrid.remove(); + colours.appendChild(grid); + colours.resizeWithoutConstraints(grid.width + 80, grid.height + 80); + grid.x = 40; + grid.y = 40; + ids.push(grid.id); + + const numbers = getSection(page, "Numbers", 0, colours.height + 80); + const list = autoLayout("VERTICAL", { name: "Tokens", itemSpacing: 2 }); + for (const name of ["Metrics", "Typography", "Motion"]) { + list.appendChild(await textNode(name, { size: 14, weight: FONT.medium, fillRef: "Brand:ink" })); + for (const spec of TOKENS.collections[name].variables) { + list.appendChild( + await textNode(`${spec.name} = ${spec.value} · ${spec.codeSyntax}${spec.use ? " — " + spec.use : ""}`, { + size: 10, + fillRef: "Brand:ink", + }) + ); + } + } + const oldList = numbers.children.find((n) => n.name === "Tokens"); + if (oldList) oldList.remove(); + numbers.appendChild(list); + numbers.resizeWithoutConstraints(list.width + 80, list.height + 80); + list.x = 40; + list.y = 40; + ids.push(list.id); + + const recipe = getSection(page, "Orb recipe", colours.width + 80, 0); + const note = await textNode( + [ + "The orb is the one thing Figma does not draw. It is a 3 × 3 MeshGradient whose edge midpoints and centre", + "drift on slow sines (further with the voice), under a soft upper-left light (opacity/orb-light,", + "orb/light-x, orb/light-y, orb/light-radius) and film grain (opacity/grain; a seeded scatter of 1 pt dots,", + "one per 26 pt²). The words landing pours cobolt in from the centre (drop, drop-rise, drop-hold) with six", + "four-point sparkles. Orb/Disc's fills are stills the app renders (-BlurtOrb ); the", + "parameters above are the variables. Source: App/BlurtiOS/BlurtKeyboard/Sources/PrismOrb.swift.", + ].join("\n"), + { size: 11, fillRef: "Brand:ink" } + ); + note.textAutoResize = "HEIGHT"; + note.resize(720, 10); + const oldNote = recipe.children.find((n) => n.type === "TEXT"); + if (oldNote) oldNote.remove(); + recipe.appendChild(note); + recipe.resizeWithoutConstraints(800, note.height + 80); + note.x = 40; + note.y = 40; + + return { page: page.id, created, specimenIds: ids, variables: VARS.size }; +} diff --git a/App/BlurtiOS/Design/figma/layouts.js b/App/BlurtiOS/Design/figma/layouts.js new file mode 100644 index 00000000..8ccbcdbc --- /dev/null +++ b/App/BlurtiOS/Design/figma/layouts.js @@ -0,0 +1,222 @@ +/* global figma, getPage, getSection, variableMap, ensureTokens, loadFonts, FONT, metric, autoLayout, textNode, paint, bind, symbolChar, DEVICE_WIDTH, DESIGN_THEME, STATES, PAGES, findComponentSet, findComponent, VARS */ +// --------------------------------------------------------------------------- +// Layouts (03 Layouts): the three keyboards as frames of instances, one per +// state, named exactly as the gallery captions them (//) + +/** The instance's label, written on its text node: setProperties refuses a + * text property whose font Figma marks missing, which it does for the local + * SF Pro under the MCP runtime even after loadFontAsync; a direct write goes + * through, and renders the same. */ +function setLabel(instance, label) { + const t = instance.findOne((n) => n.type === "TEXT" && n.name === "Label"); + if (t) t.characters = label; +} + +const STATE_TO_MIC = { + off: "Off", + start: "Off", + idle: "Idle", + connecting: "Working", + recording: "Recording", + processing: "Working", + pasted: "Pasted", + copied: "Copied", + error: "Error", + landed: "Pasted", +}; + +async function layoutRoot(name, height) { + const f = figma.createFrame(); + f.name = name; + f.layoutMode = "VERTICAL"; + f.primaryAxisSizingMode = "FIXED"; + f.counterAxisSizingMode = "FIXED"; + f.resize(DEVICE_WIDTH, height); + f.fills = [await paint("Keyboard:kb/surface")]; + f.clipsContent = true; + await bind(f, "paddingLeft", "Metrics:margin/side"); + await bind(f, "paddingRight", "Metrics:margin/side"); + await bind(f, "paddingTop", "Metrics:margin/vertical"); + await bind(f, "paddingBottom", "Metrics:margin/vertical"); + return f; +} + +async function keyInstance(sets, tone, label, widthRef) { + const variant = sets.key.children.find((c) => c.name.includes(`Tone=${tone}`) && c.name.includes("State=Up")); + const i = variant.createInstance(); + setLabel(i, label); + i.name = label === "space" ? "space" : `key ${label}`; + if (widthRef) { + i.layoutSizingHorizontal = "FIXED"; + i.resize(metric(widthRef), i.height); + await bind(i, "width", `Metrics:${widthRef}`); + } + return i; +} + +async function bottomRow(sets, parent, { withSymbols }) { + const row = autoLayout("HORIZONTAL", { name: "bottom row" }); + await bind(row, "itemSpacing", "Metrics:key/gap"); + row.counterAxisAlignItems = "CENTER"; + parent.appendChild(row); + row.layoutSizingHorizontal = "FILL"; + if (withSymbols) row.appendChild(await keyInstance(sets, "Modifier", "123", "key/side-width-402")); + row.appendChild(await keyInstance(sets, "Modifier", symbolChar("globe", "🌐"), withSymbols ? "key/side-width-402" : null)); + const space = await keyInstance(sets, "Key", "space", null); + row.appendChild(space); + space.layoutSizingHorizontal = "FILL"; + if (!withSymbols) row.appendChild(await keyInstance(sets, "Modifier", symbolChar("delete.left", "⌫"), null)); + row.appendChild( + await keyInstance(sets, "Modifier", symbolChar("return", "↩"), withSymbols ? "key/return-width-402" : null) + ); + return row; +} + +async function buildPanelFrame(sets, state, theme) { + const f = await layoutRoot(`panel/${state}/${theme}`, metric("layout/panel")); + await bind(f, "itemSpacing", "Metrics:panel/spacing"); + const voice = autoLayout("VERTICAL", { name: "voice" }); + voice.primaryAxisAlignItems = "CENTER"; + voice.counterAxisAlignItems = "CENTER"; + f.appendChild(voice); + voice.layoutSizingHorizontal = "FILL"; + voice.layoutSizingVertical = "FILL"; + const mic = sets.micKey.children + .find((c) => c.name.includes("Size=Panel") && c.name.includes(`State=${STATE_TO_MIC[state] || "Idle"}`)) + .createInstance(); + mic.name = "MicKey"; + voice.appendChild(mic); + await bottomRow(sets, f, { withSymbols: false }); + const plus = sets.addTermKey.children.find((c) => c.name.includes("Saved=False")).createInstance(); + plus.name = "AddTermKey"; + f.appendChild(plus); + plus.layoutPositioning = "ABSOLUTE"; + plus.x = metric("addterm/inset"); + plus.y = metric("addterm/inset"); + if (["connecting", "recording", "processing"].includes(state)) { + const cancel = sets.cancelKey.createInstance(); + cancel.name = "CancelKey"; + f.appendChild(cancel); + cancel.layoutPositioning = "ABSOLUTE"; + cancel.constraints = { horizontal: "MAX", vertical: "MIN" }; + cancel.x = DEVICE_WIDTH - metric("margin/side") - cancel.width; + cancel.y = metric("margin/vertical"); + } + return f; +} + +async function voiceBarInstance(sets, state, hasFullAccess) { + const mode = !hasFullAccess ? "NoFullAccess" : state === "term" ? "Term" : state === "recording" ? "Wave" : "Orb"; + const i = sets.voiceBar.children.find((c) => c.name.includes(`Mode=${mode}`)).createInstance(); + i.name = "VoiceBar"; + if (mode === "Orb") { + const mic = i.findOne((n) => n.type === "INSTANCE" && n.name.startsWith("Size=Bar")); + if (mic) { + const target = sets.micKey.children.find( + (c) => c.name.includes("Size=Bar") && c.name.includes(`State=${STATE_TO_MIC[state] || "Idle"}`) + ); + if (target) mic.swapComponent(target); + } + } + return i; +} + +async function buildSlimBarFrame(sets, state, theme) { + const f = await layoutRoot(`slimBar/${state}/${theme}`, metric("layout/slim")); + const row = autoLayout("HORIZONTAL", { name: "row" }); + await bind(row, "itemSpacing", "Metrics:slim/spacing"); + row.counterAxisAlignItems = "CENTER"; + f.appendChild(row); + row.layoutSizingHorizontal = "FILL"; + row.appendChild(await keyInstance(sets, "Modifier", symbolChar("globe", "🌐"), null)); + const bar = await voiceBarInstance(sets, state, state !== "off"); + row.appendChild(bar); + bar.layoutSizingHorizontal = "FILL"; + row.appendChild(await keyInstance(sets, "Modifier", symbolChar("delete.left", "⌫"), null)); + row.appendChild(await keyInstance(sets, "Modifier", symbolChar("return", "↩"), null)); + return f; +} + +async function buildFullFrame(sets, state, theme) { + const f = await layoutRoot(`full/${state}/${theme}`, metric("layout/full")); + await bind(f, "itemSpacing", "Metrics:row/gap"); + const bar = await voiceBarInstance(sets, state, state !== "off"); + f.appendChild(bar); + bar.layoutSizingHorizontal = "FILL"; + const rows = ["qwertyuiop", "asdfghjkl", "zxcvbnm"]; + const letter = (ch) => { + const v = sets.letterKey.children.find((c) => c.name.includes("State=Up")).createInstance(); + setLabel(v, ch); + v.name = `key ${ch}`; + return v; + }; + for (const [index, letters] of rows.entries()) { + const row = autoLayout("HORIZONTAL", { name: `row ${index + 1}` }); + row.primaryAxisAlignItems = "CENTER"; + row.counterAxisAlignItems = "CENTER"; + f.appendChild(row); + row.layoutSizingHorizontal = "FILL"; + if (index === 2) { + row.itemSpacing = metric("key/gap") * metric("key/side-gap-factor"); + row.appendChild(await keyInstance(sets, "Modifier", symbolChar("shift", "⇧"), "key/side-width-402")); + const inner = autoLayout("HORIZONTAL", { name: "letters" }); + await bind(inner, "itemSpacing", "Metrics:key/gap"); + row.appendChild(inner); + for (const ch of letters) inner.appendChild(letter(ch)); + row.appendChild(await keyInstance(sets, "Modifier", symbolChar("delete.left", "⌫"), "key/side-width-402")); + } else { + await bind(row, "itemSpacing", "Metrics:key/gap"); + for (const ch of letters) row.appendChild(letter(ch)); + } + } + await bottomRow(sets, f, { withSymbols: true }); + return f; +} + +async function buildLayouts() { + const components = await getPage(PAGES.components); + const sets = { + key: await findComponentSet(components, "Key"), + letterKey: await findComponentSet(components, "LetterKey"), + addTermKey: await findComponentSet(components, "AddTermKey"), + cancelKey: await findComponent(components, "CancelKey"), + micKey: await findComponentSet(components, "MicKey"), + voiceBar: await findComponentSet(components, "VoiceBar"), + }; + for (const [name, set] of Object.entries(sets)) if (!set) throw new Error(`component ${name} missing — run buildComponents first`); + await ensureTokens(); + const page = await getPage(PAGES.layouts); + VARS = await variableMap(); + await loadFonts(); + const builders = { Panel: buildPanelFrame, SlimBar: buildSlimBarFrame, Full: buildFullFrame }; + const built = {}; + let sectionX = 0; + for (const [name, build] of Object.entries(builders)) { + const section = getSection(page, name, sectionX, 0); + for (const child of [...section.children]) child.remove(); + const states = name === "Panel" ? STATES.filter((s) => s !== "term") : STATES; + let y = 40; + const ids = []; + for (const state of states) { + const caption = await textNode(`${name.charAt(0).toLowerCase() + name.slice(1)} · ${state} · ${DESIGN_THEME}`, { + size: 11, + weight: FONT.medium, + fillRef: "Brand:ink", + }); + section.appendChild(caption); + caption.x = 40; + caption.y = y; + y += 20; + const frame = await build(sets, state, DESIGN_THEME); + section.appendChild(frame); + frame.x = 40; + frame.y = y; + y += frame.height + 40; + ids.push(frame.id); + } + section.resizeWithoutConstraints(DEVICE_WIDTH + 80, y); + built[name] = ids; + sectionX += DEVICE_WIDTH + 160; + } + return { page: page.id, built }; +} diff --git a/App/BlurtiOS/Design/figma/lib.js b/App/BlurtiOS/Design/figma/lib.js deleted file mode 100644 index 72a22d03..00000000 --- a/App/BlurtiOS/Design/figma/lib.js +++ /dev/null @@ -1,1187 +0,0 @@ -// The Blurt Keyboard Figma file, built from the tokens. Plain Plugin API, so -// the same functions run two ways (README.md): pasted into a use_figma call -// behind tokens.js with `return await buildFoundations();`, or bundled by -// scripts/design-sync.sh into a development plugin (plugin.js dispatches). -// Everything is idempotent — find by name before create — and every builder -// returns the ids and counts it touched. No `figma.notify`, no console output. -/* global figma, TOKENS */ - -// --------------------------------------------------------------------------- -// Names - -const PAGES = { foundations: "01 Foundations", components: "02 Components", layouts: "03 Layouts" }; -const FONT = { family: "SF Pro", regular: "Regular", medium: "Medium", semibold: "Semibold" }; -const DEVICE_WIDTH = 402; // iPhone 18 Pro, the simulator this repo captures on -const DESIGN_THEME = "ink"; -const THEMES = ["system-light", "system-dark", "ink", "paper", "lavender", "mint", "midnight", "sunset"]; -const ROLES = ["surface", "key", "key-modifier", "legend", "signal", "popup"]; -const STATES = ["off", "start", "idle", "connecting", "recording", "processing", "pasted", "copied", "error", "term"]; - -// --------------------------------------------------------------------------- -// Helpers - -function hexToRGB(hex) { - const n = parseInt(hex.slice(1), 16); - return { r: ((n >> 16) & 255) / 255, g: ((n >> 8) & 255) / 255, b: (n & 255) / 255 }; -} - -function token(collection, name) { - const entry = TOKENS.collections[collection].variables.find((v) => v.name === name); - if (!entry) throw new Error(`no token ${collection}:${name}`); - return entry; -} - -function metric(name) { - return token("Metrics", name).value; -} - -async function getPage(name) { - let page = figma.root.children.find((p) => p.name === name); - if (!page) { - page = figma.createPage(); - page.name = name; - } - await figma.setCurrentPageAsync(page); - return page; -} - -function getSection(page, name, x, y) { - let section = page.children.find((n) => n.type === "SECTION" && n.name === name); - if (!section) { - section = figma.createSection(); - section.name = name; - section.x = x; - section.y = y; - page.appendChild(section); - } - return section; -} - -/** Every local variable, keyed "Collection:name". */ -async function variableMap() { - const collections = await figma.variables.getLocalVariableCollectionsAsync(); - const byId = new Map(collections.map((c) => [c.id, c])); - const map = new Map(); - for (const v of await figma.variables.getLocalVariablesAsync()) { - const collection = byId.get(v.variableCollectionId); - if (collection) map.set(`${collection.name}:${v.name}`, v); - } - return map; -} - -let VARS = null; -async function vars() { - if (!VARS) VARS = await variableMap(); - return VARS; -} - -async function variable(ref) { - const v = (await vars()).get(ref); - if (!v) throw new Error(`variable ${ref} is not in the file — run buildFoundations first`); - return v; -} - -/** A solid paint bound to a colour variable. */ -async function paint(ref) { - const v = await variable(ref); - return figma.variables.setBoundVariableForPaint({ type: "SOLID", color: { r: 0, g: 0, b: 0 } }, "color", v); -} - -async function bind(node, field, ref) { - node.setBoundVariable(field, await variable(ref)); -} - -async function bindRadius(node, ref) { - for (const corner of ["topLeftRadius", "topRightRadius", "bottomLeftRadius", "bottomRightRadius"]) { - await bind(node, corner, ref); - } -} - -async function loadFonts() { - const available = await figma.listAvailableFontsAsync(); - const families = new Set(available.map((f) => f.fontName.family)); - if (!families.has(FONT.family)) { - throw new Error(`${FONT.family} is not available in this file; install SF Pro from developer.apple.com/fonts`); - } - for (const style of [FONT.regular, FONT.medium, FONT.semibold]) { - await figma.loadFontAsync({ family: FONT.family, style }); - } -} - -/** An SF Symbol as a character where the runtime can (the MCP one), else a stand-in. */ -function symbolChar(name, fallback) { - try { - if (figma.util && typeof figma.util.getSfSymbolCharacter === "function") { - return figma.util.getSfSymbolCharacter(name); - } - } catch (_) { - // fall through to the stand-in - } - return fallback; -} - -async function textNode(characters, { size, weight = FONT.regular, fillRef, styleId } = {}) { - const t = figma.createText(); - t.fontName = { family: FONT.family, style: weight }; - t.characters = characters; - if (size) t.fontSize = size; - if (styleId) t.textStyleId = styleId; - if (fillRef) t.fills = [await paint(fillRef)]; - t.textAutoResize = "WIDTH_AND_HEIGHT"; - return t; -} - -function autoLayout(direction, props = {}) { - const frame = figma.createFrame(); - frame.layoutMode = direction; - frame.primaryAxisSizingMode = "AUTO"; - frame.counterAxisSizingMode = "AUTO"; - frame.fills = []; - frame.clipsContent = false; - Object.assign(frame, props); - return frame; -} - -function gradientPaint(gradientName) { - const g = TOKENS.gradients[gradientName]; - const transforms = { - "bottom>top": [ - [0, -1, 1], - [1, 0, 0], - ], - "topLeading>bottomTrailing": [ - [0.5, 0.5, 0], - [-0.5, 0.5, 0.5], - ], - }; - return { - type: "GRADIENT_LINEAR", - gradientTransform: transforms[`${g.start}>${g.end}`] || transforms["bottom>top"], - gradientStops: g.stops.map((s) => ({ position: s.location, color: { ...hexToRGB(s.value), a: 1 } })), - }; -} - -// --------------------------------------------------------------------------- -// Foundations: variables, styles, specimens - -async function buildFoundations() { - const page = await getPage(PAGES.foundations); - const existingCollections = await figma.variables.getLocalVariableCollectionsAsync(); - const created = { collections: 0, variables: 0, aliases: 0, textStyles: 0, effectStyles: 0 }; - const collections = {}; - for (const name of TOKENS.groups) { - let c = existingCollections.find((x) => x.name === name); - if (!c) { - c = figma.variables.createVariableCollection(name); - created.collections += 1; - } - c.renameMode(c.modes[0].modeId, TOKENS.collections[name].mode); - collections[name] = c; - } - VARS = await variableMap(); - // Concrete values first, aliases second, so a target always exists. - for (const pass of ["values", "aliases"]) { - for (const name of TOKENS.groups) { - const c = collections[name]; - const modeId = c.modes[0].modeId; - for (const spec of TOKENS.collections[name].variables) { - if ((pass === "aliases") !== Boolean(spec.alias)) continue; - const key = `${name}:${spec.name}`; - let v = VARS.get(key); - if (!v) { - v = figma.variables.createVariable(spec.name, c, spec.type); - VARS.set(key, v); - created.variables += 1; - } - if (spec.alias) { - const target = VARS.get(spec.alias); - if (!target) throw new Error(`${key} aliases ${spec.alias}, which is missing`); - v.setValueForMode(modeId, figma.variables.createVariableAlias(target)); - created.aliases += 1; - } else if (spec.type === "COLOR") { - v.setValueForMode(modeId, { ...hexToRGB(spec.value), a: 1 }); - } else { - v.setValueForMode(modeId, spec.value); - } - v.scopes = spec.scopes; - v.description = spec.use || ""; - v.setVariableCodeSyntax("iOS", spec.codeSyntax); - } - } - } - - await loadFonts(); - const sizes = Object.fromEntries( - TOKENS.collections.Typography.variables.filter((v) => v.name.startsWith("size/")).map((v) => [v.name.slice(5), v.value]) - ); - const weights = Object.fromEntries( - TOKENS.collections.Typography.variables.filter((v) => v.name.startsWith("weight/")).map((v) => [v.name.slice(7), v.value]) - ); - const weightStyle = { regular: FONT.regular, medium: FONT.medium, semibold: FONT.semibold }; - const textStyleSpecs = [ - ["Key/Letter", sizes.letter, weights.letter], - ["Key/Legend", sizes.legend, weights.legend], - ["Key/Popup", sizes.popup, weights.popup], - ["Term/Text", sizes.term, weights.term], - ["Glyph", sizes.glyph, weights.glyph], - ]; - const textStyles = await figma.getLocalTextStylesAsync(); - for (const [name, size, weight] of textStyleSpecs) { - let s = textStyles.find((x) => x.name === name); - if (!s) { - s = figma.createTextStyle(); - s.name = name; - created.textStyles += 1; - } - s.fontName = { family: FONT.family, style: weightStyle[weight] }; - s.fontSize = size; - } - const effectStyles = await figma.getLocalEffectStylesAsync(); - let shadow = effectStyles.find((x) => x.name === "Shadow/Popup"); - if (!shadow) { - shadow = figma.createEffectStyle(); - shadow.name = "Shadow/Popup"; - created.effectStyles += 1; - } - // Figma's blur is about twice SwiftUI's shadow radius; the generator's - // DESIGN.md note says the same, so the two stay one number apart on purpose. - shadow.effects = [ - { - type: "DROP_SHADOW", - color: { r: 0, g: 0, b: 0, a: metric("opacity/popup-shadow") }, - offset: { x: 0, y: metric("popup/shadow-y") }, - radius: metric("popup/shadow-radius") * 2, - spread: 0, - visible: true, - blendMode: "NORMAL", - }, - ]; - - // Specimens: swatches for every colour, a line per number, all bound. - const ids = []; - const colours = getSection(page, "Colour", 0, 0); - const grid = autoLayout("VERTICAL", { name: "Swatches", itemSpacing: 8 }); - for (const name of ["Brand", "Themes", "Keyboard"]) { - const row = autoLayout("VERTICAL", { name, itemSpacing: 4 }); - row.appendChild(await textNode(name, { size: 14, weight: FONT.medium, fillRef: "Brand:ink" })); - const wrap = autoLayout("HORIZONTAL", { name: `${name} swatches`, itemSpacing: 8 }); - wrap.layoutWrap = "WRAP"; - wrap.counterAxisSpacing = 8; - wrap.resize(1200, 10); - wrap.primaryAxisSizingMode = "FIXED"; - for (const spec of TOKENS.collections[name].variables) { - const cell = autoLayout("VERTICAL", { name: spec.name, itemSpacing: 2 }); - const swatch = figma.createRectangle(); - swatch.resize(64, 40); - swatch.cornerRadius = 4; - swatch.fills = [await paint(`${name}:${spec.name}`)]; - cell.appendChild(swatch); - cell.appendChild(await textNode(spec.name, { size: 9, fillRef: "Brand:ink" })); - cell.appendChild(await textNode(spec.value, { size: 9, fillRef: "Brand:ink" })); - wrap.appendChild(cell); - } - row.appendChild(wrap); - grid.appendChild(row); - } - const oldGrid = colours.children.find((n) => n.name === "Swatches"); - if (oldGrid) oldGrid.remove(); - colours.appendChild(grid); - colours.resizeWithoutConstraints(grid.width + 80, grid.height + 80); - grid.x = 40; - grid.y = 40; - ids.push(grid.id); - - const numbers = getSection(page, "Numbers", 0, colours.height + 80); - const list = autoLayout("VERTICAL", { name: "Tokens", itemSpacing: 2 }); - for (const name of ["Metrics", "Typography", "Motion"]) { - list.appendChild(await textNode(name, { size: 14, weight: FONT.medium, fillRef: "Brand:ink" })); - for (const spec of TOKENS.collections[name].variables) { - list.appendChild( - await textNode(`${spec.name} = ${spec.value} · ${spec.codeSyntax}${spec.use ? " — " + spec.use : ""}`, { - size: 10, - fillRef: "Brand:ink", - }) - ); - } - } - const oldList = numbers.children.find((n) => n.name === "Tokens"); - if (oldList) oldList.remove(); - numbers.appendChild(list); - numbers.resizeWithoutConstraints(list.width + 80, list.height + 80); - list.x = 40; - list.y = 40; - ids.push(list.id); - - const recipe = getSection(page, "Orb recipe", colours.width + 80, 0); - const note = await textNode( - [ - "The orb is the one thing Figma does not draw. It is a 3 × 3 MeshGradient whose edge midpoints and centre", - "drift on slow sines (further with the voice), under a soft upper-left light (opacity/orb-light,", - "orb/light-x, orb/light-y, orb/light-radius) and film grain (opacity/grain; a seeded scatter of 1 pt dots,", - "one per 26 pt²). The words landing pours cobolt in from the centre (drop, drop-rise, drop-hold) with six", - "four-point sparkles. Orb/Disc's fills are stills the app renders (-BlurtOrb ); the", - "parameters above are the variables. Source: App/BlurtiOS/BlurtKeyboard/Sources/PrismOrb.swift.", - ].join("\n"), - { size: 11, fillRef: "Brand:ink" } - ); - note.textAutoResize = "HEIGHT"; - note.resize(720, 10); - const oldNote = recipe.children.find((n) => n.type === "TEXT"); - if (oldNote) oldNote.remove(); - recipe.appendChild(note); - recipe.resizeWithoutConstraints(800, note.height + 80); - note.x = 40; - note.y = 40; - - return { page: page.id, created, specimenIds: ids, variables: VARS.size }; -} - -// --------------------------------------------------------------------------- -// Export: the variables back out as tokens.json's groups - -async function exportTokens() { - const collections = await figma.variables.getLocalVariableCollectionsAsync(); - const byId = new Map(collections.map((c) => [c.id, c])); - const all = await figma.variables.getLocalVariablesAsync(); - const byVarId = new Map(all.map((v) => [v.id, v])); - const groupOf = { Brand: "brand", Themes: "themes", Keyboard: "keyboard", Metrics: "metrics", Typography: "type", Motion: "motion" }; - const out = {}; - for (const v of all) { - const c = byId.get(v.variableCollectionId); - const group = c && groupOf[c.name]; - if (!group) continue; - const modeId = c.modes[0].modeId; - let raw = v.valuesByMode[modeId]; - let value; - if (raw && typeof raw === "object" && raw.type === "VARIABLE_ALIAS") { - const target = byVarId.get(raw.id); - const tc = byId.get(target.variableCollectionId); - value = `{${groupOf[tc.name]}.${target.name}}`; - } else if (raw && typeof raw === "object" && "r" in raw) { - const hex = [raw.r, raw.g, raw.b].map((x) => Math.round(x * 255).toString(16).padStart(2, "0")).join(""); - value = `#${hex.toUpperCase()}`; - } else { - value = raw; - } - out[group] = out[group] || {}; - out[group][v.name] = v.description ? { value, use: v.description } : { value }; - } - return { tokens: out, note: "merge into App/BlurtiOS/Design/tokens.json (keep gradients and figma), then scripts/design-sync.sh" }; -} - -/** The absolute bounds of every named node under the layout frames, in points. */ -async function exportBounds() { - const page = await getPage(PAGES.layouts); - const frames = page.findAll((n) => n.type === "FRAME" && /^(panel|slimBar|full)\//.test(n.name)); - const bounds = {}; - for (const frame of frames) { - const origin = frame.absoluteBoundingBox; - bounds[frame.name] = {}; - for (const node of frame.findAll((n) => n.name && n.absoluteBoundingBox)) { - const b = node.absoluteBoundingBox; - bounds[frame.name][node.name] = { - x: +(b.x - origin.x).toFixed(2), - y: +(b.y - origin.y).toFixed(2), - w: +b.width.toFixed(2), - h: +b.height.toFixed(2), - type: node.type, - }; - } - } - return { frames: frames.length, bounds }; -} - -// --------------------------------------------------------------------------- -// Components (02 Components). Every fill, stroke, radius and gap is bound to a -// variable; the orb's disc is the one image fill (see buildOrbDisc). - -const SIZES = { Bar: "orb/bar", Panel: "orb/panel", Home: "orb/home" }; -const WAVES = { - Bar: ["wave/bar-width", "wave/bar-height"], - Panel: ["wave/panel-width", "wave/panel-height"], - Home: ["wave/home-width", "wave/home-height"], -}; - -async function findComponentSet(page, name) { - return page.findOne((n) => n.type === "COMPONENT_SET" && n.name === name); -} - -async function findComponent(page, name) { - return page.findOne((n) => n.type === "COMPONENT" && n.name === name && n.parent.type !== "COMPONENT_SET"); -} - -async function textStyleId(name) { - const s = (await figma.getLocalTextStylesAsync()).find((x) => x.name === name); - if (!s) throw new Error(`text style ${name} missing — run buildFoundations first`); - return s.id; -} - -async function effectStyleId(name) { - const s = (await figma.getLocalEffectStylesAsync()).find((x) => x.name === name); - if (!s) throw new Error(`effect style ${name} missing — run buildFoundations first`); - return s.id; -} - -/** Replaces a component set (or lone component) of this name, keeping its position. */ -function replaceNamed(page, name, node) { - const old = page.findOne((n) => (n.type === "COMPONENT_SET" || n.type === "COMPONENT") && n.name === name); - if (old) { - node.x = old.x; - node.y = old.y; - old.remove(); - } -} - -/** Lays the variants of a set out in a row and names the set. */ -function finishSet(page, name, variants, x, y) { - const set = figma.combineAsVariants(variants, page); - set.name = name; - set.layoutMode = "HORIZONTAL"; - set.itemSpacing = 24; - set.paddingLeft = set.paddingRight = set.paddingTop = set.paddingBottom = 24; - set.primaryAxisSizingMode = "AUTO"; - set.counterAxisSizingMode = "AUTO"; - set.counterAxisAlignItems = "MIN"; - set.x = x; - set.y = y; - return set; -} - -async function keyCap(props) { - // props: tone "Key"|"Modifier"|"Bare", pressed, label, width (fixed) or null (min width + pad) - const c = figma.createComponent(); - c.name = `Tone=${props.tone}, State=${props.pressed ? "Pressed" : "Up"}`; - c.layoutMode = "HORIZONTAL"; - c.primaryAxisAlignItems = "CENTER"; - c.counterAxisAlignItems = "CENTER"; - c.primaryAxisSizingMode = props.width ? "FIXED" : "AUTO"; - c.counterAxisSizingMode = "FIXED"; - c.resize(props.width || metric("key/min-width"), metric("key/height")); - await bind(c, "height", "Metrics:key/height"); - if (props.width) await bind(c, "width", `Metrics:${props.widthRef}`); - else { - await bind(c, "minWidth", "Metrics:key/min-width"); - await bind(c, "paddingLeft", "Metrics:key/pad"); - await bind(c, "paddingRight", "Metrics:key/pad"); - } - c.fills = props.tone === "Bare" ? [] : [await paint(props.tone === "Modifier" ? "Keyboard:kb/key-modifier" : "Keyboard:kb/key")]; - await bindRadius(c, "Metrics:key/radius"); - const label = await textNode(props.label, { - styleId: await textStyleId(props.letter ? "Key/Letter" : "Key/Legend"), - fillRef: props.tint || "Keyboard:kb/legend", - }); - label.name = "Label"; - c.appendChild(label); - if (props.pressed) { - const shine = figma.createRectangle(); - shine.name = "Pressed"; - shine.fills = [{ type: "SOLID", color: { r: 1, g: 1, b: 1 } }]; - await bind(shine, "opacity", "Metrics:opacity/press-brighten"); - c.appendChild(shine); - shine.layoutPositioning = "ABSOLUTE"; - shine.x = 0; - shine.y = 0; - shine.resize(c.width, c.height); - shine.constraints = { horizontal: "STRETCH", vertical: "STRETCH" }; - await bindRadius(shine, "Metrics:key/radius"); - } - return c; -} - -async function buildKeySet(page, x, y) { - const variants = []; - for (const tone of ["Key", "Modifier", "Bare"]) { - for (const pressed of [false, true]) { - variants.push(await keyCap({ tone, pressed, label: tone === "Bare" ? "×" : "space" })); - } - } - replaceNamed(page, "Key", variants[0]); - const set = finishSet(page, "Key", variants, x, y); - set.description = "One ordinary key: a legend on a cap in the current palette; Modifier a step darker; Bare a glyph with no cap. Flat: no drop, no edge, no gloss."; - const labelProp = set.addComponentProperty("Label", "TEXT", "space"); - for (const v of variants) { - const t = v.findOne((n) => n.type === "TEXT" && n.name === "Label"); - t.componentPropertyReferences = { characters: labelProp }; - } - return set; -} - -async function buildLetterKeySet(page, x, y) { - const variants = []; - for (const pressed of [false, true]) { - const c = await keyCap({ - tone: "Key", - pressed, - label: "q", - letter: true, - width: metric("key/letter-width-402"), - widthRef: "key/letter-width-402", - }); - c.name = `State=${pressed ? "Pressed" : "Up"}`; - if (pressed) { - const popup = figma.createFrame(); - popup.name = "LetterPopup"; - popup.layoutMode = "HORIZONTAL"; - popup.primaryAxisAlignItems = "CENTER"; - popup.counterAxisAlignItems = "CENTER"; - popup.primaryAxisSizingMode = "FIXED"; - popup.counterAxisSizingMode = "FIXED"; - popup.resize(metric("key/letter-width-402") + metric("popup/extra-width"), metric("popup/height")); - await bind(popup, "height", "Metrics:popup/height"); - popup.fills = [await paint("Keyboard:kb/popup")]; - await bindRadius(popup, "Metrics:popup/radius"); - popup.effectStyleId = await effectStyleId("Shadow/Popup"); - const big = await textNode("q", { styleId: await textStyleId("Key/Popup"), fillRef: "Keyboard:kb/legend" }); - big.name = "Popup label"; - popup.appendChild(big); - c.appendChild(popup); - popup.layoutPositioning = "ABSOLUTE"; - popup.x = -metric("popup/extra-width") / 2; - popup.y = -metric("popup/offset"); - } - variants.push(c); - } - replaceNamed(page, "LetterKey", variants[0]); - const set = finishSet(page, "LetterKey", variants, x, y); - set.description = "A letter key with the system keyboard's 22 pt legend and its pop-up while pressed: a 32 pt copy above the key, the one thing that floats."; - const labelProp = set.addComponentProperty("Label", "TEXT", "q"); - for (const v of variants) { - for (const t of v.findAll((n) => n.type === "TEXT")) t.componentPropertyReferences = { characters: labelProp }; - } - return set; -} - -async function glyphButton(name, symbol, fallback, fillRef, opacityRef) { - const c = figma.createComponent(); - c.name = name; - c.layoutMode = "HORIZONTAL"; - c.primaryAxisAlignItems = "CENTER"; - c.counterAxisAlignItems = "CENTER"; - c.primaryAxisSizingMode = "FIXED"; - c.counterAxisSizingMode = "FIXED"; - c.resize(metric("glyph/hit"), metric("glyph/hit")); - await bind(c, "width", "Metrics:glyph/hit"); - await bind(c, "height", "Metrics:glyph/hit"); - const t = await textNode(symbolChar(symbol, fallback), { styleId: await textStyleId("Glyph"), fillRef }); - t.name = "Glyph"; - if (opacityRef) await bind(t, "opacity", opacityRef); - c.appendChild(t); - return c; -} - -async function buildAddTermKey(page, x, y) { - const off = await glyphButton("Saved=False", "plus", "+", "Keyboard:kb/legend", "Metrics:opacity/legend-muted"); - const on = await glyphButton("Saved=True", "checkmark", "✓", "Keyboard:kb/signal", null); - replaceNamed(page, "AddTermKey", off); - const set = finishSet(page, "AddTermKey", [off, on], x, y); - set.description = "The small + beside the orb: a new key term. A bare glyph, quiet until needed; a check for a moment after one was saved."; - return set; -} - -async function buildCancelKey(page, x, y) { - const c = await keyCap({ tone: "Bare", pressed: false, label: symbolChar("xmark", "×"), tint: "Keyboard:kb/cancel" }); - c.name = "CancelKey"; - c.description = "Cancel, in the panel's top-right corner while something is in flight: the orange × on no cap."; - replaceNamed(page, "CancelKey", c); - page.appendChild(c); - c.x = x; - c.y = y; - return c; -} - -async function buildTermField(page, x, y) { - const c = figma.createComponent(); - c.name = "TermField"; - c.description = "The voice bar as a field: × to leave, what has been typed with a caret, ✓ to save."; - c.layoutMode = "HORIZONTAL"; - c.counterAxisAlignItems = "CENTER"; - c.primaryAxisSizingMode = "FIXED"; - c.counterAxisSizingMode = "FIXED"; - c.resize(DEVICE_WIDTH - 2 * metric("margin/side"), metric("voicebar/height")); - await bind(c, "height", "Metrics:voicebar/height"); - await bind(c, "itemSpacing", "Metrics:term/gap"); - await bind(c, "paddingLeft", "Metrics:term/inset"); - await bind(c, "paddingRight", "Metrics:term/inset"); - const cancel = await glyphButton("Cancel", "xmark", "×", "Keyboard:kb/legend", "Metrics:opacity/term-cancel"); - cancel.name = "Cancel"; - const cancelInstance = cancel.createInstance(); - cancel.remove(); - c.appendChild(cancelInstance); - const field = figma.createFrame(); - field.name = "Field"; - field.layoutMode = "HORIZONTAL"; - field.counterAxisAlignItems = "CENTER"; - field.primaryAxisSizingMode = "FIXED"; - field.counterAxisSizingMode = "FIXED"; - field.resize(100, metric("term/height")); - await bind(field, "height", "Metrics:term/height"); - await bind(field, "paddingLeft", "Metrics:term/pad"); - await bind(field, "paddingRight", "Metrics:term/pad"); - field.fills = [await paint("Keyboard:kb/key-modifier")]; - field.cornerRadius = metric("term/height") / 2; // a capsule: half the height - const draft = await textNode("Rizz", { styleId: await textStyleId("Term/Text"), fillRef: "Keyboard:kb/legend" }); - draft.name = "Draft"; - field.appendChild(draft); - const caret = figma.createRectangle(); - caret.name = "Caret"; - caret.resize(metric("caret/width"), metric("caret/height")); - await bind(caret, "width", "Metrics:caret/width"); - await bind(caret, "height", "Metrics:caret/height"); - await bindRadius(caret, "Metrics:caret/radius"); - caret.fills = [await paint("Keyboard:kb/signal")]; - field.appendChild(caret); - c.appendChild(field); - field.layoutSizingHorizontal = "FILL"; - const save = await glyphButton("Save", "checkmark", "✓", "Keyboard:kb/signal", null); - const saveInstance = save.createInstance(); - save.remove(); - c.appendChild(saveInstance); - const draftProp = c.addComponentProperty("Draft", "TEXT", "Rizz"); - draft.componentPropertyReferences = { characters: draftProp }; - replaceNamed(page, "TermField", c); - page.appendChild(c); - c.x = x; - c.y = y; - return c; -} - -async function buildOrbRing(page, x, y) { - const variants = []; - for (const [size, ref] of Object.entries(SIZES)) { - for (const kind of ["Still", "Working", "Ok", "Error"]) { - const c = figma.createComponent(); - c.name = `Kind=${kind}, Size=${size}`; - const d = metric(ref); - c.resize(d, d); - c.fills = []; - const ring = figma.createEllipse(); - ring.name = "Ring"; - ring.resize(d, d); - ring.fills = []; - ring.strokeAlign = "INSIDE"; - if (kind === "Ok" || kind === "Error") { - ring.strokes = [await paint(kind === "Ok" ? "Keyboard:kb/notice-ok" : "Keyboard:kb/notice-error")]; - } else { - ring.strokes = [gradientPaint("orb-ring")]; - } - await bind(ring, "strokeWeight", kind === "Still" ? "Metrics:ring/still" : "Metrics:ring/active"); - c.appendChild(ring); - await bind(c, "width", `Metrics:${ref}`); - await bind(c, "height", `Metrics:${ref}`); - variants.push(c); - } - } - replaceNamed(page, "Orb/Ring", variants[0]); - const set = finishSet(page, "Orb/Ring", variants, x, y); - set.description = "The hairline ring round the orb: green into white, 1 pt at rest and 2 pt while working (it sweeps one turn per 1.6 s); solid green for pasted and copied, orange for an error."; - return set; -} - -/** An orb still the app rendered, if one has been placed in the file. */ -function orbStill(page, size, mood) { - const node = page.findOne((n) => n.name === `orb-still/${size}-${mood}`.toLowerCase()); - if (!node || !("fills" in node)) return null; - const fill = node.fills.find((f) => f.type === "IMAGE"); - return fill ? fill.imageHash : null; -} - -async function buildOrbDisc(page, x, y) { - const variants = []; - let images = 0; - for (const [size, ref] of Object.entries(SIZES)) { - for (const mood of ["Off", "Idle", "Listening", "Working", "Landed"]) { - const c = figma.createComponent(); - c.name = `Size=${size}, Mood=${mood}`; - const d = metric(ref); - c.resize(d, d); - c.fills = []; - const disc = figma.createEllipse(); - disc.name = "Disc"; - disc.resize(d, d); - const hash = orbStill(page, size, mood === "Off" ? "Idle" : mood); - if (hash) { - disc.fills = [{ type: "IMAGE", imageHash: hash, scaleMode: "FILL" }]; - images += 1; - } else { - disc.fills = [gradientPaint("orb")]; - } - if (mood === "Off") { - await bind(disc, "opacity", "Metrics:opacity/dim"); - } - c.appendChild(disc); - await bind(c, "width", `Metrics:${ref}`); - await bind(c, "height", `Metrics:${ref}`); - variants.push(c); - } - } - replaceNamed(page, "Orb/Disc", variants[0]); - const set = finishSet(page, "Orb/Disc", variants, x, y); - set.description = - "The orb's fill. A still the app renders (-BlurtOrb , placed here as orb-still/-); the brand gradient stands in until one is. Off is Idle dimmed."; - return { set, images }; -} - -async function buildWaveformMeter(page, x, y) { - const variants = []; - for (const [size, [wRef, hRef]] of Object.entries(WAVES)) { - const c = figma.createComponent(); - c.name = `Size=${size}`; - const w = metric(wRef); - const h = metric(hRef); - c.resize(w, h); - c.fills = []; - c.layoutMode = "HORIZONTAL"; - c.primaryAxisAlignItems = "CENTER"; - c.counterAxisAlignItems = "CENTER"; - c.primaryAxisSizingMode = "FIXED"; - c.counterAxisSizingMode = "FIXED"; - await bind(c, "itemSpacing", "Metrics:wave/gap"); - await bind(c, "width", `Metrics:${wRef}`); - await bind(c, "height", `Metrics:${hRef}`); - const bar = metric("wave/bar"); - const gap = metric("wave/gap"); - const count = Math.floor((w + gap) / (bar + gap)); - const level = 0.62; - for (let i = 0; i < count; i += 1) { - const t = i / Math.max(count - 1, 1); - // A schematic of the engine's envelope: a soft hump, minimum 12 %, at the gallery's level. - const envelope = 0.12 + 0.88 * level * Math.pow(Math.sin(Math.PI * t), 0.45); - const capsule = figma.createRectangle(); - capsule.name = "Bar"; - capsule.resize(bar, Math.max(bar, h * envelope)); - capsule.cornerRadius = bar / 2; - await bind(capsule, "width", "Metrics:wave/bar"); - capsule.fills = [await paint("Keyboard:kb/signal")]; - c.appendChild(capsule); - } - variants.push(c); - } - replaceNamed(page, "WaveformMeter", variants[0]); - const set = finishSet(page, "WaveformMeter", variants, x, y); - set.description = - "The thin wave: 2 pt bars 2 pt apart, flat on the surface, no container. Heights are the engine's (MeterBarGeometry); this is the schematic at level 0.62 — fidelity frames use app captures."; - return set; -} - -const MIC_STATES = ["Off", "Idle", "Working", "Recording", "Pasted", "Copied", "Error"]; - -async function buildMicKey(page, x, y) { - const disc = await findComponentSet(page, "Orb/Disc"); - const ring = await findComponentSet(page, "Orb/Ring"); - const meter = await findComponentSet(page, "WaveformMeter"); - if (!disc || !ring || !meter) throw new Error("build Orb/Disc, Orb/Ring and WaveformMeter first"); - const pick = (set, props) => - set.children.find((c) => Object.entries(props).every(([k, v]) => c.name.includes(`${k}=${v}`))); - const variants = []; - for (const [size, ref] of Object.entries(SIZES)) { - for (const state of MIC_STATES) { - const c = figma.createComponent(); - c.name = `Size=${size}, State=${state}`; - const d = metric(ref); - const [wRef] = WAVES[size]; - c.resize(Math.max(metric(wRef), d), d); - c.fills = []; - c.layoutMode = "HORIZONTAL"; - c.primaryAxisAlignItems = "CENTER"; - c.counterAxisAlignItems = "CENTER"; - c.primaryAxisSizingMode = "FIXED"; - c.counterAxisSizingMode = "FIXED"; - await bind(c, "height", `Metrics:${ref}`); - if (state === "Recording") { - c.appendChild(pick(meter, { Size: size }).createInstance()); - } else { - const stack = figma.createFrame(); - stack.name = "Orb"; - stack.resize(d, d); - stack.fills = []; - stack.clipsContent = false; - const mood = { Off: "Off", Idle: "Idle", Working: "Working", Pasted: "Landed", Copied: "Idle", Error: "Idle" }[state]; - const kind = { Off: "Still", Idle: "Still", Working: "Working", Pasted: "Ok", Copied: "Ok", Error: "Error" }[state]; - const discInstance = pick(disc, { Size: size, Mood: mood }).createInstance(); - discInstance.name = "Disc"; - stack.appendChild(discInstance); - const ringInstance = pick(ring, { Size: size, Kind: kind }).createInstance(); - ringInstance.name = "Ring"; - stack.appendChild(ringInstance); - if (state === "Copied" || state === "Error") { - const glyph = await textNode( - state === "Copied" ? symbolChar("doc.on.clipboard", "⎘") : symbolChar("exclamationmark", "!"), - { size: d * token("Typography", "ratio/orb-glyph").value, weight: FONT.semibold } - ); - glyph.name = "Glyph"; - glyph.fills = [{ type: "SOLID", color: { r: 1, g: 1, b: 1 } }]; - stack.appendChild(glyph); - glyph.x = (d - glyph.width) / 2; - glyph.y = (d - glyph.height) / 2; - } - if (state === "Off") await bind(stack, "opacity", "Metrics:opacity/dim"); - c.appendChild(stack); - } - variants.push(c); - } - } - replaceNamed(page, "MicKey", variants[0]); - const set = finishSet(page, "MicKey", variants, x, y); - set.description = - "The mic key is the orb, and it says everything without a word: dimmed when Blurt isn't ready; ring sweeping while connecting and transcribing; dissipated into the wave while recording; a green ring when the words landed (with the drop), a clipboard on green when they went to the clipboard, orange and ! for an error."; - return set; -} - -async function buildVoiceBar(page, x, y) { - const mic = await findComponentSet(page, "MicKey"); - const addTerm = await findComponentSet(page, "AddTermKey"); - const termField = await findComponent(page, "TermField"); - if (!mic || !addTerm || !termField) throw new Error("build MicKey, AddTermKey and TermField first"); - const pick = (set, props) => - set.children.find((c) => Object.entries(props).every(([k, v]) => c.name.includes(`${k}=${v}`))); - const variants = []; - for (const mode of ["Orb", "Wave", "Term", "NoFullAccess"]) { - const c = figma.createComponent(); - c.name = `Mode=${mode}`; - c.layoutMode = "HORIZONTAL"; - c.primaryAxisAlignItems = mode === "NoFullAccess" ? "MIN" : "CENTER"; - c.counterAxisAlignItems = "CENTER"; - c.primaryAxisSizingMode = "FIXED"; - c.counterAxisSizingMode = "FIXED"; - c.resize(DEVICE_WIDTH - 2 * metric("margin/side"), metric("voicebar/height")); - await bind(c, "height", "Metrics:voicebar/height"); - c.fills = []; - c.clipsContent = false; - if (mode === "Term") { - const f = termField.createInstance(); - c.appendChild(f); - f.layoutSizingHorizontal = "FILL"; - } else if (mode === "NoFullAccess") { - await bind(c, "itemSpacing", "Metrics:voicebar/note-gap"); - c.appendChild(pick(mic, { Size: "Bar", State: "Off" }).createInstance()); - const note = await textNode("Allow Full Access in Settings → Keyboards", { - size: 13, - fillRef: "Keyboard:kb/full-access-note", - }); - note.name = "Note"; - c.appendChild(note); - } else { - c.appendChild(pick(mic, { Size: "Bar", State: mode === "Wave" ? "Recording" : "Idle" }).createInstance()); - const plus = pick(addTerm, { Saved: "False" }).createInstance(); - c.appendChild(plus); - plus.layoutPositioning = "ABSOLUTE"; - plus.constraints = { horizontal: "MAX", vertical: "CENTER" }; - plus.x = c.width - plus.width; - plus.y = (c.height - plus.height) / 2; - } - variants.push(c); - } - replaceNamed(page, "VoiceBar", variants[0]); - const set = finishSet(page, "VoiceBar", variants, x, y); - set.description = - "The keyboard's voice row, and the only place voice lives: the orb (the mic key) dissipating into the wave while recording; the + for a key term; the field the keys type into; the one line of words, without Full Access."; - return set; -} - -async function buildComponents() { - const page = await getPage(PAGES.components); - VARS = await variableMap(); - await loadFonts(); - const built = {}; - let y = 0; - const step = 360; - built.key = (await buildKeySet(page, 0, y)).id; - built.letterKey = (await buildLetterKeySet(page, 0, (y += step))).id; - built.addTermKey = (await buildAddTermKey(page, 0, (y += step))).id; - built.cancelKey = (await buildCancelKey(page, 400, y)).id; - built.termField = (await buildTermField(page, 0, (y += step))).id; - built.orbRing = (await buildOrbRing(page, 0, (y += step))).id; - const disc = await buildOrbDisc(page, 0, (y += step)); - built.orbDisc = disc.set.id; - built.orbStillsUsed = disc.images; - built.waveformMeter = (await buildWaveformMeter(page, 0, (y += step))).id; - built.micKey = (await buildMicKey(page, 0, (y += step))).id; - built.voiceBar = (await buildVoiceBar(page, 0, (y += step))).id; - return { page: page.id, built }; -} - -// --------------------------------------------------------------------------- -// Layouts (03 Layouts): the three keyboards as frames of instances, one per -// state, named exactly as the gallery captions them (//) - -const STATE_TO_MIC = { - off: "Off", - start: "Off", - idle: "Idle", - connecting: "Working", - recording: "Recording", - processing: "Working", - pasted: "Pasted", - copied: "Copied", - error: "Error", - landed: "Pasted", -}; - -async function layoutRoot(name, height) { - const f = figma.createFrame(); - f.name = name; - f.layoutMode = "VERTICAL"; - f.primaryAxisSizingMode = "FIXED"; - f.counterAxisSizingMode = "FIXED"; - f.resize(DEVICE_WIDTH, height); - f.fills = [await paint("Keyboard:kb/surface")]; - f.clipsContent = true; - await bind(f, "paddingLeft", "Metrics:margin/side"); - await bind(f, "paddingRight", "Metrics:margin/side"); - await bind(f, "paddingTop", "Metrics:margin/vertical"); - await bind(f, "paddingBottom", "Metrics:margin/vertical"); - return f; -} - -async function keyInstance(sets, tone, label, widthRef) { - const variant = sets.key.children.find((c) => c.name.includes(`Tone=${tone}`) && c.name.includes("State=Up")); - const i = variant.createInstance(); - const labelKey = Object.keys(i.componentProperties).find((k) => k.startsWith("Label")); - i.setProperties({ [labelKey]: label }); - i.name = label === "space" ? "space" : `key ${label}`; - if (widthRef) { - i.layoutSizingHorizontal = "FIXED"; - i.resize(metric(widthRef), i.height); - await bind(i, "width", `Metrics:${widthRef}`); - } - return i; -} - -async function bottomRow(sets, parent, { withSymbols }) { - const row = autoLayout("HORIZONTAL", { name: "bottom row" }); - await bind(row, "itemSpacing", "Metrics:key/gap"); - row.counterAxisAlignItems = "CENTER"; - parent.appendChild(row); - row.layoutSizingHorizontal = "FILL"; - if (withSymbols) row.appendChild(await keyInstance(sets, "Modifier", "123", "key/side-width-402")); - row.appendChild(await keyInstance(sets, "Modifier", symbolChar("globe", "🌐"), withSymbols ? "key/side-width-402" : null)); - const space = await keyInstance(sets, "Key", "space", null); - row.appendChild(space); - space.layoutSizingHorizontal = "FILL"; - if (!withSymbols) row.appendChild(await keyInstance(sets, "Modifier", symbolChar("delete.left", "⌫"), null)); - row.appendChild( - await keyInstance(sets, "Modifier", symbolChar("return", "↩"), withSymbols ? "key/return-width-402" : null) - ); - return row; -} - -async function buildPanelFrame(sets, state, theme) { - const f = await layoutRoot(`panel/${state}/${theme}`, metric("layout/panel")); - await bind(f, "itemSpacing", "Metrics:panel/spacing"); - const voice = autoLayout("VERTICAL", { name: "voice" }); - voice.primaryAxisAlignItems = "CENTER"; - voice.counterAxisAlignItems = "CENTER"; - f.appendChild(voice); - voice.layoutSizingHorizontal = "FILL"; - voice.layoutSizingVertical = "FILL"; - const mic = sets.micKey.children - .find((c) => c.name.includes("Size=Panel") && c.name.includes(`State=${STATE_TO_MIC[state] || "Idle"}`)) - .createInstance(); - mic.name = "MicKey"; - voice.appendChild(mic); - await bottomRow(sets, f, { withSymbols: false }); - const plus = sets.addTermKey.children.find((c) => c.name.includes("Saved=False")).createInstance(); - plus.name = "AddTermKey"; - f.appendChild(plus); - plus.layoutPositioning = "ABSOLUTE"; - plus.x = metric("addterm/inset"); - plus.y = metric("addterm/inset"); - if (["connecting", "recording", "processing"].includes(state)) { - const cancel = sets.cancelKey.createInstance(); - cancel.name = "CancelKey"; - f.appendChild(cancel); - cancel.layoutPositioning = "ABSOLUTE"; - cancel.constraints = { horizontal: "MAX", vertical: "MIN" }; - cancel.x = DEVICE_WIDTH - metric("margin/side") - cancel.width; - cancel.y = metric("margin/vertical"); - } - return f; -} - -async function voiceBarInstance(sets, state, hasFullAccess) { - const mode = !hasFullAccess ? "NoFullAccess" : state === "term" ? "Term" : state === "recording" ? "Wave" : "Orb"; - const i = sets.voiceBar.children.find((c) => c.name.includes(`Mode=${mode}`)).createInstance(); - i.name = "VoiceBar"; - if (mode === "Orb") { - const mic = i.findOne((n) => n.type === "INSTANCE" && n.name.startsWith("Size=Bar")); - if (mic) { - const target = sets.micKey.children.find( - (c) => c.name.includes("Size=Bar") && c.name.includes(`State=${STATE_TO_MIC[state] || "Idle"}`) - ); - if (target) mic.swapComponent(target); - } - } - return i; -} - -async function buildSlimBarFrame(sets, state, theme) { - const f = await layoutRoot(`slimBar/${state}/${theme}`, metric("layout/slim")); - const row = autoLayout("HORIZONTAL", { name: "row" }); - await bind(row, "itemSpacing", "Metrics:slim/spacing"); - row.counterAxisAlignItems = "CENTER"; - f.appendChild(row); - row.layoutSizingHorizontal = "FILL"; - row.appendChild(await keyInstance(sets, "Modifier", symbolChar("globe", "🌐"), null)); - const bar = await voiceBarInstance(sets, state, state !== "off"); - row.appendChild(bar); - bar.layoutSizingHorizontal = "FILL"; - row.appendChild(await keyInstance(sets, "Modifier", symbolChar("delete.left", "⌫"), null)); - row.appendChild(await keyInstance(sets, "Modifier", symbolChar("return", "↩"), null)); - return f; -} - -async function buildFullFrame(sets, state, theme) { - const f = await layoutRoot(`full/${state}/${theme}`, metric("layout/full")); - await bind(f, "itemSpacing", "Metrics:row/gap"); - const bar = await voiceBarInstance(sets, state, state !== "off"); - f.appendChild(bar); - bar.layoutSizingHorizontal = "FILL"; - const rows = ["qwertyuiop", "asdfghjkl", "zxcvbnm"]; - const letter = (ch) => { - const v = sets.letterKey.children.find((c) => c.name.includes("State=Up")).createInstance(); - const labelKey = Object.keys(v.componentProperties).find((k) => k.startsWith("Label")); - v.setProperties({ [labelKey]: ch }); - v.name = `key ${ch}`; - return v; - }; - for (const [index, letters] of rows.entries()) { - const row = autoLayout("HORIZONTAL", { name: `row ${index + 1}` }); - row.primaryAxisAlignItems = "CENTER"; - row.counterAxisAlignItems = "CENTER"; - f.appendChild(row); - row.layoutSizingHorizontal = "FILL"; - if (index === 2) { - row.itemSpacing = metric("key/gap") * metric("key/side-gap-factor"); - row.appendChild(await keyInstance(sets, "Modifier", symbolChar("shift", "⇧"), "key/side-width-402")); - const inner = autoLayout("HORIZONTAL", { name: "letters" }); - await bind(inner, "itemSpacing", "Metrics:key/gap"); - row.appendChild(inner); - for (const ch of letters) inner.appendChild(letter(ch)); - row.appendChild(await keyInstance(sets, "Modifier", symbolChar("delete.left", "⌫"), "key/side-width-402")); - } else { - await bind(row, "itemSpacing", "Metrics:key/gap"); - for (const ch of letters) row.appendChild(letter(ch)); - } - } - await bottomRow(sets, f, { withSymbols: true }); - return f; -} - -async function buildLayouts() { - const components = await getPage(PAGES.components); - const sets = { - key: await findComponentSet(components, "Key"), - letterKey: await findComponentSet(components, "LetterKey"), - addTermKey: await findComponentSet(components, "AddTermKey"), - cancelKey: await findComponent(components, "CancelKey"), - micKey: await findComponentSet(components, "MicKey"), - voiceBar: await findComponentSet(components, "VoiceBar"), - }; - for (const [name, set] of Object.entries(sets)) if (!set) throw new Error(`component ${name} missing — run buildComponents first`); - const page = await getPage(PAGES.layouts); - VARS = await variableMap(); - await loadFonts(); - const builders = { Panel: buildPanelFrame, SlimBar: buildSlimBarFrame, Full: buildFullFrame }; - const built = {}; - let sectionX = 0; - for (const [name, build] of Object.entries(builders)) { - const section = getSection(page, name, sectionX, 0); - for (const child of [...section.children]) child.remove(); - const states = name === "Panel" ? STATES.filter((s) => s !== "term") : STATES; - let y = 40; - const ids = []; - for (const state of states) { - const caption = await textNode(`${name.charAt(0).toLowerCase() + name.slice(1)} · ${state} · ${DESIGN_THEME}`, { - size: 11, - weight: FONT.medium, - fillRef: "Brand:ink", - }); - section.appendChild(caption); - caption.x = 40; - caption.y = y; - y += 20; - const frame = await build(sets, state, DESIGN_THEME); - section.appendChild(frame); - frame.x = 40; - frame.y = y; - y += frame.height + 40; - ids.push(frame.id); - } - section.resizeWithoutConstraints(DEVICE_WIDTH + 80, y); - built[name] = ids; - sectionX += DEVICE_WIDTH + 160; - } - return { page: page.id, built }; -} - -// --------------------------------------------------------------------------- -// Themes: kb/* re-aliased to each theme's set in turn, the idle frames -// exported at 3× and placed as images, then ink restored. This is -// KeyboardPalette.resolve(_:dark:) in Figma — a Starter file has one mode. - -async function setDesignTheme(theme) { - VARS = await variableMap(); - const keyboard = (await figma.variables.getLocalVariableCollectionsAsync()).find((c) => c.name === "Keyboard"); - const modeId = keyboard.modes[0].modeId; - for (const role of ROLES) { - const kb = VARS.get(`Keyboard:kb/${role}`); - const target = VARS.get(`Themes:${theme}/${role}`); - if (!kb || !target) throw new Error(`no variable for kb/${role} → ${theme}`); - kb.setValueForMode(modeId, figma.variables.createVariableAlias(target)); - } -} - -async function themeSheet() { - const page = await getPage(PAGES.layouts); - const sheet = getSection(page, "Theme sheet", 3 * (DEVICE_WIDTH + 160), 0); - for (const child of [...sheet.children]) child.remove(); - const idle = page.findAll((n) => n.type === "FRAME" && /^(panel|slimBar|full)\/idle\//.test(n.name)); - if (idle.length === 0) throw new Error("no idle layout frames — run buildLayouts first"); - const placed = []; - let y = 40; - try { - for (const theme of THEMES) { - await setDesignTheme(theme); - let x = 40; - let rowHeight = 0; - for (const frame of idle) { - const bytes = await frame.exportAsync({ format: "PNG", constraint: { type: "SCALE", value: 3 } }); - const image = figma.createImage(bytes); - const rect = figma.createRectangle(); - rect.name = frame.name.replace(`/${DESIGN_THEME}`, `/${theme}`); - rect.resize(frame.width, frame.height); - rect.fills = [{ type: "IMAGE", imageHash: image.hash, scaleMode: "FILL" }]; - sheet.appendChild(rect); - rect.x = x; - rect.y = y; - x += frame.width + 40; - rowHeight = Math.max(rowHeight, frame.height); - placed.push(rect.id); - } - y += rowHeight + 60; - } - } finally { - await setDesignTheme(DESIGN_THEME); - } - sheet.resizeWithoutConstraints(idle.reduce((w, f) => w + f.width + 40, 40), y); - return { sheet: sheet.id, placed: placed.length, themes: THEMES.length }; -} - -/** Bounds of whatever was pasted from Apple's kit under "Apple reference". */ -async function measureApple() { - const page = await getPage(PAGES.layouts); - const section = page.children.find((n) => n.type === "SECTION" && n.name === "Apple reference"); - if (!section) throw new Error('no "Apple reference" section — paste the iOS 27 Keyboard instances into one'); - const out = {}; - for (const root of section.children) { - const origin = root.absoluteBoundingBox; - out[root.name] = root - .findAll((n) => n.absoluteBoundingBox && n.name) - .map((n) => { - const b = n.absoluteBoundingBox; - const radius = "cornerRadius" in n && typeof n.cornerRadius === "number" ? n.cornerRadius : null; - return { name: n.name, x: +(b.x - origin.x).toFixed(2), y: +(b.y - origin.y).toFixed(2), w: +b.width.toFixed(2), h: +b.height.toFixed(2), radius }; - }); - } - return out; -} diff --git a/App/BlurtiOS/Design/figma/themes.js b/App/BlurtiOS/Design/figma/themes.js new file mode 100644 index 00000000..a9f12770 --- /dev/null +++ b/App/BlurtiOS/Design/figma/themes.js @@ -0,0 +1,73 @@ +/* global figma, getPage, getSection, variableMap, ensureTokens, DEVICE_WIDTH, DESIGN_THEME, THEMES, ROLES, PAGES, VARS */ +// --------------------------------------------------------------------------- +// Themes: kb/* re-aliased to each theme's set in turn, the idle frames +// exported at 3× and placed as images, then ink restored. This is +// KeyboardPalette.resolve(_:dark:) in Figma — a Starter file has one mode. + +async function setDesignTheme(theme) { + VARS = await variableMap(); + const keyboard = (await figma.variables.getLocalVariableCollectionsAsync()).find((c) => c.name === "Keyboard"); + const modeId = keyboard.modes[0].modeId; + for (const role of ROLES) { + const kb = VARS.get(`Keyboard:kb/${role}`); + const target = VARS.get(`Themes:${theme}/${role}`); + if (!kb || !target) throw new Error(`no variable for kb/${role} → ${theme}`); + kb.setValueForMode(modeId, figma.variables.createVariableAlias(target)); + } +} + +async function themeSheet() { + await ensureTokens(); + const page = await getPage(PAGES.layouts); + const sheet = getSection(page, "Theme sheet", 3 * (DEVICE_WIDTH + 160), 0); + for (const child of [...sheet.children]) child.remove(); + const idle = page.findAll((n) => n.type === "FRAME" && /^(panel|slimBar|full)\/idle\//.test(n.name)); + if (idle.length === 0) throw new Error("no idle layout frames — run buildLayouts first"); + const placed = []; + let y = 40; + try { + for (const theme of THEMES) { + await setDesignTheme(theme); + let x = 40; + let rowHeight = 0; + for (const frame of idle) { + const bytes = await frame.exportAsync({ format: "PNG", constraint: { type: "SCALE", value: 3 } }); + const image = figma.createImage(bytes); + const rect = figma.createRectangle(); + rect.name = frame.name.replace(`/${DESIGN_THEME}`, `/${theme}`); + rect.resize(frame.width, frame.height); + rect.fills = [{ type: "IMAGE", imageHash: image.hash, scaleMode: "FILL" }]; + sheet.appendChild(rect); + rect.x = x; + rect.y = y; + x += frame.width + 40; + rowHeight = Math.max(rowHeight, frame.height); + placed.push(rect.id); + } + y += rowHeight + 60; + } + } finally { + await setDesignTheme(DESIGN_THEME); + } + sheet.resizeWithoutConstraints(idle.reduce((w, f) => w + f.width + 40, 40), y); + return { sheet: sheet.id, placed: placed.length, themes: THEMES.length }; +} + +/** Bounds of whatever was pasted from Apple's kit under "Apple reference". */ +async function measureApple() { + const page = await getPage(PAGES.layouts); + const section = page.children.find((n) => n.type === "SECTION" && n.name === "Apple reference"); + if (!section) throw new Error('no "Apple reference" section — paste the iOS 27 Keyboard instances into one'); + const out = {}; + for (const root of section.children) { + const origin = root.absoluteBoundingBox; + out[root.name] = root + .findAll((n) => n.absoluteBoundingBox && n.name) + .map((n) => { + const b = n.absoluteBoundingBox; + const radius = "cornerRadius" in n && typeof n.cornerRadius === "number" ? n.cornerRadius : null; + return { name: n.name, x: +(b.x - origin.x).toFixed(2), y: +(b.y - origin.y).toFixed(2), w: +b.width.toFixed(2), h: +b.height.toFixed(2), radius }; + }); + } + return out; +} diff --git a/App/BlurtiOS/Design/figma/tokens.js b/App/BlurtiOS/Design/figma/tokens.js index fb1b9e9a..11433887 100644 --- a/App/BlurtiOS/Design/figma/tokens.js +++ b/App/BlurtiOS/Design/figma/tokens.js @@ -1,2072 +1,197 @@ // Generated by scripts/design-tokens.swift from App/BlurtiOS/Design/tokens.json — do not edit. -// The build scripts in this folder (lib.js) read this; a use_figma call is -// tokens.js + lib.js + one line that returns a builder's result. -const TOKENS = { - "collections" : { - "Brand" : { - "mode" : "Value", - "variables" : [ - { - "codeSyntax" : "DesignTokens.Brand.appleDarkKey", - "name" : "apple\/dark-key", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "the iPhone keyboard's dark key", - "value" : "#6B6B6B" - }, - { - "codeSyntax" : "DesignTokens.Brand.appleDarkModifier", - "name" : "apple\/dark-modifier", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "the iPhone keyboard's dark modifier key", - "value" : "#464646" - }, - { - "codeSyntax" : "DesignTokens.Brand.appleDarkSurface", - "name" : "apple\/dark-surface", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "the iPhone keyboard's dark surface", - "value" : "#2B2B2B" - }, - { - "codeSyntax" : "DesignTokens.Brand.appleLightModifier", - "name" : "apple\/light-modifier", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "the iPhone keyboard's light modifier key", - "value" : "#ADB3BC" - }, - { - "codeSyntax" : "DesignTokens.Brand.appleLightSurface", - "name" : "apple\/light-surface", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "the iPhone keyboard's light surface", - "value" : "#D1D5DB" - }, - { - "codeSyntax" : "DesignTokens.Brand.black", - "name" : "black", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#000000" - }, - { - "codeSyntax" : "DesignTokens.Brand.card", - "name" : "card", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "the warm card fill; the paper theme's surface", - "value" : "#EBE8E8" - }, - { - "codeSyntax" : "DesignTokens.Brand.cardBorder", - "name" : "card-border", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "the card's hairline; the paper theme's modifier key", - "value" : "#DEDBDB" - }, - { - "codeSyntax" : "DesignTokens.Brand.cobolt", - "name" : "cobolt", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "AssemblyAI's primary violet: the drop, never a key or a surface", - "value" : "#3923C7" - }, - { - "codeSyntax" : "DesignTokens.Brand.green100", - "name" : "green\/100", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "the design system's UI-and-code green fill (unused on the phone yet)", - "value" : "#CCE4D5" - }, - { - "codeSyntax" : "DesignTokens.Brand.green200", - "name" : "green\/200", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "the design system's UI-and-code green highlight (unused on the phone yet)", - "value" : "#99C8AC" - }, - { - "codeSyntax" : "DesignTokens.Brand.green400", - "name" : "green\/400", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "the brand hue lifted for dark chrome: the meter, the ring, the wave on ink", - "value" : "#67AD82" - }, - { - "codeSyntax" : "DesignTokens.Brand.green700", - "name" : "green\/700", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "the wordmark green, light chrome (the app's accent in light)", - "value" : "#01762F" - }, - { - "codeSyntax" : "DesignTokens.Brand.greenMist", - "name" : "green\/mist", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "the pale green the orb lightens into", - "value" : "#DBF5E6" - }, - { - "codeSyntax" : "DesignTokens.Brand.ink", - "name" : "ink", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "the brand ink: the Mac pill's body, the ink theme's surface", - "value" : "#1D1B16" - }, - { - "codeSyntax" : "DesignTokens.Brand.ink600", - "name" : "ink\/600", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "the Mac's dark card border", - "value" : "#3A362F" - }, - { - "codeSyntax" : "DesignTokens.Brand.ink700", - "name" : "ink\/700", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "an ordinary key on ink, one step up", - "value" : "#33302A" - }, - { - "codeSyntax" : "DesignTokens.Brand.ink800", - "name" : "ink\/800", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "a modifier key on ink; the Mac's dark card fill", - "value" : "#26231E" - }, - { - "codeSyntax" : "DesignTokens.Brand.orange", - "name" : "orange", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "the error word and ring, cancel, the Full Access note; never a red body", - "value" : "#E67F36" - }, - { - "codeSyntax" : "DesignTokens.Brand.page", - "name" : "page", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "the design system's page background (unused on the phone)", - "value" : "#FDFCF8" - }, - { - "codeSyntax" : "DesignTokens.Brand.violetIris", - "name" : "violet\/iris", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "the orb gradient's upper violet stop", - "value" : "#887BDD" - }, - { - "codeSyntax" : "DesignTokens.Brand.violetLavender", - "name" : "violet\/lavender", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "the orb's lightest violet: its top and the gradient's ends", - "value" : "#D7D3F4" - }, - { - "codeSyntax" : "DesignTokens.Brand.violetPeriwinkle", - "name" : "violet\/periwinkle", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "the orb's mid violet: the drop's halo", - "value" : "#B0A7E9" - }, - { - "codeSyntax" : "DesignTokens.Brand.warmWhite", - "name" : "warm-white", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "key legends on ink: warm white on warm ink", - "value" : "#F2EEE6" - }, - { - "codeSyntax" : "DesignTokens.Brand.white", - "name" : "white", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#FFFFFF" - } - ] - }, - "Keyboard" : { - "mode" : "Value", - "variables" : [ - { - "alias" : "Brand:green\/400", - "codeSyntax" : "DesignTokens.Keyboard.appAccentDark", - "name" : "app\/accent-dark", - "scopes" : [ - "FRAME_FILL", - "SHAPE_FILL" - ], - "type" : "COLOR", - "use" : "the catalog's AccentColor in dark", - "value" : "#67AD82" - }, - { - "alias" : "Brand:green\/700", - "codeSyntax" : "DesignTokens.Keyboard.appAccentLight", - "name" : "app\/accent-light", - "scopes" : [ - "FRAME_FILL", - "SHAPE_FILL" - ], - "type" : "COLOR", - "use" : "the catalog's AccentColor in light", - "value" : "#01762F" - }, - { - "alias" : "Brand:ink\/600", - "codeSyntax" : "DesignTokens.Keyboard.appCardBorderDark", - "name" : "app\/card-border-dark", - "scopes" : [ - "STROKE_COLOR" - ], - "type" : "COLOR", - "use" : "the catalog's CardBorder in dark", - "value" : "#3A362F" - }, - { - "alias" : "Brand:card-border", - "codeSyntax" : "DesignTokens.Keyboard.appCardBorderLight", - "name" : "app\/card-border-light", - "scopes" : [ - "STROKE_COLOR" - ], - "type" : "COLOR", - "use" : "the catalog's CardBorder in light", - "value" : "#DEDBDB" - }, - { - "alias" : "Brand:ink\/800", - "codeSyntax" : "DesignTokens.Keyboard.appCardFillDark", - "name" : "app\/card-fill-dark", - "scopes" : [ - "FRAME_FILL", - "SHAPE_FILL" - ], - "type" : "COLOR", - "use" : "the catalog's CardFill in dark", - "value" : "#26231E" - }, - { - "alias" : "Brand:card", - "codeSyntax" : "DesignTokens.Keyboard.appCardFillLight", - "name" : "app\/card-fill-light", - "scopes" : [ - "FRAME_FILL", - "SHAPE_FILL" - ], - "type" : "COLOR", - "use" : "the catalog's CardFill in light", - "value" : "#EBE8E8" - }, - { - "alias" : "Brand:orange", - "codeSyntax" : "DesignTokens.Keyboard.kbCancel", - "name" : "kb\/cancel", - "scopes" : [ - "FRAME_FILL", - "SHAPE_FILL" - ], - "type" : "COLOR", - "use" : "the panel's cancel ×", - "value" : "#E67F36" - }, - { - "alias" : "Brand:orange", - "codeSyntax" : "DesignTokens.Keyboard.kbFullAccessNote", - "name" : "kb\/full-access-note", - "scopes" : [ - "TEXT_FILL" - ], - "type" : "COLOR", - "use" : "the one line of words the keyboard ever shows", - "value" : "#E67F36" - }, - { - "alias" : "Themes:ink\/key", - "codeSyntax" : "DesignTokens.Keyboard.kbKey", - "name" : "kb\/key", - "scopes" : [ - "FRAME_FILL", - "SHAPE_FILL" - ], - "type" : "COLOR", - "use" : "an ordinary key", - "value" : "#33302A" - }, - { - "alias" : "Themes:ink\/key-modifier", - "codeSyntax" : "DesignTokens.Keyboard.kbKeyModifier", - "name" : "kb\/key-modifier", - "scopes" : [ - "FRAME_FILL", - "SHAPE_FILL" - ], - "type" : "COLOR", - "use" : "shift, delete, globe, return, 123, cancel", - "value" : "#26231E" - }, - { - "alias" : "Themes:ink\/legend", - "codeSyntax" : "DesignTokens.Keyboard.kbLegend", - "name" : "kb\/legend", - "scopes" : [ - "TEXT_FILL" - ], - "type" : "COLOR", - "use" : "key legends and bare glyphs", - "value" : "#F2EEE6" - }, - { - "alias" : "Brand:orange", - "codeSyntax" : "DesignTokens.Keyboard.kbNoticeError", - "name" : "kb\/notice-error", - "scopes" : [ - "STROKE_COLOR" - ], - "type" : "COLOR", - "use" : "the solid ring and glyph for an error", - "value" : "#E67F36" - }, - { - "alias" : "Brand:green\/400", - "codeSyntax" : "DesignTokens.Keyboard.kbNoticeOk", - "name" : "kb\/notice-ok", - "scopes" : [ - "STROKE_COLOR" - ], - "type" : "COLOR", - "use" : "the solid ring for pasted and copied", - "value" : "#67AD82" - }, - { - "alias" : "Brand:white", - "codeSyntax" : "DesignTokens.Keyboard.kbOrbRingEnd", - "name" : "kb\/orb-ring-end", - "scopes" : [ - "STROKE_COLOR" - ], - "type" : "COLOR", - "use" : "the sweeping ring's gradient, bottom-trailing", - "value" : "#FFFFFF" - }, - { - "alias" : "Brand:green\/700", - "codeSyntax" : "DesignTokens.Keyboard.kbOrbRingStart", - "name" : "kb\/orb-ring-start", - "scopes" : [ - "STROKE_COLOR" - ], - "type" : "COLOR", - "use" : "the sweeping ring's gradient, top-leading", - "value" : "#01762F" - }, - { - "alias" : "Themes:ink\/popup", - "codeSyntax" : "DesignTokens.Keyboard.kbPopup", - "name" : "kb\/popup", - "scopes" : [ - "FRAME_FILL", - "SHAPE_FILL" - ], - "type" : "COLOR", - "use" : "the letter pop-up", - "value" : "#33302A" - }, - { - "alias" : "Themes:ink\/signal", - "codeSyntax" : "DesignTokens.Keyboard.kbSignal", - "name" : "kb\/signal", - "scopes" : [ - "SHAPE_FILL", - "TEXT_FILL" - ], - "type" : "COLOR", - "use" : "the wave, the caret, the saved check", - "value" : "#67AD82" - }, - { - "alias" : "Themes:ink\/surface", - "codeSyntax" : "DesignTokens.Keyboard.kbSurface", - "name" : "kb\/surface", - "scopes" : [ - "FRAME_FILL", - "SHAPE_FILL" - ], - "type" : "COLOR", - "use" : "the design theme's surface (Figma binds to kb\/*; Swift reads the palette)", - "value" : "#1D1B16" - } - ] - }, - "Metrics" : { - "mode" : "Value", - "variables" : [ - { - "codeSyntax" : "DesignTokens.Metrics.addtermInset", - "name" : "addterm\/inset", - "scopes" : [ - "GAP" - ], - "type" : "FLOAT", - "use" : "the + from the panel's corner", - "value" : 6 - }, - { - "codeSyntax" : "DesignTokens.Metrics.cardBorder", - "name" : "card\/border", - "scopes" : [ - "STROKE_FLOAT", - "WIDTH_HEIGHT" - ], - "type" : "FLOAT", - "use" : "the card's hairline", - "value" : 1 - }, - { - "codeSyntax" : "DesignTokens.Metrics.cardRadius", - "name" : "card\/radius", - "scopes" : [ - "CORNER_RADIUS" - ], - "type" : "FLOAT", - "use" : "the app's cards", - "value" : 16 - }, - { - "codeSyntax" : "DesignTokens.Metrics.caretHeight", - "name" : "caret\/height", - "scopes" : [ - "WIDTH_HEIGHT" - ], - "type" : "FLOAT", - "use" : "", - "value" : 20 - }, - { - "codeSyntax" : "DesignTokens.Metrics.caretLead", - "name" : "caret\/lead", - "scopes" : [ - "GAP" - ], - "type" : "FLOAT", - "use" : "the caret's gap from the text", - "value" : 1 - }, - { - "codeSyntax" : "DesignTokens.Metrics.caretRadius", - "name" : "caret\/radius", - "scopes" : [ - "CORNER_RADIUS" - ], - "type" : "FLOAT", - "use" : "", - "value" : 1 - }, - { - "codeSyntax" : "DesignTokens.Metrics.caretWidth", - "name" : "caret\/width", - "scopes" : [ - "STROKE_FLOAT", - "WIDTH_HEIGHT" - ], - "type" : "FLOAT", - "use" : "", - "value" : 2 - }, - { - "codeSyntax" : "DesignTokens.Metrics.gestureSwipeMin", - "name" : "gesture\/swipe-min", - "scopes" : [ - - ], - "type" : "FLOAT", - "use" : "the carousel gesture's minimum distance", - "value" : 24 - }, - { - "codeSyntax" : "DesignTokens.Metrics.glyphHit", - "name" : "glyph\/hit", - "scopes" : [ - "WIDTH_HEIGHT" - ], - "type" : "FLOAT", - "use" : "the +, × and ✓ touch targets", - "value" : 32 - }, - { - "codeSyntax" : "DesignTokens.Metrics.keyGap", - "name" : "key\/gap", - "scopes" : [ - "GAP" - ], - "type" : "FLOAT", - "use" : "between keys, the iPhone's", - "value" : 6 - }, - { - "codeSyntax" : "DesignTokens.Metrics.keyHeight", - "name" : "key\/height", - "scopes" : [ - "WIDTH_HEIGHT" - ], - "type" : "FLOAT", - "use" : "every key", - "value" : 42 - }, - { - "codeSyntax" : "DesignTokens.Metrics.keyLetterWidth402", - "name" : "key\/letter-width-402", - "scopes" : [ - "WIDTH_HEIGHT" - ], - "type" : "FLOAT", - "use" : "a letter key at 402 pt (iPhone 18 Pro): (width − 9 × key\/gap) \/ 10", - "value" : 34.799999999999997 - }, - { - "codeSyntax" : "DesignTokens.Metrics.keyMinWidth", - "name" : "key\/min-width", - "scopes" : [ - "WIDTH_HEIGHT" - ], - "type" : "FLOAT", - "use" : "a key that isn't given a width", - "value" : 44 - }, - { - "codeSyntax" : "DesignTokens.Metrics.keyPad", - "name" : "key\/pad", - "scopes" : [ - "GAP" - ], - "type" : "FLOAT", - "use" : "a legend's side padding on a min-width key", - "value" : 4 - }, - { - "codeSyntax" : "DesignTokens.Metrics.keyRadius", - "name" : "key\/radius", - "scopes" : [ - "CORNER_RADIUS" - ], - "type" : "FLOAT", - "use" : "flat keys, one colour at this corner", - "value" : 8 - }, - { - "codeSyntax" : "DesignTokens.Metrics.keyReturnWidth402", - "name" : "key\/return-width-402", - "scopes" : [ - "WIDTH_HEIGHT" - ], - "type" : "FLOAT", - "use" : "return at 402 pt: two side keys and a gap", - "value" : 104.40000000000001 - }, - { - "codeSyntax" : "DesignTokens.Metrics.keySideGapFactor", - "name" : "key\/side-gap-factor", - "scopes" : [ - - ], - "type" : "FLOAT", - "use" : "shift and delete stand this many key gaps from the letters", - "value" : 2 - }, - { - "codeSyntax" : "DesignTokens.Metrics.keySideWidth402", - "name" : "key\/side-width-402", - "scopes" : [ - "WIDTH_HEIGHT" - ], - "type" : "FLOAT", - "use" : "shift, delete, 123 and globe at 402 pt: what seven letters leave, halved", - "value" : 49.200000000000003 - }, - { - "codeSyntax" : "DesignTokens.Metrics.layoutFull", - "name" : "layout\/full", - "scopes" : [ - "WIDTH_HEIGHT" - ], - "type" : "FLOAT", - "use" : "2 × margin\/vertical + voicebar\/height + 4 × row\/gap + 4 × key\/height", - "value" : 272 - }, - { - "codeSyntax" : "DesignTokens.Metrics.layoutPanel", - "name" : "layout\/panel", - "scopes" : [ - "WIDTH_HEIGHT" - ], - "type" : "FLOAT", - "use" : "chosen: room for the 96 orb over one key row", - "value" : 216 - }, - { - "codeSyntax" : "DesignTokens.Metrics.layoutSlim", - "name" : "layout\/slim", - "scopes" : [ - "WIDTH_HEIGHT" - ], - "type" : "FLOAT", - "use" : "2 × margin\/vertical + voicebar\/height", - "value" : 60 - }, - { - "codeSyntax" : "DesignTokens.Metrics.marginSide", - "name" : "margin\/side", - "scopes" : [ - "WIDTH_HEIGHT" - ], - "type" : "FLOAT", - "use" : "at the keyboard's sides", - "value" : 3 - }, - { - "codeSyntax" : "DesignTokens.Metrics.marginVertical", - "name" : "margin\/vertical", - "scopes" : [ - "WIDTH_HEIGHT" - ], - "type" : "FLOAT", - "use" : "the keyboard's top and bottom", - "value" : 8 - }, - { - "codeSyntax" : "DesignTokens.Metrics.opacityDim", - "name" : "opacity\/dim", - "scopes" : [ - "OPACITY" - ], - "type" : "FLOAT", - "use" : "the orb when Blurt isn't ready", - "value" : 0.80000000000000004 - }, - { - "codeSyntax" : "DesignTokens.Metrics.opacityDimSaturation", - "name" : "opacity\/dim-saturation", - "scopes" : [ - "OPACITY" - ], - "type" : "FLOAT", - "use" : "and its saturation", - "value" : 0.34999999999999998 - }, - { - "codeSyntax" : "DesignTokens.Metrics.opacityDisabled", - "name" : "opacity\/disabled", - "scopes" : [ - "OPACITY" - ], - "type" : "FLOAT", - "use" : "the + without Full Access", - "value" : 0.40000000000000002 - }, - { - "codeSyntax" : "DesignTokens.Metrics.opacityGrain", - "name" : "opacity\/grain", - "scopes" : [ - "OPACITY" - ], - "type" : "FLOAT", - "use" : "", - "value" : 0.5 - }, - { - "codeSyntax" : "DesignTokens.Metrics.opacityHomeDimSaturation", - "name" : "opacity\/home-dim-saturation", - "scopes" : [ - "OPACITY" - ], - "type" : "FLOAT", - "use" : "the home hero's saturation when not listening", - "value" : 0.45000000000000001 - }, - { - "codeSyntax" : "DesignTokens.Metrics.opacityLegendMuted", - "name" : "opacity\/legend-muted", - "scopes" : [ - "OPACITY" - ], - "type" : "FLOAT", - "use" : "the + at rest", - "value" : 0.5 - }, - { - "codeSyntax" : "DesignTokens.Metrics.opacityOrbLight", - "name" : "opacity\/orb-light", - "scopes" : [ - "OPACITY" - ], - "type" : "FLOAT", - "use" : "", - "value" : 0.29999999999999999 - }, - { - "codeSyntax" : "DesignTokens.Metrics.opacityPlaceholder", - "name" : "opacity\/placeholder", - "scopes" : [ - "OPACITY" - ], - "type" : "FLOAT", - "use" : "the field's placeholder", - "value" : 0.40000000000000002 - }, - { - "codeSyntax" : "DesignTokens.Metrics.opacityPopupShadow", - "name" : "opacity\/popup-shadow", - "scopes" : [ - "OPACITY" - ], - "type" : "FLOAT", - "use" : "", - "value" : 0.12 - }, - { - "codeSyntax" : "DesignTokens.Metrics.opacityPressBrighten", - "name" : "opacity\/press-brighten", - "scopes" : [ - "OPACITY" - ], - "type" : "FLOAT", - "use" : "a key lightens this much while pressed", - "value" : 0.14999999999999999 - }, - { - "codeSyntax" : "DesignTokens.Metrics.opacityTermCancel", - "name" : "opacity\/term-cancel", - "scopes" : [ - "OPACITY" - ], - "type" : "FLOAT", - "use" : "the field's ×", - "value" : 0.69999999999999996 - }, - { - "codeSyntax" : "DesignTokens.Metrics.orbBar", - "name" : "orb\/bar", - "scopes" : [ - "WIDTH_HEIGHT" - ], - "type" : "FLOAT", - "use" : "the orb in the voice bar", - "value" : 40 - }, - { - "codeSyntax" : "DesignTokens.Metrics.orbDissipateBlur", - "name" : "orb\/dissipate-blur", - "scopes" : [ - - ], - "type" : "FLOAT", - "use" : "and blurs to this fraction of its size", - "value" : 0.16 - }, - { - "codeSyntax" : "DesignTokens.Metrics.orbDissipateScale", - "name" : "orb\/dissipate-scale", - "scopes" : [ - - ], - "type" : "FLOAT", - "use" : "the orb swells to this while dissipating", - "value" : 1.25 - }, - { - "codeSyntax" : "DesignTokens.Metrics.orbHome", - "name" : "orb\/home", - "scopes" : [ - "WIDTH_HEIGHT" - ], - "type" : "FLOAT", - "use" : "the orb on the home screen", - "value" : 112 - }, - { - "codeSyntax" : "DesignTokens.Metrics.orbLightRadius", - "name" : "orb\/light-radius", - "scopes" : [ - - ], - "type" : "FLOAT", - "use" : "the light's reach in points (fixed, not proportional — open)", - "value" : 110 - }, - { - "codeSyntax" : "DesignTokens.Metrics.orbLightX", - "name" : "orb\/light-x", - "scopes" : [ - - ], - "type" : "FLOAT", - "use" : "the soft light's centre, as a fraction of the orb", - "value" : 0.29999999999999999 - }, - { - "codeSyntax" : "DesignTokens.Metrics.orbLightY", - "name" : "orb\/light-y", - "scopes" : [ - - ], - "type" : "FLOAT", - "use" : "", - "value" : 0.22 - }, - { - "codeSyntax" : "DesignTokens.Metrics.orbPanel", - "name" : "orb\/panel", - "scopes" : [ - "WIDTH_HEIGHT" - ], - "type" : "FLOAT", - "use" : "the orb in the panel", - "value" : 96 - }, - { - "codeSyntax" : "DesignTokens.Metrics.panelSpacing", - "name" : "panel\/spacing", - "scopes" : [ - "GAP" - ], - "type" : "FLOAT", - "use" : "between the panel's orb and its key row", - "value" : 12 - }, - { - "codeSyntax" : "DesignTokens.Metrics.pickerPreviewWidth", - "name" : "picker\/preview-width", - "scopes" : [ - "WIDTH_HEIGHT" - ], - "type" : "FLOAT", - "use" : "the theme card draws the keyboard at this width", - "value" : 393 - }, - { - "codeSyntax" : "DesignTokens.Metrics.pickerRadius", - "name" : "picker\/radius", - "scopes" : [ - "CORNER_RADIUS" - ], - "type" : "FLOAT", - "use" : "the theme card's preview corners", - "value" : 10 - }, - { - "codeSyntax" : "DesignTokens.Metrics.pickerScale", - "name" : "picker\/scale", - "scopes" : [ - - ], - "type" : "FLOAT", - "use" : "then scales it to fit two across", - "value" : 0.41999999999999998 - }, - { - "codeSyntax" : "DesignTokens.Metrics.popupExtraWidth", - "name" : "popup\/extra-width", - "scopes" : [ - "WIDTH_HEIGHT" - ], - "type" : "FLOAT", - "use" : "the letter pop-up is the key width plus this", - "value" : 18 - }, - { - "codeSyntax" : "DesignTokens.Metrics.popupHeight", - "name" : "popup\/height", - "scopes" : [ - "WIDTH_HEIGHT" - ], - "type" : "FLOAT", - "use" : "", - "value" : 56 - }, - { - "codeSyntax" : "DesignTokens.Metrics.popupOffset", - "name" : "popup\/offset", - "scopes" : [ - "WIDTH_HEIGHT" - ], - "type" : "FLOAT", - "use" : "the pop-up sits this far above the key", - "value" : 58 - }, - { - "codeSyntax" : "DesignTokens.Metrics.popupRadius", - "name" : "popup\/radius", - "scopes" : [ - "CORNER_RADIUS" - ], - "type" : "FLOAT", - "use" : "", - "value" : 10 - }, - { - "codeSyntax" : "DesignTokens.Metrics.popupShadowRadius", - "name" : "popup\/shadow-radius", - "scopes" : [ - "WIDTH_HEIGHT" - ], - "type" : "FLOAT", - "use" : "the one thing that floats", - "value" : 8 - }, - { - "codeSyntax" : "DesignTokens.Metrics.popupShadowY", - "name" : "popup\/shadow-y", - "scopes" : [ - "WIDTH_HEIGHT" - ], - "type" : "FLOAT", - "use" : "", - "value" : 2 - }, - { - "codeSyntax" : "DesignTokens.Metrics.pressScale", - "name" : "press\/scale", - "scopes" : [ - - ], - "type" : "FLOAT", - "use" : "the orb while pressed", - "value" : 0.93999999999999995 - }, - { - "codeSyntax" : "DesignTokens.Metrics.ringActive", - "name" : "ring\/active", - "scopes" : [ - "STROKE_FLOAT", - "WIDTH_HEIGHT" - ], - "type" : "FLOAT", - "use" : "the ring while working or noticing; the home ring", - "value" : 2 - }, - { - "codeSyntax" : "DesignTokens.Metrics.ringStill", - "name" : "ring\/still", - "scopes" : [ - "STROKE_FLOAT", - "WIDTH_HEIGHT" - ], - "type" : "FLOAT", - "use" : "the ring at rest", - "value" : 1 - }, - { - "codeSyntax" : "DesignTokens.Metrics.rowGap", - "name" : "row\/gap", - "scopes" : [ - "GAP" - ], - "type" : "FLOAT", - "use" : "between rows, the iPhone's", - "value" : 11 - }, - { - "codeSyntax" : "DesignTokens.Metrics.slimSpacing", - "name" : "slim\/spacing", - "scopes" : [ - "GAP" - ], - "type" : "FLOAT", - "use" : "between the slim bar's keys", - "value" : 8 - }, - { - "codeSyntax" : "DesignTokens.Metrics.termGap", - "name" : "term\/gap", - "scopes" : [ - "GAP" - ], - "type" : "FLOAT", - "use" : "× · field · ✓", - "value" : 8 - }, - { - "codeSyntax" : "DesignTokens.Metrics.termHeight", - "name" : "term\/height", - "scopes" : [ - "WIDTH_HEIGHT" - ], - "type" : "FLOAT", - "use" : "the key-term field's capsule", - "value" : 36 - }, - { - "codeSyntax" : "DesignTokens.Metrics.termInset", - "name" : "term\/inset", - "scopes" : [ - "GAP" - ], - "type" : "FLOAT", - "use" : "the field row's side inset", - "value" : 2 - }, - { - "codeSyntax" : "DesignTokens.Metrics.termPad", - "name" : "term\/pad", - "scopes" : [ - "GAP" - ], - "type" : "FLOAT", - "use" : "the field's side padding", - "value" : 14 - }, - { - "codeSyntax" : "DesignTokens.Metrics.voicebarAddtermClearance", - "name" : "voicebar\/addterm-clearance", - "scopes" : [ - "GAP" - ], - "type" : "FLOAT", - "use" : "the wave stays this clear of the + at the trailing edge", - "value" : 12 - }, - { - "codeSyntax" : "DesignTokens.Metrics.voicebarHeight", - "name" : "voicebar\/height", - "scopes" : [ - "WIDTH_HEIGHT" - ], - "type" : "FLOAT", - "use" : "the voice row, where the system puts its suggestion bar", - "value" : 44 - }, - { - "codeSyntax" : "DesignTokens.Metrics.voicebarNoteGap", - "name" : "voicebar\/note-gap", - "scopes" : [ - "GAP" - ], - "type" : "FLOAT", - "use" : "between the orb and the Full Access note", - "value" : 10 - }, - { - "codeSyntax" : "DesignTokens.Metrics.waveBar", - "name" : "wave\/bar", - "scopes" : [ - "STROKE_FLOAT", - "WIDTH_HEIGHT" - ], - "type" : "FLOAT", - "use" : "a wave bar's width", - "value" : 2 - }, - { - "codeSyntax" : "DesignTokens.Metrics.waveBarHeight", - "name" : "wave\/bar-height", - "scopes" : [ - "WIDTH_HEIGHT" - ], - "type" : "FLOAT", - "use" : "", - "value" : 24 - }, - { - "codeSyntax" : "DesignTokens.Metrics.waveBarWidth", - "name" : "wave\/bar-width", - "scopes" : [ - "WIDTH_HEIGHT" - ], - "type" : "FLOAT", - "use" : "the wave in the voice bar, at most", - "value" : 240 - }, - { - "codeSyntax" : "DesignTokens.Metrics.waveGap", - "name" : "wave\/gap", - "scopes" : [ - "GAP" - ], - "type" : "FLOAT", - "use" : "between wave bars", - "value" : 2 - }, - { - "codeSyntax" : "DesignTokens.Metrics.waveHomeHeight", - "name" : "wave\/home-height", - "scopes" : [ - "WIDTH_HEIGHT" - ], - "type" : "FLOAT", - "use" : "", - "value" : 44 - }, - { - "codeSyntax" : "DesignTokens.Metrics.waveHomeWidth", - "name" : "wave\/home-width", - "scopes" : [ - "WIDTH_HEIGHT" - ], - "type" : "FLOAT", - "use" : "", - "value" : 280 - }, - { - "codeSyntax" : "DesignTokens.Metrics.wavePanelHeight", - "name" : "wave\/panel-height", - "scopes" : [ - "WIDTH_HEIGHT" - ], - "type" : "FLOAT", - "use" : "", - "value" : 40 - }, - { - "codeSyntax" : "DesignTokens.Metrics.wavePanelWidth", - "name" : "wave\/panel-width", - "scopes" : [ - "WIDTH_HEIGHT" - ], - "type" : "FLOAT", - "use" : "", - "value" : 300 - }, - { - "codeSyntax" : "DesignTokens.Metrics.wordmarkHeight", - "name" : "wordmark\/height", - "scopes" : [ - "WIDTH_HEIGHT" - ], - "type" : "FLOAT", - "use" : "", - "value" : 22 - } - ] - }, - "Motion" : { - "mode" : "Value", - "variables" : [ - { - "codeSyntax" : "DesignTokens.Motion.caret", - "name" : "caret", - "scopes" : [ - - ], - "type" : "FLOAT", - "use" : "the caret's blink", - "value" : 0.5 - }, - { - "codeSyntax" : "DesignTokens.Motion.drop", - "name" : "drop", - "scopes" : [ - - ], - "type" : "FLOAT", - "use" : "the violet drop is gone by", - "value" : 2.3999999999999999 - }, - { - "codeSyntax" : "DesignTokens.Motion.dropHold", - "name" : "drop-hold", - "scopes" : [ - - ], - "type" : "FLOAT", - "use" : "and held to", - "value" : 0.90000000000000002 - }, - { - "codeSyntax" : "DesignTokens.Motion.dropRise", - "name" : "drop-rise", - "scopes" : [ - - ], - "type" : "FLOAT", - "use" : "the drop is up in", - "value" : 0.5 - }, - { - "codeSyntax" : "DesignTokens.Motion.dropSpread", - "name" : "drop-spread", - "scopes" : [ - - ], - "type" : "FLOAT", - "use" : "the bloom reaches its full spread in", - "value" : 1 - }, - { - "codeSyntax" : "DesignTokens.Motion.flip", - "name" : "flip", - "scopes" : [ - - ], - "type" : "FLOAT", - "use" : "the panel's carousel", - "value" : 0.25 - }, - { - "codeSyntax" : "DesignTokens.Motion.heightChange", - "name" : "height-change", - "scopes" : [ - - ], - "type" : "FLOAT", - "use" : "the keyboard resizing", - "value" : 0.25 - }, - { - "codeSyntax" : "DesignTokens.Motion.keyPress", - "name" : "key-press", - "scopes" : [ - - ], - "type" : "FLOAT", - "use" : "a key lighting", - "value" : 0.080000000000000002 - }, - { - "codeSyntax" : "DesignTokens.Motion.mood", - "name" : "mood", - "scopes" : [ - - ], - "type" : "FLOAT", - "use" : "the orb's colour moving between moods", - "value" : 0.80000000000000004 - }, - { - "codeSyntax" : "DesignTokens.Motion.press", - "name" : "press", - "scopes" : [ - - ], - "type" : "FLOAT", - "use" : "the orb's press; the one thing that answers at once", - "value" : 0.10000000000000001 - }, - { - "codeSyntax" : "DesignTokens.Motion.ringPeriod", - "name" : "ring-period", - "scopes" : [ - - ], - "type" : "FLOAT", - "use" : "one turn of the ring, the Mac's cadence", - "value" : 1.6000000000000001 - }, - { - "codeSyntax" : "DesignTokens.Motion.stateFade", - "name" : "state-fade", - "scopes" : [ - - ], - "type" : "FLOAT", - "use" : "every other change on the key: the ring, a glyph, the dimming", - "value" : 0.5 - }, - { - "codeSyntax" : "DesignTokens.Motion.termSwap", - "name" : "term-swap", - "scopes" : [ - - ], - "type" : "FLOAT", - "use" : "the voice bar becoming the field", - "value" : 0.40000000000000002 - }, - { - "codeSyntax" : "DesignTokens.Motion.waveFade", - "name" : "wave-fade", - "scopes" : [ - - ], - "type" : "FLOAT", - "use" : "the orb and the wave crossing, either way", - "value" : 0.69999999999999996 - } - ] - }, - "Themes" : { - "mode" : "Value", - "variables" : [ - { - "alias" : "Brand:ink\/700", - "codeSyntax" : "DesignTokens.Themes.inkKey", - "name" : "ink\/key", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#33302A" - }, - { - "alias" : "Brand:ink\/800", - "codeSyntax" : "DesignTokens.Themes.inkKeyModifier", - "name" : "ink\/key-modifier", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#26231E" - }, - { - "alias" : "Brand:warm-white", - "codeSyntax" : "DesignTokens.Themes.inkLegend", - "name" : "ink\/legend", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#F2EEE6" - }, - { - "alias" : "Brand:ink\/700", - "codeSyntax" : "DesignTokens.Themes.inkPopup", - "name" : "ink\/popup", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#33302A" - }, - { - "alias" : "Brand:green\/400", - "codeSyntax" : "DesignTokens.Themes.inkSignal", - "name" : "ink\/signal", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#67AD82" - }, - { - "alias" : "Brand:ink", - "codeSyntax" : "DesignTokens.Themes.inkSurface", - "name" : "ink\/surface", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#1D1B16" - }, - { - "codeSyntax" : "DesignTokens.Themes.lavenderKey", - "name" : "lavender\/key", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#3F3777" - }, - { - "codeSyntax" : "DesignTokens.Themes.lavenderKeyModifier", - "name" : "lavender\/key-modifier", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#352E68" - }, - { - "codeSyntax" : "DesignTokens.Themes.lavenderLegend", - "name" : "lavender\/legend", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#F1EEFF" - }, - { - "codeSyntax" : "DesignTokens.Themes.lavenderPopup", - "name" : "lavender\/popup", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#3F3777" - }, - { - "alias" : "Brand:green\/400", - "codeSyntax" : "DesignTokens.Themes.lavenderSignal", - "name" : "lavender\/signal", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#67AD82" - }, - { - "codeSyntax" : "DesignTokens.Themes.lavenderSurface", - "name" : "lavender\/surface", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#2C2557" - }, - { - "codeSyntax" : "DesignTokens.Themes.midnightKey", - "name" : "midnight\/key", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#1D2440" - }, - { - "codeSyntax" : "DesignTokens.Themes.midnightKeyModifier", - "name" : "midnight\/key-modifier", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#161B33" - }, - { - "codeSyntax" : "DesignTokens.Themes.midnightLegend", - "name" : "midnight\/legend", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#E8ECFF" - }, - { - "codeSyntax" : "DesignTokens.Themes.midnightPopup", - "name" : "midnight\/popup", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#1D2440" - }, - { - "alias" : "Brand:green\/400", - "codeSyntax" : "DesignTokens.Themes.midnightSignal", - "name" : "midnight\/signal", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#67AD82" - }, - { - "codeSyntax" : "DesignTokens.Themes.midnightSurface", - "name" : "midnight\/surface", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#0E1220" - }, - { - "codeSyntax" : "DesignTokens.Themes.mintKey", - "name" : "mint\/key", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#1E3F31" - }, - { - "codeSyntax" : "DesignTokens.Themes.mintKeyModifier", - "name" : "mint\/key-modifier", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#183429" - }, - { - "codeSyntax" : "DesignTokens.Themes.mintLegend", - "name" : "mint\/legend", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#E9F5EE" - }, - { - "codeSyntax" : "DesignTokens.Themes.mintPopup", - "name" : "mint\/popup", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#1E3F31" - }, - { - "alias" : "Brand:green\/400", - "codeSyntax" : "DesignTokens.Themes.mintSignal", - "name" : "mint\/signal", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#67AD82" - }, - { - "codeSyntax" : "DesignTokens.Themes.mintSurface", - "name" : "mint\/surface", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#10231B" - }, - { - "alias" : "Brand:white", - "codeSyntax" : "DesignTokens.Themes.paperKey", - "name" : "paper\/key", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#FFFFFF" - }, - { - "alias" : "Brand:card-border", - "codeSyntax" : "DesignTokens.Themes.paperKeyModifier", - "name" : "paper\/key-modifier", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#DEDBDB" - }, - { - "alias" : "Brand:ink", - "codeSyntax" : "DesignTokens.Themes.paperLegend", - "name" : "paper\/legend", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#1D1B16" - }, - { - "alias" : "Brand:white", - "codeSyntax" : "DesignTokens.Themes.paperPopup", - "name" : "paper\/popup", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#FFFFFF" - }, - { - "alias" : "Brand:green\/700", - "codeSyntax" : "DesignTokens.Themes.paperSignal", - "name" : "paper\/signal", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#01762F" - }, - { - "alias" : "Brand:card", - "codeSyntax" : "DesignTokens.Themes.paperSurface", - "name" : "paper\/surface", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#EBE8E8" - }, - { - "codeSyntax" : "DesignTokens.Themes.sunsetKey", - "name" : "sunset\/key", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#4B2B20" - }, - { - "codeSyntax" : "DesignTokens.Themes.sunsetKeyModifier", - "name" : "sunset\/key-modifier", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#3B2119" - }, - { - "codeSyntax" : "DesignTokens.Themes.sunsetLegend", - "name" : "sunset\/legend", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#FFEFE6" - }, - { - "codeSyntax" : "DesignTokens.Themes.sunsetPopup", - "name" : "sunset\/popup", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#4B2B20" - }, - { - "alias" : "Brand:green\/400", - "codeSyntax" : "DesignTokens.Themes.sunsetSignal", - "name" : "sunset\/signal", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#67AD82" - }, - { - "codeSyntax" : "DesignTokens.Themes.sunsetSurface", - "name" : "sunset\/surface", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#2B1912" - }, - { - "alias" : "Brand:apple\/dark-key", - "codeSyntax" : "DesignTokens.Themes.systemDarkKey", - "name" : "system-dark\/key", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#6B6B6B" - }, - { - "alias" : "Brand:apple\/dark-modifier", - "codeSyntax" : "DesignTokens.Themes.systemDarkKeyModifier", - "name" : "system-dark\/key-modifier", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#464646" - }, - { - "alias" : "Brand:white", - "codeSyntax" : "DesignTokens.Themes.systemDarkLegend", - "name" : "system-dark\/legend", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#FFFFFF" - }, - { - "alias" : "Brand:apple\/dark-key", - "codeSyntax" : "DesignTokens.Themes.systemDarkPopup", - "name" : "system-dark\/popup", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#6B6B6B" - }, - { - "alias" : "Brand:green\/400", - "codeSyntax" : "DesignTokens.Themes.systemDarkSignal", - "name" : "system-dark\/signal", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#67AD82" - }, - { - "alias" : "Brand:apple\/dark-surface", - "codeSyntax" : "DesignTokens.Themes.systemDarkSurface", - "name" : "system-dark\/surface", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#2B2B2B" - }, - { - "alias" : "Brand:white", - "codeSyntax" : "DesignTokens.Themes.systemLightKey", - "name" : "system-light\/key", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#FFFFFF" - }, - { - "alias" : "Brand:apple\/light-modifier", - "codeSyntax" : "DesignTokens.Themes.systemLightKeyModifier", - "name" : "system-light\/key-modifier", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#ADB3BC" - }, - { - "alias" : "Brand:black", - "codeSyntax" : "DesignTokens.Themes.systemLightLegend", - "name" : "system-light\/legend", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#000000" - }, - { - "alias" : "Brand:white", - "codeSyntax" : "DesignTokens.Themes.systemLightPopup", - "name" : "system-light\/popup", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#FFFFFF" - }, - { - "alias" : "Brand:green\/700", - "codeSyntax" : "DesignTokens.Themes.systemLightSignal", - "name" : "system-light\/signal", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#01762F" - }, - { - "alias" : "Brand:apple\/light-surface", - "codeSyntax" : "DesignTokens.Themes.systemLightSurface", - "name" : "system-light\/surface", - "scopes" : [ - - ], - "type" : "COLOR", - "use" : "", - "value" : "#D1D5DB" - } - ] - }, - "Typography" : { - "mode" : "Value", - "variables" : [ - { - "codeSyntax" : "DesignTokens.Typography.ratioOrbGlyph", - "name" : "ratio\/orb-glyph", - "scopes" : [ - - ], - "type" : "FLOAT", - "use" : "the clipboard and exclamation glyphs, as a fraction of the orb", - "value" : 0.34000000000000002 - }, - { - "codeSyntax" : "DesignTokens.Typography.sizeGlyph", - "name" : "size\/glyph", - "scopes" : [ - "FONT_SIZE" - ], - "type" : "FLOAT", - "use" : "the +, × and ✓", - "value" : 17 - }, - { - "codeSyntax" : "DesignTokens.Typography.sizeLegend", - "name" : "size\/legend", - "scopes" : [ - "FONT_SIZE" - ], - "type" : "FLOAT", - "use" : "every other key", - "value" : 16 - }, - { - "codeSyntax" : "DesignTokens.Typography.sizeLetter", - "name" : "size\/letter", - "scopes" : [ - "FONT_SIZE" - ], - "type" : "FLOAT", - "use" : "letter keys", - "value" : 22 - }, - { - "codeSyntax" : "DesignTokens.Typography.sizePopup", - "name" : "size\/popup", - "scopes" : [ - "FONT_SIZE" - ], - "type" : "FLOAT", - "use" : "the letter pop-up", - "value" : 32 - }, - { - "codeSyntax" : "DesignTokens.Typography.sizeTerm", - "name" : "size\/term", - "scopes" : [ - "FONT_SIZE" - ], - "type" : "FLOAT", - "use" : "the key-term field", - "value" : 17 - }, - { - "codeSyntax" : "DesignTokens.Typography.weightGlyph", - "name" : "weight\/glyph", - "scopes" : [ - "FONT_STYLE" - ], - "type" : "STRING", - "use" : "", - "value" : "medium" - }, - { - "codeSyntax" : "DesignTokens.Typography.weightLegend", - "name" : "weight\/legend", - "scopes" : [ - "FONT_STYLE" - ], - "type" : "STRING", - "use" : "", - "value" : "medium" - }, - { - "codeSyntax" : "DesignTokens.Typography.weightLetter", - "name" : "weight\/letter", - "scopes" : [ - "FONT_STYLE" - ], - "type" : "STRING", - "use" : "", - "value" : "regular" - }, - { - "codeSyntax" : "DesignTokens.Typography.weightOrbGlyph", - "name" : "weight\/orb-glyph", - "scopes" : [ - "FONT_STYLE" - ], - "type" : "STRING", - "use" : "", - "value" : "semibold" - }, - { - "codeSyntax" : "DesignTokens.Typography.weightPopup", - "name" : "weight\/popup", - "scopes" : [ - "FONT_STYLE" - ], - "type" : "STRING", - "use" : "", - "value" : "regular" - }, - { - "codeSyntax" : "DesignTokens.Typography.weightTerm", - "name" : "weight\/term", - "scopes" : [ - "FONT_STYLE" - ], - "type" : "STRING", - "use" : "", - "value" : "regular" - } - ] - } - }, - "gradients" : { - "orb" : { - "end" : "top", - "start" : "bottom", - "stops" : [ - { - "alias" : "Brand:violet\/lavender", - "location" : 0, - "value" : "#D7D3F4" - }, - { - "alias" : "Brand:violet\/periwinkle", - "location" : 0.067299999999999999, - "value" : "#B0A7E9" - }, - { - "alias" : "Brand:green\/400", - "location" : 0.14419999999999999, - "value" : "#67AD82" - }, - { - "alias" : "Brand:green\/700", - "location" : 0.3029, - "value" : "#01762F" - }, - { - "alias" : "Brand:cobolt", - "location" : 0.59619999999999995, - "value" : "#3923C7" - }, - { - "alias" : "Brand:violet\/iris", - "location" : 0.75, - "value" : "#887BDD" - }, - { - "alias" : "Brand:violet\/lavender", - "location" : 0.89419999999999999, - "value" : "#D7D3F4" - }, - { - "alias" : "Brand:white", - "location" : 1, - "value" : "#FFFFFF" - } - ], - "use" : "the Mac orb's fill, the design's own stops (App elements\/Recording.svg), swept bottom to top" - }, - "orb-ring" : { - "end" : "bottomTrailing", - "start" : "topLeading", - "stops" : [ - { - "alias" : "Brand:green\/700", - "location" : 0, - "value" : "#01762F" - }, - { - "alias" : "Brand:white", - "location" : 1, - "value" : "#FFFFFF" - } - ], - "use" : "the ring round the orb: green into white, corner to corner; spun while something is happening" - } - }, - "groups" : [ - "Brand", - "Themes", - "Keyboard", - "Metrics", - "Typography", - "Motion" - ] -}; +// One line per variable (collection|name|type|value|alias|scopes|codeSyntax|use) +// and per gradient (GRADIENT|name|start|end|stops|use); core.js parses it. +// scripts/design-figma-call.sh puts it in front of core.js + foundations.js. +const TOKEN_LINES = `Brand|apple/dark-key|COLOR|#6B6B6B|||DesignTokens.Brand.appleDarkKey|the iPhone keyboard's dark key +Brand|apple/dark-modifier|COLOR|#464646|||DesignTokens.Brand.appleDarkModifier|the iPhone keyboard's dark modifier key +Brand|apple/dark-surface|COLOR|#2B2B2B|||DesignTokens.Brand.appleDarkSurface|the iPhone keyboard's dark surface +Brand|apple/light-modifier|COLOR|#ADB3BC|||DesignTokens.Brand.appleLightModifier|the iPhone keyboard's light modifier key +Brand|apple/light-surface|COLOR|#D1D5DB|||DesignTokens.Brand.appleLightSurface|the iPhone keyboard's light surface +Brand|black|COLOR|#000000|||DesignTokens.Brand.black| +Brand|card|COLOR|#EBE8E8|||DesignTokens.Brand.card|the warm card fill; the paper theme's surface +Brand|card-border|COLOR|#DEDBDB|||DesignTokens.Brand.cardBorder|the card's hairline; the paper theme's modifier key +Brand|cobolt|COLOR|#3923C7|||DesignTokens.Brand.cobolt|AssemblyAI's primary violet: the drop, never a key or a surface +Brand|green/100|COLOR|#CCE4D5|||DesignTokens.Brand.green100|the design system's UI-and-code green fill (unused on the phone yet) +Brand|green/200|COLOR|#99C8AC|||DesignTokens.Brand.green200|the design system's UI-and-code green highlight (unused on the phone yet) +Brand|green/400|COLOR|#67AD82|||DesignTokens.Brand.green400|the brand hue lifted for dark chrome: the meter, the ring, the wave on ink +Brand|green/700|COLOR|#01762F|||DesignTokens.Brand.green700|the wordmark green, light chrome (the app's accent in light) +Brand|green/mist|COLOR|#DBF5E6|||DesignTokens.Brand.greenMist|the pale green the orb lightens into +Brand|ink|COLOR|#1D1B16|||DesignTokens.Brand.ink|the brand ink: the Mac pill's body, the ink theme's surface +Brand|ink/600|COLOR|#3A362F|||DesignTokens.Brand.ink600|the Mac's dark card border +Brand|ink/700|COLOR|#33302A|||DesignTokens.Brand.ink700|an ordinary key on ink, one step up +Brand|ink/800|COLOR|#26231E|||DesignTokens.Brand.ink800|a modifier key on ink; the Mac's dark card fill +Brand|orange|COLOR|#E67F36|||DesignTokens.Brand.orange|the error word and ring, cancel, the Full Access note; never a red body +Brand|page|COLOR|#FDFCF8|||DesignTokens.Brand.page|the design system's page background (unused on the phone) +Brand|violet/iris|COLOR|#887BDD|||DesignTokens.Brand.violetIris|the orb gradient's upper violet stop +Brand|violet/lavender|COLOR|#D7D3F4|||DesignTokens.Brand.violetLavender|the orb's lightest violet: its top and the gradient's ends +Brand|violet/periwinkle|COLOR|#B0A7E9|||DesignTokens.Brand.violetPeriwinkle|the orb's mid violet: the drop's halo +Brand|warm-white|COLOR|#F2EEE6|||DesignTokens.Brand.warmWhite|key legends on ink: warm white on warm ink +Brand|white|COLOR|#FFFFFF|||DesignTokens.Brand.white| +Themes|ink/key|COLOR|#33302A|Brand:ink/700||DesignTokens.Themes.inkKey| +Themes|ink/key-modifier|COLOR|#26231E|Brand:ink/800||DesignTokens.Themes.inkKeyModifier| +Themes|ink/legend|COLOR|#F2EEE6|Brand:warm-white||DesignTokens.Themes.inkLegend| +Themes|ink/popup|COLOR|#33302A|Brand:ink/700||DesignTokens.Themes.inkPopup| +Themes|ink/signal|COLOR|#67AD82|Brand:green/400||DesignTokens.Themes.inkSignal| +Themes|ink/surface|COLOR|#1D1B16|Brand:ink||DesignTokens.Themes.inkSurface| +Themes|lavender/key|COLOR|#3F3777|||DesignTokens.Themes.lavenderKey| +Themes|lavender/key-modifier|COLOR|#352E68|||DesignTokens.Themes.lavenderKeyModifier| +Themes|lavender/legend|COLOR|#F1EEFF|||DesignTokens.Themes.lavenderLegend| +Themes|lavender/popup|COLOR|#3F3777|||DesignTokens.Themes.lavenderPopup| +Themes|lavender/signal|COLOR|#67AD82|Brand:green/400||DesignTokens.Themes.lavenderSignal| +Themes|lavender/surface|COLOR|#2C2557|||DesignTokens.Themes.lavenderSurface| +Themes|midnight/key|COLOR|#1D2440|||DesignTokens.Themes.midnightKey| +Themes|midnight/key-modifier|COLOR|#161B33|||DesignTokens.Themes.midnightKeyModifier| +Themes|midnight/legend|COLOR|#E8ECFF|||DesignTokens.Themes.midnightLegend| +Themes|midnight/popup|COLOR|#1D2440|||DesignTokens.Themes.midnightPopup| +Themes|midnight/signal|COLOR|#67AD82|Brand:green/400||DesignTokens.Themes.midnightSignal| +Themes|midnight/surface|COLOR|#0E1220|||DesignTokens.Themes.midnightSurface| +Themes|mint/key|COLOR|#1E3F31|||DesignTokens.Themes.mintKey| +Themes|mint/key-modifier|COLOR|#183429|||DesignTokens.Themes.mintKeyModifier| +Themes|mint/legend|COLOR|#E9F5EE|||DesignTokens.Themes.mintLegend| +Themes|mint/popup|COLOR|#1E3F31|||DesignTokens.Themes.mintPopup| +Themes|mint/signal|COLOR|#67AD82|Brand:green/400||DesignTokens.Themes.mintSignal| +Themes|mint/surface|COLOR|#10231B|||DesignTokens.Themes.mintSurface| +Themes|paper/key|COLOR|#FFFFFF|Brand:white||DesignTokens.Themes.paperKey| +Themes|paper/key-modifier|COLOR|#DEDBDB|Brand:card-border||DesignTokens.Themes.paperKeyModifier| +Themes|paper/legend|COLOR|#1D1B16|Brand:ink||DesignTokens.Themes.paperLegend| +Themes|paper/popup|COLOR|#FFFFFF|Brand:white||DesignTokens.Themes.paperPopup| +Themes|paper/signal|COLOR|#01762F|Brand:green/700||DesignTokens.Themes.paperSignal| +Themes|paper/surface|COLOR|#EBE8E8|Brand:card||DesignTokens.Themes.paperSurface| +Themes|sunset/key|COLOR|#4B2B20|||DesignTokens.Themes.sunsetKey| +Themes|sunset/key-modifier|COLOR|#3B2119|||DesignTokens.Themes.sunsetKeyModifier| +Themes|sunset/legend|COLOR|#FFEFE6|||DesignTokens.Themes.sunsetLegend| +Themes|sunset/popup|COLOR|#4B2B20|||DesignTokens.Themes.sunsetPopup| +Themes|sunset/signal|COLOR|#67AD82|Brand:green/400||DesignTokens.Themes.sunsetSignal| +Themes|sunset/surface|COLOR|#2B1912|||DesignTokens.Themes.sunsetSurface| +Themes|system-dark/key|COLOR|#6B6B6B|Brand:apple/dark-key||DesignTokens.Themes.systemDarkKey| +Themes|system-dark/key-modifier|COLOR|#464646|Brand:apple/dark-modifier||DesignTokens.Themes.systemDarkKeyModifier| +Themes|system-dark/legend|COLOR|#FFFFFF|Brand:white||DesignTokens.Themes.systemDarkLegend| +Themes|system-dark/popup|COLOR|#6B6B6B|Brand:apple/dark-key||DesignTokens.Themes.systemDarkPopup| +Themes|system-dark/signal|COLOR|#67AD82|Brand:green/400||DesignTokens.Themes.systemDarkSignal| +Themes|system-dark/surface|COLOR|#2B2B2B|Brand:apple/dark-surface||DesignTokens.Themes.systemDarkSurface| +Themes|system-light/key|COLOR|#FFFFFF|Brand:white||DesignTokens.Themes.systemLightKey| +Themes|system-light/key-modifier|COLOR|#ADB3BC|Brand:apple/light-modifier||DesignTokens.Themes.systemLightKeyModifier| +Themes|system-light/legend|COLOR|#000000|Brand:black||DesignTokens.Themes.systemLightLegend| +Themes|system-light/popup|COLOR|#FFFFFF|Brand:white||DesignTokens.Themes.systemLightPopup| +Themes|system-light/signal|COLOR|#01762F|Brand:green/700||DesignTokens.Themes.systemLightSignal| +Themes|system-light/surface|COLOR|#D1D5DB|Brand:apple/light-surface||DesignTokens.Themes.systemLightSurface| +Keyboard|app/accent-dark|COLOR|#67AD82|Brand:green/400|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.appAccentDark|the catalog's AccentColor in dark +Keyboard|app/accent-light|COLOR|#01762F|Brand:green/700|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.appAccentLight|the catalog's AccentColor in light +Keyboard|app/card-border-dark|COLOR|#3A362F|Brand:ink/600|STROKE_COLOR|DesignTokens.Keyboard.appCardBorderDark|the catalog's CardBorder in dark +Keyboard|app/card-border-light|COLOR|#DEDBDB|Brand:card-border|STROKE_COLOR|DesignTokens.Keyboard.appCardBorderLight|the catalog's CardBorder in light +Keyboard|app/card-fill-dark|COLOR|#26231E|Brand:ink/800|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.appCardFillDark|the catalog's CardFill in dark +Keyboard|app/card-fill-light|COLOR|#EBE8E8|Brand:card|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.appCardFillLight|the catalog's CardFill in light +Keyboard|kb/cancel|COLOR|#E67F36|Brand:orange|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.kbCancel|the panel's cancel × +Keyboard|kb/full-access-note|COLOR|#E67F36|Brand:orange|TEXT_FILL|DesignTokens.Keyboard.kbFullAccessNote|the one line of words the keyboard ever shows +Keyboard|kb/key|COLOR|#33302A|Themes:ink/key|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.kbKey|an ordinary key +Keyboard|kb/key-modifier|COLOR|#26231E|Themes:ink/key-modifier|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.kbKeyModifier|shift, delete, globe, return, 123, cancel +Keyboard|kb/legend|COLOR|#F2EEE6|Themes:ink/legend|TEXT_FILL|DesignTokens.Keyboard.kbLegend|key legends and bare glyphs +Keyboard|kb/notice-error|COLOR|#E67F36|Brand:orange|STROKE_COLOR|DesignTokens.Keyboard.kbNoticeError|the solid ring and glyph for an error +Keyboard|kb/notice-ok|COLOR|#67AD82|Brand:green/400|STROKE_COLOR|DesignTokens.Keyboard.kbNoticeOk|the solid ring for pasted and copied +Keyboard|kb/orb-ring-end|COLOR|#FFFFFF|Brand:white|STROKE_COLOR|DesignTokens.Keyboard.kbOrbRingEnd|the sweeping ring's gradient, bottom-trailing +Keyboard|kb/orb-ring-start|COLOR|#01762F|Brand:green/700|STROKE_COLOR|DesignTokens.Keyboard.kbOrbRingStart|the sweeping ring's gradient, top-leading +Keyboard|kb/popup|COLOR|#33302A|Themes:ink/popup|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.kbPopup|the letter pop-up +Keyboard|kb/signal|COLOR|#67AD82|Themes:ink/signal|SHAPE_FILL,TEXT_FILL|DesignTokens.Keyboard.kbSignal|the wave, the caret, the saved check +Keyboard|kb/surface|COLOR|#1D1B16|Themes:ink/surface|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.kbSurface|the design theme's surface (Figma binds to kb/*; Swift reads the palette) +Metrics|addterm/inset|FLOAT|6||GAP|DesignTokens.Metrics.addtermInset|the + from the panel's corner +Metrics|card/border|FLOAT|1||STROKE_FLOAT,WIDTH_HEIGHT|DesignTokens.Metrics.cardBorder|the card's hairline +Metrics|card/radius|FLOAT|16||CORNER_RADIUS|DesignTokens.Metrics.cardRadius|the app's cards +Metrics|caret/height|FLOAT|20||WIDTH_HEIGHT|DesignTokens.Metrics.caretHeight| +Metrics|caret/lead|FLOAT|1||GAP|DesignTokens.Metrics.caretLead|the caret's gap from the text +Metrics|caret/radius|FLOAT|1||CORNER_RADIUS|DesignTokens.Metrics.caretRadius| +Metrics|caret/width|FLOAT|2||STROKE_FLOAT,WIDTH_HEIGHT|DesignTokens.Metrics.caretWidth| +Metrics|gesture/swipe-min|FLOAT|24|||DesignTokens.Metrics.gestureSwipeMin|the carousel gesture's minimum distance +Metrics|glyph/hit|FLOAT|32||WIDTH_HEIGHT|DesignTokens.Metrics.glyphHit|the +, × and ✓ touch targets +Metrics|key/gap|FLOAT|6||GAP|DesignTokens.Metrics.keyGap|between keys, the iPhone's +Metrics|key/height|FLOAT|42||WIDTH_HEIGHT|DesignTokens.Metrics.keyHeight|every key +Metrics|key/letter-width-402|FLOAT|34.8||WIDTH_HEIGHT|DesignTokens.Metrics.keyLetterWidth402|a letter key at 402 pt (iPhone 18 Pro): (width − 9 × key/gap) / 10 +Metrics|key/min-width|FLOAT|44||WIDTH_HEIGHT|DesignTokens.Metrics.keyMinWidth|a key that isn't given a width +Metrics|key/pad|FLOAT|4||GAP|DesignTokens.Metrics.keyPad|a legend's side padding on a min-width key +Metrics|key/radius|FLOAT|8||CORNER_RADIUS|DesignTokens.Metrics.keyRadius|flat keys, one colour at this corner +Metrics|key/return-width-402|FLOAT|104.4||WIDTH_HEIGHT|DesignTokens.Metrics.keyReturnWidth402|return at 402 pt: two side keys and a gap +Metrics|key/side-gap-factor|FLOAT|2|||DesignTokens.Metrics.keySideGapFactor|shift and delete stand this many key gaps from the letters +Metrics|key/side-width-402|FLOAT|49.2||WIDTH_HEIGHT|DesignTokens.Metrics.keySideWidth402|shift, delete, 123 and globe at 402 pt: what seven letters leave, halved +Metrics|layout/full|FLOAT|272||WIDTH_HEIGHT|DesignTokens.Metrics.layoutFull|2 × margin/vertical + voicebar/height + 4 × row/gap + 4 × key/height +Metrics|layout/panel|FLOAT|216||WIDTH_HEIGHT|DesignTokens.Metrics.layoutPanel|chosen: room for the 96 orb over one key row +Metrics|layout/slim|FLOAT|60||WIDTH_HEIGHT|DesignTokens.Metrics.layoutSlim|2 × margin/vertical + voicebar/height +Metrics|margin/side|FLOAT|3||WIDTH_HEIGHT|DesignTokens.Metrics.marginSide|at the keyboard's sides +Metrics|margin/vertical|FLOAT|8||WIDTH_HEIGHT|DesignTokens.Metrics.marginVertical|the keyboard's top and bottom +Metrics|opacity/dim|FLOAT|0.8||OPACITY|DesignTokens.Metrics.opacityDim|the orb when Blurt isn't ready +Metrics|opacity/dim-saturation|FLOAT|0.35||OPACITY|DesignTokens.Metrics.opacityDimSaturation|and its saturation +Metrics|opacity/disabled|FLOAT|0.4||OPACITY|DesignTokens.Metrics.opacityDisabled|the + without Full Access +Metrics|opacity/grain|FLOAT|0.5||OPACITY|DesignTokens.Metrics.opacityGrain| +Metrics|opacity/home-dim-saturation|FLOAT|0.45||OPACITY|DesignTokens.Metrics.opacityHomeDimSaturation|the home hero's saturation when not listening +Metrics|opacity/legend-muted|FLOAT|0.5||OPACITY|DesignTokens.Metrics.opacityLegendMuted|the + at rest +Metrics|opacity/orb-light|FLOAT|0.3||OPACITY|DesignTokens.Metrics.opacityOrbLight| +Metrics|opacity/placeholder|FLOAT|0.4||OPACITY|DesignTokens.Metrics.opacityPlaceholder|the field's placeholder +Metrics|opacity/popup-shadow|FLOAT|0.12||OPACITY|DesignTokens.Metrics.opacityPopupShadow| +Metrics|opacity/press-brighten|FLOAT|0.15||OPACITY|DesignTokens.Metrics.opacityPressBrighten|a key lightens this much while pressed +Metrics|opacity/term-cancel|FLOAT|0.7||OPACITY|DesignTokens.Metrics.opacityTermCancel|the field's × +Metrics|orb/bar|FLOAT|40||WIDTH_HEIGHT|DesignTokens.Metrics.orbBar|the orb in the voice bar +Metrics|orb/dissipate-blur|FLOAT|0.16|||DesignTokens.Metrics.orbDissipateBlur|and blurs to this fraction of its size +Metrics|orb/dissipate-scale|FLOAT|1.25|||DesignTokens.Metrics.orbDissipateScale|the orb swells to this while dissipating +Metrics|orb/home|FLOAT|112||WIDTH_HEIGHT|DesignTokens.Metrics.orbHome|the orb on the home screen +Metrics|orb/light-radius|FLOAT|110|||DesignTokens.Metrics.orbLightRadius|the light's reach in points (fixed, not proportional — open) +Metrics|orb/light-x|FLOAT|0.3|||DesignTokens.Metrics.orbLightX|the soft light's centre, as a fraction of the orb +Metrics|orb/light-y|FLOAT|0.22|||DesignTokens.Metrics.orbLightY| +Metrics|orb/panel|FLOAT|96||WIDTH_HEIGHT|DesignTokens.Metrics.orbPanel|the orb in the panel +Metrics|panel/spacing|FLOAT|12||GAP|DesignTokens.Metrics.panelSpacing|between the panel's orb and its key row +Metrics|picker/preview-width|FLOAT|393||WIDTH_HEIGHT|DesignTokens.Metrics.pickerPreviewWidth|the theme card draws the keyboard at this width +Metrics|picker/radius|FLOAT|10||CORNER_RADIUS|DesignTokens.Metrics.pickerRadius|the theme card's preview corners +Metrics|picker/scale|FLOAT|0.42|||DesignTokens.Metrics.pickerScale|then scales it to fit two across +Metrics|popup/extra-width|FLOAT|18||WIDTH_HEIGHT|DesignTokens.Metrics.popupExtraWidth|the letter pop-up is the key width plus this +Metrics|popup/height|FLOAT|56||WIDTH_HEIGHT|DesignTokens.Metrics.popupHeight| +Metrics|popup/offset|FLOAT|58||WIDTH_HEIGHT|DesignTokens.Metrics.popupOffset|the pop-up sits this far above the key +Metrics|popup/radius|FLOAT|10||CORNER_RADIUS|DesignTokens.Metrics.popupRadius| +Metrics|popup/shadow-radius|FLOAT|8||WIDTH_HEIGHT|DesignTokens.Metrics.popupShadowRadius|the one thing that floats +Metrics|popup/shadow-y|FLOAT|2||WIDTH_HEIGHT|DesignTokens.Metrics.popupShadowY| +Metrics|press/scale|FLOAT|0.94|||DesignTokens.Metrics.pressScale|the orb while pressed +Metrics|ring/active|FLOAT|2||STROKE_FLOAT,WIDTH_HEIGHT|DesignTokens.Metrics.ringActive|the ring while working or noticing; the home ring +Metrics|ring/still|FLOAT|1||STROKE_FLOAT,WIDTH_HEIGHT|DesignTokens.Metrics.ringStill|the ring at rest +Metrics|row/gap|FLOAT|11||GAP|DesignTokens.Metrics.rowGap|between rows, the iPhone's +Metrics|slim/spacing|FLOAT|8||GAP|DesignTokens.Metrics.slimSpacing|between the slim bar's keys +Metrics|term/gap|FLOAT|8||GAP|DesignTokens.Metrics.termGap|× · field · ✓ +Metrics|term/height|FLOAT|36||WIDTH_HEIGHT|DesignTokens.Metrics.termHeight|the key-term field's capsule +Metrics|term/inset|FLOAT|2||GAP|DesignTokens.Metrics.termInset|the field row's side inset +Metrics|term/pad|FLOAT|14||GAP|DesignTokens.Metrics.termPad|the field's side padding +Metrics|voicebar/addterm-clearance|FLOAT|12||GAP|DesignTokens.Metrics.voicebarAddtermClearance|the wave stays this clear of the + at the trailing edge +Metrics|voicebar/height|FLOAT|44||WIDTH_HEIGHT|DesignTokens.Metrics.voicebarHeight|the voice row, where the system puts its suggestion bar +Metrics|voicebar/note-gap|FLOAT|10||GAP|DesignTokens.Metrics.voicebarNoteGap|between the orb and the Full Access note +Metrics|wave/bar|FLOAT|2||STROKE_FLOAT,WIDTH_HEIGHT|DesignTokens.Metrics.waveBar|a wave bar's width +Metrics|wave/bar-height|FLOAT|24||WIDTH_HEIGHT|DesignTokens.Metrics.waveBarHeight| +Metrics|wave/bar-width|FLOAT|240||WIDTH_HEIGHT|DesignTokens.Metrics.waveBarWidth|the wave in the voice bar, at most +Metrics|wave/gap|FLOAT|2||GAP|DesignTokens.Metrics.waveGap|between wave bars +Metrics|wave/home-height|FLOAT|44||WIDTH_HEIGHT|DesignTokens.Metrics.waveHomeHeight| +Metrics|wave/home-width|FLOAT|280||WIDTH_HEIGHT|DesignTokens.Metrics.waveHomeWidth| +Metrics|wave/panel-height|FLOAT|40||WIDTH_HEIGHT|DesignTokens.Metrics.wavePanelHeight| +Metrics|wave/panel-width|FLOAT|300||WIDTH_HEIGHT|DesignTokens.Metrics.wavePanelWidth| +Metrics|wordmark/height|FLOAT|22||WIDTH_HEIGHT|DesignTokens.Metrics.wordmarkHeight| +Typography|ratio/orb-glyph|FLOAT|0.34|||DesignTokens.Typography.ratioOrbGlyph|the clipboard and exclamation glyphs, as a fraction of the orb +Typography|size/glyph|FLOAT|17||FONT_SIZE|DesignTokens.Typography.sizeGlyph|the +, × and ✓ +Typography|size/legend|FLOAT|16||FONT_SIZE|DesignTokens.Typography.sizeLegend|every other key +Typography|size/letter|FLOAT|22||FONT_SIZE|DesignTokens.Typography.sizeLetter|letter keys +Typography|size/popup|FLOAT|32||FONT_SIZE|DesignTokens.Typography.sizePopup|the letter pop-up +Typography|size/term|FLOAT|17||FONT_SIZE|DesignTokens.Typography.sizeTerm|the key-term field +Typography|weight/glyph|STRING|medium||FONT_STYLE|DesignTokens.Typography.weightGlyph| +Typography|weight/legend|STRING|medium||FONT_STYLE|DesignTokens.Typography.weightLegend| +Typography|weight/letter|STRING|regular||FONT_STYLE|DesignTokens.Typography.weightLetter| +Typography|weight/orb-glyph|STRING|semibold||FONT_STYLE|DesignTokens.Typography.weightOrbGlyph| +Typography|weight/popup|STRING|regular||FONT_STYLE|DesignTokens.Typography.weightPopup| +Typography|weight/term|STRING|regular||FONT_STYLE|DesignTokens.Typography.weightTerm| +Motion|caret|FLOAT|0.5|||DesignTokens.Motion.caret|the caret's blink +Motion|drop|FLOAT|2.4|||DesignTokens.Motion.drop|the violet drop is gone by +Motion|drop-hold|FLOAT|0.9|||DesignTokens.Motion.dropHold|and held to +Motion|drop-rise|FLOAT|0.5|||DesignTokens.Motion.dropRise|the drop is up in +Motion|drop-spread|FLOAT|1|||DesignTokens.Motion.dropSpread|the bloom reaches its full spread in +Motion|flip|FLOAT|0.25|||DesignTokens.Motion.flip|the panel's carousel +Motion|height-change|FLOAT|0.25|||DesignTokens.Motion.heightChange|the keyboard resizing +Motion|key-press|FLOAT|0.08|||DesignTokens.Motion.keyPress|a key lighting +Motion|mood|FLOAT|0.8|||DesignTokens.Motion.mood|the orb's colour moving between moods +Motion|press|FLOAT|0.1|||DesignTokens.Motion.press|the orb's press; the one thing that answers at once +Motion|ring-period|FLOAT|1.6|||DesignTokens.Motion.ringPeriod|one turn of the ring, the Mac's cadence +Motion|state-fade|FLOAT|0.5|||DesignTokens.Motion.stateFade|every other change on the key: the ring, a glyph, the dimming +Motion|term-swap|FLOAT|0.4|||DesignTokens.Motion.termSwap|the voice bar becoming the field +Motion|wave-fade|FLOAT|0.7|||DesignTokens.Motion.waveFade|the orb and the wave crossing, either way +GRADIENT|orb|bottom|top|#D7D3F4@0,#B0A7E9@0.0673,#67AD82@0.1442,#01762F@0.3029,#3923C7@0.5962,#887BDD@0.75,#D7D3F4@0.8942,#FFFFFF@1|the Mac orb's fill, the design's own stops (App elements/Recording.svg), swept bottom to top +GRADIENT|orb-ring|topLeading|bottomTrailing|#01762F@0,#FFFFFF@1|the ring round the orb: green into white, corner to corner; spun while something is happening`; +const GROUPS = ["Brand", "Themes", "Keyboard", "Metrics", "Typography", "Motion"]; diff --git a/scripts/design-figma-call.sh b/scripts/design-figma-call.sh new file mode 100755 index 00000000..3936b37a --- /dev/null +++ b/scripts/design-figma-call.sh @@ -0,0 +1,49 @@ +#!/bin/bash +# Assemble one use_figma call for the Blurt Keyboard Figma build: the tokens, +# core.js, the builder's module and the line that runs it, in one file under +# the tool's 50,000-character cap (App/BlurtiOS/Design/figma/README.md). +# +# scripts/design-figma-call.sh foundations|components|layouts|theme-sheet|export-tokens|export-bounds|measure-apple +# +# Writes .build/figma-call/.js and prints its size. Only foundations +# carries tokens.js; every other builder reads the values back from the file's +# variables, so its call is just core.js and its module. +set -euo pipefail + +REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" +cd "$REPO_ROOT" +BUILDER="${1:?usage: design-figma-call.sh }" +case "$BUILDER" in + foundations) MODULE=foundations FN=buildFoundations ;; + components) MODULE=components FN=buildComponents ;; + layouts) MODULE=layouts FN=buildLayouts ;; + theme-sheet) MODULE=themes FN=themeSheet ;; + measure-apple) MODULE=themes FN=measureApple ;; + export-tokens) MODULE=exports FN=exportTokens ;; + export-bounds) MODULE=exports FN=exportBounds ;; + *) + echo "unknown builder $BUILDER" >&2 + exit 2 + ;; +esac +OUT="$REPO_ROOT/.build/figma-call" +mkdir -p "$OUT" +node - "$BUILDER" "$MODULE" "$FN" "$OUT" <<'JS' +const fs = require("fs"); +const [builder, module, fn, out] = process.argv.slice(2); +const dir = "App/BlurtiOS/Design/figma/"; +// Only foundations carries the data; every other builder reads it back from +// the file's variables and Gradient/* paint styles (core.js › ensureTokens). +const tokens = builder === "foundations" ? fs.readFileSync(dir + "tokens.js", "utf8") : ""; +const strip = (text) => text.replace(/^\/\* global [^*]*\*\/\n/m, ""); +const code = + tokens + + strip(fs.readFileSync(dir + "core.js", "utf8")) + + strip(fs.readFileSync(dir + module + ".js", "utf8")) + + `\nreturn await ${fn}();\n`; +const path = `${out}/${builder}.js`; +fs.writeFileSync(path, code); +const limit = 50000; +console.log(`${path}: ${code.length} chars${code.length > limit ? ` — OVER the ${limit} cap` : ""}`); +if (code.length > limit) process.exit(1); +JS diff --git a/scripts/design-sync.sh b/scripts/design-sync.sh index 569390df..d2574af5 100755 --- a/scripts/design-sync.sh +++ b/scripts/design-sync.sh @@ -103,8 +103,10 @@ bundle_plugin() { local dir="$REPO_ROOT/.build/figma-plugin" mkdir -p "$dir" cp App/BlurtiOS/Design/figma/manifest.json "$dir/manifest.json" - cat App/BlurtiOS/Design/figma/tokens.js App/BlurtiOS/Design/figma/lib.js App/BlurtiOS/Design/figma/plugin.js \ - >"$dir/code.js" + ( + cd App/BlurtiOS/Design/figma \ + && cat tokens.js core.js foundations.js components.js layouts.js themes.js exports.js plugin.js + ) >"$dir/code.js" echo "design-sync: Figma plugin bundled at $dir (Plugins → Development → Import plugin from manifest)" } diff --git a/scripts/design-tokens.swift b/scripts/design-tokens.swift index 202fa342..7059fe40 100755 --- a/scripts/design-tokens.swift +++ b/scripts/design-tokens.swift @@ -1,6 +1,4 @@ -#!/usr/bin/env swift // The design's one source of numbers and colours, fanned out: reads // App/BlurtiOS/Design/tokens.json (exported from the Figma file, hand-written // before it existed) and writes everything that used to repeat those values by -// hand — `App/BlurtiOS/Shared/DesignTokens.swift`, the generated tables in -// `App/BlurtiOS/DESIGN.md`, and the app's three asset-catalog colour sets. Run +#!/usr/bin/env swift // The design's one source of numbers and colours, fanned out: reads // App/BlurtiOS/Design/tokens.json (exported from the Figma file, hand-written // before it existed) and writes everything that used to repeat those values by // hand — `App/BlurtiOS/Shared/DesignTokens.swift`, the generated tables in // `App/BlurtiOS/DESIGN.md`, and the app's three asset-catalog colour sets. Run // through scripts/design-sync.sh, which also formats the output and, with // --check, fails on drift the way check.sh fails on a stale .pbxproj. // @@ -454,60 +452,60 @@ func figmaScopes(_ token: Token) -> [String] { } func figmaJSON() -> String { - var collections: [String: Any] = [:] + // One line per variable — collection|name|type|value|alias|scopes|codeSyntax|use — + // and one per gradient, parsed by core.js. Flat on purpose: a use_figma call + // is capped at 50,000 characters and carries this once, for buildFoundations; + // every later builder reads the values back from the file's variables. + var lines: [String] = [] for group in groups { - let variables: [[String: Any]] = tokens.filter { $0.group == group }.map { token in - var entry: [String: Any] = [ - "name": token.name, - "codeSyntax": "DesignTokens.\(typeName(group)).\(token.swiftName)", - "scopes": figmaScopes(token), - "use": token.use ?? "", - ] + for token in tokens where token.group == group { + var value = "" switch resolve(token).value { - case .color(let hex): - entry["type"] = "COLOR" - entry["value"] = hex - case .number(let number): - entry["type"] = "FLOAT" - entry["value"] = number - case .word(let word): - entry["type"] = "STRING" - entry["value"] = word + case .color(let hex): value = hex + case .number(let number): value = format(number) + case .word(let word): value = word case .alias: fatalError("unreachable") } + let type: String + switch resolve(token).value { + case .color: type = "COLOR" + case .number: type = "FLOAT" + default: type = "STRING" + } + var alias = "" if case .alias(let target) = token.value, let other = byQualified[target] { - entry["alias"] = "\(typeName(other.group)):\(other.name)" + alias = "\(typeName(other.group)):\(other.name)" } - return entry + let use = (token.use ?? "").replacingOccurrences(of: "|", with: "/") + lines.append( + [ + typeName(group), token.name, type, value, alias, figmaScopes(token).joined(separator: ","), + "DesignTokens.\(typeName(group)).\(token.swiftName)", use, + ].joined(separator: "|")) } - collections[typeName(group)] = ["mode": "Value", "variables": variables] } - var gradientEntries: [String: Any] = [:] for gradient in gradients { - gradientEntries[gradient.name] = [ - "start": gradient.start, "end": gradient.end, "use": gradient.use ?? "", - "stops": gradient.stops.map { stop -> [String: Any] in - var entry: [String: Any] = ["location": stop.location, "value": resolveColor(stop.color)] - if case .alias(let target) = parseValue(stop.color), let other = byQualified[target] { - entry["alias"] = "\(typeName(other.group)):\(other.name)" - } - return entry - }, - ] + let stops = gradient.stops.map { "\(resolveColor($0.color))@\(format($0.location))" }.joined(separator: ",") + let use = (gradient.use ?? "").replacingOccurrences(of: "|", with: "/") + lines.append(["GRADIENT", gradient.name, gradient.start, gradient.end, stops, use].joined(separator: "|")) } - let root: [String: Any] = ["collections": collections, "gradients": gradientEntries, "groups": groups.map(typeName)] - guard let data = try? JSONSerialization.data(withJSONObject: root, options: [.prettyPrinted, .sortedKeys]), - let text = String(data: data, encoding: .utf8) - else { fail("could not encode the Figma token data") } + let text = lines.joined(separator: "\n").replacingOccurrences(of: "\\", with: "\\\\").replacingOccurrences( + of: "`", with: "\\`") return """ // Generated by scripts/design-tokens.swift from App/BlurtiOS/Design/tokens.json — do not edit. - // The build scripts in this folder (lib.js) read this; a use_figma call is - // tokens.js + lib.js + one line that returns a builder's result. - const TOKENS = \(text); + // One line per variable (collection|name|type|value|alias|scopes|codeSyntax|use) + // and per gradient (GRADIENT|name|start|end|stops|use); core.js parses it. + // scripts/design-figma-call.sh puts it in front of core.js + foundations.js. + const TOKEN_LINES = `\(text)`; + const GROUPS = \(groups.map(typeName).map { "\"\($0)\"" }.joined(separator: ", ").wrappedInBrackets); """ } +extension String { + var wrappedInBrackets: String { "[\(self)]" } +} + // MARK: - Write func write(_ text: String, to relative: String) { From 0f2cf47feea4f8c02a0a65b013face3e1d656f9b Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Tue, 29 Sep 2026 11:44:23 -0400 Subject: [PATCH 48/79] =?UTF-8?q?iOS=20keyboard:=20design=20pass=201=20?= =?UTF-8?q?=E2=80=94=20surface=20grain,=20a=20proportional=20orb=20light,?= =?UTF-8?q?=20and=20two=20variants=20behind=20tokens?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The brand's film grain over the whole keyboard surface (opacity/surface-grain, still, one seed), an optional vignette under the keys (opacity/surface-vignette, 0 by default), and the orb's soft light as a fraction of the orb (orb/light-reach 0.9) instead of a fixed 110 pt that washed the small orbs. Two directions to judge sit behind tokens at their old values: wave/liquid draws the recording wave as one smooth shape through the bar heights, and opacity/legend lets legends sit back. Key chrome moves to KeyChrome.swift, the surface finish to SurfaceFinish.swift. ios-record.sh gains --no-build. Captures and loops for baseline / v2 / v3 / v4 are in ~/Desktop/blurt-review. Co-Authored-By: Claude Fable 5.1 --- .../BlurtKeyboard/Sources/KeyChrome.swift | 19 +++ .../BlurtKeyboard/Sources/KeyboardViews.swift | 22 +-- .../BlurtKeyboard/Sources/PrismOrb.swift | 18 +- .../BlurtKeyboard/Sources/SurfaceFinish.swift | 38 +++++ .../BlurtKeyboard/Sources/VoiceBar.swift | 55 +++++- App/BlurtiOS/DESIGN.md | 156 +++++++++--------- App/BlurtiOS/Design/figma/tokens.js | 8 +- App/BlurtiOS/Design/tokens.json | 30 +++- App/BlurtiOS/Shared/DesignTokens.swift | 24 ++- scripts/design-sync.sh | 1 + scripts/ios-record.sh | 10 +- 11 files changed, 264 insertions(+), 117 deletions(-) create mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/KeyChrome.swift create mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/SurfaceFinish.swift diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyChrome.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyChrome.swift new file mode 100644 index 00000000..d2e2f885 --- /dev/null +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyChrome.swift @@ -0,0 +1,19 @@ +import SwiftUI + +extension View { + /// The cap under a key's legend: the palette's fill at the corner radius and + /// nothing else — flat. No drop, no edge, no gloss. + func keyCap(_ fill: Color) -> some View { + background(fill, in: RoundedRectangle(cornerRadius: KeyboardPalette.keyRadius)) + } +} + +/// A key lightens while the finger is on it, the way the system's change +/// shade, instead of the default button dimming. +struct KeyPressStyle: ButtonStyle { + func makeBody(configuration: Configuration) -> some View { + configuration.label + .brightness(configuration.isPressed ? DesignTokens.Metrics.opacityPressBrighten : 0) + .animation(.easeOut(duration: DesignTokens.Motion.keyPress), value: configuration.isPressed) + } +} diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift index aa6650f1..1fa9385a 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift @@ -30,7 +30,8 @@ struct KeyboardRootView: View { .padding(.horizontal, KeyboardPalette.margin) .padding(.vertical, Self.verticalMargin) .frame(maxWidth: .infinity, maxHeight: .infinity) - .background(model.palette.surface) + .background { SurfaceFinish.Ground(surface: model.palette.surface) } + .overlay { SurfaceFinish.Grain() } .clipped() .environment(\.keyboardPalette, model.palette) .simultaneousGesture(swipe, including: model.layout == .panel ? .all : .subviews) @@ -335,6 +336,7 @@ struct KeyCap: View { } .font(.system(size: DesignTokens.Typography.sizeLegend, weight: DesignTokens.Typography.weightLegend)) .foregroundStyle(tint ?? palette.keyText) + .opacity(DesignTokens.Metrics.opacityLegend) .frame(maxWidth: flexible ? .infinity : nil) .frame(width: width) .frame(minWidth: width == nil ? DesignTokens.Metrics.keyMinWidth : nil, minHeight: Self.height) @@ -379,21 +381,3 @@ struct KeyPress: ViewModifier { ) } } - -extension View { - /// The cap under a key's legend: the palette's fill at the corner radius and - /// nothing else — flat. No drop, no edge, no gloss. - func keyCap(_ fill: Color) -> some View { - background(fill, in: RoundedRectangle(cornerRadius: KeyboardPalette.keyRadius)) - } -} - -/// A key lightens while the finger is on it, the way the system's change -/// shade, instead of the default button dimming. -struct KeyPressStyle: ButtonStyle { - func makeBody(configuration: Configuration) -> some View { - configuration.label - .brightness(configuration.isPressed ? DesignTokens.Metrics.opacityPressBrighten : 0) - .animation(.easeOut(duration: DesignTokens.Motion.keyPress), value: configuration.isPressed) - } -} diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/PrismOrb.swift b/App/BlurtiOS/BlurtKeyboard/Sources/PrismOrb.swift index 3beb10ff..c7bd5856 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/PrismOrb.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/PrismOrb.swift @@ -44,16 +44,19 @@ struct PrismOrb: View { Rectangle().fill(mesh(at: time, drop: drop)) // A soft light from the upper left, so the disc reads as a body, not // a flat swatch — airy, not glossy. - Rectangle().fill( - RadialGradient( - colors: [.white.opacity(DesignTokens.Metrics.opacityOrbLight), .clear], - center: UnitPoint(x: DesignTokens.Metrics.orbLightX, y: DesignTokens.Metrics.orbLightY), startRadius: 0, - endRadius: DesignTokens.Metrics.orbLightRadius)) + GeometryReader { geo in + Rectangle().fill( + RadialGradient( + colors: [.white.opacity(DesignTokens.Metrics.opacityOrbLight), .clear], + center: UnitPoint(x: DesignTokens.Metrics.orbLightX, y: DesignTokens.Metrics.orbLightY), startRadius: 0, + endRadius: min(geo.size.width, geo.size.height) * DesignTokens.Metrics.orbLightReach)) + } if drop > 0 { Drop(amount: drop, elapsed: elapsed) Sparkles(elapsed: elapsed) // invariant-ok: the orb's star glyphs, not the Sparkle updater } - Grain(seed: animated ? Int(time * 24) : 7).opacity(DesignTokens.Metrics.opacityGrain).blendMode(.overlay) + BlurtiOSGrain(seed: animated ? Int(time * 24) : 7).opacity(DesignTokens.Metrics.opacityGrain).blendMode( + .overlay) } } .animation(.easeInOut(duration: DesignTokens.Motion.mood), value: mood) @@ -154,7 +157,8 @@ struct PrismOrb: View { /// Film grain: a scatter of faint dots, a new scatter each frame so it /// shimmers the way grain does, drawn from a seed so a frame is reproducible. -private struct Grain: View { +/// The orb's, and — still, one seed — the keyboard surface's (`SurfaceFinish`). +struct BlurtiOSGrain: View { let seed: Int var body: some View { diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/SurfaceFinish.swift b/App/BlurtiOS/BlurtKeyboard/Sources/SurfaceFinish.swift new file mode 100644 index 00000000..c96338ad --- /dev/null +++ b/App/BlurtiOS/BlurtKeyboard/Sources/SurfaceFinish.swift @@ -0,0 +1,38 @@ +import SwiftUI + +/// The surface's finish. Under the keys: the palette's flat colour and, when +/// the tokens ask for one, a soft vignette toward the edges. Over everything: +/// the brand's film grain, still (one seed, no shimmer — a keyboard has no +/// energy to spare), so every theme reads matte rather than painted. Neither +/// takes a touch. +enum SurfaceFinish { + struct Ground: View { + let surface: Color + + var body: some View { + GeometryReader { geo in + ZStack { + surface + if DesignTokens.Metrics.opacitySurfaceVignette > 0 { + Rectangle().fill( + RadialGradient( + colors: [.clear, .black.opacity(DesignTokens.Metrics.opacitySurfaceVignette)], center: .center, + startRadius: geo.size.width * DesignTokens.Metrics.surfaceVignetteStart, + endRadius: geo.size.width * DesignTokens.Metrics.surfaceVignetteEnd)) + } + } + } + .accessibilityHidden(true) + } + } + + struct Grain: View { + var body: some View { + BlurtiOSGrain(seed: 7) + .opacity(DesignTokens.Metrics.opacitySurfaceGrain) + .blendMode(.overlay) + .allowsHitTesting(false) + .accessibilityHidden(true) + } + } +} diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift index 8adb9ca6..435d7d69 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift @@ -181,14 +181,55 @@ struct WaveformMeter: View { .accessibilityHidden(true) } - private func bars(layout: MeterBarRow, time: TimeInterval) -> some View { - HStack(spacing: barSpacing) { - ForEach(0.. some View { + if DesignTokens.Metrics.waveLiquid > 0 { + liquid(layout: layout, time: time) + } else { + HStack(spacing: barSpacing) { + ForEach(0.. some View { + GeometryReader { geo in + let pitch = barWidth + barSpacing + // literal-ok: centring the row, and the middle of the bar + let inset = (geo.size.width - CGFloat(layout.count) * pitch + barSpacing) / 2 + barWidth / 2 // literal-ok: ½ + let mid = geo.size.height / 2 // literal-ok: the middle + let points = (0.. CGPoint in + let h = layout.height(at: index, level: level, time: time, animated: animated) + return CGPoint(x: inset + CGFloat(index) * pitch, y: h / 2) // literal-ok: half height + } + Path { path in + guard let first = points.first, let last = points.last else { return } + path.move(to: CGPoint(x: first.x, y: mid - first.y)) + for i in 1.. -| Token | Points | Swift | Use | -| ----------------------------- | ------- | ---------------------------------- | ------------------------------------------------------------------------ | -| `addterm/inset` | `6` | `Metrics.addtermInset` | the + from the panel's corner | -| `card/border` | `1` | `Metrics.cardBorder` | the card's hairline | -| `card/radius` | `16` | `Metrics.cardRadius` | the app's cards | -| `caret/height` | `20` | `Metrics.caretHeight` | — | -| `caret/lead` | `1` | `Metrics.caretLead` | the caret's gap from the text | -| `caret/radius` | `1` | `Metrics.caretRadius` | — | -| `caret/width` | `2` | `Metrics.caretWidth` | — | -| `gesture/swipe-min` | `24` | `Metrics.gestureSwipeMin` | the carousel gesture's minimum distance | -| `glyph/hit` | `32` | `Metrics.glyphHit` | the +, × and ✓ touch targets | -| `key/gap` | `6` | `Metrics.keyGap` | between keys, the iPhone's | -| `key/height` | `42` | `Metrics.keyHeight` | every key | -| `key/letter-width-402` | `34.8` | `Metrics.keyLetterWidth402` | a letter key at 402 pt (iPhone 18 Pro): (width − 9 × key/gap) / 10 | -| `key/min-width` | `44` | `Metrics.keyMinWidth` | a key that isn't given a width | -| `key/pad` | `4` | `Metrics.keyPad` | a legend's side padding on a min-width key | -| `key/radius` | `8` | `Metrics.keyRadius` | flat keys, one colour at this corner | -| `key/return-width-402` | `104.4` | `Metrics.keyReturnWidth402` | return at 402 pt: two side keys and a gap | -| `key/side-gap-factor` | `2` | `Metrics.keySideGapFactor` | shift and delete stand this many key gaps from the letters | -| `key/side-width-402` | `49.2` | `Metrics.keySideWidth402` | shift, delete, 123 and globe at 402 pt: what seven letters leave, halved | -| `layout/full` | `272` | `Metrics.layoutFull` | 2 × margin/vertical + voicebar/height + 4 × row/gap + 4 × key/height | -| `layout/panel` | `216` | `Metrics.layoutPanel` | chosen: room for the 96 orb over one key row | -| `layout/slim` | `60` | `Metrics.layoutSlim` | 2 × margin/vertical + voicebar/height | -| `margin/side` | `3` | `Metrics.marginSide` | at the keyboard's sides | -| `margin/vertical` | `8` | `Metrics.marginVertical` | the keyboard's top and bottom | -| `opacity/dim` | `0.8` | `Metrics.opacityDim` | the orb when Blurt isn't ready | -| `opacity/dim-saturation` | `0.35` | `Metrics.opacityDimSaturation` | and its saturation | -| `opacity/disabled` | `0.4` | `Metrics.opacityDisabled` | the + without Full Access | -| `opacity/grain` | `0.5` | `Metrics.opacityGrain` | — | -| `opacity/home-dim-saturation` | `0.45` | `Metrics.opacityHomeDimSaturation` | the home hero's saturation when not listening | -| `opacity/legend-muted` | `0.5` | `Metrics.opacityLegendMuted` | the + at rest | -| `opacity/orb-light` | `0.3` | `Metrics.opacityOrbLight` | — | -| `opacity/placeholder` | `0.4` | `Metrics.opacityPlaceholder` | the field's placeholder | -| `opacity/popup-shadow` | `0.12` | `Metrics.opacityPopupShadow` | — | -| `opacity/press-brighten` | `0.15` | `Metrics.opacityPressBrighten` | a key lightens this much while pressed | -| `opacity/term-cancel` | `0.7` | `Metrics.opacityTermCancel` | the field's × | -| `orb/bar` | `40` | `Metrics.orbBar` | the orb in the voice bar | -| `orb/dissipate-blur` | `0.16` | `Metrics.orbDissipateBlur` | and blurs to this fraction of its size | -| `orb/dissipate-scale` | `1.25` | `Metrics.orbDissipateScale` | the orb swells to this while dissipating | -| `orb/home` | `112` | `Metrics.orbHome` | the orb on the home screen | -| `orb/light-radius` | `110` | `Metrics.orbLightRadius` | the light's reach in points (fixed, not proportional — open) | -| `orb/light-x` | `0.3` | `Metrics.orbLightX` | the soft light's centre, as a fraction of the orb | -| `orb/light-y` | `0.22` | `Metrics.orbLightY` | — | -| `orb/panel` | `96` | `Metrics.orbPanel` | the orb in the panel | -| `panel/spacing` | `12` | `Metrics.panelSpacing` | between the panel's orb and its key row | -| `picker/preview-width` | `393` | `Metrics.pickerPreviewWidth` | the theme card draws the keyboard at this width | -| `picker/radius` | `10` | `Metrics.pickerRadius` | the theme card's preview corners | -| `picker/scale` | `0.42` | `Metrics.pickerScale` | then scales it to fit two across | -| `popup/extra-width` | `18` | `Metrics.popupExtraWidth` | the letter pop-up is the key width plus this | -| `popup/height` | `56` | `Metrics.popupHeight` | — | -| `popup/offset` | `58` | `Metrics.popupOffset` | the pop-up sits this far above the key | -| `popup/radius` | `10` | `Metrics.popupRadius` | — | -| `popup/shadow-radius` | `8` | `Metrics.popupShadowRadius` | the one thing that floats | -| `popup/shadow-y` | `2` | `Metrics.popupShadowY` | — | -| `press/scale` | `0.94` | `Metrics.pressScale` | the orb while pressed | -| `ring/active` | `2` | `Metrics.ringActive` | the ring while working or noticing; the home ring | -| `ring/still` | `1` | `Metrics.ringStill` | the ring at rest | -| `row/gap` | `11` | `Metrics.rowGap` | between rows, the iPhone's | -| `slim/spacing` | `8` | `Metrics.slimSpacing` | between the slim bar's keys | -| `term/gap` | `8` | `Metrics.termGap` | × · field · ✓ | -| `term/height` | `36` | `Metrics.termHeight` | the key-term field's capsule | -| `term/inset` | `2` | `Metrics.termInset` | the field row's side inset | -| `term/pad` | `14` | `Metrics.termPad` | the field's side padding | -| `voicebar/addterm-clearance` | `12` | `Metrics.voicebarAddtermClearance` | the wave stays this clear of the + at the trailing edge | -| `voicebar/height` | `44` | `Metrics.voicebarHeight` | the voice row, where the system puts its suggestion bar | -| `voicebar/note-gap` | `10` | `Metrics.voicebarNoteGap` | between the orb and the Full Access note | -| `wave/bar` | `2` | `Metrics.waveBar` | a wave bar's width | -| `wave/bar-height` | `24` | `Metrics.waveBarHeight` | — | -| `wave/bar-width` | `240` | `Metrics.waveBarWidth` | the wave in the voice bar, at most | -| `wave/gap` | `2` | `Metrics.waveGap` | between wave bars | -| `wave/home-height` | `44` | `Metrics.waveHomeHeight` | — | -| `wave/home-width` | `280` | `Metrics.waveHomeWidth` | — | -| `wave/panel-height` | `40` | `Metrics.wavePanelHeight` | — | -| `wave/panel-width` | `300` | `Metrics.wavePanelWidth` | — | -| `wordmark/height` | `22` | `Metrics.wordmarkHeight` | — | +| Token | Points | Swift | Use | +| ----------------------------- | ------- | ---------------------------------- | ------------------------------------------------------------------------------------------- | +| `addterm/inset` | `6` | `Metrics.addtermInset` | the + from the panel's corner | +| `card/border` | `1` | `Metrics.cardBorder` | the card's hairline | +| `card/radius` | `16` | `Metrics.cardRadius` | the app's cards | +| `caret/height` | `20` | `Metrics.caretHeight` | — | +| `caret/lead` | `1` | `Metrics.caretLead` | the caret's gap from the text | +| `caret/radius` | `1` | `Metrics.caretRadius` | — | +| `caret/width` | `2` | `Metrics.caretWidth` | — | +| `gesture/swipe-min` | `24` | `Metrics.gestureSwipeMin` | the carousel gesture's minimum distance | +| `glyph/hit` | `32` | `Metrics.glyphHit` | the +, × and ✓ touch targets | +| `key/gap` | `6` | `Metrics.keyGap` | between keys, the iPhone's | +| `key/height` | `42` | `Metrics.keyHeight` | every key | +| `key/letter-width-402` | `34.8` | `Metrics.keyLetterWidth402` | a letter key at 402 pt (iPhone 18 Pro): (width − 9 × key/gap) / 10 | +| `key/min-width` | `44` | `Metrics.keyMinWidth` | a key that isn't given a width | +| `key/pad` | `4` | `Metrics.keyPad` | a legend's side padding on a min-width key | +| `key/radius` | `8` | `Metrics.keyRadius` | flat keys, one colour at this corner | +| `key/return-width-402` | `104.4` | `Metrics.keyReturnWidth402` | return at 402 pt: two side keys and a gap | +| `key/side-gap-factor` | `2` | `Metrics.keySideGapFactor` | shift and delete stand this many key gaps from the letters | +| `key/side-width-402` | `49.2` | `Metrics.keySideWidth402` | shift, delete, 123 and globe at 402 pt: what seven letters leave, halved | +| `layout/full` | `272` | `Metrics.layoutFull` | 2 × margin/vertical + voicebar/height + 4 × row/gap + 4 × key/height | +| `layout/panel` | `216` | `Metrics.layoutPanel` | chosen: room for the 96 orb over one key row | +| `layout/slim` | `60` | `Metrics.layoutSlim` | 2 × margin/vertical + voicebar/height | +| `margin/side` | `3` | `Metrics.marginSide` | at the keyboard's sides | +| `margin/vertical` | `8` | `Metrics.marginVertical` | the keyboard's top and bottom | +| `opacity/dim` | `0.8` | `Metrics.opacityDim` | the orb when Blurt isn't ready | +| `opacity/dim-saturation` | `0.35` | `Metrics.opacityDimSaturation` | and its saturation | +| `opacity/disabled` | `0.4` | `Metrics.opacityDisabled` | the + without Full Access | +| `opacity/grain` | `0.5` | `Metrics.opacityGrain` | — | +| `opacity/home-dim-saturation` | `0.45` | `Metrics.opacityHomeDimSaturation` | the home hero's saturation when not listening | +| `opacity/legend` | `1` | `Metrics.opacityLegend` | key legends over the cap; below 1 they sit back | +| `opacity/legend-muted` | `0.5` | `Metrics.opacityLegendMuted` | the + at rest | +| `opacity/orb-light` | `0.3` | `Metrics.opacityOrbLight` | — | +| `opacity/placeholder` | `0.4` | `Metrics.opacityPlaceholder` | the field's placeholder | +| `opacity/popup-shadow` | `0.12` | `Metrics.opacityPopupShadow` | — | +| `opacity/press-brighten` | `0.15` | `Metrics.opacityPressBrighten` | a key lightens this much while pressed | +| `opacity/surface-grain` | `0.14` | `Metrics.opacitySurfaceGrain` | film grain over the whole keyboard surface: matte, the brand's texture | +| `opacity/surface-vignette` | `0` | `Metrics.opacitySurfaceVignette` | a soft darkening toward the surface's edges; 0 is none | +| `opacity/term-cancel` | `0.7` | `Metrics.opacityTermCancel` | the field's × | +| `orb/bar` | `40` | `Metrics.orbBar` | the orb in the voice bar | +| `orb/dissipate-blur` | `0.16` | `Metrics.orbDissipateBlur` | and blurs to this fraction of its size | +| `orb/dissipate-scale` | `1.25` | `Metrics.orbDissipateScale` | the orb swells to this while dissipating | +| `orb/home` | `112` | `Metrics.orbHome` | the orb on the home screen | +| `orb/light-reach` | `0.9` | `Metrics.orbLightReach` | the soft light's reach, as a fraction of the orb (was a fixed 110 pt, flat on a 40 pt orb) | +| `orb/light-x` | `0.3` | `Metrics.orbLightX` | the soft light's centre, as a fraction of the orb | +| `orb/light-y` | `0.22` | `Metrics.orbLightY` | — | +| `orb/panel` | `96` | `Metrics.orbPanel` | the orb in the panel | +| `panel/spacing` | `12` | `Metrics.panelSpacing` | between the panel's orb and its key row | +| `picker/preview-width` | `393` | `Metrics.pickerPreviewWidth` | the theme card draws the keyboard at this width | +| `picker/radius` | `10` | `Metrics.pickerRadius` | the theme card's preview corners | +| `picker/scale` | `0.42` | `Metrics.pickerScale` | then scales it to fit two across | +| `popup/extra-width` | `18` | `Metrics.popupExtraWidth` | the letter pop-up is the key width plus this | +| `popup/height` | `56` | `Metrics.popupHeight` | — | +| `popup/offset` | `58` | `Metrics.popupOffset` | the pop-up sits this far above the key | +| `popup/radius` | `10` | `Metrics.popupRadius` | — | +| `popup/shadow-radius` | `8` | `Metrics.popupShadowRadius` | the one thing that floats | +| `popup/shadow-y` | `2` | `Metrics.popupShadowY` | — | +| `press/scale` | `0.94` | `Metrics.pressScale` | the orb while pressed | +| `ring/active` | `2` | `Metrics.ringActive` | the ring while working or noticing; the home ring | +| `ring/still` | `1` | `Metrics.ringStill` | the ring at rest | +| `row/gap` | `11` | `Metrics.rowGap` | between rows, the iPhone's | +| `slim/spacing` | `8` | `Metrics.slimSpacing` | between the slim bar's keys | +| `surface/vignette-end` | `0.75` | `Metrics.surfaceVignetteEnd` | where it is full | +| `surface/vignette-start` | `0.3` | `Metrics.surfaceVignetteStart` | where the vignette begins, as a fraction of the keyboard's width | +| `term/gap` | `8` | `Metrics.termGap` | × · field · ✓ | +| `term/height` | `36` | `Metrics.termHeight` | the key-term field's capsule | +| `term/inset` | `2` | `Metrics.termInset` | the field row's side inset | +| `term/pad` | `14` | `Metrics.termPad` | the field's side padding | +| `voicebar/addterm-clearance` | `12` | `Metrics.voicebarAddtermClearance` | the wave stays this clear of the + at the trailing edge | +| `voicebar/height` | `44` | `Metrics.voicebarHeight` | the voice row, where the system puts its suggestion bar | +| `voicebar/note-gap` | `10` | `Metrics.voicebarNoteGap` | between the orb and the Full Access note | +| `wave/bar` | `2` | `Metrics.waveBar` | a wave bar's width | +| `wave/bar-height` | `24` | `Metrics.waveBarHeight` | — | +| `wave/bar-width` | `240` | `Metrics.waveBarWidth` | the wave in the voice bar, at most | +| `wave/gap` | `2` | `Metrics.waveGap` | between wave bars | +| `wave/home-height` | `44` | `Metrics.waveHomeHeight` | — | +| `wave/home-width` | `280` | `Metrics.waveHomeWidth` | — | +| `wave/liquid` | `0` | `Metrics.waveLiquid` | 1 draws the wave as one liquid shape through the bar heights instead of the bars themselves | +| `wave/panel-height` | `40` | `Metrics.wavePanelHeight` | — | +| `wave/panel-width` | `300` | `Metrics.wavePanelWidth` | — | +| `wordmark/height` | `22` | `Metrics.wordmarkHeight` | — | diff --git a/App/BlurtiOS/Design/figma/tokens.js b/App/BlurtiOS/Design/figma/tokens.js index 11433887..162193d3 100644 --- a/App/BlurtiOS/Design/figma/tokens.js +++ b/App/BlurtiOS/Design/figma/tokens.js @@ -121,17 +121,20 @@ Metrics|opacity/dim-saturation|FLOAT|0.35||OPACITY|DesignTokens.Metrics.opacityD Metrics|opacity/disabled|FLOAT|0.4||OPACITY|DesignTokens.Metrics.opacityDisabled|the + without Full Access Metrics|opacity/grain|FLOAT|0.5||OPACITY|DesignTokens.Metrics.opacityGrain| Metrics|opacity/home-dim-saturation|FLOAT|0.45||OPACITY|DesignTokens.Metrics.opacityHomeDimSaturation|the home hero's saturation when not listening +Metrics|opacity/legend|FLOAT|1||OPACITY|DesignTokens.Metrics.opacityLegend|key legends over the cap; below 1 they sit back Metrics|opacity/legend-muted|FLOAT|0.5||OPACITY|DesignTokens.Metrics.opacityLegendMuted|the + at rest Metrics|opacity/orb-light|FLOAT|0.3||OPACITY|DesignTokens.Metrics.opacityOrbLight| Metrics|opacity/placeholder|FLOAT|0.4||OPACITY|DesignTokens.Metrics.opacityPlaceholder|the field's placeholder Metrics|opacity/popup-shadow|FLOAT|0.12||OPACITY|DesignTokens.Metrics.opacityPopupShadow| Metrics|opacity/press-brighten|FLOAT|0.15||OPACITY|DesignTokens.Metrics.opacityPressBrighten|a key lightens this much while pressed +Metrics|opacity/surface-grain|FLOAT|0.14||OPACITY|DesignTokens.Metrics.opacitySurfaceGrain|film grain over the whole keyboard surface: matte, the brand's texture +Metrics|opacity/surface-vignette|FLOAT|0||OPACITY|DesignTokens.Metrics.opacitySurfaceVignette|a soft darkening toward the surface's edges; 0 is none Metrics|opacity/term-cancel|FLOAT|0.7||OPACITY|DesignTokens.Metrics.opacityTermCancel|the field's × Metrics|orb/bar|FLOAT|40||WIDTH_HEIGHT|DesignTokens.Metrics.orbBar|the orb in the voice bar Metrics|orb/dissipate-blur|FLOAT|0.16|||DesignTokens.Metrics.orbDissipateBlur|and blurs to this fraction of its size Metrics|orb/dissipate-scale|FLOAT|1.25|||DesignTokens.Metrics.orbDissipateScale|the orb swells to this while dissipating Metrics|orb/home|FLOAT|112||WIDTH_HEIGHT|DesignTokens.Metrics.orbHome|the orb on the home screen -Metrics|orb/light-radius|FLOAT|110|||DesignTokens.Metrics.orbLightRadius|the light's reach in points (fixed, not proportional — open) +Metrics|orb/light-reach|FLOAT|0.9|||DesignTokens.Metrics.orbLightReach|the soft light's reach, as a fraction of the orb (was a fixed 110 pt, flat on a 40 pt orb) Metrics|orb/light-x|FLOAT|0.3|||DesignTokens.Metrics.orbLightX|the soft light's centre, as a fraction of the orb Metrics|orb/light-y|FLOAT|0.22|||DesignTokens.Metrics.orbLightY| Metrics|orb/panel|FLOAT|96||WIDTH_HEIGHT|DesignTokens.Metrics.orbPanel|the orb in the panel @@ -150,6 +153,8 @@ Metrics|ring/active|FLOAT|2||STROKE_FLOAT,WIDTH_HEIGHT|DesignTokens.Metrics.ring Metrics|ring/still|FLOAT|1||STROKE_FLOAT,WIDTH_HEIGHT|DesignTokens.Metrics.ringStill|the ring at rest Metrics|row/gap|FLOAT|11||GAP|DesignTokens.Metrics.rowGap|between rows, the iPhone's Metrics|slim/spacing|FLOAT|8||GAP|DesignTokens.Metrics.slimSpacing|between the slim bar's keys +Metrics|surface/vignette-end|FLOAT|0.75||WIDTH_HEIGHT|DesignTokens.Metrics.surfaceVignetteEnd|where it is full +Metrics|surface/vignette-start|FLOAT|0.3||WIDTH_HEIGHT|DesignTokens.Metrics.surfaceVignetteStart|where the vignette begins, as a fraction of the keyboard's width Metrics|term/gap|FLOAT|8||GAP|DesignTokens.Metrics.termGap|× · field · ✓ Metrics|term/height|FLOAT|36||WIDTH_HEIGHT|DesignTokens.Metrics.termHeight|the key-term field's capsule Metrics|term/inset|FLOAT|2||GAP|DesignTokens.Metrics.termInset|the field row's side inset @@ -163,6 +168,7 @@ Metrics|wave/bar-width|FLOAT|240||WIDTH_HEIGHT|DesignTokens.Metrics.waveBarWidth Metrics|wave/gap|FLOAT|2||GAP|DesignTokens.Metrics.waveGap|between wave bars Metrics|wave/home-height|FLOAT|44||WIDTH_HEIGHT|DesignTokens.Metrics.waveHomeHeight| Metrics|wave/home-width|FLOAT|280||WIDTH_HEIGHT|DesignTokens.Metrics.waveHomeWidth| +Metrics|wave/liquid|FLOAT|0||WIDTH_HEIGHT|DesignTokens.Metrics.waveLiquid|1 draws the wave as one liquid shape through the bar heights instead of the bars themselves Metrics|wave/panel-height|FLOAT|40||WIDTH_HEIGHT|DesignTokens.Metrics.wavePanelHeight| Metrics|wave/panel-width|FLOAT|300||WIDTH_HEIGHT|DesignTokens.Metrics.wavePanelWidth| Metrics|wordmark/height|FLOAT|22||WIDTH_HEIGHT|DesignTokens.Metrics.wordmarkHeight| diff --git a/App/BlurtiOS/Design/tokens.json b/App/BlurtiOS/Design/tokens.json index 47ecda90..59fc4515 100644 --- a/App/BlurtiOS/Design/tokens.json +++ b/App/BlurtiOS/Design/tokens.json @@ -385,6 +385,10 @@ "value": 2, "use": "between wave bars" }, + "wave/liquid": { + "value": 0, + "use": "1 draws the wave as one liquid shape through the bar heights instead of the bars themselves" + }, "ring/still": { "value": 1, "use": "the ring at rest" @@ -501,9 +505,9 @@ "orb/light-y": { "value": 0.22 }, - "orb/light-radius": { - "value": 110, - "use": "the light's reach in points (fixed, not proportional — open)" + "orb/light-reach": { + "value": 0.9, + "use": "the soft light's reach, as a fraction of the orb (was a fixed 110 pt, flat on a 40 pt orb)" }, "orb/dissipate-scale": { "value": 1.25, @@ -545,6 +549,10 @@ "value": 0.15, "use": "a key lightens this much while pressed" }, + "opacity/legend": { + "value": 1, + "use": "key legends over the cap; below 1 they sit back" + }, "opacity/popup-shadow": { "value": 0.12 }, @@ -554,6 +562,22 @@ "opacity/grain": { "value": 0.5 }, + "opacity/surface-grain": { + "value": 0.14, + "use": "film grain over the whole keyboard surface: matte, the brand's texture" + }, + "opacity/surface-vignette": { + "value": 0.0, + "use": "a soft darkening toward the surface's edges; 0 is none" + }, + "surface/vignette-start": { + "value": 0.3, + "use": "where the vignette begins, as a fraction of the keyboard's width" + }, + "surface/vignette-end": { + "value": 0.75, + "use": "where it is full" + }, "press/scale": { "value": 0.94, "use": "the orb while pressed" diff --git a/App/BlurtiOS/Shared/DesignTokens.swift b/App/BlurtiOS/Shared/DesignTokens.swift index 89e6a9a3..bf57b8d0 100644 --- a/App/BlurtiOS/Shared/DesignTokens.swift +++ b/App/BlurtiOS/Shared/DesignTokens.swift @@ -233,6 +233,8 @@ enum DesignTokens { nonisolated static let opacityGrain: CGFloat = 0.5 /// The home hero's saturation when not listening. nonisolated static let opacityHomeDimSaturation: CGFloat = 0.45 + /// Key legends over the cap; below 1 they sit back. + nonisolated static let opacityLegend: CGFloat = 1 /// The + at rest. nonisolated static let opacityLegendMuted: CGFloat = 0.5 nonisolated static let opacityOrbLight: CGFloat = 0.3 @@ -241,6 +243,10 @@ enum DesignTokens { nonisolated static let opacityPopupShadow: CGFloat = 0.12 /// A key lightens this much while pressed. nonisolated static let opacityPressBrighten: CGFloat = 0.15 + /// Film grain over the whole keyboard surface: matte, the brand's texture. + nonisolated static let opacitySurfaceGrain: CGFloat = 0.14 + /// A soft darkening toward the surface's edges; 0 is none. + nonisolated static let opacitySurfaceVignette: CGFloat = 0 /// The field's ×. nonisolated static let opacityTermCancel: CGFloat = 0.7 /// The orb in the voice bar. @@ -251,8 +257,8 @@ enum DesignTokens { nonisolated static let orbDissipateScale: CGFloat = 1.25 /// The orb on the home screen. nonisolated static let orbHome: CGFloat = 112 - /// The light's reach in points (fixed, not proportional — open). - nonisolated static let orbLightRadius: CGFloat = 110 + /// The soft light's reach, as a fraction of the orb (was a fixed 110 pt, flat on a 40 pt orb). + nonisolated static let orbLightReach: CGFloat = 0.9 /// The soft light's centre, as a fraction of the orb. nonisolated static let orbLightX: CGFloat = 0.3 nonisolated static let orbLightY: CGFloat = 0.22 @@ -285,6 +291,10 @@ enum DesignTokens { nonisolated static let rowGap: CGFloat = 11 /// Between the slim bar's keys. nonisolated static let slimSpacing: CGFloat = 8 + /// Where it is full. + nonisolated static let surfaceVignetteEnd: CGFloat = 0.75 + /// Where the vignette begins, as a fraction of the keyboard's width. + nonisolated static let surfaceVignetteStart: CGFloat = 0.3 /// × · field · ✓. nonisolated static let termGap: CGFloat = 8 /// The key-term field's capsule. @@ -308,6 +318,8 @@ enum DesignTokens { nonisolated static let waveGap: CGFloat = 2 nonisolated static let waveHomeHeight: CGFloat = 44 nonisolated static let waveHomeWidth: CGFloat = 280 + /// 1 draws the wave as one liquid shape through the bar heights instead of the bars themselves. + nonisolated static let waveLiquid: CGFloat = 0 nonisolated static let wavePanelHeight: CGFloat = 40 nonisolated static let wavePanelWidth: CGFloat = 300 nonisolated static let wordmarkHeight: CGFloat = 22 @@ -510,17 +522,20 @@ enum DesignTokens { "metrics.opacity/disabled": "0.4", "metrics.opacity/grain": "0.5", "metrics.opacity/home-dim-saturation": "0.45", + "metrics.opacity/legend": "1", "metrics.opacity/legend-muted": "0.5", "metrics.opacity/orb-light": "0.3", "metrics.opacity/placeholder": "0.4", "metrics.opacity/popup-shadow": "0.12", "metrics.opacity/press-brighten": "0.15", + "metrics.opacity/surface-grain": "0.14", + "metrics.opacity/surface-vignette": "0", "metrics.opacity/term-cancel": "0.7", "metrics.orb/bar": "40", "metrics.orb/dissipate-blur": "0.16", "metrics.orb/dissipate-scale": "1.25", "metrics.orb/home": "112", - "metrics.orb/light-radius": "110", + "metrics.orb/light-reach": "0.9", "metrics.orb/light-x": "0.3", "metrics.orb/light-y": "0.22", "metrics.orb/panel": "96", @@ -539,6 +554,8 @@ enum DesignTokens { "metrics.ring/still": "1", "metrics.row/gap": "11", "metrics.slim/spacing": "8", + "metrics.surface/vignette-end": "0.75", + "metrics.surface/vignette-start": "0.3", "metrics.term/gap": "8", "metrics.term/height": "36", "metrics.term/inset": "2", @@ -552,6 +569,7 @@ enum DesignTokens { "metrics.wave/gap": "2", "metrics.wave/home-height": "44", "metrics.wave/home-width": "280", + "metrics.wave/liquid": "0", "metrics.wave/panel-height": "40", "metrics.wave/panel-width": "300", "metrics.wordmark/height": "22", diff --git a/scripts/design-sync.sh b/scripts/design-sync.sh index d2574af5..caee5eda 100755 --- a/scripts/design-sync.sh +++ b/scripts/design-sync.sh @@ -72,6 +72,7 @@ files = [ "App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift", "App/BlurtiOS/BlurtKeyboard/Sources/Dissipate.swift", "App/BlurtiOS/BlurtKeyboard/Sources/BrandOrb.swift", + "App/BlurtiOS/BlurtKeyboard/Sources/SurfaceFinish.swift", ] modifiers = re.compile( r"\.(padding|frame|font|blur|scaleEffect|offset|shadow|opacity|cornerRadius|saturation|brightness" diff --git a/scripts/ios-record.sh b/scripts/ios-record.sh index 9d2cc824..9051fc1c 100755 --- a/scripts/ios-record.sh +++ b/scripts/ios-record.sh @@ -22,6 +22,7 @@ THEME=ink OUT="$REPO_ROOT/.build/design/loops" FRAMES="" CYCLE=11.7 +BUILD=() while [ $# -gt 0 ]; do case "$1" in --layout) @@ -40,8 +41,12 @@ while [ $# -gt 0 ]; do FRAMES="${2:?}" shift 2 ;; + --no-build) + BUILD=(--no-build) + shift + ;; *) - echo "usage: ios-record.sh [--layout L] [--theme T] [--out DIR] [--frames s,s,…]" >&2 + echo "usage: ios-record.sh [--layout L] [--theme T] [--out DIR] [--frames s,s,…] [--no-build]" >&2 exit 2 ;; esac @@ -54,7 +59,8 @@ mkdir -p "$OUT" name="$LAYOUT-$THEME" # A still first: it builds, boots, and gives the crop rectangle. -scripts/design-capture.sh --layout "$LAYOUT" --states idle --themes "$THEME" --out "$OUT/.still" >/dev/null +scripts/design-capture.sh --layout "$LAYOUT" --states idle --themes "$THEME" --out "$OUT/.still" \ + ${BUILD[@]+"${BUILD[@]}"} >/dev/null raw="$OUT/.still/$LAYOUT-idle-$THEME.raw.png" read -r CROP_W CROP_H CROP_X CROP_Y < <(swift scripts/design-diff.swift crop "$raw" "$OUT/.still/crop-probe.png" \ | sed -E 's/crop: ([0-9]+)×([0-9]+) at \(([0-9]+),([0-9]+)\).*/\1 \2 \3 \4/') From 71fdd86b2bd1ee77c93135492aba0cbf126a34d8 Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Tue, 29 Sep 2026 15:57:24 -0400 Subject: [PATCH 49/79] iOS: the brand's faces as bundled fonts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Modern Gothic Mono (Light, Regular, Medium), UN 11ST (Regular, Bold) and Oceanic Text (Regular), from the website repo's public/_aai/fonts/rebrand, registered through UIAppFonts in both the app and the keyboard — an extension cannot read the app's bundle, so each carries its own copy. Nothing draws with them yet. PostScript names (what Font.custom takes; the UN 11ST files are named with underscores but the fonts are UN-11ST-Regular / UN-11ST-Bold, family "UN-11 ST"): ModernGothicMono-{Light,Regular,Medium}, OceanicText-Regular. The website's licence for these faces covers the web; app embedding, and committing the files to a repo that will merge into the public MIT AssemblyAI/blurt, is to be confirmed with Brand Studio before any upstream merge. Private repo only until then. Co-Authored-By: Claude Fable 5.1 --- .../Design/fonts/ModernGothicMono-Light.ttf | Bin 0 -> 56160 bytes .../Design/fonts/ModernGothicMono-Medium.ttf | Bin 0 -> 59148 bytes .../Design/fonts/ModernGothicMono-Regular.ttf | Bin 0 -> 58776 bytes .../Design/fonts/OceanicText-Regular.otf | Bin 0 -> 91688 bytes App/BlurtiOS/Design/fonts/UN_11ST_Bold.ttf | Bin 0 -> 95152 bytes App/BlurtiOS/Design/fonts/UN_11ST_Regular.ttf | Bin 0 -> 92392 bytes App/BlurtiOS/project.yml | 21 ++++++++++++++++++ 7 files changed, 21 insertions(+) create mode 100644 App/BlurtiOS/Design/fonts/ModernGothicMono-Light.ttf create mode 100644 App/BlurtiOS/Design/fonts/ModernGothicMono-Medium.ttf create mode 100644 App/BlurtiOS/Design/fonts/ModernGothicMono-Regular.ttf create mode 100644 App/BlurtiOS/Design/fonts/OceanicText-Regular.otf create mode 100644 App/BlurtiOS/Design/fonts/UN_11ST_Bold.ttf create mode 100644 App/BlurtiOS/Design/fonts/UN_11ST_Regular.ttf diff --git a/App/BlurtiOS/Design/fonts/ModernGothicMono-Light.ttf b/App/BlurtiOS/Design/fonts/ModernGothicMono-Light.ttf new file mode 100644 index 0000000000000000000000000000000000000000..1b39fa83a9d0402eb8501b12967d62b2ba6e3b76 GIT binary patch literal 56160 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 BJBR=P literal 0 HcmV?d00001 diff --git a/App/BlurtiOS/Design/fonts/ModernGothicMono-Medium.ttf b/App/BlurtiOS/Design/fonts/ModernGothicMono-Medium.ttf new file mode 100644 index 0000000000000000000000000000000000000000..20f1a54f78a0fbf2755481bf1abe4db2caf60ffb GIT binary patch literal 59148 zcmb5W2V4}#`v*L8W$)NU1U82X?%jdCgT0H2*c@nD5?+ttJ zvBub2j6I1hnbSSv`<>mhB>De7@B4yZp4q9-PI>0pXP&Wb$Bu1@H_0VN65cp6(z$+9 z@>xQHE)%l2Y14=%k-kyBPD1tqWJc3=Z96y)R}aSXWXX#{?^ zBi%_T&q@wm9e?QaJ_YOkX*C)jB8J?WJ1K|L`*&vk@YenJBf-zO1dm2y;Ia5YIpc z75-5VW)*s$k3ew%VRIhuW$oEWMD5vR=5u&H$;G%9#XPA*YLSt&9Ia0~(UFEALk+`G z!wsX!Xf=8pWn(d8Y2!Y7340CuIQs(oZu?88)hRjsoS!)Zopxu4v!pZBS;bk~8R1NG z4s}j+E^)4Q<~w&g_XZaV4hb$9Trs#$@WkLbA%+kkq+p1DNMMLPq+Cd|kiH>tA%}}6 z7Jpp)U5SMyPL?=RYGkSLr6!j8=C+_3{(krF?Ynp2vH~Ri?bYqM;BJ@wh0_A=e4Vnhu(PPssc~1?Sxe(C)0z8!aMuppO$B#m zaOd|4cd_8Euf|-eobx8~g%fw2Gequ1+R54+x%kn5GM?7Xu4%CalVLjr_C#(IWuZM^5Am94bC zp`#(wFyEj_FT-QQD}x(-hk3z&5Hj#E#@R=YL70!a@B63!O${%Q7p07L9q)4*1Kx-9 z^p8&;LPk1`Zlbg4S^C0YqMPY_`W>A`FViV>5&e?Rp zc9b9`NjYt{)*VC+RozM|zQ- zp+6Z48U#ZngM|jtb@W%d*kCo(GD!3;O`)lV%JesbnSN`iO$X8-x}J`pL+MC5gLpx@ zTQG;MkZL|eCcz|#*olKw!}_j_wOxobCv8bftl$o$4ZTXDAdwPDe=>j!Bb~`zGMd@Pa3MB+!jCZCaSh>c8#Y@Z6LKNGTl76~DFkOFhD&K8hjWFb+=JnS;dNGY>9^OdvYFf_%t@abEG5riF6}ZNq2IM^dvV(A99=YCbvj0auc%f zK4j^ykk|LfAnX|_iO; zbwem5MIA#;LluL=;5397N*PKUN*L@0#Zb}^Y$#?ZW2gujyBhnzev(aGkm!GsEW#i+ z7m*RLC0TXk8r?k_)R<1HBH)H6MW91Z|*$ zP6rLwffWx0#{7WZid+VV0LHp>SKY;et0ZB)o%jg&l%K3-^_&COTz~^0@2Ymj- z1DwajK%xgLK$ARJ1KQt%ZJ+}@$OldKU^nPMAO$!Gqc9?2 z$UYCeK=*sVc{tz!@1KJn6aYQs0e|gZ9y-1&=Qo-369nPp9dTr06xDt+5kW6z;3S3bw1yt zfGZyGb;Hv*5`k*~Uk7}h-SA)-=uHnggWmFhkM(U2#)IDRU<@cv;}{40;=yE4KJPic z0Dkpg66k#oz65>X!8Fi^9`LpE$b&hckAWw^eBh}EeBS*A`~hH&VprC|=hbr$_&B`q zfcN)H5BQk8^593%KRw|6`c!X@qqKI0&alw`ql#;_qPXp zeBOD0bc!Gc|2BgDpaEJFfj*%D`V*l>9nhrk5v&6`6``2N9MG-^<@o^US%g}2K;t6R zssp+gp)`U3w$QCG!9bC7fJPqLTmGWnR>sGXf4lZjc ze+IZdMSJNWw?TXB;5rxOX#khOw66}Xm(ge)Tu#$|I=F5{V{~x&N@I0!{fqK6fXiSS zuY>DnG(iWK(KJy9*Oh3J4lX-se;r)Mq62hrnM;#(aD9#M+1kGS7?kG&xc)^`b#Qr1 z`7^-vHOkun@HItfx(=?p(F`42meWifTrZ;@aM?_=ba4HPX6xWGmk!avbuq3JXnMit zpu;>sbCj0>$S6>rkHY|r&_QxRM|wb^_Y~Ga`hphG!S_8wpboCX8iI82eawJ0#liI& z1Lmj!bJkE5xal z2$upCbQns2T67rfpjI6Q1ys~wCo61p_19r211jslS1U2{G{8^+l$S4! za9PlOIwVy0#s2nuF`<_Ln;N{_I3wInhTHGQ^2K z;h?8LeE~m&mw}=moSz}Q1hg=KIYHNeVm@%t6`(}{^f6rpihk#yD?yz=F#3wuhcV-z zGeOaZ9Q-W6i8;YR!I!f#PzCuhCeB(wZNzT?jnKi@fiq19UyDxkk#i{W@Hq6Rb0WfR zKsm1fJr9a8;GpL~^L5Y*py(eCdI@x|4tg49fI>P9UZCKY!+^OH41PK2Q&5aChru7T zoeqjI32qNWAcGfja0jP>eqZeE?cc2Ym$EOb7i1w66|&12k3# zy#pGjgWd)`tb_gx(+lz!Peh%iK(XF9xDHbMoer)ml*j`XVq6I52^|JJlsKsa_8?N? zj1KxYRHH0lB~Bm^_RjpaBzL36vna?`km*wZ3NISTrR2mK=|5Dw7Pu2hEpIbmu}@Tn&Y5JCvLw_@Mh48}B`Qlst!!`kR`lM1AOIG?M1YX-C?F_Mve!nP$Ks`vnZlGhkl+o-T!nb_d-{Prw9yiQa~x_&1pD-WYJ? zX0YJ^BpAlR3NRnmH#9M{GDI1A8Db47hIGRS!&t)?hAD;_hPj4?hSi2mhP{TvhLeW# zhAW0!Fs?r{FvA-d)e9IuGX@%+IGU(vtYr*0Mi^Td+Z($Ydm9HB(~U!oBaLH?lZ@XQ z7Z{fq*BQ4McNz~HPZ}>7?--vO-HfGNaO-c-X>&(zG+)f8*WFby?LG<|9M+VqX- zTT`BCrD?NipXsFOlIgbTsmWzFnq_l{In3P19A)lj9%LSEo^D=jUTfZNK4AXQe8qgv z{JZ&$AP9a!un;OV5ZVcSg*4%FVXClD*dS~d_6kRY)51mJns8TmBs>$C1;>{bUrV5+ zn5Dd>s-?cAnWep@yQQC{za`T$!t#aXE6Z%lBFievM#~P%KFd+dkCvY-*Db$T9$TJU z-dP1}0qbYhAZv)Vj5X9+!&=|k#M;W*!P?!LX3e&aw2rgRur9T3w;r_Kv_7={ov=3h1V{xgI*`R&Usz-y5;qY*8{KLz5euaizd-mEFu;c z%ZpXTx?+8?iP%c)Aa)mH#Qx%7F-IIDP7!B_--%1aHR5J*w|GQ6EnX0>i@%7E#pfau z-%5g1K(a~2q*78jsg@KjHI>>(our;pjFc=5mU5&q(j@6yX}+{rS}kpo@}>RKG3ktS zO}Z;RlAd`N_71C2XDShIf7>COI;9@eCC)#fdlf5_2XueiBhar4Zi4=x;__2ZNl{p8M!y0zd8tL?DBc1d{I_YoIDLpAA zp_BGXU9_gUd~BjiY*Ji$Tt-qxmxT1_thjC;Q@Uvp-L(SUKlD?y)>yP&f3#kIjFu-x zV=d-m1u-8A#cD~h+PKDP6~t*VaUXKT=@rI(I<653TGoV*HELa6xk|!^Vu|RI#DAn? zT&pGZPtvPP(yL3-UR~?0DmD85BRdAQ#(;$MxVV($=#015_Eu7&Q>x_RgQ#q_wCf+FX zW6jm8=!4v7uvYuvPir5n*FM3R^hMuB5er#8N{G@R$;u8+^=Z|b?&mVcwA3tG8i};i) zE#ec_v}a7L%AqwwbrPl%E?E)D*B(e!omA6Fb)D4E375^tQcHWw*p$?P{Pj5H@1;@g zg?LDN6D`1Bfd@G68r7KQA)Q+u(%9qyt>%=$1F>huVQ(Fn&TH1FRx=N2HERK0GY{~Z zHLBIjLwe0Tq}9v=8tXOqn}>!rs-+WcPYG?Lzj+P)&1>jyUPFKL8v2{p(BHg9t&Ftj zn7E4Zka3wwsVTh9uxgPSsmbfalU7++HLbF+YFcGs)wIgOs%e#lRnsa9tL7=tP%o#A zNmw;)Ov0*FPK!%VN{!`e0yeDJipi-l$&DL!MAp#Ih7r6(XqY~VVPSDYAjk*CrewP^Ki2Uf z=3^~9Dg$yCIXz5%i20aF>%>rfd_(z=pl9_i4drT1<yO$%g*J+S zJRTUGnV6EAiN20b#(o;j2Z@K1<1+XFL?=h5rKP71(Sk`S@kuF3nM30SrezMzh|5gE zkYe9RPD|p|Ru0wYMrBSgGpnIo?BJNpjKKrZ2!=5|8XGloW1~!pPL55AkB?4IPt6{j z#!H9Qs-Zn;Z>2}n)FSxc>(8~cXWkL|b9L>xA3W-`z~Ho4En~IDk@}XwWq4d{ztkZ- zd$opP$*IGz-N$K#!)gpnN`X?F5f_8`#ito~jEjxdCj$0zeX^vd4v0&6{}i7bozS6U z!zhkEAO4`aCZVBxt$^^g0>ak{h}IER^bx5NT0`4nV^RlV3Zi8mK(^2-+8BXoOSnoX z*IV$^xMFlNe@_HG)il(0-H*k1TcK6L^kRCaSElAH8HaN;*wLdKV%Q%97Z;Y zvl|w66ejoKe{S(P^{;?ZL`r}09 zA$8D}v>iT1@8g3r)X)N-mqQI-!$)hOVWnZW;hw=|c#DrnZ(|W-h_QmPrZLSp4xfuN zjW10WQ$tfzQ%8IhrkSRgW||h6UYhXWv!fzVMsyMtEoOvdESqmM}{_OG8Vfr8PeI zI$A!rjI~U(%(r}RS&a|9BlyI-WBJwc#%i>RRzGWXYh7z2YbR?DYrHktI>kE8`mJ@I zHP5=ly2X0Lde(Z?ddGU-s(Kai3h}Dv)!Hl3Yn0byuccnQy)JrP@w)Bx#On_)=JifA ziWX56oni&ChS*SSCiW7O#58fV_?0+QTp%tIe-L+yKZ^o=x2S|BZvHb{G#K&SDe6Gxs}^I`9NSE)y)3h_wk+x?^JjMEc%u5NQEJ!o>rX)G}(Bj+GiYd~9{TInw`h(8(ifPGu?bBVUF!zFIu%WNPfI@c23UMjthc(b?=zC%`Jjzbc!sQ^i9(2L5_ak zZ%Er0Bww0zva+(24L5&td=9HREpUqPP3Sjur?p?K4lm4V3uj+PnpLwf&>b+Y{zLC6*n-09XF{^NU|f$$IYZU5NSSbO?6q;1lU)IYRg-Y$ZKT;}M@rXq z&4bh;WmPNQxWX?^R`{p=8+R>tNUcZojc*>*pwp2@5B4AV`Nz$%9cDXN0fG4qD|=J5 z1*s*`M+UW$T8SA{11lxjx+N~%eC*7e$I~2(r_7r?`%CK}OY0u3YTA8ljXR_F_8z-< zVQ;&N6}z-+?C?=LbG91@YBZQ&0m4>R$;{G)O==~xI?|p0Hqx^Dbzz&Uv-`2T zvmn_{sFf`8*%FF;yP4=Z5iCl!ZxpqPFdTt_S&No0&s(%&d0u8}YF1{d!{_IH{2kg_ zYIN*byFt?Wb))R6w@_vFg{rJl5G(Q5Emp?iO14M`*Y7%YW@+~hc6Ar?W4~Cw5$)1$ zqf?Q(C_ZxsWz8B8)Ht?Bq(gG`0=rcOcQ0@&g^RmH)jwO2mQG)=Y}V`vL)O@(^TMI$ zX6C2*O%gGIXoy-xt^T|itH6Ao{`_*0L-iMW4NDx)9XvFk@l1z0 zT{tuQ@VcWxK5AW8Pga+Cxf8Go>biTXbyY8Ej*vTAx>uP6ssSvp@;!ekFUwWt@ex+2 z!c+hIvqcupimF9fDZo#@oXe5}TxD1bcNymAnqZMH=Bmd|2zlSmT4+D_R8@p73GtmB z#Vzt9Qltae9zTo=>^A;>yHh0L7?3^KK4rHn<+S-;d z*HP5cu9LQ_>H)J_L-4WHRHQsxTGos;8Q+^%3NzQtN&-pGo{?mhzEc0R)oM3q+p49r z*Em@C1oP%e^Kvo+d$$ryk8(Z|`|>#nPF1^Buj% zXAVdVlK1uw-UXk;2tBG=c__+h?Pp);y!@~0wADgSR zx~d!m#xb=~IVp8$=77{83l@!+PPBSB_we(R{;c7pKdv^uAm>ZWUkDx7tw+b%%Kb|Y zsnYc}k1y<5oWIpB*%C+1-t1t5Eqf9-b+W5noJoUDtmd*h}(4wh}%^zH1m_Or}S@YyfQPa9fu2P^W^@Cmt7=Sr-Zz!I6j zDzi?klPa*1YNDf?`@Btx&Rn!|yrUeJQh%|W=#Xq3V>cc=uyNyo{TpLDc8HDbzFiNY73lxTV#Ou2?+Y5iUUVcRwxe{8c>KOG#5Z{6p-gpvxSR>Sva69@V|dN?-f) zxs*Wi{pT#iWckgEA!W||ymq^JIGBTr4TTvFUiFt1yzPf*&BlWw!-`4w5vO#RH zf_)X{B}nrW`FeX%8m9QO`>>EB%?vZeh?8EJ7! zQp-Q8&dN!)yC>Id+u?}GHzz0b?O!iQ^(+2@wPu~3qFp~$__SI`Eg?M?S1Cs6c6H|P zm(p{Gr`gqNrPyHM(3Z_d9Im@khPa#gfy0|GUhH|o+CP@=&$W%g-uPhA@r%C)GM`FU zRX@AB_H85!U>mOstc<$R%*qJT<_5?#MU+@UhB@Op{*@@TI^i#!W<|`9jYZYKW0p2* z5wkRA%Gk+M1Hbxu%GXoBp7_O=cIjMz>W9gS?hgv@aG#ZBWe-Y}O=EsW$$vfjOv+H= z9t`*i%FXJ+YGpKQW#HxE=j9LJ31(@CP<5{fs7&9v=NK90py3XDbF;8sB zSyJ^iW9`a)F+=3MLv74V6ns94NG?9@Qrz^FgEj@7*>?)6Oq24gGK70I=t;%YA(D+P zU|#A1NVM}1{vF;%x_aUHy5OVDyX$=3VM(;M&7AYyjPJgk|83z-i}RNp2|Uq#OH;e_ z+RN7Qm|2yCXPk>t!ZYS;hUE591vO3B&l=kH3Uj|5lQUw}m>fqJ!RLO?eo@L)S}CnW zpUL-KCa68$(?!XDr6?Uhj}K!3(kAv9`wktm`2c!+og%dteONiQuUbw`L{~$cuq3r4 z>tmJF8CiscU?Voc$R0}mYnY+j%lgbL*`BBu%ULAXdfTxbTMr-VwXIE? zUVWn4@929B>mhio>K&^V2#ivsV{@lJ^|8 zs{w*q>|QliLbBc7a{kGa=(E+UM@N<`wA(#v8jTJ6rFi@n57%r-I;Yr-tj#BU~z51cT5 z;&{9CjwC|(v{ZH}5U}bwCu{%KuC{lwbAk_7fF;)M1nYLnAH^m$xFnyI&O$(WH@Y}B z+kYOLQT>*5UUB(Ilb^8zPfuZv|HbBGY0dkKN>An}QudwEio^=-@L#f9q9;IuaP>4wXRe%)D6V4QI~!-o@Cc+hFkfxJl?}3v;`$6J zMsc|aUemZ<#P12rg|`PKII!Oc7jQ~8QSPj~1uoGBQi{^qM))1l`386;((mCfXrOuA zJDM&u;I0IBJt6g4hvw9B4=3<8GLYiR6Zf6<^D+dtg_E3N5XGe=LxzDnq%J0gEP;j_ z4I?PO6H)+Ib}1REIa%~21d|31F6r8}0!h07=}X{MVECL6FUtM@dTXAS^>N9V7;?4S z3KNN86y@`CFy)SP*_vw<80)XyI~YK@e?%fNj48}rni6n>lE79&`te&8hVLoA(X&kR z`o}!66T?D+`(1E~H7ufVl{R3i^wIor8xX@%5&jNvXfUkzA;GvItlfi%*Su7h62o4C z%U$rSHSD9@zc3Hpd(?2CC~kn^3LD9x+<|)};jYP}2zNxrt*3DWH^dCLC>#~wqnv0= zGWLgu!3g7A<1yn?leejisg>z-)Ay#^=5pql=0)cHFbn+wKY$>ZgKEPZlq3ulrVIOo zOTsgYKhF7ESyC;_EYGX~)_T@K*6G%x*0)}YSBls7UZ=f&fr+N9*h3s4&KL8=ds1mB zU7CQ?@l(=W+IOWdv=+b0evy9N{4)Kf_$~L_<9EZqo_|CCEdM%L>rcl8`g?=ui7A{u!yTWIS6fN>Buw!6i;OBv}12+er3cMdA22Bjw6!aqKT~WDc#i9{K zdlem0^sAx^i|$rRE78hg<$&_qUdG0zG3;!<&(?j zmY-67arx8be=Yxa1xJN86^2$=QQ=rcTCrWlF%^HQRJPKX(4f%h(CMMuLvM!O4r>$^ z5tbjeD{N2YdX)!PzF9@A(x=MNDzB?{sCu&M+iIUzdsW@1dX4Ha)pM(VUwv1NqBW}2 zh^moQV^WQIHI~=dS>tSt2Q^;QbkwX>GoohSniFfTt9i8MgIdN~y=o1v^>wYawGP$# zsn(rZf7X_2ht#fEyJzk6+9PX^t3A2)wA!<3=ha?OdqeFVwfELOR{KottF<53epV;2 zPO&=W>Qt*!r%ptj)^&Q;iLH}dC%4X&IV8%?xo&3N zoVs7somqEw-Hml`)yu5+YyCd;=Qe28Ai2TD@Tl-n;V&A-G@R7%QKP&@w;NY)yepzr zL{vm{L`KBeh=mb{BW^UQ-DFCWZ<~DA21ceS>9$-n|p0-ZOgQcZ#%K=%C=|Q{?#s|-TZb}+P!LTZ$Bf-6jeLw z^Qg5Q0y>QBu&l$ij;4+SI_~Jyt<#WBi#wg_^r~~=&UHG+cAnDtSm$?L#4Z6{g1c1e zGO){xt~I;%>sF-O_HK8(8@jjbKBoKZ?(4em?S8)dqaJdPAw3rMSl{Dt-&TEx_q`Xl zEU{(c^Z{K5#0^LvFlxY81HK!udO-ewQv>b|_%m5Zwk3xqw@U7roSdASJTrMw^4jEG z$;Xm^O8zDJ*+9#{LIX<;tTr%WV26R71|FZh62Hgs%Y3zeU;00R8j^HZyeqC5_J_iC zlB6?T=NDpkHSI)uzAK&+WupDa2FfX`>58<;CM~S`p0RkMT~>s`ksglEmM;bNFhDlp z36EMHEvV%|$d_n&cm_yt)z`#)o8nW2D$uulZL%*SaeHSCB3K(JJGmqmj_<0k!0HFc z*eLMSdJW>Wkd}j(pssw915chD2&MYmZP&!asck zhj^5oPH;rj*R5@GxE4&FZ}CJvL?Aa8smOObKn~~Z5iMB@@no$0>2$BTq69X~_ir^1cn;ae8SU(vykP`7xO|-zO8NCs}(jIb7>pbxE>qr9}=$ z-Pr4r1vy;f@ivrO@aCJVMS7k{xF?G?TJIyV-J#rvC#u)Ns|)`SNld)zQ9P2k#Q-@s zmxn&a%@^ccj3;i?@pf}H&Uk7r?-KGrk#jY!v?$Jn7Db#0=ux}?&&9jQ6U7T?Q6%?$ z6fdAhp)I{2?|nTA`8`o+K#xNH_fe+zQHBpuB-fLRgul;4eBVb|5#@uQyyl|+T-T5C zW!H^>3JNUu3SwY)(IT(2b8k#_L`MHM*^u~DOFTbG;RUX;gRh6$#W%8H~I%9^LhKmlSNIu&dTE@T{z;vE4U_B zw(U~v6_mNcBT;@F58K^$qWntj@w)g28!39==&@_Z{8?94M3HadMN{gEcrBGz`G>~R z&kYpj^HP-0?_)h*kG9F@_SME2$i9Bcg^fGU;*?|GJ{YX_)fSOZLqV>7qO0HA(Y*ZK zeGv-2!?rNPGTn&k&-OD}-tG!#yKFeU@lx$DL{tR*OHi}9ZN88oyYg8TGxJfaux&`F zDX6k5#-^SOv-nJA7S`+)i(rEPQ5*uL!4_j;MdVkmPK?=P*O8@b51$KUwB`jhz^*QW zDP_GNzheH6E;He3ucMJm9I{I-%m&%^Z5+_CQ(R&vhx!?d5Zuuw>`us7S~##Vu~SrR zQb&i+MUn1dg^ldToa)L&arajue{zx6<87Kv2qwMSFem=_b|z2W!+f>euHkP?WyQvC zowjmtr}RKo4GV5nQ4MhTM2cE6vz}(Y8%0-h-gMdKHnrLR%HCX|*O|@e zS{uN;s)!b!<_f;~c?^5@dVH9|j$)?0PuVj`K??e051;o>G4Eet-ao~>f2Gg+v6%Po zGlK!W<^h}swW_=CLZ!KKdbFpCzqFO`6f2>s`#YY(Kgm&hBP;?U!{!htvc6i|7WqvT zSd%{FSc17iWH{a=1J>bk&@?DekZ}e&2XKATLdiJ8vr$~Y zg}?Q)$$NRpJ-px77fP{It57X892AieShd_XHNOUvW*?gXC8hcL}u{az9{cl`J0` zyr6ih!vxgd|938`jqVCI-n1IPZNm338E+{UKjm>J^UMD?m+YY0#HOFdd5lh!jbw$4 zt`%5m^%RTG1dOhQSzH&g{g2@#1~EyIhp-Mfcf2J+7apW>!wXOd*KUi|i$u6o{;EBl3Tz$1gr+5~f){JM- zaeJIUYx=w=awfV~z@Ysp=Ysr%s+v$3iyuOjBCC4Y3XQe0Y+br?a)fv2EK=I9xYa0WmM@btIp$5T*|T)EO>2Y?Hgp zd7?I1JV_^E^LJgqE9Qx;oWL`gQ`~17L#B(av)Nes0Y=xJfbSIaF(RgmJc4!QBkoE? z4|@{)S=7g@tch#F5z*&o5vRvS7SGQEFil-4{DeUGQ{CBE`I(=0==HM0pG->8rDU@n zdaEp+owc!mGiD}R)PSaDHW?<>A1x8_W>vPFUvE~Y=rw9ZntRETga*`8M)TSe==5A~R1qVxJ;xP-C~Nli^0QolV}r zV$D;8NzEpyfmH+5b1z>*z~$XgCTIKq!RP;aECl!iY_;HY?DASgOW|q~5_ho&+9EiQ zF7aeahScC?p=@b6T>bd2b3%35k`)%rGii%ftNtjnqOX2pR{5r@uB*5W4gB6-^yE@Q z-m=Du8pRCHvRpH=S@&%EhltaK0Jhn3Xd(;vVm)4CZm;}G3wyJA>Vv|AEU9CLC*TAP z{s$4lxvg6-I9^W!-}5aQO1Fne7jZQ9O<}e4+ekrY5NZ?JZ~9W~h4wc%nTn|@ZwS}7 zj1}RStsBBITNmYFwl2xjX6vFn%+?J~%+}_Ztsi^koO7+RLOZvBmrSU*RpGMXpPEQ_ zafNtLS&dCv-vq8Ngtn&%{}Ku z_RNf_W(Ji;W&49UB7f!T`nsh}?wplmULMzbUXP$oV!4HN*0pgoRn2BD4wmJuHK%OY zK741;d$ykpz8-(nafX@AZm0UfCePHIca|*5&Hmo5wo!3Pwrt!F6IQPaWYYsQZ=Uqb znR!F(I7&Qj{$}7;{o@0DR)|yie%R@y*cpo1-Ed8+$aiz~p*qh6%Uv#54u@l?j)!YQ zbvPVDbvL}9(&X)wP^e;FaHEiL&fxn`^rcWN~1N4+UK(sAWRb z!fKM5^a>hj83%SjFSV8+XQ}cOTiw35Suk^My>r#U_p8-dgE%R~3CI-4&8OHP5mnQ| z{O;d|F6t9{P4#oA@L%D&uFZAc#zKWd>*G6jiBE`fsG*pQS*Xnl)~w8_@3UWGbK=zm zvlI$~c_AiGj&B@B{b5!|-f2EXR`8aid z^?#naALZI2a{a~D@UOE(_suxvr~-|X$GKYZrGMJpFHXt%RiQf+BRia9>#4MxZ7weQ zAPRark9^E!$hEgKKTYB~JJMWnyo#pk16y&ir=qLu|Ea1M^mf#S6|{q|uV;&tsqW%> z0cI7~AwSLw4>G^KEXc@qxvFVN9o&~2E90Rt;$9o;{0FPgtp10gY)-@evdi^7A1JHp zwzTQfyOl%EabLyQ;ZoSFd28%AfyPm7xVg-)ma|)ukh-f?pQL8?P*r#!U@4JfIMw~E z%E{8xFg@mJI?^VLZ9OJ(wFBGAA-=ILz@F7rt%qMELAMNmj#(Ei)bZ)DSz7>9j1qp|SuI9=qA|B+#DXL{1J@!h@h{}yGX^%^ed z=@4ej>b_}j$Y%%p7}lb zX&aI6<+24_l=^W$B~^we$S%<$zaTg*_Y)E@W#nhMdR2}GqPvgf-wh$_czhmwd@D^7 zes~f6MRl3@Au=1E@nEF)b~bE#Zww3+T1{t?UvSwtTIAZ2GwXF!HqZ4PzD<^b*B7oT zZ1{iPQw_RQlNB6pm*1phWF^PISwsE{+S8ks%JK!v_AGP!x%lKY<`?)$FK8e8sCPO( z_os73^d0t#l>eTY{~vxF^6R(xCQtuoV|PO>%}=wGE6u^)|9_!58bZ^zIM<~7=eW+w zX)gZ&)|b2K6&2+5YFYOQwUq0GS#=1kC-)qD?>~@D7q|`^+0=m2$`6Vb{FATlc~B5a zEAKO1;3@KEY`NT-hJSjpAosU6-DT1G|I1~O)e`<+y&-*mP`F9Q$QH(lRW(L*)?DU9 z@$Gn1X+>8UXSsedvd{p0Zcc;W=`=GdFQ`e3u^#LfGdzqi`$oasI?Ak85LkEhA$Ers zW-L_n5M`s8Kg2>z1vNf4A(=-)sPM>1T%xdGwV90x?ihSGU$CgR-Tlm};L3(nd|>fGd3@?D;1&-B zUmokU^3jU_aWI+;ooSbAKD$yWeRCd^qn{RFSvw`7%&FfLezl z-_CzF-Fv*)8qDSAvSKL;KB#BGX)AZX#>22&&S~yH^J}lNhi&O0va;&fe{l*O32pab z7u%vrBImQ>`xJTiL6v#h-mTTe1%mZa`z)3X$2INs%RP_R3hZ_*oMM|eYr@u*fov4^ z^6ICd%-ieKEk4T5yoEh8HvVul=)}5&&W>T0?DWYK6C58rVdNW8io9d+kMcEjKy-%zJs+6azFQ7|ZU^O!w zFTOS0^Wsx^f3~>7`e3^;U*RP-_GP_TAQaxdP?|RTc7@jO3w>$>x0Y;#wZ!FAKgY;y z$ivVKa-yycd0JgLk189d7bTwiFK6bG%=GZLGQa-?1rnMe z_t21=opYUHlWnYao989_^&i%MkbPA~!gqaw$)&bWNxqaA%ujegY5%j~H zv@VVm%h)lKCuTV0cIPULsS&GM11lV9du8|LylqSE(aX1H?g^4hU%Yzm^sAW;x%7EB zKFiI{_nnZFof4EdXwyB%R~EV1arm2IS8Zoou`sosLnXrHB|ogR%VXQaS@|nlm-GS2 zDMOZS+`V$~zNz-_rlk*#OJ@V+$o+B48>}wtBkhg|* zY2C=~lOfW*>@y=fo@1LTss)6yaC?6&YEkMa@kjUNkI@;L^^zyKAZf~qd);PRS!Jrn zdYSd#inua_LZcOwfvBOWBJ*=M(#vRVz)Mbac`Xx9eA-Nm2(S0X*)6a>Tw$&zwlY}O zjhKi}9K2w@TF`y3JTwI(JNANg%g)P&TbCc(fR4f5IO4Tz%Q|J2ud4z5hRn^LlRdkL z8aQZq&a$CPhZL!lvamS|+L|A|vG=m*BAb(XecvfawU<$$YpdlLh1n&PRegb8tL1>^ zCP%V@#I!bwrd` zsy8{KJm;G0wOKIo5_zj@`D@W8uRY3NWouh}MayezGg-A-@RBL0!L{Qa60Te1H7Nc= zc_l%Cwb;k#+RZXU#00LS@<(=&3$vfx@jUJzOvFB5_z0wzW_gA5nyg;qNxHEa#WVPD zvBv6SEtVUVeeebFHw2ir;eF{YrPU6BiIh|rTmNDuwu!gh@xMVqs0%LihR^85`^HSdbs8 z9S;kOXU$n^XBD5S=|ZR2*ba^|YTfb{V65X?zwy@ zTb=L}yBf}3V(5P6R#<#Mc0m5eJpU6d|5YtNHov*bkIe7jWrgjAl7IBMxv3CU!VI5N z{95E&`(HtN45UXf|H5Z9Rl)UvckvU*wviopT}or>4^b>VawhtQ(e7w0V{JZDM{a zVV3$w(^ZwZZ=o4zR~T+8xMASWzVKWufDMs-!Hrvma8(9uJj`|9Zy<7a!86K}2I3`= z-Q+7pHS*}2{G5UNBSI8eQz3Jf^EiIO068hAFuy?_wWiWGs5PZ{5md0hhdADy)IfwE z9y4aSCS+d)1J`i50o@1`h1=Q@_ffhPe;gxF5ND z0uGXL*#$Mq=J7#B+zyNGnjBn8@VTknIT6r5n_2GSQ$@m(;GHhjV>1y1Wt=4a zMD~R{wt>hjdZ%w@imIU1AoL*b_|14tSeDW8FvoJoQp)@j7^p+E|TqDHEyW~&*tPs(AcO~_{P+4MFmU}S%?%{CUt63z1! z&1(8F4fD+CI)bX_E3m|GHurJIHHHF>4F4+m-ffxm zuhn_%zZ<6;^jGblwwttt7SJmpBO%?fbx7*`enBxQnK95%F733)KZf8%Df?4cJ$KD3 zk^N;^J9p(P(PhN;@+5k1W4lk@DiP~)`)@F$4uq101-^=#gb}xk9oANjL2aDPV_#y4 zU~Q_fAhB-R;BRGpT<>hmM?594*uhXOra+3Jmi&KTTavfp;u3EP@{8B(isd`e=&so! zmi#J_SG$4vtwyCc!N~8Z;$~H)J33{46<&&sIm<*|>dV^k$-dYZll_N0O!oD8*ajB0!(?C54wHR+ zZ=1YmD&FM4R8+la>c_fa7{(PWz@oYeVv+52 z?X)cvHEZe=_X(Z={Rb&e8H3E`PV-;Er26lhd{{;QxasF`SNlJ1_I;`N!wG)icrg|F z)Km7|7}!*kc;nG&3KRQAyyqfK2!7>CaZRzw@hJn$%ldVj3q{Fu^|0lF4r}^2YKEGbMUZE% zSY=MzygTPW(0l$*W*_Rm&2i&bv%8);-6k)4cqLrVd$*)=a9NV__3)d}m#Q(50YiH1nGpAodM}LEh zh6xi!qz(v*&DeF@fqX+23anPU7tS6D*?rRN>ofR;ES0u{-M*|^<_IdIj;VjzVuqZ0 z_;|tDO`GROR16)~te->v6Qt(n}Rx5Ik6ujS zAU?it!Vp-5;b5;gBTWu9!4<@u9rL&BJ{`!+b*`xjPJT#3wXWTbt6#2emV4{=UOurp zwoCVvevR$DE8G_3{4-k<8aC+>+sIMBnBX)1cXr}Yg~y4Cyxz5N{0R|#+>SLUElg-) zmXA$nnU&CRV#LJ4^7?Bca#|lg)AL?-86MkS;5e|xL$$`U-eO6$XhkR^zCVd<#P1&} z-OUPMABsZVn_Y02vHdE@tNG@o3c??6bI{htk8Pd**w*H2A~)yef8gvgIJ5n(RqO7m2 zk|=NfLXTB^6#KeAYB{592BMNEwEdoEQ{2&vj^&Tg!GpecqacP#f`g^$(tL z4KfZy#uT1W(>{@LD|?QiUkl;;hr15XwFS8bBUcvB#V0H7tVNuU7%#Ru(F!{qZmx0R zvpJj<#?BAbb`!y|x1Vq>0O9SqFgp1O^7imnI&a&ZsBMUo^Bt}+zOsk7T7CO3w(&x+ zS=xrSt!%0${$YgWG;4A^Jbr$0;!Vf~zLySo>pbKJv7cup%)0>>zF2X}pE) zxxDdQG(MEXXdhWtCe-6P5HHO>d*07eHs3V|nv&|L?!uP{3SRj_M4{_AM9+`Mr#6f^ z`P_SDoT8b1QFa*2IAcCGypymUnki>j?(gnFyy;!xXgVhxwdCaTeuSO(3Nyja$}jZ3 zb^)-!mHK)|E_JdfZSQsRy>}|#d#Ccfmm77Kz^KDk;Y_w;Lbq0SdC`Ox>AMa&*iLYI z%c7c3M?61%VCCjDcDdgKwA3#z2Iu0`6_oA2*0l^u&~0{*QJWg*3Nov>1lGnq!HiQa z*3LD-j0=oD+Jz-L!*#{TMhBD;&njB*#VB#A`?#%)s3k)eMJ#ucfPo^|UDh_X@A!e^ zdcydd&728rmihlF?mgh5INty9-8**g*u_&hj~K|_p;%CfvA0-IQL%UIi3PD@K?Muy z*$Z~T0xF2u8krby7TEGkk&W%U(n`Nxyvd;XGrEmj8tWUlnDB@3b!=`yH=k|-LwR{G&BqZt8)q5AJ^vP9NCAS zA&EoRu$;q!NMTK)!~-}`FSF;8yFaQyN1mX6Sk6AEi)dk#bOkxQ3@dGVqG z)H#^@ECT<E4vji6gm-4nlGxIq-%Y4O89!72o;p(Ke$O0o-CPjxGyIRAKJ$k zBsCulAfH*`Hb)KZssPbUneSR>dCTjigKS5QP#uFX_jO>Y<+cBUH?t|@V8-~RgE9^V zdx#;nr3Wvn{LFQ_{&9dt2fM?FiYZeO;UY}?x$@t|z_ic5Z`!<4XqC`A?|DJHREr#?Bo6{F8h?~2_3bw?8Z+VBdQ_Diq{`CJ{ zTWoo&ejryXfz>phHjdrOW>R#kEAyNVtP!8V$7WkY?%Gd`a)Itr{+TjZ(fsBY@1~e@ z9Q7qc@=pgM>2!3G^0=5cySb#0#~UPgLr(pfG7;%<`$(ZaQaZW!OZn5-n+&I7Ne7{s zrOeNF$)`3o0^6$*hNHP#o>#Dnz=+KE)YYj+?`&fiydLzn_>aM53{QNl<f=5-+O;iKceatjCRLC{MFOerMr8jm+PFFL$5KNApmh&$2vjXc#qpS+b36d-=d% z-fhQ+B%O>k6`IVB9n#XTylCFaed`Y5_gwWA0S0rVOML}&T$Cf#L@?8?8@g>9m|-;q zEA1rm;$r(#e{)@ESXJ%Z*V*1A@K<8KUF#O+lS$--wVFDc;lj!H9P!vrj8wAn`(%i8yz=wuCdgNkdY02%^7Wu_CIG$ zyJ#6cHYsJUZSLmuRo^VwGOzd~L&T8&J*+13>@I0=hbP4zl20FEgPlCHJi3--Q|P3i7d@9H&ce z^*_bxRv)d;?^+-P7V7>^0!bgz=Tj^Y)wO8`kHgzXc1y8oleBKa++}ggSNM{OU){QA zbq@FFHekciXd9VKx(V|p$4#E(t9{m|Ry8Z6+XV9bHVc z)+E)n=UN?2fcUncRiyHbMo0)syjq_4>aio*WxB!9i-_&~KHFow-q-11V@g;@JXKTf@Vgav|j2$QZj_(=JsZ-y`*0%0tPh*kz z(t$y(TlE~&re*gX7bn=TIjsdH5<^o`9J?{Z<1+c^ewPy=DNIl&2*-V2(ABHqWSK>+ zu9Y@u$DO4F)cC7f5Qg@kXRi#9lH6v|wrK-t%#36%(LaSCuv(u=UXa5y%2t#V*cL#Ak+(k+f&aalgw4!kUKk3TqnL_rTGqHcX8)bK*lxoBc?MS5F~f z^ilN}+DEi>jaW_9LmtV~+X2lbw@4eQy5N_+NBvH2iws|G z!<^=i3Bf;ViXXm;3qj{n>}QFg>$=*yrG8z7lz^z!AAb-(@=?Vn;65CRQ_PQ=bw6?8 zQpV9M7Y}z2v6){s@7A#?mV~0!<4Da(HAa6@J#HZ{Ma@IwG+Fy{tQKb^0b&|il?6s6 zNo6B+O2yDTFpzFfNlT*hK1BTRHSR74v2qNuW~@6eLaqkw3=Tu9o{{xjxW9l%ah|4$5*?)`FdYO=gxil zw`tR7w*&66+CIyPgI`_AKG3IQhcEgxYV^fdC#mEHmD|!Izl_k(@G+QTz~g zA$(EB{u=x3sH60_!ANbmrCImGSr?9+xODMw$L39Yc7;A7VvxQiJncS0JQSbu^A-w8DZu^eIq6dbXbgGBOW( zz@G?5%x_$jF8xIs^cTGe#bU2CUU3s{f!dMRN6b$g{)%QMtDDgfM<2&N5@Rzli_~GE z%^{;}N#>_Rsox9Fp?m?$>4+;21q?)2UBTpag{6c7zZICamR4s;ImUoHA`$M0`Dt%| zWg)3huo5cLJ5LMM)7~FYL-phi)k77#U#;v8Ss=5CP+b9{8jaI8KV@A1+MOgmoQ3%p z!kkBf8YysgYsPUCa7;Z8jn{3^%u>g;fPf_}0G>2N=IhHqR0?@d+J!45?V33q?}f>i zYorTG842GafIou=sn z6OU*;s;E3B^P16M`k@+CVL^<_B9&Z0j3WKq^~ghU)gzqxk)9xHp3*oz!NCUPjfdi{ zMcK;ZBhq79e-QLI#J@l-X8*nd#T``r&k-8r3o`o!%aygNKWdPN!m>46c@j>;`-_Gb zP5e-KJQR23L0nk9f%9$ZJW?I-UcG57k&UD|@;I;NG?vtoq#dm}jZt$boLh4qvYG=Q zfg~fh<{U-M0cJf}Tu{}4OF8nDyXxR&D{1bkJ85c$vjnX>KweSX{Hw|nj#XulZz9cI z6$kJ-H6cJMHAgCi1XMVnRM@BlMM*)QDWxKnga9Ry=#(om`Nh3DzYVnm}<4~3j8 zRaPOjcEMDWN)3`q`AenR;miOT7a&caBTc8(?SSHAms~1eq9mXEYSgAjDzA`q5$z~D z3t#!YN%nb*Ii*FG!QA_NhQXZjbx+bc7%x95=9K%2X*v!08A6^;L!Mq1Q%SM}VK1pB zO&=sp_m`%#ux|uNDnADXp{qtT;dN-jY8}tpJ5?AQcb#ALIv=6T zM<_E8%4>vj0ePohpqZ!6K&2lQbMu@xp}K3Z3loB)E5BjS;5@$A4%fhLM?oqI)fs3H zLt?(o)q=Ghahk!}g3Ww^D)qCPx4)y;@2k8Xb^8Z8)N`~y&6$ft%|)VSAW<`rs2MC# zmjm2K8aAnWvBK_COELM=!5o?S>YDjFN$7*UQ;a*;TS+g&pvs5#5*gvj>ucB{pn7E< zk!7HG35qA(Bz2Rk&>v&$c@iq!QTALQz0O19%vL(iwWZBq$0bsA4_5Rp^>y-16jDrW zY>Ak-_iGy*zFxT}Jw35sTPs}K#`cY{l2Y0Y2v=NsM*-uGJNY#*?z@wxf^o;4_jNGt zxKw}=#yg5D`e$iuw%b|sci0jCNP9OlG)!=|r@Ry3c1QjIzjEXSxZUx7fZJ0F4)9xr zM6uuk*J0H%km&K<9=K035B+AHl*X34|_X}7MBtr0$q%I9Wet#80c`ThrI3#oehZ5cQ3`gJWB^1zntDL0`F=GTu;qVAr3K=6% z3ggn(Nn@NtEdNv)Y6C%A#TqQ4)s9O?vqeaU&R>5wSB_DhM*@*8jcK+((Psm(?vm54 zY&nN)ITD&bTaJe2Wy_J!_p{~5JB5oqhy%!(#+GqX)Cb~sq*iYHVh_0DM`YU1)y^Ut zSZ35_ecc4^g|m4RM8!^Q>I=(#g~U7kY43V&Ks2cem3ytux>|+r5me208U<_j=Ixi% zveOG5k-xIP?SLHb_dxLIRxY|do%TZc0whJ06lC3Dgt+r1DXTX8QZWyIsY%X;NNB6tpk|93JR&Jw!qoVdG--8D>qHI)ewQJz4V(wm;Ek$z3syO5o;sk zQ5ECuY4K~X4g0(F{wPF)hoIf2K?77}~Y%Rg+GF)n;0_1=SQ>j|PM5q+mDKBX)2-8cexP$0V&q^fPF` zbd{Oar2!N1t7m^(ylZHmzWNdhxO&fm)pz!?=c(^pz36@Qo$%_`;JNxvff_t#TxxaZ zdB*IEq%uA!E$N$saviz(n&{Y&p}3@|f9w#JB-- zj6IK+Zrj=bHsr)vOO$=%{(Z|fr=>27?ER&EI20|$&69k_LasiL$K=0)9?P_)_G4!y zko2A>k(ZWUIEtvf9QzLDhI2Y2;ZsP3W9(l~f_*^w+GR0z>h73yD(ZNNye1Kr6m_(q zl^2tpqXm2&`DhVi6@t_Apm31U2!>RkdiC%nbDl;;ZHc89(h4E_6D-{j{{#5A=b-uW zI_YmYx+?AH4r^+XaB|PyL*M%n3CezpY37ozltVj?`yJmqpi9qzqx(XY^7+vdgm!&L ze9_!@lmX&M{#yUBiqb0$?Bv&}@6KZxJ5u*p$mNd?HtzFRHNlLt<=2>P}b~6KHrZMTvb{pKw%w350+^SwaVWNEJ14ZhO%Pc zUqY$;K56uTC=d9R>P5Z!qdLb@`7UJF?n)KK2|>bd;wViKKBM5TcNL<$tNbb^J`gI2 zsYDU(i`qR+u~3lc8KEhsb4->Lcur!^oX*!2e-ee#Zh*qRO5+VYkFSPL^lEdhss-yP zei5W9vH23L?^nZGi!W6GT0zsb(n@O~zFL#BTIq+H-b(qBkD%XpoT62`tYBXc!oykW zY0J80Dzzt*~lod@>oYSYFT`c9cN(ArchdP&@oFsYwSi!pTF-S3E%ba@ShfFtcI z*4ao?L*~eg&I#7cg!LJjz9z*K)p+_b3}iG==CH4 zGp>UYIp}i`5rm`n-`pS65pBsq{$P&u+$mb&9Wq+oo!1I4otI)$A!z-7+fLS_ovcSY zi9|bz+$;G*#3+!5n)V9%<|K8j(jn(Smek>##GW~muPN1XUh>fH4jmdDsL;t0-mZFCN^1fo#AmfqtX{$!>SeWYO65PuS}d)l{K1n>RQB+4PGNWD^!h^! z6T=3EqjHWj^qVqi5GrS(OXBu~N#Qnaf}!iKa8%B)KcJA?RXJN498m|u60DAdw1W;` zQx#NqSKU-AbX2Ois%BNXiaVqVYGzy1%(kz!^R#AGL&aQuj*=UAD3{dfagb$)g&3SV z&48}sz}vcd0CknVy6ftJ*9uYIR)r%YCHCs73r9w}9CItf5mW|D&`>+vwc!|Q1C-bJ zqaGVb!?@74Ph~gyZaMiFJ&~0T&A$Ybq_UQ$r^iiXYarO|7n)f6hKe~g%a%Qp8^LrHhbd}>zvW(b$F!rdQ zHU%uDxPMgxi{4?AYmI zs1O-GzFU}YmsMRihg+M4p6Dc?Nq=H#()rZo%bBMxXJxi;(xh|y5SwX9bZT@?`xx&` zQs~F*UzqsIVe|~`EkqY`PV?Dfowz`N603ugHw;|S1?$=3I3hN?rpYUf-_vB8CfBJK z;H!Dv>-u<2|J}*&FaUY*M4@}_Gt{e= zjVtENhSq$&Vd41k^9TEB4YVQ^vy)@t~hs8!xYAidkn zZ++7Ig^ASD?AVEOWBoL_zT>B%Hq!4qh{Vrb8W$h$yDTnYUV@cGeW&#mZ*RGBln8#P zi~0xIXR^_x4c?GdGj(FekzV2;i{7#^ZPnKKyNskvwpLjjdqyB3+0g2vbr)x(%ubA# z#x96j5@oC02qH7dtp)AlM)crvS+V7;_Cp)^5gu~}57igL7(`LA2~-%zjmbTWR=8mq zXgwqYA1N0eDVRu@AVOPlkWkO?+jgOO9;9u%Z@|>281keCrbAfQulol&jJ!BPR+2?= z^ZHdgzVc0+lRRUMb@noWRQ`jCJGU37ZWa*9qnvhm%Dy^k!MZX~?}pPa!q825s-L3E!(|B(p`&m))yoULSxk9o*T zQr}?S`b4XL2HVHPeE$b*G!(6LQ#0EjE3rt+Y*y-GC^j*hiRK}J(EqlzBo3S)3wQMfiI+X4=LaR+xt?Kpb(ALC$^(o{fk*f9UQwM<8>kFm~ z5_J02$+w}ZwT~#ouGKt&gN)h$s#5u@uUsmX`}CnIl})7Lt7oq8-kgxsVOl?gnuk*d zSW1fLNFkxL*h(uTXelMgKryV0pj9pLf?=L9SF-k%HdxGjCScpvbU_{WopM$UwvZc| zmv%#wu`Op%hmqEhc{MocGnYh%;R!ApTnZbs8`vDWLA)qzibIUfstqmVXcg^fRVvO6 z20=J{Mi~S_mx1#TqUoXvuxOr?3!EVee)MN@^d5zrhdf?6hn1kbNLOU~Y?|qW1X`d3 ztNAOfIcCXvEO~^MAfeb1B?q-YaQyMKvhB3uz3Bn@-LVo)~QA>5ipw z3+Jw|28nQ3CYh%=k|pz0#}5=rkbp}bD~#B*J^GZNHpj#5C-gl(#i^e_>Zka7eoW*` zgu9uAJ5LQFU*-neDlgP|2=o*94}$kk5aPVN08Qj)bWUmw;-ObJ5MK+q;2Z`qvcI%m z(3kw%?~qJ(sME~7p=$wC6Pu_t)!qm=vuI91>rKY-sbu( zE%TP(EUuk%sXN%bK6ZGDRqLW15vT%+^gIO=!$+=MAB{N)bjB*ZPQ^BL;M|y$LczPn|s4ss(&1nr7Z>6|EM- zzU6alE|FtCLSXbAx2RM!XFo*femwOiCDEDoEecdt2R*6Z>xT+gVmhfs0^9-Of=tXxxCE- z66i|;&foj#_W3GMa!|HSP^(F}Lx&RJ3$BsqIJxyMhCz&QV!#u%e2n)&Tvq^H7x*M8 z8uS2j-J$B{-z^bSl6Kk1ODgwhFmLM=(XCbUQHM`h$zgi53BnziD0LPmC$FEe+3(xq zyBu3>=E0rfw~hSP&pednhV6knH%wFu0{;-(&gJM1d^EB?X8|eqW&!yqXTdEfK=@9R zZogT8uaXYLBc~K9bh?_VPp4H@Fd*?awTasI^hk3m@o*M1U@Z7in@+wLR5Rp1O{C^i zwLuKOP`#%oNzE;vk{<=FcG+wZXIftgq>4xu|LK8lL_}&ilKPbR63%-sw3E%n-AB+M zf?=_=`n!cRAYSdYI!kO{4`{u)k)Kw!W&mU$N)oOV3HasP^ecyLdrq&t_0$&!y8=-x z$yOW_D(6%!O~W$3|Iv|oDa+Bh_UB=pF{5F6)>oY0L-z`?p1TeU^7~=Tha98=*5hLw z5o|rah#G?R_&r#UKje739v|aq8{01eYfcVw)Y%f-AJfl}vS&yQYJ=J8>nE>AT|0G} z@Yl?*9Hg9D-*V^R>Fd{fovKl@XZ!l~Guqv@;mU?DEmff+G#Ceb1_(HPF(%mAxRYg< zTkCzU7JM7|+G()#89sj0SlhaB!&de2GanDG>*8|rt4*uct+tI?vvK@ae%~Vm8<-%J z&#mU;4t#$1x15CLD4&yxX*1D7h;g$;En~o(Stn_ywNuv{0Bj^U%NR_5^GEF58HN9w zKTe-|wJZ6{GFzK1yi!A)O-hJl)&lLecKfGlf(iXmVSc9iN(R4T;zwPL&2pDLy76>KOCTd6t!vbx#cAMN4OldS~(@3lZ2ZtNgZ{XrX zPBplOiy9gUY8i}8jMo9g3#&I%EDOkNp@cI;ZSqRgX3ZwI$?a-CAzrHyuUUu}PVN-9 z;7WwL4X$gawA0Z2bo$yg4e#JZ3X6GZrTm~^9?Ri%yTPn~c1gh;G z2U#6xML6J0lT(i-XN& z2+-Q~*kay8^==&GHEtmfLA`%?uF z=4IMV^?_wq%J7JYQG+`Vw~gE}e)AUJ-Dw-sty7(|E#}0geKU^lS+#xlS{wS-U<5K@ zT-21lex@A#w>(*W_0d(m8c*{e4oYK!s$*VU=s`7HW#*Kw<_viBX24bSU9Dc^)c?c# zJduNtj26VJ0+F$XmI-AqnA#S-d;Q7RBlq;(08O4J*KW%=>q~UC_SV>B?X*T{uzqCn zF5kV|*E=$IMR!?YB_eK*8T;nvJ? z!i|yZW5Rv=hL7mnv2WUuiB{<3!t$I)(l5bQu@)SJO#0Zi z;F9I`=}UyisiB>YS|Yf%m@~9rf4`msPW}Gd&QlpXw?#CYkGg@Sbp*)U+g+;ZSGi$z z3~aXVs{dj$Jyf!e{hE3G#CHzV_z}|3io$znlUjQRZm%w%Q55N*;BG6^SuwHr{-^vTb}c9$omej>J? z5G(Z)%iXN3yLUq_SFhfrN%iWNL+;vs_UJ!!%dTBpw(i=!Wk~=2Lx+ajOlmMmq!${s zWNS&6F-tyxH6|c=Vp4H>CYE8y2_K-DHj>Fy%@B_AP^mxkFMvdWh|E ztjyk1oHL+GXa+pbpWDg=nD3uD~O#9g@RIEZ(v1V za1DKdjXHWr){RoopZLahr7j2w4kEYkS$4}CC}_{QgM{|jA$=mQj&o$<_h6ZQCC-#P zdasdRi*pQE`~XVZkdqeO%{?x+9IfUSc#7M6nXZ5e50)y0ar}&BRF+PrgbG%t+cqTb=))~%7fREvbc5h>F&N>l3jKRP-fC-*W zF`sD4oJ<^y3Jwh(gY#s;fx(Ls1@>B5x*uzq96wrG32*;nd=u_nKBYMqe~PEU*xv~R zSA?;^?cJe-c=A-?x#aw)OD6?5+#*(4dX6Z)|JEI`hT|dSt)o6SOyQX_dFn#SvZ0=1 z$(!a19 z%#WrE9QAH~;vsP0umPC_6l%j`6bmba_b7-UF(OtHNP(*)rn^cCj;NQ;fIgPd5=|`b zK)fSejsM3Rf-A~RK+S#P;mN{(OGa_}_i%1T&cI>+;PjtD`EPEl6cFWwu|m#Ct;iDv zU4(zGZTj=Z^5`7s`BW32Vny2{l31-?6%G2UFaetY5Ta(Wq@DnmYGkbda_mkOxlZ<7 zCnk70q@IV;1@UG5ep->2*Z-)GV~#Jc({obc#3X3bofDyNR0Nv3f+*LuA6(U4`@cBb{k;Vb4J8oA!SZ0}9UJE!70 zZ?Z8h>R_+TZE3NYgAc6Q9hEr|%byiCj>uS)8NOl3;l3MIWQOnFm)URQ>J1})>6|%o zJr=&{A0EMra1DY(y=TcXtPT;$4?XW6*|OG&&OPpi$Spt|0l zG^3j2bbuZWr|uM2-VJzX`+Q^A-bUC&S%Sp-(a6q*$V_1neFtF?M(BwsIK^zs@`1uA z@x=~HlDINqYOD?SKKXN@9uue7Ct4?ns(>?B^!_K@Nbuqf781E&fE+H^1S0^4FIw#J z#7r9o$5X_jM7*IfyXa71%)kPF1E?ano`Az;c+>|S4&Va_>O*q*z?<6#pvm#Xhc*)G zkI(hz?G6bD`14k9b0fVz6qIg{aDYb(I&9_JaPWilL;*w0i&#c zVcAkNH8urseSyu92PZr$l8fpr`gh{ zCd5thwcBT6$tM^Tb}nY>(!?3Io}xRf@Woq4?f1i-8~6(*?U&%v5eBZ8O#|QA!OJdf-kG+EDG~ECdQ^j zp9@ZcaRU1~tC#9}22OCQ9-~8!+-=aQrs?LXoHR^R}Z*`t>X3?8AaFrZ+^efig zh~H}{XYtcSoImjM2jFMWMq?R;h_tpK+m}yWIC%lK|LnmWw+z+Ljx56s9-I-+6?3M< z$NJ$454b&%md~~!>F^T&je=y_aR(W0>7YSPn!jvn66lcY9D!yV#v5=RZ)6eU4Nr_W zo_W0CmdhJnT)cHI-jv^4-a77dE^FOe)~Mz#)*f!w9&cI0?TNI4MH_{(ltmk*NTW?l z$;~<#HILIm=2^@-3MK3lP`d!c_r@TQcup8E+Pe#I^XEAGVIf8|v+mK}!+uB@hbvYn zX<|#^HNC_J;JID|!iu;);VpuOxae4aeKhMH%dU?R$lh)GsPe zOT$B-1YNY_Qo#PBS_&_GQgF5A>d7l(Yz)_KSWA%< z@k#8TU@#+euE>_eq46&AcIk;>Eyb|ImISx=geB9bOqo7?ifszY*B?Q2*k)nD+Lw+N zCWxq{r03Jjr#y+v3Dc`LbBfoLv@+9bO5~TOigV!SH6``yrpg<==2cV5@ymrMjyX~) zttZIACoU!Wr^d;1){I}XWc`@6(J2m6?<8q_^rkclBlOO+D5xDXq%KU0UUz!kmeiQ! zi5uswN#2l<9J}HEy7-M#(iUKBuDy25kGZ2WdRC;3+{D;Shh_gX*Qi_sX(*QlsZQJ` z=fRPBoh&z%jUt9-)LwfaN1AT8&=J|%tNcNc4$l}7jVSi7qA(8f0CI<9qg`jGBl4Yf z;)QIuAuN0OjdTdMb5kD~e(Ve!K!5kZ3+IyMH{^}WIy(lqr6hP+o{dd8fy5B*7qq)mlGPh4`i zWu<-PI4iw02p0iXLj-73;I^?Q!38gOT_+TrI9OOOj@==+ye(U}Wa)BW)) z&KNaV*fyrx+I5DdOOuD-Hg1>mfQ+qs1P~yHoX?wE4y-gROPDrk(iFSh<_byevc*EV z@-#nKq>{x&^JmYRIcpBO2V|26_vs1?O^ye*G*TEVn*5h4&OSK(uKhGkqA%Lt*e2KP z8`z7p7MZTsLg_($M#x@IOmV%eP($?2vQ*oS$zMG?Rl)Awb90Ioy#~@&UJCCVPM+(v z%rwPcoelN;P7|r5cbb@Let-4QT*cX++%osp95|Vrf`iGu+fX*?IFrre#LvfyUUN)= zS4RWIIfm-8Gq=*lca;3qA0F~foQTkC{)AI#eE)(FiZ)_#rwG=Dww2_W_?R1ycc!z?qplIHyAjWHA73SB)H}7@;fA#ML5*V8F+F^CO z<>Zf;3rVJ>3Ta1G2V6wvEmg4h2N8p<$UERek#%YnhCwy z8~MZ1NqQrlcWd2Tc>^at92YFwZd{^Ef4gwe zGxV_}G_$NuSdp^aYTmniiLfDQZQ579r+e)S!Jbva?!7{%*lvjCy_+DmzQHdoDK>hn zecG_GHuI**(}dyUCq+m4PBoa*Z)u$6hw62(pp>Z2P9%-v65~WSm}u1cCV5&@YX0rz z8RsQGg{DmTX`+`GDVpF_NPSf7wI$Qcy}HKE?jLuK@nXZ>^ zv2KIzpzf0Hitf7Z2i*wgx^=I`@^sn@9Jj@bvO@oB%EgKm^4c!f282aOq%h85OhADt zu+4DL;4qvrd}Fv^xN5jZQT zH916XBX^X0$o=F2@-TUfJXM}0C&=sM4f0O;fP7d!E`Kd&%Qxj;J+M%izAp2~{+J%%V-TN>uYFeY_R|VgZXH}jOi4&4K??w` z%Nm9)fg;!#sBV-0aVht=9(12GcaM|qZ$k8hDUL5#+dEbD{$I4he4%Z1X_|pfnSZBg z1`8*W*rClk7pu#;x5xi__4MIZnz+~o5hT)LTo6Qrd~qBZGAw@D7;Oypdm(~=ySQzt zj;YG&>Kr628Na|j$#=rciBqGkF;l152l$mJhr`#$cdb2|Vk1k{HxRlKP3u>#Uc1%z z@E7|V1^524`_R>+(X4I&dvBPX8s=Ht;EMBkBFK! zVVrIG>0Y>qoO#Gk`DI=nB-+PO!^BJxaOYWP(WtTQ<;x%7%sl=8? zP8&O7@}vc81|h!C(c~#E0lR-(4^K*Xq$Z6YJ$eE)t5Q>wR;A)Lb*9cqgOs*J&iT;o zKdP4OF1k22&cg0aRS<;miuK=&XV0GGo!T0OQ(LaXPNwlwgfB*R8dlMFy1^8UqvASpoD`0Wk)h6JUI$6Gq!`Gj zl~J~pp=UW~-&d|^Ia{&3+Cc89< z{Ql`9??=!f(h7nuH%XKa)Nu$< zd~zVGPH$ApyV7T6?;W3|^dMC|W_7&b&#BVU=%nFfY_W|>Ut0bBD z{f@E=S#3iPp>Z?1w`+&Kwdk*BU*B)GU(+SoWRz_^933;Arn+u1!#j+UG+%dX5GCP66HxemQLGFfOLmZwj!w{9u>7!oZ$f#qNqdlHEDf7qjJ{Tol8UBB`4 z$@O|=%GR$JXp^@~_kCg|diKLXEd|Fr2cTN6s>tLJQCpKb0 zci%p1hwL0{mCpo|_*Mp4JyRKdN1&vhLEb{+8dV)+0gqfGj(Rj9`j}5jlSc* zE8>@3`Uip`f1@YIl{^iSTRKp-zdCnGLTU*tB^IY6iO)#(kR%mv?^*B*Jhtj6ufPu@}T4 zw^VF0R1RFiv8;3`u^78X*fcC6xr1MY&=#7(CTqA6W0H1Cz`m#jI;t(CkKy87NYd^X zWL#3{~pNi4#|@bUe|xamS908=vTS z#b%mqabGzHolENs>?%5W%c9juseWsdCPhb2oIGHxZTwV09;Pf;4eerfBkaBo(TN4+uCdq@8+mKrqdFgR7>>i_!E{884cy`F(d( zRvi{}oog-&P0}9sGfZe5dq(Ih%F{3Ok0#Zjj6}ZJ^{FEBKdW{1q@Nr|M71x9B=)`} zyOdYTR9pBZLuGMYwZVdg;Ys5Nwh!OSp_%b{!eHL{BrdlQW@J z8ci(gyyBk0$f!RtM3U8kK%+a?vc8k#I0=nTL8BH(2e;^i?7ID-b9ndRHcauY@`Nc< zC)=0KMCKbIvTl^I$A~<{7PQeWGYy>b4bu09ylq?j5L`<4l7L%04`G*hd_E(KIcI;3 z!wlq456$N<4})o{rdRjl7@0|H1ko@^XUQR9{XVzbZi_O#xe-c=YOo;ea#BM4a+?g* zE zI1e{agmVGNc^3_u4h7(kcLNlIu^#fPQ)6WQ0<;LBKSlF6X^|-r$9cifKON_TWgZi7 zMX>hIb7i>CU{~fE!4Bb?!EVlVg58Dd4ZANl680!A2KG2^9_$5NJnUs$D(p0FH|)LK zao8uhYp`!{cVYj`sj&a#vC_yF<3Hwf{BQhkfFJXZIbNseDsp=QMF^L5)pB8PA#Bbm+8NZXBYz5N+<_ovUb<2Hzf#90L zw1WQ*cyC|PV6U<7d6)T-ERyq-^bcV3fnaoOOCM%t#taMUY>Fi>qbBdMD zx2$yTAv9f~zHZYF&oCI2NTGqu=&`c$);*VQAX3l{CJgE5iDzHLcp%6B)rF?Ev}SQUa~Se3RU_)hTi8~gX0Q~XJG)6Tl^Dx-_;9s)P;K&a{0}Vlj`QuNp*8w z|0mGzBm>8w#|x=az!B2=SZCTqv~cJt!5pO$$B z5$I45Gc&{}lQl7sfM?+OiQwmj{^&fIjT%%c%Xq0gzlwc0+(E z)J_hP%P|ZX8@K|J!}6ek|F00G zcXM(19qqyZ2S^^qTq(qQQQ4m7`WBj*hg$)vB$#&~`LBQC+;l!(pLi8vz9>}k{{;FVKgK;Tue|c0+#W8sX4CTc z2d)}oT#<30P@R7Pfs0o#qoYu(4?%G2>eYd|GU$u{1@s@dfOoiyGoZo$5*m?57tJ7E z*BnotkJsTVfv>~ts+cnZ){lT~blHr?$Xv_2Y>LsLw*yUiMpJ^pk<4DiXbQVv>dGx) zb{4}oqIhlzg|Q<@=iDV2-k;HzVBBUgjLd8U!^;d`irJM}3`;TB3Jg<$VP-JO&lvtQ zhOfq8TFN|MjbWNI3`!iB<_uGb#z9wzVJb1#>MT~(8PDnzqcbx+{T>3$T&plUj`^y> zT+1@dM}OlhjW5eEL5zPDMpKu$)@3m5*Lc1zqZz{R2IgxB!+g$MYcRV3;}Fa64O|!o z$1-05%w{uqK7iu6whU8&(NthCoAGl^m|y0~IT+l8(R|A68Z4!sGWvG9dx%>@hH0uR z1GqH9m!`gS0`ps%`3hqA%GBl@EdG@lz81p=G0IvDQ<7qIkWm4*k__`PqxqP@mt8he zDpHEPZ$X|5;$q+V7A%KvLD#ooIednFrmM{rV&BXm@J9{J=~^%t`S4ZbGP!QK&lVj2 zw?sq#E1B6Fn4Qh+?_d{)&lccR3tZaa7sB2tt{uLndg4oJAUBK~&y9w0{lJf=;ICw6 zZ(w#8W@j_|J8JX2n0<}eeW}e6X8*-76`38xFqjl^ul3X4`R1<0zDemfH|+}rP!z^D z?8lrHU!N7YN?diW4%Yy2ZO*m9+JU}t!%qHO-PUbe`E%hN+P3z`s({Nck35#a!-DT$ z8&?)NT$!uEea;1=hP2??GOD7;V*~QFC^-4yD>(pCE1x1qYI1eChFnvwCH=BQOp3B^ z_(J$T{Rm&~CGag=j;qL3Mb6d3N<}lS71!QP=fQbmHN%X&RUlnlnk$d>jA~qMb#;E&9@Ssx(XY=3?0%6WbW*<$*x^G54bT<&pgnAOq|PV& z19n7IpMJVeK4cFa-fyTbnAuHT_OLOLQMy(ivWG{757Tw{kUa`HpzHcUd(f~5-4~-i zWRI#;SrzQq1_D9Sv&g@SR z0*@90i$NH>u;fE=et=vdDvZ*K`WeRi^FQdy=vwGz>!<1u2(QIwkP|6m2r+~kW*W8_ zE*VtFf3z{i8c!Qvdj@(&;5W&0nddhAG9cM;6>BJEq(#yOX|ME+^n+XkGjWu}g|6OtpoP^ztNw!P&rO5$%?zw# z&EjTrbGW%&99Evza~rsg+$QcEcbmJ<PDy5yld%y7}^m2j7?P%D3T% z0_w+i&^p#FRhzCAx2Pz2wT@4$}$G=T5LcjQL`8VHG@PJ9%gLHw6| zXMPl*!F+E%j2{hX2;YbA!jIwfi1k5!KSGS=Gmyg`+*JHH{u915iaCK#;ADO!zY?{F z)-xSy5?yNqf$;!xs}d`l05@g>+>4=SrR5a>Td%923&J{N{#8jj5>a=`NrG)ch$u%| zQowt#Jg2#u8(Jyw=E0RW4s$)>m#*yc+>tz&PI)efGk*2JCpVw(AUqnUK=iJ)P^O#U z?!mu8dT%j^Fo>?H`f#7{uaO_AaM2-rFT8;YBb$!DkGT4vyaJKpT3j&t@>b}3yYf!( zN~J#dKbg-|U>FDXOaq?2ug5b7TvqZL>_pJ&;D_32%wCVsOyEz)q#&*e|Az6n&z@<# z>$x6JmHDG~8iUs(1qN_U1UFjOZX=$#`DUfLBVs+*fN`5Xkt1b*(+N=`T9lziF2wNE zmj!9-fYCV~tEyStGqj{Yz7guxXnr2}AK=gPclZ}N5400nCbHoC=TC>#Xc+p(>ImW^ z3pfAy1D;Yy!h!dH{7KZhlleHLfojG3KR%85_Y}sy`{Sp>_w;q`Pc?JE= zI7VgVC%CBjiR|gmPiD^&{519~$beu@jv&tgy7lX&n`-L$mTn^1pfY)kU9^HI!k!|2Hn(-KH-03QHq+HPpdS#Ihc zAvccVo#xEDE?MxGh+12a+dlA~gx~A}T~{D}z1eSYf$n2Dfe&{7(9#PCJB$-~Yu+!g zK${^(BJKe;Zz944%Q zU+)5`dt<~3Ebv#wO|L^~_2q{kBwDJ`d^C!3Eb1ej+vJuikC_tB`>=No+_3wG5xEbX zDZRw#<#*`s!#`RGz7l8}Xl~QJJsJWFi}{e44>|(6MmPFR{(!Qm?fj1qS-@L_E!Z*s>x03iudHYrj?ey)N zh%XtMZ*+E$f48qZXpHCw=ov~nj#@yqjxPp#J91CQ9pOKM{WGX|Ze1Qf9eSFN*z9aS z#+QtLHABM}7Uo+^kRZ&t5R;XBDq09eKeXJP{BEuYW?Fi#7@KX;`P|!-)36aAZht;( zF_c7p8rmOV*7FYTF2!*g{0%I61jBg_N+r~%dkzZNLzbEvRgx!y4JnQICI z{x^mPU0s-}A26Q-FTmtJ+XMc$rX6U@6<}z1o-p)DO(U3k?k9ymWLm?Gnp}UBe_I&( z%r*J>=F;VV78IZSI2(B7zUTU*@3}C2T0daw0AHp6Qxmv4VZhMx?R8-8xs z@AIYk$c#HrgYi!LKib}?q3zZmhUOK0(lpcdLGy~{0X5W5F8rY3;s|cFS#F`P&37V;>k= zFKC#wyqm#)dSc{5BYzywdM_5D>9 zCIP0W%e;YP!Cz%yFyHxWCd_9rgJ7_R_!qt*|H2pQU-2+wU}D_w%MsRLT~~eup0r+3 b(+OrG3@z7LFqtqhF!Nx}!(4QipXvVt$bu|l literal 0 HcmV?d00001 diff --git a/App/BlurtiOS/Design/fonts/ModernGothicMono-Regular.ttf b/App/BlurtiOS/Design/fonts/ModernGothicMono-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..c6c87c9f23aff74463763f9061973fa0a6432db6 GIT binary patch literal 58776 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

~oR1R+RxRMl-bD>?A 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%0A?0 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

20^tUanJg_zPum%EeCyv2p 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 z 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ν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.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�#YEo-Au$A^q3gClA;=# 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

W$K%vP@@@U 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�H7!oNg>^Rn70%mv!f9DGxyjIIn6)=R^ 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 %1Ad+=cP7oxFgnJjC-+YJt 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

A`^SbSKBcI?2Y_nAeVCK#eo8m#W=)KUu=D8!An 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 z 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 QH?3HV!d|YWrvp5~6DljJ+{nIjS}Ky$ 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

f{4tqV#H&Q<5#&C7+dpo8*fp=M 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 K{oC4oVI0TUGh!R zNzu4PaM9BsJAH2brjTZ#IJD||+IDLxlo#)C?(`#PdGqzYqX*B4xYp74HTO^2XG&GI z#uXDN@^@gh3MTlLuuj&0b0sDvefp%F=ax8`f0a&YU#+0aeC^JdNB~$63=jRxVf-ci zFd~{cHmkA|Mse`q9K^kx2wGMU8&C zEhkJvC{-oO!}l$b)XkwvhQ06BaoFbzoiOLpuT!*k_KgHrCG5+h!#SBHKd8~waU)57 zw^4K^J5?;a&zJTL*eWFJnkS5=v@jtN;IdyPT<^A}3M5M|$tv0@VSHbow-2A#gB2lH zw)Sg@1)FHT%B46e)y|Q@EPuX;8{5rUuROH-UT)Rn$Q-AIrj(aP2)Z^rn&XhwGQwnD zPehUcBD9gkgD@YvRtLYPnr8J2f`2hGF~3t?@r%#dR`*O50@^Pe&@mJt)Z9%=bR}*B zYmi6>`m$%boZSGWv^Z9}D_?*>6L9Ts6a6{Ev_#c~IiYnOw|>)P2IdWh<%<^eIq1|ni*YR6S?7t`)E>QPukhpUaePO*v7V(U(YT8l zmE$jojpa~V)^w}9*?%^Hk}9Vu!;E~6H0i<0pa@B`>tk6Rc-tKNzE>jhP-S1Y>ecyVpg|kGf1Udm46bMa z9gjG3A|LwaQ~sv4C#=c1+8v!PbmW+@PFBY3)pr}y?>-xGzOnNM4uO}R|jI=TAq!h+|*S%p3LKBYV`&X&PSEc0iiqyfHQPq0EFId4 zPwY=StX-NJ6AoDEUSp6jP}6THeUcs1BmGH~_=j*XVdq_V*VnIg(2zVVi>f~w)>7)o(FJ1^Cx9^1w@63UOg zp>FeZy+Q>71}ZU=o>LI4q)Ic3$G`bH0^O-G&#Wu)H3!P<3Ex4bDs<{6Ef*r2GKZ^> z9OX1}aq1UtJtm3bIB{nYE=&B9Mj#3S;6r~Ht>BE1c+`4af-N|Yfgt;2$}U1sH8-?P zjM>qkiC;bDm(D4VHUmwy#k;Bo#6Ukoma&PH6R?lAIFNO~%G?KzwuYua_H=ZAO&8%e zsU_)li`U4Apn&)I;h#`Zf_bK{5`bPY3I360bD}*(tCo&3?EX-!B48!t!>XjIsPc)V zN-$ZR-Hn7=dulTnJ)hZ}B5Ph76ve)zNq@z!P#q{MSWUhs5=8rcTjEtMnDKB^6mr>y z(vMp$xqtag7?aswg~u8G^Fzz6Rl`(N$mBer4j^_lrk2BtTFTgg;vgW5o> z>Y#K2ru#Sfu@0`AeP>QI-zVm@GT?bInc%48sO0X}7wW42YuN|ckilNdevuc#u9#RU zMVoloF4GaHn3qpRW@++XD#9&Su+m6dhitvAIa~uv2W61$H)l*`hb#4!w5> zX^&{IKP&pP7LtS-c<#Z&yd-~xl=rZ|I=XR~<4{ER_=fKJ9rwgMqHsQOGg#OxW96R% z8{1#&I5~@TXJ=tS9r$CvgQrtnTp3{~*Z&{nG$*9OU8?ZZ!svsv%5z#Dif`Qj?;$lb z2#T9K9}4qlZ|=z8aaKNqtNR=ZkG8B+ zHZ*x?Kv98*hWr*K z4d0ja;!viZ_XgFks3(VBD0vJjY179JKy&s&S&Z(J?eHm8znU*vJJoE(aMei?E_>mcMu_mCg&jJ$jz?<8emt3claE-GYuITyuxnBD*wI@k_c& zGM-GFyq>5~ynar)(cm{%XH0%WL6%U}Lm!F%LRJ5KU1X(|-~-=E_G;?d357qK`<7cW z3$#Cg`G360J&=k5-+LYz@iQw62S=JM1H#>n$;%dERHFm#XsI5d#fdYgWy9E{to8>h zoB(%)()qb3htqdVxH98he2b7W&M96KLk9)J3vk$DXX3tfK>eJVc=oJj;8A-lticnE zW;gk9iqQi{PL#OfY}CBd{LFOrKl`O%j*t~?T2k}dIlCKE%QVP5Es#_vBOuvns8oBdIqqiiCF*PJhsBQl4zo`@As!i zNQ~|srs#jDiYB+$Tk&srb0}*L{KAT|-tii8+%V~JJ(tbX@x86+(US=YmKIZLgi41* zAKE;hzbN)JZ4IM<@}ES;y->u|@u~AENm90)v#V1wSYzWlh}cs0sbpsW1_3&XZueWW zixb&j(yw-e@z3#*F6`ta*~VHH@-ZG&V#ZlI-F5tw@BTW?3IXUU@n#8vjSN^xqCbDm z$m}T%f#oXR+<6F`iEAv=H(|9!V%_z0sLi-j@lk}I++@t z&Dz2so)k%a0bkR9VZoK(S6H-U$ijL0JpmFA=Vpz4ZqyhdTaQ!^ht9BZ8m)$mee2B8 zl=5DoDBKX@`=8y%`koOo-QOs z@p%Sn&M@RshynjWj;Rp51d{eO-cQbL$5l9$X$EI(x>CO`=pr4c?DC6-FkTT8`{<4T zLUR>z&9;@|4LH8P(5{jX?F+f=K={#i>W4yLa84Ck?sMtywAB3Z(cn-wJAmTGPSrah zsn$p-VhG+o=yz##=E{lA*EJ|)dock3nVaixfX?LHmpua&s8om8xp`!*eV*curU*hM z>AA8vI09S34^WERXWd(e=j#@NTMY~eQP%?8d>EEcj+Ikk`u=6By}MC zWf9%A=sYLPo-tH74Z+%gDUU$uR3$oGT`>9;6oDzC5=)KRpTg|Jhc8f-;)s(>ZvB-~ zoPJ53QcAbaR}&`dZzQK?NS6FF$;WGsscOH+fHbhUhg4kWifRd5T^842j(q#mH3RS2 z#f>$Ruj}S;Z_~3ybVOgK0?ad~36$>_=Sr#$*I!?=x-tpM#?Sj*Ie9(|t2#B8(o>*W ze_QJYQJ0wrSqPmKNXB9%?@Tzo9~?kBdJkb|Rv5geWDmomyU0F@BB#uc=CGRXt(Src z3WdBza8AkU#?gDet;^HF9dz}w{3X@ue7-s}D7Zqg0di8C&NPR$*J4x{-H(0FV}-?ZTT{9!KDH2WrL*q*O})I{%j};;l~lr|o3)q5O`s!<+Eh3J>0HB8 zc-$B;?^i=-mBYW!_TEB%t)ii?z@u!{kSunCntu#rnOUXcjm}{DzjjdU6U{==Rz=cI9FI1i#ZGct1&HKU^f2rT9P_c z2#)!8bvxBVt%R)BGP_Zd;c*)eeiUsRwGSxH0OQHH#8(pMHv`t^z=whkO|U@5WM0@` z%&>Xejle8np0#o2+-1wc)yE#n*~y+dmsb;DsqD2oI`>5LYFK>I4Jif1bV@e$Uh@CWm_*=0Y)AZU zpkQtZsEF^ohwSTlzjYX$TL==zZk7)?WHt=>x$$Id$6D2-IOaxWetEsNCtQ-R`FZ18 zg7>`9;!7{hCZjDCKaryCnuE0glp*REkS+bn|5IZR&j;MD4LNgbUvmbr%P}y=^0spcV2l^<@ns zg%RLW4}^J5UW2M=kWPVFqOkPW-2V!_c6kZn#`B?2FIs-|<2w-t81Uh_5Psqpuhe1( z=oG-;^I*(*f#WmU)%WRR)8Ki?xM)!v{Q|;YZeP1hKvHu42xzo+>{~LiPlvk?y!tPVD>36&!ddM0=lS zY!34dbEDz@lbYd;$x-dkL`7^2Ddy<6)0HF`dRyGj&_`Q^Bp5D1S}@rl<9nc3I`oDY zP|ZiUqKYgl1AUS|qE&k;b)_!}#mDcD+4&C)p=UoK$7Xf- zz0lUhb7r&&^iMxS`&c3mt!K+#ZE!Z%KiVKpOWxfgwiH<#24tuk{h*rncrcI}znV)! z1>I9rHfz{4WKI!IG!28x81TJ0BBy^n;wg<%!TO5Z($l0HN*ef07NcVueaNvNd;Kjw8h)61Ulcocn_hu? zq&IQ+PA7Fj&Fm&;k=@<-@k+rgd0ukruw%_3{EKllxJ*Vb7}-U=e1~lJg{iDxT6=17 zeBNZ4aY2rTj;v*9-^zas6~ou>U)mV9!{EuHqw>mZe+uwxD^U{qCSGclbzjfduE>!) zq1W~Jhk>?5!F>r-gC(02rI>@ytOfRoFc7-sf!rVO+!vvFFo=Lohm(+HW7)ToBp2Dm402tjDW^2ahe9hdLase(JY zG1CGVgMjiouafp*4T9IDLYoz`)2zZLZHn|HBal;}$l;g^ftu=cbZn!;#DN=Jy>?ng^h!As^DoZF(^6}C>Byl8NA`!SkN5e#}?f;BLiS9oA$|e zh*yCX)im}1DNV)WsvY6USzsT9*;+Yj?2}nr4ETBU+esjyeudtyQ-*&A=J42#a*@NB z5DmQl5t#X4iC~P~IdF-+qGetGt!ofvPV*>g7L@GyLnaicmEN;^g*Op zqi%Zp&vUm}0?&#_ezk=Mr@B8va^_FP4*kh50_-OOJ#H@qk!dAjQ6tJf*pn9Zc;Dlx ztfbhJP6fAc)m9-hCj~T-2_k=nBt0X&1Cr8ec0O#fd$3KNf4#Sy-5bq&PVQHrB=(Q! z)Dd=QPMCr9YB$&z5JHZ<;=qrfmL8tA=W;!7)|@Z#Z{4fh?8-c!z;q_J-+?ECx=u9O zgK~eWUGjnz(DrdBpEg#L$q=C_C?_NWok}t3KVK<%if^{{&%wI52>Fq5F^aM{V{?`` zhOLTIlICbm;tcDWdWtHVif++dm6b`1lu~SI&NvDF`S>s14!}&nyR$(FRxwd`xV!b$ zxmyME+kZcZUN8tTEH;7^vR!lHKu-PLqyg=LqvF+xZy$;f5>S1GWjYnyz5;4%f0Nqp z8paqwj5xCT`iAoKh5t7G+Y91IpW)s~HP%C@@uP^g7%Vq(R#h`oH5AgqDr;0pzxO0%XzEzqRco!Crvti+1!{P$9 z79Cm|zGkH%#OOav+C-Sujh16V8;@p7!hikN%cDi|=;+iG+Mgb^m*kn+aLtd{hntN8 zQY8-ySdKxPI4r`e6}F z+aADgJ{?p+H#P1$6WZX_X6N^-7-9+gB;@ld61$DSjGeb%U&UxIdnKOOLlk0|d`mXX zR5B&W2;IPe5)!71=b{Y{C-WnX>~ArPc4@Ay>x)^;BE>nk*~^23`0wwtD-}5UB@VD# z@EJ3u89`ST&}lOC(tiudp|VTe^_>|Q6) ztE3k_ry1L>xeDzXYFDzN2;eoc2Zv*+XW%gBmPDcw_D_Zg&_>?}7t#by0_Qc3;BQv8 zSMbI^enjn`)_i!d2I`n{UaYOjzMbKTjr0&Jp)Wd3%Th~cg`(BY*O(!Yb27{S^#^e{ zNvSm-@Wze7`TM>-pI&UQ;l8dDgX&3oKD^nI1Uw&(eR^DpP7!*Aqu^146l9C7O4Osj zl*qokZ+QH0C8EEI&4{`d?Vjyrf>o_+0P-;-lFbG!nUki!7r;jBRAKzg{{%nLT1rpq{{;Lq2N zOTikYqIq=9xDnxF6fdOW^JG+4$(DDXT+v-=^3S;Uv*Wdn)Zt3J>ObGUsuC7!Sc>nE z=~u65v&V&Cx^f;tb;&CRP7-;A(Wr$eVzpPpW`uXG97Q}e3gPkR`-x1-b+^pTwjI|t zWX9kmhHrkQ%gJf+ zJ<0>3t*l>D+}#4GMW(RJGZw~IMP-GR$30ko0M?2#ij%OKZ4FeF=ea*paO9EH8q128 zWXmsm5}nEkT5o&t8ixs?EGn2~Lo4?#1+EvHYzA=n@-4Q&lUgtK?h=iphA+dzn6-vW z|053np17|f>YsHtKM4daRE#a^XxoZau$j)DoXs>li0}9#x;-^(kyzoY;C@-=51PLUhLI|!i!E42-&!v3|uV{b<043sq6IJh3jvl*n-)D8b=;E%@FrOCw`C=E0AZIGC`epR`p73NI$nn+--Ms?6qtNWZl zmMc?)&&imKNcwEXRf1Qn*4Znp4Yf$L*52EKkl*b79=Xr0sItms`z+7(^wo~O>?c{A z7Ed=VJP0Qo?acC8HZNg*Ov$i=^PeU6#7}4{oBu9x7?`x4v z9w5uEycY-L8969Ap7im}6O$s)^ukokE(~}iMI{M?j1DcZvFM7KMbk*!pUBm3>x^yX zne>=B|FhoLpveS!xR%u})w*J-ee!>{9jO~-+8mIIgJ>+%&WP#harQ7|bNgkQu1+ipT};^mFx3=b@#2#nQKes4+%EP&W-fb1XEW2pDl z)w`$Po>vXut3ldn14v#fe)f3hhYS(q-=yIn%euv5Y3ZudeXNZ6>jqQNH`XgN*x5;) zgT^5rlGLHGIvMgQJ@{_sv6DG4T5{Wt#>LK?>*AuMbebV#XAqQ=VpTF-ZCFt;!{8b@ zM@mH;A(D5}=64%^M2CXwf62W@6fIIQSa|5pXOW6}#7EW0;gpK8$-3zB-+z%##jUJ) zUP>yIGpwB2HMmT00#Ts|KbxHUSZMm!dp@EM#gn5L{VWT_rAGHEl5WJExJ@EdZ{QIG zmfrSGdqj>hBY~~7gN~dLd+b=+bA6_e0FQ4Q=@nFJRiFSFu@UZZ8aB|%i)@Fi=zKd>pFLqxm5&x-yQ6S7 zBe=+b*rNnSf)tEKd=y&b!LT!&4$GDIAeVzBU8Y1D4kwn$lw82ri4w-CJ84_8%8 z-0FU5nU=YLq&Z<6!fj6#M0Ia-6DR!v2t~`2P1wei_2|SK@O(?M=HW?0nsu`rcc!$i zR%r+RrP|_(Y(#J9FdP%4^qFID*%g!=Ft;a%9213X!8&z<)?4COyjf)S2rA*`;o-&E zEuS0p6h%^pSR)K?_R~*StN%>EZDbiw4RtmBu-5A)gpjz4xV@j*qAW*TFYtR~M-0Mc z@lDwu6!>(jP*)Ii;yiesk*R~q{@C6R7J9#MmYGs&(k{qzuOm~6d_6Uv5_&q`+V+CG z)(ki18R0eB_3_1(wQ&>KHU5;2_(`kh`X^gpl&FhdwE5B$~hS{v#7z$1%3xh*tTROppikDR`=Vly8)%qAtfDq$g^2gniHZs zE@@0y2=kqe1gx-VT68;TMFE{MfFOMT_k9G8KKfvkwxwRF)Ie9{LZ)GB*QGkXx!+9H z0pF5O=hM#Fv$DfKrXq(yukMieWe+KKlw_39T9yA~pUOfoRz4ysPg9!0peA@2%O;9@Ocxu1p4X}_A@%&LrGaEMvouP3=J!8?pS%t z$$$6%#-oGj*jj!P9*B{zu-%C_E5HuL<(7)`WKZI#H(=YYAT+xqLz@vG49ymLL5ac7r;{(V zLsm*S-p68SJ=c;izNOiqidVoJ7+Bn|C>iD=tsTTnIs70GvWm0WdSB*tXBxeZz{wF? z-g|+w5C^n&FYE1INz-h^s2YdrHQgTf3;HAv&^Qr14=(Gz^;NPuvIpT!*4@_C>MN92 zDDYvSm-yyWpSB1fYs`W#6<2n>6!7|`oQ4mqCoY#;!;iS2`YFLDsb&Q;bUw>Ub;qN% zkd2j6oDhsywon0C<&36kVb~u<|0LrV#M~4xR~L0Mo{hS_bS8%SC%Xi5VkI==xA79{ z1E$=uh~?1jtU&h8hwU#=*VHhw6w)v+{zQ;$eDkHIIrH;1681qlCGyT#`X$$DFt1v* zLUF#GZ*P0Y%atK3o{o-ho!%rt$<(C2mk&48`%tY6mHs-uqzr?3|1rAj-%H;QNORNi zhA(Bjg7y3D{x9&}iWk3dIAXCVR{|qazD%t#!gGRphLrMSpsa*0Sp=3+L~!V(rgQDzOI>k@*(mAxCx41 z%c2B7n`GWi_<3!-9Q9p#SE6F|?kD|}#sXuASE(ZhD7ruu4Z_)eyf)+%IX*5BK!_(M z+Pz=QW_`)8g)T>+W9a{?>%S|hU582eTk!^o(}m-gETzID#y7FXPSbP!v%3`GBf4Vs z`K%H-hV0d?Q-D{jU~?6a$_VU^30|DKORZ?XPRLJ5aDSsfAtXC&ruJtdKKBiQ9yrbp*4SBT2)Hz;l+USEdA89Tc@9lVC~$!S;f2aWvBkWWqQz| z?zobAl%;2+^ubhjSSfxr*YWbD!|>3?n89k|_jf=bHrMS5LjE_p4;pOzxCYyD4UubC z?qX&#vu`(GPiyZ#B`T4YWCA~bB;3K_X||4&Y~`&lZ|6l@OoBTjb7)#ah!7Y1JuB;v z?IOr~8yMroVo=}H%1$BzCbQpEE(7ByQ-6LitzX)1zUArg>7M>x3SoD)K?PdzHva>g zL1ezxk2gP%oIKrsya_z7e)den$t+ntxtxqThr`}=?KkiLemHtS%{PTYZ8`^7Z>4cI z=-eyG6qeMd&(hgHC$0Ys?1vDiPZO?=AWGHd1=vrxQ7AM;J$(EQJgH1>0{M2nSUowW zY$YXu7zuHWg@?n%$(Ib8tVmsZo|Da$w;SLfg8<>k#bmf%PG;lo+MS<2{|vQM%RIe$ zjVPzR^*on~qRW?GvZ(3UCzr4Moug%PYiE|q6_9`;o2;D&`SxNu!0=m2;=r_c@=?M@ z(zo|`L-?v(uYIef^Jst}p*!J47zr9@&k(uZPI*cV5Bu$A8H)+!`dKoSRTA1_+=pBO z-bBr@wpSNF*D|@l^LD-iM+U|6f;jBlSDWXR#u@QuBiTQn4m|7OXt-@3S~`E!eL@LV>ouRUKTT_Y9f7PKF)^S^Jkxt8JH1L zsDDVZjQqDbBOopGd(KWjm$9k>jV_%ppI*LBq_VybfZfIE*M8vTb2WzLO4&=EmrMgW zkcg&}sf?l|MTjTuV^|h`Z8gb*#*Guh`T1v+`svO^&ptznW%*J)@V&)kKmaC2TuFK^ zjM1`+t{di;$*u1-gf0WcDG7>nPX|2|a)oL6aFnw7q zrs+&6B5)zwG|IKJO5+R`TVu6e%`44w%sDiSD*sG6O6T?z!uq}T`!L-5hbOsNWSbrgk_#wiKuP`IiZtB>FR z_DC!V0#9F#lj;2T-~FAcrS^L-t|aOw&phI_f$~pQ%8j$h;!z{gu|o)kH=av)Qq5yL zzh2GA2-&GOuIi0viA2iVISK?uAO{3Nur*e_$B%}-Xq>-@LQK2K;i;3#mX16Mz|k$^ z_U_k&SDQT=E;*Vf7>C%-bw*_Tx!tUnv(ZLhs!-W`#cFfCoV($?P(7IqyAegnTm|{s z#jK2t)&PTGia}>Rt}rw;?B2V9Z5qp$pZpT+piv(`S(Y*Md33<1HVhBT>Cmw@vvE&L zBEB}Px9WY-;V0zq7WedLV>x=2mv0)v;b^?T1&vgf#yYaLWkaXgD zHUIs8{r44sS+VBrJ-i3v({t0w5=CPb7LTh@NM-UB)6n<(p!@KCHtxxa+I#%ayaW}R zW*L1sN#~0CVwNx0eQ!6P_dU-|k&Z9e+lO#583wx@9}~rR{IK8W3RRYpEMpC{07lV& z4khP`HJQYh^QC$kN86H#4IWU|51s^BVHvhqYaKI$ z?Yp;IW4$r-<61Qqi`iR~Owb^}VmW|fF{{Eqz*yV$`SZ`y*+MFvry!!4qN6B?XV;$` zx6`5==fI!~DJs1G@I66`Zf$Ej$GR2Ba+ZrxVVF$AWU^T=1K%sxnhzho$6%fU{pmOVYm(rAF*z{T zk`xE0RZ%nfQmJ;5Oy}PG>AxX{&^Sdeh!}r^07$?H@sF^6`pnhqO>l9!Yg?16xCuE#x zF^M_Rh{mD;XfBo0X`FPTM8nkcj-+u?owTu;6_vxd(HPiVr3t9sR^{!(X z>*X;_Xxkf>=t7@%v*}Z=ci@qYx#%d0t3to*8Qh@c7!(l(_J&;L~OjC3fk;*%By#zn8 zbxz`;*%{GK6v_?wn+EMPo;9wls`JSpoh#AAo)hB*$F?Xs8c!cD&cE32eQRsb6t!6| zFeu{r`Lq{N(doq}kM}FMhgn92f>X&$8CV^2y2N%lr4=>5Fl$P+QDK zimE}XB}lnaHHxT&md1MIfL}N+CItR2U#j*y_Zfh9z@s%cda+zb=nb+GOdyh}OndlU zRt1$Mt|T#@oQ-5)V%bD8LzDZlxml^nwD0W>0NhexxHs2JEmtu0WxiCK6PgV#N&U`E zwSEDR&Sou0Xco@(ep)SL@)eX;(P-E>7RtLv=y({Sfqpc7@S?O{f=mZeXR*4N3~)|L zLb#YO)r{35oiB8r-ia|ulz^}Db}oKbPcDfxyNk1?Wl#}CbS;|axmeVMN6EHBg;5ZA z$F7)~Oig-E=*7Z{LgnDF2)CQ{eAG|n^0v8YoljbdbhzJBG+nGUF|gTgSMxE6 zP$IY8f4cQ3w^}^+K*`|j%{l}VWq*488gJpn^Z?DUcGw4!lIV|aGKmtDyLy>T>B~t-`ZEM)fu;Y^1px%sWSA+GH~M_% zTCQ!S^F@2R1*T(YnZu1Dp4hq2AsMS#wRJh_ zKP8CWFAO0U;CXQ}Y-bDA`E>B=%U}NRhkr_&C}44MLKUv6@#;F8WV5EXOs^U*PIB?PKfWZE~q<7=;^S zUaeiCN=qXUqR%G?=Asc;#(eG&kVUP22==wp>y19w(s|r)R&x~B0QI6pNkUsUQ|vu` z#CnjX1wqagE0ZCxT?s9d(6aB}{kB>aMi{EmpY8lry3zg=_H@}zS3i4i9vJ+7#vOj29%qIhm;1)K< zN)+Sv*1Z1Y>v8W%B>y}%mf0eX>{uVgyAQyFaxr1LdP+!nQIy3v8Z717$*}i8lin0S zUUHnKnOvdTZ{J|tDB|}E=MMw}C@P||#p+@@SZxNGB<|bUTzNhnma0ubj6*SNqIEhQ zb)zu6c=5%Yh^QxncCJwI{GDYQAU>m31d?(lR~~lnwRBz(Aqip_j?6v~57_NobG>pM zGp>N=y|I>wcs5re-XcU1Hko{RF&!jQ+2wTDIJsWTMuI3Gf}^PT^S5vQv6yciJEoiU zGG9Us5girq>3vC28fVY$-~CCH<3w(?vP`{FKZBGPpw+dZ&jLS?WCWf#VYAxD{AWg z{kL39;8?EGI*0FERv+%aJ2`ntxbo;|4cfP_zWOB&3E9GOJ{G`)S*P=8Cxe(2<4d5u zO+xHOVmzUNkr5>BR2xFv>fC)$ld0Cli@SHj(*R07)=b??E{I=!?_ zaHTr;Z?$yJGB*&JmuiH9kY#8_UxG46GM}5%>(`GT--wb-SJMB7BlPN6(KsCT#%fV0 z*F1l>_q~V;V=)0zA+(rbwagaEtNA#tB$x9Ma=j!pzMPDj=g$+#%yK^7=nEy0F4s?% z)6s6{_#SS4N6Cf0oIJLt3_N*c*KZas+}%p1J}1w$-I(C9S*@!Jlwwj zu~I)@&BrXuX_-6~hA0rH@q}7TN4au!4q8Pz#>3SW6NKXh2AF)B^01VEBwR_R2W>2i zi9r)Xntgz^m$NnV)#k8wpUISf%5$JjRN@+b%@WC2jOSPm$vwgbNo4@4cU_C7n1~7; zw9wS8q327r<3@PBnu?+l6Zq9^1lcv>!scQ*D3{L|l)iHy3X?Emoaj#H)4`6=_cDbF zVKT7ERK~!g3WI+De70sXlf~;+OSxN9%M>UoBnEXXvqV`Y3kF4u%dsv!_oL*BD)g_-T+cZU4 zhMqQw`CJr5F_Na;@4Z5~H6A}GGGtg(gtNZqxq-JE^luUgpszap?+ckT!XY(PEoH3c z@X_ACQeiVjUwlL`2s46ToL#HqdSS6k;d@4iWDq^)HP5<-qJ9Ot48wET9fqY~hQ_(rZzSOJlH1m-d zpY#dEFEs;_0#^$v40Rmuax_i5wuOL}9JfpmFgE5qo2jl=lXRw-#z4gc0GFg<4*Nqw zOPj_rhrRr~Qa|fGeasdrsPx6LMxPG50UrANW;aeN%~&kP2|`>=?0p}Cr)=KZ7`C+` z>Hxk!`d$?(TnxfKf>?1O@O=W019KA*mwc&12#;Diw{ub7*O$}nRzJCTMR;NWI8YcX;$;Al(|ow6 zHWz1q732AvkKbgHML`0~%QDw5KL7b-@DvlI{^N%u;wF{JZLsCfcKhFF5)H?;{DXIP z@!4e1Hr?g*)z>o^p!p-{@URcgu3wu5NcPAqQ3$=v#=V`rJzCE^*O6p}n1)r?wr0~_ zy?K2I!5^b&I+HCP!}o^1bS*QP&L7FmJ4CweeGnMV{IgI0*3f6J$1 z5`LHDxh~BxroNOEwbr`&_~!R&GMz8gw#J&p@4~iu{`~gsxAoI20IUGu3TLBU^ZdE* zxszdA5TxDC$(3r$>5%97wJ}d=g_t0in{^KSUn`pjsRo-LEW`~-Rwt8oxqOC_rDZnG zU%K{oF&QRP8Eb14s!fKbdk-Iz*{tWfM81RDg^Qjv9Z{&RdOK`O2IKFl<!?jhJYR=(0SR)C~hoDqLwYZ zdGjAr@!AneW*Ts@sj19U=Z|qde{6DlI}CAv5ZUizF`i*rQCPz99CD7|Q|=GF^6FJpV-yc{SUuKRVF+vrUNaDno79e z8^%(S(d3q7Wj^U=3zgc*^~X2AS4a*`5anU_;n}A@9d_?@a=!f8-~7+``-*XWIVo0} z%h@QAgf7ZLyY$t5@AaQY>=H zINLnPVEy%a&M~oUv6{{ldQUgy`l-2DXL6+tzICc=qf%LKUETcnhsn5e{pu(90~3fU zI$DHym@C)!fk)HqMxSG^l+=oqR`>oL;BV>Not0aI`h7P>peD55{l{wSvVHfXAV|qn zE~03j=jW5bVSgY?>BZrIl0zz641AAf=&i9l5IxHwJmiZNYiq8c^36(e{KK2yU%dE& zWm%F@u@Twl#rddLuAd-G9Z|`27ILf3{qYcg%=g0ITcX};`c<=W-%p0B0!TNv*$&}+SX66X5+qPt`V=y zl@Nb0*XCLmB#EGb5Y@#&JX1KjP>AB4@h^BkUnlnL_*a$Fu9t41IBQ zROd=HeLl(LN*K#l08p-aZ)A;cHZ=QepGjHb}La^5@)9@S%G*}-3d)Kj2 znf#GLi}Nm|tLOs+fv@5iNyTEqWYC85fo67&_3YE1F{Hd2_};N(1&}UM`_Q7z$9?=Z zVf%3|O7ZT~O|jfSFc@SZklAUPHT3!E)$9J_N1A1MUV=H;G1Wu{qsh4HTH6ml{O;?2 z@jtY0emnxKHtVGz$<}7gLsbqzik8l|E?;yW-pjHQM&WTXZmi~;jb13#rFbHd%5)z; z?0x_2`RBmW7&^@`d)%z{jOV%t;gEN^Y3Mtoh0?*^-vJ!9Pb48Ha*wD)II$P+KmJBh zQ(y&v1I-B{yLIYkm4n1UIO zA0$fT`xwSgN1dJPupGZI6dror8&Ff$%M>wkmmBA< zy=4J67dHCJhCLUmfgQZo5bwnZ+n!}{ry8JMBU2RIhk_`sHi-94hg~|Nv`isas-;Ml zS0b9Yt)V;aRwv^3Bbusy{*1!`D<0$d?HVt_)63V0O6z@~es+#1VO;e1@dw8;$IHk1 z$@S&Mm*kf`@~PcMUmo#lnQTR$jsBd`Urdteyyv>9Y$5QGjGqji;&{VFg<4CLWQt48wrJ9$+yUaFndC@a~VJQMy*t)XkgUWs8-`sEeLcqTn6e zV=>_POffg;T0OMCUCl?mr;o;JejGj-tNGQ-uNjuz8cQ52H>-FY--qyU_;B-EM>WK(8=+Lz-hNcq9RQ=>y%j85U zUTt0Z-Yx+}zzmwk=}-`{#-SP3@wS;9Adjv3=UO_K$`ubm04yd^^Q>m03ADuUyU{dV z$Xo+3=Q_L?Kl-*ag>t2FiY@`PhzR#xtc{MncHmJo73_VArfqwx zX?ZaYgJz~suC=a~b68N0I2W2>j@64JA48JW>(@Vd{qk3{ac`q9F@{LzQFlWPnkrOU z#4Bkp7DG78(+EA!Cj&v0f#;k4Sq#Ur+@HSr&srw??)^XQT-&v`kWAA|=l4R-=3EDiUHqX&E2I3I>J3sJ4p!eCp_ZzKiQHlqMKcO88ip_M!RL!=B29M7E7MqoVL0kN z{?mW`e>2de^rHyH3`vf|yJ=gOufHZsu=hL1p&3+z?JcBf5k*g?Z8C3kV=DMDu_Q6JiMta|+#I^k%`asW(gnS8zV?BeBD2grT>a{WxzGJ+Hbe$)Yy zE?caX>L=D_4GjoBeOV9~XT#Ze5Qf-XW%9-KazfGAss)~-rZQS4zjJIL#=}To&F=30 zXlL)SCg7OT* z{OLFUkzttAXP?Z5ohS@5h03vIt1qVv%gS=x+qvDx_k*X8hCbIa`F{JR`*g#wY_WDK zND}h&5PhOn?rcp#kS2pp@8QE_&?XAAwTWlN*fQ3KLjaXZwUsR(V9oPFTuoM*7o~b@ zHtt@$_&isvLB!d;uQbp9-0YI#M-uUE)!oWq3jS{IC8c!*Yt6 zeD(FO=93}N0+U|gp?lf7c*%=WsdfT`|41I1{Cf^EX&1JEhKB_e)|?l zcOnG}4}1K|*UwA!Q~c~OQ?5l+bR>`t+BY$BV+?!`NO9jQRO;{xZP&7*7Annt`)0e* z8|Tkc*&-KX8yt}mux2))4dr$1S(rU?z2 zb{S!5^j^>^!3BOK5zIP8Q3%klm&Ixep;ip_a_hy^+UNmr(hL%kJ6DRM&MJu55(BHh zUO*?x;Zwc${U>q?CqA!KLQ5Ab&8M3;?OXg|07#`EOWC=0vC@PBWza!zIy_XH=d)2S z2(T6~H+l$awz^);K`|M%wRFxwQ?vkmN)#?;gIuxZxz79Ve>)rXkaSID$GyjD>jDgA z@fbO;HP4^N1X0TrfOxVtzx(@t3z*fY$I$G4zZc{Bzo5ClX@jwcofr{Yw%-K@8!VMWVk?d5pz)P4Mj z&&T{n$Ten9h@1jS13mcBkOG4#Q2Gx%*k_ivb5@ISHea6fp0?XHM=olvz4d(*u2sO@ zy@ZyD5l#eNV+>QMHbJebG)lmP37)r0=Sz#}P>!qFQgyW)W1`==BhZLUctF}R2)wNc zX+m7ljthYpFG560)9`d=3Z4r+)_xDskx0bylVK+o6E2^BnMk5(p{QE0^D>2U_whre zasim;=@o(4DCu0OR=vz+Yl5V7AKqJ}1CD8;n7|;#G?2#ecJ14@g<1<3BKnw*#JV$| zt51zyxpB%c?EAOBV>ynnM@6(w_CA<#@JordqzdI(*GV(CeAdyj% z$#kwfCbZ1EAAW6a^h~0pYUy;YG@d-rP~iea`jemhPZ-<8ASOf! zhKlc88`cG5#qm7u8->cl)AvWPm%f@Tro(;U8{7H$vrp~qh8N|J-~SezhFA>a3R&qs zyz}>dsn#OZH`wEArB9Z#QT5~^ohsxD*tP>CCrZBWrt_8gcu=mMZS(~o=#>k9=N#in zgbXV)4E_B2uW(Y=(nv{?NrD_#R`bcmSf(-sHIbUn`e76u^{%zzWjv9rR4yii&Step zD|JOq7t4(mmcoj@oThWd9Q0lfu5E`=G#Rwhxe`ZemjW-1`yCqu^xfMxzXk~|kzxsi zBAqQoQ7C{Ujcg*#Fdx4ET~f>G^C?fE&zdPzxEMT>Jh+oAFMtrNsG7N1`n%m%zxeNU zxRBT6^aF5YB9%!bQPxqDS^PA6kBAUtiwrU|ti3gHJ(lA5*GZ=v#4gvFPx`Y_7d=ZF zAyJx!goWb;;sp%F7~bu1HHq>cfnKw*nCsa6$$Jx#WhGy!Z}esF;r%go68Qf4^DmB< zZC#&j^o3;t!mA|GD3bC*CRdK}LZx@yHKbEVw@(Siu%SEo>IT3bB|55Us7mZBtbg_;&G zONz=8#VO0h&^2_d)&*4dj%9k(I$NkFQaOg<2*)NFMd;oIdw;#0tAtnzb&({WT)j4J z=oFMh3f^cUM4yd%`f@hvJsPWdq12!v1cGyg>L)+>8y?ULzS6k>gzP8JkJLnX<8w#l{(HIXb=a7B;MXvfAC z2wK)kYdnX5Mop$l)ssr$+VghFMDFDJHM*+ffgkKHUw%0obu;;L^ZdE%B6sxmkN-_g zq>qa!(kbUz0FE-C5ugu)yjd8Af+*)p2=dw_6BR~LTmWzoiq<5W6)|{`;fN?yTh;nS zOc0Q(DOB*2g>5&^fz9gio{ zxc|tuW$Dn!NGuc6GWl4HkD@S!-)n8>!i-K7lR+w-I|3qc>?3j0!1tzuHe^!3+az|5 z4WygvAohmf4dM;OYAcb<&PSMfrgLSy_^T%vnkG}{XJ2aRT;mKlpyQ4-@OGuz>AN@o zczh?~^`S3Z+gwgZ>(zYFxk)J5`Kmjc^vm_rQ3uawpo$q*)3ONCNb=FbwsRcZJ}rY~ zm}==c(ph&uA}Jb%?VC6Iz|WWJ8yzS{bns%r<*Tn4h9z8=S-#W&R6`I~vvK46Mf3cH zC`pICpUy#PoFt)klrlYU*uDh<%QF0(n@pn-{_@o?B8sY?U5|SAcruINqD+PzQIt39 z1qO$Kx0sEBz&pEsz0nuL&K)mG%gL}(JQpMg6Kf}z1R4%*9PEC?P@XB2lc}7NNbR9h z)kI9sGPVhgRO9R!nLbR^L<%jWOab&iGH<3CwEGf?bf!@4K70^F34tq&nE_{$WJHmV z+|tv_S4slYlT;=j9`@yGYiGj=h4PQ<=1cW#9_JkB_JHj!Z%reiWh#w}Lb=Iuu^1O) zI4+^(l3F%bs2<>Xq;PWITwnCmlrYQnooE^%$I5$FBD331Q)TK2fqQLh$td;l>HIH_E&%VKi5yMK{Q-1 zB}Lhzk_$U8aeIg8*G>ADufD{bc557wK}sTN8hWXA8UsXrYHu-W%oeNT-c$YLT2{1d zp;B#Ll37N;g5u92*oNxkrdVmh1Vh%sJaNpg<|CS>q&UPi_I8czVq7KSFeHZ&NW=1k zcOCoe8fg1WzC7&Q%Zj@9{YmdB3X$`C{q(Bou z41~gvJXq~Q^0Lx6uawS@NNLZ7Ws_l;HQ~(Q*HsY1D6F+gMCMgJC&OkT4U^3#-`}h^RbL zhAhig$N*lDq+#zKZ7`1OKE8JWI$-xi0DjnGM}wwO=Ye54Sys#Sv)YB3#MU4E^l^ZIH=SV{28#6^6>1;{~AvDJ;) zF_`}1?D~71(YdP1)9I7BUSb47MM(wr(*WUwrXYwM&)>fL(>~a5 zH|t!n9uq{%G+uo13((K~-ExA|bwUMtdDyw|X=XO=XOb0JN#Gw=8^&^8KYgAlRD6Fo z9rp(l5bKUt2N#T{#IYkFjZxdE7)#U>m>pw<@%Yu-2j9_ ze&nugb?)EgbB%1ivfulg^>R5GK70Msbgn2$aigS`kJH`tfi7=L>C zDyil6hy8rq|Lmv#9m}HTzW2R%@Bg7(c$LYQ2c0`2aB+{o>4*2p8NM(w(lOr+E-kR0cC8|5B#;{EP;Ui`~5%_7*A z-fqyjJDNM=iR7Lry)z`(z@w^w$tb|^?b~COXg2AirGR@Z7&!aDV;Hvc@SdU~Cyv+GYdj?We<{%(ge zfCh*&P1DupWjb3l*0Uo!ZnK)_3YZYVRyOP`r=x!7?pS#z?d_CfgKwD0mG-`GZg53! z-@ft5k%$*0lF;)D)#m%}etq}$TXJ*WB0?NM;;X31W807yL`XJ>Q0U8F{Of%X^q+13 zY*o?UfMO&7;A=8$7i+Cdq4JZz{vQs9JrTVF$n)KA|E^GNMo~2CJrV`jrqVc<;WdLI zqkeJ~MWJnOYOM>$HuI$#m|du2#vIE+Ma0D~6hI4F_WgIiwYP>KNKqIqCjD{m!O-Vi zj8~G{WYFe#KAkHqXQOPsswUG-@#(^(Uf4IyoG-nvIS)`L}=k$H5aYC)l0lidUcf#I?6^H3>zA zk|b4cCtD~dQdxx5123+o@Ypd{Nk>n2A7|4stOvnJiLaz^tWm z$01RIgc6PQ0%DMj4u2LR%Hf`*Uco^MAk94N_n-ajZ}x#ND{49mmCEs8(7t;s$5m5b z)|wZXr=+sW`RI7A3-?eiSmrwLaPYu-0l1zRP@!DRGS^t4tdZS1d-j>RUIM5EmJ}?d zo!hsVeU$53HlNBANtN8lm+I3=51i`-5&=hNW$o;lO^kcf5oo9Se1r_@dO7Jo(F_Fw zY_3RFB4O|G2EU|^#qs#vadB(Gr0j^{wr$fT+Y;L{nrF`rhrOE2P$3oqsZ0TiK-aN1 zMyY;MJG}-(A@BtW#iv30hG7`E3&QBxr$3ud1`Z5&v7>*67lfNPe|WlkOEz+)D2)0~ z9}`+8SHOF7NWi8SFTX^g4$Q5HA$CRV`4yGU#s3YiG6~HzR-zP#_muEiInu*`CUZG4 z9X+3|S>|T%d-c<6eKB5}^Q4kHfAM+m{=@#@6F~zqkz~sZ8{%4@70a#ZxSK^*kB+O! zFgif;W!n^uBN|Bz!&80O2WYhD3v0Vp6m1{u3)Olo2GV?~c1qLKd@@L;vfK44gUa9r z81e|^`st{{acD?TGzB{KavD!+imDl_8S=GMM8-MzMJ3n5Y#2qJ>%dIZxm)Vvv$IdS zj~^@bGjHdP=j}|Ql*tuk1rLj2we|k}uN59kE_1)A=dWp+Db-KN+jpPJ7RG~i8Q@si z+OF5jS>x>4ejfl$jUNf7O0gI*t*(Jj#U+X)M19XS^m$Ut;#N2n!y z@p|i=OlN@#jw{KnvC^`|_S2hOwwB5jR6Z zBSL1RDS^ZkY?=t46e{)3-TO=d;5?$NibI;#xEOZtkc0Pthg&bF`@PR0Q_JOwwWr%3 zGPw%cu?f)4@<3lnGa{8srjW5q=L%6oxwd7jW`$~VyIEVNE-OhKa2L~TvEtZPvC>cy z>Gfg)7ziOo?}I&-CwtU4!!RU>Tnu{*eGylZsayfg<9ScuFMUj96_e~{tn{-a;Fc&J;1pAry^N#04vSmWW$h=JVjIHdR3~O z?7=2=%=NNUrm@7UOB6xo#^N=jB(vlG zJ-u$;ei9ZL`-SRQfMor~i9D6?DJ!qF zI37ZrRIW7W+$M?KBbCjY#=6$LSk6b&SvRR7U$n#cUt3HN!-M?+vlFDn_WJ;?%2aMS z9r-?b*!C7cQk9U%)}+np?c7wZxR~_gpnCx&&N7J6F7%-m&!%&wqrQGRY*RF2noCJi zMJbLr{-~SK(yPV9^5zPk13ew07Es%3CzsP<7mW_cWdMFnWuTAnJttqrI+dJk*mmc; ztcG_mxG1~DY3mE9Er^FGQ>c=l4Jgt0i?0`{OkpzYR9hGC-~X5Et6%ZF@Z;P6P|m&b z&;d|3`f?9^J4i3HaX*#Gb1{A~9SNd@ayaWU%R!#SPw;%K2D*K}mLlHIqeCNx+r+@5;54je)`c zayoP!gx?SWcdRfvFf_B)7gR(^k~|tdNK!%+zrqe~JZBv<@V+X#^!T(JieBW`*D2fW@22E2Pn42$% z-y_oCUq5V(CC^Lk{*RXzUnf(!QSWhU0GmS++vhffgWJ*k{_Ny)d>-~eTuE-$%WMI$ zmV}lG_OQmvP{MlzV0~Dv#xFkoMgQ^RF_;>Lh@IHvcgNc~NX~%f6v;}m_waFP44+;7 z6yDT`*u!=^tZD()!~>kHPSLo{t zBckV@`@T<8(PYpml(8j9Ldwn~m`c(eBzbG?_W>1AqN1#3SeX`UCozuifvbxbXra>V zJ$^_eGX~T>Nt&W0z}7$$#se(~*chiTXQx-M`cJo16xB|y2Az9`VR%sv4+jv094DSk zK^Eb8G|RyC?%1uX*A)I>Z7QVjzp$8An&*eTpDR}96ZkHN9e8O-9x3Evf=eF7<32j# zI6xl`*yNB;h`rrNvZ`n)&v7)=H18^n^WNi!a^rlC!!Z|yk)$Z8OtIg&@pn6x<dY%yD?eE8vaaF$Jn*+O|T=;n&mQSZLexG?k? zezTOsi_iY*hd=y7TulbRZdib7aIwX77>_3sncNoqfKu=2Bg@6e85a+wh@xD}{N$&9 zGwj^cG^%?3&W)=YFN)@RAp#3q)tA$_k|c|0nC{tF%-*ckRCdt5t28foUSwEy(t9d5 z&-D3}s2N_bW|*EF_P9pw@UI(7K$C%v<#647`1pOX(%iX7ugpeW&vUbdiYUkNdFI$1 zxvQshCBS109Raq*w0{1~Sj~^M=3)2#u-~tjvln0dVl^LoyIrnW8Fn8Cdkq`MLHmx8 z)r6|0asD=S_-o1cItVECYFG|Ygppx~>Z5F- zqR%H4fR@xs<8+m~i=AUf zQAkmgxd8yga}j+bswPC!Jjd2jxyPF~FNYXPy@HS5oFc+j*5ojd#*M`5FS z&5Lrmar)}|U+~24`Q}gm;CZen$x#^66pa{>i&(!P%H!UXEUQP0hiU16WZB!&QOlpB!1vIvN@r`Wt8(K^R#cg+4$hx_c9ivohtS?{ zQuz|gaO>ry-nedH;b`-MxSWmQQCdwIhN+U?^BQb&YBal-@Q*;0gcPW<_I5EF~$N0lO04#+_tS`>LNTxv*MEr5s4fcEduVpK)Yp(Pm!(gok;hwiV zX?|WkxyV;qVE8g@GM#&D|Ci>)3w$Qm@Vn6zJ)iWGS{8gh%e=q;_Q>s4`0U15RGSyE zSge%4Fjlkv(~T6zS#UKUvTSTQ9hGXQ+s&Gb@q}BI+-~&C^PeC404e2^Y#r7BoU6&x ztJlY2p&&}P_y2{9#pbK7=UVs)g!|=W(5QTJY&z~-I}SVJR!f6n5Yfo}Q#7?QMr6t$ z?4f@JooVOTg=(`@JMmn1)Olc8R?8KGz{}*zTDGVPsRU#uONt6zXIneDGB^5mH{&Jg z_U#|FRE{7%cjNvO@aJb=Phs}Kz-%_^&W4>-rhvsdL1CUf`)mo!K+bh+h;qaI9y%1L zz8Qw$2uyvmUZk_Qv3Ks@xh}-Ua$H%?Ml6z`E0&8@YG=jT3Ckdr>$-M6b2^{&;)!HL zM_7Q&Ml|Gr>>X+P4kjOq<))U-XL2Q$<+i}KaNvIfeO6DVF;qj2M%6@F4T8Yh7+~6X zySS3H%ngwk3fr{~y-6}16Zq|Roy}J3t*f&apOS)>+#h|LEmpSMHAPcwOMjWDmBB0#IY!7LNN^>zCR_bS& zT+#P;$yAQR{z}g0>vwOz*=(2KPxw2AVT+ZPAjOmEys@3j@r1cv-Q4^RN%}&ilsn;p zLRwA+o%Ir8HJr{5d-!Tl#zUgx$YtMdR+B+{hYrI|kYqAm4Z8R5ij@XT-tmOKm`W0! z_75MwFE`E>)3GQb`x*xzWkK{nmWQj62Vbn35JhmAb`E5~N7`n#Q0+Z_w6;l^iA+HQ);0_7{7p642v_>g62ChK2~qvToS6e2$dN0)5>n+5DB zUR>FzoZjq(r7|BfOg|~r%r@)1;&~|3u{hMD4{R~_3au4ja#svKqRKKa%yXx)RCY+7 z2CpS)pgGL)Cw18j{5M%hZ&JjJR4-z*fWpFw?#=nypCDSQpKC9!vx5H1y#9V)mr7|J zVJ<=e`I?h|BcuE32zk__#ong5$=acrq9|dW_QX`0t?wX`*0zNd#WDnDEW=7Ib5Qr; z#T6*wrCn+uAqSmWJ0hz@UoUl!Kq!4U077LQA;5^sWq87x|G!kUEajvM;}#%#^K@wk zetwv#Xz5%ZX-&tC{lg5AH?w5E)<$3%2JK)SemM^pswBZOiUEjmDcb=k8t`w;F29YN z0!0!L>RK9Lblk0$!8RO{5B)n@>)$qlJgK>8Oi$z%jz#g;C6u z3uk_w_;kIQ^t{G^czsl>rVeb&(LSG?xq1wQKtJ?S@5m&kCJfcbI@{pvisI-Bd zATv$*{Xyk~eKpL7JbTXjso-{m*S+?yj8UfF{b1(d2Y8bWH>Q=|Pt2Lq<8lylzma7Z zO!-&*I|l+_trBekVC15Uk_zL-arB>00)+{Ko>yz(%kVjHqniiS7>4jcqb@BeGG30- zby-xXz<3j?RZ}E_(7kCXZ=_i=g>BqpF0Z`k@#Hp_oSL+WInJg0ZkDo{SsNtBRdUhI zb9a*=EQS1d6G5eg{~DYY5(Aii-RyO2f|x%zrJeGJ!or%zz}I{aawmLsolIE3ee z{D(}OqM_vB(D-sn2->E6QNygCY@&f@LsaL#^#EDlV1z|KTwPi}RQ2zyfq9-iELZ@1 zz{VGZ{(>STT1> zD}Cg18d7LxnVo6lKo|GGcBp~y_5&(ZN2H?+Z(VbmJPIA;^lPaM#N3--@{klPK*2|X zLbxGFm_U92UC8sQSA46{+ZX*8weQs9id^+H6$Gy)iG5KOT}OQBp8%B#sy9+HFR)5B zH8YB-W$uj`eil1I4lY_tFypiJjJWS_XnpHZT4-+B8WP=A8Q+3wX5sqQGrg>tj3qYM z(m)!PP^zXQ534!Wo<=!*5OSzZPy%O9`u86++VQ=sJr{`u;xE!9_TSfsrlGMnkIMy? z>l+=f*68WUx{NUS$YT18P7fZ_0Qi*T0Y|z{-H$n9--}I1JWX&Ym*eBHh7^Gf+Ff2O zMG77p+M$gCKe)L!W0q5b!<8JqBF(B=-sI*z8F*dxdp|ecU_}f~8is9^t8<2o8&29a ztn!{ngzF&;Dsu5(A>10|{d#g_=D;^!CBO{wV$bm6=9<`E1aXrHVO<%*h=iQSx0y$7 zj0u%WF3f+~=mq`DcCa&-mJAIFP`?*SGvMFC5h)Sbv9mA~O zE`{c?E*cb>gh3hmZQ8$F$zv`Tr}K)@y&wxh7KyR50VbP=+EwMyB8K2mckLzx<;C zJmrwa_Urgw{08f5xGI4LISh*9ijhXRIP9dGlzZmmSQf?1#x0yc^e-cT#E@|WNUc72 zeV(lNQ$);@eBFoyMLbxTk}+>P3mP&00Txz_-N>JM1<9J~QB@VXH|^9y(?HYrKX;S! zO*{5fmt3Y3O650FnZPFy2*urBjhNMybw6iLn`O%Wrpuc{|pEuiTBlMGTM&`pL8V0!# zEJGVjBYo3&^Ql{}VR?SwJ6JitM)gy^Fm{zf97t9iW;I^CG_u%zcS$=PfMIi=_CB8< z8DV~0kM{KiX&Xr_PBtCbQjQMTRp$$5$9Em@(;Ia-f4~W>%=68(aJ;Z*rNsHVIvLBL z6BCa9r6kYPX6YaPLrbqyF5Z2y2Npu}-`@4@U49+5Ww{HRaN>Wf%P<^7A+ze0S@m+@^1$U7S-t}tBF^FLkb z`@c+XwCzxGK&vFRo&AzWrH^g;)7AE{e1MD+8*F0NllzmFXEqhW(@t#g7~jzcNo@2n z7gJ+A$v}sN+KGz`Pe`xlJUCuxeXMxNrVn8br zVjkjrg2IR{aU=!78ad8jI;^ZA=m%~CPj?t9=FC5jNA6q}hx_3XP41a|ma^dD$cO|c zr({V482X@=B&aanc)wgZj_Qs%lwOC-PKZu%-`UN$ja~NCF-+!XGCYtL?kPh8{mLl2SgYqO^ikw`T(igTVSyt`6^|Lqnv07!#l~u@=`n26e9sfjBtQMau8i2<-l> z`k3?zqFGa1ED^<@KTDm2FGWjerDh;a0VZuJ`O~%j2a6f_Qgy&KNp@&My8EuaU(rh(|h*^+!@dITA;CN z4rAcA@(9QTm60CuD>kf$%mqW530`-*)_T5kowYeMQU15vi9Pp|8txb5ESD-K#`2^V zVG%7&EhVt^Ga>8m+*nf%`ti(rFbVL@7dw3-X~Z!Bc~f3oXE!PDGWKS3?DVkXB>KU# z&t?rL3vdp@psS8a#3?xmK4Or47A|RrAS|Ty-i|wHzcAOU%~uR3V!VG?67DZqZs0C` zt+?t0R{^jPAf&Z7OUs0+;p+yX=Fb!zj1Xd;%mnCUYDf9td7 zY9wo4-I%nvah-_NUSvl%`E#9bCT9mHFf0?>_pxA}Mx{~bVnam$PxY>gQ&=_`&}B`D z`|r13H$P5UJ|~;H{l5SnSy3w!8Zyk=p6hAG5mNhZ=+RU^@pc2? zJrH&OiM#QiM&9s39+Dd0%TSyb__m>lb}!8zt2iP3XgYVDo3cs;3I*GJZ_DfWjn!pN z?dLS}qK8I?S|SvSkImBgx3PDRw~+Rfq9HC{Vyaoe{H%*HTqmTj~%JSLM?wO$5_ut{KNP6{kxjTbOX@+ znlV3rk57yKG!l`bfitG25to?Qw()T^F3y>-Zwd$uH)JjljyLtC8Rd&KGlQ8La-{{J zi*J8ElOSZ`2&{~2oQ8u%S4R|Gzm9H*Z+iF}Dc$wZ2cl6_rH3$M~-!s%#WTlsqR5e_)-4Wx6h1wZ717og(gZJ5X;iJXyWJFp=XBa>PfCM;Wod!gEj`}G z6=Zo`(~I-do(a892GTkdLL4U}VSZ6_PVBE=KT4W(Bu1Z5DYh+ziA?XXd~hvUed1d3 zp;h4G--y!8n&pXWVdBE0?75j&X2_H1PzD`kCJ40ge-mga5I%;Bm$CuTrQ2?o#?T2g zK7Ksc={(;~{r^1Co@&?HHEfDrgD$jmbCnGLO8`Ym;0_rZdUUn|zxU&S-(ru9zad*K z=QQ_OXxhY;ZUkImI=R-4BsmvZyK1{F-*P}CdC!y3uSwi0zURm^Jc{lFS|s@E`xp0O zkgb|M@n0b{&yJxYqUfUU>KF|f&(Ak+uked%tu1UTRc8i5UGE|m<$cd};~s}7Uv)Is z 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

2)l~U?l&kC;@mvm6oRq8;JRwC+nY4PnRcOx23hK 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黢W$WmDa+X2KOn?9vBoZ!CC_ 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

~>SGZVA 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 `KC=;%xYM_i>K}CwOjWwU~g#p2n7)0RV|HG?B)3 zlg<_hC~vNBuo_j=?D*lTRBa9(Zv;Wa5<`+|r>|(5+Cw~dV|m%j!c5YmIBzFpQjr=IW5?>=+cLalXDsUOr@ z$AT<_H+p!4)P5@Sc=Iun!|l|WkLrLsVX>U#gxRRKAjFqN|1MJ~bAmuv(i}leQoJBl z&t4)VNhfUb@yHg-{fA2t_QE1Bh>y3QI9`P68@I|})V-0_bUIUD7?#HNK5zGXu5H?; zKJMRTiy*?K3l$-SwFV+*7eC1Da_<34K&wR&;qe$N@i}20cEXz2So-bAk zm4@S5JTH}MO+a*lV7-{anoMq$K>#%BsCOI3@v48HFIKDPul53{Os)hUi|;L`BL$Fa zJC(_A*NcN!-%<&hk(7r&{2iO*lQ3u@Es5i3CYNAXDv^leUA|J!Nw zq9|(caOrNKly+S^LD5*O$;y5jc=!F^?rBlwTD#CbVpwLgno}%09d>bTP9ze;?p3AM z#QQs?>YGiHO^*AwgrXqqTZa3vuaE6dY-lUbb9?ufq33q*E*`GlITl(ti1cL0uVxdxJ!9Ug*EG(kQ;695gl@3oz z6jd5+HIqMk0Vxuj~ z875z@{rO-2M{FM2#}NOJT0P72o@4LXUJxuJ-I!w8r0+VT?hV1!QPsv_5cnxIoyis9 z=ur`ccN~l3`Nx|N*<2C&FhNXb3xkKxx1WBrjIC`U9!evN`9dZ3gY{xUQL$?S8Dx{Rr0eWtq{r*1R#)=G^D(e;@a4FtdWWdP_)oDEX#tnp>GEdm%i^- z>g^y52ang5q3=umf+!6iuc_S*O3O?>3yz8fE@w<_mUD(>ICNF%LZ!~};&wfcLP+3o z59yq27L%uMe);LAf2QKNd2p(4md8)On2q}^o2;~s7SqvcIa@8pi|LRPC7PyJv+;I~ z5U`}As?9^tIt`tLMWHzA-q48zX`A79MRYj`qVPQAj>T%DbMjQ*EdB-Nm>}XgbiDNK z8cIJwnvHv$C~oFsCXon(z%sXC6zba*O(!rQw9Osf^e_aSzxwv-!}lC7eEjiu`Ep%K zsg>qoxzSNN zI_llx^#caHL-d4T_Enn))z$&_bp88Ft5m`!EVmo_*OqeZE?Z!NS|^5^Mrpm&Md|3~EQoN;=vFg>sD(1p+@^qQ6B` zu5ID>t8b_TWD(o-qTV^NEu9ktEXrM%rm1lsshdjkFiy~$)oj?kftx7^7Lz^#bGgEN zI$X^sMC*o&G*n{q5mFzXef;E2`vfdYk`^&B_sZp&WU^4HyN;D96u0YT2<;5U)%*Ap zNl#6Kz_)aC)~k&JfftsOLFecxzzZ0PI00FJY}X6K09FgnvjgATOJU1|Z%8ND#=)sX z9OwHh3W!OBd=w zEmdaYK8VzaK_*d1jiFuwP>7Io;I`xV#k5Z|^yT|M5R?<6Z59~W++IXsFnGK!*W2sW z3~j3rnm>KBP}IzeZ~n}6ti@!oT8!aA8}%WfOkvUw8B?J&9X;|QWZP0owM|{$EYi8s zhd=&YO~qT3b;K zU6WI3;QT!o6v$kWChr1$yOPy(wRyk`GB}t})X!N05h8UpiRaNKlvC;E5nf>>vVJ66 zFH{J2gbUX^elqFbrL%FaIq@dkl=$mQ(zS22mlgY-xS+;eA#G{2z_ra9@+X&s(ZG?gXBs~xqoO#R~Le-1pa-ae@`4$(Q0Q|PythMLLA*+MRl0fA*` zNJr4fLZAwgOzt@dG+md)QbY2tarp*v1aJ& z?cMceIT0m!GVFrtwwyxta``UW?aqGvSDs^|B#;A7CHp62@LGc|!xacZXEnzu{PuVM zIdC29uH!g`j{5?o6egjdOAU%{7zL?p&i6b&^!4@3buAFg#{KOI&pJ4o5=^aitgYuj zi{#3wd}-9Z$(}slEGB5i%PA$DSF6ojsgf(z41KejPeS}4*qOkl9AXx1XyABOn}>yR zJy)nq2M^nutIEj>U*C!{LPyh47t9ixZg$QDNx^8()Rwbx7=-obU!nX;(|cw>u2fAG zE6drC<^_gjhuvFkJ>T~sNdXt@J96}>`g+yuob|3hVoS!dOoBDH8^^_Kh+)|T zgQZ9R{xgju=mDazt(K&y&7*S{TTS?69oxi9fy5;Who`P>O@~G0E}L`P%2dFyIpwx@*9!^Psh7xF&T2A$U|9(7dkOERuQGCG`HHySd6!ug(RmY zx1TnPX(GWEDvj35uXa%+NJ{PWg}z?)Km0L@0^8Jkw->s$f{iXyB)N15k2gyIDlzFm zEn6fZRhzEA{`JA}b3_F^Kb(E3#Z`o%p^3 zLz02l{Jzu@g`sI6{n< zr27w7&4VW>kLOF1!NY9SL(I9+ab26hF(4 z33h6IHJh`{ZMoj*-F?m%t4cb{AmO8>vxVEwKcQ<_Yb~ckAb0W@b?-+SB)lH;g1p@< zGI^v{1X0n}^VZ?{ir*iUW%!mAmDc^ zr%~dOuppBtpHTclIH07 zdN~m!W!$@c{foaa4UGWxVajxElaSz{qYnZP2e?FHyP0RQ=o=t&nMx13H#>|LP@Iq? z+0?g&4sQC{i?11mT`y<2JkU(J-l1q}F&XS5^^RqBPM(c=cUYlXW}(_dlQM)dbKJi_ zI)9Z&FvV(p(7mN;N?$LLZ}vSoopCIySgv0D^!ul8ezBTQ5)7Np6&BMGp-OK{wHEn3 z1e^ey7_OANh>BxDR%}Bn)!XQWBQ;ULJw%XIlp2?gV=)YCY&Xrr^YvmZ@RFR)B9%hs zQV1qhnt1975-HMc83q-%&2pN_mrTqrd4zq}bKBG<1+69@k(e9&P!zr?DK&@xL;5;b zsNljzC@UPtlnorh?Nu}0GFii94JdUZK zzWc9*O08IJZC7(mTa;@pnr19xV;Z`mron>H!1^%tZHiFLlf>yJf}xJP4WUE>=^Of9 zzS6kAe0Tox>*?^(GBi}uT>{dEGB&AgR@Fv3$%|2hJfdlAdUu~8)6fu(A~y(wPSB(h zUr^8C~kR_)d91|h!LayWf>fPCkujmA0Y*v|K_>Q3#ll<(2E$vr&(zWK)?!(a@0fpAH`g16yM`sB=h;A2%7qk#S59 zZ$JOoI()*gtRPAlfhekJfNrjDSDV#5moG;axOZu3t2tf|B}_5YY)+Cex+YAsrHGx+e7zWh5Eq5JFw7P!=618srrVam zFsx;Qp<%&r*`}am9-?fQfz4phy#arWVRj(~G>&6Q@IN4c&hZF`xPS-PN-CG+IFfV{ zwi_6o_KO`HiSk8&FECD8C0Hy8SMzba+Z~+0=s#QmqL9wwo0uuAm(xtPFnGLGQt9U5 z8MUK$9>IX=sHbN0rUr5p9S z(jl$}o(shXXgpRrgP8c9Ngw+D`OB|AzyDsq+msU}1qKySTrH=LWu-DXDWwiR{X{W| z1Tn9r)XZ$uJAMB3Y|^6;mxwEk12V$@cy#uPNif^Zay=i@iG=UDos(w|AK#`5WghnT zVzh&qc6jr#*gn?QizJ&QHc)eEj6~{pI`p;gY5k zoFG6C!gA$C2k(e5;5mE}(%Is2I^adQ+C21KhX=DR^>79K{Jxa34^>y2hdeKAmb1?3 zv*m1zk(Oig0Hfi#?b_ycvpjzCX4Jo{)H}mR=z(3wT#S0pzWVKaGT4_{3C23EwLm%o z_7S=Hg{y0+0>};SVp2MOk|j4ril*W?Dpi~P`>TEaJCiHAwk=2!=y20frgI_)5_vr` zu5F=5ZkaqR@@e1q>h0tH{iT}8r!u)cWRoO47;+r%5gN>N+)b%D zW3wnWI)paiCdqWqu}$3QSafv&3r4!EZftR$<~U)`jR`!TqGF;VMVS);c}am*jEb{( zvZea>m+2g4(!Kl7Ngk->`oYO&Fxzc0iT7! z5`ceC5nPPk{mpSzOFYFJMeGf$u7iq(g!_Xp=M zUE4DBb>rZSisQlKb&Muw-ZqR{>(FuRQSUA=^mMseX&l~udYdbfe7kMgWJcgR=m{_h zw$f-@NSFf@!SSNLSyo$zKKOX~QTJBO0zj{*InYqn3uyIRSJxJTl$!SL#8jFEfDWb? zKwtsRQasmX%VZKv6i0*m&(-E(>*z_P*0N0_MhI`#z5U=g zW*Fd2lP%Rg|NNbFKbSBI|-gA~By13YErUI#ARs4n4fUaiBUTIRP_B z5>b$3<^JkjkvQ9XcbDg{z9rUZ>gLmrG@Ymd6&$S>h%{`L(8qR?lJCXA2{5}ojL^e8K^hrav$-) zaxx?g`>nQFOu(YSZkHFt{f8`(piiE^x&HWevz$+d-7&d&<1aYw-Cw@nGhs=34--&M z6!i^emZF^MoIGnDo)t>DmJ6Xw0hh59uV()|krI5q{VxBKn5g`?2SysIZN4>l0=wTm`ir|tJ1 ziQ}k!^khEnXY<8<-aYVLZH4(Ud27PpSg5puAfRE--BAfp+0d^ATB>k=^>IEP#56s8 zyiVtfb2Q1Y9@+Qg=A)jaKc^)a)epg2g9{HM4|2F1b=b#-SY2On0z z1M|M9vT~(EbcJ4uT&J`By^8kOA+&t6Jz@>}ihS;BSYS8XtymxciioQ??Okj3gWKir zTle#A5)Aqk5|W6aG;Dgwgg5(!;cb+{a*5mTWTW+bWA~1YozL1BNow-xA1UJf(6-D? zHRpkh^8UZAxX87qBEKoThQe%qdpTr@9!oNR@t zw%Mz^gqLZAk^0RU$A^m!`G=GBaoPcIbn*q@H5VduIQ0Nu7;`2|vD7jGO122%>LQ!azFKM3!A)o`h#HCb{Wa)c*DK{fAr@QfOG=Ljd8ce-0YV3`w$AvIZJUk*1AY}vJ4ssF5uj1&JmoyzfGYs zz)|5=ZEDu@X_AL<3ZeXZZHqw%(#D*~K`gyo64K^HYyWX%0X~oNMF4q(g4}2Oj8^`X z(o^FXWF=G89O*wjR40IlK{;?_5x@H+7PvlOk-%s!di|6eLB z21~vw4zvV0v&ptvWJZm$JQAIfFh{Ff`wp$~e`mkO_7CET;V_6@>9cm^V54WYjIqv& zqMMGqmxR@qLieQth>5e;)%YT6E==*LVi|v8b9Q8V{2TNqqeBFLPwGVV{@B|8(rz6k zy29o-kXBW>tG4WPCVg>!yQiT>Xs)cAsS@7r$$FmgV?jAl7NVGS6G-uwR)=y#TyXtN z;;l{R^VGkEu16#jHJg77S2sggEyS0)D%rs7a(+s+x9)cj1}BeR_r7O`|DLbFK94OY z0YYF&rP<7uXrSpb^#rod7rly74eihtqr2jbk0=WI(I-3uGotA+XQqvgwnIU0*ch(D zYw~%%x&44Zeg$#ui9~0J&IQ09BbCPM5c02Z2Ppv+rgg)~Eca&55BodY2_kaFcM8JB zBs~z3za=TzN7+7NWj^)YyaS)UvrYYnePafge*#0yBU?sgwj%PAghykB?E;c@xr6lk zlSbE6Te+FV()zp~J@`kes^tbQ z@TT`K56p8Rr|PD&e>H!kr* z@RDoPqi||!9?7^(=DNM2#Qu3OHbJI(>u?yJjg8=&xA9}xF; zc)dlzY>5AiDR4FJ)&T&b;0vthcn8QDl`PRWzelHCn@x4RHKZWBfClo`qqdJ61!M}H zN`6wrKPKi?5k}ULOR1b3mR_`Qh%=i99p%Wj$`cw)gg`W2la4F*j9zapKDZ+CU&`G= z74At~458CQdE0C#T#!H;o%n*uPaUDI z26+Jfea?yShep7_j&H&L(J?8eeh z0Dsf_wC!z0F?6DHS4`={C{4!HsnkY5yG$iq45E~(2v-ht^+jQS@o^9Sl87wDi|vB0 zug3W|*m39R_&#Tc0wNNhx{7Che$asRe>SRJJzUc@>KbyWi(6+f|4mQ+4AvFovCQa{ zx|T}S_!SBS5WZD+CVd(lh;irgzSLO})^nynUra`J5^2!;*Gr1kW1iudp#&lVaU+ec zLb5t>gsbZJ)LNb1<9c0M8wh{YF*x1s&KYr`C#vN;VUkxQu4dDSNmFstm`^N{(j0H& ze0)#Y>1D~WH@*F5--C608X)9QxhQh8|_$2g*>C;EIt*k_Gj zhq-9bHS<3YNT`3`cVTiTJT|s}Pos8^LHkB*VZ8>dXOf1{Ke=>Rc~Wz*)&;1su9 zFFatRxe%$G@}gYJli*(!r;@e7GVwbDJ{Ry09U2>4XyY{3OF1;2toRab7EXRgX`XV* zS=LS9ap1O&$5oU0jgYxyiClarF0S?MRy`p$X0`8HS%21^K!1FwO?S5ADW$wA9Lz;# za&5S&@eR%jU}=@)8}RiwiN&~B8|r=P^hWl{zf2XUBOMIEuslGyg>|sqJT1_}g2bn67F}l&hsTGv9O3LK>{;}& z{c-8%!03cKI6@JP&S+TOD~S747dTyDoc8uIky)=Xx+H}zUP9jWdN(%I)J^;C*TeqI z$PF`$w4is0k+!ZZJQyO&gF&jP8Z552ua2Gu7&BwsKZk0J$1&;Yj00gjy3fBT~^k3+tg ze^%hf60F92zypg_D?^HKCcE{NI_>`OHKa?FiiIX|qPBlB7(+VJRVou1yC-ZchS7uS zYxQP-NjmW~v9=RBS5J9c5F5EF+;bxL5&n4EcKdkxxEss<;KXX5$u0bTQm6HmIUw4^ zu+SmLntpT<(~S@FU%!ma$YR!ar$6VJXPWc#ZmU*E|CWc!qcdlUQ9Z7Vw`IL0+|lXj zB)8p47XRD#6xb5CUpJ3m}O{S&Zl%vs}BRCGX(8BdeRu zGr^B!$Hq!Cq`q?$dDSJOM$J-ybrP@iQPxiuWhh#uL>45}o8`6!D2hjCboq(bXVkVI z0Wf(%wm}LWY---Y(vt{w?npw!a%yd+abxDP98@hI~bHhyINfMd~*ZFbQ^?c&@nEjqz zVzsptfn~%M4R>h9Ye$%|4B65wGCc--&npmTQ0-bpMB<>pb@Dj2ryK5)NaD`pQOOEF z|BCp33&KmZh@$QFH>R-6QwT$mCj-z3Hn8zvn_LqEyG>k~M$+3T#`k*Ckrt!GodE!x z=nc4_pOXQg2`>RJWJ$m?(8!ZcbcUma3I%Ame9_2C2e%fmf7eLM9CL()9drCsY1 zbOcM7Py2l;F?d|$=L0(GR(wGizL;L4KkVEt-PuWu`_t)@h=yF{GUd0~!hbp*7OPES zI!q%5?c6LZWUs4#BeEyM-I;nbJvoITuZ&)hK85xt>fVcyw>l}LkzO)#;W{;Q6d!^( z2A7=x#OG=Q?d+Rl866_ zCkB7?AL_2qC7g^dHBVbay+rR>m3z7MIEWnVS^{)J;O-tXGXYfj=!#}q2ust;3$4E5 zbHP$urrC=SWPTM^30XUV9&=U5HcXbnaS&@sQ)7P;X*qAj2~fTU9z^dpHAKT-((1S~Tfm&Q zMQ_}d?A(SB?K8xB=`6l@tqqAYGdqfSCY5~Dfh<;YB?;f1iR`!pZ`J<_z3eCubo8Y1 zcC{~x2fZgjy>4j0f4=eE%u-tk8k4lKs&dwbEO8vQZ6V8=8jmY++_Oq_bqmKc>B#2d z{rd8B&ozplU?TGI-B!Kx!f;g0&du-H=L_2q>B!Xx1u#nbH2(E0LC#j-c<=9U>SLBR z$k_l}Xd8o6ms49)4wi*cOqfpfQ`wA@7I>p7IT27b>uo-f(y`efW6(hd=9IKp)$eG| z_wBWDaA`Qo32%dcnqVn}M#tqHFO!did##a`+{9QJbJ7*pg_U%x@$mWGF}6?-Y2F2~ zwU2$(KI=KUc{zEYk3*Grd<96n8vw#IIxfMv)5bPdP3zCp@UI^_b6K6hb;+y#@4_!D zzGwi|*uy9_!<15k^<4^BBIL%B5rzg-$J+pWp%)~Av8#D@RbqR;h=T@2UWa`e;K zlK1ehdt)VHxliY*l{KDMuLnc(LJf!(meQ0J#IQqKnnbs{@rd5g56rgcx#WD@<)5yOBf} zy+$or16!gLuzE|4@^oO}crjI;j*?HKIW7sQG>@cwUECEYu5@VhY4(gxH*NVAlAAVm zwqasLl}(?3`;{X43r*h^G}1tHjnhkkG$UTl7iO$JHz!@!{0BE}7glG+lP1!LE%SWc zLJpiSp&zdwJU}*kuT9Y1{pZb+5pPi}AvSifgVV`7wu6-QTA%xs`)KUZ5Y$3(G~dYqsi1mZU{Vv}$RgPmcLI z7w9GJ@@y;#=IJj`rkgFDp#W(0^tgf0#B;FBW#17uJnC+M^nZEdp%^30;L@87k+vV@UFoeiZ_M7>Jblk zd+i+f>{USbP|nycN>)+P67i^Ke_~6Q3yeGRLhi$y$7@BL+gHYtEJE$k>2PYzKv5ob zA_AeLSI`)?Pz={qRe!*I`T3vk{Xo{Ql-;MknPijKihxb^GF&=&5N9w+RuKz)EY|kL z>b?Ojb3=5NfsLGUD})2GZ1Q->!_^~p?yg+s0^V^?mNB0SV_dk;UzO|ZuN$!`#XJ*% z?XK$WS(0VonEI*I(~as=v5D{l)?IaIcHSVn1>8bC5u-|Lv%1-1mjv93vXF`MXi^kC zLl3GU>37bvrkKe6*$moc5T#9CK6A}(Y4o-AJo|t7BK~kFwrjMFN+5$`G8xiu5!20n z7tQK%@~yjyu&yRADH$~f#3e=lnMklNS)GJs$mYq^$B$!c#?&Jzc0LYd@qZPMB@F|N zW;0?W{`O;&;MT{ZY-QixIYFQ|L`mu5cIR8o+t&7)dK!7zkB3GA8=YL4Urd+wu+X;- z!XqOTNh7e}Myw;ea9tULYGF>A8=kfL{O1??MNMl(lj3ovYHx>xN(@xXs&$;FK{cj#iZGd3|}8b{D9TXT+;_#JhMkueFh4E;7Uu?*;9^k1RxXz3n)JiV<12KPRiEvQu#u4U7+Xdog z$(Wjo19nvWGjvB;^DQyIX7B8gsJ_H zl*>pm9QmW6V+%#AT7)05KW`i2#*+EeNA{kdNz#EM?-U3x&Vh04jYu_AP-O%N=DMvNb20`EGOorlSEfhFk$J%uq z;J(o;%-3Iy%rMjDnFZyN3$KwOoV8W`1QDW_YyeaE=f@pEab^3Lqaj3O0XZs-Dh^aA zd)TW?^4-I+5;sxm!xUsH%_Q!qF(8C*-gjQ&w!p(b08>33qjFs1#_ry{I!dmTh4A{k zMJuk1)c(SjW!?nNB0VfIyT|<0Pv?rE=8{r*jL@BCfSH3iYa}q(me|87q!L@VVkIkR zf7HO7X=6s%Z@psfj%;FN#iY=wr2$+5qxzBScK6q9 zdaBq(@!<_o=4L&pte_H2KoU`yK!@91O!7cd!b5y-_YlAT+*4X%_Kmp{!T?%rlg&FI zy_i(EDv-0SPl3$>{$c6|A|M$?)@m1WumBUltu2*(#H7&$o}oI=Mq@<8grDV!9tr^UN=4^mDq<>>@N&5E>W~BZyQu$Cc8pQm_@Z9E7yBen&`OOld z_}wY3Pagc~W|;L$2D}8+FrVX55n=w$TVF=r&-^odFsnB13yta*i0_xyscMREj~U+= z%~R8#7>bn6UNn-iNEBX9QJ`=jsDPkOw~+HT&^|eu3LM3PE!#A0v1I0sHXS zTO^`So_;%5eVUayh`75)816*=Qb7{(XMZa`Ss+52Ff*r!nct) zsD;UCqpGYwKZ)S3m+7>?{>Jgx31U9T2{_`L|E9tl1A9AS5FIBeCeulsxcKP0xk znwhP)X1~x4W{KPszOVT>t+@~o02NeS66x@%%ZTC?!*<9o#HYG-*sKSNR04s@fofNi zw;F08466^DqRBBG^}4v+5OQf- z8}7*N2f8tZO>*u)TOOr151OlCymgmKqe{!v<+0+XVFj&_xN!x^=mJWv6G5GGrw)H) zij;D<4N0JuQ`5>s6|@pKbS&0IXUexd0ZLf;^*| z3yl_WBtWE)3~{>p{m$=_Un!h$=uh6HOQi{0X$d}J!#&ZcBPUC-EWlLp>sM>lvEH&V zw;&9YvsPAD$m$}yAmA{@bC+n`G1vd|(qxF&W6vOCKG9`{iF_`Ys)P3^rHGkiK^QbA zDr%KKY<0i6i+}y;DG#EjS(L<-usj6x)m6}QG?1XOC6kH<>U08mISN6RYQ%hPj_lZ`gPSjM|nwWA5Ef%lvFt#wx1SYO9mwvBwUPK0E zkAOviFi(24=aXZl&V_xu5{MX?xZ09xiqDrV`+i}Vr;(B}csQTt_I%49h~TF{!J2fW z)#_ZAZ@e;Z;|&OSQx58~HLcA58hSP>w5C@Q!}DhEkrBOeOEO4Rz8I`^S(JvH*brm& z&R;#bwpBDnZ?7@M)5na8da@GS5(@+gQPRp<#Km>AA%S4DmuzM!bqhKA*f`{*S#d~% zLe==pZ5Jky7nX%|M*kWKc(y-peu61yM=pN72gL}LNf>xE`Ww9Yzjs^y0r-yZAjNK^i3nAr5qRUNtpAUgFU$eX-sb@M;D=F zg5b5tGwHW?g;h?m#C2aE6N|Eb~2b$U1|b0z?8pd{s-E8Cv?v8#n8@ zJ34Ulal|?yPeNBX25KQ4bt`A@vX=>n7VR$G-mTX*`XPkZ@e@55Xs`amK$0*jCQxmQ zH`nI_yZGI$KdgbRbbdi|Xdj(BVuTp7Q9mG0{; zQEl!VXlC(@Toa>&XT)JZ#-}3#9V*}L`gF9z7WlR67+A!>Ac}B1pkzeA^YDFmI1&?+ zwlRsO*lH}_M{XDryUp%`5*TO_msis9n^U@q<_6)G_1SD7ra7{pB-k-u4FrH&OyWXg zC1Nl+zQ)wT5qj`v)2h)$1sOF0DhxbAZDa@Kj&8idAO!u&&k={-yDti7N7kdW%f-xL zh;Ae@945gw6#HL&U?f)rl!`0Oh492;)5fYbR0&0EGg*L6e?w46UcHtA+Y{7j3o<*t z!1kX#11La-Dl60K^lbEKU!MUUq#&=0Bo`mcQ9fuz;8V8C{!Qktem9Sy7~{Z^$>a4D zWoU7hPaSYktK%qel;4T(o>y_+77hkALx9;z=`=$EE0eAwY&&TK>IBT^+6* zH$Hczh&Icv6@0$Sir(RRfkr;VzN8xCE&!f^J_5KUzXuTIRrBFBm0OV zJ~7owGlNtLy6ttdMw*6b#@;D7t)AJtGf%GL5Q~sWcUkaD=`W;$0mmO}hYgBZMbjQ2 z&h#}uiIO6nuL)Q~2ylve@s0&qLfP`g@j86k!~3#TpwezavR6hrT7F8JUn>khjjrn$ zRk5%qAon6yV&t)-$v#6k6#Ys-SxtV`fEOc}d}bNgQe4|>m2rxTv&u((9q=v{Sq(FY z&inF(X#@fPiqH%ZTR1R{F>&xuw5eu;%N9Dc8--*uyzu5kao-HCexW0b(ro?H86()b zUfOQrpYHfjUIv>y=>2GDYG6hAgNbU}e4_Tp5Kdu&e>Jc5aXLi~Oe`do1V{*k-bF#u z0RIKa`@u&~?bw)!zrIM7Ne=VpZ73Zfq}9yf42AZWEjKXeuN7?E>70%-yWwT=7n@C=qz@s#*mEgBwJJ( zm8!_Z>$MudSwPDTfBnmOQ>5sIpw|`SyA$yS8;CPhfub;i%}T?7p7Xyf>)78uR6SHQ zo^X69Ib)??tRJT; z6{--Ldy&7IB6ltn;;)TfCmyG|O^Fbq{slkE>LdntpxbRvPC>bTc*b0cC)99ySD5I+ z6%0ad4J0&puSYjjAQeB!^ z3N&>N6DU0;b`j$1_Ec|b`@KQbvEV#960hO1(Y4WqLY9s<5fyD*@Ah2a?t+kHf-B>oDLo{A=F~|X#vnL-DiIcIv@)t>G|GNBZE-XKRpknptB&) zQ-woMe=oHmPOwmBSop7v<~T!ue%_uN-n&}UPS@`>Ahb zdBabT+52PSA1(Y>VN zP!E6}P<$qS%V+0u)s0bEL{dyt5qEbDfNro>Z!52zZ}|GQKlLLG@6M)$T0wZco3j*w zCxMT3>WWz4;N-&MKZy>)qVW=2>l2txid;dWoEH&xXMfSeI$dTl%Ac_8mc1V1JNYAd+;vx@CzvzL@>cE?r;4;J^ZZRLd%~PIFJ|sS6(y0YdhbXZ508suOj;Nnxr)~a0g#fz zEH+r~sUkw%-HHDOj{U7gkhGKwm6T15Go zsK2KdH$VubFvU(fDE@*>JJiwE@#ePb2cKW#^C~u$=)X&SBc3Ebzf4_(im~YYi2i81 zvss{kj1Wl5WVYi|J^1n!+VUre7=MsYqXKUb-~f)rYP{I|!9p}JFBb<^m?!%0ly!k^ zha)HYw-?N+sf2h|c?Bkpz#>aXF464eQHwm5<1@;Cxioa}K2#%Sk*1WHS3XVayyCc4 zk4jZ;-WwQVl!+4L^hHLx+E2uDjn`J90KD$*#ej71%Rd*SN`=)+Cq z$Pzi!Bf}H^{$FU8x4*6H{WNpo0=fgbnI0itNWWJnyKZ{3$^EL%;Pj|8mI*Q)v^RfC z9Q;u$YnC_=Qz&!+6;|Rv=_wE!`i-Oy*sva5z`KTnr+OF{{_8u5Zc+J3T9=?wnL3Vz zw0C@VK+;6e|6O)2DQyg!e(Zb=1{xJ7%nR5+>^-SqOGFYW!SRddL-ioU37kW~S%J}~ zn#x!;(g5XPFN~{M2LyOsqk`BqjlBH?&X>gI3mI9t841 z7_#3ajIxZ847B`<66w{rMxQpf0Ky3$ctG~r-JUrj4wMGSX1NXV@RVC=o(vF$I8n!) z1`svlldhg#y1rWkC&pH7&=WKhxi80`w%#(2 zSMG{QK9*Sgy~tCKEOGqT5HqEKE5SW(jY{K)BYzC`-hSU$D71X?$=Ul*69lH(bhC|? zeAVX)_k+lDq*bC`t{DkNJitf}eWAPsqLoG^WWv$ckkzg}e59_XfQ?SH4=AS@x(>~mHv=5g%bgdJ?ViH!Fq&%&~H8NtAW_0-Qahc73J*;vA z(|aLM(i9DBu*84PXjPQCekNoa)7%$Qr-43k0A zJa7|E4-WgrRz-dX_bA&fLNI~dpN?%q9nVJ?Wx}Gebwc3 z<>CYNYlHXERo7c(+{k&Zy>lQe!$2cwDDB>MDCd{rXw;WihSCNR5%u)B2DgXs0a@b6 z9{A*6yG%GUWUlG|CH%z+^70OnYZ&=4fgmcVUzP<32+1SI5>7HnySG9OD3XK^SCVS= z6u8S%(}Fh({T@8v&eWDC)vJuF_P;6!33DMsU2}4bkpA2iHx$6|?BE3jL592;D+ zNWs=;1E`MU*_ENgu3Ex)xujz_ZExEw5q8!Vb#%RBMjbML5q_~ zHyFRQI6@AQ`$iDo<)EZ`u3s+RVeP_Y)+oi1%plHN$;{O5QaF)np;69goe8N+-jYZ|2y9D@f&`x57XWdN8w&!qpluBoxWJ zii;N$Jg*K&0x=4UQrFK0oFAJb-TcMTyoA2MZ5?mX!4cG!=T>L$#}KO;jPhY;fMw2(Ktmq{^`_`iAdXZ@0Ah!CDLwQT>nJc-H;_u6}d-swYHdl9+gH5 z^eMYTG4Ko%$Jiozp>=|^Qi6<;rE1cE0ZccFo=dGB5@Rsd9#y(tyOAbtG{|_Pq&OHayzp~Y2Dc*N>xx-~B{P}vtg zodesE;Vw2_;6`@ApSZ+OG|}}wb{8t>SrtE$h?KZ&#OEl~7!<*VY(P{eC%;hva5JAu z+9GKexU{%Z%V#NQ0m(|g&r0%7PW=)c{dVz(SW_N_{sC;ErU`@p&}UBtezq%4IufR( z^8db3T^OjVSm)JdE|#JD@=uU_q2j^=$S;pR!9P~MgKC#4TrSZRyB-s(Ds@)=C6*x> z1TsKFkKVETnU8b`R6uT90AOqb5-^dEF}Q{ym;p4LaV$Ufek^cCRc6RI5gw2SHM2Lk z)T(5ITkqy;Vcgt204M?6r_D(O8T3S>mL3W%rLC~JxaLpgSs<9tq(i@Rysl^5J}T9$ zTao}087eNaa*~QwV3CJ1mrJFNo#47RMXUceMSrPq=(9zf(YjzOV^(~jP-0cOe!kPq zD?0rORvQ&`$_a?g3R{$XqsL;$`z#N%vR6}|B3x2z*iW_qiP6V!cf-YwSgcn#UF{5k z51`Yg-G6x;>d-zjAL&@hd%iYmMRoh8Q#x4pZ?EkFn=_p;0exXSF@=KQ@!gZvk}xB` zy4s8e0J;Cm)u16k8jzWBs!*d6B)Rin`3gPpJ`OYw%AEgz8eJZbhBgYPpK$d* z?yuJ_oWxBe03u=E-HUe%@fTYQ=?E)rKJh6U@&m*Wh)4UoJ#cp6`)p=?*!Kq_`Bx01 zM%RiDc(1%HQY)imU^ie7T}kV)KnR4fglXm*=e&n+R1R*RO8i2#GdeNETGT)knEzZm z45Zv@bnNVsop^?8yR~lk?b0PW)#~Mq>(i2~GYub#oL+B_ceFnl@=Fe05Mmn9CayD3 z9eLLRsj!i9eHNSR^Xp=jMwgeT;$JWB`pW=_`@OF)Zyx~nl2);%1?GIiPF`QzdWu{s zp&luv7|sf^+7Z$oQ%U6)SbSb~A_`9UL#ZXtk}~j^73msbEUE15em~6y;U-xJDgf(# zkH#mjjh$M(bp-+R-!5F|_P2n>oOXqYV{hW%&TitTOcM{clVis*r}8LSj=`%s{f)-98aRF6x<4tv%nXt2@hKi7Qyvq9>P|o zg9OT?8PI%{;qwB>b8yU^A`**i|IVmJu6QbDf2C8ZTUnvP3TbZ?)r&8%@#^)PTXw|3 zTdQbKU~%aE-FeroUDafiuv4^n03ba2K{@$g#{dS z#`Nb~=1yoinpD+`Z=vrepRB6zxIf=7T#4M7L}8m82q$a>5*4zKmdi9jq}M}vwWPy2 zS&=F-EB`$7WJ;IzY}9Dxt{mk|ZMHj=*n{8K3X3ZfjON>>9~V(HQ9i3PBC0^F51-Ov5#L7@n9teHV_A6%xxMM zCvfJE@7FXPG0Y1)woSk_Mz`xtw{_WuFjH&Lm8~6@qHvk7e^mxn0|=1@;M=7)v-JCW zCebMg3uE)2x7Y- zsg3Q9sNG&&zRm%vP-lpN&Hv>SnUs|B&uF7}-ZG1O(ik#!g>Db{fkZ|-RzyEOtNPWi zT9u0wvH~_0h?=>5La}UP5=8GQYv(xK5oxD@1{t`1>-asAePNoco8m?BUZC(k0NP%d z*-jis+Cz#(eM~r6h09g~>-t}WJ_Eg(b0Y0Zc4Tt05~Sxx)+@Ng-8ZHNr7F?Ih+F}= zq7aDm^`wp&($5X2>80t2j8#0xKWZxYy_jKYC1&=hsr-7>l)N>6?(4Y?{gKj5p+b`A zliHea6Zgr&U``Ta=s%@<`K5lROIPXG;Z+Zm*<==(fmKf^zaN=7`zCua=k4tNYy}ps z2S!y!m6dil$mzc!aky-U3N{U6geZ#A#BLXC19hERJ-H15Kf)(*FU9CIw55Kgy6;ru z&ZI2I%JQU-X;1}ur718JzZH;@x4^mL-){g1#kYfOnJ9(L?`gRK7yKj1WkD||a-9h| z%Ic}kcD%ydJkTi)UI^Z4MZZE7f&G~UHO}9ibss+c)uuBo;zLw9Xp``R&mU4)*7C>) z%W(Ohp}+&b*hj9iH{LomzkK$=4N2cK5jdu@sDQ#@C*5K|(&pETo1Y{sqU3EP#aCBA z2Q2hqC@`Nte(3ovcVWuR&3p1{urFp^<#_`xLJM30J>yWOVWGb)%?ZQ9x8GkI0M54t z$%p$rq1WZnBP()yK6N!s1l?R35Gu%q+P(};-9^NX0B`txxD{vxVqm>SuDEQr?wqe# z35Z~`UCJbyRr>sXgD?QqGMynhwQs>zC;`55#prEl`38^fK~PDbsuBOyLF6;+1JcF^ z+cdTFtFjC<9c9h9%b%>c`e`edQ^3SV5uP7Ie*coo@+jDmjnSe1ZY|M6H*1-(^_O^Y zLA|FcOaeoejgQL*Y48L#eW&$H)eJw+jnBfW?fsWxnf!b^oRR~@XCRThuP(YmrYeWn zdpAUqNApLz{kLI!812_NT+t$w95y=~seD&(4|0|wZx%E6a_+?#^&7zCuTEx`vSga($8&jG$PAukC|dR1oV@Rzy>r$ zl56#J)tGDhD;w>S4Pe!sI>^BgOSF{Q0Gl;hE3=Cx5%MTpfF$PfI=fgkOgAt31YPv6 zWcv8@W$1D5aeQnb8j_3sH%hLGgUH24P8bT4Lew0-HYs75-&e)b_4dwawTnPNZ$rN$ z84HH4m2w&vC_+(v_M|Hk=z8&?(x+4ZX84;&tI&bv`1=YXWfJK)RnVS|l%qa_@OQK= za-p3FU`HW!^~r_)S>OFQrTNC2EWSFff%i1GrEOPs%+K)ag z&J+YtVuZF}Jg8GbmNCu9p>)IDlwmEo8T^Km3$y6wBIc;bbi$kA9J{5;Q~CS+E4t<` zivX(sol!4U{E`R&H2Ff^%QwsG!F9CZ1_<{?pu@}-_22hC(qf!&0%_V%RX!^v@)lJA zGOfO=O+(26!U<((@~AUGkOgq|)?(mh*mN*MfW^-;YD5UQHNwOUa%)+ZndIoX)`VDo zD#an2*$%8Mu(z0-ux0i=71W`O_byWU=3HGraNH*N>I2dI$qw_?i#I;!kPG0#t~2C1 zVTz47RM>rNZ_FUeNmB?L%1Il1YS@`;P!d)gWpiGrWl&Wt)uJuDCt>O%U9`PK1mryo zy*Wn|-*zuCn-^H0$$^nY_ygUHrX)^7xwhamu{UBy!IbWkf(51V~AkuW_`2o;anEk(S zBco)~iz4|jXO2?X@Dv{yZu=r zU_gYkVQzB^(NCCy&SMgn#{pOJWUs;H7TTu4am=NngBU1msBp{)_(D;7V{YWYqfu(1 z7ix4p-VB{6KB=rZ*yzA2=+jsgX@cz3ozndOs}II}3Ptit{WQ6j)1`g04vO0m=zJSm zYJRy+7hJI#J?MIsU0~I9NTC#;%6!!Bk@Fmv2Z_$UJr~r5l{z*7AMMhk%qpN8_c|U#TiAFvWeZ2rLw5&C`5p?uW!7LMES9Q!9TQ>aGnEHta5qZ*ljFfD zCC<^|tu`bV=xlWApg~nTU6ZeimoL$P^MHu^>j3w&naj(K8$4`7^n>ote*iMnnJcs$ z34`qDIW5nUGM%3LlC_AopSza^uw(yvDe!PNiyNRaq&{33V?%!3DYoln(Ht9!t56@; z-}L(?349ckPS+qaYL~%_LFJg;u!?VOh{LNi~|HQSm-8(LQ7ifRkxLS_;Hirw~D!AqvzWR%A?&I;M-OK6y^<<|UcPyS>Sy_}2 z(>BJftnvQ8f9<{9)GM+CL~mz<-PN&(I#NT7NGkjSBNy{d#9msI;64#-5;{y^ZPp+pp2=V9^Sq|KDO=D0WuKD#~{i~S(%zR!1GB1F+;*(^)N?DWP#t` z(ZdXEsd0N?MGX3pd-9L!FhJ=@u4V%Pib<9xh!PV^zJ;k~ISC}@05HS=?6)G7`3}?h zF-IE0lj9fCN3m(Hd%n6%Jmc6twDq8KS82U4e7U{IpDO)%D(IXgVj(oP>Zk z(x$Xo-`h~rV<|=_M-)$JSAeen{#bSY(yQD7pSM1&Jh2UJ3yNa02vj*JY3blYDC(H$Y1S^d=yg}ncP$8EeZQ<|-)t_D-|KIz zUTm|RZureYM*Fr9%4?xzy~i1Y!U9;I3oVIf#aorCu>W#yOTpFNmUlhD>Fi!*&K)9T@?Ydu`}gPw5>ND`&=td@F!xbif$CT{D(D81CT38@qiLX?2({7t=H}K zs5!Cgw~T0IttzOh4wt0JbW5Un{V@=GAZ_RT20RtZKgpNz7R~W&?JZ|P2mn5O!AwqJ zy2O{Mbjz{!-up?F>H=!s+-5u`AA%BC1S!#>pT8I!A&4Y4z(ic|!LhF0aYq_9;_Wf+ z=fgDqQORm8Rn2_0^ZHWej%|J-S<;XZ5BSKso^aT;@4puL?>>EP_7Of@{cORakb6}o zjxwk|Z|r|jrAgrLB43@XFrz#_I)0G+q*m9@9{MQ>R0puutX#2&eDxlgDt{Kfc@;o6!e;(@NIfy>Tt=Z9Tol6@TBj60F}77v@WKEo#y< zJAUJi*X0f!^w=KYvf`$g1MxL*X+JC`eXXJbNK?Jy>v_9-c~WbwYo~YF%={UFuF@aC z{FAvz+bQm8A^Mxen2U6h2juqHL6iZX@#X;T;zByOu31$XeDqX%CRD8IOBniE?l5Jbh|^#f#doRgz93v41@_RCs`Z;)(zW^Sx4%M ziicvl3j2norP{r3)XcP)qk4m@(yllqQ?R3!iJk`%@ic@9C>BquK(#HSN^di^L%(8? z)>#f&u2?qqCl!CCQt9=QG?LtoggRghFEdx{LdsC#-Y~PyA4};!Z}q{5)>O9LST)zk zzYosyCyA%n)*<$Mo}D2w5&a=ItaJ^ zxK#Ig^7dt!mbw&uP6vn$BcmlUYt6tih8c{>&hB#jfm>QyINR+9JRL6h;Q6bfE28r! zZ(9j<{Qqjb(vr>ApROh?3XIrv)MraL(k-{$!wWYP>UzrT4o@G)>^ZFP6tq7*6t~Sc z@=Fjpi9P46`_LfD`Dx-e1M0Obfwb@I53eVFY4A|9I&gdb8el(HuC33xzKFPm{0X;u zcW9=pNjo&O8#6Xa)O<_)E?o)Z9cDPkjeo6Psx&c1xho>Tm_~`mi`uppRCZ28lW#PK zOA04s{`HqhddLwrLZ}F^L&Q*dtKQkMo?MmKM}z*Nrmb#%7YnoIeTDnRQ1_qz8{Spjq^c5soM_HsxT`$h@3S_k4Ml__Uh|3Hp&!z61Fcv;Vhj zV@t`m)|gHpf5)-dX?}Wg%l*E7%?Wx$ym}Z(t0T8UqI`rVp(Jw&BA7U+&mK<=b&t0O z8825Jkd8LMbWMdJuVEV>P{PjRQ+9Z(&`Qy&1k$O4r7XROTJhU>DI>(+(?oJAsc+^T zb-rEXlblSuLl=79;G#Z^r)st>>a&$SxU%RXU9y&LuCB<*jM;V&2#BKqV{mY0)#4E6 zP5(ob^?vWwIoX4gfmVfjtp$#_pp1gVkk`1pSVuZb3UGO4jsKSo(_{o2Mpk|%N|6+H z%V$cACaEs`aqi=uUtp%!FSOtB9q4r15RgApygq!D9>_GJ zG_1}7f_8vZs>)`8|NeWQJ^0_B885CJ2Y6$3E`0?J2^>>4`C0f~bk@EijW5J;MKRjl zKi9yFH`u(}ziY$No1rSvQ!h6p#p0pWD6_?)~oCEeh1d!&{~>743(-Bq>D=?2g3jiUkLNJ(JkL|D4m+y{xtl51Td6M^ z_B&L%^$f>g_5YB(o1D?Q0pY+7P}JIGB4dTCna^~==J&a_s(dISizZpRVyFup;B+%e9bSg=L+!^B0N#$%6j< zV5(DKILyH~$9;IoL2Q5U45` z&mA2VbHEn($mT+-7J-v@1PJ^j+rDNQyqzY?_Wmp}z_ZX!9CtMXamSAbwQXzk@7+^R zc04DIY+nvAk|IFcGOn9KM-A!cN#yo2C8MaUu<7M>n>1@=CQ;oC??o}r50LV5Mo6KI z&2tJ^w(r$*t_CX0D}^^m9Os&lU{qus`U{rCOC3+@4rIDnWWqGMKv1h>D36c?KAted zrsL-M^)cQ43ItML1F&Pjm%tr(-)fCC<>kG|W-ax6iz>`2OX`z1p3bb~B_b4~1_rbX zkQbwDYui`=761CuEXi*QsA_yu=#SS5M8psRi`v_rB0d3a8iVLth@?MXt*6gw$9t4*mdt^r75dFs4yUX^kZh_?U+#mnKrl5P3*UGV)zdZFToro=LYmm`k^M zihG4$H1KiOsa1M&>qzWm&Mn^JZprgshnvXW`e(ab5e^k<>FKavE3kRX4N#6z*T335 zh^8x$B18Vk;JDVJ%q?uzoOwjEVab-v^k6BgQ2YwD|A*IAxBsnlN>ImXK!C%32fU;0 z%=tx@(b3jJ>)!V8XvDi%QweU@tV)c0>d$l8Qh8$@B? zd$oDSi5~5KKsnSY{Ys-YGz~#zCW)5yEk+sJfzca77vK*;6gycw=?M8YBj zZ2(yVUq&WzLuTL6Kh-_@yHp)NjlglqUtZy^lO4O-trWh&dn6z; zy^?*`)q%r+StT7lfMS?3J8K>tC$J%49h2&N^xLC)#X65AWfRqzFBRg(!MT@ghIzK& z`>#nEYt)D{*+Sk)F)_vEZT#+^22mqeomQ;JcwCnCKKpS4IpFT1IcxlrX(#CJ3~`N2 zI6!tJu<8DC{!Nf!7`T8lu(jGG3yipaf{%_BuC}MHgq1xB@sgbSewL^Qi4Z9X^BC89 zv0HH6p$uM}1DQ_qfrM5!moaCa*{PMK4mAMC&xqMa;&T$|s=}{3v7Zxp;$ty?A*$+{dUEx)?m419R-h;C+Q0ibv&$LKM82$`JgfB$7@?UA zd#pdNspvHo(UyrkD5c4zWr_d0)}mq!*?qv#PTl2>FI>=Ir}k0j^Gy%hxdl=M^JlzI z0$5B88ScIVP(E^ zwEDn2Dp)zCYx*1=jq8Yb%h8LT{>22(S+v-d{WZFAZz;@`?1U%2WvuJ0{Q%;^3;Esa z%3DahB#mK4Jn&wF_JkNY+dkZiD{SQOqI60yn8YOIHq^2!0~2Va29aiET0s|PLfStVaQ7}}bI9H~yfO^uF6hWN(an;B!l%U)oH?K5 zU;_!*FgI^w+M#nPok{lZmQ!DDxr!UI~exV5dG z=7@^?5n{G51>8b#RvOxksB)AuEheh^X~tu6CBBAZyH0P9YA8zta*E|3U8))mAfTqO zS`$At1;1pKRp;<#T)%A<&;vTu;C-s?C8jq0;jyLIWIUmC<5^%7v&E0udE(oUgQeR9 zAU^u!X;M}8&^xdQk6mlOMQ)9CVJ}fNXT;ui%uX(HeURQ9ny$_nCc>#I3wcKzy~Cc< z^>lG@1z2%8%J56lna>Y+;bTR6CDXJlPe}w%;iJrL54Qy3yw;tW)g$Pb zq;7n0)(t^^f9jQORN?D-AoGJwXcamt^T*OXOB4Z(tLO|))W9| zDS4RCLXh{yzir9Y*g+&e&0Zy3;#qub8)1TH%%3r&tib9JfO$~z1TH+u8#ntuUT?7l znkXYHC?Jo^r_3pZ9^fp|YUq%XD1Wi65ser-jMAtcQ;}}k@qNJ*pkG)8MxiGNfAtXjBlJQ;HbC(> z+QNQ%`uGkS__6PgRW-z;3?Iy8C&4C4V(!nqAp!O)7JFLHz7Ce za%PFaMO2xwP5R~ee{-Ci%>?IzC^t!L8r9oqN}}-h@-u==du2= zKH=R@btKeOu&vv#X6CUXM1ZL~*PZu7v zy8EjE<=pYeIP)-Fw*O{iW;)dB3U+J04Rsrj*P6We@}8z0k%bppCyTmdtnK}9M*~Fj zNC7j)J26gQSKom0@2bqy-}|Kuh{#fOO}gGNf(5)ylLtIGy-vHwUL;u^V_31j5`QL) zM67S4z#Z6c(gp+OfQJbP=fQdm+<(apYqwulcUUAqstRGZlj7+|QvUFXuu zn>)^T+#EkIwyZ3BX@Cf;SSFhB(0VUpMGzz%@yc?=7P@(3zPKdwW2;ppGouY||qH5XJUemb|CN0T(MTuzAc;ch!92d%hL<=xB3f z-cO|%JE`#R^%##9kOw(3bF#*7PsIeP^mi`b!He_<%E@qyO=*B4hKhu4ZVy}qqvcg) z)@o$*dAvwWr2jeexa>l6ySalmT%+ji#He9I7jiHUFAe7iXI)FbNiaI}mg zMs@Q^3up=({((H4ypCjQ)!(VnqB$c(={_W3&WOlN4lvTk0go@`KQIR?cfut1zy($G zChl;63H8gRx`yUsfUZNX<<-tZ`QB3=bCDV*9ENMhv8RX}{7*feYZj2=qbjpDwvH&9 zI1Q$pc{PU+=BPA09CK1N09zy-1-M44M9@+F0;7aN+o=w*F5k8+wN3WW1L@`MD)2RU z4uduGxaY+I>XC%Mv$*APb@`67O2c;lqd`oCd$Y^+DJ(E;J0;{B?y*AiZN=F_3`6y* z3%-8q28N5WT{c0foeTHbs&!=z(gdFSjZVsc5-H6q2Dma3+U8jXDkuo0Ki?sUx9}Hp z+mOQAp}_Ej42DoBuDQwovHKN|K(?f;4rq2R24YxO-=m)FM*la;ot7}qxqTgZhFnQci<{Ho6Jn}MN2ZGrr*19wso3lio#0%Q6<(;g+%oggiPk?Pc@1@y9pOTkV)GHV zAK#%WT}EI;i~XnB!G<8rV#j@<=fgiDwT7U>y2Fzumpivo?UNiaz_2kl_*57`UuSMO zK&h?3wQrsA1m-o>A0I4HbnD8PF|=99_R6@R`>;GKnS{^0`Anf(&0HD+a6cUk1yVCr ze1RcH-y)E;=+H6i*_4=y$-E^^3qI^va8WaXbkKn9Bofn_zE^+i1XhclJY{oC4YS`< zxG!A?6iH>8`d+5bUT?R^-_jqa*%~zA_PxDs4t1U0F4am5mML;+Lbc347Nxy>!su7- zLm9{WzUBta;d-Vzp-XhAIbHQ=j4_@^;gf)7w%noGP-tpLl>* zWqInI!XTc`S_5eUC9X;l6K&Nut_(r>F3^(z2LW1eq>*r9`-bDSZI-W~)(^W%9|%F{ zYVn&mHVikfh6ry;&Q-O}1k10*6!OBCR>5YY7q%UpT1*cNZ`zEU5Qe39^)UN?te!5l zLG;IViMH~x#wK80+O&bV-3w{|Rd{_9Z&q0g!uRJmkV{m~%$=rVU3hD>Ff-g0Bs51p zA|}3X*jmk{N8ID|ZdG+w$SOUA0a((iLc2sF70=##fR8#IL^DV_K_>%S1~}8f%Ftro`FkO-ddi7zwStSM3HLzv#_ov z8&f4t!CZySQFl}i)?_xp__0Q#ZoP&EV}o-A;F`7cffJ@-`UU7zq9L90xgKXDeMoewT{NUq8y(44D@)MI}fm57-L|k%%G? z7Fc6}{U8s&c;nvYYWsg?ME#01-*-p$)%|eOfBHF_O{-P(cbg{o{60!8I=tJ87;_3q zL1$XuxIaM-AHG2HkSP;F>>O@(*K4xCTKXHK%_VZ9`Ss7mD@H4&G8$8Vz4LiC*_ z_kUELVhox1@R8r9^rFSLdQT-T zUq2oaH?-CUt}yfU2ySgeJ#OOgIpKETV8t6QK5Ii=J@z8u7E&s{G0abRg8xD8t(oz} z;;nN~U06ySuA<1PPJ-|8c5yRZ7f@BR5it*qF>j_BEoT)r>alu2>Sqr^iSn)SxIBNr z%9c;uh0|LPE{;t4C=>K<-w^p}`jxCNA+!*cs=2^v*x}Q8zH%+9Q+X0CIwci)2&An$ zOCkX%yH3S=SW=Fl6+l^+gZYUm4*MG=stp8y?4}MAvS_W+FNrFC$f%}YKpC% z&7s5?;mhtAWIJ|gh{6Yv;Ls05Y{dd4FH+}PW^6lGWxHwt!bP_Y_c~B~Hi%&2Y1X2lEb<2@(T^A1^K;ReKo|NmtuekSj zgg+wwy$~+YNF?1YSp(Z(3m=;7q7irSLrg=Eq;(h>+%8 zuwR%=aB&xCOm#>9-Yt7{xqXr=KN*)Zme2%5d9Klm4~`39JSl;Vk7JRlCPUjXX(dw3 zT_7b_bZMm491t@PGEUqmQT?7d63I3^L)z0_K2YoX+-=D5gdAg4)Q=8&X39q|A_NFS z-VbrS7thEbq_(T8p=tg4Lq*x@@@NNtPB?3WA6RdhGR3KCrpPAn(dpJ>|5BX+qjH zoBSqYbaA%_)*MZ-UCfBSQd-^-tky-ECGdPFzQde}@%MRk#nTa`fUY7Nt7GluB@pt| zFBYcpr~c1DayrR9q<+uK5pih}x9oXt5)eP|&(s>hLWt#p&N_YE4sZQUjSuoMo- zG<1l63Fl&y$CNz!a-_{*a(3CByV0Xd_Vx$0&I!Zs+Hxpa6fEhD$zg`nU2hBsk_qES z^L%F)QxBro>EpHB2)Ho%bE(Jg^swW&Am|fZ?x|dIB~!djWUbooVHAUONm5F2gC=-%4D z&KHR!Es#HB1+E)SIb9plp1`Rm$9L2S^mJmdp*`6mVX;Cuw1hciRAOPTt##w91%NfA zS^{z60CxSdx5RS(N&$rI{R`E#*@gRb%@4XL7#JSODTQY(g>j2BF<_Haua1ZIiHS3> z1+28p?Dl{j=1hAcq)Ka8Xge|kjd_(S)sA7vQac}AB_q&^8wF^xCwxjYsmWRu+O>c% z52O4CT$_aaoT=z)H{1L&=ICVLo!G1C)x(Ijs13-v$1vR{=+li8jX)Td6fMa+N@d*lw^7OPmu7z8ErEEcy)pS!)}a^eZrLa_2e1M#uaq;*53upb0ESAlXo$g+$g^1Nnn{XdCk z*&@Xxw*Mr~7vTG%R_z-&Nrdq$#{lW3ZB&FQ&qD4=GU^U{rQg%4Tka@ZcfZf%RXKlf zNB8Q({o}-gIge@W$s9%+BFF^ZT&CF0F^1IyvfT63s&Dp#Ci1@7Nk<$L-Y;uhM&jQ4 z>U4lFP$>Jhv5nI^cc2n#oLa@Q428^p!ueJRQ_r+=frS~Ah>+i@@BKKq9Zu%Q#-Zwk zWw+4jvdJaPt8mZM8-``5s?a^07saMPnr>MBP zpn`Z8UVCGO85I~==+P##6`f0mix1cXzmF`Kt`~VgX*vJ*brvZgf!25LdYWyGXv9N9 z6MgX%ZmAN3iZ9)Y& z{baiAx5MrVRVz7Zu2>Ab@S?=k_!q&^dSy^}f5b#5g^BRfNJB$7tw>KbRG(L{Z0Re@ zu&utMj#jm(`l7O|3rNPSVF{SGB^BZh@$j6kpf{pRxYi`6SZbu8t*!96*DMOq4c@c& zVPukKH~_8p-bD9g^O%XDjT?>FISujkru!$yvlG`-U(dIV$Kzq8U-odnQmr#~hj#*+ z%+0>&cR;bsf1)nY7NRB{wu!gq3H$Jnc+6^Jw^X=$w&XD}R1;Ct5Xfji)!Uw~Kgzbr z+6cFzU`rxA30xzFm&hnE=or3qBp?}zHi4yZ6P4Aqh_`k6PL(8uR4n-fqb9N_#ED!u z|7`P(GW0F`S+z#gv$%knbSr)1xmscKWV&*hs^&K~)H3`Gw zzrSHAXS1VngJlLdu!~C2ow@zub{0b5rl42|PFT$1Q-`$JtyRE4SOp0p6tC2XSp`n# zma%aS>(`iFILiyXdLq_+CjGIuf3@ap;X!fb z?<8Q6MQLy#?|EiT9R_}15euC>UPm-Tixu1jh*txyTkD98DpER}1BzQ$%RSZ@1Z!?? zVI$_eGpC|?&!^;sO_VSf@nZ?Xwsyz`%V$V0H&G*s->Ae$FU3f)HO!dC(;hc{MnzQe7Lf+!z$eSsTxs&VDPz zlN{2ziWA8NKgJQif$1+-NTeBzI9WBt|4TZ}3QR&3#*WH#gKb$7Q}HeILw5o@EG%H} z`rs=f{~bIEwnW`tn!^}9=G}5?c`-0cKyBfE{2jDcX{Vj^ALESI>tnWzLx$-d&f6!6YZ2Pf7;h`n; znHOVE!U&kZ`-faLKmZWyG-4j$5LoIF60y+u|LF6sWnduQ?%s@~8P$VvIx6k)ujXJ+ zbU*1P%sUydPaDpujNKJVxTE{BgSR@|7ibdmHU( zj|>JW)e>SF8i;oAdCzUdt#zk0YCJeweI}@pcyiI$TUjRLaD8c`Bx21LBKJXmxe1WK zEz-dVF*^G5;)6}hxkS>-KuF6ad~2Tkd2$~WnO6El&*U6ajuqLra8zZd)b%iJU5o#>GZP=`D^rj|Wzm4lE8?(MS2)x9K2Af6(;1xG4|Rs7b^<%wb1PnQ#qVT3qdTa!MPOox_7x4IvOaiK(a-e-rzkSUv0q8YIfuoNhdTA1+9IxCh+ z$~kt(CMg32Q9UlOJrFrRGbeG9_->p`O+ zqAhLR|5Xq}H2O^7K)KHYybviRmd%9rVfPf6BXy&c5E;fFlxv>x#}kD0S@STZWn-#j z`eB)SWX;ZDjBqNIsqwR#o$_=Zu$x3R81y{NKpySA?>HEkYN6lJcZ?d^GjP~>Uaw=8 zM0wn23eQu{g@J_%j57NVZFD1Mt~|9DlO?Y31W)rDbkOWOS;-s|obrygU>}`bxXgZ! zx`FajDfH#C<*hyg%Q+&dg8saK7FR>8VAJ;8xxe0#G<2*eW}v*vS_#^g&_Cqi_<0-5 zyxNtTAY|R6>wk08=iXpEF&bAiYhGN;`FjEGiVyW-dBwey|P7S?6pl2Ag-zIcm%~4izT1o;LOCaVZ2YarOC~Bvn$t?w2bgxEuTZl!H^h)z=-T1{;?=2I`2cBX=c(G~n!^wS(W z?c=R)iEOi*83q${74Fzw)8?6_2O4*~&x`XV2GhS!1kAE!yFAjy({b3)By@m)*`E8L zK*$5aq2t7)Cw*i+v)r+ZS1qE)#g8X_T+4k6Ll|%u2c2R0@r^E?U)&;!D!(`C41oJQ z_O*l7F$m$+OQT+21y2D4QudFiONI{P|JeUvnORy6wCn8hq~CiO_7h`<*H3WXfUx4* zrFI{8(Zdz*yefwd{!-8E%;I7V;)GwCH6D_)45E@#q}^# zA``J}O0k+#w~e0j3n0B3J`aL~E!-|9U)h-I8uVuS!pjdYLKZ#1X;vEKDgU_&j{$U+ zJdu~Azt>B+Rr<15_l@dy?P=e~@$=0J~k!4u8f+#bWucZt*-bAaCn^DKQF$N znPPA6y4J+4Ub#Yz*=YM&D^Exb%Xvj$1$N@>a$O|Te*@mm-tNTSM&Ew@tuCin8fSN} z)q6J+U!dYY(Rl31C5F3SR#au6oY3vV3S@@Bir?4#qrxYF z)B*`F3=@}-h=UY8q_?ZOopxJMX#2;)nMdl^?wav*2 zlf1Xzrn1fxc!l=(&H`teJ@%g>O_K!)QGx@C=Il*=(XRt4;VVFfxdW#4w?xzzl;(OZ#QtoP+Flt7b6B4NjEygTi%z zzpgf%o01gpC+sGmJkG5P4M{q#JX&l-WJ9*pPjEB_bxYiNM@ z5?JMVWJ=4uMNfdv?T^kbUY0fbjsdMHzT3c!5pq+Qt{9N4p&AKE z7=(twr5%B;`(10O80dQZ&^crh|GQhtD$Ufc{qbGok3Bjwg9-xgKKA#b%383) z7~V%rV(tB5TdG9?f2i?92?QQAIcEpegBSnB(J|liv(Dty>j-Fn@+{QO#AsyDHl8r0 z=UZb`FP`8@D)sDsPB7h!C-*#f#amfk%KYXMw5bnE0@J~0ev-9o22&>=Fk9Mpp8=C@ zNC`*&trd+-6E|E|qj`3Fg#-Qr+lMGRVC}DrE3*v!ML!si@n%*!CBQbDjX#!A#URW6 zSM=8`flOdJb5hmu?-X~UuHG;gbm9rT?deG)~h8f7xIqG=`bIdIt(cd9S%RLz{c>X z>wS{^VcMI=nz+T-@s|SBTTj6so8CPGnqLJESxc#4Gk~lypatsQ38M`BD~$4Wg(TwDGXb;q$14{A5nrX-!+={4qqM@>X(~tRK7)fNMJnw}jI5>@-VM;T zb7xPoJYU#*_ns6Aq@98hf39~dE4+ydbB%Qs1o2p!1z|3F(rWcu!ek3^=2$Gw{A&03 zjXraD-vhUx^TA4OA?_$KN^Y+rwoic#@i$pnv`f>L9IV(E)x^}7uUaC0?Vy`-0m#+P z7E^WjPmgZBD@VGOwnR&cT?38~=0~9e3TO`a{6eymJP02=S2Nm0}wNR=9F64hcQ6DMu3IEr##_iinFEERV(># zVP=$)bA(!v%Y5Gm4NCLMQ{i3r-RYx0W2EKU9IhKp#@a074>+bztMxz<@KaERY^Pyf z$}HMPPcLZ}`sg-u(j_jIhRAHxW&KaepUA%o%Zayp#J%vIOGrlpF(po~%~q!*xm;iF zKay>RfWB?whjomZb9P2R7;}lJ%K>hbDco*!;stOMTn;ow#_63Oq>E*j^5$P7=@SbF zu%;XVN20Lb?SI4z3`mlz&*us76<2k;TZ^qgumv?u7-H_? zOirhWnScGF7jE|kp5^2fUI~5tuyBAtKDOZA1iz?8`CLKdu21I|>Sk?+Uu00@!ezRV zQs|z#qwWh!}Arq6FL38k3!h{ z<+|5WR58d){ltQvG?yL;WSZ0DvLR?vj}))BTH2OQ2{*=eWsU7bMa#^4DkwZW-?DKK zl)1@(hK5tR++HC91CDS;g8i}urj^{}Vm)z%&iBqWCprg4pW^elA?4&IZxzwy zRoC|qKvAPV1_Nr3bBTKRq&C1Wdpa?U)W;cA{>vw;_w#$NsEUoPF?;0bTBv?XWvk)_ zS)0DOtRL_$RI+rA4b}tpA$t#9Q2)DW@=YM?fL<*7S2|AlHQSD0qA3pK;RVtHAj^4`f)K0eZN`PS&(0Yrj^g-Ty# zqG4FM&KhwUi2*cy$NtaZh(8($6sWDCy13gN8YpxPZ=02+f^1vdItTe@s*DVb8%y(d3R=#wbWM{&{JA>vfH?ztY3q zsd9SzDnQ~>n;V3I7fFYYV@*Yq%6U^mp-^H#Vz+d!eo|1u4?sJTqC-#N;mD`Gp~akS zArmGk_#e(f1+bxHJiw5w<>;aB(FojIEyw$_+!_#ECvQj<7}1d{8O~3l@Z1WSq@3GR z5u_K>bCSl~cUv5F@PsSI6Msl5tpz(HZX`#%4RUW>eK^<9SK0gV{)e53Dj*4SbYKfA zQ0L{Q4-f~%6c!g#gnu8=;NJ03w*?|Ylc?36?(!^Bk4{$XzmF4I(&P>kbmXs{42rl< zK>~RXKemULQ}$cB(!^V7j2etJ#7CY77uoGD2VUjJ=ljP=3_fW6j#r41(VSMmcbNuG zUJ)__nk6^gQAuC5@yq2COfZ_HiBq{UetpeVe|rOLJtAGBz>6XC!8_ zFFGZUlh}b-Bohd{1}au8qx3r2Vdyy|&~dOZBDH&{(xrIqi=?ZGeWvMs}ZRPtS0#(u+&wKsEP8=Vq;bX**QDRYNE4eA_VSg5k#T@MlKgBgrPeGp37^a&@b0zjq17gP2+_i# zGi%Hj&|l#zdWcUw6k8n>JtZ)Y!v7HP=8mLAbwnPuv~?_=j~RA%M)~aX2`|XJCd{|N zsyx$i?^$2^PYq^75bdv$Es1p$VYc(mawlEPHjyd*ZYKk^f~CJL4(r+1BBUReXTOHT zH(F#{=1eN02e-ixd|L9-v*kAJNOGoO6J{XWqXAEz5RAn;?BV}hN5;MZ0tFXTd^V03 zp5Ef9?_l0*j9g{tUD^_5xM`F3e4Hf~&RGAdPQdt(P8O?+;6?4r{hXC(Z)a zB_6&J@M8vRBj@7e?coUz)fHBM2q-r=%UKJ2lu4OYtnqh!_|>2Sn<}Fc7ST`Z@_jH? z9spACN}B)=?w2CV#^?%J+Ef+*fC;?d>I+P=O_WST75T10xfb~3gt*sUz{;uyokqF- z%jp6u4*sp;6)Mg-7y$seeDKI*v?}f`R2qS}E|l?(C#}S<3f+*S$Y$<^l7dBx=6M8o(B=A0F^@VWU4L z@66r!v=WXg;s4L^#-CAZXd68uY~EJ@5F=}5Lf&4BtWGo#l%l8mfJDpu^JF=EVtRWn z5D2u)4d4{#4*tWJIhrjtaysEvvfL8yp9$`*BRBpzkm6ilw>X8m6UPT@;uf z;bEWp3dm?*Uk{s6_fT%dxfW@C#`xV2716Eylq+^aYKTh{ZsoRPkMG;0k#OGmkRhp0 zY|Td@YME#Itv7~L)Sxur;@Kg^x8dj;l-98Na=5sA?blyN;_&Y5WWFE^5;G9Q_i9gD za9OZTx<)uvpM|!GupmX~X~R zb!&K*sOkZATSy%p77tG3U6vo)PH`{we?;;|Y4oD)Y%_xDeY!inEcy6ay7;TyOX(8= zF}TZIAohbP=vNZ@MR&0G4~u}`obj7M+6XhW+*4W zFP=99-kF6(+8e_g~+&GiL3wVxsH@A#!bfBd_)(dy|WL(@B zCM`)nFNDpF-2oICsx-veTSNf9E_s=6%}GZq%Zh6eQmY-NCAm!f&bFQ^Dak(1Xx+HO zh8A7A{)NA>2fds71X~n>V^gk^eT$!;e;v~*6wiYsYBir zi=^gGvB$nJ^x@6A)cE@Xrn?j0_xJa6R218O9kYMva-!U6osPZE)xKvJ6o3_8%;Ldt z0r`Rjxaf$tHAtzUbA|^#?-2ET^f;rIne_xRf*O~Z z6;pTJ?}4Fx3f%EkaHLFx-DyZKAVn5rrU9jKpe0epZ}v|q%zw*=1?xsrdxuo%G z4Dm^Y-jIu5oE}-FLb|50XKNkt&1+y#TFGXswu3>q&RNdU6S&A)wE;WxLd8YwWNtfTkjI%0+i{~P+BmlXRYlo~ zWn$-9wR>x{HN&I@3oqfb_W%i5O&Sy1f6xx98Y@~I71bx~(Dt|xs^|~^Hk&JiQ%P8h zJ?RtVYWHUx>-mHbR&43Y9pfBZ%9LI44PY@}4~&xBhnA}{WeEYf7?_oyVxkjL&95?I z7xB-aB=EjY_v=5UxuzMnhVCcLFy^S9GlT;7 zLAJy#F`{_gs&Fli-Pzo;s#C4bf9g?af@XKS@I70CI!<9#urvKB# z1*K@`j2G0kXmGlcu83z(2JOZ)-Grz~n^a^&pf~}4u(xE1H`GZ)_6-rcUuS$er2yGm zMkV*GxdKpMP(Qtv*w+C(3Fi?wdhyBvnAs6n{jF{Z+uxEVoiLHVWqIj!2TrDBOQ@b2VRp*cCZtcywxtn$qA zD)eBWIYaEwKr2GrB9&G1zFoQ1P0N8iRV8P&xGN(Ln^VUiRGz`890?>qAxdV{DK!$i z_wb`OEw;Q#B}6$Wa7noBc%w7CKGtN{z5KhM%kxoc(EPg&0d#E7l$T;{v_2!L&_2%| zD$sPwFPA^XDAFT&sdIa~9)@6&jM9ty{_uD3z$=i?on30P=nxQo8!0hd1)Z<^_W!&Bo50;%t!=WsXpVb)CtXw_yr+L4M=1NHy749}XWY7WLA4s^Y`Ig0i5X;^!j zGAb4@L=pK{TcS~YmIr+|*@aZ>CH^2ShdF2R_C+E33285p+}c{iA~{Xgh#f!@N{>i# z;wcDaW2ny(8i=`Ff7(5c_A4tdoJD94Ym&U!){UoQ2<{OY6KMbuJ&57pv&bGyrN~9D z;c_|fVcU`-*U_Zk7x)~u3g8C3`ts@&)PDB^)QJ3X92owoTaN(I5ix835}}*pKp`a< z)}=8gh#5GeTsKQMmz1_U#B+E#u5kbFbqf|{xBX-(1=bo##;dLP1S$~K^wG7*e0HDa zWXKg`W2^%3U`TErfcxAZxX48(WkmR*uS&W$H8W)QWDa&mSu+Ns(a^^*FxbeZrbgH~ z667RoMb5#|G_|PB7lA)+ac#}F#7C;KU-vlQJv#f;F#^RkIQ!%agNvhCTf>3TPmloRy{vP4?SX1{h+9%#f6r1=3`B?c*`etByinV~c36IVuH*&`y+Pur zVfNQ|&nBV+Gz&_GnKK`5pMQ53`ok0=8$hSn4tj(Wf5j2tjtj3-z}eptyZVpM?RES< zgvm*(L80Kx2L&9F|Kj|rwd6Ud05++kUVw}*`1!T;lZ7FtInLrUal~3s{UZqniIL^k z0*2{RW8?1ly7WRSm#(ZhE~%wONKv2>b_x zlZU_rKl-ih2?PidSEkNQ9(^$D9^Z|o(k03`SOsWieI?m4B}1(_UqY?C_5C9;c{KQ>B#5b)>Q_VOx3zimjS0X5%HEu-$Y>( ziTfvqS29V|13-E%$E;>)4(N*&;Gf`vIGCcsn3$`>ImYq-^JSw3%Y(EceNSTZnZ*-( z^vFC|?;w?ho>G!2Vm;)Q@cBqiX2C13zmy>HjrRU)-JfsCCA5q^;fiuc3F-e_U(F0m z9k0^0#+K5j%4O*X;3D-pegXt9JU_1;f0n}wuJWW5DZ1J=8;sdn@*l@M-}|XMv!f?( zBAn7=jCZ}Cd|iy#wh%p@K*A0_VGuA(#BqhM-k8Pw^RPL?3!eD)PY+)S89SE>iD~J6 z72@>{!YOij=SWcccOlAy@rCpr0oBlfXwh3g(IT;obqQMJ^CguNUQ- zx5JAHppip+Jbp&iFIOWZvgtid-jMw_Ay!}QAi#m^eclq-Y&a<(3j0W^&t2+GjwPcH zXRINwHSx+Jdup?4dH2{Kw=k5DcM;2(1AzKemr3r9okX%DD0|^?xn7yy6Qmm0{JRZQ z2%#D(`#dqx<+j)v{1t<31IbxKjOo#q3RkcJ%~kj-Sbsrbn> z7L~ZcE-s3LmaNbzIcj^dD^E7q0IG3${CVMPiz;v`iK?*#0T7yoG|~5`=5&dbA2Wj6 z0*l+olOKPJv;C)wBHdt*|D#ZUz>UnP6ygs(4R~nP>=y|yKJ4v}aUkKHD0D*{mT>y? z3(g^&NkF+F3XO#4Z$kbb?lm7#4o#A|x9pe@Hdjoh%oT?Ez=29ayyAn?D@ec_+c%ho zT^w-ALK0JdNMEGdGbTk1yW~mNTk3-8pV9Iz=)7J@2-C@`Op1m%Z2k75d9m7m>N;$R zn{PdJ`tRqo@{iFbLBUvyM%FA6Zef-kh@J%aIC}u+6daI=-#l(puBmEqLuFMexa9el z3DCGLXhNiBO~dCgkH*F2+MsOyOR)2#GYl4=j|N>vOl5JaQ_UndaUYVygTnHVMf;}A z;b@Xq4UP>i*16DmV%N8GgdfjURn^exG}vSYQW%3Sek_vfdln$LY7mK%d&rgpyT! zMGtX_sMxKJ^dn8Iq0{m?_8NA%l?(-gKv22sc%y^XGMzt3h-H}&Vv!=Z_c>-&tVQP+ zcdZE#v6J#4DR#QVdP~L0NAMG=4;aEM-PB4jr;O2loH+vop8P0-K)W*Ln$7#gjT+2J79{zu9T8kx}>UgUHynI`s14fiBAZ+8uLYH1Cm3=W^CTvpzYYsT;U=4; z3-lS#-?|V`V^g6v<#P2cEzaLq$o+@&1V?~D5N-P!LHHvrAFyU{7rA9q-R^KH?V-8g zWBGp8ep7dUz6I3g0BQ(NyFAcnuW~)6+Wj(dm)T7RrU_T!f9k>*|1P?uki$?wnc1@)`>v=fq{4Z*<@$D|PytrVAV!bUr0t2<%43 zBg}o+QYq{-o28)UWVfB~^nW`3{Atbm0JNn@=O;og${?L!_CbDnuJ;dY2!_m8BzP4l z+mdedW9f#_>&rRvW#Z_G=W-|L)1yRL7-8tazT(1}E!K{SIu7C^3~M91nF!^_3d|Jg zF}sGev;h+uR%R}yFN8qX5*kc2h(&|w{=B?OW2y-SkDDdsB$94<;`KT1k)~X$4Z@Lh zEZ@fjz*R~boJ+dUg_qN#)P9crGTu@W?LDKw_guHL22G*dv3=&Sr-z$d1oaa{PW?Lbj=@PX-@KPCAl<}6?4!kUKzUv~e- z1y)(8J?wYQr3TN6|MK+R3@X%Yl%DRFDJs(64bfG8h}RlSk!HJ%Q0|*ybYF?}BamkU z&%j=}mC(NQ98B0SBTlO_Ub?PuuFsc_B5ANXDVPN#(CW$V$5;C`b}hX;Y;uZOooX=a z0vYo+ld()2CjbNMqW}9E$1tcslvfjt_aj@6*Y?WZ~wd^*a-NpU`E>Fnmtw@cF zJ0#q}ZRfioaLakUb0<&K487i@ZaSoBU?e8WD{fk$@6j`4XNDGMB)J@%?Tj-;0rBR) zOdWoY6;tom-2|$+JZ$X-oB&{d3`{gN$x!L43oLIsRclm@{75zMRnDNvbgc0PXtSVdHcB~s*VST(MI*YfVTqy^4gpELlCETorJ(G zYL5M*LQ^qBM}oloI2^^g$OT`PDTt#)vgJVW4p3=Zn;ii@wh*cUt$XL}(Nu!|;hhpA zN39z_)E(_{Db_!;UaOvxbDAf&sK-nlVuJ~0CgbE`!J$p?i7A=eW^IexV4`7X)R)yO zsG7$3(X!su{C=J2G0Po9x^4ddTVjnFTEZLc8Zrn*6UY%a7u3}?j+AhREl4#(UG9;z zXyML)Ai=S(u?cQyQV)hSC{uFX{`Mg~zsx=lP1~G|@jDYrB!pgs)N{dIMvEr}%h>VY z^vG0rWLNPiV3-kBUT+d9Khc)LU@NK}9+d&ZKjlDtneG`jsbP*-WAk|zJjT%o-!OTW4XGvtzO@rBj=fW7HxgFFmhE z^!8H*4~FD3vamdqqzICV)a%0ye;u~XHSm8pQss}jkmiT225d|fk4y}b`KKdhO98D+)v?%z7L0t-5I#sxK3&gf4H1h+Ow zvN?Ui7C9724l@`($YFX(A!^Xp?AALI2f@D`2!1rQtC~V^U}_om$N%%wOacGNBcP8E z=G+}$xN|M9`S$Cgz$x#7zxJag`aPwQ+rzWTc{FM+-9!m3bY3GptFo`mJi~Wx`3r*L zkD7P~2dxh&y(#Yx$I-ga__YftEZ{p=pSwY?<*FZD857Sr26nmLg*MIWf6Q1W2`ZqN zB%O(sQBhBK7jM)k62pAp5NFp%n#))9DnaV~;63{!94Yz#%vczZbetM=oym~QJ`k6CEW`Vn#X^rLviq>*G&}dKu`)zRLDH;iwQG zflQBtvjqA5UD-l-DK=#5d}pdi_vG*|v2;(6a_iQ;GlJ8p zZ}-8oath|e?$1!?=vJ^vt3*-G*2DJB!JePgr#~%$xtvSIE!KO0=y9b~ul#T8Z-=Fr z$w9w)Gr_L!enk!hozOTJvTr1^e(C~bPx5X{D3V``O+lc~<2Fcq*jZG{lA$~{-Twdf zoPdmk3DM$k3@fHLmNh)>rkA!h+)zM}PteKoJ!K$}*Nc8+iruk28G!tH>u;(ow4DHV zLVDK|e;vzPrzsSas7tY_!h%7sahVf18iW`KE0HS&g4_P1L|8%;0{1am6_p~>4<8r}O z5lg$(<5fYwLdE_|sr^l zjnHwmSfa9=>zEh$W?iu7pcppy|Pv zOJKeB0N-EPW_E_bqKQ`LBR0x!c17 zv2P!h+-2X@V>GZJeZH;O6x|4TxV*`=&XC5;L|_`fgNW-Z$HzCY4W0e|)&9S0wy&6y z_gLK!ESpk?;g3v2NSV+T(7Gs!VIe3gNKAd;knx=R{*nu|Qgz$YZBt8_pZ9FA&(_z< z9IiOBp6{0SbmYrb6-xjwG?txtW?EeQ3$5GCCq5Odc>Hky{^{DZAxO{fh`{|>QCN>5 z6dB5kXZ<781@~uOVKH%r&M#zDqc=|>zZYoWd!Rs@H-$9l{cUc6aB~J95wpC^%C)7r zaJE$wf+I^+MVSU$u@X=1C1;=~4Jx%n2iDs)2E!Q`6bSNN-2o2AUn0^Cxa=g;6q@%9 zS^v{R%ZH1Uf2Xj{R`>)jK>m$s3Bate%9s{YqmqZVu7t8#1N>e~1fqneTm?S95JS0}@(iH5M6gxPz z8hX6MU-eWpT7|_N@cD8v9txeGUPwV9yW<`X1L&wIlhe&KJ(s0;XU&=FO(xb~Fi@C; zV)LbVY(D7d)y-D&#UbJ?0y4u3z*`mkNcY_kMPiDV*R?sTxc=uHqY*(l=3jwmxv$W1 zg5R~%{OAI47ozfs3L2Uxhj7srg8wmnZagCi)Q6+?U<2y)rY`0~dGLTHi~`0eyvjHRK~`De4tAAb2}FrJ37Z85F4)5>YqooC~V!NUjQ5z7n}YazBhzR zkQA;rl8VROqtD%`;@>cU(8J)36PIKohM2gN{AiEWaP6O!hMHi3lg)~BxY<4k?3^=} zTm=`#-9*Rx)cY^YunV%FPeT-B{8MfxYKVFvY@t6$hD%fpJ)FM6Obk;)0f3k232Se? zz)f-(1JRF2ELe??LH(1ox_aE_ixvdcb!gFqD`)0(I-Sv)T#|zZpUnW+}C`*(@k4wa-K=pm-9`Lx7%>|YC;kw z(Z{1ZquCX8bxpiOcsdV!0n9`oL1eVy5@`0VQ z4RO)730yay<4{9nOPf`PLw$#NbW2nl??R;9O}}0yNWkr>V$i<-eO$_k?xd9-3~yLp zh&H;r__`h#FeltKg3kiTX=#ajnH>68MBYLDQBW3?;^OKR0(?bZ2l7Es z(RWQIlZ5ab`kw5Vi?@Y93`yV*`K)K^gAE^7oW9^U+x>pHs&%r9Mr|qlgkFz9S6l5s zoMGcW$!3rl##BS=X1!=prm_e5Z|4XL7B9uly8I&4qu43#oG^$2w859e(T$fmf^Ey()G43 z@ejIot_q|28G$|##qXrk(@V?8@0u3j{)DxbJJK&!Q`kd;#m&ff&vOtV{FrZF_rL$~ zyGov>@6A%+e4|I++H&=N!*+q0PP!kiL`7jsR$Sxy7{gr<70L*l`2@N=jCMq#J^xX` zfaPIOK{St`E{qR&^kc(gy~Q~quI4j4!jG)VQUD#@=$9Q|``{wf1-7T*&b{q=IqM#D z=3u6Rl^+C1y(}UAdOT@<5aE>j@+3u69ubXU)=DT4Q36;et?jJpVYPQwt zs4k7KI5zbB^J{MNc|6&PCahR#Sry9L;_7aFeYi25UGijQ=nX+E-1_8SJ7?7K@C5CC z#a1P|{M5DL_yBHAZEuYxB?XtFgGralD~)@BgIuKzc^R!-18V zMOp(0Uj6Vh)N*$KkL@qm#}dK(wo9fPq`T{#JeoUmMUt|?Q*E4b3jF=|aQN%XyP8yW zv*af2ZQI?}n?~!*MpbHkh6-UkpSM+zdP9kbJ)FjL-bAr`S&kf-|j34AtXw! zfmui%Fcaey6FEG#|K1ZSZyKKLyQ0x8k;q+@anWnu;tvRLKQ#c|ip{}4!s zu+8<2?$(dMoKv}e>70w#55@&XZHkc>YuT^-IW>iwv*#fEL*K;`!x_xeHIVZPG;sQjeUrk`f;{}vHm<{ukKZLN&yQdJ+57)(U8pa#bowYg^x%_~}(q)VK z^O1{cTmPN~4pL1>}O3s*^MfjM@nv&#B;8VQs z(&UlIZ2Bu%;Xsp5!zuR|+N8J-$Au8rwx?UNDm=8zdT9V9ySupFd$Pxvf|pm7wiU8F z&JceahG1@b^c)91!s*JpesVD=(FCeTslFgvh~GpM6OZ$JdYpB?Ew#K3VY32Iu9Jb! zF$yO{e$?uO6dmuVP&pc(X7&aT*QT7fRB-QLgHv&+EJ*!BB;7}i6;lfl%7V}ip6jAj zzleK}N;~6%%LnX2R4>QQjHrd;E+aS`cXw9u*I(fZFfPhB^LN!tQINMPD3wacSVSxFspZ$nClMTqR*=&+7RL^o(v^$ z0-jRe=`s9x+@<@+@~XT{lv-=&3ko~=AvqdnA7dpLBLTu^VbG_q9dS;ipM$Ml7|?Dw_cz$UzeNw?$Q> zdGnp{_T$RH=z^k-ibJH0?Zd<4!{cYFr;9}rEt5sZrqabY6jZO^-G4sfI7)syw`eSM zQ#;od8DVQdigbiKq8p+RR2E~L0o-C$7qWuLMuYW^M~XqCak6{IgV$%TuP+~xM-wJG zLQy%bEob-73z*6V{}GSZAF*X*4Z40p2^lOjVq2P6=xcI-^49HjJ#OJa6sk})34h5H zY#i>dJBp~%Jt*u5^xgoiDuvk*9&=mUZCLS-cFk^Av zf@-cn3he5sBkQ=$+%#e$0(!i@04%&DG_Bb2qPYure<$CeDYr^-aIzAInKiAmWJ_01X8kBnwG{9;%u<#T= z43Rw9awq(E2!>SXkja31{bP(dq(C|$ZtCd5sg`LQ>)}H)t%c^IZ!fZjIHTNs?4ON0 zA@XvB!Yv9S7%xC-!)-7l?gw`te~bE5xV#}gonRERTlXkIg%o?CP;o4e$1ZRu2LD&y zl7+QurFtRS#i2>ca2>H+JBQJrHxW0PJ4Xhrz~IcRGP_R1&>{+WF3l;8-pk}3#t_s{ z(#XeMsvRUWafi)=9mOMUjSHg$QY{R-9#o*!SR#VU6Q4KYw z4(I%XsteE?3XT5@9M%nVIZ{(?ltK2Pnk@HNNo!qZ~V=%f@e}}J8~ooy+ArM zEsJu9%P(%g*=(7XZIF5%HmQ_wx34xcNB{4)*{qJ_5=)cT{kdeGrW;w~S74gW^!YKr z3yRU+oQOdwp&o)KY*e{n^zI6y$S6IXgeb2ffdC>G)*pTtMDrd>J`NqWBgiAyw|Xoz zwub&Y(m)~U&5a$+X{^(m;x2r7R0Rf)$-Qhpe$Gw0ke~Ei2FFagedO!Rib1TeKDqsXXZpQ>0H?&^6KLFdeBH(R$;%B8+GpzI9`uR1iB#o2pNs% z=A}_ZC<$tWtS9rCO6Oxo;tD^p)jR*dCXfM5iw4viDw9Ert;hKPm8cq-w0u2&>WZE= zXF!K?Y)Cpnvi}43SfI`Lmn*ag*kE<<;;t23K;0rbEe7SSKO&k4qutQ<)8N@kbE7ZJM zy`bdSt+$jhT(Od7l3*wM?8bMmPin6-{1=>Waoj5LUFbOPxqTBTOb3cG?txX@exiH| z(ntj1ARQ;&w8THRpRV`+B!#~9oUw*V=Q5Q62>7Z%3hsh-!R04$0uT<}*Gr>qBzW_FQGRz=&f z>DmiC?qUUr(vm{L2He(!MI3kh!B9je{&OC-6G0f{X4Pt(Gg_QqQh0sjI$DuI1bQ{E zj>-5IX5GqG(Gf#Ji$2`dym41fyn|xYU{+uqPjxnKlf#SY9n3|_KW^G&qE~z%C^hsO z$a&3DXbKOb!l^L8hLT&H3Rf74VSf4qEI`4&1%I>KAar*KX4ml6zE zrqrB#g?N%97MWH?5XT!2Z5*jnqA9a<53m7~DPmbyM##4NB|$U`vfT zz`1b#WqP?>0@ipH-I=OL!3U0?wR;UZ9w1)N)B~)XAUg`xCu2w$^$2mqIO&rKUvEMp zh6{|Mw@_J`Le);&qH9Q6%#L>AuNuRm@4{`bzx(E+1Nj_8Qj?OJa+-l2mxo&+1BY!k z!UtU7aMsrL^73)_I{LAt!fC11RU|CcN{>|0q=&s@< z`l9qeN%lZ+hs9%1G-UqpyRd%I5Pd|Sua=#nh(SR~p@S-qG=m+3LR8C^de9KY z<{%3wK$&pIdhp-_j?u=6&%8*-yuQWd5;G_D3OK!X{V4Lt(l#DeFM z`ue!bSz~`T@RN>6DDu! z4iuZ+&*Gy5wYpdSKXk~yFpp)rq)PVx$FZ>5g+2j4!DCEWVFQIcAW+JPH+j$~j1>mv z%D~uEgy{eJk(MzA9G-LC9_$1FI-BE-eYCxmmMQf7a?22yLB-fT;;>Nyg;h(BX~c}; zSc?iP@L6z$!;&qDoK^&z_-2M3)C2H=q}?WKT8bVn#&HY*Qu5BH3CD&YFcA^Pq8m9O z_(V?0f;j^hfjdDd3^XvyI}S$S&fUTjJ11Ht2%(Rq{lu9jvK^-Q_Y>{N*v`RcKlPE_ zF%y&pFCmRIjEhK%k2`WuUf03;>N7MPF?OAl5U5hoOg4RVh+jKnj=B=+?hL0UqyUsQH?eyy~rfUHT15F?|Fa z3T6f5>Y7QMTEbb4-cfnOonN4Ebsw>1#fDP=Emy0$M@?S4!)adYO0|imAt$3iQ;ct7 zqL8;Io*!_62*fc?J(m(S(y4A^IgHXux2?)hxTUU7GYQA;7FWP&`9qywf?S(fmsMR6 z=Xx+UnyMZPy`FAA3TRb*z?pNXK;eoel)egRujkSRY9u7Z6LmO14Er_LGenMO;%Z-s^If0SHghzH2;o>U8B*sZy-6x*?p#^qDH<7DBAwqh*v z188gX_mqqDZzR8#FGT5GaC+&3b{=hS1iqD)TK_#T%TS=Z!erOXD2}W}(5<>b?VsM$ z^%W!sdQGN3O}uV1d?FV88<1a&bv<%^<_prYqmw2_5Di7t5RFPmpWI_j9s&Ug^zYYb z`rYo9mzO|S3cWY4$n6=4khaeD2YInuWpd4Hb%(WfTB@)AsjJ4Lj>$Ym60|7^cwA z8cNv4aSt)iO{*OM^|oC-^Tr~y#5%6fO&+D(OmgWkO{jz2Sbj%M67Vi|9X#e4RZ;3J zZZs)p^j5~2+vDpfC!df@;mu&IIin(c*5Rl#gz<+828I=I5gaD>?vxN64Ru`j?%o(@ z3qSHOqX5$scNp0?lf$wjVcoc=MM#y)1&53b%^>68pFmaMYx?_ak%EKt=bk&@0dXe( z1eTq4ZpZ+%4~wIFKEYh{#(vmK*q;TQ3)GQBs(b=p2}UHYI{;1zw538-r#$Ai61vZp z%?kIq)-bp{3EyFk=*|%UNFBA@_%OL0gueBub22*%UueU;!>UC6le28r!#fpA%!9e< zdcO3L!7!cJ8TTtYUS6Ez4AisBonN)eF_X-YLx>;Y+C^)>gF~-7%U`oL3bz z-K2XkFLFtul2gz??lq9)C36K(bz!(*#1#<~l5F(x`A`@kt{hbfF))6je58e7E{>)D zY^(?F!MMpEh>nyCzQ&dJ1I}%JP5E~eg*0QO{)aGUw-My zs%tADt2KvwMej?L^1cBESN_O6ANUXno2bSR0*rwkmHz445GM*?`G=aAG)7>rDC?T4 zx>`)ld~C}<_K|g|<~^xLv2lR0sK0Y_xgP>d3&;eFCm4;;^8M5hwA-*m?`#7Eep=n^ z3BdhXn)ibFm$&_~$c}*{M?{I34xMw-ieKl zXOMzPhiV@BrQZEkX4D)97IZHH^X!Es7m)m6C zKCz)C3@Q|>*YL;MgDWTFEsXY~7Cyh{z9Vy@@hYD|SP|8~quvysWmtR|>BKm{BKH!z z%D2&lR>PiR!OJVx?0;xnwU6E!`~gfw>Ov8WKMhkXxUv6j*yNukOp*fOA{1#O$|hO} zx|U5Iur}%Et+o4qKHr=jrCS^+Of#%*(m2YpuwIc!*CbEOu}aM(&rx06at)Ex)%pY+ zum9GkyGbqFNnNO|GUY)sfHJ`NX#0#m$u~8+kP&Il6H61Tm?iwEp7dXos_xL+ z-san|&vRqg$1Dta>8%T(r6!N(2^za{b<%nv2RTc_jS-naW zb>(6K79?$|vj(1->9AlU2eON%7%D1DFniKXavRlX(SBWi;q~BguZCTw&&7Es-A({S zSnt-hZjyP_o(e}!9OYL#=v`&tm)u+FOFinbqU9eYc7qD*eXYWS=y0A4;#@DcLb0?z zgp-pR(v*DfgAZgua=r1!@p^yz?(He|B(+P4GbaAai2Lkh!RLQ}#TVqOX06da0rw$` z3dl@WMkv~-$N%o_J)t^kk1e-UIMm0YX^85h|L@( zL>0Hs68?z}QvUFo-$o%iyK8!(%`gtvcIX@A5u)}jTqk)4Zw}=3@Q@zC(DK;gd-Ye( zRIh(IiMHlQvn_rrfnkse`@bQ?DaP=)&pILFz7IQrL*QOWoRQx*5yXF1{O3SqpJ61r zOw*1(Rs|f=l7j^ttkQlQ{vnys$lN%A*C`MdoPqfXJyi7lInc}JX?9voKeW6+jpyE1 za#O*UKhhF@niBZv+kM?Q6~@HtiME#OI-dS6-GG+(-Tk&lFQQSbxqh;2Rl`Rh+v3E; zLUbZnO!2BM!UhDS$&L;er+MAnulnY_U;!cpJXpW8VE|F9=8w%6$iQkpdDK?1h)QN? zo#4!ei75qFa88f?Hyb}#T1Iu5`T?fugM6M^b-@?7DCZx-ym14q7E}coi9Qq$ZsYR= zV3V@dTDA{=6nNzOo>dVhCFn1SH@#GAy8M886=ru`>)=BbZ4U8OMg0CeTGEFeP_*k9 zPa_oy8M?7CMT2_e3q5y} zrOP=Ki4a&?ziq7G&Tm5WU#2Xos35s8U800K{6M{5kw%Vz2y&@mlmo+91`MamIEOUz-((j zD0-o(D!)`e#Hv-QS`Bc#uthW0=UYWNCHl?F+PIhwKD>L2?@Fm1Hm)8ut!grLRH<1}Cvf_p2 zu5r1WIU>(vYfgYJ@qEH}%4;g8L#S5DcEYTGxivP_6ggEcs`PvBpC+BX=#K-Hz0@Nn z&WWSgl-0e;(L3%CF4B9q$FWi`T9z`p>mMdUp&pmpPIXza_KK>Bx2XrZ_B5~tR5&BN z6KVnx!w4N;PSx@0<(E)* zJOzZ*^@(XZtS>Li7KOH#2V6yI8tBJwvSkiT*V^SRqCvmtyAsD-*#h9Lf0nDU=9ef& z91Zdijb$#J9=<#dFTG1pNeE({2v~P}_@ig*F?ikltLgEf^9H4SK&5d_!B_e`^t$Ih zFVNMqhD^I)sgC2}(7egvCM{MYjT)aDY9f?8aU*|)1I@g>&}fBYd5auyi_}~O`*?z9VSE&-LE|E_z#{?i%$PG z#_n9*=hLfK>{b~@low5*3d`&0qaYL+XBUY|6u7c!9`_}ru#cM>d}qsAfMf6GJY4q# zVV_|bmmbkTOmy^0KC2%e;ZHsnmpf+a=Oyaor>Xob8dP4gSixAy`a1ouQi;)fvEl?aSWxak0bg8piZ!Mq;qeQJBQb5&Ybw=1884A zeFo^E4`C)iIoO~=|MG>@HTh@dpc{I=synCTeeMX8ah)#pXyzAq#?WW?YPklbLu7C6 zGGhO5oiwIVvf(LNm@Hl)tBbdicgAmJgQb)33J{$?zt2MLmscx`t9BTJFKnRFiIpcN zm9E(mO+aoo;J)T<$9*1^ zvj+BaZ*L$!w~sacNHoBLuZUNHeQ{(es=>yH$c@z}ILQcv2~hj#@s@|Kgh#TwoQ{0) zu4COXWry(N_2gvgF~F?<(faAvH~rJe(*?G1#6d|`A40^q8>5Xst6V;`!AtyLAys?a zJN9e{!jzQ}*tpC3cLZiaYg(_L5p<$3ii#3CH6(pXw`g6KkLoi)=q=k|rh8D5l71rV9-Sdmzv&OCNuq zZB|Y^%fvtsXQSZ2Fs}+dD5DC2!BpTbx%lkLVqixG?0V=pEnVqZViTA**~q53r5o9W0Ke^ZtFW$*5I<>9=`?TS_u4jnF1B%WiE8ak3<^PtusfIc*x(QM zt$DBtL>ihbdU6)%<11q7^Aol?lfi$s1hwiGqw+8JU$Li`oW6BX-BOAY`(n&m7M$b# zGAZom7J_4nl()LUP!9CD@ec}s<=4+KV`aAfz+bUqDETpMOJ{E2xm-=00jauRIz0|EUcpk-ashqDR^opEc(nHcs@vFMdEoMKwrgmIck zwFPipILBEYx!kE8Z_y|~pJmE|0>}FYe~o3B>ocK}8RZAKI0(Eop3Cln5|jfGgd3?j zIW4wZ)x15_=KoGB6c}9wR5D9yX|qTW+7`S0b8psZRH+6Ot&>L|C#L622pj3mmPCCC zG}Q0`3k^ssVZvB@ZdyB5#P^B5ajnyrKG{TD*js;m#2h`{?`ZcLaq%!jfHVlx={Q~x zC9$u*GGi?NYn7!jA&IB7^w~y0?H`eGSDrD|Y3?@TYF~3n}}tPUit_5XUTye;Cni`MI%?35(&IU15s^~dO6Lehd>OI zdKG;1W80hdXP}gCz~fiI_h|u320K~EM zg>6_U#YQiTu550`tZZiHUQg{E_ekayEB9udKS3$w#9^tzVyGhZe*lF+ zdcH~4x1051x?Rrpz!n3EQyq=_o4>Gt_E z)ZiQk^_XIXV=>sEvZug&~DktTt<{6H!(Zf|$vb zQ`x+>UP`j8sF^2Ud?zU=R{&R);9JKR<$4>qq&T7(=Ir@5j3V&mhZcVRu8DJyhwT%UcOu})tW~a&uE&S zk+O19k~Yg3a(bDpD9V_H6A9O$zI;${a9n~Q%n|yDqu3-#iT!rHnvT#N!luo)jeR01 z(*UO2lq$&+W=8XN; zGPDfAV)|rJT&cB}lfLI62*L45nx>PI0*11#J1|Cty-%-&Y>|rN?PmV|&;JGeU~&}T z1yNBm^HI-rtT`%PNCRS_Cy2ZtnuaF9#D^H+ZnK<^y2+%F&g8iS2gpGbvkZsCqie5b zV;}*s3}53X+`?xc1pd=6f19qgGkJLHwH;odk2mjHmtV-a0^H2Q`)s~ktb)BZ=|3RR z9>=5ZXIW9nxX@SBbftOhdywVXmd>RzIN}r7B0<6j2Tct)u!3Nl#CC!*8yorVdO0~d zeQH^TASts^*Rx^#<&w$eY*=fZ94w9J&%c3HS5|;@6c9<+%|?sKpmlP!C0Ou7A3g9q zz(7Zj%h~Ao@;MNbzW*Ky(Nv**a`XNteYc}x3OiocVHtMy;aw(QX`elnW!1uGY%VKm zq1*ufV803cz|eOb$7ipe*P5rUV)0U4E_f-bG~i$cPZ0H+$-$(A}s$wf9f#Gas^e-dYjc`*wu5z=IIOHcNvzW7|!<`%+b2{vZ5KQ zIYrU5n09SjEmoGZQ5Xb^=}0VARXt~!>+O2AGuDEXHWo8XxIA~?ry^Xk+i}0MLtVR1 z27uf@4S*K2*4c~MxHlbkil{-a8V9E!(Gi*zzH1y?x_o63<_9SsGV{OuJm}n38VAVr z<;!sr8@)#|^?;NuomLmqAv9-NwtM$cK0H;mT&;PGVu_;53PgU>!PETdwort&GK%2w zh;2WJ?uU)>)LoG4% z|EDysIrcWAs7#6*lLt3U&bu8f53=l7TPjXcTxvEM9GpI11B0#mfd_@S@3A}|c#f7U z?E-%>9aftso@-GQ)qlDbB^;NT6iZRDs^zES?&-5nJ9qCHOmS#z(#f4H@I24QB&^mt zo{svM7RPb>_+maC3cR#gP3aV?=L+PWx0no`5(vH7a-dkG04BhPtmBwN` zz~7cYW*l-K00majjP;^LiWFN2L=mJ`vjq&IHcK^EG8$u)oc_e5x|;-GP*3J3E zbWWz!Xwa^glV_j(CL)JRnBhsL(|4U*sk&NBGFWz$aX%p-xy^Fw*f^w`2cJ9)O z8WB6sxc~U<^*2BMhAo(bYx_$Tk$+OR_?PgELAf&2s zu>z;2i^5 z%?`VF*?dXI4o>*^^Pllq9e1C-{^s`Gj|_Bu7-S-1C`v32CfwH8U|r^Wal8Xz&9iOG z#GPcb1lrHt(o71H^HeHdto1uLB+ccvPo7zTf_0jQ=O2Fj)8W}mmg9R5SI+O>`i9OdwH50F424>d5W3=0`EUV|svtcjX`I=tX8f#t< zzziOBtBoVuG+fUv6sy(N@%_~=mB!(8*um|NiwOV$002ouK~&3+M?)i_lE8C4@XI(w z&v~9(Z=d+Sv%h;IULWpKB&V*b5E>w{I)f+MT+On@8q$C<3_&c5+7mJKr5i^V!|omU zD)TYkH7utW%Ig)7sm5xK?R=rU829%T5ha_yd;7ftrk=s3;7V*AT|C{qB{?yl$dzjX z38h3)R4CU!{QRfJ;rXb0-#9v7%_p8`pTGR#>g{(hoDc)IqGea}asA+Y)V)PYRX#9FogA4hn&{Sxh-zEY;csrj+=eYi^c@XV2jh!n1|;TwB$0QaWRr>o`fA zEeJf2Wx|`LEhgAl0v0T*{Wsq#^@9}0SHMkPDr#;%?K_rPtTvtPHeae>ExDQ-s|A*j zyKq16^jrs2+Z3B(Q$E}fhMLWDJcN|3qYKE<6!re6e{8?_ESs-9-MkYd5!JwI8$McW zmQjW#eqsbaNSOq%m;H=NR&&0Oi}wzxiDlq9zy1&YH`7sf4-1x6{pWxCZw^2C(sOP2 zk^-OO1aM=uoFIsR&xmPjyQwyhCc|zDNSSO%tP7pHt6UMwsD0@OLPMObL(H7wxLj+y zj!h6Keh#1>!?i7*7i`On$W~gn>p>rICpq$P4FDed_U{%RrSipLkPuipG6-UUaOpLHKT>?QYU zSsC1a)GH8^7ptx5xLa?ZS?1E-0)Na4;^5u)jhA2H1u^PYY6m&e4J8otIq7}6=5pFP zeX&}=_Mhcho zZl&c6tS!r2V_{N(Dv_e;@!Ri9&tCHqn3XA(jgyFFc?RpdWufq^?1BtRUy!}vU9wk&_ zV{wrdcxlqR*Gg4mvywHe=*x`*-*FNup%@CO5{^^#0-YqbZK@zF+neQ76ye#VW6H6& z`9c-!tdCc@XU`ztpr~5=)Y#0EI8k$XjuW~+{ZTzUH5U`5P~jw4MAU47W!c`tH8e!I z(qb~mC_2vxgZryOwZ*Z*`2K@lLE)7pbokKo^ zGweF~QiYJp0$xDcKHlv}UeTcda1rSg@Ni`TPJcRibk>CD0D zOZ4(xxSU7bds)wAG5~sJ3+36Un<2S1*S5UPLMhi-mfx)A1ROjp)epAV`6R|{TxuSr zSfI~C*FApz*~5pQa+LDp%VlxnfxmL`8!jCM52Y)0bbAYHb%6$AKWFflTh*JNA~M z>BixyOK$3zII`?+7l`Q$h99aPCt%3Tr!Wm|%@tZ4WNV}4 zi&{2s?iH%#dPdccFJ7bgKOKgl|MQ>!*4`S^ahJ3=qNB46coVr8)-t6^ z@9{beyya|!P^|AAo_{jv+~x`5U~8;{(BGP?$q*~Wefq`s@Djq9mg5GUn}=&~fdn!A zc>DhD!;h_#3o(Fm1%2yL0G^>S9JA1Hc` z!$U9ysM%~>DA##Ww6Nt!XN#32j^BLu2egP-?jzK#we@o9+S?*|${^-JiX1FR0tcmP z8?|iL&J`*w$I&RRjgZ$QDYePq>D%A`YuDPgPoK{xgUxcji$g(xS27HIRm;zbV`w(% z`GGs_Kki{rSi;Un6qT@o5JfS@1Kidt znw^jO&1bKztugH0Yq^4!D^;3D6qUHHHJ=W4QCP0G1u4B=0R6%7;2V;T+D_4O=+DiD zo@ei=HEOnSfA!0|@Bbc%XWMx5{U4M{UD30kn%djt47kI_;n{8%j0YW-W#{BugD?Q8 z2qQ9&!|S$oa0F9FI%7gu5zCq`N*UL+(YMjE^C`LwzM_70XTHbQ5J+Th7N!ie1dci`l4LYmqb>U8=MU z@WFr?$QLV!)os>=Qk~}|Ue9}Y<%|zbp64sgQSZLmIARzki4!efR!bO+J$wD@QSS~C zRu)2xeJy^s+cA0p<~1oJNwRC3SHJvaHtZUNWTIukAeNyXTjVgTL8v!F@LZw@y-B&= zdiC}1Bzz3$?)?=x^n)s~7n1|vJ0FwcrX;JHN6bfRt~l!7%W8H>IH4I?8{L0gOh?f! zq_R19Bz;fSa^zbKeA&GJ2<|OZvS_U=-~ZCR`_M#p8Ll*-#HEask!uI%948PZAIAEH zVofJKCD*k+{_L|Q zPO|x8;5%~TAfXbZvs@HIx5nz_mw#P7zTAajt#!1&@Out~P~LLN@q9*xhpt>dC{`Mt zgZJEKJ=Y7RhpV406Q*+T&=ieAveDfd%k^?ntTpG;;cVEwfBz#*ULQHMA*UpNK~D#r z+9zM9SPlXJ0z@Bn?ouo_9}jBHV;NICjigp&%iI|2c^ri()|(p=!r5dL&2y}Lp|%f^ z8fedS&DFd{%5r+HY#D2w7ou?Ipj~DjoIV!-cC<&m2SJn;kJtA<{PFbH|K956UH#y6 zYpz_|B7AUle{M^0oUG}3p(G+%H`y#_1H6ARoe?E8h~z?L7lr0}iDAkvN@%)u@!D9< zrHpKEw;Ta9srdo`|JhV5plbDcrwb_&TU7^%@N+HN;`u0$@MYW4Fk7@E0! z{f&~%gYiggGr+I7TeeVk9h(6#evY(>@7@3Or^RH5q!yx#J9|1>&nJVs_q>#LY-`+q z%ry>u4{>EZS46>86rmUrL_J?Tef=vU#S7GIKJc7ZU;hq?tXv_AA_9VYaDgTuQrdUt_xASordf1)%o}%aW7K>dF9KZa+GB@L2zSnc5O8aEg zf2bawfr}uf;U@)QEK5;|P3Ftle3>B|$P}CE+`bpnnQG$@1`;is#L0Bn({e>p8KUZ34Rj4*%G{JI8zR2?Ya)B7C3?Ma_ui)Az5ey-PvTdx!oyWlU>EHZs|F1NY+M761 zsnmGzl&{ohgKmoFYt7^3VnkC6yi4Rt4Wq|o&^SCB_3v6omnhGW-&vttyT5wFF!cWK zu$Pk&Q}0aEa~T40f4qMm`Yr;2gaOF&%V3@|uquhv)0XELW;bdXKV(|JZst zt--nD8XMee#f*aQ%4w=H=&q1<(0*b8z}1#j<->C>hU; zYE4LUaJX@;5Z41PiBRZl9$kP4j@9R+P-*y%t>y~*`|H8!iy*+YNY=9J#SF9=JO|Oh zOR=n)&6}%*?|a2cV>a%kSkAG`bVe;yYRl;eISWD=x5@NzvziS%_Xi-lwp_=Wj&RK& z*pLiG)2_3XBxM%{fK+%+;QQ8gvkL<)o0pYr;JY+Kk9v=nuf8T?j)dTZ6V&tdJTgD1 zTuQcW=mbpkbo>6xzxtOC*KaO9`6`B>w^OdQC&NyPWko3?2vYa{V+M5@4|_~l<-r=; zrx)UAmn+w084<%>7-ox=#dJW?bVkUhqc}pTg%b*;8f3}U);^`P7!S4x zTLU%p^2@(^``zy^UVro9$3NyuwS@e?WRxr{FzW@`3+QXFUC)u2UQf$}#|;i&CYzi^BDC+CF(c z=-j3=imYkoX5Bu0-nn~+;E*KEhRC4;HAui0o@q|5#}p`T;1k#%k{1jSDcSPX-?Q5#U}PCu>GFJ0ksRD_n2w51?6co+!Tq>1vY>T22Eniag9M~zl@Z{O+fA}B& z>%)te)@Chb&whUu2RdD%CV6c@n;<8N-I(LOi-LVV?`n;_U zBbcFO0nKDtcwt@FlF8*f@V)lQrSCacKmMbf&HJ9CsMp2Q$NGNl&By0T*PK^M1l^?I)B}u#*_f9_f8sVjAr{{`KH}4WE$ro#Z z2S1wYZc(G!g>jOEp^rm`WvaNqr$4^=_VV?wM!maIwUy2&sE|r&MB71PH3;Iya<)dT zdGvVola{Z*;*u{1q;S={`;f0Tmyg$9|EK@OY|=+6m*+WN0<3x$PKKRquDCVVjf1l| zjxi_0z<90YO1|f2GU~(CFF-RpmTekwl9cQ1z{B2*RImaOtur*FS@f)wLHCxl9{G%- zO@>bpl$Pq7)s%`UMb8`1kgp0QI8xHGvYd`w8z8k^7{bg|ZkVh2zR9iSilT(C*wfW7 z&C};D>?@5h@JwUbK7DSi=CjFwVHiP_z?cbwRsS*9JR;S3P-`GEU(PY%0^Vpp2z;FH^_;O;7?0P@Pk%id_kd8Wwb&G12get$F$%!b?b zV!N1748x`~*?c+l{amRs9rtZ>_2SFFrWt1NbiJOA4=z4IF;CH$6qdK-6JkqH3mfKg z);f8fR@CKWXd0{5F~q1)=82M&QLHV%wS(?0Sk(kiCGB4d<@&+(n{N~RU9`n)luj#BCIgK9YTi6NA9QXqims?x?1%(|(H4Ih=(@pd(*7z9ic-<1pHw5%1@0T-5*h*V`=|x`HTr zE=1#Kf4Qz8q=Ae~lHU6tGx>74cJTP|=W6?8eET7T-<^jt3B#1gF|kl>t``$bFoCfG zqscIqwz-j29cr)~`ZJ61pjg9ZGKpf2=QqnaLo?~LVj1h!(S>V+CS0x`2$D2FQv%Ex z-^X!zvssj?&G~GI1hphST)%0Z03<4i60qiRoX1GcO))8GZg(M@;)>PgdNviM^mNdH z12HYH=aa+pm(xKf3{e(eFDCVaQ^zuB!p}h+g5$MZaWr@+*YT?{*HDiU^tpgM-D+`k z@p?5MZ>Gay4Zuk)TO{~9z@`)x?;5B%343RsMWg^xDEPj&oFOJa)L?y<<&|t+6f>@4 zM))}hOHc&^2XMQM0$d{3WBKw?OO-D=k-GSq@y_`4}4p z8lh#pU8i}KR92_N2OY8IiI9bDRaHTosAdPt6AW> z2WQX0AeQ9G@QMD_fA)V#tBPycdtW0Ash)#ZyIyeZEg%f*MWNc-tY?LC4eeXx!nItn zG*X{@)W>_S@NzaR)!G3(FI`^X;cS1rDO4KM{!{zx1;`Sk zo}y#D6-D^6RqBW4W)VlRAd2A*VpEj-%=Oj;SWVG#tN93ZE|Mw^0`NLZRUCrTX?c!c zZL*K{#!8s8H=7y54h@%H5xzcmcxNicfnL0Gf48*{U)ADm)=u4vb9zt?hw z)nY=-shYJlu!|4;IF7dFI$NknX(inGott;f<4d?XJ9m}FLI3G`&ks3&@g>W1*KfX6 z^n9gpNIcKZbkI?Bq!&_5Dy`^1q%CI*4Tw{z+Cs2zHMcD@m111Sske^%ots+YcsA-$ zh|6a=n#=#k)N`lBREHt;}#$NJ(FJ7sNQ!Mxh>Sj4# zucpnT%gti4mqs;@FV?d$GJJ8Q=1aHlzAxb1A4k!S$Qz2Ho2%q~c~6qR8ml=3dveuP|aS zWT3l7Q8b%kZEGWvpE=J96R;*wel1iQTXO{fP8=avJn9sx%_t0yEH@9|m?q&+_;iDLsYQ7Tug+`j+m*{iSDt64T% z+U)|1Tp!2^Tm`ih$^tZlGU{cDro8^mO;3T*t3c(euFWV(*`e<3tqEJFhm6 z?d`?}jXROjvV=C&Vn2zu%yq6%mbLt3@F++bhcFq3-Fs3aUj=&FG0Zag1KIBoM5cyh`8WaoDrn- z)>tq_I``rQv`p3MfGQUHAT=*1!)&3tHP@TT zpxizV0*oGbUQFm@F##3Swv2sB6EQ8%bsa002PBFkNIS?@Wpow^0@9W6BgJ2+);jLq zedGlR`c=bWdNCbjNC&1+u47eb8H1;5mDn@3=4Le;5t?2pqv+S) z{$8)PJR2P?ctZst3PV&-hMhPHr3_Nz8ChwcKEM6&V~m^DHDC1`3=RKoFKa6vE1Fw5yE@I6l8Bf@g=UCe7jABCh8!-`URbp1xDwN-Mn z#Sa`fY}?*$D2f&&>G156cYpjJThBiWcj0<5gFlU;N|mNzETxP*x_$fgfB2t2-n^9+ z{ptEm^8|r3-?eK8XQGrD_a60pQC9T3k3T^IpyeEAOB`5M`}Fz#rRLg3(l_!IzjI7fP z69XWDObE}5OY%WN+jz5r95XFDmZ|5Gl$HZr1ROnEjAHDF6g@i~b~!;Tqw5*c z424cq23M?7t<}Bzpz8VQyC1l6EhFom4KjfsNV5?{SA}xZ+$@k^KtqEA^(6%@jH2iE z1_`|EQYp{2L|Lge4>zm1s^>?&hg`8rB-wQP=yJWBY!-8#6I^GTPAfbQiEIMvu+2d& zoE_Y~mkSkZJ!_x6>R$br#{ERyzsf<{4MSstGrBD6xnkuS0eb4>^3(pql_)7vIxPwr zs9GMcampf%WIDwNyd-OSM$;$Y?_u+dCt%Mo z)+<%jVQNcpqL|+EbF;aUhwYTH_q*B_Kv)??_dL6HaAK~ocPiFedlQJ3FQzj}oFv`b zcb;uYqz4k)mR4&U^GRCK_qk$BUgCs9vx{GJZc?&-`N=o$fA~YLRAW+HjM)}YX%tO` zfp5<c0c#!_cY@+8D#Iv%w?7i;AX$uE=ufbOxVKQdlb0S{lqJt0al1qdu~i9JiW{ z=v1n4c<$QUHkU%pa5{Jd9uD=*4C;?T zXk!Du&gP57O8xHrkL6mE#MW!2TGRJzymDCNoT44lVDoX$wYSyQ;d(I%0+)!y(YGs< zYm%&3meIX^ujMgCgY9y&g2x-2wMi81&R^mLY*`y@$wR+bZB7RW=o9}yk*4T_vlnSu zIe+yP@Lq(}P9PQIx8MJPVc0j{{#y`Bs3ZsjCdK5)yh;!yMb(LwwZkx}VfWT`ti^of zSZ2A_w#~KcY(3w@_Lh*px5m=34M^I37jjTh+ToR;eEHA*Lz;L-f&N`%4mTZjXa?(o zFaV+G>GoZ@jxn32V?pe?7RN^vv*;0*0L-qPyv+yDtF9YWBq!zu9iF`|jMo z&z35JD3NRuY8ZZiD039!)iR$A)od|es^*K8w1UCR9&_orb`bb1u$2?vwJ_b0GOd$m zm!JNMmn2!swvI1)k5}kZX5`g!;=A_K?c3(@If++oO#>l^a=o2VbU{cL%XO4^uoGZ$ z>j(pgvB+^v&E^N-wVjc*1N<+ZjYWh)E)}3ykQ$cf+6YZm8mSb+i_-napG&p2isiV% zvV8008BM1~{YTGt&=OhB^g<~NgS4VOT)oMas-xb$tmTd6EMKa!9A_F36;X7uUI2Bn z-7J-CPJ*9dJnY_WmbkAX0EDK;5?jnDq$z4T=uG-gyd=5KR?ioQy*m>Fk4CmoHa4q4 z=Qg2|Lb-PF>Z@Y4m9NxE&)C3qrPg%q?R4C=u>~^H8HHuJT&Y?tHyVfM*?ehE{6vVS zW)!#*W9s4h&1CSz3w#iGwq=mc#%$2J?cBfLVrz*d%>H3otTfh(u|)#Gv+-~bF6=*D z%ZfIe^c#m~DVE(gvFh#9T%l5K9ArrHL{@ccyRpnQ;y2KYqoD=bPqvWFmyqg#cs1CX zt75eoBObVewN%etzx|FSneSoe7Q2xMXt|&M^fxJvwYD42cZ-$A(dDarsZQg*w_Rjo+%IdQYK%nZjIH&tFQNW@g zm<%6o-hlGDUeFA4`{74DS6t17j69$f~|ISN+GUjG|IB6`(3DlxnR~t?hgGO<7x{V(hJ% z;<&|peIo^H~rDyAh~5H7y>?P@WNW4IS4qb|B@ zgl~f*KK5oiFxN?`+7EpE2RH#jck=7Y;mgQxR)v-j4@Q zaTIM<2%!OUoG)v+;=$RAz4Zo=D;I=@=Fx@YY@gu5qga+JRa=e?Iq~`Dzs2VvSBx<1 zFX;KQUIbt#TPW|*ehdSJ_T%k4;9^L7WJg>@``Kg?$Fp&Fy_i0}|4~u1-P;f4`eC8k z81^0^RWyx+qM|S~jrGT${={*I^pfI7f|h<~6~gL3uc*=M;T+)l=FUMSbY zzyl%IGO0KL9uZq9#5D<zMRe$VWK3bPnx0iLJ7%YoOch~CzqTcw2m(;hiA66 ziK399Q?>T7=Q?RcRdrN5Fo_%W3e`Hzr1s7u$1?U;TqzB{D(nrXFYw>H+tr%KNgP?$ zMv|3MwUsMYDD0OO<&$UAVKqsJSu%kb5D_)>w5OKIV%RC@egu z`*0mcJJ+@q($`)*ULkOmgEl@O*j5U}?UJe&TF1{*92ZABqyIoNDOt;{S2HQ2U|;80 zxl)y;;l05f0MXxC^XS3@^qEF^i(`{GQ8Yab+I@+@+6n&KG?072yKprh_sfvjsNguxxP(vRPuBeY|>8J2-_~+I1hl|3jR_88zz?d3gx}rEs&Jd9Ho)-S4x- z%Fb9J9wJHO?wwB5H}%8wLb>Vzy$w77>;VMQfRoC@RTSa7lL7DmvJo+p5v9!jsYNyc z3ZODr@G7L~VN80DyeKeC>i)yef$!T}v;S}dred`7Z0qckuUuSHS;}<~FR3<*wWd#e zGDPH}VBwrlOj>CjU*3NBUMB^l#klKxuJ2l^o^ve|anZDb`s{q9=|#YT?d`00FOg^L zepN0C;?`VQ=9)>RTE`cTz2$g`)G!v5ZDQcnf57Y*qCMOwpc&Qk7{NT>%_hItc`~r0x?(3nX5&@K+n!Yy}$CNFwYig`ODLsN9H;4U zR7GJxvn-V)d%7ilb}YWDDe~`WGE>iFG)YmG({b)HDc zKkrf2OXy?Dlm3&K29t=4e}v6qDl2$5ADzE+9a~YepeZK_%q$R@!M2D28`=Eq$DE)X zs5**V46SDKQ5fz|kfnOt*&5+4T#x}d;K~%WT`v%KSxk{X@m(Nq!+>E@>&3*{Za(?) zpOMX}qvuMUyLTuFA!JxGR|~WDyLBD=$Wb3f=Ccy8E)m+OLLO;kT(6T0k3blpqr-l~;%dJr%6@mbYhH|yNoR4J{%6e$CwH(OM zQo3AkkMX{wMJWSom4xKgF7Qdt&!Z`1`b80Y7>?z|v;ux^6v}EA!bn7PP|K!hDp#sb zp*bv%2M?{2%jvKuYx-g`#Nx<9s(8@3DOQ?H3X^qwnkfpOC^ZM_t|;wx0g03>viSd1cl>Wq=U7x-22YPS3ehz zpJ$<9L?0>){D(K+J^SW&*k5HqfJu@_Oe0~EE7yvZM)&?BF3Aot$>ZcM<;(Ro-nbb9 zZX-0JZr*&Cuhhv}oacE+OtoyW_i(kEqePJ;$?3Dt7zlI&nqi)9-%&JOtsf%fV{aRW z=NO8^a_y+O!npT9ENqMgeqY{qtt3ts^D!;@6n072@_Yv;W%9H7ZV5^aQc}IaU7u-51U`G zU%?a#!TH{B`VC)>r5aIDKD2C2tK+~ep7s_Sx1+0o29u~G8~s;nEJulxcA^W_P$>m`Vd4| z#)?UCu3-V6&W;>TP2^OA-o-A`t6&&vn{oi0b7_wcg{^$+J(5)uK?Y zEeK~U@V$5kF+B2wEN`qA#&Wj9{Y}zx#lhn>!Hyx@9Vf|ZHYzpRdoqEwHO$paNXut0 zzj*)CpWuiDM?1yyLbh0Wyn4fP!r3QZg2T)5quxD$!8j3umMEq(vmxkqQH=khI8K(+ zfto`SW-@pRcR};;g4mHK3dyEoOE4Q{8;9n4QEi{#m9Y!AmXR;i@}=sidl&5@1@mK6 zAXf7cP0^C9tY;%?x07^Cf>Rt{{-~P>iL)kW0fFnpa5>)BU--Fv*w6){;`ucnKSZ#OsDdnKW3mFBultYr)+t$|xxS0_ptUu&gHG#{FMBudTjwu_-8;C+C3!LF zbArT+aKVa_?7CZmcfy=e&zD@=wyn*@tFK3$d*63C6lzh!Tg@lCAShSc#%9T}962dY zGm6HsP_RLvzzHcrg5S>tqId^iq_NyS+-qkSQd*wey{E)9C!iKwuC)hGcYAVwvC=eF z^JVX`&^!dfwbtrAT#MxnqxPR}BpD0CAb?8c z=*Fek;*@vN^vn2vndXQ94$AU^nBON z6-qK%uv+)wV>+Xd9lEAw^DfY~;4fLGK@c=sO)qrsKNPA>DxuoP7b~LZLUqA&OSKkF zXsL>pb+(w3QE{@xz0)gJ>bu>JT;sMtlK|`>m+Ob-8YBGWY#fIEvrm7uSU!V=Jh1Zv!W6cIoI zgo~!J8&R^k&2j<%uAW1TEL#AgR7w*Zvdz#ms2yQwtdL6l_{*Q$C(lFQqi7~cA|Cv5 zcno$S%zv;Q5tGI3`yWo9e;)eY)>sBXP-z?hZ)%xHUIyN3Hij|-?e(N{_hApldc1l2 z?DemBQE(kQMRue39B0&Qu{;?(*_M$>t1@{W?ZU8FfqyqwL~UAD_3pzJj#3%b5Bx$I z>Y?2IshWw680qGwOWQ)gVL+9m~jlv0VilSI9q%6-G?79UVW1z-9Zd-;Uy`hWpy)<*ZOfj3-b2JdK01>8O*&b#%8~FXA{BB#EZ5nF)Olp5RGO)$;wvt7_{QZ9>oG zB?QlGYr~6Dieam*BM&ntAMqiQP>iG99`r%-=!H}&C2QH)u!n#XK+bOHd-a1;!p~XI zG{Xx}x{x8_G@)W7A{oY5FA9~$(Z#Eezxz6qo|4k z`yHcC7PA| zBXy$rOQBponCfo~eCa_s{6|TLi5%D3i{-E_u<1nXSJFm4(mBqT7e|-<>$ZcKi#aCGd)|dwj0Rm z1yRf9Z{Gd5ujPQN$crdO2YwN@)M(Q0fIt99zx;UfPR-^KGgwSn9-ZbrrWzP{2{)NI ziMJb^bRCM)Sc?4+5{zIy${m<^%83UHHU;AKg0 zw1mjyWUv7fcp`No=vY<6CwV4{nIQDj8P!!O*xFSGi-LqwC9DVm#Q zvDze`()4;UX&zpLp=WQ+<#cp#`g}ozK^!Yc=}hY{Fk=v`|cXe9P!3yZt$rrJ14l6XU!OJU%bYE2Ua(!QIax4R{vjq%4ds=Sb`|XowRFaVII4A|Ord!4)BH}!AIcs1Q z;F9#|6v01YeA}PND2l?7OI9KZF5@a1x&RBainS&HSfe6jy@T>~?IVyu@3C(p>%XuDZX>+Ms>l*WCA zVKa)lnGDPAQ`g=m5$^vo=w4x3R`IpEdD}R74u+Vqq-c=!32SJv+XZ@|vYL;`vEFSQ zp5tPJ`NbGK#tlX)ma(a|0L!*E>-pd*TdAiQ+)RAe0V$s#1q4B)Xu5fL{&crbj?lZU zLGiqjFKws8Z1V`5I+lx~Fp8qIti@#G%5g&T=mM;Q?){#;L?t+#o2z-a+ht^Rb9YsK z{%I6PRFW+2Kb9^&F;~mIEiqdF-AmT9F*)C_@2}JxodsJ|4ZDTu5TvA~K^hSxh7Jj7 z29cKTZt2cJLb|)_W$5mPA*8#zyW#Bb{Dk4U_GUjT?v*!{ccq@uf}JK4{kJNQN`pt< z)YYK)u&MK|NU5Re(ch->rQ&ZH<@ai`#?NET(dzG8pVFPBfIC*?<-o4$X%pEfm^=H- zeI3cx-dz!D{nj(S@Ccuh50`9(2hL6mhM{j02PC3<%fH{G8zwB{xfI-Vo(32j4oGAv z<@>#1H1$!R8G0Cuq3;qll-39{+o~|_m8Y$#A-`4ARY@EBDw5)?q2k6zJpWJKR~RP( z7Sq^@jGcnmQ_C%#nG;|Hh-=@PbYo$#Zl?-scc-0hDj zD=+pFxY)0T5l$^@xB&w;l78Dw}9}FyCRF>(Iu0rvJG5_Lu4YKqEBjw zs@_bqDQMv$gU>+aog=cdPzCF??-$F^`s&0uj)T^|LmYLLXVlAJ$R1zB!UVLTI@cqL zZEHOs@7#lLd^ZBKr+-qBJzhNmJ!%dTmFZ`oN_w(TtS18M;>J}@eUIpmc4`p77+@_4 z`XhslD)eT!ZbLx9nPhy_EWX9gE zF)9@}aMX`0{|!H3R7$8#d6Bh91;x^K+OiCG;`%`vn#z{^F-QS$3%1^0qW69de;&&A z#CW7QaJY;O%fM}Z8`2f;x)_9g+`bQUC7rykCLT7d?YuJVa6%X{>~URV{Fm25qWo@S8!Oh2p+rZ0bbXs?>1xw6UgbNG68vPjqn&AuvBjcsl#CX$ z|2i^1Xy+8}LA~yDqNMGD=*9BHo1~;b3;@*KluuF3S#mrukj|=oueXre+X_2SV{_=UF&&|ZL4517aNCNaG%_W(vQxdcGNqlK{w_MgVsHbg#+W7yDnEJU!3Qg^4?nCGLCT-y6`=Ul4Quh)fq|FGxGL~hk_K{G04@=9Y($3j(d!OI_MX+U)p+a#M3{HPU`dtn!K3`4bUp z%x&rWvLR+XiEISVq1D2Mi1UVhqfJRw0>(XRxqgf&o9+;dU{RlQ=QP6wl{%TPB{Fa5 z^J;9;{BZM)rju9x@0dGbY^%W(ipBU|mKKr?Fz!)KuDT*`X>b^m{s;IzMojS1M75tK z5zEz3OyP&QdLRWs?hJI-u7;GyiOhO36WPVeIFHHF+vf!a%}J-D4C^MF+$jepFKXsA z>YUC6lvS%!6$*Qb0;iICqlQr0_3Sdd?jOcMfhzHP8Z*0-jo7-L_(0;;jH+-%7TBr? z!6|=VKFP^CqKHENk8kJ;W{sAj8&_8h%#=@eoIuQRWN^XDU5WIfL5f~|x>{0MZ&U%& z^WR*sFwF+i#rk!hBM%Ll$i{A+b=Q{ajjdnvT4E5Bun$eAMqBf-^OX3KIog( z?=I3z-2r!zjduU}!R?LR>&rqh@DYFI@V5P6R`wu)gOpncsZXn`<90;0hZ8ecJ0T8n zrSGwRiq8RmQYuF3*(Jw&`p)nJp9HLKqHwnCtpOXDndNv;(>gLJ^0`GACRL%qqbu?B zO<;+~*jcm`*8Jl^BBWQ&6|xfgC)d>2#xAF8Rvagfky$Mbn2sQ&sUuce)Hc#%S2R-% zI8fc&5=Np@X%_GOcJz?E^Kh^t-K14yE``97zN+qW<7L5dPz1_c{-h&0QmDdOPZmHN zLR@|s;0!pgzt`Sg3h$_Lf@nXMEdZPV`h@0}4N67fr<<4GzTXdU9Nja4jSip+`PUY) zb)#5Mutx zK#W!M&u^Yvl)ff=H)e!gEv@VU*w9gsvj4~7JnT}xU3NT+tyq3z87(z`;))jdp#K!$ ze>%Tls1Q#_pP(g=!lh~JH{8rUVV8MZ-KX_(?p%{zG(YXZ@$J%;W76r9COE5d)tF`Q zoh{*%7qnUY-PTOcK-RbMvihjIzz|hPj|0Y`tDd z-(E(Zom@4hJN<3yPp-+3_JJ|~VMsee7+%VcV`H`kVr-Dud89&) zLo)d0bmht8iS=F2i7Tv2fxR**>^sgnXmt73kUojoe-9-ygRM)v6Fs-7E38ySgv{C2 zo#J!SgK;*|utTl(IKzWV2HbTWfxZ=TKAbFf;-1bD7Q#4cLRvRCs4D}uO4?Y9Q{``B zYi*>!QQ}6Vyi~EsA4|7zWj)?iOk|$+tC;A5n(~fP)6G+r5p9N*zKCvT(zhAem_}Wq z592UaW&J7VYzi}j9yrI(YyER(^ZT2oP`mP)xM*yHH_-8sZA({?ona~(%7l?u?U@Hx-dC86HV zO%eLQG^86MQqb9au%!_P$?izq%amB)?ogQP-_TYc@)gVR0w$aR3cIz+y|~+j5kJ+l z8!x8wHt^l5i#(Tpy!FxcC6Mh(kkTGckZuzY?e$g`==~$_C(a)Ep7C3yNuh=w_>l@9tEnSl`zgGb}-c4a^r@C98Z zdWjJN#4JFZ^x-C(A%~u03nT1nK6g*zbxoRzOosEH)jm?3>tbR3%&@0;&NCiTin=Olf#YFqLZT&v7W=)sDgpt;%_nQP<^b`p(E@V!m7hHOsjE)hLEK z>hohH3m*8A70y4kxv?UG$zA;(UHK}5@rb^E`-d={WYs%udXekD_vwlB6}ahcyE||m z+Y2hoXIl02b7rOMw6}X)kqfg8jK|WExSoyc`b_$^(x<#*Q!hOuvI%y~$hD9eE>HZR z2_q>>Ia;`x4Tq*`?-sh+lS<1-qo?nr&6avgu>Xad{@11hoUixXC7OZJR9C zene3J0sg{m;S}eg^mnY{g#loSK|EL%h^Z)wHhZ-zFT7#jx5NbHGMen;e|R+i6OIRB z3y3GozqVc$Xm>l|o9%(6d3(p??%z1(GA>~Ldo$O$ug{oJ-S^a=DSI?r7HRid@x1@e zArDmv#fho?Wsn2e1cfu#@vsIO#IVfL2M&0Z6q+}c@vhCLhT0G7tLqaEb4LY7>fjWt zZUIL0@s^C|#;hr1| zJNp)4koSf26VRef#mr<(z5JE5<1PvN#E}w5-BZ=cZ%gzpc6*UfQe{%B9+ZW}92p3L z2#u@MdLgyYVDw|ER7h#5NuWzLz1S+_6zpz10QwjDpkM~wMb&R#`)Af1M#P{%Mo8Yc z&(+!6bF?o;Ce?`hSUs}32?(wgWJFqK`O;Z0Pd13}-Ijia>h>MnkBi1Og)2Fgk4NbP z960xOZ?F!2?_0izujv`=b9Sq5e&Om6DPE4g&wEC>t`wrPd7HmcAyLUvXz<&*Ci6|S zDebCPXh)88D!Xx@s801y8h1n4PPdy^OTX86vBvNq9$rr`M?jM;dd_afT9~#h?)3wn z!wV{#_8-@lKI>iw@u%&FS&eG4-sba(7OW8{tS6#qsR5FhrR2ZT>0$qsm$yvz12J&LR@HdHW(t{xHzhu*;s1BnQM_sDG_n#S-t(u{yiS0$}t8D!nx98=cG$PZV3S zKIy%zW$$Mubw;NuI@4RSo*P35lRlwvuTHz+RuzZ=%*fy%&!IPaWx^5pUw+-MK+#+R z39hhpI%faQ`fMgyc{8tEF`e-u3aA=oX1lYEl~P~~9Z9hDvf{U&BM<)Sm3}*hn`GI+ zAYG7!W=7-_@P52&gE^vX8duU4>~u|4%wxL`Lu#LX7U7L%h({ zk)w!sMl>tDIkT=OMqP1t$yR+wjWNvEB0b3L-NP2;s+(#4~fY{tFou8&l;14D>*z~zc zL|Nxns{xGtBfjl*F;3&;hbryz2ANgb<=_9MNfZ4BbVkY9PZkt<`6|a@jq1M!4ChtD z?>*vz5dJddo#$3z^t?nT<;Lz#HbJ$lVKZF|40OR5gnZq0w>(wy1*%=8a-*0}cd(wT zSD3bN-mJ_QJNuVHB;sp!1E_rmg_y&-`k-pzVNTv z-kFI*=cI*WI?zK9jvQ{jhBfZffX~;aXj+I$YA-h~34x?VN8AwM$gJt70{_##Y1-?d z4Q3#srXp2<&S}+v0TLhPj4ZGsSup&CAcwCRJ!1@al8v@NBXh9slc`p_Q1zpPlKAM; zb<}O5;l6cyzB%7q{a`xL8%<0le+s=GuzreWR*fu%Q?%k)r@=w=qfYsPd~b7R4zT*A z?)=};LKi9l%b<0%XEZAm-Z9{Ndy|tUEFcCd*^3)rKQUEZ;8-E~chMH-ekC*-YIKl5uM*XJ zjd^^70;3d@*X~z=b*KIm0j;nW-p<;Ce+~YXthL@`U>#5mK!R1J1(VQI-P97o@#NZ^!_bW#Bv4SU zX=z%+N;R%}MZrVrCv44<`##M@QL1r6p$FT^WVxz#bm z=XmG_ujak$M5)I}|7^})J-FFNVSIx731FdxQxL+)dn7}kteArzAmVHI`*V_eVnsM{3R8;*@H%P+n%kA`Wplxz?Z-#dw-iw3E`P5{x_?I-1xtHTV1w9;sUan zVlPE$9#33oLd9N1ZujDn$JX#8@+|&)mhQ^ZVYsu)N}s^SJ5EyEk@~B_ynDI!}GW9u5f%j(AJGB4Xqv!^wG8RPM z=!_?!L^rSw;6`_a&?Noq-;jJeNZsoLOvIUSUqZN)98zgBk+%msz(eDI`W)7G61SH& zBM3Q94v8439}MOpLh9E+M;zd&&gZkkhK>KQWVvP z6UV~OyRpf}Cpgb41Ju*m`xH_GFyXVhpDtZ5T@`?YHy~6U;f- z8=3hS_)Kr}rV>~N<0edJ_o#GCfv;;|x=C1BMk1rzjGa!}=Tamiv7 zNkFziSJLuDLq1ghFeOdvXmFl&3s@h}&NNc0;`eMfvvD~U0cyGbsX5teU6gvhAtJ7X z4f+!q43%aEGTnnvuwsYiY=et*H0sG5Tf}DE9rh38?F1HLgkjA>-w@G#wfNRB2y3 z-h4Y=AF~i^%>YX>Uko2ZB}8_U&q6{qRoXc~54G}+t6(45(@OB|dd~Mb>&^G(mP67x z*@UtG1{4mvss6`r{Nvbqxrh-$H;Z4a0S@a{VvqXZ_ghe%R>Ul%OJ6GHpShLeanArR zVEV%yQH3;qIk%2=&A6e|E*k#|xplir+;L0XY1n<-e>S;$5q)epe7P?~jG&ys$TPDOZL(m<58Nl6px;=dMbJk28?kEn4N z-(RNmy%HFQx{EC$zdBFn73a_LcOl}$Sp#KzHLU^Qsn-MmpoiAWw4E(o8+{Bic*qq0 z6gsc|elwFe%&9Jqe!TNjS8>JNvI0;+@b8Xmlt*PFnt(b-UcH^f=Z_|)}G{8A#*eCh9hcw7BV-3G3j2ef_ zlvk?Jq3?RELBB95L@S3)0oK>WMEKoNwdwwMS!KO$9R!cNW9`6y$Tv%$#{L6e=wOvw zF^fUQTHAEJ>11jzut=LD!~eQdBgyJy?8MWlEi4YC37ZLYQX&5J*ghx7zh;~0sSbyW zVg-mCIc|^3oN7(t+|&pMoi5@1#*pNFV|}63h>Aci_{+_J4Zh02kk2S55XBE=xUNJz zRa!s>^s}wU$TH&%=9anu0e4SS6->c}$CUqKt&S*C(Nrz;F#{ z@#Nx1sxBG=cG2MnGMPVGE%o&e zH1%VR!^u5fIT{UrOx>~bvZPN)QoV9HVF__#lV9ulrg?{eO-FkBbGn#_}3h=<6IM2)A0V_O=#&J|8oOJK&U<52U8#|DxrMn7s zy^5qCt-FJHnM6n-rh?-nzipXPnP#v}dla9p`waP!7JrW1o{Gf0xghmthe_x`7r7!6 zqVu`jbhzSZ=KGzWw)t-58sj@c5Z`P_S;u3l`v z=c{(54Gac9DsnLs?TgoG!f!ese+G(J7|gmINy=JGg#X76Hz7%72%Fh>7y+mc=C=|8 ziO7?RGman0VxxERvZW1;ndDq1K=7rrJy;!WM^a`lmt=U_N>oDk#L>KpV^AbpQU+*pH z&Fn9-T2@%ETX%@|Ia!C6{O*>|$vSH%GwcH$$@c;0ko0c8wL2E>MmH8%&p;V(In{oX zc+T>^*M=xyzk zC*4~ka{|fz<>0rAW4>w*<1YV%cRcmR0@mfq8(Qo|xpZeqvhamWnwiS<^}EeFB2*-J z^BlITZ|4WRZ-!Qtx0xeU_F_+|K;(%f@grbRo|Bc|3T{`0t~?nQY`{?uxP6ui_o&Eq58W;p96lDjcPU%*FULcaAdcK z3K%k%`;Iwv-p%=4bOSjK%*XlbT&HE0->2EV$XwH?1_W}iU&-ERSURB)e)V#`U`}Jd zLq|kHYcl-ARyGCZ%}@i06?0+H2Qr*{C}lO(*J&!^v*}r7J#VeOHiQ<9e|Trmh%NGh zuEOwdP>kc-Y{-g$u3tF111?I5guJ2DuYf#Vp6Ic=fh3rRLE4db8#`v8W1UQthoJNO zGQQzD!rKG~GHUO5b_GD3)IEply+W0x z4&Ga{Fu^WbbN4*%C|x#pHO8box4S*~guHK4&iJs^?Fh)_7-*87M_w z9DU+C@w?l(-@_GPXo06E&4#91!fa@Ki0~uvz2brtwjn@KptGrZ~91&$jZCL54pt|^8i@USK z+Xe$hW9QY57v7nxM~=j;YCYqyAiLmdtB|0y+o;Bv&^XUrnXj}XYna8u3-%k_Nl`hn z+iZa(M;ooz`03U_VBB7&)qunVeHhK=`a(dbTuX+Mt%SzA(B99XGC?Ndjhh<88v1R4 z+20{1A5qN`!@&Vt*3v6a2+&teH>D&ua5|R#yRLFA@DvFUVq}v&06`j-63V-!`!B?= zwmGkb0^aZfsfxL=8Iv`C?#M21wlX_jA0;?ZjI zSSTH)SCcc zY5Hp!h%UIdKgc@2N;e`@If+0q_Uax=N1ud&fOX0%eWv#UxCi zOWxL0YM4>i+p<-f=z%n22gQ?wxHmsdfIxkgx|5+REjMaGy;^`*s%q1{aWc=m%i85UKa^xiRy#PDChE zr)_`C6j8jSjD9fY2}k9Bjul~E7qmFvBRgIJ+MldDhFHw;9bHjd#E(>*oV3WZz--B`2RbYL$jz!3OXB)!*Zp9> z`@#M*kP%!87MNQ_n3PkUIO^lNSjKd}-+wTC+aSd{P_Y@WF3bK9E&XB%fB*E_QLAbb z#eaA7#KN5RA0<$H{`%dn0cFS2kb)ud4?>%tP3nUqceoJ;Z8YkBV2MZ6hfkx)-y=La zERewZ+zg42BTr>nfSW**t;}lny)pr*))E*oJbyGu+L9QD=FaHYkV9K>q#Y{UonLMR zl;^Gm>vsewANS}=xUi*!i%z>%?9woXlI)5Dai^|JIL!_+{O1Ol(&%JV{U5+C31^;wcz)US2|mpWy13h3zKQI21TYROefbL$AHuIsH)l z%V%)dZpb{NDW&Qi`InJ}C5_nY?cN4Ug-Kj*;d~I0r2#XcqKW32gv)Bm;^E@<1HI0>0K1h0O#G!pP*cax!!B?_z+MO#!iSy<=%%dQY5A={zNKS4}dc9A~jn>JMq1P z?2fVv*k;O&0be6U20V&9E4{fqZ8zDZfNQNNGJ)RA5${?*I7l=<^Gs;9Q}3h&kll}$ z>!aCI@XfT-I-TThT+cT6D;P;MJ@0x%(uLoSFLo6Go@srQj;BBt7PexRUE&W(7=P3! z$N|8|;0$K&G09+eITOZbiL@u8`AXQg)87SDhRZ7Qz-QEYz;<7m?9u*Vk{ys*B?*CN zU8~MD=i6VUQj&bn)t7%N{G4xk)tL7UwZ4QheX~Edb0E{u0fAojK{gf+t7_>)*Xwnu ziXT1g&cF@Cseut&P};%=hwm3Si1iG0kxfX588)uqJ&MSZc*xKJKW?u<>4V0;>nH zJ>aC-aL0;?z%MYqb7d>iuu~}7g`-kP#{eET z@KkEHd-qJUl;AH33NH2GenSlIy(H^YTmMb{qihEP;I{sI{?>Sb^zoxcTey9okvq5c z{&L$MGFa{APi{Dg`$XGMd{q}<_{-GzJWW&d0uXgNM2=V43-yt3MR8jG>#$4w+ASYJ zAT;OOI<^CSwx$$m@wiF?%C?NA_5Ib#7S@S1bm14JHB_MA=Vw3l;Ufup42eij1ArWn zg0v9pSJ=;-Y2q7-s4-nE{)Wc+5oT4oep&n}pr|pFjmX0%$!3~o*i^YUydhE&KUb>z zC30q!;@gS1aNrkFar@7oMW5W^Q48_wQI`}-P;~Hy3nMJF)Z*w!1a-g;%OD?~#c4-$U|4@H;&8&J3tiD z#S5?yH7CusggFWvL9cq(&0Am{MsVQp7@e=1Is}wTK4a znN60Y$RvTLp+hrru6}pE${W|Y?3ZM?4F(xw&IN)`OxK8T-QhLtig?DOu4v|x;6LuO z`FozHrqglN?)EW!@*Lj_d3h=C4EQ8AY2y6Gj2+TD3zdJaZ8;btw_q`4g#X4R!)nRa zs61&hmL;5bjMro9;o*h0Rp_;kF)p4&`^ICKR2@tp5C3Vwp6Lf;@`g30V^y@EUSvx) z%l|pjI-NB}V;#Kvh3PF#UYqaLuncl*_5S#%SdS)ZR^jremJ6>HqtQw^MFIHu9yinC z$pX80THROnU>LT!Tml|Wj_c2l*c4lgtLhtOTRu%bI4G-rI>~!+?c%X`K(bp9@5BZZ zga^lpsW2|^+oP^v-yJoH&|=xM99SuM83>#rda`NFHCY-M_jw&zJMlax!`|-v{I2F< z*pkox+EOUG$B#OJ2W42CA{{YRO1{=<&gY@P$PUo<9Ng-YbJZ2N{`KLHxZ17l4RbR^ z^4S6%>^q8m{2m9vI9YVVRH9Ey%f|w_GTBjz2YXw+dMB48)_`N_Tl$4CNw;X$W!Vqed)pNG;SmJFwpr}78 z^<`S>Z#;M+AoBc+`tB3`%$}0QIxau?nUo4y^^Ml zFbC~jZS&b8P`gv(7K<+ml$IR1Y85?=d94BGIU-Bw=D}s zsek-gsBBT5G-ZfB$GYkBu0|4P2g4ZG)Had$QAz-^EP`t_WXybn2$5NoPWpM7RKm3g z^2S^2@!$i(^_xnXrGzXln&XRwPz-Ug(R0Io>M9Xk`TtBk=XWCLAn-zT74%MlQuWYG zf%;Ff7Hhv_%5zJ^>#*_~_wcqqkwQC1M@o@0VDGSn0g^lABPN?w90&8MN|Tr9cX{J5 zV)uHJzYv*{RmHy{I+e;Kw-n|fG_S~&?r!wr-@=&a6^+s)rPRomI%kz;V)|1eftJ4H zr*YvI7p=+E(4-k)wIqU_3S-*Qfy_Tjgv6qW=5e>IiL#N-{51Z^2Ek!zX2~odK0J>x zCzdfhV#c%{ORld>Hy$IQx{pyaAi*A%g?W9q7&er4 zfwb%YQN{D-Ju=}?xXE13FpVrok9H>)oX-cZIzuBwZ?1Mt$Er(iEL|TjBTig1*b@I$ z3zFXf1yL3JpB7~H=~bc*Y6irD{AS-USyS+NDFj2{5ds>{e4Sb2OdeLZTyhp`Daj+&Cl};BZ)xLh0@3)jHQUMbS>%7IXsQx2S0N*?~)0I79`@V@#qscwO z4E(AVx)v}}4L*=2S$MX%zio+l0S=zN@3T0sWIUvfz7@w}VLlsmG=H9)I0MAmjbl+s zP4@m}#~I|-%o7=0-f8N6bEQW%f^@?a)$;o+kCD{%)O<7bQ=Dh{xZF&?X>j_HrSO4} z?s$LT>(os<98yV6KnxALAz0sr0|cLGxGZgKMTA!MAD|TgJ3pVr%KK$&TjP^86?NK`VNAer44yp5D02_OGMQ{&=nMSM~GH!aQ9v$yUDyRLLm=;#4GX zYkK5*hNRwm=Udr41+`BE#DKszUh~ZwS3C1qyY!|7cv9k4hHin?W!N-Y$5 zMmqfhpGJS5+CvkdLB7yxcM<6)gZl%~Ye90}rs~M4{#>+g2+*JP)JC@Aq}s8b6kfJY zfQl|t`qDqT*vuFzLmU3X4dktsnO$fmdq&6eKbMM;w|(DFWt#bK;620LIN?5JG}qs@ z;hwgH(gKn*fnPxUZ@o?xIywJ5Tcb7y7f1mW>5~;drXJUAtBRB&w6VS*Y%|k9M(XdL z)XS6DovTn*;zyvmc&1?F@bGvfUJx}&+X%hRc8bUr`E1PuRGg|GyqXG4Fz^+~GkmKt z#M65S zU-qbAN9sOeG~QFkzG|p0p;g68QGk*eR+cYe-(-Z{D<7S}7*86z(TA|HiyFYgeE#nZ zNLs6v!y~)h_vsBZVy9Ks{FLRMsQhkHdOdKc3BJcsQTH9lx5HLIDJp%mI!J0gpef`5qgMBTV&oA;%hJ9=9@W#_>< z2d@vucE4%UwT3m`3YAW>aOaZjdyZ_APu1y4Qt5kc?eDRTi-IVsvarJkJjowBmLD)a zIcr|M<+}oYSpv!^mf85E1h+av)(dHeG_VDK-SH9i=w{SORNtOlPSCpGtEib&%NI$b zIL*r3x8{8j1r(+BBSlYadV~s*R4OKrYcEmoD(veu?rJ@ zt%hpFH2Vn0!Pn%>3T9$u5l-Qb%K_|GLw>i%4W+^PS-J))ChZ<-wtQ_`5Ac2+%RZ_%a^uZ^WZDN1i~qFntxCq99Qbrp`Yipl_-7R z{T7v!v(TKmv=FZz;7-fM$#@^YxT+a3lFA=B=#7da@#>cDO8IpNo zoFl>}!UXL?;{l~x#CT4xa+*;F?T1&jGba-zsD&HoPd zeU*#tT@e5D!z!V)V)j7}l54+>^RK=sCHhGetf7q&UOnq5>^Rf_Lep`p3(fGx6@+ZT zEGh0aC~1Gg0>YVONXQJxBe=B5qL*LnZEt@ab1}pEaQdk4{orF&Mk0HhrF1{j_j_cr zs5%xfbK)|U^Vx&1S04Myo_>o=FEPNTw{t`NWIRr!I41soGU#_sm(?e0}uryCwfP3$p@ zq27eB35`&D#}g5@e$fw^PBJ|+L%%ut!ewsinJgR{>BH++td^`qd=R;!jbvCGl$-d#^t*!c%jMR*_^xl+#*+f$YW@dfb%xd(vAMs}km59@)y6XWu^o)_H zN65}2^~htth(pkvV|_V63^JS)!Zx#4GmgO446=XG9)Pc_VeGe)7^O;TO~zVe7(Wax zGNgC9I@OLM;$*)3cx6F(ZW_e>GUK&r&Aa0vP*Dt8S0g=oFrM}_RLKtUtei5>qUvOU zls(Y(Rkvj5l{EBp1|p!l_J_lG%77>8ON*%Y+-Wv`GXy9|=X+^sCR*Sd!-EC0 zjhO*^?D49w-x)8;F@u?VWqsT0m{uli>gPhgIrqfwe2QrZ94--tiP|VAu3km5wRZhB~sm{ccC4 z4i`n(fXtx9FvW_?)_vo8p~!RkPvIWNNtCM=lr^l=q0oe2K_o<%jb23xmUNg#FcA~W z8mLPdBH_mHN!9V`wFqz+d*4}zpBU$Kq0kuPEVn*UYcq0U=IueE+Q?l`mA`gktSGT) zK}=9Hv|9;Oh3r=ztQ!aZ(2NHrl(*O9?qXG+K(cB* z;Yh>Bav>ms5#LrX1iH*X0FVVBrAK|2u$HqS_0N;{&a{RimSO zL3KuM>~Wy+u56PJO8+f1cPg@CjBhg0#Qk27V#eCPHV^`=GQdN{xj)1Q7{2K9oDP7w z4n$&>TC!*klf9su?mTe_q!BxOYfevhXKW**K;nIN(h^=-j7$=e$~_yQbrsg{g1=X9 zSnyZcsV#5s9q={Y_AsWyUU$2YxolT%8rf4bxAyGB>@N|w_3#uevb3boh*1YDlMzh% zT_1zbeAYJF0U9j)*=vf-KQu0^ce}>t&TkhCmli|%V?q)mt{mhzZBS#D=-yS7P^hp>ADHW)^3|Q$(lw@B` zWgVjKJ$2ui3N87T0wQSC@^Fk*s1?a?#gO0#=bF?d?J1Jm*&6ELU?-jo6jDn0?FTm@ z@^>^`?tQY~*wiFAew5Zhs*K_0`43l@w4JccxYV5Hpr}f`{%ygdAEk_21;W;O7)&_v zB^hu7CNq!zphlPK&YMjLsCS6|cC&BAK-3&@wO#FUVhxKp;tf_|Lyl$@jOFS9dV|Mh zP6bOHZBm#z`#ntXHdAUh9qT@9v0!L3v~vIK-?<$?rA zrKxges>T9FqrauFd7(xGvcP~qy6%ey;UPO4@M~FkZj@RXk56~CwCnQ^a zC~o=YB0Zv(cC+SXgejoJYsVL*Cy(0pTg1Ng{Cq0wdkGW2=PRG-tph$%CtkiviP#=i zOACOsPC`EJE6Jan{Y# zf&mJIQO3w-`44Vu7l0FG@sN8of88-sV2n?2on)w~%57Am1EY7>K%PJjwr!fVB-?yK zOO#)q!u(OvU?STL;9uu#UI5tfoO>xdhOpps#(FmkF{KIz{0Ksbq7#D2NsQQ*Gp+iPTL zRY~r-p z0+8Y?M>z-2NPM~fvU$1poGf&CW$<<^*#uo2h}D1^csyMUkBVx^a#iBgjmN>_QeR`%;?$Fg5W{yIfEpwAwLBC| z()Z;U7;)w0ikc>aRLC<2yK%A4Cu&+zBv`(mN42hbbMA3qEV@D<{F_dtfg)eqDEJAu z;u1ch(q*ulVk7_!=YGqf&P1>JWK6&|j4j`-^2H>^5}Hh&{)Z?+rEI_^v+3}L9#npi ztzl8J@a)=>=n_dx*+yak#uVVSYkz5>3y)&g?W$)%2>9C-^O{c0lWU#x?`(P9L#mH4 zodfgVKQf}TT*o%R^%MQ=S-@I@_ttu=LMw6I ztwYnQO0CY-e!2|wW#DLa>jq7>iE{u0Ke&xTjgqxNb1bojI+7S#myTtTdLW{krQ?&z z4)nwf<&jP7jkq(EP_7)J4OAAqn9|tuVq*t}Xrs1nFKPfR&=yW2c!m|jSwC$HDSLA; zU}iOSYt`uOVs~>!-Ty4T?Roj;c%f0?c*V@PPSuLY@_oQ1YtXtc`PY)^9kUKjH4IF} ze<{vV^u#2TS%gL|cNfwhF@5w=v+?cgk!BA#Kw;{0a=qHr#RKRBjp~5R>4j~?+78e*XC#v2+eOP;`)30PBQ9uz;E zL=&wcxlV&u*&9Mxm;jL#{N@lSz_VYQwu7G>>>Tn(>5$j11F&TUzEjh;}~{co(N4+O{X0Iq_H8{u3-^dd{O)4_Oo(> zrCwKY-~}}~+~V+Hw}J{HwoY4vAqvue-VRdl&F|_)`|z%+EAL1HK*a6#aScRdVn@>^ z9tWkch2d>>%g}@!Y(*&LesOE`>8Tbh7p(_?B{=`3zqfp>M7#^LY6;>35?577Mmc6c z0Z6#Go_lU)_AiwTb-2dyl`5cZej1yh3!j4Ur*)#D{tQe^;4E$9R;TkYOZmtaagASE zs~sofU*miAikgl&bT`SVZb0lzDJ;ub9mZ-2-h;zUvm&{6u1$}G(Oi3X4ku5aAN0GN z0RJ{6Tc~nkGtLS+8P@M+Hda0lCY83IDWWP#3Qnlc5K;ldKP!5%4NETRz4ONcV^~IR zy2HgX2!H8_1N=KQVIZtu28mm$LfB~(#!1pZ2X*9%%5VzSDop`_{c5%t=gZ z!Ka9W5YALi1!t%{X+$Ep3QThENPQIKpjcrO!@uz&VdU9-TP!zCY_cRvm$CRm4bKq% zJLBnY^wrk7TrBQ;tdVFnP%Z6vRRLg+M5YWwQaH(5b}IE)u}bu*Fvb ziC_j#EuK7ck4iLd|1**@$+Mp5+gUU}gpvEo4+dhP^0Wtyc5*PI@w(=_Gh7^kf|scH zod;EB6Vft=w{Tg!pW_RODeQR-C)NsW8inBFkOY|#f)?L<#BOWqc#Y6Kc3^Dol3?tD zX3V$J$Us;jU%i!4Ot~sO+@k4egQ2#q&$(R{nQY=tBhiX1onY8yypGjqhQCSvgJ_)5 zhQJaC=jD z-e&HtC78aJyZPUWAwHZ`Omg#XKj;4eut870H=H1T_~{>aJAb{JG3b7%li`!97qW#) zu2|Nxd1SrLo>8s?VJ(F>8sa)2WU$S%m-#|fMk^rRhus+>=8L1<;n_iLV$e!bnS3l%`Ir^61<36{0N(-^=|S_P9MASN}672)d)JU3UWPWq3P z`XO{E%X#_v=fqQ1-7IImYp2snzEoMx$K8hy?XP~9QB>%Dvjv<_wg%FVRcz7Gmt8M1 zs;=lcS<8|qumID-xF7C(DFgqpsu!fRoGn)N8^v@+nNJ2&oDlf-$@6jVLCqEJKmN$D zP()Y1{z}nvq+O8nUANvk#Riy0{GogQA>TSirVck`j;3fFa8E8NVtXi68&9|I3zf!l zI@I(6lfw4w_WciV0WnA%HBMh>xstJ*%_o3{L(_&oUUQG!@jY*H^$U{Vr!Oe-d@z=? zB#t?J*Szkxzt{A<=WK7^|5$6CpmktkCKY(@*{iSP82d~?fOCUFPueGIOi`^i7t}B=3l-O~OVu_?v7Wn}Ph_0NaeC3R z`DyQd(7k*A;~&vig&-pDJN9xil+_$+V}nlj`t7*?Fn#-@@o=kU^Ve^`N6ab37OTzD z!Fj!XtYwScyAKQ*$(!rNpnJb((?QnWJj5W9qG~9P_9+0SH@NeJ$=zDJM@GPSMHNm7(?XwrEo+p~oC33ckj-fNhHx5qM%PCQ0+9?)T{CfMe zb$qc|PAqdRW#r{-6zxKq<1O;ugwZj@qRa_{kQYN0T5%jFiRrz96Q(IGhrdc%&K61u zm1IlRI8NyQ1j_?hFtUzWj>x_66v@TWUGSjYyIeveHQrya{BSLRtdI zRngb08BtyQQ@V!Zgj}(T78K#Hjr&i6Af-4gPfC@h@4Fi)est4VR_aG#;I0-^f+sU` z#j5LCDD1mHJk?sq{l{xfFYKaS@BRvK9%GHt^8&dPa1wbDL|#G46+l?ubBk3St6oLV zA&j`15tE&4Tc(;TnCrz}CQZ=^Nt)TA?=_Dv0?#Xy;nCO{n^Esx)%M;H&}+=EuJja zunE<2DFV>&JVzAMrCMvXoY-4~VNxO~V8El9FHMJ?TKm*>wz)z@OlLSAv6I=Tw|DNW zmoqI_2+)dS5tnKn+uOCCD?iH>UQLq-?L(I1meWz8(iGC^(BDt%p;Sw;{1$}V zbnE1DyIHY3BBr*n3c`R+q0omPei+_g{amWH7=|JIBC}FIn2maptRzu98KB8G>^@w+ z{wDBUV>Qo~YMyPQxuNIw+9v2@NK}TbN-Y2-WgSWhijFBbr#;6;a=ifaVDIijTG5Q< ztkOK9kiA*F{NlHN`M3YNRBPo*)!ySZ0V(Ekr7CWT>~VxU5m)Sr_IB&t+_#@G6Iv^^W7v#T+67mj{8s7 zX+?`5SZG7}S*ilwFG$m2SJ85^s-vDuwC(oRh;||NFf0c|-O+{bIa;pNxqZj-0s#wN zB9&Cfk5QB|{imCQ)8`K#f65SqvAJ0@DMrz9VCLYH>>=M6N2wIY5VrbiKBh?)2rw&> z&>)=(=u;>p0XPh(QmkGmp+kvb` zeKzdeH4e{`gu1`_x!yk6?Sf*hMVN23An^K6w^+*M3d5%xLCVZV-8e}yipnslYU6M< zpJ2bdnCzo>@ecEN(h^~O7jf{-Vlo@|kIp{Xq7{&|&tBYr{JBu6k9v>KUVpt=&-eQ6 zv@BPf#}8LOHxADpuHO)3hsyH8c7w3BZEPmJ`}Wx@nxQ9y&VB>7nNP`r3!I|n!I@4g%g43163u?c&3RZ8Q{4bb}- zgzxeF$JWIsgYJDC1bjM^FID%`TojSb)!D0W$b@@m1AmO$9jPlQ!|q**pkVZTaX(!v zHxGFMGk9l<3$W+HQoI2zl#Zeua>nF}J|3W{zk^dEJbnK8xOcxCc8l#3lxnu<$fAt5 zUBCGJw}I!)#=XnezxwGP|7V(}pMCO;u~~+JH-j%y<^`TgXj#$l74cl+>Z$`q?$~Im zxK_4UC1R{32)yC-TTaVniu6|pJ5#aAvp@W$LFssb2E9mPpjH~@3eflR+~ozZ3kPzYCa)XwL(VK!qA@& zJA$Ghp3Z=dUuhiTv#3z3p^gtj!gk?H6Qzq zgG*7aNT5|a3Gw3?E$V2uuf6WI?gUCvB4JkpJT!`$Px{1#>h3#EVp?8w?IC2f{UzWjRzwl0@3C$~VhGsSdOZE6fLv zX*K7pm#vGJy@wlFQF&feb48*Jwu_bKayd?Clv(fL;KgUS65B>b(H$2m zu;cdK56}YxY_5}p-9pP2zyu$41p)O-En8g8M)^{m6Zof_ccp5J9HBF#$1AOj9T(9` zvi252Mp@Nizz`%w&n>1y+gKHAZOg!+pVTu#oF}neWPI1s^5y?OPyf{;%a*2Rf~MTe z&CJcU)*d>x-bZAf%&e*`L9)qikQWUQ1RBKjU@#Yr8O;6sqyhS(F@tHc$tJs)S*cDQ zwe=1iuC*|&&3y1KFAh*BR3Y>19Va5(Y_0Em-{&!Q2QMeLy!+62`sH>xaU45SD5aDP z_6eRHm|C{cL!Ue;;lO zvEeNn+%hzyWb^a!V;qP1a*c{(&v)?~CJ2cHFQpV-z|1cRDmJy64TU7!7QB$0j~{Ez zW6QwSj7{*sRe~qrVIpN>j(A9r=ZT|^Skv(vpUsy){`3bq1*%CVUlP#Pio*Z}@a1Fx z?ymr@EltrtiKR074jKU$Tq@@N^G~H(t5B{5fxlf&8@;pp&u_~0_F=Q8Wb=h`>aM`#Jk~FTiyFlKjq6c-*Fa` zKA;Lok)aq&zlG%6Z~sfP2c>iO^eJhG`}s27g=7(-q_cUH2X-slG(;IUkW8+$Sx!J> ztTf3P!p2*c$dce=w#)$a2|tWN3N?o7ql=e^>rlLptBvkvHAPW|;|@4;;zGk{Xm(w8wu6!%-U4eY$)XmD&w=BoYN*W0VNhWhs zDnMzZs%_Vo}Fo8QSiU8Zv;FLA9MB z+AM9eY;;fY;Lex#6qU^v4}_ETVqzG(-Fi`}br8oC#aioxO>pz^BbVS!U6oRb>o~4! zDM~IWODxN~L|5*62nQb!-DFXVC&SqNqx}{o%(yLO4xy1YzJ?hE^d3&Hq1wnpD9ijrPd`5kCCA z6ur+CD<1LCF)T+jH1>+R1^_~}W!uK#N-s)jSh^WhJ8V&2ydG!ky<~sr$7vQxB_ku`@O8OL&_P?B1wUodeTql^7YQ?V*CiQaIP@8 z`v|lE9Dg!Vp+!fRuhxq(%JlP5t#!1R464nJW1(uio{!75)_OUWfrX77%U04khQ?z- zLrxvz?R=r?SZ2B2dH3CKlBn?=Z&s5^y>n0<`+=*Z3%76om@1Z876-NUwBLL38aEf$ z$(5?B>7Y<)4DUa;d*{2&DqpCs7Nc~wFn&Pt9Dv$AcTb;gmNSG5VGut?r$yKB{GW|7xuQCsP%N7( z)gqjq0+vl!mexIaN->m%B&y>3eyP?3EJczR)8TeGrNW@t>H%W5r!%>t=i0blOThI8 zfv0bmNh$5xNb8Y_X9wrMz>mU^qA}A&4u{6ucDG&RidBZ8g(O~}0a*nwEW>eFT%f5n zdPt+Bm(jN?mvooa{>|yn|N8bn{YSc1qNx4p(=RdL-0$n%6a4MIi)5xKqLraRH!G*J z+vQBbHmNHl#o6f5cN}fEP9%5-upPEgtQ{gWzH1}&0%~mn>O;@zKKlyP6x&4m-+?2R zOD5webdj<%FdW%ayVbN%u21{dEnpJ?p_&gLXqE-}DqA|}CM_K`iT?G6LnY5NwJ45I zX0~|6wnl$Svcv&p|)A(i?#K9424|( zzR`hPnM(+ZyH6QHi3Kh%i9J8Vu!g>^cTPrEZ-h+F8;!G1o&s70c!0I1;*^pdJzPbr zS>yFLlRy87D&~u|wyAD$DK)g&!;J)ZF&e#=x@ny~UC$@ZdY*0e05cGhmZ>IqQQgcB z6)ZrmIM&crC=NG^2%B&d3G6sdDVa>6OVuelMkU)%wl4BdTwyhr_%XdIE^HS@n7W zsMLC1DAYJXh@)uqcqK|ovv;F6#dwiZ$);)nyD z9Mf&nHguWLxMc!2`{f+x&G#INVRU_y%U3Yw-p5Hv*%EihZawcDKhd^mhg!N0Bqqab zMvq6&zJ7T3=X|3}o|%TXnhVA1o{D|Tq&SX>BPo-Iq#_N#R8p3$_qSBHEXk<~F$o|L z-s-Kf49RYmQ`fQ?w01$$F_u%g2*4x!k}7yS3_~Y)5hF-c?eRk);$2);BR}*4gtu|P z$P!*}ItRkzW<3K^gJyP!I+$D{!GXQQ_@1*_%-~n&g4bKT%H21E20?&5fojEg7Eg^54Bd0;keCmmd%wsTvpYCzsW)kt9&?ulR8(9uYd7(NiiiV>2$8hviJ>dbWd>?C$UAKtdmk4ho+%o zIFE?S4nDRx?wn!=shu?!XB_(13`kp zEnMHNOSM)iohy^Mi))*JFBQtgN+X{y>)TZ-m8rFlwA~6e3PN$!H_N0bYnzp2XbAvP z_)?`VrZOi_Ud@Jg@FqGoO;MA<9WwFQ&&a#=g3Ren9J7$9**mt0kqiTsiDel#@4uf< z`+_7wR?@$5Y_m|QpFaDNO>l)uWAtzxN8vukBjD-lU*y2p0Rl`@0c#7P8w4gVU#j~) z!p#wB>1DFTt9RdG4n!J12SINtlS8j`KJ1-6J$~}~@S?4EPWEw}hp8Gd;?-!<5bdY+VzQczMh{ol@4vGQ4K$=MPG<|{T3bkh-AU5kMkZGzd@ciJQxl7w z_VFbuVlr_1ayl!@3ZiIHIJo;b8$S}zqy+jZAwByLfYZA*c#DaIfcrWS>C}@ieq~$w zA)Y6r7K~W-P*62z~8h9?t827IaZZc7nOVwtA7x04?xHTBW~2KEKmAWUtdkI)V9`t%U*&pxvz($_YZFcma?fmnPv$GNOcsx8o=jVO&*3;^ zu`pG&t&19In^>myG1T)7lsZOJ0=mNty%A!#AK(pnU9N=7R#c$eBh%KNjYY;g)%;XC@D&EvC@Q9 z5Z%osFC_D&+V%Ip`}pJULA?Z5n;t)0Q4~EL+#;7x9&{B#`mc6RTE~|#oXGN?qEgvx zhGh1P-G+)m*WSm`@b2?&J%_`{HqqyU2d1cG^5BHRHiMeo0klukbg>EwWR3{_^5yDs zHryCA?z5(@EkiT39oW{|&N9`cD8e+6f;|Rj1tlw` z(v^CvdhtrvHqBrBGMz7S37%kQ9F3^B4lJ7eet+PTGA!t*aTH#>{F>vq#bmIWj^YU3 zhEzJsv59oHn9k%6J$`B*I|O#=yY6l|LoPR0T8tl|sjfC{Lr*05+4xaIb5Zw^Ki*FV zcRC26>}o#dB}J4{DJ8R8&6P}^#6+QsDOMUvI#;YV;M0&5bvn?I*&JK?&LNnDG}*Rk z%Na%h47*uOSv)FXv{+6CG_^lWwRj#CyVYW3?6$c)l5Y&l?&GL^a&ahz0S8iVT9%&R z1;;UYUeF;sVoH@p6b6YDieX}}%aW+@eDb(iP69HRhgP$DHhH+_TTN;O9HN*492W4I zbOslsN}c1lOsS@AKnoD^WhtfDCX&hf7++o{S30?P8HK@WKAJpy=6S()F(4NR{Ra91 z88_|Q?|&DCQJ!447?wGE`UMW4BS<_&8G|HHw!nA@;2PR(cB^^lW5sHjx=Aie4sF9)~TLOHfAhGEz5-n+oA$gGeg zxEm*vD+WF$HThzV3IbE#wt8nNC7VpjIMinGpW3ED?C*#bZ6q#JEu>f!<&u_eQRpFpZ@T_x1N8!UC$YY^61GNJ}^K zvFF;W;eEE+V%bEB9JSkD{F2&Jj&05FJ_4Kt>#H(;xC(+m+blfSnGWu$LOzwwlkWR{ z@9gPrJx}L~lB`e=6;qW)7pQboEtG0dB~9VI=yXq?CitWvNP-|maa5=_ z*o4r8c_jVAAO2G&U)-&rS3JIaiSH)SzG%B8DeuGjcKZCQD28#i(L2+&E6;N`tNCU* zqxRI{m(SGIR3;A#I-n-$D2^^({>&ohCrl2~x!X@a;*A9Z^E?6KL8b!MTZMRA29y3Z zfyKf@lENUULHdzm_Y9_Y0pl021^4?s9_Y47@Are7j~thPE8esFw;%n$9X@=H3DA>h zeWm4m6o&q4hD|Y{KEJekx@+yZ*8SC+hpV^hX2J7GS;3G1`E>#g>YhDyZ8KlN z`P{@PpUT?KN?6vgZPB~QLdQHmonf~=sYiA7{DdSzfNjBACp!$zJOe* zqHR}(x;emY(z${HTN7}ErlB@_XUplRga*&~VmcVzeF75=TBYQC+9yE>J)18pne23U z%O(<%q|7J%C=7n_xBsfuI|mY5NM^FdPjCJ(xcj)<%wb}m4p;MG678rYMZs}{GnT0j z?>`Ys&UJ)_R+8+~5+pT*eqreQHy?i3ET>Sw1b*xIV!asWO4UN8esumKDI`nP*71{< z9M8Y{=C83il~Wi&Rh!v7R86*_cTS$vTgRz%E?26hGFfulW<*K)=}-T8yPReV<=uM0 z^8!Xq0E(etofO5Rix8{cC;ROMq72WjQ5d?X?mCtuo{GS$*C=dF#cbSZQVR2U zl8wydF&oYmE0&2rv)1e$o&zX?L&XY^Xue!ULf5hu6WCtM^-kcqxk7n1dhi3U-a4Z8 z`@kar0M}Vght1B}ZnJp))n7bZzw>d;=;dn%aNRPUTb@)GRbli@XeU@W|s4jq3>vx zwhSHpY?ciI|NQBfrAp)QeMZtc1-vqpc4ueHG5V09?^FA|yPR3-x_|YKP4JEG2@%tl zluT~=a04A4azH_rv=MH8`a`AOdG_UBr1KS;VRq{Ui%AxPZ9L0CzT~--kn~+=@ae}8 zPulKea93?~+rR!xh|GK}X4n7d@tYq1qsHCM%hgs_o;08YuAmhd=)3U_B?Y z!bnb~H{*UBMxp0*P9emgV714hyHanlT!PxuhOTC6?F7%afB7qd-~>t8BU8xjdI46I zl7`lx+$dFAqt9>R5V^HDKjg~PSy*Ka^H7Ue`bD@jTi_`14XFD76`L=iF5*}msa2KV*Wu^=E-PJS%H zifrd7cqF9x?Z+?-HfZ8zIgYP1dgVq}+pdJ9SSVpa>UmD%__9!{B@)7BfmCy;*2T3@ zl+~+G1hQ$9s^NnmN>S)jFjX6nzDE(}M6Ofso<(R>ONDX+m@F67hjv>n}pY>`S!skCXR`fi;q z0B|xM+*TXCCqMf&WQ)YPM(TFZXThA92R6+@YOa*Yl?yLkWDBKz9HZMAgm_$}(w=RJ zsZ`_SNf>yJWwv@qrJCk8Rc|?t#qg48s!`}wJ7-{tGW2#arN92S{{t7W-zooozo{|T_uN6xES|0t6A&l91ky2OU;*RE_N}; zrVg1=I+L4^9}Cr%v0D=nAf73fsjp@uC0k%vMv~HOf>XE4dh6)n`n{y2OV#FLiYquA zWSC6g;#F;Qck9LZi=V9*AQf~^pKX>ChNg4HTL122B7yLXlFh4|#l`clx2uKg;hm@L z*0mNqrX0s1;Xnc1>XOv~I=<>AjDkJ!BW93Xe@Ni9Ax2>^9}f}&?^+fwiu9i9oxd2| zekeCO>%|m4EZ?ovI-0gwP6zmECj&u}(%IscMCbG6+61#?N5SPGO#wBdd9L&Hi(g#5 z{f=STJl@b5%h1=0Nxgl%UQDCF&lG^v?B9M&ic+QCN$|pE3FHEigy*M&+eYsk;k!6I zefq`w?|)ZmbTC%Q=CKkrbyM9`TU~5duu^9YO_k)7oKj|ENCT3hG#x%90NJS6P^CtA zklEH@*qKNOzVBhsjuA3WjZqwq9Gek-w_c;j0spa#E7wc#myQsYcKN*n~o_+wASui#Upw#6^Et zmF(7w}Spqg!rvJjapc^nB9ig(S?o>Nb%`pzJ6Jh@xR_ zf>1=ETu&)k$1xXE#7hp&jsPu}vbJ4{a!TE-D$Op-a0eslYBoamk>|^`Ht~1|grRiF z@%&~vgES2fWjTah#Udf~`up#HTdFjcq#Ed07V7K_o5>cgKm5>WACvK(OVKF36wCE@ z-~ELv-NzWBlpiM*#hXo z_n*Nx*sdfcjbV(X(-eJ>Q7|+bpV?v=ZL{qv^aCz|DL&XrSix)X$(u&KeKfrPoGFyb z5RralS*G4OWx2$|)jJQt`uLF2Q8ERN#Uj;p>;sj5+`mm>x(@?Uxz^TpDj zS%yjyO~Ga{5dGnNpMtV zyy6`}Kn*<$2f4DC_HiDfXk;Ez>2xN)oFMcM&vZ85zy9#Wul~v7^#@P| zQ{W~k>Fi=Y+$?9!-Z{ClqBQx7zx!A3zW;5l)iZRJg2`ojTj83Z13vc(FSZ)xg! zQLHsV3YSv0ZF-JfuC`W-iDT-G-Wh~DwYG!ez{b?nOuk$w*QWj3FbZjk-tS|y_O~mv zSZKO^aycLOZJ@?-wq>-BFP76GzC1%qit=_b&R5&|ZdLD`*oN-8R`2xryWjuEWTqgc z(t(HL`0(y3Mc^uA=nJ$o0@>Qu#l@^*7(1+OJ)5SO2x9D32wJu~yZOLpatEY=kQDbZ zBDEyaM(^Y3k@oJ7kP&J8rHCwLi){EVIB&4%kB2n+2?v^ux=XPDks*#|YNNP?8wQYjPpZoP2V zi*NqhfAjIj-z%BIflzE}Am$M>*Y+P>QK)|6aFs|9%^xvx?A8lWL}y)+mF;Q~g~5K0 zLKmT@G`FjnNSLHaQQnOER2+7R*&tu6O@}x7W>so-Z9{{m9k~}fSE%eM8mtk_w(y(* z<-*XDQp%hTD(5de8xux`MSE?%7(@C2H-G{5Xb>cLp8O$IQ&&CL%9U!{<o7u2-bWT*kZlMAO7p~dsMXA+WjUJR@nWmWpFXjp*ZMzmQmoeZq)3&HQ zLW5%@(coV>i!qN59#jTmN?8r>t4HUH=}=Cm5&EzU%TOtr(bVOupa1Qsk3B=Jb+lfL z@`dVb^uTd^I+M2z6#4_#jpLAoEgo>#;lpQe=hST+BQx(f=04u{&R_VxOQ5T+yO@;D zo~LsK3Dx%S({KMbI-9S;;b7znrS*IQnM}5bL<3E6EbqH6Pg1zLz6Hy!1n)G7wTqp;G7Z>+P?XQ~DSG!~e)qtYz#{nZkdy*|RuiHIEEqo5|)A zJRo|aoZ3^gwqBqFLeV7c8ejtug*s}x2qw}DQ>-?06b*r(5!1)$I?@o9BJCg)6pGh$GPIe=eOO{CqdxHux6yx9j2$g z>z+RS;sZV>`GZO@K`N()PDVj|GLtVXCc{)Z%L}5mTWUn%VVj6|17Z+|+IFpEvm%U) zdz!TF9)eN@^JfUanACEhgo9>;BW5 zr(gaBsQkRZuq=8Wn?=3Z8$Mj+O11IB)$_0a3Nz_2N@en)?@xxem3jxvT|>Qi`Lq7b z$5OR1e!NDzaWXIswc6-vyHx=iF9W;#&Z%Xp7HV_pAn;On8=(zM@DW<~?3rU4gNIN1 zc%RPY$ph5>`LF-QxPNo^=_knB8O(SOwo95qlndGYREFF!WXm)_=3zP9DZ$rM1yM|j zDa%x=&EDYd)9~T*(=UF7%yF|jdc0Dyd40Fe3WDYkSJ}9~TZaoJbxmfdjmvHN@3zeFw0Y%!s{rK`{e`Q(54hXOs zc{D>3gtJZ(*HlyAlAxqrZFN1@x%>3f^RNGMcz;!_H14n8^iE&!LNbcO^#W`9M)%Cn zHZuHNYbli(+IJt zQV^GCIaXJ9vXa4?C4f^MRz*u!ck5iCQY5xif{od{{P|zorZ&9)43%548ij#nXp_O+ z^RNDL^mtWopKu9&IqB!h^;9~unvE?(J$?GcZoM!JHH8wJU>Rz))q@9-Xm`htH^pj$ zOW=Ouxejr^M@kw4FyHs&RGJqAb-Qv*pmiKV%EIYq22yIhb?mz4cC~o+<*&AzWjd3M z!f3Z!5ax^<1%U*CV(s&rZ%>}S#u)%r!lfjqJlEaFQLb1iR+@m;M`1dX_ed;|WtnF0 zd^sCp(uo`-24-N(lH_ZQhr?D7WiFA}t>?AY@p?Ya70OYB{5rVWsWc0|Fm^|noW;>0 z7ED|m2IO4iE)t-Kj2M-++gOHb8aS1f>)pd~kPIau#mf~dz(Vh~9LL5{EF_bl?vQME z9L0!nqhH0=8r?tt!~fPfe&V_oM5@Iyp2D{6I%W`fTq04ab>wt*v!3qv|JV|~zk1s} zdGg_h-*r!)f+t9`7q5P{TP;$V?1%4vUv0E^n{_%@nD=knxOiwWJdx6FGjH`Sw(A)@ zvRvZuY%ErrVHhqZeTulT>zxxUqlmHSUH?ERAvBe=eYG(5@a34$msr-MV(jbc!# zh~sdxT7^&$C9#O?2Ri1ajm_oD;G^=wsQK zlpM!GhthSb?Ve?-sWh_JYoNxEK;tnvYeLK?$}~+G+OBu{e6yTYYOOE~rUQiUiMA|v z_u&Vi>kE~nBsmsh-1%Z6&7mWl_X^`8x+g+D2foN0&N1zv^b7) zgbTNi;{$Ms!ilP=sT-chF)Hu?$~YK~5EhTAYO}L}OB;God@wNyQ*Z}6x}1*hMJY|w z^ak6xQc}d^@*t454b68wNlBwXLV6cb5M&GG1HW!Q?#pB@rft``LYbgQ*M!G{pbK)O zuEo-G ziw<5oCT|DVF#$ru!KjKnHxC{L%d&|4MF2e=1Y5iJ?`vOwW0{&n#K|-!2v|9S5>W=t zhKMW>cf|fPDXH6Kxz+++Z9b-nqLn<5alCVFb2_{~d-k=y#g=3J_N~xvK@Ak34#cqu zf|WZ}KqE~jilU^o_kuaHzX%S@pxr_&(N!?Pw=TSwc?!gn2rr4999KH-IAxsDN@ zlFmF_zel5h0Q*Eyo)7N}wWh9af$jjEVoI8(ajknE@9~I6>6ECf!N^LbM0nYd2X-Bl zTq|{`nm9Hgh~j+o$g-GbDw*8y?o+AO)_0H|>e`lJ*mAu!A3ySfXb$h&U;U-J1x;Z+ zABRM5PgzF$<f=afqoDTBE z8bMk)GVq$idi!WO8wxxm*-;d&Cxd*gg~YY2RGUZ3*yEM0XRi^6sbjuDKCCPONbXrI4`shD6()tbpSGVgzrG^~AbYN^(xk?RAmHtiZ z@(V&#;FI_)MW(sy06T@Vjc~SlzDo)c!CB zskV+xLq(b(3WQ|RG&DJtK_Fr|MGV`+wBB>9@#9UQSoM9MV-uJ)2Vn(0cz!atH|HaY zEO11LVCcbIQUN&>Akef;-ErVJr@&pvlKY-&>btK%!c#E+&rzEJ=xS%FuRXg1n&r`v3et?J@dg1xe-; zNnOLhgF`I7it-bB{Y8RCL5guT9i2V@dOW!K{N~&4$J2B%M)iaN)@Fc&JVqqC1c z{NecW1y1}ldI;or0TkLk3UzJQ?3`%3&B2!m*a)${*(OvJK!27hu5H2IRcU1M#m#cM zoQ+CVh*5b_gqpWpBbz?;fFI_C4LhMxi~05 zM!1{}$$3-)Lpt=8G&r8xZUuf~wje1PQgGy4$K(Ya-lLe26v6+F<7l%)fj9`$EQ52&3`(91a2zB(2d*2~G4zxpS;)dE6pOD|QM>UIe=uWP%m9frZt`E$oM?mxe69bI^it?pKm ztY}-rK)D3aX}MCBPl}&^`ct7?w@m%?$!oOe(pdxtZG)nyavjIn^?WR0k3?}CPpm8H z+34W_3krR&-Z|NA7G<)JPNtOG_dk?s4JDliL@b>_s(Z7fXu5myw158z?b!W(w^_8h zr-S>?xQ{{uE@2?Iht5!z(;N@eN=yu(;GKm5kLG7~bbpn}7cEnjQW+J+GW4jhq}r@9 z`C_r!eE9q}Aqb7$DSURh0!VqbiQojjJ?LK^_)btM5uHK|hR*=Szg%%}|EbnK7Dd@I zb^MAtRx&Bye)_4}>Uoak`+mK3v|Y~$H4Js|!R<%SMGPR7$q58p0CQx$HN3xy!l2nX z^E?~*<67(f>TT%z?c>Y!Vr*L$&nNSx3Roy}Tu^;7lAMhmPM*A;4)2ejyh05$TSS^v z2ky-yk#|W-5qeuL$b{l--^5xBH zMoRw~U=0KyD@o-Jr#hD9EJIBx*<1-}*Q>YRrnC7{r9}og62;KV*)W6t3=kIM$7?`N zlhW}1Q>oV3Q~T9?guP0x$S|zqn1myOw6~&U)$KZj2>@Q$)pR6-^oN_9@42YM!sJlI zyVlh96s4pyk5?aPhDK289}Sm&_YCjRC;&FcG54$L(R`bzrwJ6nE>UL@AYU}s{toqK0p>BL10RHWImd*i?`QgXkp=1)r zg-TKb9cCB%IB z^A}&g|KWGU3|a|;aCQ5k{_KlP9yuaF7s#ZL=S3p$hTNXCY(p9VH2wU=*PF%UaI6e{ z@KW&m@Nk{Z6`>E94$`H1x!OD!oil~NiV@a|CB(!C8Uw$*~-`3hEv(ZEQ_yW`j56p>tsWuthh!O(dl}7hK1*j1%J^m>2 z!aD5h7<58__gxI{a+M~zio{|{A^gM=M7hL)fX_}8tsbw-gfr_p_-v*K1z|q!XYys1 z<5shwIUUrWe9<|1^2h)6|5Z78iu^rIVcg5XDa)|zeA0*Ko=6568tpYMk;s>-SHJs@ z?N{I6Ww)9pI81g9XDQn<;7~7?ea}rJSPK{n5C}G|NtU5o#_nL7Y4$E=gFA|*q*NyK z5ECs{o2%K_U(TD)zFIFvuDYWIagS0T+c~~;EOWD(g{CHzs!BGu7(b>m`6v#3-v#d& zc#QgTKJ+~=U#iR}gFG4$9Kht5?6Pqj?^bgGmq{j*Eyi)Uj}i2rUcaLR0g%E*XSgIyDBp3EJe~unf#Ur&E7t*(49Fl!+ih8n6%K5!)vQW(>FRD7 zNAaH8Te@1RwS3oEYuYbSA%D%)l=usQ z3Q-g`x@Q*oZO56!cR7wdl{7pZHu+r;O-+$N*7pMJYGw+HgdLM#3g{ZkmNLJ*rTS^KDwNZ?p@nD zxqQ8x4tBFquG#|M6VeYi!He2bxZT zrp_io&GvnVgt0RbLQUBGV*{{WP#hElaFkNil`n8XgpQ1$R%M4evh#4@yi*_14j5Idg66(8rtf?+cY$ zDwP@De9V-qmZp(4h+nREma|bhn-c`twvel&C_0V-y&(T-Yc?M2_mM0sOc)^W1Qn&J znZ^!^a>T!2L;@qF-X1-E)>Wv5z)&k!NfkYM^6KY@K&@%$G)>{Z*1yRV%TW}hbESN# zlFgN}`Ldi!$NSi^z+TkVP5bCV-L2_8d9JY>Or=pk5LdjEN==8iaw;==yiO6q7uHx& zIJm#c=F8jl+(uKdgu+v;wcqcX-4hevvSOnH``zH~gRZU*v5Eswd>=zWkS4cw+a#MQ z-{nQI);?xgu3T@c>xE@NLwgvhhEd26#8t6^j2$p-6}u(^b5=@pR+3!zs70AddI5 zaX(+I@Vqd3xViiMqwl-q!*69l!!y_fsa^ovv+1_J0(*f@H+sTn>a%4pS=2}+<=Q7 zeds9MZWj7>4PdsRua}cVBB8Dqf&hj&O1+D5I+KS(cRHl@d&@MkdH6m6sjyLtT+K$i z)oiz!lap=@^{Hx8SJ!+p`EdPac=xf=Xv>O%a~!#mQ#4hoHs<4gqkFR7Q@XmL9GzuU z99_4Bad!w#aCevB8U~l(?(X&yG-&V)?he6&JHa)$yEC}E-u~|YS*%$=_t~d*)l)Xd zdn5KkJW=xq3z70_T6N!lctrMMMHq%_@GI=l_3g=z?CHrt?z}MfI~ARHNmxtXL}KF_ zZMVWS%VBlV8Q2?*S!G$q0PnVc^Gwr8UyWRsX6z3NjJ`8Bd^jW0aAEdt=nlXro%cNj zc~!aaJAg3n=eQ&fM)!VkS~FuQux*Mclb zMd1zH5Z<7sgn<~~A4u79n9a%kWjn$<@SS~LcCmJR`H@YZrJ{YGnolN-CCcOIeQ>XBZlnBbOLtx)McZC^g%61^#a7>TYt@lj$N=P)<73l7k`+L8_*j z2ZcjD>-21t9B74QnPZEaS;B9c62W}>8V^-I!l>&n6c_ovz0v?~>U|G`Yk zo>Z>Hn0&tJA601c>Qd~aRlh9~7jz?!1((>HE{2X^l z?y4`ls0zxD!t%*ZETzG282J2GCs~7GzmeV8`g%YBY3@v@=St=8hDbGJQ<|_Qk^%XO%b)d`pCZfK0r2w{Q_XEEG5&>E@B28 zng`G=L?TF%O$9G!4cfh*g)ckKE;)Zp={el7xg2GyxF_Qex!KO3h_k0e+zX(G?<#Ba zQxKLU(Up9*7?%lRRU@?hLeqM;?u*G)LXk{@9G5G+fzt95J{>3)?l|+!x7T-U9!x4) z;JY)F>}G)_jZ}{E;BHy$RGDwq^&yh^1UN+ajnscwflZ;H#TgS!VYK*N4dEV_AEZp|~}( zZmr(hpQl^P&Ml0#=+C3&j$WH!j?~t0g)u;8g|D18uT4hmk z98+KvrA)|T_WO-k>0G=FX!)SxdJbf`Z4aMS!T)?!+a=mNGa%9P6i89~gMKSD%_?Y~ zXFB-wNJkFadENaf%P=R~Yy*J=H|RD>{T)r_=W~ zU(1+*U>x%(v9GyO%ep$(&DQM$`_{Yeiybae=okUFbge3Y2yt`1_Q z4>7BfpNOu72yQ|6g|wYNve*}Q81igwG)#&&J?oM1m#q2S?sH#T|wKMqq8qtJQD$ zj#Scn{1+*_35$s>{QDcEIrhA4R|l9%SJ^OOW#FbA>>CLO)Uud0L7so$_dU+HZ&Z?H zn*$$e4IEQQ$Y{>Cs=gxqV2HHwz~(l?Ide0(>ba31__HG9<9?jIyKeVu0zVvcv9rFE zXKgc~?rtKd3X-Va$=mk#2X?}%*N~d#kClJJ-^!~k2{SS#4m|2c6-UbqpvPL?&mw$J z2!EQwunzwBV@(h+XQ+t1QKI$UUp<*|*^mLWZcIEG=zG%eVxa^5f-E-&?n~(5QrkgK zECmhzXxR%i6qu!GgVi~mIOB1-0Xtl?l5Q1ily1p*a)#cfn=4~39K!f~dAF@p=ad`Z z0!l8HfW`gCqvA;wWa+4&JtG+3P<>^_?V$!1h|~5Sdp|2BFn;@n)nYTD!=bY4Z+raW zFRc@Gre3wLBTI--P-()3(Nd1cR^>}XWSFEKC}dcPl`lE3(0%Y5ALUd^)4k7q$>86>Wg$5Eb-&)k5D<%3;BOq^>) zrtBf?&|P(lCdyK7ox;_FT~?E%c`Lb9M;O)opcW--)Zmk(%=J4nE^^T<(YKk}s-ATq zfF9PBi?zjgW7s|e70jumW$i{McecCz2Jx%q`@B}b)j-JUKo#}Fu5k75+tOjy@6~U$ zFvYb^`f5A?P14g7ofzB%T#SpEs!#A_&_7onpY8U={aU*12FW3-BuS)V`o$F76d!F> zd%we+bEtcJ8J6nUHpH``dA1u)qB}y`0rJf+_5B$9ehI>QPjlp#B4tFp*x5s^bMRXot8U9Twb`2d3%l#zdT z7H%mxyVR(bd7~r+ORKTo;0xhVB3Z%T`42AY9{>{0v5zMQ^zP61Q)hMa?Q4$Htw!ok9gT_LJatfgL?>d^vkSIUmzD{4$^>jN+E@fyb|G~vr46`T^fudFC zp0sSxJ}pYL9)LAVXrcJ*UFI=Z%bMfjxg+4^$eoQik!#vIgKP}xGX-hh}&L7SQiVG zI1%0!455GkzP6HD(!uQZ)f4KNW|;`kc&dH`BOK&*yv44McAgV>!+-H{nX8apxNeo) z52_P)+sJTCZ@+upJ4yxqSh)dLV+=@Qua}sBlU*=*+36s>q*n(gEFm%i5T2}7<#J$? zAGaA&n1lCaH1H0>Eo^@}x7+T4(w1q5`(r8P*jQu@Qk5=UN%v8@U#;D+;9Htx(lo#I zs~zAPuA4>cRHwV>ZNJik+^`chf@&!?>_{kMIxl^_=sP>va_BU(G z8o==3FMlGxScGDsNqN91k`xUBTRjARG%2>8VBXMlTtfzJB{G#F3Kv++@AUEAqY3Fm z57Bq$rV7Rk+YD&1LX;mr-ZHR;l~rs%XJej=MdO?o?;TnuWjaRx8{1CDhf|-&&E7UY zI7ElGiwUIJO8=3_QeO`=ANy?&jyP*#ozHxlWz zNbh&>$Ys_N#AxCbz}IX<82xIj6~txU3de><^!3?bh_2Crg%8@Sw~g*EeZaTLCd~dg zH?q;x2~HLv{Od`scsk0Fz?74mcw0^AB?hc?ASMy?Bw~1$Bh-|P1&3u=xYUGhge4Fz zWn(64=b?h`36Rt`E>`Ey?+aBOX=!yc(XRif3oJ{@B<<~c=-A#niM{*Wzg7%bKvf0D zZYXz!j!c_=9=(BC$~GmucvxLdh$@8h(on})8)J%NaDXAer0pcdtd;%aAup>qQGcdM zC#9#tEtsuzDU8M^dOw-DFWf_~I-67GMdiRt~ZzTofeIZrt^J}&{H2>9VH9BT=o9~>uj z9u}slxOI9mcsQ8`2NGMs23I?&r&rn&r5h~IHMg~`I2|xp9*iAZC69kf-6F)(j&_CI z%6DnPiu&DB6ppS9L(5MnQ&dYzdbH>0m-u>I6?oq((iw76ZC%!y;BfF{#Gbd8rhdIn zfEAIspe52P1`<3e`J>{9qr=#Zal9b2NsCMl654Xh(GpP5(W1No78b>( zgs(J>XXOUAcB=rUB%lH|$<*l}5y{q^osvd(r^}NJRpHg37H%k~#wj(<@>2e4Dw@hq z7OC_q(en({dGj>hEPfz^Ei}pcLy$6_93rIO;qff6BZKNvfL4f z*|F)&$ZyXY0r~(Y4j>j_&i^``?k9BOpu6q=8Y{_xguFfOCGqy*Cgp}`C_&j)ucsZzvzL;_Es#v}_>A#u-A**1qgF8_ z|ETATew9mjsJho%YY0qSys-xCNv?~TZflnU_XL%{T1Qv!-cA_%^1a7)KhWxQ&pR|2 zDsw;0mOtXX4t3EMp_2y~Jic`S%gk2#Zq*4wmF^KuH^Ij|XS)oDUFaWKGIM4rZUv zIN5Jl7Eu5tZ2ni>x&F^*Yp|%>J9wjpk5&*U6-0OZLjC|q1wx4$i|#{naFQC;ym3tx zf{zM0+$}GmY7K2f0H{)7pZw#J{L$k29hhNt1aK3(hWvhPev4XR)@{fHK0Tva!q)c~ zJt|%QJ%wEhQ(|wxA_zAmVj{?q2t=1E8=eUfAViQ|BnLI(54lc$92lQ3jBUOReT0?R zCXvon(J*hBBLtzj8%WASNV0Kf+6E`IHyw}H>m6zxY*w`{vY@=`()}2dC+OfLv==o= z>ET?gM1}@0&MpIZNenw*yts4yULHOGN$M)-O5$1A_<%6Ziovt9Ut)Y}BG>o!#;QIy5f|({@`7it{aQ_Vp^FUcUXwiH+nEv};gt(D?rNI_oQ1O=?W% zGtAG?jQZBDB8JkD!1|4UZ2A1EP3L4O99li$WKLf$&fHP^2AF^boitb$QHx~>;mWL> zJsyZAzfESEPT41>bc}HPdkK8RjFvYZkmu(O=&;hgKOLClK;&&aL!ot!Q*m*Cxjcb; zXT@^=#&r>Ja{(+H%e({fumz6sC(l6jE5dCr@8ntQK$MTa!Liu?-%aluguf1Kq=@i* z7$8Efn+fkTI$v@j)ZRY%>{YB3VO`UO9Fn&zVkt<|ggl8TMo~_&e9Sj1j02_``!lwT zblMJ7=l-=E`?SSKRxxwj`EuS|U%_AIflqd&DU_bHN}t+|Q!tqj;hVBgl%a$&<10FD zfdY^Vhv|c|gO%056z&6kd(bMa6IV{{paYZ~$gjsBt}|ofkH;^x`U29!bZ;kaRgGC_ zXl_leEH}sPo4zUIsyrxD@-8gb1E98PY?<^8jR6q1{%^dB*gL;o)Da3K3))1OjVrkv zf*p}?OT-NN4JFe^gy?u<%J>#M7a^6c`gFYHB54|fOhCVr8<5bJa9^A^fc`=nw>wuc z=}MYf9t(PTJUD9(X^)Sfe|5N3Jl9UEMduNN}pRt1Yc z@Cd9w0oqv>e*vNGq(`-;27g7!LeOb*hwMW??03;4Uj{A9>tawLV%zf*ZfpY#*VE3{ z{j3{b=xLqiVlxR>gk!f~l<_Cb9hk-CDgrQCf9dO~fc^=nO!4egmvjJFEzA88EUCs3 zXwT{?_+;Q92#+HVcpN0VRZsuiLj+hr*vcD~Hc?HiAtB2P%!ys0(PL@ypPi%>7Qt?# z3r&cm<&dSfOz)y~&~BhkkxKp341lV@BQazPc8hBYe)V{K|H2eUCWUy@=l-9lV9OI8 zyb+(VXxb0(opP7vCt6*qR)c@NvY0xfRRmp-`IRAW^1vkZBiRR@Z04U}uGd#9a?=wk z8rl>Emh+mMVm4b$XDU&2W|{P5u|OS zk0j;Rt4+!mn>_1SGvYr}-7a|Zj1jgwc4^*;0FA4_`bq6YWbDeaH!_ciuefL){T^IZ z=)TIORj*dN0oFLWGecV)+Z~V2{Q#=$&g?Keh{x)ReZPy4^cx7j4s&5?nN)XGAwNl46Eql`x=l@*ROb#OB;UI9+n_+dmtEu@A$IG(M-_ zh^uyw9)rzI^Qo)KK1G2TeNYS+MMK;8Dv-@aeL~d1;CzM^F0aP>+TFDFc@`vC+Uy!W zp^Ly*k>yva9>q%95(*kfpUdTSsD)?gT7u+1>F)P-IO2ni-VS`RruZKJX^CS1YLuSafa&1<*nUOj-9 zE+5{ZJ~k7HNG3J8+1Kdb@tAZ`yuQ0Bn{NT$unu| zuin9sL$R3>1wmYdRZcw(7i$57{#GmENQLe1D^aHhw%%^k-C;hSC@am5y*9`|`0QkzD$kOnr(uuR)^G77#GN@YIPs1MxaGYwK8RElRhYQ)i|nk9XLhSSt@;?!-tb- zBY6~EN#>3!dA!ORm*wyYuFr)>Xt6&_rq#Qc{N;*=&1{huaDmI` zu%YR>oi`)3Eeg##lY?HDe{PuC7YT6Uwu;s|vg_5|l5{TWl#J>;WC>{!fb+sxA|qRc z+#UXL9f*5uJh^*_kbQ4Yr}ybnzv!iCkFWplc9`>=3N?1?ZvhAQVJfxDr0c6MU-)t6 zni{9g7EVb?ihWgxLXT#1kppZPlG1d=K2I_zBGkJFmGG&5ZyR4GxY#L4QZSVr73`4t zm_{0e#z@QG@!{il1;XlI-s4PUh3|q5bm=JV&e7vQ)3Ei3z|6I;DwL9s`~AIYpygxU z_?>@hXAlrCFVcPA9woK;pQu`>XgXt=4tK{RHkNNRg{+B=-%4|t?&8F;?1b5WpU7Oi zK3%?pk~F$b&TTEeM$MN%c5LIaLdwXfw!*_(V=#{{Hkv$q8dEf0BXNDwi)ZpKX3@C+ zzKQ=bYPUZen(WFWa(eYKq#nSbn6!jPjI=ZF>=x5^YN*-tXJ@u$fs#m{g5CU|ll}Ex ze`iAT`$lh@u;{4@bO#i+`JNH~Heh^hzH$f(THtyunJ z&^=pI2+=bMc_*T4mDISa4$V^}7Z7jEa^>R&x*)ZGCOGTB?|`b(|DQVKsi-ZaAv8fG zqyF!Q#_mNxFkxoay&*jcteZnGAN6I{K3<-9o)v{kcKc#qVc_-R|FF7RC(lkHDhqB* zR;bHV*H&;m1iy4#>^xrN8O1X*Xj0Q*dA}-K>-sJHKARt!nEc?{7%Ef|n^(@|;z1|h zH#4X<|B}xN8IXOs6qkw;y8I5Agqci_eWClg0s%FyTdCQTZO8o>V4u6l>055~ zdOAEEu;U~3e-!=Z7%m}xR;KrIc(tp7H>TdDPhUzNzDtTNJn@e{bEjEJ1lh$11Vuy)(NWtV+vJ|y~RzLV@kAbZV6D(VhVGF z+79^be!{8XnUJUr7NYd4FE;TrM-?a=?Lu1oI^@3v1*?oQqT)}logPS4yZ@tqbjbI8 zxf&{>>H7rhQgkS&T;=KUVf>C+p7yk}_~Cc!A~SpICRE-S52T;sIc)5jGc>BR%lZD@ zbu68h9k(qAsWmG=O>wnu59Oj%Z5*6yyd9-RG+sWAH;;e-c$59A5}h{ON0LHX8*v+7 z-<64jPB)Wc#Dh<}pjT(~+xBN{jYhqT^Ck`{K|a~0yNN5mHAED_WMpdc@4bGOmzRRY zdwf9XB;DT

>jON3eVSx4u)geh&(%tY+LSWr$J=8R~eyOsV{JAX9M5PgAw7ype#K6vzC z>R@pmOTH9D2wzb2Pc}Z?0NXgcTAon`Pa`smHq`K=+Q+RmC$<<*wjreqRo>SBf%BVv zJ4T0t&7_K6X$pTAxg+X+$MPvC5`U}Bf*}S9htvqQGS;Uaem=q<5<50eSfExs=_Fk- z58W*FR$1?A@>xr^PaG(G)6l@wbp2he$a086oAiKjqMAp?RCTo#F1JU64JXm1a|KJF zqK!iCW$vR=?4E8$RD|oedYrQv@S$J4z?Ni}Nh?H&ZANE(@%KXsa#$Dmk)Cg>rlq5( zn6_?bWc#B$OWo}cK2$ai0jP1H?_0kA&I^XJSzIhEtbF5Else)=j7wJ4Q_;nVUDJX( zy?>b|^ZZJ*{NHK8u8&t>h1b>uZ!kKKSi5o0(zznK&O&$Oz^VOPc&&p~^Eh)r6FjqE zrg&DiGZF@A8!R#oyhdRqT|&2_-mHy;5+>Jp8QGFutyYv$+DE}5`o~@ZD_)ZbzF67q zsoEuk5r$x8)|3RD-PUYw1U{>2EXu3(CNcDU8vUl2=0l0rkvO&pw3(KVpF5$`2{{yE z<(KNqSu=nU0;m`(t#;4sl+|t>ZZ8LnUuU=9lJn25i-}#!&WVWYGDT!+(MFLIx7V-s zE4J6^GxD`>ezh4!G7j)196EX^yC{6Wmg#gas94&zx~4@mPvBj`5&_IuaB?CWlUoU%ydVNS`Xt zZj+6D^Fn^`EBn{e)y6Po$On*1AJ$|9M#v0>S9>Vt9=738&d6+)-X+fGQ%7R z5GC1HUG2tZsWXZHx8S#l4nyGOt3fX6XT(Zhl8LSLKhsP<_2QLIzd2bv|N2KeDp&owI0o(n}`p3)shfQN915I=%f&drI)XnTBOO8 zSkV-RF*kSTz(W_!68UL2QYlCiz|z>F*q=+bc4fp%&26jt87Rq}z$dVzD^lKeoY{H3 z?^suxlOeqg7pvy|5RZbi?&)QH)U-46w6HMkqgDqgZRc5CW9LlZ0jh9qZ}EW^u<7D6EQ;@RrCCgMLD4Q|u@ zM;{N)qH-R`Zqj10wpo3t;AcRZ*v6n{Em0Sb3J3U6$s_wcDNPueDwFlPDa@KA{DAf} z`{MdhvT$tZ_e9Y0T*B4w-n>~!ht_v{Av(=-*p~^U$57v`=!}U){qD)^k+0kj?q^BV zUk-@k#t7^|eB@!GQ5R_&GOcEwBIN&78?x{-M5$|Yrzj=aIof!%gz^%V)EDc$q|xQV z>uRB#CAw981Gphym)hQ!xF2V3I!ysoJHB@^*I)K+JNUffP8UP zu6|l%tnQ2YE#lWvPbzZtPb7=5%?m=GHv$LWh9r>6Rb|CmHbjwKzz75w-rtEBMh>P0 z9b!6yYH!{2E=cnY&X+(K{7)NCs4UO!17^joX=u$SGL6%K>B+MbE}SdWVCVH|(T!<0 zExg+CCc&^@6|A9oZ@okk6bv2G2s76o@Hed+3Rdm2Jj)*FTZY84qOh}y9A>LsJpfkC z7UREL9~pDT;-Q}lP7r@aw*72BIfbbcSHaWXU3tV5iG&qvN$K@l3*aF*_&n@yzK$)g zTT5mtWf^ot^)aL;{YEuqJsxrK zWC2D|3sztR#s)QekLEGt+$5BBZVVG zeOkfnQ437o1g7|Mij|!h=;FY`Sdv3{J0gUlB?Dx2FyBgVsB;luL_u2ZUOu)@V;xc$a(A;7*6x+ z87s5kAH?wtB?VCVx;RRTK*W^3`$sdYly>vJ-IvWnE4%SKzq$_J#42y~vX}tx`gn;B z0OVN69xy=pUGQF{RJHnSH_bHYo<}p33SekhCo3k0)0PMpXQH`@_ za}tH3;B3VBgv47?PL5a(8_)(+dCts0y$cy~Cl#1;%EgQZT4&>S_*#* z>Qs;Ht9wXqwjyNbyPftnXhV2RN}Ha5Yv{-iIxh9Dz|)Npi#C_0bpDL#oAVc>M@vU3 zW2GU|OeBByZzug%M!m>U5>?pI0;+77b<~Rpq5hXco9aBBVSe(bS;D%C&r|+OT5U54 zG?pSndCY%T;d1!NfHIv3m56B5EPmoe{UM-(VD6iL^T-~k>x8ttcHS!9jPO?^o$w+V zrqjAaOD7uo%!cUh2BPCzlNx*xk*A9Sl-tWN z0>(yq@7$ggJ;mGgl7+)!W^}3b(c-pF!`1M?+BH9}Zefg&KQY!{mUpA|PFnn*HP_j| zb*G5c)!XU~IdK}G2~QS~I!fp4-PNn1PJOr|f0=;+d+Yw7PB)E0Ga%T1V*53S8A0V4spTsUOxJbJ+6M6|Y(5b;HE;sHyDv~OF;_kN%z5`~@)Z=)`0 z)C4J;m1$YngOV+U=1E;ioB!C!vqhdB4x4n-j25F%@5QEBH-_9PL(ZiEy4KiMT8)Ej zL)#9?;FsLw=pb5rHGjNp{NkqsQ>zqcCH=C6wx`=S_V;IFp{>#NWRh&Xo8czU$ZZGa zkRv^54un=<3FA(4AC&T$W8=H<1`(fp|G(LH*0QQ8(%Ozz3{6N=akH;=Vvl3BPS5=& zpG|n?Z7`zlBwcDv06s#R5v-q0ehv8R#H<^NsaaHt#*vf_DD_SV& z7s3a8(VyGUlch7QJ?nrdTJ?jZ58RFHEihkvW2v5zi));j(s2u`JOK zyK5hX*(3@8gX!(^z?sN=C5dA*&4=@4xSmczM{gXM6h>x%;4^Oc_T$w(5=2;Iv8haR z!BbI9ov-33aq%yjpYx-O=hZb}=#^YIi|eLO^jS7ZjLobo&6Z#`^Um7Brs);YY4E)7sJr{T@_WOd!gDz zd;79uKMST*6jB#u94|Z=ns+MhgW?>!*M9aQ7YP>>nHb>76wwD&+A*Q?@x& zelS!Km}gfmqR`;l*t848;YMhx2t`PUM6-`lLNpM04enqrCXQg4_>gPVv0js)4&d!%dXF4 zodIyjagrdg9gN16nM1mCN79I{csjMU$0R?6Kuta8+3_(u{$>R%-qorb)dWF1bFD zK7AhAELGt3Z?0_ctr(!uW{{GExuxkc`KRF*k3_}K*R6`4QE*uT5Ry$Xnlh z5={q8=m4@0*dwILPc>wXEq*Bl$oxrFd_k;Mx{meb-YVUmwzr}m=VDRwgQBvj*cgRw z*-6$$Br6z2!4t@zE=)^NMAS4Hm@tHMRS(=M;Gv$>nX2}#SLb^_i_&BYG#wwyW(udo zvpcSGM0h7vdgS=!SF9%exX6Egn!Pf9Uq?|LYoGy`RICUOXzUH&34rvC>Z8)qF97oljsgvnJGvo1w~TRG1rS#AhFp$|8&LGcIHMUopmj zAHmLAMf>I_!w7O*d;x<#1NK#+k5^Y}PA4B!-r1Zyp!&ekXno<9^>Rf>93+Jk^ z8>#p*CVrDgbA6q7o?G zOPi=aA&aO89~m2&OoM$EB;?DsozDZ$`J*614)V4dk2W3(ElJmupV_X|wer=acjsQ} z>Tu_hK2c6?qOnTxGu;d9-{hD!jdaO$(?0=3q6UB>Yj^8nIXU!GGJVZ)3AnEUIwb~i z7OY8>Id15fwhZBQ#ovyP+Y;4sjQ3Z>YM5@#Rt!))2noH(k+>pVy}B)E-bzv93n^>& zv6@t-cz*s^ZNyUfOrGh+Cm@0O% z834Eg;}M(D`i9{S;`l!LzHMI@mz_b~qleu6&P}jjh=Q2&CEI#U0u3fJUZz`W;VDkJ zP%{iPyBv5HVbslUAu~G4)>0-V=5{JXH@~1XHNAPs0d(YXcH*Ce9i0Qa6~I|b*P~D% z#z)rROAu#CmpIcB*cs7rEx7bE_S`gQAA4-u%q6qN8_gUM?vLeDj>ZY;q%3C6iKf0t z5gJ;fsuP?jn&9lTRO<%lQhrGKcf0yULQe(v<2(7a^<*K1i^HsUmPglbcDfNo3`7LO zLKB<8dbgj$;^Pk@wAq<)=aaeqo-ap37C6*mDN+o7R}LvAaULJT2`a=T71Z$tR-BTd zHf{fwVl*AVjQ`<@EddD`OXGK|{=CfOTI3e472$7SIqc#3FK%~Xk2pMEJ!k=Ch!$yP zt~Bu7`JI)|gQvox)Zw2Pl0n6~L*T@0e1in6vwIW)_}fOxK()g``(r@FQgcU*bfCqMxRi>*h)-f95M) z@p6%hU0o>MXZQg-`<1`QFk&ie-*|kRlG2ijJ$#iCCOZ@9)tTOYcGLQkdx>wl>&X#B zyXIQiFcu@p6Dhwi)R~$j`z?;_VZYC6{;tx#;pD&$HOZB>*uyN8|se(>~c;K@=A$ubb{=iDU;PUzA3Oxu-CbO79=dYxHly5Z^C$bNI%{kh{ z>zjZI)avOmQul}gSQ5^S`P(6)aZ|(z-Epx&0C=z@$$Rs?Xql_oLy;)<7gpP& zp5mYCl9UB4^~k7QT%;IEc77`RBH!50q|r)9VIsZp?S&ZA(VCA-B7Fxz5@*vGTq@Ft z3)!SJ*7DT2K&#Jx-ggLl&Qc1yPy{wS~n0!gwY=f0DIF~#oi9Qyz32>x&LINN#A z9d~^+iKbMiKk@5SDmqBx!xFD3yC z`qO%D^t>$LW9-I}8$zQaow1#Va&3Ra&urObJD1d&IWi6HI`|wFqrWe40v|m8wDgBw z7>aDdcQ4&*_~I#)R)^%(@T8wE!&UjCHR%Gk{OphEvPZ^_Sfse$Ug9I1k!&^8RzIaF zfasiwi4_FEq7u_WP;6C4X8|y+uf?j66`rLBKMD->V<>?MakAA?mP6q$7QoG zN~p7c6InDBbZXWcKH|v@Y946v5QKM(bv*pR@CE;?#LHWk!G%Lgy

  • zehVleNMBk7-r^nD@O=|xQno57RF)dt%vZ%lsKA^pKPegdWQ^PQA@q5yxh-#c*(&2JXlkZ(d&|RqnMQe}YpDr`| zG|k`|2HNtWR(nbYsHAAVt5hPd9lpNFZ%87wiF!ppv=1u|UK;(Ttj{OUa|6O!HPo z>~HNR>2Z4O*SlpbMab68fv1O#mvIZq2P(64P%~<@nYX@P9tX z3Ace8N4;DBX1zR7O40|fr7AcSO-Q04e4}rI)>= zzWG$g)g07DwjB;PO*>Ev%vf?Jjc$Tp++ytC*OgOqA!f2AzU1BkF}w3gSaBxRG5T!1 z%Sw=yjNae>es8-zuZLuOE?Jgx4>kA2{laL-xsDU3As8?|GT`Lq^{g_X!puZoW{6hz zk;0)w<@!ogZNj67_h*(`$HPg1`HlmCQh?sfwGZ_yE?}12Jydo7ZmfA?tIW?9 zodjM4GMZ3%>3eNO`SU zRY+%Y=rQ?CdDm0H7y99_)~N*CalCAB(`hXxxYX`pe;KeMxe%Pzr?KU&^>|J)ld&9K zk*A`ror7C)0jsu^A-l~FO_9LI#q&+wDqnGGiL}Gf-ebtL^raH`dZSm_yw)B!4y`Ag z*0J3XQ?ifkm-#PDbs_)`zM(=_#} z@9Rl`J$_6h3GBO99xxq8AYzr@PP=S&oye04a`H|ZOlppyFa#pS`~irB*Ope2()@=; zjm?Ye7zICuoV?5+*UBA+Xi#p>G!TibD&%zAjrM0)(@cQdqa-7fwx*XTw{i+lAmjXB zDrjz-(rwe>#hYf44H1IFL=eZfb`T;i*MvTdC0|R&h`p4O{#Ei)(1l8^&N`fzV|i1R zE0|E77O%i(+?$`!Sg^A6X57pHOIqS*e=J^7l(AjdM$7)_VnBPrkFO3oKJClb-OtSc zW{Rq#I^UU_uKO7~W4rGUz~I*;ILXVdn%}yS%P)C8Tk&m%@E|6au@`?Hh>ZI>9QM$! z>8~yWg*i79n8U6#WmMZE-Tz#}h|#M;*ZnQT+LTtE9OeA9bb9%BP-v|DYgSGa7=F4< zPM{B7cC7gu#}4wtrr%$f7=y1BcYAJ|=W_oIv84yJe~`ak95vF5RUyuTOGvl+2G(a; znrcs-$+^vpL^SS(gHo@I`r?Y);qnUb-z86OqaHN*7vrXM`JF`DvX5s=%L`$r+_tX} zO}Ld!*#sjA1o{=6+Xun9zLzJ!S1@fW+~nuW7EKf-AeOb5!-Cb%!74KrFm!2o(CVKL zv;th73<1E)0rs3wbW|c^bw}76zZ(o4g>q}qQ~S-%#)y=DJc$~(alL;N;z#J!nG)S) zT>}!ZPU8IFk*yp*$B>oM0&%qay2VZrQS9|^+iXy|JiRiUYn-n3cH72~ofXVWyWD;` z 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

    d(ZVvu>DJOhNN^9z9dc5kCZ)_vmwI;T!D{4Ky*L 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 mTS*kBiQ6P&SPLUILcah-m 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�|sKx^q6BpF!T#BFJn8RW7%HQX1S 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�UDO3V4$S9bppe?gsD}`{>8RJ)fV0rCg1u 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%0AGl{=ZuLa5Cn=iMMq1Yy8tZW?>xP>BQE>L^ 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%0D2HlUn^%?fQ_vS0K|og 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 )T)Cq@Y7bMVraMVmt^Pn6Jfj77JXl+CFmnh# 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 z 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

    7P((f2oj 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

    <_;J+k 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 *F{$v`{?A?K$ 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 *D0=6 zBtx2JXK%iLr8Q~BCj{yasa2C@-H_v)-|_Zyw;xe)t(yYxGtdBB>@DW~+()3a7;hbmzv>p-k|1 zo8Q5KaC0j@cEOI&eFtnLidt^3Ip*vi%c_MD+X&oq)ohqA0i}!Ro%|*mxvrFyhsOD< zN5CsRZK_CI@Ke{T)sv|b-0SIdwryw$htD>gpbA^XTq*Ai=* z_uTWmicPINGg0(=^GH)a8cE5$j-ns057#$KXKcG_(gA-BdaNK?VrjZGde%Mz==*)> z?Kpu8{BYLo5zq?`{|Cuw6glu0b9WFUxv7oPit?DzN>TbaAW|So(3B?)be8H7;9+a3 z0g&0FOkkfCcR6$^*G>G+CD85aeQ6#Ij-*te-E>?p&KYxXITZT+&5uRW+;Y^9!Yb&A zojofXxFa5e;n(<`TI}yJQaxS8oLOb~#0jEPBa&n@ER3hm{QgVW0u|3xafI z&!XY6tklG(hu0B#{$1ie;EMo}e;PooSDl{t3AosEY!QoM_`m@JSR*L9?f|eq#alNJ z^0n(u{I_I)i@Wt*q7<;cOY&552fitrVcDW(4+;`H3z4Npo7L}c(Rz3z}4gp zdbrhVb}h$NF|g2mULC}T81;WrxKmkP0JjIT4HifePhK0g3T2Ln7A`2w`+4sJppK;= z>j_o+b}wnqkH4NCUaCJHHTHLC88PMc8B;)x#V?85)RT}s?LCA8VK>owaAXy_d zW9%P#iYWF)1|a3sv;652h#_w#O`t5DXtwSp@^;f{fcmo}HqYE+Yd?51n!{e0wtbNE z-=5m;0!aqD*6Ke=bylm`-GEY=a%jd8oG`sAebP%rdP3O=qKXmhtj2yPp0HB9n}dxr zp7Hjw$lF09!}dE6{z@$RaPt9F%6!vCB7^hn2+Vux7qH^-4f+>WWd~&CuPhCeDN!m( zZ~trb1?nmw8!MDGAfNk22bA)8P=@FV`wc6V1mw2Y)x()V(q(8`d{oHr>dBpc=Zj*U zRt*K*5g@x7Fg_MnUcod9P_^GHE++QKKWnA*w8DwQE5uqlL5~cLT&}EV26jR1K%6Ab zKf#yj6*3qhA8rYXbxbC$Gq=YnO-wuVawQ_9TakK7*N@g!Kpdc@lvHw&tvgivpcS)) z+MIDy4>fBW#VuKFxnt?*?X(iXc?`gWxqEueI%xCXk%{xYA43l&@P-3s&DT-?%wvnI z4EDpkWFB&hHQYK`v;f!QRA4Ph15VK}Zp^N85E70j7#xCz{d@!m_Zd!3@~x)jL(RS; zNVC(gjiNyXa){N7JEoxg+&8jIKA3uZph6WShso9M3hcOr%{gtIhyZxBUXa@;td;s@ z>?pr7NFN?{0!|@5{)5I;E>ZN+^Zttjr>QZbEb&PUpgJTQrGnx5J>0T^x`uaZm+QBg zI^4Z-;b2+83F|eHi;t!4h9c;eHL4N_fGTE5xj?5h;9n}6f9bRCsy`9T7%j|J%~g!9 zrjGr}QtG{jPeJ$r29WM|WoosU(8`5)d^R@ zK{tJMnhH?-N&>}aWkaF_d`z%ay)Y2wkcQ!$P&zem;h+p z=O5{TZ3lo`IIk#PE%HB3g1J{6#4O;$8pft9qELCfRFL zTp>jopb!N_Fo;B$CZ}kP*UtQ;2YL;pves9eK7xxET(8)#LSBqN05ZZj;2sHFbgwuq z;4;}ncIPKCK zLYdJYcC%CwoUA7PQ3+AAG8306OU7w*HI8jbMh_ntCr#aazA%GJM_J9rWCcj6LG;(tiGXHi$tEkZctK zWUZJ7@qPuXdeMQtA_df(W)L86pfRV5{rwcu*B!HQ+v}BsWYBr~(39m(W|8PE9kve* zf-1a{8gy;C$LNAVTxu!)vLMpyfG}N9k9c#k-jORLOx+o~{dt=oyw;VEe}~GGRi?Zf z?faj&=3;>b9GvaZofx*)48KpU{N}1Sggc4|Ws76_(>+183dn&K|8lwsEVQ7Abz9D2p|5HUb&L@R3fP)eb=ZK9e*9Vp0Ob(yu|o z2$-^0g@pDzJ?_SaNj%aKEE08NAsAwhw;gMgPsPuqjvq*sLUO}E#+2YgAqQBcfprj| zyFfGvV4E6d%Jo=h$m?$wvIlu3P-gv+8*E8dV=_K;;np$yAsb_SguO!wU~Sfr6t!sl zo`A`M`XfVZwNIy`YjP3E4T=60-{ru);sODA)UF7P8nD$@8z})R0aY0z`s6R_{DSwP zatkUAatoC<8xzs+mU{AEF$05Z4J=?6A%KoI(zHSVP&>Ai;*pqox%OnZZ!VO5|5XpV zFri1SYk@0To^0GrP0pVrmDri9l~-lEFI)0mf2s3-fii%>K3k#2k1QEAFGRXEhL_r} zif|N;i|D`5h_uCmkxyCxPm-7{>DWKw8`2;LL2sSu$4@x-mt^sIo#oTOUf-$pO6%OH zrL&5Vd0c|+lpnLpS-8F08}pEY!K64QdwlO(oE3-EgI>i~(dW?%ky?ivB=sxcf~;YT z>wUppgf^vw<_rPuL)-iOQs8j_3`p{#I8oCI@rpxjYG<9D1vUHQI^j*OeX6b!C5|)& z#^E24mJ9*}-ZF+uopf>#_|+iGMRHV1vUkV|FbU%oS+2fwY{?);y>D~?R(b@nevPt( zFy{;3(fC)u5WnOAGDKd=seOD}V|mm|!2_|~n9dMWK-YVA6ka4VbA`%9Xg3Cg+@ZWF ziRhSP^D>4*0?1K(sRo3h88__2-`u$1K)o2sSn{Fuaox9Y=CunbdK5YlHk~E`S6)je zxHBF({>foL=o}z*KZ70uPKZ|VTal=^{#-1Z*4~qYG(<0yu6*bkbEi{7#7Cp8|E3q* z!qJH~w3E9~;6W%DP=Z~1$P|P26NhSB2|h=M~+OuAw`M6HYx3Av^eJTQXPYC#%NTIP$qf&Se-QU`4f?gf8T9euyZcHJUmAR54s>WMKE6DvwXG z*Aao19?q1C8n8CpMA5uhbw&_v zv1CvE&0=bSTz-s(3WPAM@q_5+&(L^IA~MI7V#)SxR-JHD?N57jGMpY3>rjl<=ACxCxOW6s=5t*n)fKt10T(Xu&%JdO)Y zFq;YfMf7)K<6a$L2x&sH+aiGNB7TqGliW;b7ao`qCBF;qaWT2wB0x)D2%~ z7-eE>%W+d|&TokA)LwsVz^2*cH`L^L2?FwRWs_?nsi*baTTxoa&6cHtvhTBkpLR0h zp^@^tUw!asNq6YXkoBfxi%>wgD{ytMC2R;Zlz}Jp^FI*Y&)@?9F|nPl z9)JkzAJo-Lgp)a4^vVAQa>~K5VY+!lbpr3$DT$KMiZ$kjmk>4zjlva7U&=J`N3dy? zEEBUHnLtsT6m`0^A5!_#1(X;d8uXvONDjhI{wLI^91mKG2rj9W3slf#^l+P8 zr=%5uTF?X<<&a%;$Q5m3|O zwkpQb{pz_`<%$R8)RN&nEBu8G2Z%s%nY$x-v-Cmx0*=jPLcG}*{*xxH-^~0$w&BWC z&uE>1_2PQ~)ia}lr@n2AvPr>ah*YcWcXuGCgX{ceSnnb$H;hMimz!HQj^hJ2yimXZUfvt!oi$p!Z9H8npfz*J}SorFmKpo82KwX zd&!xjK=45uj~%GZu#2EU$+btcj^X+c^OBVN)mA zLrnyRCJ+k$=n;*7o`1~ex+fU%26$Cf-GhB}(XmU|l|!7;fUTFD6{Mi>qMOnn!>>Vm z7nYy6K&JOLHA2JqQGO|7@=|!Uu_*9jfq-5sDbg6>(Ubjv`)3I=tSiu96lVkphxeWP zVEPB64HUzHzNnwuo$QY0q0Ge_Sx$A%bK_lzv|4kh+EE}$pfjx0gKT1Mm_V?HYbg83 zlurn-S0Mp&R3}D3fm-+wt#@TYrYT)S*6k>hHEKz;cg2Lj7zKW|)jM?LCsKN$0U!Sn zYy3370v8MZ#Lx`JTH=p*py*BK*pj@RmdM6n0DLyU%>R}3na(SLk$r_0$6Ma?ZP`)| z3z|klK8!PL~CI;K2cH#RX8{oB=uBal=;M>%M&@{rIur6$Zq1q3irr5cd#CaxD^E&S9hE zT~69!POes&!ot!eE{N?V%fOhXu7Nm9UdDl;%bTRf-4g&gJM0i2UA7|NOsaEs^Z+fz zAOglpFD^_M8~c_5?Ayq1Xy?KB`SbQM;1{@{-sbF-Z68HgnClT`b-b1`O_osOkyQH( zlB~gr{QlhNOcpw)^v66j7pZkAwABPy$~U}2foO2CCi-;?KWa?uluua{An=FTbD@k7 zEt_(D&aYGHSK;4GJI)yAqG5KGbPu$=a5iBdM zFMVs%Wa3B|J^Y`Z1hQm2y+VZ*a)=8yhoi`xH@ckMK*e<4ium|oDz7GpKmw({<{xMH zUrVL7n&gWKB6R|8yeitDMULSn5(d-Kbq*5zAz)amWkr(qf zNPJXyd>)+&;FWW!v`d@Yd?RcaG7~3QTLVGmNBTA?QsH6K6!g&YYq@8OZO!J-ghTSi z+(#P^ee%GUIjFSiHn!xetDN1ptKLl3qIKk4onuf->86h3^S{^b-Ups8x`Yi_l8jr; z3JCFysp#U9nj-9U5nm`LL|Uz-Y@O1#phr_DYI9~Ea zgTdB(CTr#1e1iF&$zx%hoNTsh zGUmmuM-g@({5N%TwyMHkiB7-JZ^PKt09i3z(O{guy$O3B+KpJWYeUq^eBgRE6|EBLWQuuFM@w`ZvGwRpr&w_s|rQEgc23A_9bEo5uqg1yr zMyi%ejx)dQ0w!n&HL_6|B$7FsA=1e15zA?XNi_vW~twZT1m!`ht_#+g*oTkSxO*cIZVTCy9Nd zNS`-e-wuD>@f5KhrL*DUO;SOfMcGlUfj@bAqSj8jDg51vc+``!?~`WvfRwv%&b+|e z*-n$Hq+HuCPV!PjMhUE~I*AH%9>b@%3Iyjktu((*H)?}_1-4`}icpip4>3mm=1i&m zud(oVQ`$GXIu+Z77!+P64)>`vFMDTAsLq(XhJT|v<0Ws;wvc@Vt9QQzFR{EibHcJ( zQO@5`yLi|F^Hk6jlQu1eodEn156fja-oV=Vu&=#iAi~x;rW)ik31`2ZeEm%C6>44d zNMfK_v;h<)+~;D*Ui7Kzw{Cy#^^Me2aVQmYuKc&99{Sr`PKv%XmlJrXJUDYmPpL`Mx>NIh_^7c)9 zpQY?Oy^wgQx{S*{I#{kwJu> zZQsA@2=Dl&&fcafM5SZZRV_`3_)~$HnW)82^ysN&v#HuyOONzzE=l_zo`Sm8E5r*N z!!BKZ_g%KWWRp@f#VDCdKf_co7ueTKCr4CiJn&@bD`l4U*j4UKs2I6^zMgMlGubeT z)M1_!6r}w|Ykcp1f1=e@Xhr;3%;u)d#$&Q#OF|5uwaWKrt1+NYYl5JbN^J%2=KZ{G z$;ig1Y#gZ<%TGrg>qqA*WSMe&HlpNtb|jnj!H=x8$6jQa#+<}*Z&u#-Tk=w1OBrx- zu8HRe9^n5U+5&<0hizR9 zL-KxaZcLG#{N&394bzTg=klVb+VRi!`55|iBS(`=+Gtc;qrW89FCm9BEXm`X<9^hEL6NK9UNqO$ z2SKmsskyXe1p{+TB2k~lW_}})bF1u+f^jOEU@>8DT$A&pk;F*N$t=^0ZK>QH?=6eJ z<|wmF<~xXA)QKl+=4gMARcpJ7Gve6(XBMI`@*6MAfNXYs6~+c4=|i{gW57WnYwUEJ z%U=@C(=A~vdrM)&2Zbnj(KbIgXrpOiF*ti%hW0r?!+5GXS9X*6(QjHo^s!m1o<-W$ z3;D#+C^Y{@1*~`faVN1!UtZrWPQWDyuyLahe$Mcd)+YK@xZJ_ z$>XhvTaCI`R;4Fi3CQ)<#f;23=?E`A{T5ZSbBo4W`OkD;qg1o`ZVTzG0j))v>@KlP ziQ9-8nYRtN3N)Ze3`y^atd-Rf=u;kU*q-Co&r=k`Mh~up##1-RrGsUfO&1#6mYCBG zN7g{wEBxZ$N(72}B8{@fd8gR}bpcgmEBBX{rDbhN#|^CYN&J6mGE{nra!XMc&zXKb zA_XEJ;*L}QNFwsM$-z57t*@Ak{~M7AMe=gM5LK(~~OT%;_eZE*WK;5F>3 zsV`o9=uQQk7;xbJKHcRzge}5v`Xq2i_o7tn&o!{WEl|cz=;e5_W(dn#07vC#=Rm~K z`?9;zpU;=B_dNb)^7J3*2k~Z^a2a=!*S&Gm8xMoIK8cdAH6d^-;qhI48l60>iaa;x z+7lVzRaKe}Q}GPRRlyC@ZD64zs0z1QIPes@Q{l_|=`5l=Qsv!tA8tmJ$2k0*Xs;TN zJ`UYNvv-zTDG&NuNj>=-M|;VdC)>P4Eci6(H#rEdGfF;3+0@qvBn{|gN52)Y7cA=w z;a1{r_Zc=9+&CNlFz2N0_2o^1nu%T9!8>z>&>@%bg+qb?VT zu<>*pJ;es%`Qw7P0qssu3Pt6vDs_sVZN)%EH9z#_cRBA+k=2h36>$b-n}ip3@v$16 z^TYOX?bAu&9fzh{l4W+Ao7dY_ebcNEPc!7rGxNz4|64zm{>R`N1|__QVfj$rQi8Zf za@0*h?}cO*`wBTS#8Tem^}dDU+e?+_UKd_EoB0b0ryc*N@4J>c>Ug57GsQCpu{61* zY^co4krG+QVrtAfSYuVY|FQMxO1bh4XP}>-H%ugH7mn&y0 zeT{LA+QUYLm;A6tWb3>9{@Mup6dBsFr(et;d)7rO7xI?8E1c0LKO|YW#4T2ZXQ7U! z-kJ;~a!=M!q^2i?LB;u8)JYvEYg3~cwDv%ocD$LvBMiZbAOXNlVr+)wi$N_JDJ3U3gV9x)f)B~NUsG@wC+ zC-{9f6>!(hx)^7b^PVKBWrwKU{EOj8-nv;prg9(3a_rHM8C5VC06d9Gq98%rr{Qr&=;%O3nd(7!PNOhKGgVSTkjDE%!NRx0; zVn8ACslTzOMFjeF$O5bI3yspiODKi7NRRyf_XKfwQ^xIQWO;KPIx{Yy;z^0pK)ME{ zQNqJNp2d2X!yiHP>FEnUUZ?evv)=HpsdSn0WQ{!2sH(4`W-G9Bg&*B_F??-)*Dud^ z#Rbn}_@)fHZReb3!M_M;M@2yYOrN{gCd#K6FmvvSj0p<%Ez80?3uKdx*xSXE%}KXV zxzAU5CLQhKk6vdNGFI{{t2HIPdTaDKYg+og+HGXBSJBPmQk!^@)?*RXjrU`p>)C`&ou@R=yRU&r%Hm;{;Wz{}icM z*#T6?UOS;90Eqfh#@AtW;-*mR8dS8O!yDT3^wPUuEAwmOXvagA^!BR-hMZhj-yHjn z*z(!gBG!FOT*u8%~L#M9Ae?l%jQrJ&^IE2l6 zz5XmdD`Yry-Adk1$YzyCa)*jb6Hul8VYQ0jRUlg!7fZhS`|*Q}wbF>);V`jrf%c8v zE1kdQI7ZF>7(JTuWhBXtT*SgKlSbxW!7`vrKH>1XJjE59hyLx^MEQ6+Uz?VaOA}q?m?`uX%@!{6@;i~}ktmM$tFP=7+ub;Q#J>u~DX~CPE z+PFEV*#EL9*k&k0s@6AjA0Mhsf`pK+x?nYF{DA`W00g4{HtF@u- zdVflfKhFeS>x5C{K7nOW(_%P0TXxFt=v)OhU8AR;S5Z7lHXIZm-JCJ>q=}Hn-D>r* zWvIaXN;aLceE0sxn;TNp%}Dhq7BF2!kD8FNzG%%P5~8uz>H^RbznK7G(!3Yc|Abra z6|P<>MO|Pe{Lu?AIbD_beR#SRd#VEFDBy}86K(F~cFiyephlvfw)%Ul@#*ng%)%ET zZ4nPKrZKOcS<6ztMMVqUZ{+;ZCNQw{MM+#OGT-}Co_hsh6-I^1edqI488bqttU4Jo zId4@?Ord?S_Vw4@oA3Jf;f70eAGVYB7hlWey>wqTVG|G5-VVvI0>2RySq&q`_8@fP zC=)DlxdKcop3qTG%{@o%chsm2lB>zLmN`UZTV3TpQZWRYy@uT`n1h8>qupcFrEvMZ z7tA<_aS=uLlf*?8rdwjYW))bC{h2Tg!0;}R@9!3EwXmV6pf*3+Yi&9|ME`E}>4?h* z%VY}iE$e2zbxMD0jA7eDC>!OIECjL17zgs&C8g+s;wRZ2RW$vNr;HZG587xTm

    ) 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

    OiJbbO4BYbP3#x&-qSUWklwrV=$oNQ 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 z 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%0AEz8;M~oWL(DPv=M^ptk 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 &0mSn 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�&oOFt(w9 zm6tvma-#{JTxXJ>{XaE>^X6tmE};U(N%i){yt_nnYh!7k2IcWVe^zAvLnT)gn=0O3 z*7Y4Qz1h^5C4A?aU5S&`x@GN$2r8g}**}P6#00>H`NMgW5{x|$)vW*{HD06Jt=IN2 zGukzss&?ImgKXumr$b^7?&>%?DunCe}NzYO;+~@kTwX8|-o%4`-YY zV~dPe9gcDY7-Q>7>`A&!@^?3{%MH(3GJNjM^{XR`t50AdoOD*J8JN4A@AtnDxVpQ! z#f&Qbm3OT1x_RGfZmy>lOK7PyD1Dx+RNRc@#d$-$;GR8;0x9} zUT**SbS1QS^McA({ka*3Y!Wvto$_A&K!Eq7c);%P%f(K@f9a}P!D-1MI!yQE{NTnA zt|BB1l%(*yoBz&8!}3bA-eNwH+y+G}@D)XslyGCIJ__etzcX2_5^&Npy=mb(r>6N1A_aWPqCsG)`#YoonL=EYSS8 z)01_T$%z|H#W+;EsF^@SGpQYNX!T>bbbA5u)r_d~UXsK6rsikjFI&gU20X7jvOgzM z9fDxYjEe#9-(0p+1XmgVLR-3x{nqIeFp_?GK5kC^Syb2X8TH&McC=i!Y0ioMZ~m$* z02du{pLUbului_yvyAvOTq))l77VO*9~q2PIGV8BF0#htRQLUS9VUBf@lERFc`Gt~ zYK{J#I*RLfp%}=`0P&B-mi4zG>Fws94chz{{9hh-b(5fpwqPADnRIRd3X;!uvH$K> z4c@+;x%KHP^FB=c+zv#f&Fjf%prq!OpL`ZoqW`|-N1^0x+H584oBaww>-vL}4o_x7 zS}Qwb^9g)Uw2Obt61bk6Qv|i&riM*gLgX^|Z!)B{@R%D6Sscf0xTvU~*}qSS^dBmD zixS8DrS@jiL5b(NC|Rfy*&Ptc5TheYD`XaZ@;(%9Pe#(I=46Fyz?{_DKfOF_lh7;{$QLj!CfX1q*2^DQ z01M|AiyQ=o?( zWpn7L>X{O51`;a#%NbYTz>Rc}ZuVrPIsdPnPFWop{`ShE`VKC_W;V3C)S$B*xd_R* z80mWDLT`rtgcCytq2yQoN7*eiTST7%_Z6`7v4iSlhTc7URisdK3{f_LXl{3ORXqztLHQu3gIJ z836628 zor{K1qvfo`oBHXOOG0Cp zPSr%n*CeEIW~S0msxK;RmKd>Vp^a#R6#@LwI(U@o(*Gt05R zqeMANdh0De^j~Yg02eKMFk7qiU+Vz9nFjNhRcV;LkZc^Mv_n~6oUF4kX`6rEJvo5R zSa3C71sB+lmhYH)r6*DPCtz}4w}fDCPe-tHj_me1lCJJsu#lt^7Zo=RzR%GxTD0*h zJZ1Vav$Ia(DTy-F#lQUY$#$jT11IhzsC&6gn0~ZMoVZ$5_9b>$=#y`*=N{=YolopO z`xPO-TL~wsT>4^>Q%b+=56z*A@ff0;!04n+Dgg{)Ncs9kwJr;*n_`Y`&Y)07m1AOK z;Tmb_!CvaVE#LjOb`{S=sI$pJnI;DlPmb@Q9tL~%Rttaz5_WDh=ma%|s77#av{DL=F?VbLHzad=*ud z#9Z*6PBILvIo0wV-AIi7Pc& zi5_#1Uca;4Z$3|&FCs!AHroL0h&+FUWcN}Tc*`Pd5ZpXs6CTs{u zr$Qmg*g?20I@sZ|50YofdExe`_E4#-bD`2j;$DK1i?PGf$BxxwLUEW^4(gSI#tm|$B5bOm0IkXOC$$3i7X^Cu{apK_PZtZ!Hq9N_mPLfE6a z)h!}bJqTVMB=w55F@B3CQSNQPFXm)`qyVmPJvUdccCv;y9rkYuGiAN&YMok&+oqwe z@l#Z>Ilsi3ti{P;vA-jLbL2-;XUOpQ+0KdBuzna2{6MF7qwGoJtHY4|?jY1L-R;K_ zMHDY6j7Nv>S1hRkCff_~Yif_xZh4v5*N&Z0rw^+RM%Odb?$o6w%Mf-N=5qtB;}xQB zKI<~`$GQOJ9~E-rKWn4T*IlYfaisc42YKIswFBmFs3wNE6lyrb!5o&U!G6%B(E5by z=VL!s(OaK=wVSwA*9}*H{1=8V;eNR02b>Kd@~X)v-}u0)cwG=S>iyeAM}5(n8hRvN zo%g9@93HTJ*XWd+J1ljlnipiUX) zOQ@jhz;2rmWNXYnG%J>`d{a+H?s0sO-LD8ixU(ea&D*KNMl`ji*tqyjKx(3s4 z!-q65#NMl)A{f;@cuOs*uLkHQPEZ;5RkKR0Uh$(Xkx+X-BebBb9=>R8%j8vBd2i+} zxPf(kHzZec93O*b2;tNCDn%xmdN06_Ic9?5v)_FP6=G`aazUXCd~vZUwy>OcjRElLZq&SbWDZlymu9%GL= z0Whj?W4~zHL0o>sBiB&U;;iLaQ|di=3=g$Oa@&EYjOtG;emSDa@weUoqIxb0EwIpY zq!#Q2V7>fPN^Z$i82~lV=N^oilO4LpH;3ibg;SW$5aP7q`EAV^Q9>t!I8XH9Y6z`? zFKqKLas?NL1p;Nb3PRZYh1vP#LF#oOZNttW@9RctaNp483(9iJ(YR9Z)5$*(dZ7~EtbbJ|BlVxJsu z!~8W1{qnvJ7`LC8`^(I@6#ous_rEwb@k-}|D2Ru~r%|U{Gqo8}Z}DlD`=>amBnTDU zrl!m01qr)fCm&*1$h{-3a3(f{kXK?vm^1(8j^b z##bD%jff2!rfSr91|#~`|W`Q%Ed9Ek03 zm98r0ewTMzWcp&y=Sk}=SZG{7*wTM;6b2LB3 zGH}h${*R;c4yU^R!+7b@kd#eUGD2qd-g~cXLdc#WGs({8keSV~iIbI`5aMJdd&?dj zvVQM=|2$XEb3Iq-I^Xm8zCZ8#zF+q>Sc--B+rC*O384<~jCKl7sL>)sxBH#FMcOVH z)|=p>bH_Ga1Sp}F$fq=_m9PSStfaRx2-kyc`6o|2DT01>xpw(58_MXS^*O9JJs*SJ zWiiLYqW_2_d-nY3=7)`J(Z%&`x&k}49T7DRi9_*M7Dz4o$c}`=uOuhitrs-;_jj4n z+Ib@2liB36r){-oNpo@$`0s-Pz55eCkvBm~ufB~>l`{jZH;rmO_3aH6bb_NvgA$?- zQ=sLnS*Bx~ZM^Imby+68m1#=F#tG(_1*Ss% z0#66Th$Q3^BF`;rGazY;nqjr6i5LG*#{6sVkv&|}9hwx<7-Yh(X_ECyDvb9&VbVo9 zj6WV>9Vo@adhu9qBmcc|#!K`S+4;jGXZ=CBC*j{^8OGNRU2a>wd8Ul8hUu7Gh3vYy zciU7MWaz4>^z6hjH0v40IIgYw3oDhE@hiOyQ>W^mqDcyn#UDQ(3Kn2kS=z(Yon0e! zS*PS`>9OMrn4wHXDDcZqwIC@2g#opkq|+Mg&$`Z@27?SaBw@5RL#CFge9Ly3y=c*> z$$PS+H$5p<8gh9eq#)s@MVaC@c>m|}&aY()sZy^moddpSza&0lMDI5wo{f41#)Z38tAG~{ zPLg3B6TEdrsnfHxEgyy$=b^lrZD1!NE6kg)f%JLv4Hf)RwY`M42rc&UV$>-pUby`W zXMcG+dxkpL4I@JB#mMJK`rv*xQJ#|2cjwPVj6kG7Ye2L%E3o_Wq0i60TGu=o3F{NF zU62wtlvrLyAxnwwQ*rTcKGh<;=_#*kn(&2QP=8`paY03rcGv4y%lXwJog8DwDkF{q z_dNG^ou@O`bv56M1$>$H%~zBD=ZQWFDST#|rynStt zTP^47<~-QB!aJ@(A&maE$MlEis z@Xp|ySqK4UC$Qrq6^|;ZtZ_*svIH=UEjz>8$^&0G-#T0T)RH9^?afw1FZ(0ySnQ~` zX3DH}kgB-hQd4y5W^1Hpo_tA`AuXyv*1?uuj7vY({YN&bJzgZZ} zpp*F6mSo4z_=Xm<*Lg3eQ6L?mPzRbXSkJMmF z+H1Zu<22yZlCO`P+u_@MdRwUuRy~iQwzB^%J{;V75cy^?E3*n!OrZbaYf~l{`vR1A z9ck^Cnxrw*x7_nGteWU;S(9lb(7cMW<3^MgT&wwMjDN?Ox-et;Q@nIjYWJD zL+4?O1DhSigswQZo1W<^=y&D0#U)l#Q_oOJ{dHeVdux7t{I%GMUcPeh{QJXiDcDfp&F%ZLDN)>HQnyUS)|_Aac;RiVUqv?Exh0p5xp z)6Zy*;lkINxD}_(TAhjqO5B~&lebbO9kjd4*vsK*wEY}{k4T4xUoPHMfpu9}@Q_mr zk(+WVef7hF#KpM*Xw(HdWEq?&XQF_7NivZowf^GG=rlXVJUd@0_1bEt`8~ zz7C_r^Q|xoP(~EU>%L`jRD$>(U%DVH1W!C(7up?PJiQ{M`5&^QyOtls zA5n*+p^`DfUx5KI`1K0Em3q0w zew*!LhXx=D0+iRM?rX%7WI*rFm6BW7 zMH=_UB&016iV6Fp&KKA-Pm}aRw2r(>baZroO&Iw6c$x32Qep_r?jbiFQa#iMCu#hE zi9tHlDkPG#897noJ0W z6HXucn<7}w$^|o0l1X%tNT@kg97zS+rj_vFU^ZOgdXsQf`I+?6A;SO!dG(D}N<-%^;bdOmT%|U;mu^lT(CBP$z9$ z4P{4*dL6Uv{mz>3&U>9TGOu)PmrO?Phb~JX=6#LUQ9FEPB#CDXcB>S>+46cQN{-2d zx)aXuvbMzt!s1m9)Y$<%n|QW5Bbe7SwCT?wp8o=@Q!I6SX|zXonluP>vu&%VSikE; z8*0Di^vt0jVh;>P+QQOXrJq(=J3;?St|IIAE`b;(y^XcT-sz%j=JAcx!c2F%xn)$K zz#pP(ft_|@45|cYTPvwgtEZ(*vk7jT`|v)Blxn~wE^z)l#SRUZZgX{1E0#fAy1(IW z#|0rMyB5_sXWNgBxI5yvCjIz2svP)!%YF`-Ru=IWoIm`_8)mFmWP88SNrQD1oRx$v zYSr{Nh9<*poIj`B{_P_PAF`}D$_PKq7g#|vp3-UgxCb^FMoa`DH~Q+X!#fqhMsZ|V z+c~$L*DSohDqAq~?P^SiG(>n|c@=z0Q6i~x-@&aPxR=#w>ag+ob^cdxfu1%-3bey$ z>l6VYg}-fVN_NF#A1334Ak#vNBMlQW&W9>}#OlnyKDHbUq>I}gR$x<(j$_=4#wUQe zq-}}C@;l2Oar-^Ei50nw^bX9#sy8CqIGTPWr8|(97G_E6jxy=xG}6syB#;u6~RwvL?}{$z#qgjzg3Nf?g-WBlmo8~TXJ8(8No;~Q(C zw81MXA8q! z&SAK2mqkFUd4dd9x^2#IquP9mpRCHvYonE8Px^>N=;S@PpQGt#syG+lpFEdi=5@IDhWvqm+bCY5g_x zQNF$)3wCjVwVw9Xp#o-8&`|c1f?@)7>3sy-v(JE0hBmE3CY14hW)y9MU+j1`8lQp+Hf+s8V z!4*E_e91D@HZ6C>yNMV1Fzl>t%JpcULN0r@ddOt|cXx&-hSIrKXk*j?rI4e6C0pR@ z#_;mPG-KsE!*_w_+$FYJ6@2^U>&C~VGYGZIH*FZ;bUa-pD$=()-hB^9>=TVjrdxS6 z8J&^IEXj7tZLWyJ(wAtN;VuDpC_HJNdDybblZf%F^Znw+1rOy2J^n?Tm;|rt7ycau zBH4vsic*yFF9cIx?RzUz%09oq8}PjKh6)E~Y81Dh&0_36y@5)}3_0~D=Nb9T zuw(wMvM>U{23z5L!B&{E_(}yItqwt%F*xg;F83$GDoo6v_Y_R+i#ua4(!TJwUZ%V~ zeXVk}pPBON8**}B*Z@X{KBDS_j%qx{3o&1A?cg46lcR4gnhkESh3#o55#gkwEQ&J< zeF)+>)Xz>C=jqd_a^roDHP?q+-PsXAkp{3jUwHi0vOg4s6A?&i2b%-V5FY%8C*Sms zW$o8zD|8FM{8!jGRpFw{@W(e+sZJKbP-BvX>-u|ulIe5Dlmb?L;DzyoS(s>}6@FNJ zet^H=BWs+GLN?H*dmd%;$_{gCi8~E)5VYm^$X1!eGd(hMqHVRow|z$~(7^NdKk-AvxW!amgeYt0L9j;Vc~ z_C9;!-`y&oB2;jJw??zEd0?W1;m)|AbK!&f&O;2!3s7(D+N5QnN!6V9FWZ=MmyJH}- zbmtP$Jf)taZ|!;-f8vG^^F601MA599v?wWP``C=<&|8WOak3@p9R1P?8So(wJr(uL zi38twVQ1J6=4A3fpD3f!>bqEwKZ`N4aKT)a)vcO-__J30Y`&FOg)T!qY~F$kN7v-8 ze<10YVT;D_;qJ<`S*Oz_%ey?zXtco3vceK0q)d#_kG^F?2SYX2rZk4at)$2T!}_VR zGPt&Nak34#n*5^>S@VwPbxIcQb=Sx|b`R-GsrYX3f2uv;?n%WmFl@^rYKZGCCKAFB}2R;YvAR4^EmtJC-R_w z9^d?v4b6Z5W#JNeOalTqZHtg35kJPL3nMxf#axW^IFKo3BPBEqr?syZEOlu)qogDmD>Of?x=hrj z;xX${5GfJoxSN7O;=kszmAf_F3WUfyMyT&x5Xc|f49^yhi_s_;mO{VmOTG_M-Eb%P zGH=b#fKC9#u-=aF)sK8Nf6zpun0RvvKc$Qk4^+uFR)Qy-3XQ^0qna^2ns(@X-*F|8 zR?~a#@2Ho2=8|VEu%4mdhFmN%K~0|+KW5_=vVHLL#;YO1oM8*2Uk3O?#fhlOmB#sU}wzr0lbb#{1HU({eb zd8$vAr)*-L+$-TTJZ|Ex?TveiNg9>H>ke@XX+Z&Wc#)GzREtS30`Ep-^8MKC*?x&3 z2&%nIRhI)M8U*yE`SYo348FNNs)4UQkzKvHo7>5o6PfUdQwi#|7^9^sjH@znA8=UL z!>8_wQwh&z{`w2yXfFPxZPzJRW<&vpp1p_0%R4CjmGuMPt6V-5!2M-{)1vlboVuyZf$6uuhMjX!Fb*!^4~4{aml^NcGyJaP!*@{8az zDhHCj4zHo%07^aonIh2B{|2LOH#Qow&0W#;J2Rh8g9H#fQdNnaD)*HySqJITA`7_# zniFkmcEHVJGw%FdHF4S+T0y|>Hd8dV$(6UzbBJ^T{)538y1Zv*PKr>;Guv-OOLx zv{bN5f8lUG7YxXq6ej)BVNH9K=oZ~+uI{H}DTM1Z3s00BuwzP4FtbTje}k|>$?8%0 zfL#nKSv3STrGTps`@JGqjBw(Dl1)3k`!u$9F2*pAE`KFuwk8$#>lJi8V9MPZVo*~{ z@uMWBMEhsyvs~oApu!EXl>#xYQ4Aga57yr{i#Hf>NL)qfx4Yh+P`ipIsmtCXiSdiv zy$8K-Lb;=&ojj~R&Rj-C8xpSdIH;5lL(h1D2Vvg5&bW4?1bQeODkOIpcUKG$nU19S z$;?S1wy+c|t~(BOwi1jU=Pl~@yN|Op&a(rLj39~pV~PrEh_3g^NsMln6hyt!GPQqM z#6x@A&(5Q>n^;>}#tS5mKXpF=d(}(4pV~Uux|;gmz6iSKyjjF~{2-c84p^)1qg!J4 zc$YovfKuEiD9l`Fl~}+$bwnVm%|MmM(xYkw4H&00h(Dvs3%dZdvE=zwVCW2FZtsgN znq5x{L~R7q6W-(jw;1I5ua?Vrpe0u59kMTB6|56fW~p9>r6JU)wPiL)RnN47k{i(( z(BoN`KejQqlTXuP@NHscZ`ZC|6%1#1JIuVoZ%?lTqLRI|5V;hLGiof1qjI;Mn-Ca@ zCa?cm0YD1uZhHPcE5M++;~a8i;mhZKj(%9O{l1XS?}J^iRzsTfUn%4fpDjYOoFDiG z0wGUAq(Zg~KR|)8GBWc-QcsiUq)hIKN7Tb=$=4lrVvM+$R~ww_re)X;Hj^>*jXyr69`U#j22Lp>XI=YJ+%lz=v5r*Et34so1VReB$ISN6(3K!FWMo>Y)$;j>cvG%E zD>Q^cE1F$Pcjti7eQ3TAzDDEx%CV_3X!x!~$g>*q$6#KspP!#Yw!8?7e)k52H zxJ|A(r~&PB0GsX!dR8#Ja)IV}(MWql(D~q|r^iqQM0xCLuh~YL>nD)(|1Rsc<_}9E znQ(l1I9Rb;|JeF&_IEZT_IG)YHZ2tEr%tbYec`DFI&leaQyD3@VT=1%|9g7HeTE(% zE_q&6kDl&olLUGaBXvq;7G}jIgG6ZPLB;9iVp}&Gu|-&tZ~9E}!o}k6dI8gA!hhYI z#VB8}WrM_T~dbyipT8>B@VACjSJjxz~kolwZss0f+* zAuNhlJ+e1ObS4O&=Fs1+?M^bp5IHxsyWMs(=g?K)F3~KCATtDx47}{OeA@Rf2-lsY z8~mjZ)`E0pS>vVJIwtaxc0sP*65J{qQdb%PC)^L z>)vSS>rvrzce$O5zV-B3x66x1fYABfO*CEgA}b>gX_vsjoPP4Q4YP3Mm*Ds`>fA!; z+lYW^XqZ2&K}c_ihvTAu9t~FHcGBL&?Zo3vmXN%I*`xia@`!c(zB$6$JVy&JkqL)a z^|q)pq218sanI!*u%JE^GcgHDl=fMRMS914N ztV2s`_0-MoF=isrNrCW~pprWjw7Q&<+_`u4J)>p-Q<(&UE1OvyBMa^ysm1ze1j{fdYF^evdsvO#TqMUj(ks_$%__Q1d`)I=Bad2|8rau@4R`o^lz~orUh*;oc&zr zD{wcNk`t*CUPrSQE_92v_`&OkGoX=<4kkC5;UL3OXp{n#Vsk9YQvRuCfo}=yEzI|) zX)f#H-sIg=9Kxp$ME%RCt6J<*^P|Xuts@a8hhwRk^k;~3np)H zS63VN)2(m}-yxjl1Q!%jP;5mWuA+Asc+wD_T_u)BKcZ(Mv^F2%a$y60K>$#o{_^fwR-uq(vCp+ zOe%x}@%u;GmI%q#@|DlnAr`tqpAd8$15fpGYj`#D{2SKtUEgWn`yJLw=!3GF67fA3 z1t7obc!T#J-jEvHV<=OZsF%2zz6G@{;+Q^lC{lcGpj2YmpScuf>`Jt3dz(~u6vQ|v z)B1!F-1I+TwI+{79A@>zdO=?liSy&X3jNHx7pvmK8(EZB)f69^Omb{UqHBs*hJFi> zjA|26=UYy_uoPxL8jJWosGH1`6lmR&5os@qYwIOzr0;wL{V(80?6u&_1%>txxM-1E zSzT4*BjXO3LAO=k4j;jsKu@;8HMy`(T3CXEnt;+^ROX&{^)}Lxz2XZ_qSYHmR0op^ zW%!z@@@hjN*jgnkWAC2;+?aY^g|8KWvytdhy|@B6A;F~MX?B5%p~I=6M;z+c%?O!} zAr4@4jcS`+-fhE%hWE~yPG-dW80yLL5S4N}p{Pl+>F*JQf)0_?dX3-b%>#e1*rl;A zZA!&&*~J&(-~sS4!$Q$cV)Q!1Vr?=kG!@PwJAUt6em!2tV^EjMG-*k)F|NuRdjZuE zP_EacYI?$=D+zgesgkj_s?EjLo{!7!TaGD^8K6~$+p03oVTCD&RDDlFX8P4@al8Y2y{qG>%= z{9|Eg%`i#a2+zGK*bM8qrodwqV5E>N9=qqX527uh9PsawP0Dj-Fx_bI!kZ6$Dobuq z!9y1CH+iPpJ;P2qD;+6EN#znnOoGmNA-QUab5c0#d-l%6enr%@#22D5cD2z?_w#M# zh_WiNTQ6KdkdtrSGz`K|HF@nbNE_gRjgc zUS`)k|H+w+$EA`kS1J!Xh+P-y9HzO?({_U^vw>|5o0Mz{g}5(?Ds`l6>2v59#@$9n{gt(X!&!pT`x*` z(Vgv&%CaQmGeE>WXNIrTEanY``4mI7x?rwzx~MUXhB%_dVVB<0m)+xK)D_i{HhBr1 z4rluC6k#7Injh_wE7H zEYk+V;0z)d^*CXOD-sFMzCB1V$!Yn9FHJs2)mh6QPL5u0m%MHdU)N;^ET)7j1N5Sq zatR;Bg#5qwu^zQ?IOI(p2R+?MZNq5b2){wa?_9J`;REhDXvnkf?HkRUlKl#f2Hgb( zyAU*{^y=%_nob|XrFy%EO?yIf(upKN;_?ikRsHsO|KjJ) z7`>uY-n1WHW&YJbDC#^ja@RJqVq}5C`wKIQ^UHB0D^|v)g9!er*?N5+(eK z%}sO;Z2P!rvUDm?u+I)fcG9sLZL`kkckj-fG7I1Pq5n*=rT<2CApsE0u#39#<2Thu z=Zi(4%)SXGWoFWBFpa%l#E}PvP~Fj7CIOjbL%N?ke40dmUzKP@iC^qn&TQi?2t*$m z)@GJjFDkW6E3*~p7!7=B2;5~w84nQaj*j;;mo6vyYw}$gGWG8{KN4Pd zeoMR6ehV7J?Q(FqSZ|M)6UgSMd@`CYibC6ok$7vsW?<5~C8?PHyMUN#spineJlmWBpy-@$x%57q3o@F6M8NEkc{ST)aDlQCKK&aP3d9vDSS@ z=v4R}az(?`|KJ87j?Cu>|N44P5g!$HZTHFEm*iK;Wr9?z>*Wa>V);8cm{11=y@la_ zDBqT_kP3N9&gGEKs%pUA zMNT0P*XH+nwI3^ZRrr-y!|y< zPvSAMEJZtJ$V^0);{bTy^cQ6ER|jVBn?~O#<;jw5mgq1f*!-+-esNbAZ-zv7w1h8> z0R6aO!ihZ2*0(8;W$B#9T&QvJABLRTnMuzcg6~a%-z@mB+-5G$TY=YbD=PTaj{d_S z=&gq0G{##n%n9HW^DT9}__=?t${~yip(;ysy-V}!`lx+I0%Zafs^hu0G8v`Jcy0We z8&RYZYa~`y>p!sn1=RJro@^L-PJwwZy0??JPA>gCK>7dXbm-USq?*=rdyMNWUSm3- z8HE#Ryz5_*xjDwubS-8u>$Y@`R$$}ThSB>`>l*CTQOwQ($2QI7_gr3fe)#!f{?s>U zdIApyE~NdEfm%@@E76`>_Oz#L-3*c5*)R;C@7CAqCvNuh_@UxU8nsy#xA=ZUMt`#H zA2KWDexUZyFf*@XTVsCv!1;-ay{86IGSHVbbgstQB7t%8LCbOfBBd3~=@Oa^muDnB zY_+K|)yh`T@D%-2kFP>gqLy1imncENg0Im=kYZR=jL@#qmh1DS@mkZ{CBO5FM=Jd} z`~q|X1Zm~eOV0$cnjkoKlrmVdwYxth?gmB$`0t%fu}?xw2iERDO~PvTkEWsBZNdw4 z^#(1=I6hH7LPrmmP1ww6WiphiC7chnVJxP+?Q`a@rUymJ3( zf9}i%C(SH+6L;wWSHN@4wq&`$liOA5V+&6}tkO=9d;2 zh~gJH7(+$E@-^yMB9-!dWy*CO^!Sx=`&a&Ksq0rfHq5mSGtBFR2MEy@x7uG-JNCky z%Ov|sVs$C zsKqkWE4yp#JJkmyOS}1{&SZGUhu7`h6P^)MW`SKLN<7>#QV2No)GrkR#+h*h9!|?OF9aSf%tFbwO zK*19vBSrp^#kZL$R|rsobcC>~o~oGerN~H7PUvf5xaoHy%*%#6Lg2cx$$Q@uly%S( zO43|IZ&2q<;Ry;J{Kga)Lf?4d$P2;{-*-}__GH&<%`QSG?iWIkT)gn|I_1sp<;tp zo|dx~i*BlMt28feqh96LgxrLcBu>^6mDKuAOB7pTwN0^W^__D|3G2IA)?RH(7isM$ z+_~R5SSgsN35T~sZ;(5!81z|l<&83rL@3Hoz6D^s6NH9Rp;MsIRxzOuV|%3jwRb{= znpu|ulo+?St{;Af3Vb6bzO16Vb*)*d&UeB$A%IzzHZdm}X!N^?&Y8xd=ve~e`G%Fg#`Op6^>jXL*? z;Lm>6B)ea1Oqi}!E_sjgtF|J^j}1rairL|9s`&g{F-DT(FNaxCjj$+qmBlj!A8Bob zaUY!S+wB4m?bB&3kp~aH;GlQZsG9jBR?U1f0i5IR`xYxnND|CPOTm zqI`V3P1o`;(jT6m$*TL;k%hyezH*3y4=n%r-bMYqcdgypL}$WdJ=Y#<<-h8No6&(C zC$;Ka&Fy<)-s+6KCZoPNCa6y?JGX8ppUf=~FDqqgm2_-P zWf${IZT>M*jO7z9)8qcrM4X1i|Ib&@Z0&kvE{R=Fvp!yVm2ySC3&x0?XOaOVQM9O# zB`V9^#s$ANBQxoV&rf^=tz7;!O3ckU>JJpb zE(~v`zW6R5&beF3cO+xCSMM9+O?HG8;UoO0-@M`(P@nvXz3lMeqTR*ds%2ZI7=tUN&PVy9aRE;HXcDXH+ZP!&QY01O z)(YH9wENghMa4MLp4p>rk%dTaqmvvQypd}>DpA%=>Uc>}>zV~WnZh%SIvza04KcVE zDh9@>si9W$RFd*-{La(Z5y_`@k5qMQ(W`4`vcvB9;=VZrMPm-y<-Ia|>f8;l)u^p< z3z*7Q2{*Q=Z8M-9h)E9#<{%1a05%4p0)PU66YhS0jGHT5W%8!G#W!C;RTLM+ zbS+pcRVdK^R^i>DM)f)1`{`X&#Xog`iDVvOuOg2DiXm`}9>z#pFZzz~5YK6^64a%W_u)!lIF5YdcU_SBq6e=yqvHSTw2m-Ly)kofI9ruT zAip~FUc~hF?1y2ws|!qB%o(llC&nbp# z{5TKk1zJ>=9Ajp3N4nUv+Oz{;o+Wm;8##XbCuGr72nOyEM?M^!>)j=B%P|qg9=|4w zf2^4HeUo~gra3p)tpm7bLv9dNh+BPs&)nqIiC>A(bA!IE9y9o1EDhE0e|vGMhM{dL z!*AQ!6NOBuMf6PF^*id!UiuJclhl{+2aH<|{0lla@}+GI-~;6`A$2Y*wA3%`T6?l? zdwaknOWO9n^5zT%o5xO2XQRBR-UWZ}w41zFPNf($-^H^9U$?k2U!1V5SwwteUQ2#h*wIZcU^Duv5 z_$6VJ&KDLI&C{*WqfVQ?0X$a%i%EvYVD3KM$+uqDi(aIiP5W`Vee~_oB8|ct5qPLb zK=eS-0&1CpI9%j((UC)H4%ZCsqp32KH>4!lbNZP>ZE-%<4kvt+EtkwH(y!OpMm^T_ z;q{SsqrD1$Em--x$x65*vSB> zv6gneGKoodF71zE1f1RvcSgT%sHpQC_ekfBh26G}A-X%ooyY0%T z)o;pIHLx!dYfoJ!hiQLupZx_tn6Mi7{PMWYVjohB;fm+$VklC2Lu96Tacxs@vB&-==@1ud z6sO2{VWCHnSgcJll-CbqIF=iT{{uKdOFKFACz=d!vB}%{xau6fpN%7ierk+9nP?}) zf<|b2vR!aGCa`E)yj@(u#{w=)`^)?vqO9m+{C-Yb@}*-(skfTz+INJJO%oP&FeY4_ zFh_Q1KjG?6cxXWOorV235?S-<@~ziI9@A?ij2+dfF~Gst^m?+X&+$c|;z#9Y%CqPM zWwK+k5GfBaVy)9PnrE^8SFXIiq9`M&^OtJbC#os7Rm<@sQv)&HDOG#Br90-mQjr-w zj*Kwk%Pr4d{0C+P!=jDP_!@d@D4UPo@Id!mh>WvvSA2$`he@Yv!N#z#PznY`Cmpvv zm$c;*VNSM|rul=~Ux%kJxv}_(f9&8K@JS&)PZoN_GjYJDocrCT*6^7=$?t9%osR`L zP0P4M#Ll8UZjX)q&V@&KXhkS@J?$IiZ8p8^c}!CN3(5sKFu~)4la||K_28WDrK>&V zIkqgY^e4Ny$T-B!GyR~SK*=ej+X2pAOP_-*BJ8gU+T;%+MCn&H(#7Lmq^0t@$rzn% z_>z|)Sqj{+%Rf>2P7$Z?(W%w3zpfidc!0A;ZFa8*?zXRoJ8eqLZDC`23;f?p^M)Iw zrQ`!@G^*o!U_VFv#+FQg7r-!Y@VRF+^2PB?j9kvCy=Tln@#CpGm|@Nnm96tmbCEj4 z#ZGB%eis=JCZYzudg`-%NjST6mnrg#k68N@JMdUkcaE{9n88o2m>aIEsmqC*&UCok zN-Fl3ksCe*DMzSsE6;*roumj}$3Mqw15k7VoIFDAtWVYclP7Qe`MV`m*n3 zL}Dd^&<9Q$|4Q@JeU(z3+m=DNaZ~4XxSfSsmHiKnjwzj+B-sYPF9U%mq_@Xx-K4n< z}wel97Vij3vx0?_kdF`V4T*+Mg{$!jx(KVvK_iz?` zNnCxuCa#+d;G}-%i?54Y@@bi32YaHUK*ziJJ&Gv8b~0q4L4jzguJ*TC3gOH^R)GFLSl8tO#wXs^(? z+;w7$uR{Xe$)uve!!XL0o?xOhtoy*mCotHk1UeQY5>xG3Bz3O5=B?E}*Df$rR!)}t z`NC7H$XL}sFgvX<*|0zhxs*>@`B_o?Y~O~Ve}srZ8+l~?^LO_9(`m*Qzaz)3ZM5@= z53e&^zcUhkvs%-sRhVu>=0@^4a*blJhkeBY+T4_0Amzv?z4wm9Zyr_}K5q2FF-Z9E zf(1$o8HFf@f3FD@nh$R(iSsF1-{>bjl2TRM%Rp< zZC&9b+p=T-=yLhM2)PhvO)QkjxjXC;>}GZ6!0Zr_uA`wCRxSc>X5jsz_ zaOWVMf>J`t|K7&GX!QUC^?~z52;GmVe@cH^`R9D1FJ2S%@b8mxOoz6ZnBBX=O2qTB zfHu~_&5fgv6xc-l*B&%HE&o(j{u8%=`Hmxf1r_CPDcocI%&*esllm6CQJaralTk*n zf|Sf{_uaAmp2rkNOjY@E{y#Ga`Q2`LMu`(7pm(qJY*?^=vT7p#maIQ-w!&SqtKm5; z&}36ehP(V~aCj1kGGu7C?~wzPky3T+ng>UI9Tgw)fwZIX8f$`auHP`P8@59Oz;kt7 zqc(9ln17_?q+0Jn*YLIko10Ei3(?(v!>vY#y#;6P6K`WMAxSNM-l;v}pjyQ;F}2f4 zx^9@o;wRO*RYJT~Zkf>L*vHdHNssF~9wa=0$~L*+&&Ky_brz=17nQ}%|L74B8D@fG zoW}cnTAT|`8w4XXg|aqv1w8(-k(c;*J}ec%bpGb`mJgobNS-`%__7h~<(&$Y5X;A5 zqBA~{QCeyL7=>I+>pZGc^q^$ktGd-meu0x9 z(yyw=vyYWA7LJRoworubL)^Qt;B;=v|G7pI=9yD|n)PVtcK<^~3)l-WX%QQwJz-~> zL9kt6_E5HHa7t!Xh1sKkyT!DI{aIPEVeqJfQp3}pS!Ye&%mKGSFkTy|g@H=Z>B+k~ zzjDnMXq;yhU_dT(tTp10F=$97k**X=46|4C@4`Pwzx(Nkq+UCrf5T5EYxx~b6rQ%{LE3s~Nh4RaukCd?0=6cm^ zE=C0&Y=wmIbc{G@Z?Pqjs#WV$)imq-Xqqen-s!yCPY)np!o2tt4jUwkTFEy(@iXqF zk(Zl)hK|qBfs30b<8O0bsONFg?_#iT39nXR1iX#@J|cA(k9wHQ(1@Z}6c7rG!O{vj zIet9Q&fGtF6YdXbX-Kp%0NWc0Lsb(*;tOQ@<19ZtMOfo|P)%$a|`i$8-X<~?vtVkIkCq-B2Qyvq{|)8dXk8>0Y2%E{7I zwA=2ua>eJrH>kxflp1DO8^68e`yC?To_MpL*}TbWCGW<@KTJ$GeFV9Wk}R z%H}P!J1Y)WeJOT5onfbXE0lt3BOj$7Wo%0b{TLX;heabNZg}qNJytvIjrMU>4-w8|8;RU=0y; z%8YZ+YsvM4yVz6a6((eM$#ML@8|v)M|JpkhIGIPd2e$D;*@p0YJVQ)rsCQd3aT`=` zOY=wO6ggCy1zyIoevwvui2XVBy$ARM+0*BTMe7jxiJlN0yD-ZGp|S!@O_yu36Vf7O?v$ z73s{+gF!omgMKR)f}T;Wn6*RotPL@nluB~{fUxyXI>?tSqe6*c6t7~TK=(My4g-hW z>vz_uA*if3F6U}GSJ>Gk&zp(`d@P=90dEWgxmE>_%!vuX9P_Ke<^CNI8z9yo=K{!f z-TPbAqdrlf)WC;3yt_Tt{C9pfrx+f+?(c@uTx^Oij9i)RlZgwpGaCsu%ngU^bE;5(EldgX=GQ^47qyE~pYLCdbpIBraK3nMNT-putL=0zIFzDpBfAI1z$mh0i} zh=D)WKu!Mb{MB;(PX;k`R|XQ4YvI}A%NcnQv42waNSW|kuJt@TDyLM5zfmHW+cXA) zp*0fwo}h1m5D1MsSn5d8#zi->>Dt(bT#DsO6^TX6kUdp`cV0i|_GCH@*{oR}`Sm&< zBN8iDiM9R*1Fof;q=bz{L*aQ6GiHsF_j_Qv+pAZGXL;*_*+-MO0@avgJpVQ1B5T^B zZ}{Y2+wxO@5pb@_O38-}^ccT>kM4uED!e ztuCg}4qL%hso|%@Fz$lD%E#{&X^3lrD&ps%Q=&@02k`oP=@2GLD*bYLcV;;^f3YX) zJ%3e5{-w`IwbrFoSSM`&SN7IjUyeI}(u;@1lu~NV?UH|a@HeaHiKy|)Do!gs7Twgd zZJAN6zwKvsHnb#oVHzG?UUB7~k`s2( zl9IeSdhfRC=zJC7f=`|4VJ*ixO*UcJRbOZ2gs(YI6fKadL2Lp}MvyIBnFIDp` zM|iA7(|7-#23qepx;}o%7@ND>7a4O*>i^S+m!r*%u!c2R-{Ro|#=YVl4V}6*OlVRc zF=z%?;`Wm+_Cg#6a>IKU9k1dwf{Mt-9;m#}`d9#qI;=&-ICe1m!22Nn<8dvo(6xP5 z24zb@j|uh|qkkZ~a_ZXQOk7C~=47~S4-O-JySOn>?F@$E&R2O=@VCgy-qoqga_Bj;!5A+{cWa6e|6YpZm8= z2CrB8z0Re*3&K!y3xk+^)fK{y??t{Ie||)bdSp%>$ICT64x7+9D?=87v{G%<|Fm&z zqbBtZn02vlNWu<)9I=&Kj8mY6{S{~0KmxOtq}9-IJfFrBQw6ZvULTRmjT?X*5o+#q zHO^Hi97sc&3#qlo?iP<3!d4-qdoCSIryfEo1e;#)6Z#!Bi4#BgO5Eu5^u~hr z2CH9onbUSbh3lK1ShNRsM$V3=X^0hy`ME%BAD>*xCH9)8mg{l+BfzDMa zenAT15LtqVmDNu5%R93eO(Lf8`*2eJnW_JvMiY)TNx)_ui)B3Q;rg9#s{8WMvsM!> z8u7WUF*gnN@wbE{n^jY+4SpwVFs8~7U58sKsDTV5^{GU|tm)gsf|)R(t|g?NEX7~! zVb7?2R6Fw26L=UVI^9m5R_N+=j!2BslL=Bm&R!my2?m}-i)4?aLS@tV(iH~7YWArk z%JFg+w1lzTQnEzCd2!Z?G6?)yAr_QyQ`u~EAWik``16tV} zuwLRS^N9@nxq@OGVv!wU@RoEnuCBWEYo;~ zrSAITsXbH<1f3j8ej?Ol>Me<;e=Zb^#>#&*{6hfmYc1vLp5I;{PkZ1c3sugP+2Tc7 z_HGCBHuE;e0g}-vQDz86o!?Xer+cl>gc;h;;*B2qAR zVAkG!75^?O1blp8N*i!6K969M8LSpq>&)ttPgUrc& zulJMKzs8GIB1=GYtdGc3V8uV+s`H6D59mqXxxf$Hsm9bpC+2(=Y4OH$h1yZeCPS!{ zm?*Obz-_Kfnge^DKw5V)cEi0Wm_I{JWporUTl7uMyb^e50>%Khq67n1 z?H*lN7)1;u*JYB=Bl3!qAG>DdOeKBzBUosf96QsqHCXjWYH)DB% z9;O;_$`TE&59sZU`@XO1JkI0z9Qzz>MJ`kj%~i?6HyRqyKpTb~ zMRAeae_m=QQY=z~#Zq@WUul2vSJ{f@Gx^e>HcNrTjA_3JGsi!;xNa)Io4<=@zVWs) zk5iCQ_CF88&SAk-n0@l)O_W|v&&u2j%cn(m8_up5tCS9953Pa0Oq%Gkhjg4~~)`Nc^*u;UTO@Xu>Do9(Z+n)qmXo zgnTMVoWCmAawVTL+CIB&NdCa3=;C^A(aQKREB`gus{K80DY*Qr?9!hgV`(AhOjxV^ zpoN~eQ$avIPYiz3pxRM8Iovbi*JrLZ?JU(D@_dve->{PNa+KDBWr>p?Iq+^h4+UfPp2elg!HSxpUXSDq z;2c;rqp-ljRxt&jBmKOv)~P%r#4vr@vtM}~Q>Bs{-Vaezwth$U&wjD-c1_w9M;aAh zXY=)94_P2++T=bEBOt!S5XEhrS)5<;4sQEqqFq!YxiM~6aJ4ht3Kz(E!RKPscO_b$ zx&`$6cxsX#a~7-Q8RwYVuVmDI6I5^3b|veKMQ>(;)G+v8g+@a6PK^-lYYsVVlK58KBwH_)_OVByIxEqFAc0Jyey&5oW0>)zGq|sRX z4C$EEdwh`uSN~kEEMf*S_fDoY=`y7S&S&qShMM;u^2LLjK>|O8c>8&rc~R`Lq!Err zeXr9#Q;af`fTvZo{<3{>JiAaAIb0l8>Z zB;I9U?L%>SO1l)CYQ=EyU^wvSE_iKUM^_Dr(D(3@;NV77e({Gd4-Aoa@Lvs!uo1ud ztWDjxLYU2&>n=|osa-y{Mt&-U)g znx?a}pyic~`j5Wox0l_a*QVNnB?#@w>DMk?6l~p8l2kBrO^bvw@86YZw5m0~OF!LB zSr??;kqRZrk5-p!{I7@e!TSNL_i8_~f_E85F&aZ6As(eM=jUgI4a86CI%?w{4-$#3 zOTs5y|LF1Qmtsz0lV-9l(2=e$sl*!+-;2Lfx^=DA)PFeEuqI@iG35iJdygm%M>5FA z{1$=0M82e$@`~Dgu@$OEAn0UP8U3~-c^3XL?w998mw~FN>6{^o z6>Y$O-mB-}P|_0RrnvK(@lc9)DmL4Yw8xs6*r-=A4bG=pqskPO&^%#@1$1L8^m$K> zrnPGj=Rs#i{TP!f*{=|k97oYDinsgIHl2Tt<9Jo=y>K>~MZZBA`jDm1S!@nk^$u;p zFnU-d9jdwW#vY8T2Oh`QRm@)fql7Ee>aPQhx|1Cgoe#p9`kGA<;py+Yd%G+*YZ-4` zU_snx+6ziA!)A6tD!egGt_`j=)i#!J=!OR*vap2pxtr?QiZ17+b&=b~SdSdp3d!}e z`6CB6i48Y=PL0wbo9ZX44P9pI*V3^ebyaiLnWU%N$~4(bwYEk-Cr8)Y z>Ynh&-MRyATm7SyklJqoy~JMKoqXd)4`#)$bc!%)487;jh=4EELoFb0*SS#i32KSbyEe;<;d)Xf%8_hqZ%AAA4VG`kh(qIHS^0p0yVBIuF=R7zH}rz*ID z5zK%R-gg7d-tyP*)wted|5h^*{78*+6!5_x*zEmQ$3s#ksDFC7cAiq!ht*!bdd9Mv zDoPo6qzc)iYYWcS4_I+E(nW4#&+i=O5I$3jVpT32%@Zi+#E&elOp!sZH?TfBl-gj% zKo)ZcW}APRzMJQf*k`4J@_$=vwg+pWCl6d|_wbtIc>uLXh?XB;qW)smr%<_6D#V9d z9h`&)+lqrX*>k&M*4dvXQ+!p(1#%F*>EH%%` z`=^BGv@5wI^cyoi7B8BeP#)K`Y*g#zBb@o-{>yd_W_m4m8)c!Cci>(9-hSY(OtV!x z5p(U3{eyT4g)&=4TI+L3Mle`zG!uoOmyaR)$Ms+3$v4BYr<44p8kwD*@5Gxr%R~Vo z+S_$BA|*}SNMCwc>GUlJa+V*qy0O9Uu<6+`w4@3)SeHER>UhDdpn%TfON7n#VnlJX zQQz*E>gz~`L({-BT;+(~F4LytFo_uX%GxwbT}Qg~)~C%WRkNkme?)zK{Q6~nHx(>K zici5!Kp;QuV%NKOTZZg*6Y13-cfZ}pKW<;AB5NcG1K>uvD0qH;`-%y%yjLQAJzTnL zS>Q497*qJA^fWDI~P;7Jq^fzFoeKM<5K-Cu<@JhMkntR(-mF4 zXGV5RwmJR{7dqcR)b=vEYI!QpQdhHcEDNOk4kQhAN8qc!67BL(DJ)h=vN>*~h~B#9 zDt4z^`%Qa{jrUGMF?hHtN{9|;!VWBg*hFIq5-dsR^00rnfa$~2 zr|a()OCV_u=Pd=9=>AwjEL!@*1>7&%5q%E&ypjR8y)&5ze~2WC^sUfm3OAf_`Yk(< z)fTpSY4GogslEwOs-CeqKa$niVu)x{7gvZfbcS_xqKf*J;nSBbA2>R-Fo!C-yGMb z6;x9JUWZ@&v>(@BjzNPC4qrOqc16u=H)?eOysvw_t|>b^cv5P2})76@NOZM*~U|23SWM} zpZ3w93!|ebZvRsegt>8&!NG9E%Oc_9GgUqD1OHQjp8V+!8-FUyjzn5g6igWC^BjFo! zG^8617?!yT>sBKz$CvNgKT5<5im2CJn-Wb#RLJV*{D+`@9R%JC-hvKKpQzT9d9h!H zi8NmIZ$R?-9cfqAdV*z7LunJ1M<^CK5?PFQ|7GA_?6*#W&u_SJ>g}TS)W0GRZl9G3 zawoj;ucVrZjU}VM@2QjZClXl!NB6O@1MT_}VHX9xT^aR=34JlFlS5K;pmO)RgMcWH zk+DQx)edP4gmF3g_R^kilh8GF_%}WD{`nfS!@Umg94pV`WsalR`U$6mk5tR$bSvv+ zV2ECEUPD>jcXvyo$|qXgD7wbQyR_3o3~AZTm)=+ZICMqJb=Q6Kj0Zy6Wi0sFed(}$ zsc`EpsZLfq*YC$*ItNWGDbuanBNiL%C)}wPfzCnO(%Q2i;d0}eGV0ZA&a{*mIHt18 zl1dtCjnK07UwL&kE!~*ZLwD?qh@G-o3iL{~p4iO=zi)x9 zIoi&D5`MymNMt%o*N*KU@AAe8?a=${GO45Q!RCmMpQm!L+HTsf6e=Y{xtU;{Q@EzH zbnSuOOX8U%_<#uJO&y$1!z_Sl01e{W!t+~jYtI;U|;RK;RH)hrw z_T}CyxGxQhB>L=m{%{KD0u2*$_L*2*#AM4m2`QIP#yVEqj6r9W!2zD~sYh<=B`-R{ zXD^ASlBj(1W;&+IPR0VM>=cFDxn7KW8jB#esQ~Tku+QeVR<9BVxomMZ1)R&^VvR6U(9~L__}1WKr032 z^6_gXhhi;nfR3ekw<; z(DbZ+^r+UTA0uZDOwx9(Q6O8HP>}WbP`t*8uS?T6e}{HnzgWTr8~ZwD)$EPsrvXYu zgH+g;8A}20k@g8C^Lf(#mwI#E>Y+7=hXn#7Yn=OR=IPcz4J*xY?nr~(07n5F>d-SUA6~`%QSDvZ! zA7_IvxLtBs<7{)nEmyrKd*UFPlhOs;Mk_(@EQ!MFbHB*8zVJ+d({(qtUY+2Pvf5x1 z^>9(Z3{2M7j4Bn(6X-R?80mqh;=_@7*rgkeCUshEe44p9(Cj$aCbeoroF2G6_ z{9%W5auL(nG_*zR_TOW9Ax9oswTZ57tNWO}dJjF+{4rHrHD(}#1V_f5e9%sr=Aj;W z*v)b1n6Rle|9JalqF+hRBA_Wtlu+LCq}ZK@J_CRD@f&rSyI&|~2Ic6M2-8Zx%S@%4 zozf~J$P%6K=Ph8V;`JZSaR}p*w=}!4JMJ2U^!L2XwIVu%Murvp9BV0lf7eGj2K%}2 z{cq?`WxVY8aJ3W^_={K}TjCwhLB3P=k;zcb%MVZVi1hS~_~c!^cWVBnoh&KIeRQ_W zc!nUJI!L?Uv$8*6sK)R^JA2u{L7m(KcF?dJ!VAHIrb~3sxRqw1Xha*9(y{>d;%%j2 zrS$tAo`IcS)zDlkmytt0W2-ls>jg!8wZ;OcLubeqL3ZxAN8t7uI-$4>>~cEiq`l@E zf-DAG95}pkOq~S->%Ms`UX$Ui`HS9dHVxB@{wn*UTsm`*KS3qVLp3EZ5Vs-5S!yIz zx{B9YsHwo)FI3A=6#`}AvsWy8-5)!j|8VjYxO7z&d6($*A?bpy}9Z5Uqy@h1P!&2V_jGex?=ov zdCa0x+8b3Kq*>2QVs{1oh+CG1V(?G4Y$fxlfSN1=33w&IObNHV7<)rxRMV>u_V=LC z1~Oc)&JqaU=^1nm|C+pg48C1L ztSZ*;{Po%jzslad5lEiP9gM&a-n~o?YWL(BF_vc7mWjObYs^2|5Z#;++S|pdSpawj zY8R_{AJ6@aZID)j!cjN!e6>mEC5lx>ES|2l8m1M0(#Afo)lIt6zwCAQM+h zR|twH@S^rg4Uq?1`np7Jz}Z{gD>IZrkPd7U_QQDaR5q|EtIqxeZu>wWZ&%nm- zrDKI-OCF#q?H)aZp$bV9pjlo`dppcumZI0-qFvxj=Gm@@bF=8l`s8=HnD zVC($H?%iID1DE{%AxrwQYvJwRS$%%}hlf~w@dPKn{dc!y&w1??%(~z=F?$(3a#!-z zA!2EtL;<~H@B)W&fO;knX*`js!EZiaYJfR_4PqXIw&F~zg&2mV;sP%{WcZI|WKvIZ z2Mg~ZbBHlL*ldAkd46JhZ{Yc$^)G0xjw_~+jMl%|Q)7ShL2^S(TY**>L+F5Ln4#kA++b}*`KM!t@juS+xEi!#SLkRdMi{K zJeC)Gl<&7?U+n&)Ww<&lHypjUw+j`ygOPj}koxHJ)1Xr-MDVM=@d#b$Nq+7NMR|ku z0p_e}qWu{`3g(3PBOXRs5jRjQ6aKwjkNPtp*T8CBV-_JMtV$}zV?;dNdOJk8AfHhl>H{-w zLk!tA?c`p0C4KUe=VNa-MTiYTyZlyWmOTwv zchK&6fmKt3RB1!9^&eHX6+fG~^CrJ4(2W)L*W-S~iC;3AvS({yX`J-CtHu#$Ss-%p zd)Q(H2bS?P%Rf2CN#2CU%^AG(41n(s7W}dU53xx5E&t9eJ@u>KV0PQ-cLYI{C@mGL}@uzIR_p@ZPn@a8=? z6MD~fQ|f#L@=zWgObjD;j1co@Qo7R}e0p|XIG(t+_h$m0inWa6atutAE-RKu z{aGl#`rCA}_2IJt$|g>J(P+k#j<#KdUQ*;F%;`Y?I6QrZAq{>6NM`_$q|5kbP^i!; zh^fBr2wDpr_iHq-;QgWy2{;tBqFTSgNVyUz&aX@?P1E?brVGdC*p@y_>ZDDZG(oKk z=b;Z!U{R7NCrErk*Hxz=&)yR{Sh9-wU__+;#;ZGqwGBw#l3M?d%K?681{>O+;ATU0 zdjEI8pN&aJQ2Y-XGgk;T^1K6g+z2{#O3;+i@BRx3i^As$K3;wO!BaO|@1K~I9N;V& zKRT_f#%Z6@TnT&F=-mrTz$MQg-An(4n|mOV%3YnbVixcr2ek}VfVDo2A)!b>Z>lkr z7mb=IC^azujPK6z{AacL(G_r6Z^#8$A}0ocrfcgxSEvWPB9*UiwA?--zCSd-tI=(} z?Htuz@UdLfOu%aFPMAH|PyRa;yCFlIN7cZ&TTE2XT7A~VyZo$a8nL=Vte|KA#gF$d z+3L630#4-AYl}v5^~6e@M4%1Kna~7J+(qr5%p|PQp>rOTtQG< z7sTO2Ho;YH`HKxwq;N6QeDEC_t#`Iq!kfceDZTAV{8^h(mqMwdgwuji*Wa%=}H< zZ^@{p^?D475-I4}y~GJP-7KFcwcwMe_v>5e!@c(F;u#{HW&W`Q$?`yM_%FMo$Oerz z8_6!NL?QL4q4w&LYnYif%Qr$zueo;4y%KB4(Jd47t7GS|6?&CBv?c^gFEggr`|-o9 ziUM?1uUjdx=bbucrUo|%?Yv^_yr5pj+b5L*Eb~y$NVkakqRO9trzoSjHhYr)OCt7? z3eYJk|3|Osiyi~hOIilL$$d2=DG*z> zXAVD5Y~+Y}%A_jH)Fs$?VpcX%-x?ThNmYn|wzy|Pv_orj;E0y=p~XP>I_h`2X=`!4 z+p(Gy$tpKcL*^h-;L5FtgA;T;mGyLHpkuRXb;bX z^xv0zNWbZAF@=NTh+R)dmZO-8ung>>Roo7FY1k5D`!iWX3HZyoW0I4rn%g~+da35 zJGcAXNb7(Tf-Db*b;@|YY;6TkeQ3SyMU|{wuZEhYd=|A}Wx}R-Gt+mkPZoC3P+kM2 zV~CE=HqV4M(xjnic8ESL;=2RSd0OXA%tfHmRo}ShDF?)^!F`3=m0nUwoZD22KpEd| zuyg~f!lqyU#wFr?8l-w4|A(!xM&bYA={T=S4+qp@J~m0JB+TNPd0WAc#bOFT||4uKYu=}#uswYPny{DkKA z{}CbbLyA?HpSnT%{HVkJF0ZPOrbhjs`53-Jc`oiiMswh=pEmX?^})^e^6i@(lH|0hqg2{Z{LYT#<7xsxlfrC(q_BKFFd>M4BQ3tO|AAbNqVi~5x3t}g~#*n zwuY!-1_hT~vOvq77);Dr%Hn`h<i{w8JzoEi9K}b(#w|%uB0YG zb&tv;eVHOcQ3=$yVWhAU<6R@dTVK6}TC74u*PqX6g8hnn6lZTYr0_8XU;%*qr0AUq zWNb6e9?~>zg^V0`wR+>OBd@w8AlANLT_~mU7D=D>dsxaAX&_vQ z1r~*#xG71Ytw(T%Xu36usPBk5dOqS@8!*543QH>(KO$x?_pWFghi^T0VLx5%^N4gw z0UyUkGySOFqo;3PYgP}j{`5F(B#K(Sp*~(HuHftEv8%FX)xe)Q9?%9N!yt& z|IUTMgkr!eOe&(TjXCO<+UF2v|I08*or?U=Z`SX#+gf^wt5ccw>87No{`W$J*P_LM z&}nGa>5XV#n4)=K7)jn-+|JOgZ|uPZ>$u@T0m{|Md6ERa{b5Y! z1HHlHWgX=|IN?~u`9e)+u#{h6$jolAMr<-P+=)UC9%)53#?+cYFl)2S&8we4_4mbD zrergz+2?KN-3#e_`)<IR9`zYr zS}BagQ@=fa)-RX7z-E)J_bb9~NiI}mQPfFO|XZ!znaI5zRkk6weSwDN~I#KzfZ zlX4r8Dd{$*1j?!)pU7XYR$sH*x1EeSy2xG{cl@|Rc<714Are_;Ohv~kCq_#l)Iw_U zCtR*KC{%}=lC~c|=S;K1@&_b;F^D^di$+D7Vabl|w6ll)D1RfC3o>-NMgJk>ACJ=* z);vP6X9b(ZmFdx8d+dA`pZxr`Bh!|;+9uUQ&s?{_pxo}unJIksz$ckhFyAy2L;*n-KHY3GvJF=qH-k<;1RNg-*cGdw&@B6}2zyw2w4n+NSM%v( z)NZpp`j@n>UM%jejnM<2e^%{{ymoWQCA@%Dm-1w}(mvq`J%cqq5%p))X)4bPjy-yA zDdkMA3Ny^yqC3NbBsiotZ&I4M2WX4*c^;osn$?>p`I`2T z_Mh(0WN{9EP#L}+Brw$ab@q`Z6V=QsejHP&!*2376G$O+ohYTGOP94h^-)4e z!N?)j!&S3zn|@Gwky@FT{CuVxTglb{X3|Pt6J$;Z86jG3{H0eaTWaFq%&S?lR$u;b zL$nu&dUK35ko!o##4DMsd!mU~+Jcs~t~DaX!7xHVBk^jcDNLKF*ba)Lsl;4D%!oro zQs3O4ISFep`KcEf2i>E(@${uycWIT822i7By4etSUM<7^+@ut}vX32i;P$9_$ah`` zT*2@;d?rd8&uWEzE2xpsaM-Zn%MyZc`i)hvFVqS0Qd0U+okD`>36pvU(=%hSNF=h5 zCR!0!Z@hc2=~_7h6k9!qjlgTOqMOf+9uA2Yj;2Bjph_P1QRb{wiVeo?1oJ)0$e;|C zpFfQsIhZMf=&1dgGZ5CBQ+;s`&1|jtCTtRP?{Xghp2L>vsxe#j<LOyX|_AomaN;)vjEcpX5)ShKnK38 zHeBM;}>a$8!ipBitZ7>YiLoq?f!El4)yT7*A#kxDN6DOL^+n9`Ib}V*QN8V zCd&i_S`Z%BY8RoL{_%2Xf~CVHNt2gQZ+wU_egVakgeC#9kcychiA%i-osy>VYhzTO zgAmCLmkdytMsRB!m7gW9%gKxr0bR7ZluC^dm^68P(F9PKlb$p(*bwU7c z7HLKuXy(-=BF{DcGL^N01F3DB71pmHX{&`>IYRb`jU;|~vEiGa5T6h8J>T6KH@f7n zvgB*lT6jo@=Mf{!?OzLwDTE_yjYt?+L&K02=4zo=Pp)}+r?RDA3Pt9}lhY;U$f3n9 zYh|BR8wW@-x){80D2@4whhrPRSU!C}|*i3hf8W1PbS@16a#o~pM89+AbXi;MDFUwg^} z2b})B(##KP<2dP9B{q_s*MVBL&qVRNq6b!t{6|8MBA*t(-?tqx(vWj;=MncF-OQ@xP8B~ zh&eG`8fxvilgnV@`qO{ni>jt_^W;vF*H!Md!S3w=?!-aQ5Lh>O2npbnYxT!#2&>0o zYNW{uRd|{uq_@$KOxV1EmYmwS6^a4orS49iLlX@9@NCTtmcLnjk%LDobm{ItmhRsV zI5TjVW+^J=#&@U6GA8cJnCQEA@k}MOrfQVo)~WwmsZ5?tvIsFAIw1#T8)v6X2CtY` zUd(F3yPV()FFw&>=1P(JEBUfwTq=3PhZcy!4=`nSGDRAJMzTzP+*xi} zWybe*4t1N#k`6mf#=j5ZQ;YMVh2+k^zRYKMYgWKX%A`5VOB=jnZKhBd=>(fzTR$0;o+~! zL^I7Ui-aZe(Xt9dtn*V0;QA-YcYz2T&^w=$ioOIa$JiRpj2Be(xFOqLt0|{KCIIHX zK8PSa-d-H;9;PDiEF7azW7uBFG+&8YeFxWIt&ZTMM$sfQye#EV{gHuI9(<} z7X>j9L^04|QemrR8ZIu~TQ+WlOL8X&P>iR=i%JD0!^A)rHo_<|U;xDpu8N8rlF8%e_Pf#o3 zQm;=pahRY&fn%GD>1TJ;$&%S~n~9G>!k!d0#hY7DRA{K7{D7!4+rQCB#kGs#odQ%O zN3i_IriCIKZUd;`8!q}?3j4E@^u8yw1arqsu5zT>*x^Q_^BF>~vc3NQY z-+S9~)^!zZ|BKGzK7=qbIqKiIf|{~m9FE{+}_xhwQV zKDQ&gjr;w;K@m7#gomAny7RHhq!iO)*$H9a9un_YLyA?QHi+4LMTCzbPSvxWS(zC) z$}kpr9Z~)8t-JWK+et7fMj^efZNwjEj~I6HR*rk8@BN_E4F+7DU(L_v1)tt+>f}m{ zSh$52DH8jorsVCBfh?4tRIs}e&DW0S zge|FlV3hih6gKdCeQ1*h>)oJi!>z9R;yGu1u%2@e5|f(nCECCI;I?u1(o!jBdU@00 zN_a*w%N_*lX_wH}SqKrCHk~GMk_UG9N#;yaXJu7P@fV8S8@3pDA!6o_+{`cf_(fD* zK+IfQYK7k7#vfbM_X=K@nX6v$pkvC2%MzN`tpdet&dA5_nIILA6Ydz(pGhfpBlTn@ zW_3ruVKb2%QS3h9f^V4LQ(zI4ix-zaS5bZwJYtiL%qeF=kvIl}=J*Jg9!SvaQg))NtRl zHM!q@?(=r0snsMg{EvgiKm9Q~%cSTo^>q9)ml1bOY`Z0tq(YYT5Yb%Aqekj%NwNQd zKzec!PsV4$|3A-Msh8%Fp{MD;&oscZ*twa}L1Um=CC@*Bd})SNPd6f$IT~*9SkL$G zE6af1?>7q(`Vtk4mG~0{wI&Oc8B5`gCmJrx&%m89CA;+ZV&LEJ7p7jFmKaYP(}q?v z-2l)A=?_qdT7sT78tt4m20a&LjHlEO2ZSiCEGvz8=-F%xp$WnOkdkg9>&{j z{c#=?O^26Xt87G`tmLcHez5%%TuX;MFIMGXP>$@Y$n6ai--c4QjT)Xe%}ULq3R;bRlKmSH+4K?sw z8{58IC*-tA*Zq90^T97!r&W3j!GNoI|6)Txd&`(0cc^L17Ta+tD)w}3%dGDpwJeTF=O+a>b*^tPb0k{Z*V zkWDo=O{Z}P?BY51BNlF;tBh{CQkga*b<4U#*?M*ry%)nwpT7wSUmv4tzM?KMwUnZd zntrGSlLf20eDxUlL@6^g!i@#>clGM_L9Ul+_=-Fg-0u#*7{%`VaTOEmA+D_#Rp}3{Lk(8#t}ijpzzHv!r9> zg*LXmJ?_xTe&lk%AR@0W588Q`^Q7)xyb|Jq49Z^qb=DrYC>5DPdS^7pWY}_6Ho(e& z@Ue#Tdg?wbQAwMOr@{l8ezmt65(CPSJIP;v%~MU{?8es`|}ny%6te;Q`~ z{Moeg^y7?FsSbKyMhi74(HAbN+s6s4G1yzB#Q=A^hmHHJ*8GX1*KQ3Dvuju9c1Jv)%K90{Gp@Xx+zD-M$soOtLY5K0gMiWYe==nds*mkv`y4J##3g4 z@+YP8wUZ^9dArnLJqNR-Ln&V9LwSrEp4Y65P4q@_mNe{{mxmUTzLyjW;RBqJ_(n0s z4!RENau#YPE;;HkX?o=CR;}^gzyJJ8By=5qyXnXEsG{@jL4e#gfW!*V3NV)#X5ayV z{dQ9yLgQ+`h&hX!rgVm66UC#f+sEO=ST^*NqKefTl~I|d`2%?i%|+=XOszJRcNg5m zekh&?2I^hzX6*1Aer;n5j8g@)CmdvKwY|%=LGgTnXRCY- zWd!X{YxDd)+s;qvqrXv~Ev0>~d)uY(YfO+=8J0KzIB_Snqyik{&{`%k>#js%j~}T5 z=5T5ESI&VKaT0#TuNx9+)|s8>84o`vA(hKTI$W~2@%JX{f;YC{D*&FW&-gOGHs%n# z@2Q%Oak}`stMv7-9i#%Yg8VxDgc3*2`fzD3$mFg*0{TS_4gJe(_Hh+H=X6;Pphm27 z628lM`f6euugNTnh8^rTWPM*IosuJ3jdr)M%CCU-p_g1Ww|C(5QV*;$-`Pdz6<=+#J!K*sXkZu92mm~ZKf zLkH~c+0+|#p~FjJzKUpn@Tf=xWXNX#)%cW9Zu9X!HVw#+fRG9M9eAq8V3j=pY6Jee znS?z`3t>jtVQCp9wCJ#iBAT$tO86r?=KFYp#D{V6oQ0hDYT^HdzUmB#`5oOS< zE=zjMun4!q?(_R*BgFR^8*^GU?%mdd zhEaU{XpPJtvVsyp{PLbtxAT;#$n|0<41i(3wPz9|V19q~K^!Ymn=EnMLFk(xpNQEr z>CCEW-ihrRsxZ7_mHM>tQaL7dh(r){HyedfxNH!bh8eE(oaszzj%!iJLacs41Sy zdZK*mXNI?rv0VN_yu-zI(C>dBn^A zuEh3uMPpx_nx-S$U6gM5z?T{&m1SBAc{MG*nhq^amt_fjAchSKl#ML?vHQ{Ka<749 z=csDhV=4GECn|MwTr4obdmQaU%%>AK* zo@hiFLsR-!O#p8^GC|xBI_xxnGK|Gp5~X<|i~a&wjAxB)+&Yo*!sy#02-;soiFarP z7dupSd-71_E0+ZILioZG_Sj3~x{m6YLC~UCzMj(oX(jlhVJu)y=F*MNf%LF z-Par>dNdMg^nK|6THm$at=?-WBilFvn76Lk!q$T87k`d6m%GZ4w0z@+3XLcxJp5t`;M0D)At6VtCWl_k5o=JziBr-PZH! z#Qs^}nZ=d(8iy@3We*#s^||D+({D&9ioeZQPXbR0-~l9js){Un6{+&0?WgX~y!y%? zF?9xj-1u12pA@(HMr|T2e|1;O(pc?f(X>A1!sf0 zM11s=W{Ou)#Y@ADBifoCE`;Ua8eyl?Y#V7@qOJ_22c>sYv(igG##XfRu?-OUrD4ns3H7rkmC;}%+-G3+UjZZ%A|86 zCT+T${ZRc8Qd~?&%&>lPeVQw~mEGtE1e3_=?;n4a%+Yg z46cQq*Pr{J{-d4eY!l&2`Y@jRpnAs2eUG7!%l+gZEt2W!<@&79`b(UG0l_}2EE_6L z7iGVz9_m0kh*HFTta!WF8qkDc)@313SQA=OG4;8V;fbsJ-sLi8euENPT`Rs%F~NbT zUZmRZdP|c*3+roLb=>E-XxN05=};ybP^Y2BPOPF9Du%v<_H{r?xRE+u1jEh4y>*bByI*pkO0hS zod^DHtocC!MrlI^Bee8Ms90TX!uX+0r6S&?xVS=cwW6V^OaO5Gd{ay{{3*ZF1x23p zBu|kvT;!|^&bcz#OK#N`5x5V>E?UP`&3;~L)N{3@VozOqZ&Na`cq*;0g)SCpa7q&H z&wRyqt7!>VBH{N19wZ@}QX7>zl+{2k_-s3ohhL1WFjljFiGxYh`|t%1A-~0cD0XG? zVd}JhJ{K76RTHjbREi|_(4%VLYmU)BU6uB;v*ty>!{SvaI|*qTC&zaE_jqqH&LOAM z>Xh?ZV?03>FI&trs34zlF%yjRn;5;uW zBY6khOp|#Nm(?2$N2~#;mY49mO8%Ij**%Ya;EN(EN+<52a{Vt((jrH4HjZEZR^J7C z=V$D+i^YC;07B?sfxfyw_yEEDft+OO}ACxmR53cJ?EsG)zVp=10C2CBfWonVb_ z0V+8Qygj-DYh4(cO0^wdB4%7V7k9t^#|t%zqq0u|2dc-}93^};B9I?dN|lrHMH)kx z{o+Z(WNKK1=oR#=9cpHG!Oaddn)7ncvjPY?h^RmQexRTHr-G8v(VfZeNE2`jhA}e{$qL?)hSO5 z?tiMVP!|O7dCZT~F%peckuBM3`!99AzJ-$%$^jmC^O51m)GS2WzG!4tU1+u+1S9E2bW80%bOG6y`2A*q&IM|M6C10=@1iLQFrR^diL``jqf5)s^X5T3cp zXz{1cTBh}k7NiNb+V|E{Um9M?T?KDG*8MUiJBOCi+SQ|pmg|D;w6CUl6O&`K*vDrG zvC^4XPlJo*j+17-d~1r`Of0~=oIdKbb^s7DBJayRtfuHXUycvr^C2IeiLGPjTj$W` zKdDo-9_x{WN&L?9+tOE^$CXqJ=~Yv`1c+L78V=Gs86PCMn~>6T_DtREpjnFt(iCDXNJS64l(0Y($jr`Q3-PR8Ms~~+}_cHX@y~zL! zc{sPJe7iemx1qIQaS^Ook@+MF$RDa`fsOZ=zqK6&8_rmn;yH7@1C)*TE0%1vt+um+ zz87{4yVs6x8M5|u{L z8^tg%dychzd0D>b+Ye?!&U)n6#*1SfAoC>$!V};a5O_rf89(EaklN|TO2yjQa2lmV zXAm#E4$2ainA=(?=Oy@x(DSGyz--B1O-b6@mn$1H?p4IJ6;>mtHU5u68nwz|lr-mT zjhj1C>UmC^OJ{`VeVvq?k8^G*4h92wSfp*9$pCegSm{ui*}NtpvUh zUpTZx$t`b4Hk6^#G#{hL&Bp7`mS(fwwZk%Q4_>xg*fK|%fse#H6(MOB!VAd=n5s&= zJHVSlcOwL=bVkUl+ggSis_Ui~2#9A8-8(TN5tF@&Uq1BLwFZ8$pMBdU-Xiy25zi=|PA+jw7#l;1&Xr%bUO|E*{wmD^3 z`d&L%JzVNxILmXPbVVuN;UIpsdcZEUnL&87xtrx+MyO`}ZqpU3iE`K9Kh8yB#+oK4 z_j~^HJ;B-oj?G`NZwdF2iXi9`0!|$DjElHa(wEz5$B}FQW;^O{*{C#fCP73Cg|-dc%a{%fk7H3p@RG#? z(~mT)qmfS|Pa{d$f#XKNe_m{II>T}s%{0VlKySc3Rt}B`Oovh#ce)5}am}HZA>pY< zBQ*a4>08gF{EAF{zA3bSlGlnA`GJ@7?rCdI&;ep|fKiK<|3Dvi+QU$jv75a9Jx{R; z!rG^iZ3)^k_9*Xu8C7o^RMI1dx$@R2ri6_DVIpDnMTpY~A1%JWJgJi5(p`-rwd$ce zs$@;2o_~qjNe>oXgIJVxj5`Ne2ekDGinQS?ppPO+RBV*EY4=vaKzc{|d^1k*=!Pq* zO_0y#C=;*7aRk#mi50JA6L<#)`jo&mUNgIT+cot8F2_031-eDDM5E9G>uw@VJfl(5 z60ILA@BiAmF?7oduR+7x?YoWW!pfw<@tN7s#hB!Cp=dZu{!|M5`3Ps2){2f}jpVC6 z`o67Lr;9eMEWu`9O=tL>^CvHR9X(FcY3O%3f9E1KVw`Rz#pU*6Pf{RrZ3@mg)ty%F`?lnS7 zWfi210397=Fl$M38~Q#vEFUL@6c>uz!>Y-gA$8;i4;u{1STn~AgsNYE<@g(SCEx!Y z_y8^9;o;OMPfkhy3f(5SSzvgwHHT1HzR_6tL(%d9IS#x^8FQ|(aqBoqTmu`t>RP(# zfHne%rM=22+ROAX6+0Sv4~oi)KH>Y!uL&zq<=s% z6SbMJqyGZoTpu3{wM1+Y3kBGdE-2&+KQ5I84~i*1)zNBiH3Sf3qVI&%U8 z4t28PXt8`YM92M}sL*##RZZ;&u#uE1h7-OT;!(6w$8V^lF}+9pCfmw%q~xsY#ys(&-rz`@1e2-oaXvFUgM zY8%5ET^C0pwc0itQI424q&D~a&%CNXh7-;{v|34O$9kE*mUk_9L|DMO8o?XCX4h?f zaAqbZSYVoMx$(3MM#TA06p*-+1DQgF zGz@M}yvsScLku66xDfe6YiWP{O%7*>?-t?vrcxMRtnD8mifxu0L`z0Yj51;$X3!H) z^$zy+7Kz?n^5w}Cgspi=BN6U3%k3#&xE+th0a)sQMZ?=KB_XC zb9h|^1zt;!A#?;Rp&~6pP_(oHIOH8M z>;E`9?|7>JHjJ0jkWrC&jIxfsXGXHJ_ueD2Ira`kb{PkU2-!2TNmfEgvXT|D_x>5@ zxqJTYrI&;6_}tfhUGGZ;G#SujJp$yh$Dx{eQ5H|MYbV~AZU!}xb`3i!Cv@g~gt;Fv ziYdg%kz9pb-b!a0+!Jar8h{-)OpZA9jARgMOMBB$_id&MYbBr@mU0RGB|-_zrz;M9f(6enm)x`QT}Yt`qWv35R^2v*0bb` z6-EU_LMIRM^%Y1Y!x!JNwtM(*nuS=p>Rk1q%QcP4=a~DlDO$TbPlE@ zXr%^vj;6z%V;WV1+7Sqkz5zpUxCQB3$FP3;i=Mr*{G9q{j{Fv{1UP7%jj)zZ~z7$|l}I7p5$5i#DG= zDe#UlDuE027JaATHMu4MC{AODt3L%9WBTTzVOX9R;?m2W?Q4@PH|JJ;fK8Tlj8U6+UfP$a8->dcAT1r<|vk9yuFb62rCLy{T zgbWIu3v=j;iF+2y^GWaj@(Krj@$u~j(Jaln~j9@K<@DGyaNW&D?H%o0-jX>JJtDG`walz5X*)%1L9oU#P)1E4Yt7}xA$HyIX&}?Q}>J=acp;P zF*kO^eKfbcj;AsV3e~Qq0x@T1a6epNQ zOEnTG6#AXQw9b;RLM)oz!ylPv@3FV`%08ZJt_mh!?QaOwpN-7j zW)T^NLV<4BgT^{N{KgcITi50jdLu_2@dN{2&EaQWMKz-DZi@YjdwBS;aeqWW&}gcS zB`BkE2E1>7eI^B(a58LCjG?58hx!lMXsU3+W<$<%JCSxH4Nr-SLwes#i;;BvEy-I& zl6W7S$okx@`Et_t)i`~zGZ$q4k#V_|c>1CpM?ubpJ`9<*xt^9l5Q>q61}YIh(@iep z$iX^O8W8~x#IlK(h#%}M+7bR9Dz-b@X`{0-Bd7;~uGr_r#f8Ok)$}}z3~@kL*U@&C za|G|mnu=S)L&hTB@mj~PefL7oGr9Ml9-C9jWXC(>$uG_Z-k(Xy3|ESt<3MZK9G`H2 zK@EBV%WQD2Y-E`)qjrclrP9)8f;v5n2c`oCp%qS9E0y>FEfzK}Y%S49A67tMZR@J3 zjXwt9i;|P89o*yPWD5$4rthm>@Vx%Mx=%43@H$%>Beue;GR%Y*SjBGDgvqvVWGHaF zEU81q0iH8FLdc0n%}vSw5?443RJiIaq(oYMUt?CQNZ>=Cj_CPtd&2!oO1L#X@_Oq0 zVOUxydSvTC=S^64d~8T-YCs!peV5NG{C1b4{OYS)e?l)^zR;1lP4{Sea%#lHB-xX9 z@74DYH4YpqRJ8do$;^n;-rVtTN-q;wI*Pr+yqjsN++8KxdIFx;{=J|&8y>%Ro+#)w zd#rPhU+H6{ssgJe9AsF>Saj?mtZONlAGq^aw94Yq*4e-Na9|~wp=(s>a4oO!${1Th z4ogiayOn6b?CyaJOT8?#^<0V47U9gQHht3ND(WZ0x8Th+^6JIm3L{bQ1v58CzR=c+ zcyI^AHNJbCa0)&w_$C(*ML0}h*YSLU!*krG*(2H|h{J#95CUdX7Ov~J`{K$Sr6)h-Aq~NBKc$ZEpwYp7CSVq{`r?ZIOSFN>53Zp>koZ z>Ub%s&w*e>2XxL;V{{$~d1&m%{bwA!XQbO#gul8Ml01*r=UOT(#xPgW#`#%w@KcCS zeQglYJ2PoH%PjB?&YO+A{Deg09g2so>sCy^5d?lwgjg6ZJ6a^qlE>s`rF5+E<(o@HKAdtNxU4 z!6D6&EEl1et5RgVvw%22C9jt^@0e+@ltYB4RgjyMqe80Gxyp+C(4 zbBBl5(R~hq#udl?*OZNKYyHVqyqXlL3zB|$@r+!|VK1=9^Uf`n<=?hYQ`EmG%k{gDFw#1`yTR3XL!M_$vq#7hn{7br;^4CZSinKAJ|_rki+D? z`)t$jxt2O0cyM9_JX6*`Ta%yE+Yv|n=oVB?KOOu>YNiwZzMe@PxdIN5j-d2Y9y^aQbeP8W_W{7G3#%BN_W%stLWCF$mOvg_l< z&kc!eD=wkAGl@|AQ%Lg=5kB6i+bUgY$ zSK`6B)wtrDMQg`F@8deJ=s)_LXrPdK>e>@9b;!G&9Bx7HTZfcranlq=1IwvKV@(p( zWkseTq->MhonfnP`8ya~FpXgIk;#y86jFkd2}J9l|1luw)E26KZUlhM19l3?WVUf< zjeU~{>W*%sgyyO(! z*}xR1J4h9O)(YxB5v%x1+Z<-Gh~i=T>6{JaUyP;Y*i(M_L{%Q z^2X>#KeA4@&Y)JtSSyR0+Eh7z#NHI{Y_G_fQqF~FV9}pbvNnQRvyELA%oSHgY(zd+ z&Z3W3)Uav8(PTMD=ytUc={s$AXts}KAl1qF8CLtTv4BA#!KKdXazGdFl&+_*FU_G* zDBaf*ZbsGJwlF&bu>jw}k&-Q+nG3t}c&M><3zSo96Hhy3!3|O~k+WbD>tuPM83atw|{MLL4sIMx9uF4Io z7HJKEPiOzpbG2e~Zx&?k zwEiH?Ycht!o4%kBm*xM$ch<1Z%WSjfeN>0{?)ezWX-w-Rk6&Y+zgNE_?>j?>-dem9 zY+CHKoTuO3uZ{#`$ubPJu4zQGq>r!%n<<3BAYD zW)b0>3iX@D6`@+}xfD!O)edkGW$ZaBjkr+k==dX7ZgN90SE@4=u&ARUmt1bhdW-_VRbF|O*Q_m<&?{)}2 zYB6)em$}#U^vM9ZhAB85Pq6Cd7}XXMOlg*X zSH4PWf3K6|9hIXHPOak+CvY$`Ok3NlZk5{7XDDvmxKZXks9#}QZ<=-aD}4tZ1r}a9so0SZjQsyWgAh;(+xV z4QR67*hdKYq+Wr)!xF%)|0YMYj^_JiJD3`K3ble~41X7Pah=P@O89@h$R0eKLl4`! zEJNT)IoWXTYzM7b6X#4`&lu03kQ(6Ix0pV|L-X5hd@D7E=4K%F#uA5)J%by=o9ULb zbK{CA;GqCeU{qZAiKdgpru)SiRqfinT0JzY!R#%hSIumbTb5DhCB2&$I2fxsuh7aq3lGtIlV^~T?=hH_YfnjJ zHciVW1g0<;%eX$B|Jy6`B=`2)2rQlbCjcz6{($zC5jOa-HEt(R;&f^25KJbruKEey zkF{(z4C}BMv_E4IjCmY#0E9tzcq{3$Bl3IdgX1ky_0h<8@k`kqnU+Nf?y|;S(B5M) zr?a@UK4K^qaF%=yhnx%8mw&S~sQuF@g<;fo=hVP%62IMZU{dquZ(8z6ro@!o#shHSqU!_5@k+l}z33X2kkVM7kgUflH>SQ> z4EvA!hPB1K&eit~829n=9ZIK<0Ymx7Ri5lB!+}D9Nyky8%ZyCzY9i}GKNRTm|r`gbD8mEayN`uIJ1i5Zuw%dYW~{u7n&j-0`Yz=YQ+-t95>T zgvfC$A%WDVRt3{p-^E*8o}J94_DSsz-KT&Z6|uL6^TIbQo0hxE^!20x5@8z@=8HbNXe{Gt5cd$VjBs1H&R;x5CnLt8F0 z<+hoWTRBvlRD4%~9wQ6at5*1%l8H~>A){{dwl=3^K1Ej3V z>%x6gQwf+K4Yigl-0n&-^}eYv$vN@(3g96YQe3(Z1|0Q17vWQ03P7+!_ZU!5JEfr@zR4NnNjW2>rF^HsRHeR$O4CUbF~i)DLY4!=iYu~gF^&~BbJJHY2T-R<1uD*D-r>3sk!U%_J|_Z=X1J zMr2`e+2UvYMnuCRxY+aQMVZN}vinD#%wLF`<_&lpKRH^Dn$mrzGqtxQtonvOk!+}- zPEvE9wfVmbBACJ#!mpwjtzRW}PfB3_qqkUIqAI`Nw4r#TA-^l&fjHJaxBq;pPAquu zUtvrW82lV%P8Sq8At1fhmEor(+H>F)Ke4^1@0||$fAE3^({02CUbVV84=uG-Rsq>y!^trpfS?ledc>!0<6bsx_=1x7ySnHN zXc)w{YPs;bP*RBs#>DrL(8B_L(Smo+x3=7(pF+SsEBKrbP+=u{t#{<4vXPHIw9(gU zS=X83anTX7)c=@J-A&1~m{7hB=o$B%NAK)wwMaaTYT|N=Nuu&{HQiHP$bd<&S`<)< z04ANp*%?=cq(6P+J-x!O?^%HOpP}|@UOzl}Qm33>3@)`w$Ln9a!nrCSSLaw9?%uj{Ts!nOz7m4Yc7uq-Dpub@=hSb7F)mKAsxPN;mxj<26(AX-gT z8~k>}-PrHUa>qSap8Y6$|KxgGh^`vl3+shJp5#!i2P#^B!>)&JKU%)k6lUC2XV4FC zzv?x;cSwAi)>+a%eA-Xy4xUe?*U<|N<`2oyUFRuv`sn^=u8;vBaa!CC(Otr?g3Iwv zoxTlkz@uSL3-M!rV7zM={h=k?IOEijJ zododiO&gdP<^RU!FXP>o*D$4Sc%Ak10e1~U9EJFFR9pTJx=3O$dvz(sBI6qTPQ+=k zYuI#4C9&CXi-c@fuai)QNEYxfVd59VjWdQ zLX&WxLd3CT=t}Z5ZbyO99|keguX1WaAJw>cc0)=`Tq8rD+Z-inVDH;@`!onvMdhS} zi8jr$ETnwNuk+yUa22`4Z`biHb%A8fTzZA%2>F;O^56`B#TtJ0#*2DiudQ9e^#g+9X`Uy_vn|=~s zUH>@hzvCW0rj6|mU*;dqN;cT()HCKv9zc~*D4gEm){hIVpqxO$@C%T%VonCEu-Yh+L#`cyo zO~L&eGF+lpn&O_*j5(@dUET85H^rU$Zs#?aC*3lszH6_1jVNKZkpI>E>khxjjU-n@ zyzssO1kuTi8<)nuG4DF=Un%lTE;*Rr`&DJ)MP)&ENrXy%X?L;iIfJY;_PGst(wftu zH&JJ!cF6f6PLsBcD5;8X*+kpXQS-^%R;t=nn{;amO!3`o*MAxZE+vWmmld=);T>## zyp4;kl)pc}GC!DPuTmuwey1>DT$DW@ga;VKpU^%WORH_P{dVfT949THMhjLeytuyk zrqn6p&gdhXao?-JrqLM!I1S*DX(u33>5PJ}o!4*@)1q@PT)%e-k%a zA?sZ5It{wlag?nzv_IhZIqk8gdlY>;_vep}hEsfJ+@C8Q*AuuCM$i2lQ@DzL8eRRw zRa(q1rRAxu0v0cpWLCtXzhie>iJ$>TK0KH^-Ur8<9M|y=+e_RrQazRV8H&psv4$?( zA4rQog%J=Q9vi4H9uF=Z2;;db>HM~gY@6qB*0^?%b3*WvqMBS9Gv}w%TXT&_@|>?N zfHJvhNk-#U@VIQ%PeJeK$@sKMN456PYGGfq;4REx*O(T6-7S0hBu*r!FAiw?_2$Ug%mJ)4jN(Hw2 zKGJIoq43aWC(|M{O4GlmbPo_tn0$qp!s)wjwJ-@xJa~9-tCiq2X@?nFG3kw_i{o)j zXMeM-Px7C&!551v2EW(_)bx#uB19||kJ1l;973@Ap(0H=?H4$Wo`Ox(-YF&CiXqwRa|dAyw#oianCV*)IaK$H~X zR=kA-g@%i#LZZH)+zDElPuXxv3$9@MmL41vx#B z%;G4!sKyFVgpRgd-wla8J>LGOO#1Q6pFy>%i{xvDn->=8)vRK*;NJEzuQLtJF(=Pw zP;SOc9J+#A@Cp+=11-F=6@CF}G5>ituvSIekySdTLpe{jzO`t;!u~Gq8WbA@vH4Y* z$LqKP9c9Fl^^;Q_(yjTkyaowjlauKiH{2lNlTM4I$%mxvKausXZw9#5narcbvV}{E zg$K7JdOI)X_J&$1yYFi(gyEFD^cen>FAVi%ovR!Vyg8}T;zVbLI&e*%FIQ`DOal|68+3mje>|~!bJ}%jE_#d zO>5t3kb|sTjfsDHDZNAOdiW- zU-yPXCr~@WEcCxIRV`|hJo8X%X!TVqGJYx;@NU+xl$1Dab&?b8^4=FQiYD)J^X;hD z2%7pah9)_M$>G`$z$V~^m?wEj%d8Eax_| zoOTwjpE>+GHDZkRJ3V;(ti7-=`)w2&3~gxr2Tcr(2d#1{3ZX%MR$OL?TA0ik=3LC*NetxzLNk)S`o9ZwL> z-`nlyNx*I|iXX_Ozz%FehSNoXvTwA~T~YaqmmrhsUH0yK;$!m!WWctCesffbzp{ny zDn|nU;>zKbsc2h~O6C1ej1}#087fTOyEj~dJg1>gAJbs%mxHV6|oF|~(qRvE#wQ?3FOy39VI4VMwrJ)Q0QxCvE z2j;twm5wEUO3vVBKZ!(cl2!IQg&wqsDhr2VNBr@BdvUlrty^u)cT z=F_!cGUB8MmmYO|eC9C-`II&f#v#9P7lj{JCrkb$m*8);A~+zC=lVzUQ+4Va-DPCr6AEveOARqW`sCdX?bf)}>Ne%8~rOTb!d$^BcL6i1O&aKdbOGk0>NH z>|`wx%OP8KsQjn3-##kT@axfOI<2{UK_DXF0CVhh%_b4~C{?5yn&zzyZ&uA6@ zgrXG!7)Ly$uemfj=e&a{mWRHlq*<19#%&P4Lm>WVJyz?f+B-V6~fN@ zX-@}LhOL`2`l%}v(RtT(MhXQdcg_ccbJWYb6z&q2E!(v((JhWQN=o6%J z$Gd!^m+!UrDUt8j7JqB#2=L+ef#uQns7ojySiZq9rRP~&8>_H(I<<$1WiclILuwqH zZB8tfV$85-Gr}zaJt)z3mgEoYRQ=q~JO@E%OQY57ntWyeL~i-Ki7#%Q*v6S#v2N7{ zk1&zN6$`*gfFpgqsleEL(Rv-*4{Z;wsp=9d1Z2c}bXk^g+4HS_Yo-~N^a0vl{Zh&7 zuInC+iV#E?LalUof3UZ?z4V)0f6GfHZqdZ4$JM$t*XPgPedqDB)2oln1eEoL?>bK0eW#== z$!000;50s|wns}ie)*=1Lz5w|&smHG zsrpy_Z`}>xx>fy_Ql)?G}3tT2dQ@)nJ{>Cq^~w{Cun%>ObPD*eW3;NkdHHGRI5nNloC+9QUds!E^z`Mtmyh&m4>8aRyt;lsN#hM8b z=g&lp8<@mB+vd|gN$P_7VkT+ACnD=dIfZ?inVS+no@H?d zG`AgG-6!k5gWh;j(f4uN+elky(e?K7JG%*BqCm$A9Pr`F7gjAA9;(tLS<8i0PL zAyEpZCnNd5L1}Hw#vV#@x@{Af2}C&BFE%GsO5)@ z#N%8sF9%rWD=tzJ32nKdK0Dk-EWZ_}kCQG9cr}~Mc(H~S0~^8dHbu$okJU{0qe?E` zb?IZ^;)xpb9mx&*0W~zJrzYS}pOp}G*VC0I7Ew;xbHCEov zquF9;T!8jlSGaK7(ZRC1O)O9uI9!|(o` z6TgUa=Z=$+e=8D8_b0>}TX8gQExg4RyJtSySxOKt$@mE38u64eh!ACVt2u*Yv$mIq;uJ#{T zG7CzY(;2cFZN09Ns8R;my~)a%^0eR0xj&y-O%NWr1T$#qJPuAT89an#>!WOKhbkkE z?IVAiu!s1Q7H1yO8#g=EM?6V$r9Lr^@!aCHyBnPYc#-|B3ED%Fy&Jo*3hFgbfZzA9 zmyAF@6|f~g2w#;bX^OYb@A27w^l?&gv5!9vk>8JcGu%PnY$!b-ye0yN@+ zYo@R7M>6$sZXciM6>rd>O}>Uy+|1XZ)4iHt?BW$U|76vmJUYSQCga43LndA*2*;>n zFIBNf6eh{7n?Hl$%}d{L;4KL655)!Q!eq z1T5pf(qaw9@={M+$CnTUMF%WV;W^KP$F+(C;jjtk(G4$!HWnVg==VvbJf`u zdh>$gZOFJeZuNO>+xHt!qBWep+J2grfO91bTgd!aFh_I;I_iCjE-tQ0!*^r##5>8? z)zBsl^AEs28Y=lr_rG^91L43&9fs+^R;uGd*&ZjmUM zO)NAE`*P1EhzQAV$c&mvi@Ca5x^g^8psI1#Az3cEEgt(gd+7G1-4y?XQ0?-7;FRuq zV$u%(7?jGUjxVE}2FXBHiwKSc)kY>m0;?z7bdNE43>q)yN$)e#X5O%pz2+au{*#1! zDzLqz?kn%*cYZbD0nDrfkg-~^RBUkfZg(Atj|vWR{i-l z-$5<1qHp9{qn&z@pqtWDkB(l?i4TQxLeaU0lPrF~qyynG+xsL6oGzHoPK_rdQGuni z^+^v4V2$V!d?t_Im*c*ZajFJePsT6jr^eV!Ucci6heX+e3!N1c2d~OfoN_$??#lEV zJ5>5KKW&=%0F7$>i!}QCy}w}*q-#1MfPaGj?Mv7^_RxVqnq&k=i0F(uafmqjLVRSp zL5w&mfo2^vsG!+-owYZCh`6AeTxJ33PpyrnI0_o`i3B=c>GUs0L^zF$H|R6ikw2<+ z$~3*c=N6opAGzftV5UGK8B1?AL=r4P@n5ahw%%}Lg&h&HN{W zA_X;VAr&ZSR~(ZcGZ^UZj{XI9C3srSRsxp|b`Bw}&?9T096=%;kN=$@491eAW?raK za+;o5BExdvRUIhKU!CN@fnwIZA|kQh%}W4JXs7%9@m4doFW9!p^!w^tKEKALk)vQB zj4|cP|6(Q+u`qe3YSw?5f+Bq+3EtG(E2NXGP?}qA8We5U8@B9Fpv(8oxP`<@|7EVI zx{z{syxDh8X(lya+aa$gF#Ft>^d98iz`?6hco=-q@0M6>PYHe}3ru(9P7pYLCclff z%pP_O)@PoH4fD&6Xe*a|hLtJ)Zs=?F*bnvw1%q%!XDKJKVT{Bfa-({)u)_4KyP&ztx?3Kl<$Eb2T0J z7LzN(AGZT1@`ZiBb$@g!uF)NMpilg_2d_^5%MlTX2K0b*_$G8*HZ79M+uY!DXvmps zSKfbCoSfsyFRfgNvTiYl(o@Xa%7uk5eR)k#sI#p^yDy>e0D{_44_3;4)q0qa<+%TJA2+KRdJt)uRxXOV4G@xd6#0yS>%w=L z>vi5~y0{%3%Kt>*kiC!q7(mnPD>I#uXZxJ$Iy$Tr8n5zKo;7~)YRb`c(O~x_&+l4U z>^pnFbcyBURAndZ3VP$xgoYFGg3)LD7SEU$D&a&VzaO0TCn%bpR8njFxVO9cu{>SI z?MZH6`|!qf64`ssZBompv9M9~p$j@$flV>X)O5h@Y6C8YPd1a#ce}J71^@Q?E3*CL zt@j3UA2gpzthk@AUMC&qY2;Lhm_8A(m|fzLI2g~?Rp(Yo51rp#*@&01cyzQM1&drq zvCk!=z@6lOQ(sWL)~z(6Hx0Fuy&n4vtOY%<6?5rtMo*B--s|>3OSMc%5A!Sc$qn&? zi?3vnqyl)D5X)kIViNf8;Dub!NFF}uZ|p%JHIi^y=4t=eK@_sWdVBw*HIfnCG*@voHs7j{#ySo((qMi`EFMKYeP8< z1DKY+Kxl)!%Cuj>($}l&gX29oF7EZ*=%`c|aI*?lagxnOo;9OX8sFgR)!r-bKK@JH z)Dbce?IMiua@2MI1UqZMC?~Fn*61=<(3CB|m9*mZdB33ZRO{-iTCrJs^6-l1|6qqHg#Jtr|0G9CC4rYMHf4)dsE46VWUhF^zAVD z+LU+G!94|hGgx=L2sBTH9sc%CxUxniyM+XZ*Ao{ceZI04G9-U_{%k~rYB7v&F08EglZwdJ(y>R1UiTPlF0OqKWAtddcAZ8lB7 zgU+>Q-AGho@}}iM=+RZ>_xSzpMk&E)4YH`d4>V_SeX?jWeRBS^b#a9DLcDK-r%u@f?HGKHnA+wTVli2N~;7LrS*>~du`OAHle91{ez3jDE;+wKhX+o+(% zvzIl!Q>OwSbJbg8zIfGqJ`g)h7pOJrJUX(rlM8PLBAF1}M73w9xwktKv=wqktR$#E z7!4HFHlj$!tPS>R!m0kdK2S09+FlfF&x@-)nhh9cJqAx^vLD1y+O%WOf!|?$biudi zUZhDa7dSd804643bXHzDRkyn$LP2v2%z)9qIqA+_DF}a3QbSDvas-2Nn=Us{xt5BS zu9;>?+`Mb>4*>p9caJ5q`0fd~dg3~Qm~ELm7z~wpqMwRz$=;EwEKq0HaCxhaB!yAi zg8X}v&wWfIilZ(%51clI7}Z?wwg6G{W7m!mqTq##VI$+QFlDGa#=M%aty$RrgL^KC zy_M!FENZ`-TncgU0GGE<5VHQUq%z zv#*I>>3t4VnVnC@U(Jqx#=BJo=jF?jm)*(Str-_1T@nD>b_DBaV+r zP9T`kY?z3ws9}v#EYeJ5EV1CJ_f=!QE)&IMm_5B-HCeXJN&q1m_ly68lxba-GbB4$ z{2)G0@)DNEPqLwWetYpP{vApjj-y_I9Pan}?0fr*)VO-2_e)L(wf)J!NO`rhg$&nc z>x@D*58eax_+iglCuX0h2=xkli5PJ#tsnX2AwZRD_aFZaqIIt|>E-LaHZ?KB47wRP zWF^IUNzGL`g~d55jen9@d!1XM~KD!R(fekZH*<*+8ZI%&&zNyl` z1|X%|CKmjbDo+Q6f^!mLZI)la1>QT7uRH<*&R(GiI9sA8UQM6yg#x+R1z5|EKPk(W zZF`)CAn{f*B|CcR8h0-{zLvS{MqV}J~N7eX^`n9-1Z9DnU%6kj_Y%-hCKdF_Cn3vU@XOO)pva9 z-+wS6Ijq86n&n2tL#vrQ6k-c_4J-0lcJ#-&2ph^&@C8VRM`bamVwNtp7TdnEg3c}vL-4QsV@ zHP4X?ubcV=rrxiof}IjVKIgqh6iMH`(P)a--~#^=VHVU`@)N8!$j|m7iC0yJh-vq|q_@s6;EgCS z!@jV)_v~l@YR{Dhh}Bb7uKA3}1(|!_Cr;V%6Jfk^HWh9kWM^8jU;{7wi$Bi+5C{a#Yyvvba@%z{og<+~BxOK))2_f{^(F8>Uw zBYpQq52kp$;RjK4N<%7%33~G@7sSH_4;4oc0ZX*+?^YV@PPSsR((t!n5G2Zuqbu8UJ<6kFoP%&Ur`(4u2>m1YX7qa;E zomETHf(-dJ;k*P#b3vu>BeQ22#+UG-a4`23bL5Ul_#|&n#3?1E6M=d1-}s5Xi)wB=x7{HsVXfB4+FNpg3y3BHD8|4h4<-9&X$pKv^xqvc(KmWJ*Qwcvy$ee0cOOqcL7Pou+T!OT{wY9RG8Wgjfdr3Ep zzE^i`fbKh)jdexBx#BpzBHk=~?%lTdc{I7i%`2a|okBY{pZ%x*?F+D{_*Llf7q$<4 zjv|rxg-bfgie)TUvXBq(14pCnrZ<#%IGBZ=8&{_i@_6v64W7Wx)Y1bR35KkmZH@YC zQjdm+uh(dm-+d{Ozwxf{@#B9)9!^)vFrFv^$*(Ryi`QrJ*b=1A5}Y2TwBU25x(PTiNUk( zlU&zdn%U{Mm*S<6%A|RcsC}_{%F$&!%znG_GRA`U($e;!kL8Bjv$q?5v$gW zkeokU1wTa#*vW_~%QBm9k*MF}F>qWWE-niomI&zV6Pj}_Qbs?8Wt^@v^Ms2~DVn&Q z?$T$oL1@^#R;T~>?^1BKzLR>P;+ZJD)y1K0hE2M#${wcQJwx&BqGM7zIVB)oYpLA6 zE7i4zXH$WQn>yGT_gdyo(@4zdN^+&qU*anMZ1;ksHH4N{!%b0OoDFg8~s zuCU^rH>m;I2U89e6KU}@Zi@GGt8dO+^tamjoL-iU`zpv*+~R&hoi}mEnxgAY?DW4f zEQR5i#ApDAG(Ti*>EQ*tZv^7? zuYA(|Q8ensQe?FM@M<%A~VB_qUVvu;dM@@q;D|OYirYPzxTcuu$%AY3{|2q%B zqLUW<4|QycWi-XbLn8M^qn;D#6vyfgINx42Pt7N9Y=d$tasrxhweXBjXQccD{k355 z6F~^-qd5-PW!ti0Guaxy{HUpSH{PW|&;urb4{RR;Y%KawVaWH2JypGlV}zL^oL3I zyi7!wJ}#L+1-D^sMhnCoL5)w~x7l8#Ha#L4uJZLewQbhb`@x|aIW!yB(?N#w0r_&5 zT_3P|?ZS9`CVYY~EqP1^zXa-N&6|7suX1~8liX3=a=yY4%bYe?@%S8v^VCaR z^||_!k{)N9`z?xM^6xoyTe)ICR8N&AZ%)YC3Q}mX>P3MAx!=zs(^$+_B+C_b(yp9% z1N8T@IyfjH(Y=2xbVwdx>BM^t6Q@tyy_!5P=u-4AP@)4wR45I8_qyt*WWeHwh4_#I zyRCk0tWiP-m@?+ZXtB3|5!!P%du`MZ&}XQKm0H zOPXVHg8hzn<8&eP?I(qi(WU|l)ZfE-HTXJ+IsTnQ6ZCJgbRaV8Ob1{-22F>?dHR-H z<7{O{9JCC83`nBW#`%OyN$6XEA}1AEIPO*ZYuFXGOgt5eM zaj~y91?W|b1;?8fyI$nkm2$lv z+D%sIX)zE|aZ}2P|5f@oN3n0J6WZ1w#reTW-dx5jM6rzVc}K=TYmZQZX-!*UaJ*4M z1(W)~`1IMU~2V=E1xR%C(aVa2c4&)(+b*i&LS zS>ii_yaOn%&q>wZREWtbgpi426CFAfBXhtOO9~szzm+Cdse&7cdl@h3$kb+LcFy`; z>RWvWyAG%l_$5XIcxTsFae-Px0>)Na*u+{I?DOIle6sBQ;oV;TK+vmGh1iQ zV$EL}B(D46V#~_RAItFQ^JF|(^k7>Ir44SibQ>WPhSUL`7@{hjinG4FqVkN~n*>lg zI`z7e!Hr1r`HB06aO6@aCLFt?;oUR4OC7Co;UW}#r2IRRl;|fgJ%Bl{K4cm0n561U zpBY3|Mr|^C@!J(}t(m&~y8#1;QS{>+BLw<}ORFIkF?~5JB<0N&vW`vJ@a7;7f;o3%M#?kpCFuEdRfq{Xj7v~3A_FG{ zw*>{Kym)b$N#uEw8cttvdL$D0c|4{#xdoZ0qgtlez6K+{RB#l6^Qqm$BNwqvkgZOv z^fJ?JBhvq4>InOhc-X+orF_om+Zl*j3$^ce&Pa%kID{pl_t1+60CvlGQuAcGusTjib@G#sVgZ0^R}Z)vFsnwm{-?o;d>qy zPLcw)GQw`^+qlYP1@k+(-uo%gf4s_wNhoS`u}Bf0l@`l5fR@E)&+vA4It^a5^vyDd ztjq5;9oDmhXC^ESBz>+|p|(@oZaWkn!z;6yr#Yb=LOXq57F> z8p%+zzr3w*`3z7)s$1o1r%wsuRg4-+khk-rw~l4R<;g4A+z_tU=!Z~5~D{BFkk0r=-rRwL}? zrFUTpRn7dkDJ9&KKkOI#+ms^}yF@$IwhZNH?>f;!>11&?Hl zBm^i{8Z6JTynt(E5e+kc5?xiSnokeO+B_xk#Pl0I2A1cBj{h~iNKp*tFFpU`KPqyh z^(QGppM)I6yENBY6`Hce`poruyWPUE)wnCyTdH4it)XX&A^cp15UhFsn^Q*Ib1c~6 zti*ptbuCG+0f`oV+B`%PzA$;POG2oVz9N~&_GEsHr-8t6>m+D!d73p9+Yc4)Q@HjZ zhVe?juXUd%%5AWx&OH@q=hh{^44#WX9n>WhZE=7rA|`>xq0T&c#`ZJwu~$GsVkuU* z^!Y&)#Loh`tKG%O{gla=fY7(-7JX>YW_j?EP#k>}IxJghaV^DbGc4OoI8FQYNEp9{ ziS5zatsj?{4JLx5w&zzx>X@-(JCH{h`ISY0tu;4&b%~KySUic4jPgC|jdO4DK@KOJ7m>ckW?6ejskiW6^a;%!q}wD%0qN z3kTGsp~jfYnlQrEB5CreW6}Xlda&o`(LVn`MWtUkxpPIKH{z4~H=k~O!P&7Y@8-z> zJ>LpWd`z3=h2Tr$puE*lxyVJ2pX<|C0uT&y*)04MNusotOmNDa!&qS~K9d|SEh9$g zXTTdT%j5${RSuJ#Lfwt>}%0oipLKQ>!D`E}_cMyj6Hq)U6XVEHI$ zFh4d!L+ZgzLh{)9hHU36{^h0HYR|&2!w$Aw+m4@7P{FKxY+?0Iks^F`DH_IS_2tQ> zHBC<(Lh{V7XUX7OX4CJqa7N~3dqXOrROV)Th4Jxi#pLi?P@oF3YG)}n-7QSAte`ye zlk-V7%yXivnm)&ckkh!!m*vsTR}|hS_s}G`@he0P!gv%#!ZX_%y=|x^&P+EWOB3RbEj4P#$_$61(R?EbeJevcgZm0*JWzs{G0uvxw6Lfe1u+_ z;O}HNeUJyDTmN7^f|FS#s$L!|AxXRbX zV{fd>ANvj28?X7lA~rG3qM?ygbil&>ZtVoS%Q?59-kn*37`OcDxCjQq;3ebwuVVs6 zWeJIMjwHojln(5BzVvxjQDJ3{uTeT-1B9BZ7S4Y78o!Tq`SD7-XVKezbUC(@YNW_p z8vP145G;8=+MrkKu<3O_VJrJ7xreripd1lw1 zZkOujLrRgfI!^;2M2n z+>QosmeRghBBs^S$9vS?{#5a5Gdxj9T@AK5V)9jd$4!{D-BrW>mf>A0bG(N2acO4k zZ2OlK(X*fa8;rVLwek=3ELtQ?8(}{*E&x9PfAO1;_u{!~g?JK1e&C>Y+4%3T)5lA% z?!}Pp2ZEC*de%p``GlT4ktTq}?dUeopTtRW?pYX43{%q(T`4JhYU4y#>V6u9103ezB_J z)`X%ci?MHZ0%JSV-e>US1Z;LRjIc5tjTdNR%bv$wfUgj-OrR}~eGhd$(D|XgHe$50 zSup!IaXsUC!EdGIvRS*w#nVT>NrnR2Vfm`TJHZEF-`WeW6-u9Sy7*Por9{ ztLFuqmk(Qll??R;m+HIz8;e8rUOINd0WM%A$S~ObvabJG4$#5$F@bkg8f*>dUuDx5 zOdq{@|B*mA(uOzKNCj;#&u-m3PTggt$@5!`+y*n~MB1kno{u z3wFzI7vv=;5?&P3a+{JwsN5FqnKfrP?+FHftAg!ICC52l8flIc?{lrC`D<_+I$2Fc z6M(E!(2pnaS%=r!3^Cp$|4!Fq-@WbA`8%Di;&0?%{~CInM_%g7Zy!2;Hag98XNW=O zt6>XXg&O|_vQT9r5$PD4fU3D%*2fyUpj)e^zTg>Ee4X=r5?>Et83SM7C( zQK?3C8#k14`*G1Zj?m@L({AWt4x2QNS3^8yzaP55+Atk7l%{R5b1-W%Aw@C5H0Scu z#7_DVP_U}BBXN4IW#L#E6PPcaUKrPi?J<|j9scTkB%}C#9za704qU zilRft@b4;HOW0Hnn6iObD1mh0Y#f^u9 zQDx!kFaCQ?f@xmRG}HY8yY|DnO2%E?gHbDF_2NU-CQx>gP90wIO_x#}p-988r~0fb z7F57gbm!BDv1*pi(8FM``R(kg{`r!?tkPi~!Wy*ipwi}4CZeLU*25fQEM0v^!FQ1t zi~tsAoK$?r#(F<>9Y}I=Vn%a3?{g z6N~Kj9%1tR^?V%C-{NW7E`yv#JX`a_nlMg7UeqoBlfi=%$?JL4kLMNrKpy=t;PWJ= zrj{k?#}y2-BKhv&`UznDhgR>rtWq5r%n4_7ym@{=)>?)c;3ohZ4+=6HCVU5_TdFyrebad zSp2}S``a6C?`=gg4!eR8Z;!`c)Q~SC*E|V`I#Y0lfxKzo`WhFg)kDLz-uY3 zuue@HgxpY)JRCV?Iz6ObXMWMk)5YC=n@;`d%6a%Er0cDrnt;DR%<|HL4I^ar18?xy zghz&xlWY^iwc?~8ta5FuuglUb9bmOd^*%Gf{TN~NHzT)^`qRs|-u`BvX&H1Y+N^84 z2*NN>i$3=0kpAwR8~oDrO~)3P0>#tcpgO(TtJ$2pX}ZAf+0ezl?a#?`NW2WQF_CrK zwKh78E(Ph4VM5EiXk3eU+}DOA{n#!VKykavMPm9sQ3zPCmf(CrxX)W!vQo@Dd#1$T#ea@}zJteYx5SpD%r&+&WvQ0T!KwKM@w4Q!>^>Sq!WuD&dauBGI$3b~$ zcHH~M5u+3W*#@`3 zpJ^A(Ux%dgLgZAg0Zm(CRpohj7J$ILlp_}(^D1Lj)zWdw_sgaC*nF7)g12I>&nBVk z_scj+>eo=a6p$rNqQb-UJUbRU)!NKKZug!Rpaf&w5)E=gjYxhw_N&8IkxFsf==x^0 z@F(=aQJ;f+k;pp|QD`TyY$p;`6>^JmI__2Dc?Eis-%Dv zqgPcEYvw(dQJclg`h>FS!hMWD2aT#kBGsl>{e*w%VlyOV(6jq^zlm-N${(lxb8QUb zU^m}iL~0o{OwXv8e{KR!!~wG|5Z{hdr-FyOIQKign%W@C?!>r-upY44%L(7#fK=$q z&LKf!@RRaUQt~wG7RV)Zq)94qIjs}zuYMj8x`0okWD>DoP$|5;kkC1UTlAMkmOw(u zIQm*J>XE<}Jb-2SYAtrS7m3*PBU&x`fo4P<9dC&IU`>F`8pR}0A-MNGQ&U{w#?1;1 zDIY3qT6Jnu7XvbrjEQC#6GAt+JRm@PT^wg@ zKRmhEVgX2a)Kld(E8}#*U}}mhIBo)?AG9;EQ3wQ!qK2My!&I)t0-9(}m3xLH;?|i5 z{`aIXP&2DgJq&Kp$}@MGI9;kM$0nON+{rh8mAn$aq(t8L;`ufP8q!#8=7O!I2o$S9 zgI35nznbTrqE}vOW>3EygK-e3`=pbsG{{VHxzDtXoL@tvp<ZKxoa+w8|HD1-qY&GrKajIP~Ekv#%`5C){`tZhmxlf~L z37l#!ysR733j#~Gy{ld+5Gm`#K5R1Wmy{~X;-LRgOlwX)hWW)AYc3qpJ-6&Fu#}YKHO+AYr624b1k=eg=HCQCPXLaan^y;Zptv${p zD}25~2Ew+ZyBj?=ou$5w(~(aZ6bL)eYF@X)_LzWD_l!-YMUmmRY{-y-4A{9{Y~_(O z;>8Q*RD#Qc>uLwyXCxaFvN|@0KwWENfV#l3s0_)UJA+ye=}2IGB9}`|CaXeF&}ZJ{ za?)XVVmmSVW&LLy=^+5Pqrp&jo_Zz8yn9cN*D^LqyPif8AF>~v+xlGDo>v08*y8F|*~$zmu-S=;B$>Aj7&yT8@JcBT{P}@3c*o=ku0jil2vBNv zvBM!(L3Lw!Gofrf_JC4Q$;wHc$po?q4=@emmC4}W1uJ+(%9_)cFWbB-8l9vpNt6)d zt*nSBn(hCVKM~0C1kV3A$q6Sm2?B;-k73*!-W$h{kef zF{iZA>v#^uqePX$eUHbzJUqd96nwn?My2D3RULkiM)Wnf?WmidRB1QM8-Ozwc5#5q zgO_6AGPvFJAJv_u*cUW8oOET?zYL~KDKB@A)h%ojOckjhg_jH%0h#x)>wHBp3x7`LlAKTu^hw+qx_sBH4%4F!4w+V7c?!Tmi8)sIxX!!u2QI*cXTCk2mE%JSU7Gqh8 zEL1{#BOw?we{^)?3fzclQGvppVXuReyrXY)<3G^JRc!BRstM@)AfZ67vM{%Z%>O3X zKv!m2sEhu9TBXMVq{6p^lNBDmSAtlcz}&c+RlAP4;qy8ZCTntfHzN=VhuorfXRbA~ zt|kffaak_ya=a0$#i!RLPtSXfv`RO>nSbg#Wbdz)o1XWOp3$UlA$jKeBjdD}3??x- zd4J?&2Y)gXLbQe#%P#MbUoxRohh=rz+xT)(pnE7(Mr9>gXCCSye|R+IsG2Q27Lshs z^VM%OKM=_rYh~p9> z438s>_vBX4zS{_3CqvA~eoja!VR!$WwlQ;(^Yg5j zlrU)h%%QTp5GD0mh6m2c$La0>78R6<3iMgmk9+#PkYls^@`k7ppjMVIlHg&3iWb(} zqc&JKz1{nPu}!qOaCj-od1W4;0RW*sEL&~7UgW%|IjnT zTA}DOI%WA^)c&+8tB4TNsk_-o!siroO?tS?!W%5GX>n443r?o=uPWhyX;S>?uf^FeS zLG8`8qlhmCMH7J)HdnFU-o_7b6IVmGhVEWm1~(haXFd%Or}gU{BaP3BJ70|2-RVTQ z5)p^kb+RJncvl`>e44Wv*2!K`uu1)rb$JWfojbOcylh^Qn@h${HC7lK=Qq)A{@0M^ z3!@5r34jB{M%izA%xjrxqkGT=kuIoXoH>U-{Ktgil>_5CNb zg+2JrFh1JOa$QA{D=S_6+QR}>5rxM)d7J`rDW%H)y`?RJRszoF17Qv5y?>l!c0Pm~ zFHjZn<9fZSdTV3f0Rxz}NGjb^3OyV0@`_t}!$-Q-IoxavB}6I+Ey01*@xFq940YoI zwHGs%r9oVQ$m?v-JL|9M;6~EdyoX?Zi;NCg1|Nc3Y+nf$Gh{KHYPp)c+MUV_8Z;IY zHv=ZDaL+N4hf1U#TuLeZ9gb>A{pd{d^Mz)__{+o($8jgJl_F|XS}r7P;X7Pdm0Nk=B{PiDr7mJ z;h)~VASYMuxu^5}Wa2LKWXQ6(fF^nOU3P2?fGu&!W+T51hv#vv7Rd{hzC|VrSBQ3yA>@aC4NKu?5 zpMn3z?2U~RP(h+pI~6O}G5yW(&%mR+>;0B5_UywZAs8c2YFRM9+Bm)kr?EmK6k1sO zZ$iAsweHeo<7v?{L7fy%)k4sgdBxj54YXLV0T}Idxi7T0NqL0O57rCo@ zJ{S=^+W_oQAOvYrKY?4}0f3JY+3&>UogMlL!xuCp1sa=c8w_H*AeTrV>=R{i|J8pA zz(qBV76f(NjvOWmp#EoQ{44uAIq6O{J!Zax>;B892O=dw=^xB>aEo6RKA9*qrVoaF zh)CK>N#__gX0`-5rZ^7DR<+AgO&a$cCsQg$0gXFZOs}@S;{WPqyJqNSwWZqr6LFNL z&7J=kvE#xY*-8^3q^|^0r!W1))_q$ozpP`^-bpumo|m^2{5=y}E$f|T{re@3T<)Bj z@Nn|0F+slOY3bH97a`*S(zB4_BykxtkO8Vsd(R|;EfBgH0g$xTBtMuVC z&!Ef&->2HhFa8jVmODDH=_~$>5 z41l2-X{BUUxtj;@w-Y@!OR{#N=Z>%u5A><1o5Cy2%Z^in#C;`&Nq>@ExZ+ zQm>{Z+un!Tw8f)4&@sk@%;oy~<(XqCXD3x4Cd@rWKhRn!TmKN$QGk>^=q*xE#+sDkh;<)o4^P@Zfl z-+X8C170^awEe~17EF3WZ;*@s_JRIzvn6)|{w|81@a;%W-&S!ulk4fR-pfzMUaogB zQl-*kEEcfn6BrG*layE=34UeFyAZ&Mp7ao2zu;3%YXo0=`9C}pIK}uUe`K$yym_zZ zXggYxire(r*$iJiPW4rkN1ClCkkB%>?jTj(*2GB+ti`4lYca_*qvCD;sO<-tMvX`l z5<)3%rMEcB+}E{eoRbNxNm&e85k-xYMZ^Rn`K-`{m!|ww(s1Pkg}~w}`>keHSRmy; zKFseN#POOTz`WH}!F{FgTvz-}%#&TVb=n$o*Y6+Gh$P~yBvd!va$ZsW*qkB1f1%O) zfuTgB2VT2iprZ*h8EXl$EG20c@2Vh%IQBOBR7hbxX;yh1>Js#;G6y!GiadYJS2&Yl zr(x4yN~iJy;3a=sIryF}%&c|pL>_f!j^6O{ls}zIg1K&Gu1 zhnO$c!TT0#XeV*FM{648QhUDd-HLE~FvOV8vdu?x$2uh`QT`@juqeA|ntEZ^*8!n7 zU7K_oS8@Uy!=rr7G@~~EtZJ!ZmLt-^y79)xKEf4V6V+l05+#Tm?yan2-K_!{we|dRW!HoAij3X93e%VjN-bl|=WK@d_3sCpF{@u)A<#}1t6Fa1> z{Z$gDo+?m;;9&jOaTfL8>5(%U1Wf00x8gu`YyJZ$=Yg=`Pm)`La6|4 z{dzV3l$T*DUHYvm%Esw3oEvkVZo58X5?^Z1H#IpszKhjNyyadU><(}-d}A9D6*u)Q z4wv$k3jJ^bA{%3X{9C*+L!p)rqC0x#`FH(2@bPCc^)(=5#}LMV_{9^A`lA_ozLF(c ztPy0#V6qA3(X4dA$w3R^GQ594n6jwF~683!zSGrI=}Wv-883DL#UO0U7PmG0Jy2X=AJ-uguX?qqDi)GXkt>U4VLi>$ugQJ?pCenH=F=3lx|#t z{v4%Kk~V+eHD;nW>_HvJ+haB(^m#rpFJx1<1ZR1f!Nm?FApJOAQPqkZt{TfiWR}Gcx_Jvir*pu z6aFoGw+fn!7(;IY??DUhGHj8LR>8_`XOA*j7MbYPyXQ5xNff77GiAt?2)6FTq@O>s z-@CQKFrJfOsR|zr0DG3 zgCh3oQXI>V+OKY&gF-;^SVbjXK7cbpfKa8?E<tjQL1^+vl?w>*%cJ++lbhRZP?mjJf3Iw6}s089XRH;^X<=(T2 z{Nasa4LQj{8HsjRo*H*2Swc)$Xw>{}rRrW~ElMH$w*VXLPsiRByG%ze=XcH*p)b6F z8GgDzyi`V&9Q_Q?HIQ#G8%G^qTiYZso)_#M3luy4f{i&?X_l(JP;xN6v!0561_#sB zhJFIEpTV8Ms2_6>@jDd$g`-}Z&AdGDR)beCcPKMpq%$q7P%Yj0O8e&B zOsxG?iMlQSkDJw@w*dc!4p*!ZMjsJ`)yb2exI5^yGXw`)@TE#TZz*r7S*N5|BLh6X zQ`4)FmT-fI#G*wqwa!$ZD-WZ9`2kih<0ByJv;r_o?c z!l?3{{|>=R2RRlf6TlO{mTCTp6RCc|O8HjRoC(Eh2zPSR)EPIU0h#Y^kcBzl4Bk5B zTCbqNr)jHsf_-GEdRJTiCcPd@zQ38GMLFp`N~8Syq9U(8=mRwT3Qz)BOBKek{euNG zrawOzSx4?N0@V>Ur-8Ib@0vhr8oQgiTT!{WkyUn=VVfI#sg>QBtx`HD z;O}6&Xn7KMkEyWOiiA)E!m9cwyCm!?nf(G73lZa1YS2FfAp1Rxt&PSN{XMl&@pmr&{vB#>LXw@>%3ihO_Y z>#fzlhrv&QP|*TzH$5ej_}{HNZ0TR0P4a9@Vy`Zz2)XxoAmmmZ(MS;mT6?pVKbmxg zW<~KD`64m)T1_w4~s2 zjqc{b9_@M$HBW@4{iwAcr!1}2m&|WZF&y$=BC{Z#(2}eCe*IO7h>{Ad(bU5su|yQP zm|Z231t1lDC^|h~au=(j6xHLRh@?eX{VM%3)ye_9XMbk0&DLfU?5Ym)6JKME4P%2H z20~i1y~9%yF)Du}eA-UDy){Ass!!X)E8iW2=-m7<6W(2;k zt^_}|%G>1X>Y`SkZ|++_)7HT$)8_g}i=D4Q_e)hC>;c3(KDW8U?W+`dp{pkfj2L69 zlj7#}@8@VDog*9QLZ5_Al-?lySK?K^&^Lg?$j7;Hc4z~V=eV8kDF+1}rFS0%p9Lc8 zNXB&Zo~~^Ej|3L?pf<-p9*S^m}dHe)e!v@EZv< zKy(%GbK8-3QTH-SoY_8mGxqpC#>cF6eh?nss*C6csucu9qNWVEN$-m{^=oIYKBw=X zrgJW(1mk|sBM8m4Iv}xZf9h_e8@K*FK^?ASuy^9OK7A>WekITvMHkGM z!Tu!Jz_o2C!Ij$i`O6X6k9(qfxTF_*Md~St{JcZ%d6w<|O`kaBI>z~9?^cWB2N!2W zgzKf>#$?*~gvt0sH6 zK1*j^x`Udrd;nfDxr!<31J41@tQo?7&M;41(%ak?sNKN*Z7=crU2%kw^=bj>@@@dL+Us z`NgwSy=gg^PC2BF{sE0CgH*D;Sz=I-?(b%Rex=8M@kq3_L~#%Y^U&QQ<6_e$C7l6UKIy&ABCb($AIOOXX&n=cXm*s(O2R zDjo#8go_i30A&<8=_V&4^-!EX$K&io?P%Oj!)Ly=Z*=u~b=Ity#i#45f}yD_BKR$F4a=^v{66whX!Y z(-|@`+>d!mxfMHkhaMQ_3XIYowq*(L;)oY7N{@&PGIJR>r%1Q2_NH?y+&F7ZM4CRf zTDG{c&8}{7BoF3K1Wh)w_SBiYyH9?!lF;kMm+gKf!>t{CjULP22sj_nfblQUlrdfU z$}XyK0^YTOS6xpw)?;MKp;C}1nN)*XcXc&~h2kLT59Q5UtA@_@Ew(X0itxz7O4xAc@#P+h?$MUdYb5PTmfv+=-FVJ!NOj7H zMZm?|fZgS@toeiAFKVCiZsb%vU-54>=Wb(i`=)kRVbzFq8+|s-SL@YkTz~&E$*S`y zU%1f|Z5xHcVK7dS(o|<&=v%;Xo;rOMuUPR>i*XUFkTgr@zO>)d$t@I}m=6S1`-?XH zX(9_x%hZH+j@rF5J~#is9p_qkCMpHP+fKsx#zaEhR4SK*liu2R#SXYRLi$Nd#_tVowl_ZDVlHP^3&ddRO@H!wuWzHa-P8+Y+w28;mRjBbIRlb@xQS?CKoT#-2@IRf%3 zO$SwuwN1f*o?x+B`Si)?f=K<3c>|_Su(a*JymfPVgho;%;VCr5GahDHCja~})rpzv zbw*GjJefe`>D-Fj^C7@8 z%2YW{Bv-RH;Yi!J_?6u=V`@u3j(Gj_MwKGbi`NA~&iuu?y*YmpID>ur^c&_EM;hLh zC8V#Ts;w%|UD`1wn@Cf=ub#*igsViAf7<-g@iDvh_)mh>!_8|``XTy%%gWj|@ornQXpYm) zKyW4)=9GFKA@s@UU0i8Ngs_4GX_lz%C{eFMgc)C#2+Xez zS=7ycoHRJwP*D5l>U&l5ccyq6aMh}v`g$V0P$4E*_f?bR@mJ?j6g{J>H{vBK(2@eN726PS6dXf6n^fn zJ8zC2o0sofOkK^R?;>i8XX^B;kRi^Qe<2Vf&|cs2-BBl-gIC;Uc+{F0poB=1^5=9k z3oh*f8Yz2g`O^l(uh%!tyVmtCDdwRRC4?b(-d?-!l}gZjoVlzzvHr?C4es$(0;ifT zdqLEsz$+Dp38@%kEoOwj^^OBN5;Tz2dK%P%>PkvrlzP8%(76o~uqiuxM0qIos}lmV zl7AN6< z+O8$Gc1#JMap)sKR36HQ3!yX>6Goh+ zg3`?4xNO$_V{Zp>mCwsJ^7-=2-mA0lK1*RR!;fymtGFUH!zXbhhPCo*8>Y{?_n3NpKRi+uiYu=)9yWziwMoec5qUoIXGb`G^=* z(8**TibFL)?kz^f1SKlEcCFq{Lf^48vp!3LOI-yP|>Ec20eT4L{g?k@g1A%SDr5)V+#|>NA5nRV;FcHa7o-;x@%0JdwE6a za<(I|a{WdnLhGwv9yOM%%Gch7oxN^7s9ccSo?}5V>Tkz6th{^TYCs5MNwCUT^Zg-&e~UJ+kxqCs#RN0bN`xxjeRZ0W$V?LV(DwVuzHke9Z8bH8Nb9@*rzufG`v?qAtO=xflo&WH}-3~;tFsNMEV zJw4DxUi&UrF!oA8`I}-;tlpJBFE-$je`U+JKr#4@2S}!Fw&oUA!}ttF#dnXAblJY6 zLyh=EQSA56e;G?gwe+dr4OTLYK>4zu{@=Z;DXZ8&FJAv_3_^fSae&|J< zDmZHRbB8rgB6;kRAF6ipt@wAku|*89wiQ%8X=g4u*%64$BKa^8xV8GsVH`C{fm&ny zD|DfUW~pzTW8;u{;{M$|brZMtS9zDlL-I27vP6NY`kq2v&v;t>oOa2mMKkL-Ia;kA zy2U7^UaKnpj?z%poty2=;gfC(3S2Sf1xBvzOoQ24y+sYI(LNa|EqE1fApwcb9{cCs z;)FLjUwFb-uk|3PbI|IVh3W6Dd#eZXusL$t{xY=_)p~Geu<~TCwxRjOMyrOd1&SUk zaS=Nk;Z_&Wx4nRwy!=PYO3GSePAh+G-o0`&uRK>~$OR7NDr!o?k zc8c>u{94;%<}7)K01`tpYJtpW=4r_v0WwkxEfdD0j@RY?ypyW| zpMP69;s`TjX0XqjDmc^GiGQQo<&ewYjDX}8wWx}z(=8gwpAIzIwjWT7Mv=ywDX zHXnU2#1o}TW7(~t!8SegCy#hR94$@?5_SD-X3m&bT3Q?4cn?4xq)Tbi{%(N# zB{S+-svgZPwn1W&i|i`zH0|7XW3=Btz2|HOkrf!7op;5*nZ>MNFJ!9a4)tS4j|~dY zEwiYz(3vJsJ+GKsw6h1L%n!ERYqiZc$C>u$DX$2^pG6+K)%ID}6WV)M_~+%)*!|M4 z6&nIj7-P8-j&9v4@?X$)D07JP_UP}}9!Sm@d!X;U$&g>7_{|kY6K;AOKwe1(1x_KW z(JuqBkRMbS?e>p~)WcubsJ64V=v&tsafjT=_Y)}$Z^ub);u}BIR=>ZAn|~Sy#TqZJ z&h*e21zVplt!15UpOQT5o~tI&^~*C`zvZ6jbrvS{wdWhPajkY0 zhv7B+dX&gZ_u#1cFBawg%l4-%6QfbQf3ZZwhOj;b$yN+!3<=DxUSXK9Onq*{lT7&B ziU&;@bRXUYz43fWU@dj~u5 z-%cjCjxD~Bb2cL``Xok}WKRy@LsY$!tthIZOv*S+o+oN}43C29evr2BUJ^aw%MGtu zg9aVcdR9jGcZ`Px%!!9SVoEQ~6$ra9e}38YHyg_^`?(;Qb@p9<=F2lnRSpma+AnWr zQ+M8JFNkWRvaS(>-zo>Mi9jNMJ~pNI3C1T9J#Z$kVE69SQPiXM-Bmxt{)+mf{{Z~H zE3*V6dKbYoK>(25smBO^meAbe*7VjzqZqf&CuutYm;@)&x?^U9H9l;6 zl~~XUJDLVB!IS*V&}R8dk(}WtKFW8si$4j=v-`KAjcP1oeV!z?e!1ESuC0Q8S~64) zmPSH%IX!^S zx>Q3J(6#25N|L2UH7mYq@6WQ;VC^+)!#{;@lKUsjU^l6~1lvhPcFiyOiZ5jBN%9qG zVk==^te2y+ZQB(+S%sbfYJ3P~t8LLoW}S;sK-*TQqr_OVQDu?4ATae|UeV?#ZrU^B zy_;m&B=`p5%ZK)(Cyd+j*n5Lbg@oA1()_JG`bJxFxgy=Ngs@z$@dZOeOxub-mfhUv zbF|J-?k-o@FjqW&JFuYG=EgZrSfNOAU*QyM&E?DE4XL-j$N4afA#y`qVIHBcR))Tp+sbbAgqd1e; zH-sH~p`1i_@9}L^-tE<^qY4)8c%N`d;Nyd3{Q{SvhJM@00#QZ%d`#kxYcPsXj5e&t z0C@1caxt1^uR)M((2#n#14901y-?4Ua3In zre%ElMov2^5Hs+K6_b;X%Z&58pJ|HDT)@CK^3_JTso=How&_BNpZB{9N~f(Q!f!piBFgY(pr1G90*~Eoy-@!=bmxl6^IFE}+ZIZ8(uqfrVhPNs0P6TK!9}(N! z+Mb8tToBwjOPs#@plXNQd6mHmVGq&#Vk?L1FS(P!hXO+R{bShhh?B>ch4vYFyC*NF8ubDHL$u z_^w@e-|ZG5VO{;7&f()!wq$ly13f5_#dZbZLpTv*Id?y zhRnZ@c3k#9M(>Z@_$ZEl^J$(~RI6$yeSbrBVVu8gr=2``c80p#DGj#ggn2!+XJ4+7 zCjKCoRXhKNs-JOAP@Wm@B4dnObQOG!WwfY)zM^2^n6d6@-y1-A^+tsHJ=KUiAb=o} z?zf{Ol1rpw$@%WBzoH@XR^q#A`P^uul|08&F8`lPC6|kiW>T3`~hQO5b1&v*Y z7hNREUZq^Ttn*1vp=ry6k2XUWR>-BXWd4hpW_jz<(3eRY2pwr&tb=AC-HYUdU%5)KW1SzbK;@|%~sd*5LHE8KC$tYWY0jMtG%cmQ(}@ZUTjtwt>=nC*d9L{ zqi1Di-l=m3Oa^n}$y+3}BqcQ%x*SS9FHEGhd+?@^>-MK7@>P@>CPo;*)r-Laj(3eEy!9+s3n zs0JTVot1hVI6*PQd4%~3{NhoQrIsy(DvQO_QJHrnA4*RbXyav@mqASFXR&2JDs-!J zKsoP*{)c&0iGc^SeIdRfGP>)S9hrYkrQ0i1m#hErL>1_Nmo<$M0eVPcZe>ivW7H-n z`o5?FEtXlFa=v{e{)SZ}?%ofeA{jw_cCU7QX5P)&#LUeE<-n2zX`AN$|IQxl*B!g< z_1c0jskayS>-Y1H#qJ_V?_8I1)Zv8r zv0&M&(E2uEA7_DZYvmG50(3#bP>cg#qI*IYcmF%@Q8dUH#B<8^HL4}Av`8orR4wRj zUQS)bmQx^FjK4pzh7)2Q=`l@QCVnlBi-zj$XjG`FvpkeRDW}NA!+=($_>PsZ%Bjkm z(P5e2J={d>V}x0(dXG4CJn7iK;i~x17sf|kWvC&X*^l~bYR7MB>U1_r8xXy}etijC zEDq8ul&SAVLsp-h_u!A)zj4H=4Q$D_6G^A~O(jcknXpYkV>a-jl}U{@i#PVflkkkc z{*ogsn#1)L>GMqc7<#OQF{J|%jOix~%q78jc2`SUN#7YIXo#JS0qnK+$j^f`{DldiT(Gdd6-QIj>8c_GJ1wx!$7A|2aDEc&h(D zidUkHD6YM;cd|3Hx9m+<*&?#nC6SRmyH>7!MRM((k+@x>n-$lVy~*bH{{H^29&+#J z^M1Ww=bYzxFdGQ-|8}v)^h3&R{E&dU2dbV?B02gb!~Q|!1N}LDFTNx;0v2QY2Af~< zEq1~IkoYuvs9DBuZX#c0gIyTtgyLv;c-ESt)HVv03wd}?=7Z+tMe7)B3$m z-?JVt!RWSe7;P^c5Vf+w3tp^pLg(~7VjZ8LMG{)>l?u&NpB;*HOU%lt1)O(l{mbUq zy5hO=99r*A%o=@So>y?A?^2gQrH`!uR%GNAmNP7EuzhbtEEk~Y>MfqRpj$lJa#GIJ z1~8;?YZTPuwj1yg_?%m#P@d8deQE9VsuH zdAyNvdnOitHA!p|C#d9~=ZIz8#qg|4f2~%3B$jHM*<7e^e%F47TRB{<$;z<>PT0*q^i|V71DkBb{3>&K zlMwp|L}d6m^|BHy%gpahd&OV+^3=ZzjAOXDMOai9+hA_@$1X@%8!$zP0(2p_0UpJz zkJU<00qYNTC_^q%Y}2n4j6LJnlO9!OyqpsI2-WoBkAFG}oUgPldTL3avZAa1mjH1^ zSvuT3(&2dNRJIwOxR((02gf=!ddqnHM!-;WI$gWp^EMihkY*+QG=!r4gFe=JOIEFi zIf`gG$&SB&$*zfgD`OD6n`6YJQ}~w$)F4!i=%oIuQ4mR` z0g)AszHgqqAn8{(QetwW`9P+-R_jn#uv(M!{T7@bb61>iGgd*%Sm%Wp{nuQX0&20( zDTWTm{%ooVTd|;yY$H+rg>iODbfsuk{JZ6sP3c|lL=}typ{i+@nW%AP2|FZu$1#m~ z^|Tu!ZNbQTd1ofvK!cYTfgV&IVv1~x)bA8*>Jrm1xWK^|q3@AvM(3rUsYM2DgTHlS zhV1f@qpX=r&3@BR8Y=9_`|*# zc{*8(PpH?wE^whg4Gzv9Ul%y2p8bnUJqT`rFPp>v_FZx|Xck-P|85;iq6T4kBVV)> zaJ@;|lXUZn+V8&}=m#Sx06?AHJIIw{8hnMgJ+D4mxEy_PQRPPGcwr-t7V1=qU3)dEk_Qd3gY zJ+$Je_uIvr_Zd}9v}N+Q<%MNBsGi$hf7o(hRiZI;p$mrxxi2`(2r?M@ch| zG_M1XENm2s(khM=!`Uqual@b(ZPe~z$ogf5OJxjnie#wQyxCI7T$@Q_A=<%_<+io) zixzmy{*TI<9KxqZ{u5rIm&C(z>Xpcv3iliK|k~To*sd-}f?VE3n@k#VgKMQ&-jyxX;p{wF=kGa|G;=8s#6W zw{GA@oX8rl59?3NT|}kvgoU_?W-qQf=J);y+`tTmO|IHNo&rp)V90aU(uV#62Gp)Q zh&1GAQhLRd1)K{wXOQE|#hZ}fr>`wCUShS3R2DMdZxQH>=TR`}(?G7L<+5)fEUJEk zp+gkT_)i)d`#YQQZ>k!&1WU|b355Hx=sx`L_HGqDXYNe-VOs-VI7MZq*Radce=YH@ z0yRd!E}!vho%GQbd13=7_h16md-GP6+dhg4t+(uzUL)aJt>p^WDtwv0@$oi>MEW0eKJd25ibpm1E^Bo z1RlZHR`cRaZ9#qY%?1OmA(SK1qeY_USjI>vbr4#t+h0jVCvg7JkDTCU9XOxVn)37% z^l5TzVpLr_N{p(gUaN!Ont*xU9+vrf?^K~=jX-}+r1=uid={2XI~Mm2ERl6odik^a zn4K#|cnQizo1>nQ;PVPa)9?Dg>Dg9FK?MftBpLjnDX6gvuo{CtYoQO!8ss8DC)$-b zrEwikV%IZN>go0+86ci4tTKW*ai+9Ipszdc(jgM*%D*FL_kVYN66zeW2Vw)jn-o*9sT{`(^V6?Q&?MXOfBvZTrEwOAH-=?b7Q93$!AQ1T@ddmIKy4Ig_*&YnSSy2n z4?T+>-CATOTa6L~(f&ed$->EP&-2o2<&DD>{-M`MA5IC6$wAe!NCW;|GNX-GU&U!k zNbs5@;xi6U0fP4WimkkuA_~N82*Ey3wcV~bX$>9zWyD1S$`-TWw(&YV}2rH61(^ZdmbF$gTB2SyCer2(*? zd_h{y+jQYloGdGmQi6Qw-{p=|Af@$6GjW@`oXjM5N)NB+ROjjaw|+^K7UqzhxlhTW zS7G#!grjM4JD(`MjrCdQQe&ZCD5$L9IlH1OaRz+Tmm5fDl`W;@N}v1BDz##rTJB#$ z{rtZzfKSObG{R5jwO1%6*!#V6IyloqwD(CG3>-VmAM^pB1_jc(tA??)u$mea1IrwX z<*JtIRbpYfhU@U}Ui;BVA~$I(jPv2`T0bDvV$VT{kAIK9q9^bo%w5_$P)QXWskEGZ z%OolilH0cz{+{0;-pXM+nWbb5e_t;VP|d z?!{46^gU7x0Ih>#1?9!H%}Ei^$&)@=%yyV0Bxr2Adx*Vc@5?~@Y1Z?$=O^o~2uV(i zGPK!7cZ6hZpS~GX{`Sdl_p+qEyghSsiWi#BAgbaf4E|N9*+e96DKoNfcb@}zRd9jd z;)FtVQj`z%zC7ZWCTqn5df3I}b6C%(}cf3s7Kwr(K*_dfH~?kr7O zm*e*SGOje_&FhTp5~(~noPFisbE7KJgVOBdmT$Yfwt^*42Gu6(^7pCo*Dq|`^Otn% z(mhNMT7A4STr)nVt^_n$V8-J#sxBL@7q2V7e55;HCf5-QXoSUC*RWzH+#J$yy!F<- z#4>y_!4T^PM5mJe?*SKKHX>54ddu&%xv7tKcS&0`^SZqcpRY9!PR2=qvAtrcF&J=r z&$_iH6;9Q_UNf-N)NS0bcy*448CYLTzjRPGye?KP#AeDjVyS~e&#C`h8Wz-Vk4Y}m zL0OV#I;SF#1I%+SQP8a0eX{Mam)^(W2OC0Vzv-r7SA-Spo|BjEy_2K#;^?)5n-U}m zBtkZ+4ql!TI@uP5-L_Y2FocLC+pcm59-@4L-|_ah2i6kK-t3``)`YKSYurFZdr~1c zFRH)$pq5)Hjn$<8TYWB~i^awa0*V-cylrb$YgZ%FEo5X(L}Z>Z*IZNlF_D=j$M(%c zasP4nH3{eepAyokA_<_G~>ScxCX3;Y28s^i! zDa;&tf>&ZM64J`^1g4lECSb@Sl1Z&~kW?F!en>Jol#lTRQ8MX6!^RFXQ zpZ^X~_bt2q+-rQ%VQJ`5uR#HIQZ9J5C(%3W==ho_RuO^^;8ZhvyCja@1IFc&hq^@T z`vMiGMJyjngD)@RqGj@it(iTU;ml# zOLvYt6^f~)&dnqxxAL**@t4luJpnRHYe()qdrZLI*?)K&4ofpqF!h4E80AD`uWE+( zTMkbhUkm=cQ*oOJ@%d*Y`Vsvsb~_hAIUA%i?#XMsMm|pWA8E>q7F+u|&gnW(N&qQc z!$Uwjy=6iS)*}IVBF*Q~7DaMymJ65iR|l}3N(uZYw2}J~shno@N|mGbEf&#GMJ)Kh ztZZN^bBt^M><``?YzG0|Plp@`_|#uISc&k&D`*1`DjUY8u+MExo)htQ6Mp- zTUTo$(;gRVTnKhmeeNew^=cp*}H5pxP6@X*AYAMP=8+zwF13X zn}YH6)#h;9o&w6H79s;;ut%6A4Z4HqrfRVW`a9*+oUmc?-@yYMP8#fU;wt)JeAZTL z`0T*8FUm3GrCp&6In9bv$zcbMLfU9PDQszwclUEK`n`p?ox2fX+q*gJv67o6Cw+`l z{djw!5r!TM=W6@>9HdHbI}2xA3Z0wH=>JmuSs6!M9VNUAWeMcLb{&%eP`H;0<$!mc zU~~5#8>s34+Dssdul_BLpzviXUI8p^6$R|6Y-{u|e=QTIxfFIqEQ!VyV?9EMuj!|% zpI!KbmIXpql5NO zY}!NrlGQ!o0&gC>f67fJ-8GsFWYXZNQH5P{>COam-N%y28_KsR8XL>(bRJQ6WJG?q zz2=Lb;hAyQX@RLi2pG5$jeuZSs8(|dilO?^J69Q{Eo2kA=57Y{pc(op_UcF^;nuv^ zOLI`6{H;ba#bm;xT9c#Z7KCdv3|8rEmVmAhf}sP2i)R>X;CfEAL7>)hS~GWROO3aU zLUE{YhW0rPCkS)@oBMFu?fBE{9<~NJNWfDiUeRQQ&?gGZBl(qZ9{>AskN5Ype-XR7 zbUIX6u7PwoNw8S%;z^#1U$oyu3a2wv=_G+)OX_>dyAO-^(Y}DEv0h0ECZ4_Sd!97W z+xrU~V8(VLIC6NOVwh}{0$Zxi`bBF48Sx5mAI)YY>9z~FPX2QJuY=7HB1|Vc{b`-9 zz^`b@B&+pOB=-v}{_R_N=7arlm>$j9$<?L)~Wc^6E9nQTqMUKKZ-Rditv*x*rp^_e%8A=mf$;OYwbZAVF<9J^- zE%S|xv~l#Y2Gvd8BL`ynSoL7$wwDDyHn~1ez+7m(v;Y1)e_yjWxzsab$T9J>7j3(o zI%(~0kv?7H7Qv1lkBj_jrF-Ce{WDS&#psu`5@6$6d#B}y*VGsz+ZLF5-j`e8VqwE; zy1%wM_(+HE%Wup7hRdCXis?s~i_KnYr{+A@s2GdjNil2C<;k7eX9;){9p-kFGg~e< zUl6si{WlL`DfeXxEnLB`A*i>IXt;glz^2XQ@T?Msh12}QdIBPO>CR-b_N zSUq3(I)fiQ30m;eQ{x5phw*IuT8DZSy;-Af`= z->jF+W}d{a;*`c{KI1hiSzPG-{JJVY8-$Q9rGe(wubLeCil=Jpl?l(*xDwO&#G3KS zrD&quUhK$SyhDP%W$zziI)!8FHI_o4)KRtK{Bvt|JoD=TV>hja6-J0r+WQP- zGBfRtXa4BrY>ybla91#1fshm*fs`wQso;3_=!YBzbp3Mp^Yn?&B}>knnjdAjbjaOj zuF}1Zs9zy^Jv+X8Rw%NVP&P-1fIEIO^l`x12X~8!V)7_wKxhGluX;O&fTGHFqibxPkIMeCYsa6OG!5gDFk97xcMw)n-c}p&{gk0@wffvJtAC96P%@c7z4c7Et z4+NhC1K*LGw;DqvXuP{v%y22}2Fh`7_J28DJUzc1TAOy@_wan-%4?nho#bHhklXz` zHLJz@y}DdNdNryMH6BOkTdv#^^ww{}fVU}9qq{_+HQ1!&rFkr({AV8-z=((2wVl!7 zgIHn0rEl-#k!kDsRX%Wp(KHL0>56a zgoi+NYK9UOp#(?NvApxl$7UHi$D8qBzpQ^td#{7P?{Ly++n3Kn*C{i{9j@-rG-o^D_5N%be$^T=Q9 zG2?$ISyK=kKueM{^?D{+R;D`A#v&GWe9bsY!zKupqMmLtSL4=2*jNR)w>9Pt7SOga z?c!QaM+EOQz_;_)c76ep4%J5wjI5sQ7ty^-53n^v+24S7p>=Mic6q_$j~f-%vG)ay ze^!0>()_^zzT^b|1fwraJ!WZM#F-9tb&>F|m+!Gk@$_~w=hxTHM3p55MppZZlg3*) zKZYa%=T3HMD<0jIoo?-`x2D??gmVswRV;mi+-UEV-vvQTMleHZ$o{3B!jOX#m#7ym ziKDO454@zD8eM2=cBGu@RITV+*v3=a3A2wQ;@c$!_IhLqA%oVANBHg6D+|u&lmMvDs&FK(Ahotcb6t9K-ix>KGOPN z@t!8m{(4bu(}uofDO&K2aIrz^3Fyozi`De=4=-_j7cNxYeUzhF7zvy3+&hz|6<>Rz z0ZC!kNFLq*8`^M}Hee`usJHy-75pD6zPnZv+zf_ANe>8T9AX^)fRZT(z9d&Hj?dPOm+So+t<#cOTqm1N7=Tkb>RxU}D7ZQbD; zLZQ8jWUx84Yie1AnV*o*!`BOjZ~PLeby6UC9a+D)Z`jlPvH zs`IY@d1ev0Utq7@zVd1S$fTI*OG$O8j*~d#hkmaTtLA^-p9m`o^mz_5^S-RN6esq zgQ~I7zD)5irXMIIPDwv$880?0T+1GUz0F?y(Vi#VuV`j-4zfNqf2uXsau12vUBLKt z`I}+PLr%i~^y33J=XfRg_kH&p_}1h30$S$qB=(fQUcAO{xr@f!7ENBBzVW=I1lYKv zle|DnlE>#5xbLwt2^&b@XKk(+MrD36m&1_*j3b?Zs>IISTg=uHp3}hgmI%!I0gkV~ zW6qiPE4e$~T)zh2+!Z}P=Kb!_REeO{rmF0wTc^+lQY?G_`^+x~y@x#Ni<0s!!KiT^ zK0OgtIKrX1N;Wt6JljpYdD2gBaR1R^gv`)mW8;W^=Bqbj0Y~;F&Z;KmqBR(Ydria-N-eI z(Qf0b-?9Ty6y1ewu8#=NB}qBu*uPJB?<)KHt^!TIXq$z*S(et{R6RvFm76})bt z>y@B8o(0ExF>GHYtlG}tfheUs$DeuI)wsu7+es|DW`nB0fd~#oG`UF}ZSK|m*(vJv z#CNH2u7TZJXQe>pHw1;sYyyJiEsh4QC2MI!btW05{H2Lm8JIv}6|5)_LZvtDZ|rLQ zG{)MiKPx9EX#Y*Coz1URCZQs=m{zf*P=Rx7ODXsO%_?#}%Nb0f7Ty%+17VQ+nJozN zGc`KK5v5{h#eN^DZHcUm%g+`T+G>rX7JIX%{WV77*aKnR;{Wwe zOFZ|cSU;KJ?YtkI2rHGFHKI@{MvB{NDclc-ZhtP?P_%@d3tj(Mrk*9F8Ln~iQKl_( zeiDJDE`tktA39{NttRM<6r(oDo#Ff79lafM0~57^|Dkj;v?SlrybIa_1qm>do!e79 zSiv)g68nQw+;NUgs~rkHZ?Zv?5pL0QfEX?vTLtYwJ?7H+_iw9#EaOtA-C3A@`t6?D zEIaBuRyrcjj8&|DnP>>!1YMnK-g<)|^{8q|@CKMHTFgC<&RoHZ3&gdj66Fya1i+pn zw;|@2jW0A4+=pq|86ghbKDiRcrj39T0{uMb0&}v zNtYLGSfqg8llu_grGECAtFN=~8OX7Km^^qGcg%;tx)!vD4kb0J0-}5W4%;rNvS&~0 za1kMGd;i)pAJC?W9!;mP>kQwU|MbJLJgx+Jqq4pk4-7zg4t|}%7u;=~fpN>h9~x%o zgM$9PXbK)%fAupZ&bdG1={n0Bi?*8?Tl;JIS9lgpAQb}JhE8#SO=1y&&jg~3*S)E$ zuK||vRO#k4$pu@%4)vd*Fo&Bgnm$TaJCSS_650$6Kiv+)oHMI8bW%hMW>Qw3>kcli zH00RAZW4j;)IidG!16!6kO5pvtmqyoP!?^y&bNa^aSvl2{!rErYHeW^DSG2(WRGW; zMRmTIfOF^vQ9zuX$nz}4S2o(rd#$p|n)gtv7zgJwlKc-cdJtVC@9%?lE0?n7auK--wn%?`>XBCyf}Uxhu!?- z@+9}FoMd~S!J2}j$g&(D@+JdP!s zl99u7lXNCj>vBIwRBMFZj^V2&$o{-r#0sd^JuSC_$}+!rBG}GFf4*pgWRQ|_uhZ51 z4(jr-^jkGqD}R>he0lZ<^S@VWz~y18kKddktSzGs!=egz=zR(Fn0t;D-5r zoc|w0hfi$eRg{`n6007~FjG!)iLf*I1A@@KY0te@Ht;?W`p*^r9fcXR$p zS_b`3CA^JPqPTCM*YIXMg^aWL?GNXJ2uwX*SBPx}MtG@AJax{Xy3zPyG7-iu?CmyH zVBj3>f#dxOPwa=_w=98>4|sj__T>u?7=wi$NYT|-NNp^WU}|aF&otX->$|_snVECk z8Jc=ANqVsMpR|tXZyp=ML^oW8#~p3$f5!ij=8r;hyHeGV}x*h*Sh&U8Vo3~@W<6FLbZ_S%r zDuo)cz9~S-QE%-v!C#sKyR_6ceDaT@RJ%fg9WC;2Lq$KLJ|8Q7zMNxFtXYWTJ0auy zmrV)GuNXVdp#;@zNs`G*YT!%m`c++Ek^Z~T+>7I=jN5Fqxs33*=8(s<_X%pMihG<6 zWE|girV@Gc27ks@NEB(jt)e}Q$^=F}@KkBmJ)n(>L9TnBJC1;ZeLTK<;qqA7`H7$u zB@*+`Up7clwe#As^&<28r5cS|uNvSPMtrzRzctSWO)>1RdxdEwP(%YksdEOqJIx*Q z6nj}n4ZBXzQ6L{!zAZASmGB9}rGJBQVSDe4>Z;%7a@ z-do3r6KUR54C`GY#68+ekajcW{tHa_C~5y~jNbQ#9P4%-nNmUE{%Hz66+@q@-~H@v zEQ9rY_f{FnpT8!(S@;hr9x}labSQ^0sg4SdlnS4zUpxmS0aU4-&q~_EK%B zZ$MAx!5SMbm3UjegE9%u^C)S{D+)=U#?UZfHC<4~iydimb08iDF_o?w>tLAPT+nCg z)LW7(2<|z?W25X>;T7iM=iO0zi}%2=4m_;Y0G!&{hF9zrxp&Eh#E66Iq*PlV#vN58 zExCd_zSeeptqOXvNR?POzdw-JfqfdKRp$~S^~CY&Hfhq_o`#(z0}Zd2Sfsb!8i+$# z3GU@$&1NM!bIf_tM}38E;%?{%m4+E#ZFHsD{Ch7kmcXwz<^+CF^yF5dq7Vq5fVieZdmNm_)Xl(;7R!9~i1a29ltt zz$kJ?UwUtyQW)!6G=IALZ|voJyJ{%pU-X<5@63Atj&no$tL3%Gi_m*me&pjfAeG#G zGB1KGA%KHP1TGcg|sFa^8g>kP-)w+xQo z0#6hY`2*i@oQIk|Kk%vY;N!Jn(kSrOQWD-xxv8Ir9&5Lt9{zw_zW^j_X)v`g>0l@L zS8{Aa!nZO$#&3J_DkdK%-T{`aWs6+)_o_Z8M!?CUj%jQ;+G zI@Rux*C#A}3MZj+3a}yFmC@6NoLAm3QfmPBY=;($q|$N{HXUMP{gHcd-8SSmF$qbz z0_ZM&DRvF*HXNT(_T(G#)wOe2iKo{$Y%a;M0!s~Qq%BMtMS>LtMtFYAgvVH8E>o2A z3pj!zmV&mC-80%*BiQpv#=H#!K1g4KUMmm|zjb{`+PDlayD)h}qSVOpk``!h_xTmZ zNkF_Am4!$`SqhZ-y>CpX+vtU$1^ai3m-e@T8T$Q*tm^zXuD*XH7?c9^4LwXo_6LgPe<|S>NdKiM&VQf+ff3ve+0FQmEB z)W>5t)!z;YCR09XEz=+}!)HNP}VM&AZz;SC+g^L_trG@$6)o%Oh* z{7WWXn-kVdq8FlFELnPi!F|5NN@bjc4*!Rs4*7y8xCWZMVV&mV&T=S!mOBQVa0?lH zKmr87pi!v;t4i!TN#p4*o^AnFl%F2U3vEfT;@1*vfL+*1o&Gzf>FxB83Rqeg9e>O{ z!T(jWs)#EtEwxHRv#+J;#mUi^YHiDHU8F^r1?3-VA$>7x1IG-^*%x{8kGyc`vnugu zgaQIpZkAqao5AWEqf$`w>NpArx?oRFGFXLwGP=Fzeg42&WS5FUGo1ig^3_skmo&)8 zIITUdAMX-H{Xzcv=X@iz_**0@PlgM>%e;L!)w}zV zk4GN~kl;W$N9$sOrtw_K`4$nj_HK!uWTjv%GTELMw81XS|6?@iSCP_tw$iQ2ICpU=d1l#_H2X;8e*L3xecmSESmY$j z&#y2|5v`3$%juL)vFEAZ0@W*}9_{JG{&hCqqlt)PVwru0=1W7+q+yVrlK?s@hUE>a z#MM)?eErnnMP*3U2H5w*En9U+F^zav#m-e!_VpQac~1NDOMl>>=q@*!q+$;;PLI@p z;P-?l0wbFWYa5miSTPBxg#d$=p)au~%(AMVrN&}q?H``gliV4egAvA;fHuOj1Tu8h zTaTxhXANbUHD%{lm?zbkj^;UL9QsEyI~=^P2|XIRsx=$&v-FLs?fzH{^#P&^M1{Z? zF_#P65pe|z;i?r{RrH{6(48;&pmA>HcPzTXIg{r4L=747rnNi6BlO(E`JNCsaL+5l zHb6h$$Qmjq-b|ZGpEBN{9~584S&&Dbmgehgae(c)VuLjV@-KT7)$VCnEr8%I`r}l< zix4BZMds0w`ujO#KFxI^;lN65vXZ0sV%1j}6Q7sm%shaFSR7=iF1o3VGyf1CN zyp*bliz&7$|K)b9@}7d_tx^pVYxViq7a8J1@R}`mbnH* zIN-vH$CR!I`udlfPx_WuAZWMWBR$t-Q0wu0-gb57_tSyx){Yb5mX#6n*37d>{uQ8c z#g;gO7MG)yjtgqAYZ8l90&EsuYH$up1sN=nzl6BR1t|3BtCzySAC#GHEyl?f1bGR@ zme#a(lAeoUxuj%@&EG;TUOIy_5VCL?7z3tfO557glX(`woR@7d}-ArK5(+SL}d8T_7>Lj_`+EL!oMkW|}uYimX8M|R3x!LfE8>CV`nw1KJ z?}?~J4Ct5ZelH7!T)8$BkJz1g^F2$IQNoJmxzAGEt~ugwve(r8=unZk)tHlG4V>BP zaX;oWJFbHM76uhyHy$62`J`$V0%KDgBrIyV5g2GLQCixD24Gu8fb6P$&aGUaS2yx- zHxU#*j8*WIaNMs4$gP8Zwj1bfqz2rFa)xhF80kzWfa@S^tcoEZvu zV}Ell0AI51$79&(P)^4gd<1s~c-!Dm(D4ICgW%JO4oC6!KAucMrF?!J`@19C1uU|A z>@n3_Dc*Klzfi9fu=iZzO>WLiFQoCEsLkv4=>PESfVROAE>A+gUIJ`{nQp$5ci_+O z$G_JFkn!TVS3JNAvv=tTSIKOe;eDPTFAf(JG-+YiZ<^V?)%_?ABLxOhFeta4o*m!5 zN@h}`A_0}Kt`*D+pooKcBYhrF-)maniwJ)S+7 zmX5oH2n#MrCeHy%hK94x8UMN9fK|HEH?e;ab1++OZ1t%g-4vD@wIceb?cu@{*N_O4 zhdksDy^70S_?49>@AyXArWcfwC)u7bAOj#(;-RZf$gAnoje9~d5jTwWfmZ}XNkO-! zSKuCU^)V-St9(zCnBX`SbZLG{-lsy=(gh^yy?=}u_FyHDJ^K0e_#L;5H!ktwHebV& z2TKoS{30n|`k%%EM2OVso3xY6d|8qZQ5`Py!OFcHoEvJEpVrDMZnO|r?B`{}UT!4Z z40%5+GxRl1c?>MmUOMyIJjW?uUrtr9R2?td@qhpDo<2=c%);aNVKSU| zV31wI$(LZ?@0kasRT8B$-0Mma0)-~qMYF}YGsn@rTQmVN`82c-aMXTIL3=%UNOYkH zb0ta|ObfR!9#ha4Gcr!5S#^)F_L#4vzOAnS=U9@mf}QfksH%k<6%h$F*`tHZ$9+zZ zx%qE3bB4{}0-x?IF;vXmaLaSwZcHvQxg@;{M zhC<+C7U;>IyNF$c-U-kRdHvl%wh$}NmSDd@uf`gXky0dV4!{3XmBc1g#j5OiCTj1^ zJ8&?f zIH5*|i!W#$AcwpBI=xRsn$?6>r#u<@Iod|L*U!R2@Ng}Td$%Z#>oRQf+PuxP_>GnhmUX; z2eyVr&7If4R!>enS~%a!2VHP_T+Lw9`Vy7X|6ESTOz1mzY^-6G{wqIW40*+#Y&W$> zbV}A|$x>%Hu#teut7)(F(?x-;Z&L9lnGP*O4#G-LpGuIlUM2vaO~-`YbqavB`UXygG}4`psueE&OdZRxnBPSe`RScK^27#-dE3CE>d9#K~ep>0Q>464>~O% zb~IG)&xg{U;9cB$*pwreTzFq6{~5!35D2+{o@3qdAl(I;C|pU79bs&S0-FJtfKFx- zKz&_=6b_hk4$dU5GrD!nfCorWQ?lC*l~rSn`6xe=6v?U&(O4HJ*>zxBk04IS=E(g< z3*{cV7S#bJVbBlPDLrT6;zkrijqGwqu_QeFDlaoLCm!Th!j{sx@_M=uQNt+z8pz-0 zZ@(IpiveJmSw^?7oTA@==vgU1Dgxq=h8;=wbIaF)IbP}7`p&+ApkOuIqv37UM%U)A zdkcDcx4+T#*6f9zTF!n}N4@jC{xEo|brHe;9fTshdnz~}Mq_#swYH%eK`d01-5IE5 z&yJ@eTMr4FS+zL&$JTOXr`T@If(CoVPQPT5>wo!j)rrA-KTOvFeXnmcXK*)mF;olK zYjdq2GG7Fw?)R{k@tWs>uCI#7-%SgW4;wGF7xzI8;5)-AJDLoB{(+9p7LIv?Es`H7 z2GCYAYS{&?c2l%nrwRA_Wa07S946db!-)97MRdy>Tl8l&N%>~>WHig&-Nc~5s+s$c zz`vpicT;a$OMq)Q(7IE=0ppD;3h~uxdf1x9ueGdeN^+VwmCnu-tKLyUUj~0#A)$cv z0dSfe&3KHLZXK434Y;!koCe+u%v1XsSB?}+Zd07fq4o-QZy3?C-wsuP_=`@3sP4cz zU)2We^?rFolG-=4BgxR?n~YMpvRD!XCxkH1Jm~IqtI)%j1A>a z6ao50A2}AdSz_5}Gl0UBN&T}Vks*;@{ptB%*uf4)rvITawotQ$c3J=aWIb)MFVC-3 z?$`+K#~Y*Ea&FNV>_nGr0dVD`f1R5B4}U!Ighb-72MJZ#U;U>4ENcoREUJG@U|w`+ zq27q9Vra7tzFsRWT1s2&n<4|jj5riOMii$$FiMbnz)M2W3E(5x!}8~B)ROrKTz z6@1jKXhQenmdm%(BWiHj8cKV$W-##EO*pg@0I{XX?>Qe4WR>&+6iBCO$7zu7hE%EP zm$f|L7n;8V-)iT+)+R=KPF7JHx#|R8D>T4V;k{W=%1|&`-N-&-D76AK2|mF`H_bT- zZdEL4${#Oh%HUv-=wFNXfUo^@iD_0Ep#Ns?>iqKjn4rAkb96@kZ_1}YIql?4)slhO zZUVS_UPQQYpOt2kKj8Vzp+OE(=H#k?AkMsCm1QVSvh95d zeOk`r^k$kn+wxa{k;a!I8IW*UwekWP&k3-Z5O~eIqu{sZC)<2=oaT9UG^)ac|LhgM zPCctK0lKC4Stn6a5DgH8B5tLNIrU-#u3fU;F^iz~9~X}$SH1OU za3M?8me|$9#t@;YOn|j09!ptsVj$#^(ODxMB)kAL;@5kBrQ5GT3t}!-OS|QeBu1t! z*!qTp-6WG7E+((6aqfNidn5paW$Nx|i&yD$Q{!u$RgbzD%KS7}g`E64lG}8Gd{V(B zP1NlWiUR9ntfjGj?|63UCUN3H$!dw#?WvW2-DF^U0_Qw5@>0$oqxX_@YdSv>!RRtK z7?fI-1Bn=++V3UxjKlN63PvhuFACVUJ8NSnSiG$>chuX=tzzpJrb1eiyHyGZFmKj2 zGIAc9Kcq*Uo;(0JJ`-2!{Erj7njrG0LrBD11)F{`S=^;w-~|G1jy4zDJ7z{e4r{g_t2z8=bBr1ocwd@Z z{C+o36q)b0?;TN<4U*u12X(QlPoNCQH%Mj7FUju*MR=iJp#qPPdw3i`W4vJbe8bv1 zxeo_dbyS#R1pY~f#XI0I0>vS7CL8RY>NE^%_k=#`F_nw|`ApSC1h_~*PgOnM*K&AK zzMEB|Q*5&GPw)Dpg`av#Pm$*bcleOdo1M&`rF;H^I|VbRqwDSBF=OvKvh+@)Nde=0|xrYr{7%merXE14$<#RTJ_Ix;O8V; zRcU@MML+T+WN$kCL)=V3iL=rAmYt;YBBLK*Fbx=o=UmzmMHeP<6Zz{8<8DfcX1Z!K z?|{oNciFA`J_8dVelht_#}F*y!6z}YNHIFk6IBB6dcFBF23w>7jUn%$W;s??C|sOF zwN>gpA4vbrZECYJXYzO1-?{-SV8tuulX)vAVsVJhAx+ zF^S!eC$cL+IWs$2R*&xt-y zRCXTll`32^0{`28r(%G_;^Z?aNKF&<4VcdjT)$cl^&jLM*=b%cexYXgHfAfS{scC zjdYh>5G2^z0dG5?N;Y|O^@|v?3_S)+2~b;G@#Za*&dDTZ(M#3!wJHb_xCq-{UI`#A zRrTNDH_U1cZ23=s!4ve^skQ)AGSzr%3D|HztsgOn>-h!mox|?CNBBMOutCsMjRv;t zCd8c$^FQo};t*?m-cb@8cHdd_UjM`~7-7 zpD&mf;VEBVydeZpE{s>K(~=DWuij?%V3o0!-ms;8{vG^zTl8n>4uF+3)9sKtx^P#Y zDb1us?dWbQivbxaVfTM?wL%S!Skf1~uM(3B7H;fq`F!V8jI#5)cyE=f@VoV`LUq_b z9R^2@l4^w5)=tJ0U;V3i4VP-A@qaECkt@?NV@JUZu_c3d`|jIoYj?So+Y1QkACl@{wJlD~Nj+0xMnruLT$hK((^!+7~xGg=}GD{^H5YSxcPXxv1vAmL*}mQeZH}t(@3awZ_o5I~UlbaB#YhoLp-=-T%iGnWxu3IBr*S=hfLvc52EG z+bQpx<>Nt!BzS><%WJ+#sg6==`o%P->H9n;Q;k!T0phKv=uzq+U zl|NJs<+mw`#I{^dzheY!aHFE$XqK_-r@kwU{A+W#MJU=Mx)2trXnlJ{-*p3w$zb-3pPl`9J+jdw3!A-OH4+>Z9fV1`(W)$(lV!t3sD1 z;OuSC=p$kOV8b#^H#QdJ+W@G+L3qJQ_TjyJ=*;^`UzT*x9W;DWWh%Ix!5CgXr?ql4 z8Ep0W!*0_PC_zAeK%Z@V0~M%P&(?&Q_5uA(lFS33QY=&&zSMU+dKWqM&aN!XdlaNY z(Z_l;fA*Og%v?^-{b8Uc7|n_(R}8Adylg@|^1aP6@ZSsMmCf(2EkAga1N!KdXBQbl z*OP%%v7DbEx1M-PLrq-qS=e2-nzvT75G^qW0~e?Xo-i*`7RDl3l%CZ&q-y>eI@!Hy z)X%@%z$TKB;_(^H@$zg--lm{1(lL!vV&cVLuUww~uNOxosNFP=h{ZgdPeS@V%sY)h zpT9N#0QkOI+HxbFOsYaOhoU=Ti#>Hg-4+a(HLnXT^LDfEOB+}1Ty0sP7T5l-rIirw&|j(>>ln(N1?^R)fHR z9(eu$tqRx#i@K~i+S;Xt2W{&p9m1Y{L9=OqBEV-dGIUcABv_D75@+VE(h?7X1kF^r z?T5^KiaYw+nt(xox@YTmb}lvXeI1GpGJ2_e3}?)BcYyVtpT%D|o4mpr{!8jGf6Ktl zF(vwfBBw>i8}=tP!{#uw5`LE!khLJA{=ADdznGMpwLV8G&Qi252Gs9u@EP3BPP3`? z|MK_Muaw8p?>$t8grdlgkMj~Z54+GWFF3GF9XzCNs2Mmsime{yzd6iT4KrIZ43a4#u*u`nuKLY04P^oigRkARC_MBw`MUs2kv(tHf#pA7Q zIf!h4{s(C@%R6%Gon$f-lz>X%2R<0CB!H8O$BDd-%!fJ&Eu?{nf5h<^S+@>$lO##gdOXNYDDSLf7AcB6ABuEiaqW;qxQ1Hj?0tV5_R!AZn(6Mhc!iOc^Ko4 zp}1RM{B?O>pYbt8Mbsf3OH?bgTD6d!e;|q4Xqm_`UpcN}`$Zm2>D)pB>84(<8cCtH zq`>2qRrA*aW{t@`OXusN<$?5n<=Z)vtVOVBcBi1Tt4K2qt`XZqm93_b+kX@p9g1R% zS-$?N!G$7+U#Vg7ic+F5+sO)ROhq$yNsKblC&#?3_3;-?*|78RsOqwYc4i@PGt`{c8XrSgmr@wSfTotLi>h7kLUVi~fGHG&rHnszE-in;ga(PXR~m?<{>W%c#zR;KNDz zyOqhI%!o5g`WiF4yzzcu!%?@mp?3uvZ*;LS^;Xuhn$*UghGcD6&#Auha%eF!&ayG= zo_;e?R?zLJLk}5$mne1TKeSmCHN8q%&hpQfPLn6_r_R?~78ip~h~RC?_HH*-{&PfV zbKlm`NLaHr?tm-lOlp{b8D$~Egpwi$D^lY%E{Q{3t5Xx)-U)gufHc;Hx)pAzn9}R{ z9G&i0-Hk5eNe8iP9+C}Vm9t8oQDpc=jjNzEf*M)ol>5jDFj~72sy5+WP&_xAmM4DD zjlU7|Yx)d+AH3fJ+MTLj_#7+jRWhnix4U*OomUgIA_Y3#pir`(>cV9eFGK)&OR)`g zvM`3Ie$EVrI7s9m_iK&9`TIX2;-q;3?+eH}{_`kMd1zIF*z3Yx1v1A+UnUeP5#`kM z@vj84a^jms%k5)`0t`{-B^$*kd=SQ8$~Jlwm|UHfYY6Z6yxufkq2pw(2pGch`!mB2 z=(PQ<^mbVo5%=PCy{W^_O;`(B|g}{ME6yZcWDlCKr|o84PfY z{X8TZc+ht(aNOolmd|fDc%xkrMtO;b50uRj>%m$rYyvuSauWt0jMM=K9}tF>pchn31D?WT!+?=6Lx8*G zye#w8?2X3xyy8R~&XiJ?0^%QL(N^gmCyT$GC;MORat>|W_qI?=IPQ3rRbX34gz=tB9=-;4cuv^ zp&j>syM@_RP~DA^&L3e^)*eoRmchv(CGsiMBx_$HQ1)Mf4uj68^6hND7!|5l55;@c z((SJWT8yRG)Sr=-U}1%gmDVar-oo;*rP+Pl=6!t9?CH6$ZPBRWFOc2lR5KizB;0(u zSN);LmY_b*)_^7~Fkr$lnWN8K8J*Zar%dB>x;NXN)^)VaWPcbQ>6DH{+S=0K8kBk` zrYTr5#=MyrcP7);j;7SkqwzMJ3^)`DI6GFgY2dnZF!Y9Ii%3+Vd?|vXF|>RYxL^!X zfCQ?5D|P;A!*_BIV{=4shg0=!?rkSU;>gL3uT!0Ay{y&7+!pk@m&%n;AHnOSRXRuw zi*PoK_%B;_Lz-y(PV`d*6S#E^)|-!9=p!$crD;O&-IyjB zu{NRzjA?b2&nuuU$w$NK)xSYh|LU+wZEsVY^v}2Er7Jge{b+DQ&p$6cQpLkwbtRU5 z#}67n58NV{(M<%Nyz|QkB{-f&YjLZA zjTfUMv25_SHo3#l+`j2EMCak3Tag+_B-7+XWSgAyW+w<|be#FPFU5shg8$`rQ9KyW zGi5@}UM~p4ydle)#>@U-oYAS~d_vI!gAdDvq7l=osj~lM0CR&e)}EXq6vfdL zH}|G#-Vg|L{i;!Z0r8q8t_QO>%~V+M8S505=-`pM*Jtu#%-oQrUK@9jJ6-i2M2CPx zKf}af{Z;mnjF6HbdkMq3km5H~mM|gQIvsRxYAMTU3Y2h>y0DFze3dHXj^2J*r~fq7 z6{=Q;o97A_XLps8>_VK<_1Y~xcF@_y2YnVdCYFJU%c~SUBz0eXzwosV@LmCp3K$O> zStaq7g?;a!4nOh#dWcf=*8UfOpHQ^+c@QBu1vOaTILq-kLys2=8hZz(=M>8m@f#Ma zhaSvX|NNrCO3c=T>Y(l?+<>mbt1c@6&~T$y2(yEuYv(k|hxL2r^{b}1`aNfEI^chQ zx4BtT=f`mmR<+2Zvit;CWKHdhN%JYej!iY_Of|FVI1cNlKX{WsOBNvYR{4f2WnAM6 zF-aB8VKh{&f(BKzCcQjs#Ojx|6$h@Ns(}0ld1F_H>*5jEyBC#3M)pv-oAH-JV8l!7 z&nEMEBxQj}S(PsCHsM%2*j73Bl?;J-5FzFG6(L5<9C`FlfNC}+v&v{sIa;IsmmhDg zKFewqM|-6M$GDX!b&?fv{nV#_1S%Dy6rVk%>;ByQ`83rMf>!N3I@4cjyy8_a_UOJ7 zqhtz(a)rJzY(4qBsI{^tc(e6S+LY;m) zPDlCuSOu~ISZ^lxb;SY$Bi55kw5Vl;T9gu*V0i=$5Z&*m0}MYU)}Rk5%UGhH&O{7G zfvRyXOX}sXU^APryCtiBygzku`0ZjQ+c)6ii77VY;wkZc#x&S4b-M0!E>pBHMZGcC zWR0dof4QmijKy#2enONSakU|LHmCTcU$CL`oiOnfgZvj)Zj2Ysr@mJW1M&@CbBi4M zmRClYB){k7$!EEJT|?Af8St`nu>GWD2jCL*8u?mfa}C;njB@|dGQ2XYV-L?>!EQW6 zAz$;Wcq;>Vj9GbfA5*kQscV^;TqEArxm{+Sg%|1vLpvQLN1^JM$5%a!t?S;kIrvPt zpU*1h{bBA)2=vL)aQ4)r^U~O7Nc*Lb|NL};3ZUY`gv+MQY&kyrc@+P#H6^trfx(B69q>1po`1ZlZn@g z&4_(>xL8IQe|)sN3-ty_i~>xKC+J)55XC;TuZi$@yewk-dEv(#>b7|5wIrw9@~moO zMZ3>qfZNP;6<+HcNEVKQPbo_jet2Y%zuf7GKx9c$!LqwXnU)(wlz>|mOT8}MG!vG& zyZ)%UPa>pT6FD6EU~c_+QZmDhKb+L1uhkn<3|y_Ya7Zan^t>W5R;;(Bl}Qu_BItxq zcXU6xLhb1OA`_~WE#+-esPG=6?SM^nhM3FAjy<8Ad?&KKT}xeSxSE$)w<2N z&75CM9X9v5yLEZhyl^>rv%FM(iDWTUwx{=y$mhDgi|2J_%0hju7uR$?+2clFPU;`p zE#Wp;!ZuZX`xhdN%gTOv!;c8A2DP-0Z?>&x{uE|R+jo1=yTDKOR)1#n z9_cpo)D)!2Z1=;J?v-y7U2mP1tTzbSh>qVVa9>Mi?=#+>+Z`ch{p*}Xbv4}a^VBE# z#OLRSv=kCsN3$6cmE&c_LVsbyy%YRt*p+7NtwSnb-b1&HwyH6f6m|>SH;IrTX31!2 z6==}!DG~T9<0@Ig!PSFtlHFV~65Co8k#~I_`1Sa{WOM1^QeoFf%Q3{F7}4)8#d=X+ zR%=%e-CS?qrgHvED0#Y`U`|0gxf$4RuFEhUOuQsdTS@MA0^P^6>pcXoR1;F(XH<_7x#<1ciMa@ z$>76f7?+%PG1fF}5hFf`M=!sv9&v_|e&(lQ(!u{@?wY2t-WPy3>X2AtttXq99T26( z^h-3u{6(&82tos&P4Gu~RKxTEyMQ^zlQ)p;gc(L2DgOwk>(jU4nLJw-(gh_PMf4sh zbB`d|qM)|IBY#?5bGe>LwX^wVf>;8S#g31nwM(m6i|+;pQ1neCe|%dgzFgmyMF>(_ftIxhnc?avCKOzc8(=dMvs+z=bQ)n9U8ZOe_Y z9V1XN<)M4>oIyN7$GH=FCWnW~?6;8ns~xR4 z4kC=h-FUg&5-{Gn8P_-Evb%jusQw)+44S#TTJ(!wuR_7<{;ZYYTn>LsrIl6ApM9Y+C)Gvb%;89yg>sJ^D1LiwT| zasVG~l_*afC^Q>T?%P`I`1{W?o)yJgiu(AM5W<%WvW>?gcDVASz$nTk#tewo19>m8 zjd#CVbESuCyeCmfJu5%4q;9cP;*9!RUh~e@u{Ei(tUBo|!_N|hzFO}9t^*1bM9)4O z_k5;}Ogh9ZirJ{}IUaI`{Lq)j(lDq*=E077C#L%msdB!MFsB{OhegsTC(2LcFWL4} zUysD~_7gO{K;0;IYeWDuCsN96%fV~h`a{l~)*peZ7nRm7ZVy&|UzuOt^p>rX#AWC{ zE`E`8L(R1*^UjGzMn>#L=3M!Ep*V)wg|Ncn?$r8Y*7+#s0 z0|>F1Kz39W8_1J1V|a&foAS}-lw%#0Wvz}CFd3HVBBQCKse2n$o^Fi&eNY*~kP9YY zKpCP#fjN$yk5o`R8EedlpAQeV?Nkd9E7B-)A9b3)jZplg2dSSVIr4l%j^$u+`<`E9 zpD)jMQpp}M2n?5sfDHrXgE6^%Qw4|z?t1|A}CKOe_ zCnO5-)LBaIl9I~C zkNw;I1oO1)Z(#jf+Bs56i2Cqp9p8_kX&0TFe?DrbYndvS|3~uME?*5i#vE$SRfZL9 zcLCfma`QheU-}EEx7IBvHboOfbHsmuV`Y8{D2guO~rx>)>@kc!ZcpM*m%=A zzOgQ}hr4(!g4Q+>T(}B^HCFLGbW?Zq>M#BB0-kg3@LHvT5~HoQ<0W%p@NYpi4e_Bl zQ@UIGUo~^{Nly#V$;tY5$i^Rb35xl5&2NVbnOFeJggwM}owX@9p$t`6JBe$jyYnR`%vVmVZ+4_Y8 z9+`-y2Xk;hYQw9JI8lbSHrLN^WAnPikH)Em1gfTwnvdU_ja$eoG#Jm-`d_mPwWIvf zAf0-ct$u@OwN5XD$W+u9u zTjo}l_1A^Rt5+E8)5*KXNW4lOva*jeDQm#wrem?<#<#1JfpV!IcUF5IwayytL=#p* zw14iy*#><@liavsuo`neZ_Jqr)`0`e>M&#fYIfovY1S zO!OH`@$F1(1y7-4o1cAgl1*mJ7YD>px}ft#g@V8LyEW`vjMb5YdcU(iv258K#;5eS z{S5G{0CIjf#;X8!xN{h}rZK8YgzDaZn%8x|awH;7lZ|}=DZE+Dug$M)?Q^0r>)jA+ zrq3Y%+wF1Q7}$z4GE-er1k zC)UB(jrYobc2SnT`M@HE%5Myj0M8(F(`PbF7H)GjQbNO5dw}2S%tbRm9*mGybtdHZ z&=3NIJqef{JvuP|oj2=tTv3sJB>#2GEi)6l*Nf;VvzkcpTj+Dr0m`{={>HGxT%_D% z!%rI0I1<=niJkVki&@{@(`W%mop1Z>-a%FBDaj?5-U9bw_t=u}uA>N->+LO<)8GtM z30J>koI+bzr6vl`H!RgZE+8&kP-8cFK_o;6i#v@1sd@wJMuUO1gE8mSqw`=f)e?b5 z&~zO|Jb?mzJ!H7~bKAma+~=7H#2kv+fDP0H+HNcHqVuZ!K3Gt4R75?#DYKg$(!3?)| zgSRwahsJf!?OzYK=Jsj88nwNh-q{}+p!yKY6NSop!$ND{LwGo{Id84@we_?k&8X?( zygsM`xx&{irA`Vqc>tN31nv4uU3~9apa_%GHrsQNtrohLBbwY}k;?FO$nOW)lEmT7 z^~CPE9yushlpbpZ8Y2PedA(li-nHM%PJhq0>t!?!4VN#cmWFXkU5eGe3+Pvl#g~7Z zUYb#8t#DAh^xZDRD{W7P;H5)=T%$h&TaiN9C8Uk{EDNb{eq-PBfuc8?bZY7_WGF_e z6zHUxxNsQs3FD7Bl7o;>rNJP)7-@#s)VO9@&9(2fH{jP{ti7OY|G_cYEN&4+|naErKoE-)8QH;*(-SSp&W znvz4xHaB@aE(;o{L=HJ{@VZaEgzrQ74G0Mtkn%g+>L8=Tde!(0>xwMk%Rl^=l)tMB z2O_B7g0H8R!f%*`hgzaCJ?>hY_0ntj9J~|{1h>b|zYGbNAnd&i4v$W0F*EOPzpjqy@grnW>d5VHr_t>X@nL+#1XABSH=y}Cr zHlkJ%ZCa(KP_T&!>8sAeS2wFhz<32><~+$)OM^y}3h*$&N6R1FaJ1EV9H~3X25da_ zEB;Z2x1Y@*>}o<-F9GJko~IM0RSTj&~^V4(5s8)-L@>lG+#5 z&JedmXZ)!CLa9pMYy{Ef`qt37%0y|te&-nI;E6nL_P3xjFhs?ZEk59||MhrVmErv; zU8g1cD5uSzIK!DrLyBad4?GE|vFWA6eiWH=^EpH?>`9Z&Z;IriB?`4l#7+~48gJPm z5L8_c(FTPLz6M1^A zvfrp#YWKjxWEoXfvjtyv4yo-sEg_Z^`@EYsUwK9UN1s`rzmq>dVB;-9Bk15Ho-0f! zm)43NdxGf~Y2;Yi@|tlVTE3+M2`C%HPcM%SuNIIqSDN(B8#|=TYd9Fl1h>7@R!(x< zvU^%b=>e^rt$Eoy*}B_={!oe^vI}XCpUNGwP%NWnYH+MJP?A-&9cyp2F#ax1Kg;vI zYT;E2yVzdiew3B-^Lh==-s@E~&y%zoE)cy(2lUL`Ev=j*_$+#zW_5`qR`oxRwxfiT zXBPbg+FiS2oW*Bq8{p&qc?i75{f#Ze1+0Y&;9$&~Sef2D{HSl>ktp!VF2tZZ7HOwN zZ62rp1aoIyP)qbGKPus|PLq5Srh`XG32k1T`Z3Xo^2_6phx)@z_yLcxFTY_3hj@6E zGb(~ky&=k~-^(nlay%w=8&|xh!G$RtzNig>swIE#?>r$;6s(Q1)wK62(OOk1pX`79 zm_9Cy(d;jymNH}PoO$Pm8E2vN+MfPn_Me9%G7(QA>tJpzRT{dS4511BK3lJFb5>hV zJ#MRO!5vnQTe);g1jmyVEC=}CRp*o|A{@jmeGcCAuUjiDAbBhiju3)zJw7q~hDpWv z>A%iXp5-xb%#4h0Vq$AmD3fpW{*4;yn~kU#%#L8dXKUUhTce?#lIWC0d(F>kyV)Mb ztCQ++G7tL8`J8gD9w%c}21nFMyDIh2kynVcwYQ$|Iwem$`VgEM#NU(PF2$j(+wK}l z3wf=2Zr$xSuf_VH)9O}zD^oNt9`rK@)RN{7kZpzV~Q(i4gT=iBMI(D#orT-Y(tzEf0rMH=I4Q*tq+t zUw)gPJcqx-*$SX;H; z@nL+lWp~19-)5*c@kyAJ&`;JbwVJ;PxjWNG?R*Z#+S>Y=0*wr=ztQV*C6FAkcu(+% zU%ANBn1qvNIvQn>6gzL zeF-ytHZ-Cn=bdL$9%8Z%A9YV2>+%^>s`hF5Y(HOdN zHPRH66E-v8uVX5#@!fWwcX3ig#%zt*G1Qi`HCVoD=iS#){ho$q4qvQbz}lpPqh8DY zRw73}Oz>%@+yjnfvkLK4x_agqtOOfWZ(8Xg7OBjp7XeYzh#&_IZ3=79TCvBA-tlE<_s*&gyZn&wT0<@hVJFrV!3ZU1CiUCbK6MBMxSrep ze0oVR1{S^**;nl=9lz9Fpf6pk2&txt;*h6es_V`weypg5`DXaUW(ZJVjuApx~ddyNpXI5a|eA;z6a0T3q8}{ zSyc-Tnf|BB2M2XQ8FIPVV{!Q`QHc72D63Qj*dDwR$Of=cjY8QE^Rr@@+7B>THl?#P z?qAugOp#Ws|BYG9hKne;NjKNG@sYdJdyr6|SMRWj=&|Fl>;0a~v3}Rz`~gkOWm(P}Gn}(5Ib&2W#uzy|VB5%+Cy4*_KHcy0e&469 zTu(x(YFA}v2ta@y2L)1^4=oIlFX0-(Am28&pzEOHF4+BE<|pcPQnwIgDkI(R??s|w zmg0euBLagDTX$S`vsmz-C#Fwf*Dt~vOT7u=dZBk|&;%Nvg@1F0J2>yVEEFF%D_@yH zeUYK~NL|=gtztS$D+tkaYnO2E+nWweV>6YeSJ~Kk>^5sni}$p4P2Qgldj{}ys4Y8w`~wX_DUyP;g%bm1Z!#OgZG??#h`;VuW0moM+ctbk-c>djwWk~YU%RkH^ksZ2S zF8gz7<{7_V=P>+uJ1^q$B(pwGl|ft2pa~2nrK| z+#)pmHS~C2Ct_n-YcH~Zxb#@hB(6}FM)t}jB@K9TBcarKSqcBUu}T+bJ~i$<{-l|7 zsuh&pcf^8J)@TkyGau@tEY`CyIz|8%4QXc+4r$D!qUBw0Ui_=z*JHuo_sg(ribNLk z8yc(kedKMhs?=8~=rR zd9CS)iqY)5n_w#o%cO;fD{*wWT{T10JmYGzkt7&5NedJ5=$bOCs4+>4R4O%GWMs19 zSE0r&qTw4EWvbg%24N^L1J4L^o%R^msm0gHBivf0AUL3O-aIaoHV*URj48p|X7OB-^&vg#!@ z4HJRqcxbO;!H*HFhHgZt%3^_W;;^Ax$DWTZ2{UeCey~Ph?xH=^v{Hta?qS?~_7CdL z_USHkf05;OYZY(y6kip1KFrMZ>le4ep~dZvyCJy9iocr%9&&!4A7~L zbSM)KP`!;q&}Z7Mb}8)sUi8wj{b&3^L!Zf1Va1Pr>RNw);SiJ=IJ@niiz3#=%Qjwr zT>Ac3ML%<(TcjSTUQt(|BJ3v#M=zn93q-2gT$Kuu1aaKH->@=O`UBs5G}GOcTE8=Q z5#N0>wqY3OVAA@XUPY<_`?89^-SNxK7axqaq)l-}5qa>;^Qz0X{Se9hZF0?Aq`*4k zd82>Z+)&@Adrp58xFW_vLxK`!R{HNmA@RSBdf6PRGGGfNX=K}ToVXhP@_^EuyiX?9 zuQYo7D+uv`#^Xu}g5vbpjcnRAAg|pQb~!k)FK@nJuJz6qk$C{Vm?86DPK_VOXaVLJ zeeNm6Lr3zHx4>YoKF&&%@t~2cX?MhDG7Cl@1(QEHM@GxjlG#0xv9&go)iL{Xw{+^m zjajfNCQX)~Gs(0ED4hk0yxqVs383|R@}yDct|y^Rlra+L&(oRKyfbE7dCdeG7^CR5 zwC5n_3-~QtJ@`Hi1w>h<2|tGQya?zqIEq5e{`R$~MoV109wxQ?ytz&}6_7I^YVNsv zFP}%wvSsUjl@f8noZNksVNZdgxbGF^{7F%!QAe9wDr1~hEC@ixw0bFk*OiK?feSt! zJETP#^n?X3#UU8k^8@d6U4x6i0r$pXzE*jazDn5fAoU~aDUyym=Vskr;+!`Qh^oQ_ zIjJlbJKI&!qbeN)y(Zfphwt|>)>`9C-I}%eqB|V2-U@4}d~UKZ=B#SCP^uBN5KR1n zSkQ@L8-Vay;!?dCF~!;kQy;SKvFG=ryG8b`(!Pr($lO676RoPgMM{~5ADDqelEEQu z`K>`U=M?Y77EQZ1VyC`WOa491sQ?z8#<5YsO15}Y8STO@Kt8hB2!6l`O(orR)`n%}VG+9Z@&byFH_BQC!*a+|PwBruyAJG~eC18*{rJtTW5vpUUG zy-Y}?*$0kl$;RSK<8g{*lU%*(_6|j@XWQiHJ42>RwCUm)aotPRR|=PhWxR#Y!PiS+ z`iL5%ZvUlUIeJVF8J4^G*%Ta#qJ88^-4z#-i82sIj2zDx=1cb$$xth)>)eg$$RL8) z%7?s_nbd-YPb~Om(=W#uFT0nMUN>w_gEpQ`a)D?d0&q!ADr^q{?%Y5gpF|l!8i?Mk_ zp8k_&AL-0CnuCmQ8o*fR;2U@4CE!!95(Brv_WU*%T~^ccLRIhgkUdK+7@OG^pYa1H_*&H#fretyD_etlUjwKz}gvRtpl zfFlSf97eQd`l{7at9fk^b_)iy=&D#iE3t$mDN3U~284(2mfbU3Vs|AaA5TNf4zK+F zIopsOM`z;&H2vW92L8vda61;IqLCdLE7>tEbHZ9MMVL+;5ZK+Lb++ZZR;P zC@Nvug)5QLZ26RCi6FyI=QOxN!RYz+$#oHr_v9ab;HfX|x)J&nBsG-KQbIAa ze?H}8gnuhmzUj>Tgxk4=%*D8W3Si|n`?#ZVMofm7U=Kp=lyMlUd7QlAm%kR8p8=z? z1Z$Wb)6{X?ZVZvp($8Kgm8`(M?Q-@*}+eOa^u@P_zI#H~Ov& z-=A9{EH@a)P3^Dve!l!()A5VQt7EbxDZ^rxoMPl_8IIEDv7MJo4D9=1FZspye_AJ?Es`dOk=v{VtuOID;1q)PB7|a0{H1s4wp@X zcCSMpNIu?Ayl_a=T!31$M2MFl|Et9c%qGPz&L{>rW}MF(FG@Ws2V`UTc*Z)Fxwiuz7-O3iBfv% zr6Bpwr_+)6&U-FB$E6iFr}aY=ni#Kd?E|Ym>Q)-E1DoT_vFI=CO~u%DseKwmg@rqr_M^b!qzc&|1O8`+xRS542&X3oT?OT zAl+OIZ>>Pl@jazEx%Z*@qxk>>lYC(RgA^(WjLY^3_2o&HU+#6~V^r`Ug6(176Jear zfly)m(2{8#7xqVM;CM+dH1?_1^pm3qoe3Vp3WV&YCI1pA!P}2uiF&iHQ|u8zz&)8` z%jQaBhG2>_{8>d?SeK38gZw4bav=o7X{jmZ$d|w~MdX2fAfc_Q=WTxRlAJDt6XB~0 zpYTh+7?{xf&!({N6fWMfYyryeaR|vjP2a8}`PSSmDr?);qZO?CM|7DM4$skl3%Ptz zF*9DONCAc(J>`4#KD(R)td@6(!l3nq_sAPfRG5nd;13<*1+PxeBFKSz;QtwOh6JW}#Zh zy|_L+lq7EJK9f9$g$rp`L|IhcwEy)1JwZE2CdSQ0A&AnAf^v+EbTDq({O;<{wFnwv zp8@NS?g&G>50_WFuGXCMc5h#;bqS2RS0edfr2(Y=|?*e20)m!sxR;ey1ZW zVbjI_8 z`6gt3F*B@?`=79q^J^*$v;Fnr{ubdQrJhH#&o%BBF1!tQI(uFh^m}WMF=93`3fWJU z`6&CjEF1pSDimS9*3XjR8|0b|Y0mK3pfL@6iojcQ5N}9Rj5J(0U$Hj8(i0l;()*k` z=GK$&h1tAY%_*KRZK79xI4cZYNQn9VStG2mRS`M)oIs8;KH<`k@Kbq4f%*f;oD@_#w{cqj0kWRZINI%!T9loGeiPqx-@(5pmC zUU=PA+2}W^jQuX-TzE@po`ngY(L0O}7V^cR@HBt0s|wu=yCokw=Nx^`+1>*48;P*$ zOBchKj}b2TWdLglLM6Rh$rXX8bupV2uJ*TrxfZDa9IcgN`-9}hl}I_=yN+vaDGZ4x zcElb0*E_BSi&3{ZS-@-B0&Szgw6kt{!6R6LLJY(=%glhha2;lwpB>ZO>UGjBP438D zcG6c;a7{J;Tl;Obo6N6+0&)Y%cFJzD?PbHlLD;g_l})to3-g!resO8r?Zj0Kg29Y~ zDIP2ofX&%4%DQTsnLsZVyl>tL9vh2G40+A1U5z16WB7;;0!L>bWj zR%YcR1kG6fMGeirJKtvP?xIIUkF0r9!ylh#3qrdhHyQ7krIJY-$~Qn1;xfKds!eM9 z+6H~>3?8%T`CU}i);Dl;P!v|i*p+p`iIQdMal$;`-sdbrjdr;8$0HUqANg$aMh&2> zAB_T$YT|s08M%HBiOgqt{_8W3M!Rbps^_{%Gq%j;2j)@krtA3%rz?#)LU26gqv>Xa z#B)3M$4q^Xp6N=E6yfb#>3)3)$paJBBN?z!y%4dk%gogmOr3)zId<;mza)Q?Z&=#h z{wHuB%a161h{xvn-mg(HbumvjKEIWvfCT3Z4$ooXQU2REOX~tPU zXDUCJk~b}hV(aT%CUL5cwpv;fbUTnwOrJR}o&5x|zS(*8*R8TozIz#Y$(nDc8SM8j z-;~Jk?rgCXC zkcmuu`m?vn@f&tyyK)Lb`C_T7x7-9U^+Qa{UL^HRF9|2P#Kgtl-F&s5zJ3sFw;vi2 zL3gZsv17W8R=tR{s|i0ibe?K;NWB;d^15&RY z#Xa_K=teW}4)AvqHP*aaq^j{VY-&8Al5{+b|9W~vG8bXb7)uXr5c%o#Vl8TiG(I;* zlE*tsaS<6r;9L^N?pZfuu`OoRnP%j?BPb_jU?nS)^dEZoeNA~>I(CC}{^{rRSslAC zr_5g$kPb987Xu;JC^L;9_xwI~6UQNM6&^8*dkeZiFwGzDo7evtSZCIhV9Vy)>s6gh zG48grrgT8$e$#E8Ni|N1TJCi93vf zj>_+Mu*3XB!AW0mAxfcCv`xYRHcK2us(Q5!dV<{|Ju0R~yQ+1g1&@ZFDRSx7Facc+ z;#|H9aZu%NyV#P?QVin>i^~6gIhYdQaaJeJ$5RIGF3GOz4Mh$ zQKAC)uY9Rw@A&@TVqj1$J?#&-KCArGJR*qRdSzdhpBFjBk}Ib8*MQlCv(5l|-%D&VV7l8B3(il0xejW0CGDBp zKh4X&XZDv6#M8oY>ZDm8YI;<%i%!`ghSpQp0_#ou@3YpIU4KSWk|7*98r#fTat)l# z3fgHi4!Bl3Ks^fHg!{49W9OtVDmeP0RLWS0Dkd+qwWL-VyW5kOd#=Z|oC!qF z?w)&`MhZv$;g1D=8L^xVLV>sg`kD|qn_PL3UeynYHw-UJ@Wm@_@&%^@H-?K!j zdwu`~=i{Irz_D63W$x^h{y*u)kC7blbSUB=qt*=AXs~_c+d%Tr-{rQ!*F50lH<*1k zP>PhI!;rEhI6>n{F0?tq3E?K+;-^}VDFR$2OO$Y~rY}%`Im_8^S8$M#r7a}usbs-t zJkgp;X!E>vdJhL-mdA4UbpMK4oBirKaw z6}R1%3+LqP(*KgKFYgZ_=6#u>I#F>n&(Wb?&Nu4Ysv1$63Iz)N0{oS0#L@2^R@i$4 zT^}mp)oCpLn~OL4c8)-K(Q_ZIM|EMW?Kqb)%&xx!0$_V6%d1xcEwHXfBAGR(a(%Z; z+xPI4la%Yt47662t>9mHOEkvANz=g?CH*S}cYI6oYo_L^{Kr}&#{@FcH3mZYyc@D; zhO8hD14>z%TAZ^#WrJX$Ig~gjQ7MzH#*n0W(!5LuJVkcN@LjN{nWO~Ha&HZF9!8@= ze`5Fjsn%@o4(Y`2n}-{g#QbFT>1gOunC0}lvQjV(&Ktj-XFG+dE$GxeYkkC zBTIX6dYnbctIBHHXLs&Sr%^NhbJN283l%P(^e#oIVG;ZJG8 z0Mt^`&lUcAhpP4iad&$t#!iJ22M*YkSiuFm53pth58p~ZuUD6BmswLLq=WG~EBSBm z#F$FjtHQ%!M#~~{kc=i{$o!%Ds!m3kcY@*qn)7r$oM$U5I5e?pNetZ(^qI)>q=Unn z1VSl0+j4h1DBPBbuJ9W(gB@5lf0Ej5v}{aOZcx?KWz>1;gHdH>Pnpm5rvxr_E zTmcN^0Y+5pV-R*_-Psi%>y|%cdFCTsFid=F(<;nX#6n()5@%pnoCfa9S4>TMY&>wo z?l9c%<|}!#wA1V4g)8IwHm{^FI+H=MU!duJQAb~NwU_r%=8epNvtWf%IRv8(GJKOR zUGCdSWe z-9m7sYq_{ORINxVI|C=)KXhNv53cad5VT^I*50>N&d<&`TTQg*X3S)7OgS`DIYYkg zXIfo^j=@)F{T}q2pOrF)9EdUF2Lx>1H}pfB?`(+rQJ5xLvl0nyTFMJGNNWo`4w<|1 zyyy|k-x6g!;(On|xmu{5H%v?(X*;%dNUfv03BjBodPOGLJJr&pU6M$?7rLXW_gXGU zoEo`Z8mrS_TP!kRlsmHe$?A&fC&9ly&03YINpcX5I9-pjXv&!&+sXyyDc9ms3ft4^ zcRyK8;f892-KK-vTe8vE;|Sn|@JXrFH;k86A+mQ;_LjZN zDtnV1a%>{mBb9YzWOv96Au_V}N;;V*Ar4s?*?arl&+qT&^*pcg_@Q`?WNo^duGUUNMZH8vY*nmuDDpnqPer^XXbz%l+r*Q+ex*_ER#1}gl|5} z>lFXWFLp8o18?9o$1WRH>8)hP2@loT$WAA%(vdt-nRf0`)_1k0fVVQ^E$r$n%o1{m zXp@f&DjtV>8cF`_Sc$$Td!DsBKG4%A%nUrDu489MvSe~vrM>IrdA}WOY1zZw64(>G zo~ls+;}uzKO=Z8)=^tw7UXf1JbB8bxHkv0`73%6nssg(zuB10^%G5VKXyr&5vB+{U zNJcTAA2N>#EW+_0TEA}6_Z1Y=V-Bz}TD12(dWe)z9izOagQ*M)OX=!*OPtc!`OHA` zzAhE?qC8mqy#3$5T+Ti6;|ml2bYS{q;3>=JT7QolhkjMk8k*?dIf?I1G2Ug|PV3D3 z^~Fx1wy8U96AKG!cfPT>KR;nG)ZNKLiy!O^DV7zj1flHwQYxbqD`Tuq4&&ZbqInJP;&iT` zeG}p95R_1xi|-CJU}Cg@$?BI&U{5!?c5*tn9Nt~UWjubF&~ZA#xmnkGo}Jv~>IxUU zh=nkBGC{bjbH3g?BcE(`)t9;4y9D+~M@bhW%;H#9uIdweQ3h*i{`WK2if^}Wq1<%1 zlYxVK+fOuVOC@L57vM`?2dbyrsL%qspQhWDXPceOMZYG-YIvAcFi#{IW|+LeSi!Dc z>-o`QAalgES|z%BJ}U27)aAxxZqE38N3vRtZx%fP^PJ{f!*uxcVH6aLuOc>sA+LBARo@olq-zZKFJId`%d7!9jds%Dfxgq=Laaw4-G&1n~Isy6}Q&-cq`E z*e7ORWsx9NT3?uy=I6JG3i70JE^Y~g0jJ$-b@tg$NB~MJLb*N1vVGk8*r&e`rnnBw z-2YhpU+?wTh8&7dS~OD-UU;f(EWIH<+{DW3xjvlaMgv7EIl_4vQQ!U5vC)!ptD2%R zx8~_s889&6$aTVBMcq!#tn+`MA!T$hl4zF{1tebOxtzN|w zLVpx*T-|4AP}J3zVxy@wUsyS_0#{0X@WFeRhZES`yR3gydpsO#0+hNp7Cpss^-5`! z9L5Vi8S4YXaPjk$+8bG72%q|%Yw^1$b5Hc4G)9-1v$niW-a+8mgBHN-eksBd%}=}z z>c>7Te?)!#v&2|+xW3@0QvZ8?9TNvaWxrKOpLbPP4I@|!3k9YVsJzKEg+KmE|5i12 zgI~2oy?G>Wgee|DXM(Dj;FUbvuLVQ@(#`jP@ECI+B_HKWrh^*5_2v97>XSkTluC&- z07`^|>)6$a9vWOmE9vTrzVGu?Xt0JLAMUbh08l7W>}3JPc#1?eJ!MUk`8$ z)QA`B(-xKJtvS(73=Mn}i@$}sKK0~^$XPqCFE;e#fjUQ*?a2R9y>e=H%iGucytBIJ zb%{BzHqj)yZaP-scd$h?z5btO&l#6SIVDuG>d3 z{m_KLCUdROAaF_+;8P1~%{n_;CX-fG(k|C(d9*A8!%WJc2^px;KPQ6Lp&wv5-5tMX zDF822sTTCwZ_mayMl)JZQJkA#_yvY5Tr(~WE4dI zHPSVdvKZPz7K?WCsjnJiUei@fmmxb31?1C7IAuB?3$z|WL;Ap7303l8UKY5(U_k_5 z^ddER1G&a%u8E`9A{6(W>c;`p4Lzqq8n3$hILO_5hR_1a9Fwc@%MCie#MQTX6~#4H z_2~M(JmscR7)Tt@%gkXQ0G4eAAq6LiB2esWxfR!7{1s|B`SD*nmb_i?30<=RJ2J4} zvW1OAahMe$%1lGDo;0&SlgnUeXkf@~WKEt&b*);jzQemY+vhl8c`?gzH;$}(aWY!(59vby^w^F!8 zVcP;P$8~0*beS8+Q#HR9TwK1?msR+IUy8tEYfX2(xwMT>Rf&{C^{F;9-g?zm{px(>qxgG#>p@?Vf z?$h1Cxc@?izEd|bU$~5&R=s&rFk8aWD!h7y9a&Eqzu0sJ`!=x+J&)A__%O~JbAiIT zYN^KD8Zm+0&JmSF&Ko;%7TiR6`9ox#_kF%CGGEXcijVbwg$&lL1e=#dzsN*0uRNt; z|FeRHr>7&IhrD7kG^A#bX&Uf`F}jGvBEmw(tbfvjkf(5Qi%`ulf1D<@$@=@(#(;B` zlqXt6zP}213-c7xIWLW#Z)WuFUD23ed80VYtEkIXBz7_*KwB+kRR47sYc*(|`el%= zCg4F@isFqh&Pd6e=PYkNcOsMz=3h$eUZ&F2A9ELnRXmsY!~oeL?1^lCb5hRN@bC)a zt4jTjRc9oS0iA)9tU1%Jan;+*T0FS~&hhPCQYc#)vdg`C$!Ghu+c@Jd^+`l}pV#YR z1{=~ruTyMzpXqSyS)w|y)?t!`Gc|9&T!-`a^e-v6gbyPCt*OD-18yt$jsbI1mTpio zrS$@qDL~!ZTC=}A8lEt9q)f3UP!QIBXMP)P1?7Oewa_FOiDQ!7jdV0+t=K&qEujO` zg%1ARIKy%dyxAbd=5bpX*^8!>h5)gB9VYzLq30%@2 zemNzw6_vZOlYa4kFqU6g?pXXB8YH^hzCd4qA7jJ^N7P8VEWj%gCEf^X@aT#pFJl*f zlrzq9{>UHJVKJtx`DaoGbNazqdM*p;Xvt+aY>le*Dt(mn)vH*9~7)TjCdekoP_$Vlpu}t&efd@&IY^@OM!p9yAGmu#KP=@?6ufS~d1|0L${C@^c{D5d@l*fa zwMCy?yt^7wuWZ$lS9S{AnlqyAewBVaCRSA_4Ix5Ufr6_Z;6HQG0?-m8t3?*ZXYBlg z13+lO_sJh5s72mcZZue#e}dzZ9wXV{t7)J?bkIoUM*{cwnm<40NWy=LPzD=xdsBA( zb4Y=>Od(d9`)9C%{!|%F)A{ki{5`mKS}iIpHI}byN9AQlK5qu&IH_mU&*wvfoZO9l zvwr9z=gRxb*9RU}&A;2Ge~>^83tU!m-21351E)TmKfn`vr|)Tp0pNgAbzKHHFHz%% zIWIaT;Z2@Dbt604TF?E9U&Gl$knLK18mX;3D5JC%*Q@GmFgS;ARe-2Qd;Es^^R=et zQ&e34;pSYHAm4**bB@JF-l`9qfo!^br&=YVd-rW(v^Xc>s!xf%#B9s0wL(XvHR=VV zL6bvNQsiEx0ZUeGfu55P>^H#Pfq2G{K@6f+JAt)wPg)8}6ac16)f`;^&?~|ohFmB= z3PX>u65`INKcb#UR+{`E>HGAHVzn{E;4MMP(1(09_RJo2m(sG7oaKM(9!8Wa6FWOHA)K2$LNy zU3zgzRq4LL&e38k%!AiDFZJ-{EhA|7Ia)#0fJxcAAL(A62GnVp|SR5 zLvgUkfg^lZoBzqxynlG-p;a_i<=j8rtj>=Cc=G9^cz{Nh+sA5u*0(M$&Dd}W5?!6T z^TmsY)jazCrJEljas;Nw&#%S)vq}9fbJ}_#9FvMuS)s1bBikIPU)KyCsxWXG!faCf zZ>fP%!6~LjCR)v|qm4!)M)d>j7uv1yUswu#y!v5kSSHaX%AQcU^sKC{ z=XWzpRWGg|w3?~ewF%-maZTS}b|4b(vTsfUl2HB8E-u_BkX&idj=N=h% zK>!o3FR=Z+eOCHY>5MY$@*Ge<;=+ClEOV1KvTj0`#{8d0V-JEaH*+J^@-TDd6PIAc zV0@VQqV%SloQ(FqIQkuNLS@qWAElOQw`9HgmoLA&@j2qUb7YUN|DnY2$-5Kl7#5Kf zanCq?-P|SuYbM6!V0kxA*KlYU;iu($gS{)5V*sUB)%WKRr-x79J?i&%Id-$8^=Kn4 zcHJX`9MfagF}T>B+G^d1dX@Xo^oiGl|LP3&0yplZEP^5q3Ae#eY1vipbiI0o8~)G} z44Z8eUFVuDlJr~!&l`k3^w8gPjYQhT?2q?+F2h8ba=UZA9k7enX6T^H&QHj^NL0G% z;+z>ILNs56$qyhfDmd4=AoNvhPW46~@v+a}VkmA-V+=0(bE<$D6$KH_YHM>Q;H3@G z7nC-#?+7Wl+ney(*ydH< zbQkL6P0nK4;pR@?!%-ApkZepof10BDTZ<%<-6SP3aV|hw#6oH}^uLPVZ;yY)8~ph* zk3VG{T^9X!m@66Z^n*luHsIy|qK=Pd>6Tu7h%-)Zs&%bfFdwIS`iAmlSP2l^$w%I( z;2|#&=ZyweOs~lMwN9$)^9oL3A|mCy|9(J&4hKuS+K>9aLX>IF>Rfm)@7XqQH<#hZ z=LD<2s_b_jl7~5jx1XOQ+oJ`>%2I4h-o=0!UV_@D#lrJiGwvBiUBoco+*vUA!1#+P zg|e<{!r{B3FEF3P;ZR~J1vhu2{5P&P>hWayJpLWKbV~19gXY?M$$YlF`7oj~b*`?byQ%;sV6mQZGr&mVp)s>9KEz?(oieTbv4Cz=}l*dTbf51v3JTKmvU+zg(_bz+k zs!soLXuX$U%6s#S={)#B-iWQ7-)(hU?|%zb*Pt=|>BZ6e)9DFOw|tdeKH-+u0$B-! zTyWQ?Utsi6PElVo)MKGWgSBR>B&4@5VuOpO^&GrJHor*<9N*?&OCQMqR*+lslU;xcnvSfA{F_+CCe2run}U3}=N1}~39KJs4MPLgROI?yX_CW+Iq z7`#1|ym@}!T;8-=3KZmoT(aU%K zD@H$%@IRtz>`T}&b~n+;6x57H3$!R3CgswF z5e8qPsm(WoG`>Dd0gN>^Z0O;n_9N$EkxnnQRm2^w*3;)X^ZP|&AHp5e#MY+bwdK#~ z3O|m(q?dGgIGAVP4KLNdkzjR*FKS&px-`HkA{}I42sBqc&k_;SATZ_-NeB~17rQTGmDu=Jt^H*-n;f-VJ%ENVJ0lak$-L z-`vZ~_R{rcWqAz#)C6*S2!Zi3M13xI?=rgfwQibZO?2(V-)isFMnEQ-6pf&(M6MZ5 zuxOH}?5IB4*w=j?l(($XVllu>ofiSl)G0G>$t+Fg(VZ=QZyDd2#^U6&-PsGe&DJ-b z=U7f=LzSbYkedsqjUlOV+!yNo7c$=;T+DGU_Hm9Lx}VPNh8#+xvj&9TBs|~#D?ZtD zp zJ{u9RLvA|aOzjqFFBQqO%>`}se25M}872ujjy0@$P)+_dPdc{W5_%aY_Fg8Ky&W6E zatup!l&Wc$glsDq*m>wM(u=4i(-%0xv&r*OY{5)6p| z-sxtqerf&40p&82Czw6X1kG^|qf={izTSc8YxW3}U_)!}_?oRLNyJ(BKcDFtrkae_ zKy@vsFik*vGpfpiQj}WiYyb3zbuF8~O+whP!b=MNBXyu1KJ$@9-___;V4(@hWPhK| zNqn_Q7W0vwtaWr z_HVxKo-cY4@E+c>VW%1Sv^C0%R;s&kW zQt${28dy9$Gx@%Bj`Xb7qVGwo;mbOhq0^-;N5v3YZOqgU>=QXQ>iO0svQqmvU%qs@ zAUG{8bw^#FS3O+OgVA$;mWM=nE#JJpbCCI!%0ZZi%!^;!V5zubR(J zDHd*bAW*}8Uoyz6{UdtP;~@5+f&MC}u`L6;THm7u_w$f@(x@`B2P|4edJeq=zUP@A z$9Ny$-_qdIxD1=F<)zR;>8IfNm~x9QR#PgMmZ5lIQyp4-jd8IYo@_zABPSckhYe`& zdd^GkgxUvLQ(Wq-^qpNrO4YP6UknGxefQhTtY(3R81SHq2eRqW^ySWKSWWiq0$dr z06@YUx}JB--eCG(WDjB&Sq)%Nj)( z@cp&-##QW~UtMsVqtt2*`eo88Ftg?lq&8uZ0Vc!zDY)h2NNF`XS&0>49zDO$?>*5= z5i?cpYvo6-J6ZPB>3XQ4*u;k-PEIOKHsT-vePiX>Rc)I(jmAW$prV#&;co`k>$REh z21evgl=9qh^p4-Lukk(og?hJC^HZ$Ry^kjF2C-SXXY%g1@kLdy zMWO)icR$tg;|GQ=YR}VI^;5xH+xxrP0w!LB6Mmrm{c!c4dmeGgWs63*6h{gcGg5i-WR@WWb_Q5>!Jmvr>C zZlr#h+{7!9&RbXBcqX^W>-@`lSnbkydsmkJeJCry`O_#x+QHV-mntPa^YW+H z=-I#59fPo$UN+Fi{k7H~?T5_RJ+u%}5;&A_{4| zqY2Mi%vm<~KmE0Z2s`G42S8&i5l(q**TQ9N#hJ*uSlmka)#F&Hi4-bi9%7X09z@8V z2lu!&c07mH?#drgAHLU5Jp5qV-;%3xz7SwD&JXXPN&|A%#$}4?^%p%8aj?WUduyPz zGfxiN4s++oKKsTFPqjxWudLei4VAx?p~{9BGkXU=`F=G(F~Ms|T81inKXCg;MkQ~= z`n`US>Rf``i;GEno=C?iK3lPd&a9Y0?A@v%TnO|;U`^Y8Met1-5oDnjvX`l+ta%9g zbG2+F@7BrivWxgD77b5YSvT0_ZsE3jg{OA=meA$fysN_g=w>v!r$uGRA#iK7fnRV! z25t9fF#y<|%G+by1h-v_W5hy39=A^D6h*yPOc1ki;G&_0r z?z@w4kxXr=b30aLfK4g-$qQmWU^fxfTgOvZ$91~J=yMZ&sT+E`5aA^AucI)omRRda zT2*?C?(#mGf=MShQ{@ik8As5uZ@us6GWIqAxPeoS)MczMb z_9;!nyE_|O-5PuBX~WMrrw>*=n#~d%k837eDktQ^LUHdOOe;fYVB0kAX~1Db2m<+44h-5r43no4OAAhX#)f@RPVqN=LBrY0 zKR!?Ct#+o}6Tbrf!aFX;Uwm6#>YF-A^2ah6vsx3@w6<~*_}GD1eV*No^~{ zr0+7z-_4TQN^d>e82DA~*C}Oc;C8DPj{hKngU-nMyg zU-xEU$sI+xf~eP0t2i?MG`F~TFde{5O1rjj@^U4$0mJPKrp@aQXg-he)4XnZP-JQ+ z=Fb|7yDoPIMXwr^M*|g_)AI2JMVI1!tTi*ym`=Jrc++`P*KC?XtlajdathPRv@5&8(|X*24~) zZC3rCB2jFJOm-Qpm2OEb7+y_KgX`CRJn{ACLYA&2Kyo4euf=6SI}>nhc3E>Gn|jPN zCb+J)NTn=LUNL>&y&DDgbIN4G#=%F&5^iB?iVojHH^37H{d2qnnc}D^cSbXF0ss7dOr+ii*F_xL4(l$ls2kD4V_r0}LPB-k|0!F{>LoR-pj7_hc-)xI;Bf z`$fjl8P%%}-dQ8$)oK5B>#7eJd9GP6xoQLrrV(zsSl{$u+;q5sC+sm=-N9xOW5p?b?XSm=6n5WBR#|s_s zmn;Ygj56fBvz9<4*_9LLC=G!SU}8DYy^8<)=M6MmYiU)5u>NivPczcyW?nldb0pu{ z-F(-+g>Ow+Zqf&R8b3DVce>rrV>$mL+~-~b4~pD@q|MUdk-+K7#c7Crb=tkmL=MMx zk?e=GgsY|hkkRn67~Ek%J{-%9oHJLDT7JUzf*rugib8g9PW&i zwfMhb$@igan}e%ucWmBzaH!=0)5z#H(%&M~ZJcw-9La{$- z2uGL#j=_2!clPOlxOxYaY0GyU?0<>t-#iF_q~&r(b3&RAWjq^K1IzO=m68LOe>pRhHJ$rmbdTm_jh)jxZj7#bx4U{t5w&s4ACqcMAi6r+S^8$l?pS+#;>KUx-(yU?(jvqwZ=@~ zTQ5wQ@Lo(t2@=!y-JBROu4}$r;8{_d@oQTf&J589OphN+G&g4s=hC27R`kL z=g6&rkbI-GJGl~1o(8Jsg}in&9n*^H4Cc5s2|IR5?&p^++*6(rqqEI<%YLEhEa7}_ zjePb!$ht5d^zwhO=wj3{;)xbju=-OPvrgv!R)W`X<+bAv7}GpT9@TWhvNt5K->ne` zf4pXqD<>p-UhTSVtz~u*0hnZ$JFmxhX8}Za#D?Kt>HIt8Owegx+v>QWTqju2!ic#5 zm|@{p*QuRU*Wh}g`PUuNkEn3{vSG;}U9Yb^3a>Yal@2)s|*el*3I}WUWJY6B-$Wf>rH&1HcgxvzC-~GJDd8G;Ka3cI_Wl z>QCO78j_GMoLU8v+U;qIowmcbBlD`m1brkEBgANaA&F)@<+m{x-rY`eUk9%Ty7%}W ze*@8{yR8?-XI9sP=yncjbcDnDK3sHbPAq%!nzoQZaM+{8T3Dx=JH_yOPzp)}^ak@S zn|0o;n2=RtGw%O`rdu$5B@)w1F4>w3QI*zIduQuQgU@&T?o)){BqZz{osKNHOC22g z)5OAMlucrF3qdi7h}i#=Cb)@5Y;xmV98DLK2TTrj#W2|3niY{9XL6>BCaW1HAZqkG z_zjVEzma-5(y|S{ox!za_Yk+9|5%3g1e~LG!)g}BFGg8F$;-57eYaFEK?5F{KnZOj5J zO~IblfV^BlGC@l!cm3>|cgdG$fi1Beg1At{e#T~{#Q_|aVWyjFFR>)so^|x4e?pEz zlrNp0wWeNfo8GZHKm8nj>7oz!h5YFmvj)vmlq^y9(26m4HM=7vDNnUjEprRQ@0#e4 zF=MAbcJz4S$P)24%p3nk=aq1k`eB2@JZS(Sh@$nrl8U1~9tncO7^VS1hWD3aw6u3f z7*5Z$&cdXE##{}sf}2o9oFaGd59i`up^sAIl2xR<`LQO9LST}5XF9LP3pZT6DOh$fnk7lO>IKLL z(pgr5dZpA7jR&>cx1B_?IBZBqH-w0f?1MpDw+!6k$#j#in*LPhyK_Byc65Q+8|3gF zn$Op8qt0o=qs*Mkr}>M-=Wn|{5<}$-t=y~tlj`#;zE@PQ;+@|wNGK&ik3X`BN8Rf< z?i3ytVcR6-wa-(io{92%EL5OBSodC!4*zOUmIMjh@SbT~-Xgy(T+r5H!SRP@-pZ86 zo~nGt;PBy9eKI#nca`bl7`H}$cIlJ~RAIM#cCNVpoEz|kmUI#4M14ny7LJo~tU{tD zXI~73H`Owz#0~j2%fLN`VODFe5Y7A{r4eE=qHzN@4-HsN@c*ipcu?z1I9e!piE_EQ zR!R{v$jxaoK0Ehv3{pzh4`)(5tH0Wa-5&7FF}QLiqa%)IlOowkk^Rlu`VFjziN;OI zkRvJ&#t$*w9fp|8(Rt43=#MitrMU?Xani#^7)cdslk7`c+o%_VVakz}(lSJO|!eyR# ztE5}aLWO^%*zWP&B}Eu;i{hH~yPpx;H+@MRSK!FDRP>Nb;y{(n76-~ zCNrRPWR!M$80XQRy328SVyJH3o#{@AT_NJ=<)v7a#)#Spq|IF*ghn4>?T_sRhMvDt ztM13F+5f+G>qjsL<)rtstBS0ZyDmUr>Slf^wgNnQ6&ETajQV6*V)cc!# z{VznKbfY&C3zk8bSKA9WzcCS%Ad=(bg~Z7&&S*JIkcb5x0o14ZTYjnElkFc56*8Yk zA?{C)J}-&PO5F^KbG!JknK|JV!NID_DKyhbGB9CnBDRMx^N$1jeet(Vc1^%M4;XAG z3bb@rD)XcuRNtobK8juUJL=njz`U-zcezWdXLD4@7%Vv7W{u9jeJt5oBxd)_sBF$X zm9rRx+}sc^trUb(j!V%TCxC8&IsNqC_B-e2SJG;rX0T#f6$f@Y+4CuvmA_$?M@K7N zz*_S#)kDr&lv!9NDDKa1# z=Jx5T4wYd|CaL(qJ$^KwzGq2g6uw82yOGZ3i(wIJ1{v*em6@@;32Yk4kl6h; zs{TVo{a&o`#^xz5%FbiIySB?iiCkF(CF{qrF7{=>QqPkIR_(yW@z)iO?7U<#+FO;h zh6pn(B3j-4E8CgsZX!SRG%d#QX4V|jeptf4o0K2LenVUlS-J-YFi~PROh4(v2geTR zG19s{D+n>D97h6JA2hC^=Aw;171)AX8gkj#Jr2`F7_RBQ)7HeSJ&cnf47>^KXy79t zFXx)4@&%M~4NThTR#^6{Rwd~IQ*=!!+=dBL74RhU8{32JK1i!_O3R=pIvfkDmAO378RRdJrN~3nNu?*-0iOpNEh93^L3?ZO=+rqY}IMWyipBYwh< zad*P^V~oW5Kd29k;}s1!*D87KsxqTzmX=czqemy3FG!R};I{H?St4l{(KUSEjuxm; z=RaAi)FG2v{e`w6vZ8rm`?h6V2AgXtw$sS-L+>3tIG=dMEsP~3p~2>TCx)WG^^_{_ z#Q9bt>*W1}xX{)@1J`n1$}zY6uZZn$<3QV+{#4;obca}rABZ}*)8{j-wnBclkvPyG z0ThxAB}_35?!fp->#&qxyUXsq=5fTiuX>(rwy4Bc4<4K4kD{u%k^Mt-rQTU@8EW#Fhdsyjl52|2}xyH9d zGQFBsAvh}iN@$Pg>DA(wK4Tb$%)2dTN{dTL3yWEjtSrDH{tFj#>v`&hY}RzhgB14M zx1~SB%)C#?`n-jRUk%a_L>O@;=6A$z?oZrScIYivG$g`}BaAfKET4E-TqOVD_iCht zqbNWKMH{Sz{2Ev`Nr9G4jS)f?19$szV@g;&ocBy^LaoHFL%l?~g17j5FW(}r61;l# zmEx9hT!I-wtmT2OAsAyK){qN*+N8Ti|_P8{q4X64RI(miOLgfv(lKI z>81f=#CXZ);GW>xeob_{;A)eo1Y+Blfv+IWpjgwZ^D2bz8r;@@pHb{jEKqz*`o70e zYtFW{-#CM&nG9;UE)e3=yAslbd~$L@y15ZTheug^ap6R}IW2QZM{1G1PQq{kg`I*P zo=4tJhNqo58z&P@zn6A1)Y#CKA9k0qR+#CFwbqfdHg!#mS`Vo)y=2kG#tyXl6auH< zZ%fF-AooJN2#a6qOz&b40#9cbWIl)fkUXT9{M}t+=gFX8?MCqr24n*tiXC5{ z=iI81g9ZaA+@Zr-4N14aEdwO!k7A}@8Xxf5-vO`>EEt^j#KPGaT6&iy-E*R(5jF$qyEbE_ave!^{G_9PK=ez)}NOipA{#;B8VUvs5D@ zng*}Yg}X?gu$PmaENp^`zd}kJxEkN935p9Urrji5*kl3iotexBzjsiIc6OS0Z{!zG zcwuT7q1FoRrP3*~YSYA9yCwn%Xl=5DIs=lE>#B^v+EL9$R5!?6GMM3kwAaN_#?ajL zwe?HW)6uziG&6(VLp)^6{R4UfNYPH$zvFlHPq>4ySdf!rygRHMLQOgG1MAK8WXdQ` zrLf0SirlHpP3^#`YIeRm^+^$9EO&<(6%AD;PC>kEr1v(o7OPq+T5nGbf}Rdxrw{$*Cs5P+M?0Nm8wtytDr9m=8} zAP54pv#WAJk0T>AjI+#W$G%y$gonN+!E6Dn2+19BrOUZlQHhTlLP$sF>pyz@x5))K zsj2&2W?8{3nLkD=GUg$VeUD!rErrSqI6gmtTcE-@9-ZGc4Un(;;_QC}1$Jm}FG)qi z9AODNQHHmyT<~)zza3XAp^RrXO1!EU1)m2>JeL%}WHRJAOXWo{WV*>AjmnHTVio^u zD(Xu(n!kzmrjwt9XvIRg1qEIJ@qc5bEQBYZ)lA{yh1(;~`&#-U7WM|5A5m+W#I^}| zo<(xJ2pnQlt+1L2X}Lv6MK>L;h~vaMe*r?UQkC!xy=J!?z5$em`Ff>^2s%g9jiX@- z1In=O!^>#Ts|s-l`+F(u*_=x4IkeO+oFk~p7!+P(`ACZ(Xf#Jv`8__`J_4im0BI7|5l(G4t~I_ zv3QnAiuJ!A?>>#Gwb)rnpPn;v`k?yb!^2Yu2v=b__+R)Vac1VDoHo+*s$)0So~&Fv zjj?lKf19mHNGy&~fteXh>Y zY7R+ZU4G-<9rGFtfI%9ypP<66f5Wj0Zk{ctnClTBd5ZDeJdk!OCGlX)P5oY%OdrwK zQ&cNaA9&|@di|1e=-%3c{qs;zkpoj%Ks6c zjYcmOA+ErWaPrD)%nQmk9A*FF8Iyu`2u z!y(m^>N$?iS9uDQB(PxaEVy5!NFe9yNk38RS8BZYSu%v{R(k)>wHth~3b}1}cJT|w zSFYRTWOG96+qHMoBKLKba>mwg9N#?m?5Alxk^a_xus`5(3+FV3a8HKU@{zq4|QecZ+hMt4oE@85Y>hH)Tem82p_3V1N^N_@0* zSXRo`WJ!_vVmFKPIcpe*`b)cUAcPMLEjWYAUH7#ado?@_PopG=0si6XJ?7qhgH6s` z^^iLCbf()GxUg914z7Ba^)iPn^Vzi;k$@hY0bwRFWqJttysFI;lc8!8%BJn$mO7gq z{Umqx!v)IiT%pDnKl~ldjd>aSfP<*xWgcsbF0yLG6^zKZ)&ujvBL-*`d~x+a53_Q8 zK$5bpbNQr|eBqmlELE9FNk|uOAq~U2`;LJLN6nH1PD_x1zxry@C6rHjf zlE;Sn5=Sw!xdN9B}sX_Llu;5=; zj`*8fS*~!lc8#m4rqt;8(4DaPUZd`Q{<=B8ExWG>4Y-1ourH zYfiC}*G-GFWe(q+i^xp(ql-<_&4Y_g ztJ3pm`SY_2X51IGAr}XTMc34`v#z_uuOzg%JyzdxjAsu!*#7SSbG{;L{q$o-t3TT1 z_;Gb3Zth^Ac}cnn<=mAkBOc#B84Cj#qN8o}^7oO3{Pco^#Yf28O&BZO_ribl#5tAl zq#Jd9`3c*a?s>9{a<-^D#GML!w=;F;DZ(!6^1ij2o*r6ef}8RE6q!*`m#192V7~rk z!m~Te>j;ytAQ6S;CiCQ0ZqF}xcpin11m4D0)#&W(%(i~!{JzuuX`JaPr<51D?q}UH z5#NRjR%{WgwInk|#AW!=&+QnShn!}fA^0qQAR^YBv@-9Pj==oRF(5oE__)?$*hPI+ zsVQEVpfFWt>S53Ka*c1dRDrBu-AoIsza^$D3QAMDPC;r5eF7!3BR&sMXXe z;$;#rT!0TN`0r0jyB=%vPnA!X7KxhzFbQ0WLn|Zz*NK=Q1y~1q*>;9b?nSYne;t2D zzAY@MVzgRyT*C(Xf9)OFk^;QbnxR?{8acwby2 zf%R*t0X${L=R<>Xs12&Ek`e>JB~DIol) zpW%Kf>KSgWZ!acSaviwmkDkeV)^qsy8z4{-e3v3RQ`|59Zm`h}IlRs1O6*~X?YDyK zG4l#Pga@_?v%XO#uWuUsQ8UqERNfXoJ3i>r1(c*lkvWSt8~d7Hz%Mix6gx^Cb;oOu z7@)8$aih%T7O7|6_?&Nok6~vy!@Li#>Orq6oqJ)>#g&vxignnF#A(egIbq!QTxvPP zgxoq`xJOGMbGmntEhYmVPx($bUC@%C~iXrW%!dx!N8)i?JC4j~kX08zWvqS8VDx!A|E@?P%T zvhJD(rRP?6t@+uZwn0Q;M-(SXBs4U9&=Hi%-+m_h!GJrD=J9ab4ieWR3M!E}H;D@F zXDxS%?nM)YbEHB;DQst|jUqD4)5sh7N)|q3?|g>d&s-VT=aIHsjOfMoZV#Sern4~o znWQ0+7-*ISlM+RW9TBDRD724cmIW6Kuinedqm%0EzsHY^y;ISD!t*1S8jedhLWh=Z zrBrL^AX!NvZ-k9F5EQj-4Q?KrFgn5Dx&rgEip&^^pd;!L?|b?}8dts*{lt63@Z)O| z%9XHO0OeTDAphq9ON#)*1h4wS!LUdD@j0{Oo;Fm*R5#pf?D9BE7=L)kyw-kAp!N8A z4)|?MXj(TcfZgwyX^qN_`tCXO;k(bh!n+dO;h(7?-ZX2o^q7|Y*F|de#nM}TO^isz zza?8l&lm5ttXKgh#FL`3^}k-%Bio6u;9Wg`aU`&#UdLAVC!FZzEx`;&&xXbZ1H{td zYiA$K?^TEH?q?k(y(7efob$Pa$?s;?5sOV5JCg^`lX)gXPDA}m9zc|9ThH++pVB=0guEkbrJ1L9iC~U3*T55qE#>AK zoW{;|=~TsKL(+2gRcQ$ebTQs><8yrJajo0ktw-*H#L=B@eV~DmbZ@e6non-HUo~KE zE$8@l>y!_6j2W^+%go@%t+4D>wyDaPslVb+^I6h`I?4IE>S7qnf>R7{Z(ZYY)cT(! z?~O=SLgkAhn7=waxRXop)4viJvOUt23^@ouiJWoFt>2j^6qQ-~0S%QVUk!fvHZ79Jt|(l!gn-jjj0?+eARljqZhx zwpWlX3U2;`-8fH3j{{qWkmKzEA0Nqlqo?l0r8fb&?6pS(U9HihR(F}O*Q#u4Q;x^i zI3Vy`oRi1EJ}-$Zo?RDP(t@C}8VU-V_y?coUBaV2HZ1(^FUKCEFeoa5hG9ErC7ktu zxM<$I<%m$(5cxzmbuiTjak6AklTw1OR%HHRmsi9vz!HbIAnzp&tILf>gReXLUMD>; z=6%biyo#H3hJexi0JMb;XjPrZ&TvKdzG7WA(DdrrBbc&|%l$ZJSaDer5Pjp3eJ;S~ z1^$$h_1ihGc?)5g5JgH~Sld3*MKm2B3p^4iP%t-s!3Y{{`{6RZrZ6iLIl;#TZqT15 zM&1Y#OMF`F@=&0E@ESU^QmPoI)n9U`KGak^-|$nBxoQ0?eQW`_6d+vj9s1siCRwjR zTU+78xwDC|ga) zhOlw4|Bu05OzHMTmdCvHX#c%s+=fU55*cz#Op zzA6<*VuaYh&`vU_13J6qFUa!s+7C#~gU@JqiDm=Gi@skfJ*ap3yNa)1C@Hcj z*D0-_Z~iYX=!*FX21Q}_lPi7eaz^B>ef{reM%^6cM_2Lg%7R^o=JT|$e;o@_0YZS> zS}~l&s(O+=YV}fnuHHI*rYOg{|jqtN@vo*Adb8uFb;D+ z(_Mnk-boBZR)J~Sfd6bw4mS0pR>A1Q85C>OM{zb5$4AuZL%7A(7Q*u& zjP}`t=Q?s0BXR1Bm*IDcTytb6Bg5N1UM$@H6HVerbErY8c4*GX<8*3hJioWG9Ua(c zneAjcB`*gJMoQT>zp2s7`UdV^AAhc#^h{{`p7hlj6vyLjNw9Su%m$Sj*zO(DCabZ% zgcbuy|CZg0z7W!jvycwlL)ROdtpzxnf2W&-JNoDwWkpt!J!5l|)BCi3t&&PlA(G3C zFg13lt;XpKqMh}ffwy+4eog11P$8OEn67<W@u%Z86yOdI7Ko3aLm z?c9by8^?Js$d@blL^9|$TJLxB9VmTfq{zptuxUnYxOFOfLOe6hUqKs zi%589LE!v#aMstRqvL@`8dp$MrcC}+=iU`68J__tY=KK0)iv;b-pKxi8*Si$&qWGcOk_P| zAiQ8_isJj;)Bmggi12?AEt@Y=>gq&xku z*Ik(k+DZMCg2@eV1A)tCTFeRxcl!I{p zjNr(nh=S}h;{?npd=&4TN{n16)%t>NsKyO&WLhT+ypR0zDrl%G{kFjq?_W~6*)zsK zuA2?MkD6G$xu2;H^U?t}>dVlDwDDoFuE*!hOH!n`ZjG^v z!dshC+7{f7jZ*3GHLT~Rkg(rNCArh}X~kcP^|4PLOkN=9jC%&`rlzM~UB8#3|6Zzz z6V*fiQIvtV@HccRCSJIS3JaXvEpAGsc*(oSM5RZ+3vkI~*sgyaY~u_nN5NTgE7pa8I=E^!QQSH`6V`NXy^B(}UA+V}Z$|G8N0*mpy)8C$A33E({U%gneOdG4jhDO-<`KZp# zzZ24lP`QVkh}OL{Pgn03pwXinqE@Z%;lu^N?$W#d5v+>JM6ZrjUd z{Zf?etjyzdVk9*lzBb_Hk#`dva6Gw2K83y(o*2qPYA-tcAFt#sWzQQ#Zwu^^akIICUfENM+lV6$NPZz z^|6`xv6l2O3KjSLGev)rgg7k%)$VaGK76X;9~k`JyHUyfG9Zh%qb`X61{sn~Dg-GD zo`BTHk(S+aTyBElYCcpFPNjfw zqE9E+igrSXIMbrKBF8yr+BM#xM{dab-(@{FBP%q=*_*H1$%pE8m7SjH7|F3gepOs< z_p3Dfn3g0)IohORk4tHloA{5ns6b=5*l3Nz$lIyi;Euh!HaJGBENJTGM8;2bU)JkJ z31LjNGkrH^YyYX!2S|Yqc&Kg<8x^6#M`I_eqQgH6fwY2KDa>I}n4V=Af0*12B>_=1 z!=q%jO6@y_2DFteEmQM7|6){ncV^AvBx8%}T^Yg1OZi@aj%W~&`PmC<9}^%@fa59+ zbFEV%kXCYS%jIqEa=q> zp?fxUM!te zn|OpzH7wP&_x)T`99h z(&a4NrlyK^CsQN&%qb7ID zW$=}ebI4N1{==m1I9Eo4DhZjQRA%AA+-LdbF?4ueLr-qAlg&bd{GfC;q<;7=?F{jf(_P2Di+-oH{6a%?%H|(X;viZ7O%MfCS zN7?fN9<(yBBW%b?E&Y0B)iu&eAg$pEHEA<*$nAVXvlU9c3q)AHWI?_Nb5EyBu)K|T zGUuL@Nr_g9Ot2o79szfu`P|>OJuFSx z>~?Y3yTr_l^(bQwyjZ5FaEwnDSNHvwnG_fvp{Z%GMBG}{_~|N`R=DDKmsK6sgRenJ zVAypH`|l{ih~VVnLrv!|%J4=jLD+7NOx_^c)&gFkF?h39}zu61LtA&%a97p6dNK6A8TXd#qRp}BZ4g@#lA+`Dn^OO19 znH&cuMN9IPgZY^($1lxVnQb`zv~J6#ITti-vTpi>x7Ea zxt1qIwM$Hn@v-gV&r>x89<}6;E$Wvc44#Gmw-@tYR#!Q0dQ_bDmR)o#pu^@cENF<%j_l3C zex^KT_N=+bkQ;q_oNo(Q23P6RWUX-gNLFpMP)jJ`qV+_jg~%@*NU=4Z1rb1;I98Bk>=q94S?)%?-a5&gw^!H@}OE z5wd%f?vw#Jz(3Ux=>j3PlXT?lx1^&sPR? z$fB`KE!I#*lCS0lwDG2tu3v#V;-B7p{CdZ;+jEnP%)F523!IEAfwYy3;{ezkP>U4O z=!%Hybn?=B&t(`YMnQzN^$OyCGiY}niTm758Sz?$fIFA}tLghc^$LV5q?;!k%v>1} zxuSZuln`4zf7ju%f1Ev(_rS*VPUf9>!(q zZ~dlNd&olF_^`cnGg3BmmbS#u`p_%XmGSMO;+6wUHRQDbMkluJNEcowso{{GF2SPs zkWTCeVM7)+6vHo01vQ&q+YZl|i8Lk-yf$A8^UIBL92Qb1qFtegsXyA5a7o%8`+xj- z)qwvPAC{L2`~tppCofSbApF93d{euQ%T^r)YqKb^3t`6Oizl$U$qowm>T-PbI9g_= z$0P`fTlG(dW=?kv?!~LT#mIgTIkz*ryzo2{wRBkZq`eH06`I&-Uk<`x`Q&J~Vna~* zN24xo_ZLg~99}B)A6QbkGwYyj1h_ExjMAL zP?VczfO|V?z%#<=NzT%(0`7NLRFP+k>)0bydaH{*tx602QP4Ph@EPF%PG+#0cC_G< zO?{e#*_M0a4ONSF9htj^#p$pI*0q!K+a!M0;>_xV^>FncEYnmtHb~9 zE^x zB%YCN{OR$cU}oSU@3J|0n`9P#^NSUI2zEQ1OBV)5Tn0knUwX)p15D{ne0{Q{`BTdj zL=io7y*K?s*+N&y3diycixr8R3R?n0?-x(@GXvP$SYq;#l(_=??bCbqz5?Cbe64#{ z5Ghhh(9dj&;yKEA89mFo_j==m?rUJ%h#Mhd#V@*G=@XCM`*dcwjB{>0&@DospoBIZ z3oICQ=v~PAbxRg-NA9~*G(BfpGv6$IEZjo`?I7z!0 zAB|ibFBYUEURwFRlo{r12vFIwA(0a3Bql+o8~ui+rBcLX6_obr0IjH*22blpoMh*c-9Nh8sWLNsnVMW@v}2mUdAXM6N7k+FS!H^ ziIZqKFP-GNpiG0}{sp#-=>|DCz_=pF!ZKnziLu-lfeC|vuC!{ajORoUgzZIdwqVhEz zurg*h^|u#B$B%!I$iRs9;jk?;i3&G`{G{*fv)!uitefKv|mUOtaU{O(Zz z@}HTp-ybYR5^C1&dgh8(vSHuZ9EoFFyG(R>~$Af>^YGXvr_QRyFj)-M_f zt*%vIFVA6Va7pQ=e1+!K$jPv6Q=7T-h@jSJrT8@WLYff;xsyuAyJF=04E_^ik`5~g2pMQeJkrq?es7FG6SG(veQeLj1G9$d zDif8vtzMgV+}s7QJz{)y#FbZW2&dt_Rri9u_?~hX-jshN#Q`asAZ!NVed9vd^;c0J zjDfwtZ^9~GPCFW_S$Y>_Le(ze*E_EOzG4H<7LgN|-}N-6cZ(8oEB6o92;NyJn zcXTzV-^9a2+Z|s@@!Tn=PEZbc%=eP@li>%M%X5v6!w?FZsBC3W5A?t=_*Zn_{zi#l(ctynXKIim-jvHk3z+D8E0z zv2k}k|D6$$bx4vn%Zf&T5cP1#zF}I zylwdIkcT+-u6DQbL=b^~1c7?UFtXj_@(#uFUI4l5Nw-O%8aGy8n@q;`_ljAn$H}y! zyNrwMiwzRT_=*SRR~hz^KE49IE_rBqdH=8blgtA<{9Zk!i>p#& z7T7aD`<_J;*x*PufUlnMFJQVM^V72rG2x=YDiKt7ci`D*$NR0?@z^|Z;4H8DfR{!3 zCdV&9N=z@CcfLSP3g6{=x1`)OQjPR%egTkhgOs9+Jn5CI`BYf>&0vcu|Nlq0&sL0A ze9$9H9A_^yZ!5kTWYO4lb^k9X$}yhn;;N@+@t?e@{xkOyXjPG!$SP3F;0YQAJ;k0W zdhX^{jXUut0owV!HqTF95lYG#PmcAtP<-rz82*Mb#Vz?wdERJZxXOV**0KLlrs`*= znF;S)`Ne?GYc4#SACh~#(vB1f{ta{G;!h0dLNl?w4C7(Xookb}-}fU%F$wJ76&%Fp_-3^v*O$2Q_^By;_-ayLXihlk=l8YuLh2 z@DhI_>t7g#mepQVrYhyCQ2#7H%bL|hFZk6JVzavgys!%x(F?C94$2bRbH-?emo6g> z!lo`LCx6`TDiMVr3tw#i!xA5^q%}7s>|@fB zy%2vmB3dY^`+#;%OI(S|ly!2=%eymrPt}q0};&r~0%RuFQyG&Gc1+AYt>lZEhmO%B=pr4x>%_XaLuN;$y zwb_SPq=mjyNy;f~vTB#8Fz!1PT;l6z{`SRlZ=||+^{)o)oWTTlCxe@(Pwhooq=uB$ zgF*i{?y@XBROk#JP-y9vdYkHIe#!Too#-D)`-NWvSel>j;b!c)$&ZFl%BYTZJ}x8X z1W-4DepD^QOJ?O`<6xfpk&S-K%#Q2s{^qe{R$vg_=_!H`q|Ytbyz9V~*Ogh^_TS^So_OYsVM;A~=7rBjcyt@rYtz=LB^4kRFa4c9e}Zv4<@PSl z(NVAc`JKufeN)Bg84eGE`8Ew4LR=ds+Z>=n9SrB(9i-GaK9Z<>*@4<32LAS6kVTdu-Ea$0Eq;iE+1Ja50Uxyo`L_q`ZC&4W9s-`@*RLWqa=70h;%@`l)-hkvB?YO_AOM9R~QwR)p- z#ug{&E95csH$6d4!2WGD^PkJID%fYJiczs5H6|-p5k~u5I{#A2GglSi4Z?zr|5r!r zqeCyjU&&570V5yv>V@LWkp?odK^=Zz-m7(|n!2lF6Hc1%cs(PJ@cHtL^CcJve!(zV z&v)gutdATK04bnVGd8h14f0ED*Q^Bs`Nhv;qr&kSscDi0RDd zounbnv6S`i^1PK)W^(z*qzC$1#A_wzP>PEY&0}tvwpI))c-JalZ&NC;!Ic53%%p-; z6FKY-^@yd9$-D^g>93IyM`Is!X;pF2y^JvG*rJ3U+~JwZ>HKq%*~&Lo0#)Os;yP*2 z(no$469QyeC1#m?{XeJMcJ7{C(|BHOvhM;m9OkQG07 zW1mK~P@ttYC*il;EoCHvGL0K;llFmLT%_<%o?*h8Rnx#%pS>Fw$X@7YLvCq{nPKV8 z@JGYHO;~hR%LA|JJo;E_;tZ}$SX$o!%aP^wW9)-w`xY|;6yk#dl%;)%$2wc4&eipY z>ugC#yQ)ls(%KKvYcei_L$;x_F72*>tFl_IRHhEjBN@*Fi)HEX3vUIj4kc-g8Hkgp z92YV`c$n^m6oLv|pNw%J7tf~ovvln7<^e+kFN5zYJ5I!)l>8Gf_C`0|-1DQ$tY2U? zmh`>d`p3*dstiRtXLBO4cj>TQRl3LS6kCX6&ehf;A(|jxTGDK#_&gVrr+(_ZGiD)c ztKyef+5{BPeseK5s}DPiS|L8CD*bNKqY=80LWccN1r1gZ{+cmR5Yg71?$f-990a_x z-(P>N zpOx(hVYGI=At%O&R@K(`Fd}q~z**jMVj{#t1#-hGxokx7XS1GpO5Ke{1sLxFWVm&4 zGWB1!m-q|6=1=C_udJij%E7G5xBXAAfT06FXtRH|VJXxCswXAgxSet?48K$H&#qaP zznsHAG~fEeYE5M@Dko$hd+Ns?Q2Q0s{ewy#zeEi9@iIVpH-D7g91yxz?~9iDYTXHu zx}8sbmVE@{xkN};ST^O8$sd2dB%zZqfVlO;UbN-TO>K%cE=yu8XC*SsgB1XDUxfX@h}BP{}#)32%p-|KilH`dZn5)_6<2!LFj2kZ8V^BBbNE z9nCL`1RJ}@;Uf8RC8zF6Wggk4yy{Jz)Ix?cLf?Jnd+3d8?l$#)+p}8e9I^fOgLm7~ zle@EcfIQ5WxUKR++XY-~*5IDi=!x1-^%|a$ngG`-?Js}S=R}$C0ar2qzO>;o1{)LE z<-14&ui=*uU{(zAEeG3I+A4nZsZ5Px_?vQ{28=&?winJtF`w0}BFcExEa|fuw)nTX z{8-@B@~j*^j#pP?{9bK~;p}d*;^wYTkgBdoB$Ez=Wm`X;(HA(8&aS>7pS&^?Cq_mx zGsF=1)5}Y5ZJQfi({EQPlo;inH1T8*V$MBxVXAriBy3g^46nZD4gMU4vi&3ZCAS>a zGJ;C{ZF34AEs{TdmJ&KRTqk61Q94pTO^K>Vhvga%UFf7NSSdp6Ma{6C$NvO-O!yZ( zI@F{1q_15h1-76$79D$`Gx1#I6>rAOw|g4{4+s#Kb^h<3Ns8^llaf?jR==VG)m(o> z1!o8-_EnB%I-Z^zueL1-I+~ONzL;)Jv~4n<3G1i$`9#%vvZX?c#mWX-4K(Ugevw^P393!k)Ax*6tL&K9 zJAL*0K(K+h*GO=tpR~{=i3XvQa2Sa$#ItO!FZuM}BL0n22QHj$4Zk>HIIPV(7{4;v zp9-DIE?O#T^`&`k&+>w9!KBb69vF*v~1q>o?xW8$h@>_UX$8<9($IeltXV4XhF%mAJj?^!?w@ zPb!OymHOAS1R&TxJX9%QLZGAqPGK6E6XeHV@cHUhU20SmPqWV*gU4M{t6#iGdFw)> zQewL)@22LU$TVn;oU4IN@O)==@5V17ulEr-V)ZS4WtZ%qt4%Zn|L3QaFQCQLCiwwx z75A4PKl$NKvHD(Pz@A*rFZ*Lmmi|iootR4rG8Av0_OjhLImqIxIdo_k`mce(jStyQ zYL_Cd+XSE{`W_pPX1V3soNlQnV3h_P6p-WZ#B=32zP19^l1aEI=H;b zzij8CQA}^GTm5cZKRvowa)tjU;`ZUojvZ%HEKxpo6ivnA!!$?thEN7WmZ zKb6sL!r_utRe;Yk&dGIg^HCs79a7%!B$GCR7 z-k%?NWFe93c+ANtz8$wsNvTh7SU*C|4MP;25DTc!mLwb1m}68!Z9u~Wg+xiB8e3r2N#K|G3;~eP{TJrhjHvWS^L@r4M#E(uYXrvkN8I+iLD; zfh83T$d%J#fsI#QH?0{8BzA43!%!sh=7UOe?Yfr3U`U07qDG>@6_W4x-%I7NA;?VA z%-U6v$VbwCSIOkHM*uwl05L5YR;OP3*M@f{;Q3CPZ6p{{j=ox(YLJuE;ncmpK%8Ys+kQW}%~hDCOw;P&^=6Ak zTH8a}z`Adhf^T1WO-owkf+8_NfNF&Jo<@s~U-ktmQP<0yURZ;0!(*Lf`;mp`s3+C0 zL^-MZ<;p5fuifCSku#WPGkw58V;m`7SU#4JKod-~a}B$$ki4@~{&1M+xJ1hFS&Yo` zO;7z54voq)LMMg*2r{QLo7=QJ`uH`eh>c{gd*QR(dr zG%}Ub{dXXe{BI(qEwF8UCRpXF)X70k;E-lw!Jp-a(&q04DXC02fV}I1ew*V&5pApA z2gcylIYrG=iFLBtx>(dR+*L|qC`n@T`O|t{b4A-aEV!D9J}&vQe96&^6oNpqS`t!S z<>jzVCrPYB0R*Pp->qK+K?lRM-XO=WNYIYYCy5oZf6z|2StTyoa@_Wmjz5BkGJ*Ho zYqx3k-E`XVIhhEVWocLne{xgY+VlzPa&5})T{RFead*<8PvCt{IhYDw1bt*;DAhRl zG*LMhwWW0&cA|k({5JGbgVnd<-zhrmMN%DP2oEleLb_B7G{U+nwQKmHbdLWnwT~!S z=fO!Lf^?T<()BUZ(MoFM;MCTa73x<$mow}>n!TG2lcaezNw>(s5GYc=&&%E^~=&X(r3C&_ymb4TkCnAkpZRb4|Jix)%Cn(BmUxj zwS8_+V6D>K4##HzV);oN%67D(8J}<@6=JQGDyd^D{?Re#zMRXf{cw3C84o1qO>Op= zylobImS)JLnk*vG3bnfQ$fYRVm;o2a9{A}eK06aRu7z@tg)qK&?(lwYr*FtuiM#vQ ziy=?qG$n*WlHH)T-Hw5_BnePJ-HFVzPM1bR42q>bjK64i+==*uA@jWO;%o*}(!prx zn5(e^N-Z_7sDa0+9dDkQ8_~VJ6~j3Drz%*}K&so8Ns}*l)pU@XiJ9~)s^G?ph9F%_ z{)qMWu%{Q&@kmd78P6c$)uvQ}=#}jKPfCvXdrLs5L7qWV8~t9z?D4D|95;T&pw2TT z$^K8lB@0){D>_D>*kAWjC%S0B!jqma(JY$1h`#G=;TUXQHLnX`!T~}yvH!X)P^(b% zSA#reeNz8F|pXL&B7(`hsg>)Wot+CJ3D{sad@lq0l zjfv1JTS~adak?mIhzOV5igaBA7!YKJL)oN;T zaP4!302&X`cvx37OgMo$0HM|$eVjR#rPK9tQ+z@%|I!;U-dh>2%nOuiXyY>pBZ`@> z8jRO1kqU1+<966Se#}9Tb5%T5IojsNba6I_NL5R&*ZUqtrSmfD7;k+(E+xASZouRj zWYR|_(kSDYHgDC`JXkBq>!~{aS)N)Q#CH4aRbU^VnKKfQGovMiz2Rg{QzWC7{b~a1|GGf0X=Yd8c?H z=3`FW*P1nciW~2fe?I-8psQ^FIqJhYdOAw{ax7>|caZn2cVP}P&239&gQCh%mu-aK zIf;EC)!MOPQR>edE{f4MJJ~%g-6!QN-*0OfwfuHk6&wgDNBy}!xHD0xNC<74m{HxG z>}=UvHmrYN@O)^2D*e}9pLx@h;)r;bqvg;gm37Z%|RYPfrCd$p6L^$I4RmZDd7rPl3*50#rvZ#hv#beQ+Y=itV-XxYNr; zpUK1crDvZ&h7k!@!^%x?cynpID_DXsW9bqA<-a>|<>n|b{2-|VIhMYm3h05?RVHis zgB<(+WJe=dK~ z+&FOVR~ji`;>n*1womMKF_wS;zN^o_Pxpk*?Z=>;g(CJRcfeUAQ-3x3n+;~x{b+#~fy~FT^f^4sqPy18!Fs7J z&ob_b5^Hc{z)@7}ewVm*qJ&QsC`i_eyQgU{)XAu6}@NwGzJkdBLH{4C)Az46o!i#_zRB>&? zl-Dz-YGu=v|TWUWi` zQ#eXOhUcSCT%&AlYOG=b_J z#R=ap!a&ZB`KLOS=`7h%PlNkm1Qy-92-$4_6kohF{9aGp$LmOa$om6WQWW&;*2)5H z6gV(*`EqUxon(vl3etir8I5TCt{<5q8q}?jH*4%ukdG$K7cm|lIia- z%(}FWs&zePqrz+b#a9d3oET+DLx-R>~Zwh za2L@S-GA)@*_d($fC(|8fhPN&!Q^5shfJji&|H4DrA;RH46pvu@K0q;w04J?cez%O zDW{CVbErn;biiS!=-J`^YV`EhO)i6W7-7p$fFTWm>RU_GweYLb(Q5o&i?svNb z@0NMqu5%7J)P&&41;P4js~*LJ3`_xif! zvLT5NFGIlwm`ROI?j$mlLyz;{hV0e`r`bfWeEsEFXP+O_JLTCdtfLBXYyY0hb*q3u zRRcPG1OhoZGj(Z@q(trbhsET>nc*s9VGU}yBvw3)DPI4fP7|U;8*5BWMHJvxI40S> zL6h=ou9uw^9?dqq+r6nUa51NiU%)>nP&i{M-}^Q7?C;Wm6*P(40wts|?3P5`@&Mbb z0}$pd)|+LBrTxsKQ5tD&qr*|}4?>AU&zgqw$ChJx;#wEG>H3IP5zgKbn7eN}mts1` zi#2i<`cv7M5ND}CN3U6>91mD>*1BhH0lx)*k8H}5M`U`??pMcvlg7&@*qGvHU`d|B zap&oWs`6%ToY(L=`6Y{}JA`z3 zZ?>;@$bH|->gdSOvduFrg*`A_rXBcF*-v(+iK*+(##?jmr|h_aLCvUCGa&fBLcA## z_nNHvA=+HNO=_C2z48g@$kPVi6E^bi_@5BZYSOh;kkbSUq_e1UzvH~6ZvTllhSjR^ z+BOwLEEXf8Rxc2jyN97;=fLF%xFVONr?2!fEj@SeLG669+vGWcIgX8l-3L(A$Bj?w zK1^64#I5TQ#Y_&9gX7?Ot1OO`JNe_ik0N7bf2;k77dWtmtllMaK59+;Z~8!SWIIxX zx@KS07R{vt9~7+fU@rW6g-nM5>H&Q6wpwQIBCV4h+R}2!kX8pmvfv1U7DCf$x?;K_ z<)JBe!C;Hw8pQ?W826TrEroP*EBQSf?-z_LrqlV$h*ZcE*nDkJ`a`JX$LXRxeB3pCd^KtJ0fQ$K9bWZbC^|gnOzy+yTpCJAJfG|z>F3is zGH!|(OGP=A9$23KtV$PKcVNqqs3*{&|2%wla<&GMG;7`jqTYMC!_$+~RQ>1|fILsV zcBUZ#Q~Q&bO2zt46>hF#9I({Y4a%b{sq)x)is-H_?Re9)UB~k+}ztJ9>p9_&bnL zoO-06XI2RWtfF^bZ>;dX?jfr(H-VK*)%{50*VO80i#r-&6oqD+&7 z8_<5__{%E~&^I4T2WBt#ukWT!*_Ub%RV`;P-db6`(p;;KeCDTaKOe$BkR3mNg&3P} z?na-wzzIFwGJDyOzdx!+qzc@$QVd4bO3DqXI`C7Dx3a#`&@u7^W|tts`+yHB_`OJv zKRknr&-?Bcg7Pdi=+~!yRcexE=%Y*WUFMXK#Rv)2m~UQ>&Aq?UrDzI^tlyh@%N5l{ zuKFNgXfpKds%zAmKP=bh=3n==)r|5QO8^xC-D7AG7j>!)VWJJ)}EaT*~9Fh2}2)eO%w zLlZ)mx*(F{&xlY#iDCU>fkyR3;?v8jU4C-)BUGZ}u6;tc5iwXwRE~=z-o4AzmHugY z-$Im>4%Hi(4?7|)x|WLGOuPL=|;3Kh9e&CZ`;2-@;L$?^F5SfcmML*?Aw ziYHcc8@nhbR!YsLL1$Nb3F)Q!Qiod+Ws65Wnp5&UNoCITgIR&Us<=9e2X?%De(W!N zzun~9Hd)~;Q`zGP3>1iijP$J~Sd7yA3NpeVoSso0N!b=g`wvAJ3Q+v0LTn?`xC^YV zM+YoMN#|=Oin-gi6%|oLW9tQPMLy3wOSZMqG_Md+nFy%yfStKhxXq#qn7}%>e4Ud2 zR^D0T;-BETmDD)cqzdW@IQ-!)n`>E2zxWOw|MS{=SFI3MgG`zCD=ma0!mPSa<{t1R z=Finz2$NAeLk%Bdn;fa-LyV!GS_nj|Af-Ta4H`bdqf%`=6(HTvSZZ0}Y(;8bDqCt~ zas1qr^8@WHncMzdu2u2m8U7%34Ov55o*uHHP#5QaD&Fh>Y>eFP(%HPu*JI-i{7>^AJ+z8b6xSl!C>Ot^v_;z@z4OUlY1b3r1`fXcoiU zVz0ViRDOPt*p2k~;mmA3QI#1JPP8x{xMP3H?9(#2i_`OLb%VsEwFQogFKuhBy1r&l z-4h+7>9Oo6#tBJ=H@F&lEC#D}<_)i23@8t4U8xoPRN1yqNX@Ncs0?>UVcQb;V7Fqa z?_B-w!^YuxC6%`|TH>PA|Jf}fO48l#f&IXD8tekt~kS!Qr`PE;?H5t^t_%U zgB;m7BgQsPvroOokxBNWWOzX<8CMCt($)2i#wQ<>4T}cS+C6?uY?CBCVfYfo100eQ zw<+ z4=a++zAdRIvR7qo67*?aI0PsEc#C`ReuKGAndoAUO)yWnu4 z#8rP@5}x9-0h`D2Mu>Td4%)vR^sVao10Y+YuNYuY6*-?SL!prnM$v2J7s|HO$>L=p zA_n=;FaKLVhwPoX`utj^y{f@4#PATe#?L7Nnbu1=82Zs7udE|aQ|cai7NNewPX|7# zxmxba--I;sYs;5z%veO;C;^Zhk9YthFT)e z=_hlkd{p0?e}|uz0^@$X+7H8UBK5QOqRnUW&_P3`@P?H#<9NhXJ6K+V2^@(8y;>(o z8J+hkmdSKW|2vuE2=2V%Yg!OB$HvESG3;ReZZ(nwvDxMmBzVpPuYyzI{gChYb+4#f zqDKgH>|nK?Uil5GwsY1mbBeJ1?BfdH+6HsU@P6iWJuRe%|R6BWP^aTPf{eXg(+^% zW=I;v6M7(|6PEMx#4j4@{ljpQ$RQX>%xzyq%>y7Eh#t0u2L?!ZRyW%jD^h^n=7CoL zA%@I$SLHkNDq*?~zXTX@hgfHi5VZts5cU9@xK8OmW!mb2pS);rwb_?x{X7_K0`{(U zW%WdOqOoK6jlU&||IAvC9lu*|{%~r_9-t$HnzJ6#sV355yrW!cF(Gh>$1(?7mHk@W zmR+uOaZ~hkC$C%14R}x`PlIc<`EDnrYLIR0HjVbz_bk3n8++@nrJ+MD~E`T%&nO~u9g*ehu_q&=f5*(^EX7d6xhbK z#x0SbGj72s%&!FFB%L$NmhIqYV5Rxt_Ne>uqJjr)4k})4$TjH`+4UeF_ih_$A`(eF z-`Gb(nqy%PR1sNzrE+QkwxS8PfyV@zLbn#6vi@Spq<0?`aHPg5Hpf2h^MaJncg7yz z6O|zmI*2Skjqjb7iXy}gpU|z0i7$mZFFR#)%)F9M=#Eqw2k+M*VQttgc^@rYIu;9N zBaHxtHi53#xowgUIrmU}5sc$6Y2qA-&^MXkn=E^b+MHF z&%QUT(WQh_!AbmD1SjCE#UPoqcac83M*yd%XyCX5 zCShz>-d_+K0_jQ1}JPeurn!`LzbtoS_vN3plVGr`0L%cgj6sM*o4Hjj~ES z!qH>9<0h;s<_qp-^2qGa15m?0H*Bo|TZ6<1EK_G_s?#M^X3X9%Av zmNz-ZGppWo*ogrvm_{b|+h$R7$3l^os>zEW0o*cqFtI9a>aF^+6{VILuHoRZL(V5q zk6K?H3F>O==|l{2+XCV8kHenEG}q6nck((uBl!5Qy$7x>_j4TmOubnV_p$(UoP^qR-$A?n_<0SlsZ+`fTT{YT2&${gy~YqoI$>^ zo_#`Rg|V~!NQVrnfAPRiDh7eX2@LqTFxm-UXx!dkwpB(ZHX^*2WuiBY-HO}>CBn13 zLJnO874YV{QLZVT;ev86WA_qdzDbgZ*e7eMSif~mfz%f;^qAwXrOm1|tZQiJ3y7=J zg6Hq$Ewk$rQLXmUf$vwGlH%={tgi~xPveq7bwaHQz0!Qh<%y9K&a)4CR3{6H1m5J5 zhXj8s$Ftmc(MUI7Q6my)fL8Hw*G{tQQ(WD?_`>6P?U6cAu7LZF9)KDpIoSAH>?M6# zPr@cS!`ko#k9=$}pcSLg^H)NV|j4&lcM3AeVE}nVM*6$_8DVE07X`h9b+GQX)d{p1Dw` zXAoRu;o$^h|Em#7eWsS5TVzXEO3U~(Bs1*Lo!02TCu^rG@tqdPo;MU>lIQ+GV?Rn z+^vs^6%@h6H%FGG1?AnaFn28ATv)dX+RyZB;(pw33qj*mB{8Jd$ksB>{V+m`=T8r))~xDl1yx@a>C>+#8HvTC0^z_*3hr*sWgTkI*Ean zqo9p}7DD+sUnY`oZ-0TCmAk-zNcC%_%ar~dROm`7E7YayUR!rV6qBNC&6HAht(LDN zi6-EUYTuv`84s{>5bZEUzl+Qt<8^d$!=6N}NC*(R~2s!QI0WW)@oNb2}*^gQV9 z(7y?mI8Yi3m9%d!&;tY(%L}45<9em~>&Yi8p7+;B|2SSMWoMH;vS;>|jO;B$IoSyrcN~$ul8}+@>@(u5I68$S znb(;eS=lRl9KZMX_dk*QjMw}5dOjb|*R^DghQdlKZC_keiD&r-&433W-6Im`tMN2W zQ0dB**H?5k?^~Q5r(Ud*(K-AJ?1!pmQ0(+GmgxS=B~Dnl-6a9=BLKt!mEqT?g*Nc( zH4!Hu7c5vxY!d8i9V|WGY^kZOKN~>tY(&a4pxSDmWyuPBkLfTeKxP}2!+6PKbtEG_ zGo^l?WQ~U%KhnCZiI~bMf1GQTY5Q0#WhV4U*#s9rp@q9;2VvS|GzYJ@E-c=aPOB8= z|Lp*C$7mN^&$aZb3Dx#MB?C*wSz|+S#F`M~ z4{a|su*LLjq?{aIEf@Rob#hZ@UIdt-z&iO4+o80rN(d~r%;Q*#v=hJW~4Jt!c7rg1ulZ|%PGR7NF+!})9MsWyda%zhh#h1T(oZ<;#G80>k3p~0+$7XYD}csPZCMOo6ku7FH|T&UjLu1)aKn6loytSiTDLTv7W z6l?Qnj8=B(^?d#9mG`}2=T!br!a#M}38K?A;F5WuQP9$3!pJgaCtSxnkS`BbZd7Ic z`crZXsJN)J`MI(WxRl8NFl>R<7^eUm2I5)2pySo#6|KfFjD3A}@@^TxDQmZYDtc4A z`bdCnmsERKK5wd&7L87cyY0%QlTBtR>UvzU$>9FySQqQ-pTWHI{P3{?Ex&HW@)lD* zhF2H~F}+>L7#7(DHOyF&Rd`|J1>4*~<!beu@ZtWFL(TKMJf;i200mDd=L^{OG^_Y9|1;~(Sg$7gP;mi#ir zT9g@&AG~>Ev^-G@Q!H_>U2pp`P|m?LJG(XjWt{ap@NJ6OZq+WvJ2$arGAvL-{xm7# zpG9Q(4ErZ3$HJ>3BQ%&2h!HhEeYUIYWuA(+BM`a_|O z+p?ooD1B$5S=xej(F36R7?ujUY`MTR9 z9N%w{54yWR?Te{!YcSY!gQhC53#B{mDORqFoOk}fJ8J3)J*$rHdA+?k>1_qpnE(Gp z@s>%v)CWD_|Nn4-X-J7K%9~|Y$;bDEpEGF)x5-D@ivmEu z!)YLo;A^uF;JSmVEN?6^0%}6MsLUO(I5lN5Lt3~6#0*KgXjxWRtXF4B0p1%Z3NWhC zO8sVLbL-m6L1LmKGNRQ6%jbqxWFMZKX|-5O0kaP=dVpqD7w zohc)!c6}x0KI@I4sdoSY`w1;tifAcwyVE9?pgJv9wCG^#8%KHVK590X_kVyr&pnJDCsWP$QKUXor=M};V?cyj&5 z@itGHbD9eY8lNDdBY+7v{;$jS^kMcl5Y+~$%w=E~`A-7uPG&vcPaXtKlc_=@(y8)J z4Ox99jKhhU)^sG@!+VrqIZ%TaZ05-pc**Yl-EUPIA@nN;@fK^irxu^31B{3$lh&ehXAg+*t9@LZlxf6|bP-Yr- z#6gl4*Rxp9xs(|B$)Zx1+f7C1ssWZ;UkZ4}{`^`4B&_3^Ifd1oIpa(A0h;5SW%gkT zePSBp7K>~)-)SM%K`?x?O%BtkGHX-9m+BwJcUpIc67zSnS(%+Oge^gjdg3Z=Kb6}2U7{dzm5;~E=-$Q~ z85I?z_&Mg6G;>?B6>VZoQkD;-$N}pX0`x!tUYX5Y&TE-9sg?PTdIOFqnpMn8(9ES{ zYD+m_SLT^@hZ&a$qL@{K1)rRD0zv>Op+Y=XVK%sowcPz{C^|$o89*t_p997z?WbVH zE-B95qeFy|M?gV~cEueKAlN%sks{akc+g+@OUFNw;AMW^;dI<)FK$Y=0@R4;aBCjso#nFn;o&P#7YxWcB<#Y_i0+4Bcm~YA6@-2hNOzWy3nfYmOc%{alGmyp2Z^=3vNL?x~Fx7LO>&^mX zO@2!ndiTuY!RIypiOC4gf<1NF!0vQlW*g5Tlh~rm`f2ki4a-SSDxz z>k6OQp~KR^PgbkMcT`TqK*XEm8i%Fj2W7jFm3_$Z?{ZpXxfAre}Za2bjZzw1S0T=^T<>EfJ|{Asamoy z;Mt;V`tx%!VIl`imHz_Is9go_OehbTSSFq9rwkuW7_yV3f$YpIo>YE|(DH8iMnPxK z^mau6@dms15>15%(6Q%E3*mVY@_VwnLM`0S}_(U|ZG zLTedBFT>I0cIiW3ysvENmHu#1m_LA7m{>rJp0+zn2GKb`&-m}e{KP0aIc1sr?cfc^e7!f8`#V)^Q{kadgoYcRBB*u58B<`uHUXK=Ib|%l4B1*1EYQGeS43DTO$?@fXna%dy zFI9j~m!{f`#8A!#h*ebq|3tb(9ywjLd48`z`Jr@JU;@B(+6=DRw~M{GC#?JKj6FRg zWGL)fa)z)B&^U78kxPs5fD+$o=GtP9;M``baWIpavM-|=2a|oJaAsBDma4sInFvSi zy12BA)|x$KpT+Ag zPbvY^`lr(!`=Ymkw1Ha{%96iIpuS z&qBb_`XwuUn&Qdj$-rK%fN#n>{oi-AOl=Idmh`1rfLdHQ=7!y3ljKkvR-v)&@XC7U z>J(%|qXYUYkq5-0iD#Xr)lRU?0?vF)1b<@tZ%79a#j4>>u|1Zv&~ zB8B5BY^#~6%rN`g{I(%?cHY&kP~qLtt=9#Y$J_P&Zv+3}uPID6Xn27WRFzUEjOu5; z7hrnPfabL%S>TtgvePz~VfRw|KD2^k7?u+9^_;No73R4+vt9JyRi18&?Wd8uTuC*lS+#YakQFfsKoMQOM4SE`V zpUVLQIvkE{2KYhlX3P(;gwARNaIYH}w?U7FmP(<{_6qqBzK`!^3*XxZhmUuIax&~a z7tAK#Wd0aZn+1ClOWoMXL&Uyzli!A^MKt!5@GY zG&ONI)} z7Zl3`OYZI7ufA^5XplpNv=mLNfpS3eBIoMD!n#=!P3eB$wE?ko55v=tjQvJSOW_!U zB5Rrrn&po(eiPmj{gg>oPvI>Y164<1oblWMtb9+oN_L_qdf%>A9x%Brg@F17fNZQj zNB_}U-J!%QZCor|m+HmXF83n9H5-xFc6$AW_Z*h>Q_ z+<(9@5V9x~5IQ@EC{7%A`fw!}C~%QH@y+ZV0uHw2;@=w#eoExXKy8{2z|dsW!9_Tn zpD*?hS|mkp5|xhuqb&U}%HlONMz?8%`;EpA`l94ZZ6n6Ic@mpc<#CF`25QWi_~j9} zut(KCtK*!Goif?#c@6UOv6=u15t z(s%diK-{yd&upRbt1Aq?ao3WyTZT#|95xwgHxjH3OY+NZ_fp5M#!1B2=eF$tHc52u zCj1Hc9Hb!^;XY5qk^9*}G9}zL-&yOZ6p2p>ZyVbEhxK6*iz$@q|HcV>+=oxlhLg_Z*<)GL8bc?jcf)DJdjGma(%K!9I z9aZTNKrE$NofwwdBI7(Jg*Vi;yt=B6Fuky&;~92>+T?BMO@4s{J0JB_pBS!hAi1gE z@pZbP^)w2Q9X)zNG%C3}r$LHI+AwJM@AKxIyI-(TYrB#SIwR`?d{jVe^&AK9W2fLS zE!JM^C9u6SebM-Rw3>-hB}LQsEh=$nt4MzN|4qWXqS=Uhtr&!qa+lDf{8f@OJ*LH+=^;#W2SiUC=Ioxm9Gi(ZwEOje&x5@c19=;?jP_*Fj9Z#{ ziAC!BVLuzg0uX*`=ohcsxED)c7!XQvX09rKjNo+&B9K9{N7-{Fz^b#7BTs){d1#fR zKnjE5HlnRY{d)Jn_zj6s4G8f&rn3?qsb`dv8$Sj8x@F+!AuWQAFSgytjr;bXn(R9m@qE5j&P61eUsq*eDPQar?df_ zwTK8A^071>WD@0p_AWTR?D8e^CcMs~x9pYHnzKg!$}-&Q8~v~TbtQxM4oXC;UOy^U zRDAX_+^pt)F|KrE?GIzqL$n17&oK+%`kc?7y)?P@yi+kDa)^QGVTxF>)T}+0h5mtHcJFePODaXzbrK~Tvyd7Fl zZc2CE^m}&!Ka)_%lhXfuUtxQ4Pd)JLSxwJ6Hi9RNhVH$|8cuw^h;+32(S$oEX|QYF zQoYdJUNlhKkkgoN?zjEZRwxj&%qAhy|8SHpwd8%dAhdP#o(P#Y=D8({p&|jBid^M= z>Gp0}L#|mrCgj#qvUD3pTkZxYbmB$g=h=Kv;-bRO=&jk(GD}iuBnN_oDoKb10@zjm zXY7+wPT8~rP4D?YI&~si(G#zqOzCo^>2K5>54hTTojt}Yb=l;(w9R0C1<>i;Mbhf! z=T|mL+pmkV7-DzZ*%rY*85AORd-@w^cWX3B8;YPK5CTK7eeyJUn&n|{oHHjyTtT{r zDY|T+vL%jtWO%jh8>rk6=nTb_;n`5OMj+30W7onlpfJu=aR=-%=H(H%tp)aGUekxA zLSmD}4UZ5T|Llm2;kvPT-QAlB4>C&pZ;(wm0hJWMZL9}$7Ma1?ssDs& zh@LP7L4OmZbH=2sh@!h!mmVV|3TM{lw^~Zv|AkEc_I^YYY3RHTo~%#+*E(Kw@`v|M z(CZYMebzyTMIpY+K36C(fv$nU4@Go54uC3&6v&DvPS4JD)4xD{Z=ZkFUU$^&i&u#^FC=y8en6^yUSZ&uqR{$-WFAb#;a^_&ua5sT zYq%ae_KPLXLWOfa_jSp16iX4!F4RpAuW~?an*}~(_?_yYZp0VI*>;G&66>dd!RrBR zOZZ-;l{9D&K&1Wh|NZsN$Od^FDTi;(h|9UZP8BxtYyaj}3v1qIr;sp1n9o=6Y4lW* z_}m==1)=J>>o?Lpk~Z}mU<%CHWhu+8>hg)aQ3#=xp1;HHjTQ0~C=o8o2LMz62-Xl) zcwp@}Cg_JwC1v5`T%-U#Wczh3Gk|XkH7T0@p=O}kCb;x?`uB2N9DqlE?C*=?izjE{)Jn>nYwm19|}ToZJzg=gkdAMUcRef8)SI1;13(rY@9h4)N4~J zwQ{P>{J0{hPjjdgue~)+=HCTBELZy-a=R(Y{3%M7ryS;`O3nK;RL%j7~o35k&r@rJY$ z9%d{f9^@(yZ;(qERQYHQRgAF!NPy;ZpC1rmOo1}vgu@*jjTN=eoO(219XT+Nd>Q3p z4I(P&X|viEHz?fNWi=?yW%4fI^_xBSnfM6qgP+@KdxuA11IA%T-U^|+8NBhlI18lD zL`~(`^iX`oEK-oZ{M+K3cJn5hVtoma)UtRfSE+^o8N73{ALdVtqEOoy1H{cAZ|xEc zAJ3Oe2khd>?M9``ti1bXKgI2NAjxOj32)&Ik$?%DZ@gN70UK2b&>$>l!SW*HsRub` z*K%H76DtjN@Yldl0R)=u{Ts3P>`oYPx(u1rg6FX(gVYqEm^-Nm@f?(UU#l535z+}a zuAINkAjoKG30CQwLmcua_!hg*7YTjXn*9g(JkQ42(4?|;5k6z0+colF9Pt3>cHZVn zX5zH7oUp%S7SEZ=dZ04P0A7)Kzr=mvOl-gys|mQ&({X19o@vq3@~h z0~-*d8#Fhs;`9CU8l;ORx4`KijNx2|&)bx}(==s&XAD3NHLEx`I6@f1Fg!erSe>g( zo&l#(;lNLVG6~*PH=U?;k)Be4s=Y#7ZgTi|*8+5`gUqY1l}%AMi`}p1TYICVQyMh9 ztzQo)ALiTz_F1&C+VBQDB%ALgD~QX~^*aNmrJhk&kuipV2X2so`om2V7iVd0f`A9^UHZGu)O{ED*1Rx@I~Z3ctXs~u7WNd^)Y*? zhO1CDd$e{{EO>_2{x#bKggUX=RA&X3Vngphy&6G=SiFl?HZMZN5B9TQOJaitSImVh zYrvopzgfWgd(!)nR_~`6d+*{E4Za~iYaP-{H{m#O!(V=BdP>j7V_+IBUk4c1PQ@^L2#@y2Zoeh^~ zE(+kH--GNA-FlNC&WwZMbT8{-TM8*u3WBikIqVK}*NqiV=`e)W~4QeALM z0?+>xK3szMwb4k+A^z)=cYM(`WtwzaTGyYf#V6F#Mst1qe15I$#e&7UrySYuSQbZ1 zu6Um8&8y%+A=>+KHmyu>uUrYIj+ppyDFhY zXLf_y_pS?!vY2K7*93Snws$cUGkIRGO>~|DOe}Jvr|*^(?v{Vs-z{4S6$Sy%5~I>p zB4tCV`VrtVdBNf>$@NdAed&#zoZustKr}^D8M#2HKC#vFua^~aN~zx}WdU>iVNFF+ z$xGhM-}9b#Tt{cUn}d}JtKNMPSJZ$*KC26=Tcz~wOYl`swy+CkZ<+F6Y;+IOvy_L1 z1M&{=u0ICep0n@SxgAGC>n&<&bW%c~8B&zfcY!k6FEl4@+tZ2+M^=L5#vQ^l%Jmyd z9@l1J@fs&AQAHN=pgR<+1UXqRknk{^49#H(Zvo2%@R+Du6SdF^dh&TwPCtm>E&G>1 zTHJyE8~a-2NVNyErK4_r4rm9r==+_X=jz3{o+CSiK;g)Si4eV2d7jC!QsgtR@ixH1 zt!`deN&TWo{5w)v@)-4g0Pkwc&)Cx{#~IIq5?MapxN#JAeq@ojmu6py3Td0$s8V}| z&h4iOXyNMbcKEeMK4M`XS`aBEbWm2pbB*f8!!Y!tU(>p*#K-FjguO@cWh~tgCIBn1 z*B_iZI(&_?qK{5v^p5QD|2ns;*cXr^Pf2?OD(2tsALF;PlGx+%FKE6=5-xN<*$=oi z+fGXlaOpRn9pvu@vSz#mE|9GDd6}xAg3CS1EAKHUW;vJFMTK$hFnLePziX=u#byDy zP|+&I8s7{j!JyijN7!F=o+9YfW<`Rp z(yoM-JJ%ypV*g~|mqU7g*4^DHD;C6!s$U)g$a5nZL&jq~WC+xXj`dGASQeR8nnIEC zO~mDl-nyfU3SVVe@Cabvq`C6~0ODx^#Xe$A$v`g9r95_Esx+_C2`6 z|E}-dk4hQI7Z4NHJj}dt*qNGRy6{lW)PZkI*^liqyP6cf`2G0QDDd^bFhBYzJINzOMFSX1a`p47@=~4FWgWr*Uq^p&cQTek>D9J*BGKDxnfDLqA~p!D1%uJbURCgr_r|BsZo4l@iqeh z1(Yj4?|!*cFRKKQpG0o3gU+gLN;HL5{^%Cv@xNUP zBQ$?|dz%r+A`^x#^J1yg_D;PoX|o{?(w=uRqLJ%}$n4UPlO3|OV!wHLb&an_&^Mq; zfg4)9;3sVfG#=?`w)z|9GFFMf8c!=i$?@0qM5?qbttRr=@pDm23rQ;@Ti|kw!+So< z%GhyvY$#dn0|QSrIvZjeh6fSS4EUV`#OHVPZrR~j>P&SlE4Q)k%YlF4ND=wZfr3b0 znLVx@O5@m~`yDEF%Ap|BC>er0A;ze{-k)y2f}bReoRCrGl)m;Ba}_{o*rZ3aX!H?s zFoiY|pP!FsV^0>6KDB#hG!m!T_7|JeDFFK_FX^!K?(em?#sK;~So;Kvth(M-2C}f{ zgp9fU#^$I%a0PY3U=uZzX=(bu@yM8a>~-0OqwtBp{_u?!{crq?0@)Mb{GqQ{ESN0E zab2)IhEFS;KUEIWxxbizn`fW)0{h4BNIlkDGBZ7U-oq>!<(aM;DvjA>ZmVwauPZAN zIWV=+y2l%TkI0P&E0L*q_7t5q=|Xi9Ll5d zZOIooySt@@y3>?KI_k*@C{9Ydh=YiB*#zn77hk`-1{2xtzn^F5^Blwil+x<*r!f><8!aBx{>-Ana059gQ0peawIO>+2!+YtWWj zEX|f{RKQCu*ldxi*&zm|>@?}OL5Dah-V~GZsYsG(9QkW2bpJxHoHYCabyAJ)Pdk&W87(24?_rNm!0C5gs^hls^7$mDE4Nh&S~$LZLhAnJ+}dn|DClPTKSMB zMdRv}-Ccz;-26qq(tSy)R|zOhWI;iK5S>L%DN}_`QL>kGw~6#E(9tlsS>9soE^BG2 z3!I{Id!rkStw(LVT` z=GSK0)XU-+`kl@@Q+7;uVh0lBDFrLtU^fF}*_yH7kJ9buBE$dIkyqD_`{}ErmWSGr zov_t?ZNQBio!YOrA5dt8_xdH+1o)8f>QN%)=W}cD(JoH-Q_fz|b zAbhDZNd&0iT2T}Cq1@g(^T!Nhi8tGOc#OgvjqqmDx9<6J`-+I1 z{Du|q-oLG?Hf<*V=Y_H4#YWiHBIBJuAySF=Cb`d zwt4vyxdQiI(s2uu4yt>OSXzeNaY}av|K7PAuO;nv;n|RKFhPmoXgpWtEE^C1azd?y4N( z)Me$mYLhX-!a+-{iaub)-&T%>b`+iv!p;lgLa55+cy%3r#>C;|s`>u2k^mNdtQ$OX zz$G5HHDMFaOH)mFJP*zm3Y6Cd}oVk+oaUPM2tx7I2S&2Fv4{kP`{RBJa%G z`iMz_tLY7_f6<~v06F&W+$q~u=)g(;b`R%8U2H1`<=#ghbrXnSEk8D_VkP!9!Z4Mi(vyqsRyH+b-#nW8 zbBw(sp<&jxk*1?t`=nZ_X%hQn%nC9&n~0xSZk52*$^PyBrFpSY{|-Cx%wR+Fey=ci zT{bkjUB4vgYyAo0_~91}hvYwQDwf4C?!nbMrH$*?k;tQ- zmrS>Bh-r8Ir@qKeKTNP&_Z)MK$a6+S$}*uIi+j+#`pR*!8}f(R0cx@TwL-b?yMuVm)R(8DKw!QfAIM8DINp3qjkA>(y#_tA&xp~ z7q7i9vV6pSI=M>b=yChB#8fj(x)isyx71}k@s`JfRLh9&26uw}V)fr6B2<~2wKxZp zfssc+%}+P@xBdMD0di9rLtb{Lc(1TGu!*{m_ENblAajDRxt_&8Kc)>YB+IvemloV-;>2EdBRBNlaG>0f`Q4Wfa3d1fsSw%5~hiU zam>Q*VR0PmwBgI0AEAj`R)7%(kfdHJy^Yx*1Xup(qnn~*;`Wv-c(KnJiTVM)pu9>I z_J#_SrJjWJTC!2tLz@glbJ02|fp?cGM@v9Jl#MTLhF3c+uey*_{!CdAee$p$#u$^K_NMPsce-(6&Q47urS z0A0XFIfVLJA}1%Q%IU(h(OEH|XqoGLPP9F<$+$tqF+1$0cwBpY#*wGS_!84e%h{_z z{_yY7xc^OrSz4K->(FNeZna_h7SnXYBei#YT=31-rfT4ZX0>OO1;4$3zg9nUq=kY$DL1$13$L;ebq z0n@7-vULgFPP7*zJcFAw%j-aJsY<{I?^&U@u9K)|D_IyR3U)Wr;*O1)Nc% z@m)%u?nlIn0i~6A7LXu~^7ROLgWXhn;WCh|_v&En=9Vg^REep`L(!ev!OpP!!4taQ z9cRKd7gxMnxX6_=fE)SrfdM)mu^NbZF{fj0P}Kv!P>0FiH+6E-W#H5@u5hKArT`#* zwl@_*ZVL8)smAArvs^dE$mYM7BODdbJpL{69YrRpA7mF6$N)P9G}yYcLgekUYh;7? zn(Ofw??A!!{vu7w#l_UYq43k6FUtUJ;khD#D=7w8Jb9?Df#{DjmjGdGBe|i%$GAxyKfreLZAO0}f$F z@pG&6Wq8NEAvLL!Ll#7*b3?XdZZ2q%QBV!OA0`iJ2yr;udi35(f8w=8l00RB$9+tI zEsRBSg5+AJz)sXj8TJ_*u9f{wy@zlROy2JzuW*-C85m&Ro}bRY`g3q}N!hZs{?Vmn z!iW(sLGs|yFCoOcvmuPxi!tjiNmDxC-G7f|6Lmtobr{G9UT8Hs!h8%9QUO1Mwc#X* zEVn4&)fLFDAmY{KRUQi{mBf3y9medJxxV2m4>>s|GyOACkPCVgb!o6})&dFNyrlRO z&fC8ECW{Dn>qfQACeRh&>GJ+4^Uu8SS#z?agPp}okPovs z*6|3F7O#FdUhm}s02q<}eI4^ud2O6DU+<%zsuvN}ET8&;b27=j1r&onM43Hr$gip+o!U3Ju1X z)Vq@SKA<%?WDiXFI~3kg+=3=Kw_Il$II@|sPb(qW95f-v{r#Gd_HBeV_7645ZVA|_%Z*G`Yn_79z)&{pU#XQ3>_40&58lLRt!&qyaT_++ z4+dQv%oci3SlH{NI&EZJyOo&eE~Bt9?hk)})YHIOc$SOCpu>kAVa|@)FV``@aEvKT zkDp*3jB4tcm|99IKe7NKq@^Vohy_Ts@Z9^|9~4MG_T#0!R% zm@lh1VT1tZKNTmf9uLL9qo*Jf0QRV<%FByOE#PqpJ0l5}D7)g{@x>v;Ae+}o_vgr} zR7!q&dfVq*?tW7A0MWqkqzL=OxZVM{GdC`5Cwk}Oc;8kaQwQcvf0GbD8x`P9;%=sr z1Ln0Is>dm{esDUO?{&!A+oPSulWZjH6aP}i9Jq;TB1v>I#c#dJ>^je1aDCcfKh!sx zwa~yg-;R1hUF-5+4;}Ve=jxjZJ;>nqhQ^DbyAVbp-`@whdKs(6Ls#Tq9n$CIB>VH1 zH%_TAP(77+{6Yk+OLx*3%p<$b425-WZ6*f>eOug5bl~FgnzNHFr76u8O1enkpM6TETQW3pZgQN zFFIWmc&Y*dOxMTZIQ7rZK2?Nawxb)Aug{%d&9gtC@U z*tFHnnQ#!x0ej=rpFn0CEC`F7al2*s;cM#vmpV@{e4ta z%w5WHg#JYL5oH7_=lTjo)eN!U-uTMW8BX$$1ny@b zr};~NV_&;^Swrg6WAT-J9sd|wtA@wfM#%znh3d%EP59vcKC@PS%9u~>CS04Q7cfNe zE`8wTm5|W>vywC=4*ao3Tn%a2KZmG~_yeA90s@skOV*Rs5*E>Z5Mw@a1Ev@fbV*hN z*AuxCOpQVmx+_Bdyqu^Z`K^NVx^=Iehh0FlJaKu`lrFuei}5!BxCB9tZyjfmG<@Wd zS2Rr9ik5l!hh3KZn+`%~-hUDoE2f17a7M)JQ;ryEd|-n0N$rYc@L3Hf_HS#T+e{b) z4!1GR?}?soahu;`kA9u^Dg2r z7e|-Z(5rvE#ng%I!C5?j^;*>x>8%JJ$RR3 zp|FUu}w!0!jjK>=O5bgSoC244WZ)Agn$Pz-ap-s-@(uMLjH1HA?AOd5BsEWuwi zRg(xo|B-ROZ240_^&sB6ZY^{=w1tM`mSH(!9tXN_c>6Y5zA~kj#n2a=G`V&Q6|m^%dy%SaJXyOu-+Jg1iCu+c%U-|-clK$tEGIuQ zaNcK4q-dPs$`!K8|p{lyPH(g*tcLO~MPPZ$Ey~nW~D@@~(|CIFwh3j`!fdY{4dPV`QN)o9O zKo#m48;Rf8X~Eye$*BLWgY)Xr7I`XmAVkQT6Lt1=Glv&jLr=kShnw1Ma#{foN$ zD9ZI?SnmNEGmqY){Z%WMOQXpJDD!leaQQ4}!Kzqs3(hS4f*CUpK)M^+c5h_Wv(QMp zURgVK_hpoqwIjOqsg!Eim-(T~gefnwx1(?)Z{If%TTloisVwiQMJhwhS{UQJzyU@0 zam2dC-1p|p(tgP_yqP@taT$@3?aWD%?zIwZZ5X@d0}iw)%Opmw5ARxfy0**{c_|&w zgiH7+py5f|Y`1>18MVZU^pk7rc!m*}Yw$gOFff0beo1-&q%>f|=sLnP;3fJ{*InUy zuJDAJx*fczjgW^-Des(r8{jYxoM8}a#K{GrrIVYq#7$$yrg4bd{a*FcBH$wCBYg!{ ziE4^8=MlE!mB>3eC)akNT2}7`P(NHw)Qhla2VZKxi=wLoXeZ%@$?J1=S00u!cn-JVa(L=&RJY z4QX??m?|}1cdQqgnk~xXuWkVpad*_#Th5&dB&m(*3MKzy(6>KpGC=(WgrfIa;rPvB zX1=@`^%buJ5W8zve04z)1F@=swwTFuq&k=0d!rpNQG>)Uyr9>H;8rQjVJ($nPeUK| zK;BJldeO&(f<0)Jvf+5ws{7Sy>0(o$1kbX+Nif5vuCDIQ|1DSh7FoPEzxXczel+(Y zWm(s>#KyxKT7Q;_i3)#0zd87)4lh#m{Q!UHuThSq5sW7}gMTJeeDyf+{(0p%EVP*X zgm{`=uvrBp&e+ghlY9MRkfu&(n<$-$g_dz~oDraawC(X?cm;zF-T=ur9;T*G;<_b$kGAnSSf?&;GF8YQL6%1mkmf z*q@EbM`o;6L>U(*PVj`hBi%3 z>kHmHx@8QXSafCBf9iN9KNgVURDuVfDz3h8-C_trV1AreIQ8|~iI`6Lki6$3WjhR` zIhMOzF56^LVIhqyqANq5+M)D>AcIXKWA{>>XTQGrIE7xjci9@6HUKxWRWbkvGbD{Y zD%m@fj3q81l#?_K63wG@aW_!iOy<|08RG2=KNhN zry}BRwvShg!SVJ>mFVrqh3z?B{*67NdYmfHXN=|VvA0ZkJK!C0Y=y0?xd9NRz4N;<|M{{y=AsDjc=sk? zt*=0?)nb9CZZ)AMAX{_dt%+K?)?4)Ks0YlwS<#|2Zd+!9Awfhc3sec!=CglYDE7-W zO72-;bkgcVv5{kG4oJ!$KlOzZy+%F7)`@tQcfnsirD}4JS4H4i>hjg%3a-*vHS|5h z<5X2Kju?8A5~Hv;IL|pYC{cd#dSLL?3_%Z?p#D{y@-_L6kh^PF4`d&Ael`H<3E#sF zVMx5S$~{HJXAL2X|8TJGqK6JnHZdc&JK6AV$`nR?{Ew=aj|_~(6~IbwO2w%5$y{(S z=nU+Fa#hpI6`ZV{h4p4qsY&JLQU@x5{AV`b6UVePGO(Hiwc-NZR-chV3EUqoW6da{ ze|`!%V7mhD)fPE$c@DF^Ioati_`U~ha;9`w(L~)0I&y)#xLK2o8$l_w;|1X;k?*5) zx(pdH^7}muJoNSJeSJ6F`Qk=;mxsW2VjOWlic%x2*to{lFY3w?jV@heVo9g+!hKxF zZCeCSamNWJumM|jEYUQQS} ze(mg8-T!oUZl%eZl9g*$4{x8Vd-9rlZnNc0vY55_R*x3??My-YZBsnz`>L@Kn3`Gx zciF%wIfZA(Uqm74?Dvca?V^bYBi8T!#5`l$VcZ5Z3CjGl)lB&+w7f^nCgQTy42I>2 z2o?<%I-NxuqSWri#nf11OawPb1_B*0H-vBvz@=7>5mtkDSv!u2Nm`+d)XumJ+>f>@d#o1G9=;+Q9UD^PoWbMQsCPe(i zKbtVr@HTG1-G3oVGDdcamAd+x)UM*$!six7wQ;Pl>bdtN$1kr;yvu!WUxSRhQB?{H zd&?Tsj~O(J#3{EEgR8A>T3SY1p^!|5#x@tLI(mdUZ#JB5}R8r;3@GK_ujw~O?AG=!OdNLZ3D@H~Fq+gaK9<%*GIGyZL zwDRJv8JY%oScB--Gt37pauqjw(G>=28}^(A9wOdlVDFDuyku~L?fzETI}`W6NlRzr z-0~#u1t9+H+L5<4+-a}!m@+5uklKTjzQ?;dFh2N9fYL8|trSpk3)%vsqAVXdhE79W zY$6cMV2xOYE5U7%*w6U#HQM$v0%b9Udr#$e7lXYV6I))qpQZie^MF$e=PxJy-XCUX z!N|%O>pWYdblUt{?^}e*g6ho9e>*5a;X;uca)0ai$(4&(M0^tvfByDf#+2kRmFcdu z&a>4AawhWRdU4<-Bt7UG!X_jYIuMgvs845KN2<21#a$QOf2{1In&02bf9)g<2!&t% zU65sL-aZyf5DJ;435Xb?Kcoi>wLqn6BaW~ZL@F=u?e-#hC$QjOBDj+G^Yxoa8}@oB zL}2P>cW{`?f*q=0s2s;gUb7Fbz+RGxjjYC(` z9jEN6J3gPU9RWxPGv<`kCUsIJqzLA#g_isCcUcV*aJFHEK+>LwEi$8!^{wb{o{CND zza248;zZ9~xGq|Y<0h1L24)HTl%U%Tg5BD;8SsjKR-ioeobo|I?>g+bN})n%0G=bn zB>X>$&O09JKaS%?l)cVgr6c2nB0KYNWR;Uk_Li*dUG@<(~IDH$${7>kf4?aW$cBiwsGI8_2)U2`O#( z0q$s@I(>RFYxcQyA@r-mb1Ew#*e(6*j)-ri7cSNLZx-2gOTw*wU-9o-I*fXW?DX!I1-9CKu0*X>ewF3)z+43~~4s!Nb#=M$mvfRLNqUkVLA9BH(bV#6qqWn2b zViwQ>!nqaqF4@t%GD5xZ5lI*|g~Feu{t z=KRB-9}>h+_a{fVdE@Mc&sf1|6dhs0_MwUAC2nrEOL}%^fg8NPjf(s%R(V{zl#2-V zb>^O9p^wPBQ?8uVx69oVBwcTK9Yj8_i>1a4 z4-3`QDFtL$4ZFyh^T5?}GKYBSu^w&oemiaom&7g33mSJ6Y!MG#*Uw`{zI<+*alj`s1>PKI-_ACmr8D z^*qoi19EPK-ysG&Nl(143q4vKaj8v_q14eu_G_ySRG0US6jo>GF>9(IQ{j6@L<@HA zY~z)qru2}}h6+K-!YHRvZF*L?Avg&OVxxS=?(dPjj_RGA$(Y%V5Tx`t-~{$^{Q5Ar z9%_(xiRM;Nz)2cM`Cn_4wP#Zn@ssHw0$(q{e#__~e0q&6oko{*l+^PI-a@;FISJZ++xQU$ruCR`gOdSUrTiTQU`z9V(Q5 zFuYtLw4b>LaL{8Fi(`7xQBE`KwUV&Rg*j0J#!*^)@ABL9{4c-jqq)n*v+J+3zWRI) zeoHwk$-g`I8Tzij8Cr?8g7{^%9M%f-`u2>Z49`b^4?ui#i%!1S;V}shK@OFkX;czvzphz=kA z_g)QpkN{wZwLL#1^Q{Z{Hz}WeABaY(Qx#v5h0m?x@*Q`hm~0W&A)&gAnn5RZ7qML( zQeXaJCM{tQXYal|VeS0ZqMk>R1D8ONv{-4zkHbT11m^46p~lnWl2>|D&c40>Oww=` zHuBHOnIv|rGoOQaUEcb|7dgdyWvB|rZ6H?+eU6&8HnKLzb0VkdFIHlqbw(MExw54A z1A-qj@F8syxgURQS=?G@DkehvAJLi)^SY(8gj6(h^5*WGmnhvy=fZR9A?Du1J)V+i zIr+Z571iPM8oLba!ujIURVZs|?sEIgvj89;we9Sy9*u~@gTBg7&+IdS{+^ZR4q62_ zmKyz&C>;Dz*1y3~P7QaH+e^ZVu3CC$zyO7mNPNwd!*YRX2hRMyjr zF8cm4YbmRnvw|!2|(O-aQclPenoaRDIXK( zj*NY&oPjB!Xs#>iq4F}*#B=7a?4M>ndGx_*Ow_RH1N)_OtLVV7hqkggxB}^n*{||h zKDi4WG~vAx#5OhrrWX^lu$tOReBrrO-CUox+kI;mUd%3O`n+1fW^0DkYvP7T#J;Yv z6pPz={9Rf5tu2}#hgvQ=!D(l%k@77CDRvD7LhI&3?))g0Cpo}F)MAGVg2vt?@3^@w z$y^+DBDSQLrso?|XNp(+YJ0XxRz_H;GF961uPbB6TxqZxsd~2?548u7+);O3`N z(<^u|FrA){Dz<6VE?8S<`ot+tmuV4C{Zfxd4a`3rV^`Lm-pW(J*B!G zhyO-|InjLs@dM`&or6=#GJ^HRCfR@s;1Am|CZ}{Ur8|2D>1C*=*Q%9B^U(%ZOBO3- zdG2h{IP#}Won9`m8s_B56TAa<*PRl2byv~#S%FurMyoOs475dgu94*Va*hT}=EKG+ z?At4{i$QC6l|_Lx%!&~^MK7Nij>Y%(8N(EbF@hI=;+m_2wPM%|xjs)cj%F7?`J`?@By%<^~B`c7? z7jPy43d*Y`HHHB%hdHB?%B>#MAVSJhJ8IWq{pfh2b22|4)=i4r00}Dzcajp?el<>X zz)Z+jhFolDseZcjMmV-@i(iX*a+MY*-&xCDTgLt|^neazjPGrP6idlk2k#_-UR)#Q zlYv)rajalol9gj3eR-WeRtiY~_Pl&NC*z^DGIu1;x_u<9_pl{IV})YRj*+ribqTi{ z-Rw(9j8Dr z%gzE~u7n_C6#kLx`Etv9Z+UNyZ$*MHZd;tScHnYl0{28uGA5E2*`qTPcf~9`_KpK5 z&-N??Yalf|#vC+M9nRJ!_kdUCA;x2)Wr!>OpGwQk)!UkjP{WAl@{qS-ss8H;g4^so z*)`1}{k#8wB|2_W9GoB12kv2=&?Bo>7*94A0t;A(n!ZTsr#5go4%cMeIn4T($d8!WD?R^aW_WCJ=Xeo~?2=%)C zkH)UoJz(GVnhr@~c~2}UFOE6Fs)mc_x1A>WJr^aQbeR(0QqACsV4 z!BnJa1K@KFIpRhl!L&RP{mfQ(apvz$y%Np&69c3wGl!;Q1CV(rb@8B)WA*%$O8euZ zTMTyliM|j_yz7$Ri6|ZqN^9Gl4g~wrLoZfT`Y+>Mtl7xXpc!2vZ;>(j#>pNAJmsDy zFu#owBL50Ujj-n`2;DuIyBQzV72R@rH+%RB65r)NUi1u4rAOZ9T0ND>d1ju8Lg#^tN;3SqpQob=UIHN}TpoNF7UYhW2SCny;hE zWwjW*rld$ev2JCvbMEdi$iDt}jmEW8Xgpq{yfjKk6DxI+heM-l2*F)p^c6pbx0Z(JE z<2jkJ4JsTymM$9k$wKTQXwkF)cHSe zMgfVmr;svfPyu_Tb(r`3{iXU7-#)sji$U8q)s1~UCzI^I10^lm*~5jhVDS-hfYPsl zd?-)B3OdTs+8GKW4L$Y-rW})e-c2qq)osfZ5SFQTqYx-a_{@BY%(f`rb!1Kd zv*c^>OxphOY=PMZS|<)AL*7h1&Aw_#hqE?{QO7?AVZ=OOY}yx>)k>5|&$3Rpt`U>7 zzr6U^Vrym~w>R#oa&KzlZj=ppy|qrn-6pzg8`=W2fupB(4dI)sx8uRpr3S;Y8yufc z)K1S>COn)4<9p}l^P@Dfhdmo?QSIP0?;85_AfHtb&G++8fz7r8znEuE=w2X3###zo zhu|RyCq%GHiJ^a!xnMePfW6GG7oW)PyF3=mI5v7=U=&$=({bH{i;vJydp=*kZ&I>H zrQi9j8pf~lh=KE=6sWdHCC;87bE7iu-2X~{z9DHP!_t>an9V8JSycEF1j#Ot%)@&A z$PETOY7RL5UunjpXE`tkvWUp*dA5ElOV46Ax(qX2wYWR}*y~??S>PDv;uM@Bw` zF6=C|TCj^8%5?tw$c%U^1rtKYJ(;Y?3T|=biy_&RqNLOQ=)pYno`7udiF}`hiAMxyQy;EH}(M;)Oq)*uq zKB{qHck_=ZV5sk%=F}`sRZVbdn4t zbbrNZHlGufHka2Dfn&QW`(D{N$S7Nr0`uRmXo|ESmhrHDuVc0IW3dZ)JzRJ10u?w4 zo(yD7x@(sxsY=5gHrMAq?%ma}+HzMbBNpMAz9$OO8*1a04GbCJ0O5`4WT?d#<2gOX zDrH>K^3jGYvqeVui@}^G`>n%BqBeCf*uer+YVzERUvYtb`Sh16B&|Zua-xX&rDo%k zAtLYdjhQA~8KQU!mW9q{7=UjviV%e57W_ihL|_QxffJmYp3q^nOC`Zmm-yj^THvmI z^wzK}u1k?wToI@G>}RRiD-@{*SOnwaOX^6<}SL-h|f(@4OM(FowDdp`)EeCpQdA(xbJK~@ zM$WALjGX8U>}Lf9J0*wDrglEu=QH?4b;#^LGI?}Q(K^Qb6hxe>w1v(6TU}HjO5A7Z zNm3nOHwE~nxM(rKfbey9v>in~vfzfWLUnlzRro_t-vYGyHv8DZ4-W=&6fbvTDIef^ z!TScFI(EHu@hqm&X5!b%ebQjDGEK+mR;D1H0mn`E9fq=IBYEOwG}a?v?@4LZljqy& zRZe;>M~WGft(Br`lWUp)JO95w)cM}H+h_{>2S~19j1=mw&fR=~6Po_ktYg#>nJlPm zY}A);>ESEd`XQ75$0s&xzi4pS5SkblHOA@GDdk=2<6HcWUbTE1(^s4AZAV_{# z>z07R(&YPwONJ4bo0grpop|XtYRAmB-XSnyQ6TWKhdwiQsa`w3hIjpiOuT9YuQ(xS zezAEP=8`N3iO=R^g?a+@Fdfsw56_t!Snml++dpKRnz(yE(0oF?GfYX>=35#``q%oF z;=62f7eQ*yvD)K@hpLSt)Op>zJ|Y^6Votu~`Wd5RFNQhnvz@V>xw4F~x93ag6Z$Pf zk-f8c49HuO# zC(2pr@+W^+^KB9qAy2l!K#TFb3h+H#IE6=r%?n>s z@`9Uf3r=#958}FrtPLH@OhKbW%4>_ubfK-za)pS_tp$-k#HbF}*I3TkKO^f_zxn*D znnE;hh=B2{+?W&ZJnZZXEEFV+WrF2yN;iZus@{EfW!KeTAshPt{UL}J_;=lKQ+;l* z8q)8Afl7#$h+y)w&1s;lzdK=w|F;<+S4M#({9B9*Gr7l69QLeCuBpahNh5q=j@x0- z+{Txz{9t~T88n;4*7rQ)_ek#8PWoZlJ`im&7II2frc~?!#YRmK;tOgV=8eV%z;+P> zd)<5Ilfv`#dsYM0jC)-IlOY}F`*(Y-G!r@xm*UTt*vzC&nonZwLmyP3MjYixCdbx4 zO_jT+C2D2#{o9eZEl{b!-%L==Z)JKrbw*pU5Hn~v5OA$g@vIHvRyQ--Rrh`UzD->N z1j82(b)szTecaM9;nwr;as-QkUeZzzCSorQv<6o?H+|6NB8N2xwK~c@NEih54&au| z$3pynY;UokQa_+)muVTu?}O(uFrK*_EF~t6eM|#?IMMkfte1@@xzzrlEb%e|<-WB& zp|ERK4gI#fTQhW^T$vBmk!=e463dsnue*4CPy^Yo@zwJNEsS8znw|jW9;(6oM^(mJxz%qF zf+~Vz4~`35z67mCtl#J4$@TWu9i+p(1`Dw`&~JHl5}4;2O~f|dZd|N~3Z~Xf@Vzcj zH6)C<%Gp5ziqw(6D`+POHd6PS-=O(!Z7K?AF1AN=Xg=&;-Ue@0>jrr5>NyAA^&x~k zy!U@w4NzW|>gA_&Tcf;uW=JbL<0vSyR# zyJ8?57I|AjCztQ-+GLml6Vo1Wqt%Qm0k-@+>Xqrql&PM+`gh2T^xEF7ETt35jjDwz zChcYg9Ve6hN06^DZQ5v>M2kth*KhDDv)wv`hb88R0pA&Qf5`7@xK)^uZ@w-r7B?jx zdZ^k_W#B#BA)QJ4WX%A8xXa#+@o~~TI{Z+S(Wj`Wg7p3qK%ywy#22eZ&NTet?mws+ zZsOK!)zq3mx$va-*_xO8kGOBKihXVI*GECX^$(UG8&zSULciP5>AqMGw!P+K$p7(N@?@s!Cuen2w*|}4 zz03T*xlQFN3Vb#2#bWvcgLu3>O(VHjTTDBwLB* z)UycEg^<;sh_0=NrQ#Pl#6o8eSHHf0qItsyw4?J|CqGQ>G;9TpGEoYwnIJIkC~3Mk zGsKul`@uTMOJg1ffvbdi?*1H}bTfVhQvf8O2U~Z28kFIFp*N@Xb+6)``CeXXBTU~Z z8~;}Rjxlco0Gc!h&ErH>4aF6k+CP5ScgncLh+9J&_ zK;;xj6@LD0CfNaTy5gJY{6sR776VN#{cM#>QRcR{OpvU$#QOG z`hpBwa&BKE3Q_lf=5GQGfBz6vm4OTjfQ?Rrqfo}MWsTo^Jm-CtOzMtuz;spBK;?1u10$&bSd6%W>V$ zQ9?_5hGE6aVVyJmfj{jz5sZ70jiurb4BwH)&g>ewwBsXY<|EW-P%d9^z;a?$W9SXh zEgE0Puv#x=-lBMkW6FKI;{eddASwYxyn1c86V^!Nu#Gjw(P7kc&~aZv#~9Z~y}muN zB~H(eKLbx0|5Sy&1SvCC)|!GB>u&d_y-re)u~sIX9(>t7N1<|iM z>=CnT605285e`CabKK4)njvF%;6${3R$uH#b{kA$(Mon8U$ z+M7p@PoV;60Dv*xylZ60-d~dEu`9+q7uJ@A6mQGLWxu}1u2Hg1o$49U z{o#IxyXoOuUMuos?KUvv#T2{&ajV~RHqftn#p>25uy~#EI!P}cu)^8bp@zx_Uu5R0 zW7~WW(ra~Zh!})}4z$?fWvyyHX90^zYoBA8?8_@%q;qpGcqY%u{C~nR@0GF)Qu&=2 zU(}yP46kpmuC#o}MRBHXgz){iQ*O_xOMo|(oo~cPAq+%xKD^JziW=sV4^?Fp#j zzX%UtA4b*~zl?V-|6d4tcINQi=kZVWjmoXFaD#}b`_(YHg_a@)yrAuilO%h$7?=>( zJ*vwG6?lQXx)Ljj=AHnbaQpOCu-T*(fj&DA4wy`qFQXDK+)3H{*W(QKBUS8YzeW8<77hfg8 z-hU@)tCx8a)DUhn`;^^eNkD%O`2x*-9*ezFhSx+&#YYLTnHR$$RCi4rJWo@ab!IQ2 z80l3FFOsTY(R-)o%V%#pDX>=8Cc`J`5fRhMp?*dymhfOL40Kk!l(dsi)aU&4SyIB? z&Nogq8N4=vHnd^1VW4gfYFVFV)U#Vxn-leVNJqKTyrIk9{)RiYP-+ zm-e@9=8eAIZTph}K0LL})T-A*T|zr_^Pz7Gg<#)jX*o3i{7>RXyd-7*%&>n3xko*& z<;Q2eiRVvz7`XRCYVMY{uffbFgRBl%O8yRQ0ROEgk#(|jh@4M6J08lv7`4@PcHKG;)=L9H=UCO{fo}w@fRmm7KVS1 zhL&l8lQoKX4$dm$V4TV5%y5z#)@3T)1=Bhh1nAS6&J7w`Li#NO_@urAi)xQgndozt zgKFYGPq2P=!evkm+Lnm|gwn#w1{|ts=q?wWA)5CDcXFy{AP)>cSf?!WX1=mHUv&PE zc;>1vAMI@sVS}WF*%8dB(`A*cmbo2V3*{_!W2DLj(6MX$8r#GpRdq1RhDLwFWt6)O zW5&H=f>;l#7&c*7dO)PpSu{?j6F?a5g6IOCRlKxj(V}MRHfn&kDub4$zw!(7&Ds@q z{G7;Tj0bq}>$!=~?3}dR;mV!%KgmD`Ur$g4UN|6}vM1<2(=Ls%(@*%3WcL;~=;q|z zsWT|Q3P=d4HK4$WLTkvyTV260b$K`H&s4~JrTePbnd@g;Nn_VL8GIh8XULy@O3xAz zrs)^hRfOn9S3|<`AD)&sgi8Pr0=)Cbgc`qwPq5f~&@T_N$)(4|4G08d9o4 zDWcmFobKM2V{Lkl_`AMingjTG^*EZ*jdNi>owFMrTxeZqH7^&b4*KY5j+l~60S{fF z$KK&vz5KeGtyH&ek<`xP``!Zb=#H8Zh%8?=n z!+3DzJIQINJ(cUPF251kUgRp>rS9Y9rIEo8Fr1#}v(N4~9VNBxMu4*wJ|6nIwDb*B zW$72qWinX*!`(Ygq{JBrDk&*!=)gp*YtbvfGjhW^`z(b0ZR|_%>(RKNc-OUd;a&b*Ys=S)?%Ne(;RpIfxKMq)`@F&3q2j zLdRpB+i&M%cdtHbZaksrs5Vjfb1l-aMs&78%CVZr^kZt$^84%-`NT5tdtm->$HRFI zrP;W$(Za6?)`p{3SQ4cVqq*S~(BQr3i=MS^3-$bVUy0wu-_Oo^y2>^je;RJX`W<}( zTvieq7S}=kwiK>(f%eM*2ZHx;hfsesXL&Jjs*q@Z zHqCeBSU+>nU=;(Hi72~AsbqN@1)1bde8*U3W^CpE7P;aQee&@0-7CtSR?nt(!K(k- zA5vqTu%ZV#)XSi#?nX(ZUvXmMwNp~f!RB_w)umnXSN@nHfI&^To%6_e;ZbnD;GOqC z>+(D~s)*4srA1@iz4o&Rr#!d?gUiJ8m}2|_kk_dNtjmVjuifkR@rkou>U_!OGVgEf zHe@~9^O615?3=fpNn^&fazI(D&IiWe6@Z7p0bkr7mf(FAAw)Y>C4{`tJHhk9+2j zH(-mCx+ru@UY85Dvsg-k;0;(X0y@R1)wkt?&~SUn2-;eLbyE<1d}4r>kD6Cq^+3p*B$jH>Uo{`^XQ=$NzBXzqx{qg;KU+b-cad_ZkeJF zxLUg-FN{z%Gy?7`z)cC*3Nx`DSknD*jU+9K06Z|)3409VkaF-KLj4I5pjCk2kQ0Ir z<-!^8$vVS${YN8`d3au{I**U9y)p9rxX?FRRBvYA!uy1pu03x;gi5oUTy|v*;L{; zqFWexZqXu6<<$n|?QmFJ;m<=8aWSYNzfN*`HB2`2jMQ)%@9b+Rm0gVI*HwK`gDAt7 z5Ws>7R+W7lU5<`4G-ac`2f{1I!LLHk9z0z=`a5-@&*d}wT|nec&B?P;Ve^oS10y8d zO)}WJG~%Vmcdf7D0Lycj(XH<$)W=9zR_4FAV7T;1ixJGOl-H>hsMVl1bjuKtT9Bjl z|EI7Njqn-=3p|%Da5Tp3RtepngXbjMk?^4S$Q%3z{va^v1!a%-cJS|eUP$UX9R1a# zL^6|BKv}4Z6^e$dz|$|%T8a`us&Dj_I=QPrOPU1OCNFEO?}7z?+fvNQ;6{3uk^`7! zpULh1+s!DZqVT!HivT%!qP|&9$jAy(=4f zJJmH+bQfK#WhM!eF!z(m6WH=DaYxJ&eDj3CahpOR&2C`b5F+vU zH!;N8F9eQLn(auucwOFuz!z4c?|pK)ioj^)8^9h`u%IyL7oRs~zXrl^@YGHuTm4}s zlE8zWcc~LwSJEpPY$M*4k?XE1FUM;CCNgL}%(0We6h`np$D4E71Ge0#e~$GNAGQ;Q z=#G0JKt5@S*%Rpg(|Dr8UP95)E0h-~sBjVHnt`gSFHw}CP*!Qglxl?1mBdY?5 z9k^)OyEMHKrPgacE>kis+5Ew_HyI-%Hmiy$W@TNrx-0g4BEAq^C|oo>zOvCV^x_N) z3l43e;_&Gn<$S_Op3{;s<#3DjV>on+B3$r|?FW7Y(#z|-v1#f%6BI!#{~K#p=P0-K znaEk(j8iit7#R}2E3H-oQvk|WycfLO;HeH@u}*9>HAY5ew2f*-D^Wk4eL=Z|ElS`u zn2x>{{@NN7cLxiJh&;_y0found}%HqvyIZ-PwP2|NYKK6%B1yJ%9G~s{;5?0)0RZe z9d7g2;Pg}MVgbws>%-Uc-oIk}4u=4?INZqUiEcGa%@_hjRW?n|M&6{gvOX^16v(*! z)4dvY7kBY}X(_8QA#*u^)VJjZB`FBwmf_)eFUf+ovqfL8W1Aqi!Lzi3POBbw&-e|> zt{iiVl;Z*?B94)+8YB$XT_c^OpQ(yNP*Ko+pcHm5?~{FBSVaSfOA0*JigLE9Tv)wX z(~xD}iErBNtNX~~){vS)E0i+-(wBg6;6lI(16yME5n;5nAz{ud3FM*GPw-M* z><8R%tn?Yr3`Epnf_lPOk_px#>9d5~Kj0-7C|SJCn$$#B(R~ zZbPP+{$0)6Z+S{hi8Tv?m6^z+hQ zrP6^febxWu*6&Q1zCX;A!XF8xpipEjnQ++i>jpEWfBn&QFL}Mp4xh6^*eapPp-u6S z8^I;c#trCV&F7gHt&7s3ZLSo#jT^jNz#+9i)BV)zEx^z^|$ z1ALSWk+TQGyxfMivW81H5RAAlV?D-5WOxe1cq6pftcDC|t}U#FuD)PHu{!#qfpqw> zZv!cLH!JYK6)0tmEGGi^M;>9_<_QbjkRE=+E~x<9aH+{~xavv%RiZd5`0(A2EwXAp zyo>j>)9|GUp;v-UD8&)+=NOqzc^9~P1J*HJH(>7O{nKp+V9< zvYU+6`MCq_-i~BP|bk7JlTmiq#O_5g`w?)tf zzhuoCJ5mL&Ipd@BAcx+;T6Q%-ovuD(qss~V?yBagUgS2_a%2(ExWy++irzM5V2g~h zeJ67rAPXa z?b=6DZtqp8fBoqo@Ar{$83o_2r4+6ru#cl-S#~G)Tnnl4p+^$;>LiJuA{kEw(Y>`B z-1jg@lcRXRd8^ej=(~N0e%S;QW$TJBSFV!HkzaVFbd^hV+2bjXozc*j$2cBxp0~iL zMuRaCtV;zv-Xb<_-N76xnIbENrosIh`S{{+qRWf3o!s;sMUeh%8Cs9i*2;=nYGr^+R%Nw5%VS zOL`tQ)=3ZD$uWxZ7izxh*#Y?$4V@)yTr^clDNK&YH(#d={!3?3AGF2oF<)ak;2{^> z7WDNfhEvlK`_ev!#x1A#K~8Yj?0QWMNu7Ew@C6DuJZ?W8S!Oy6OcL~nbREuC8sgC# z{}W>E1+t;@<*xVNa|kpCUaxP_c=ja;D!Bbr;Xsua?|cV$q#PO)?<7SLoY*m&vo(Hq z1ZscwS1c>^F_=ae@ntMRnkO*@7>#85@}yv2xHTgAZUC z@Uv1AOEtocOKz2JM`ur8b865khrf(DBOUP3q*kb=29gY6ozGNt4eLbi#0Ac=s8kSg zmgErVSZ3E&jK@nB{IUaBh$8v)YnG1F42QR~f9DT-sWU&{I}(lcRR(2PO+H;L7j?%g zK#JduQhj`2y4UAYTYq+>|M~bPbxkk8p=>^tY-)21ctu<{Od&h_nDfY4Zs!D$XBbu% z)XYwj@~}BkOsXhi35<%wHyWizDI$y!FC1qH%G?@$S6b^Vj3Z!Xb|bLHW4|l*@!Qy* zN81WaTr4O7QOa2&dSLBVsdt24iP-THT7!|y03CoO{=4+nM8U-vB!LD}OG)>SnW|y- zXUmV}9)C1&<{TnCR&u{MQXCFY`5N zgGNV0xW;hkazv}E3`mG`0H^hI|3q$1)aco8%EG{{YJ~zKyTLD(aL{)>Y^65K)6>U@ zuLh!MCdBldUvotsndTZ0PDW^2Lx6 zem=$BrFbOdq2`;ch31xA)fn!P|8S#!!AIftl8?w_wZ9me#0=gar`C zu7-)&_b2^Xdm_OhP+i=6FzSZDr$ZBSxq_0Gwb%5>N_HAI$@n6h*U$buqri zVV3bPch5FNTjjIDs`2i>oZS@qNDa-B5bS&O-cLjYChhYKe6D)q8Up+3&$Y)I=0y>*ApO>BdY`6Lag*UgS*F z{og*X-g=#BCoSOJxD^X_J-sm)@3o*rL3grwx=u?W+K7v<#y#J8n=j3(q!qXK z@*1s!!DH3a29M6@a8f=xULQMKSS9+Z>Ahq0LQgL`xV4h&o2mB= zzD!AmsY#Gcx}|eb0pUf;p~>(1u311hMNRaeH*|>cQJ^-cY4p#TUGoLx&SqQzak*eQ z>iu`D9B!|1UBuX1!CN`?+y51%#2a*@8x%oF#+(0meAxT|T@m=%F_PatXQU7ON+vIs z&X^`3URFb(`+y7v%zsc_z7ff`&!!LbZhxRRpOc}!G{ivzL0AR&fH+E2F+LAVSzI#c zOj3<<>x18dA#AYK*DHwAP8kY&!H;W90X|}>A*NbrZ(7qWCd3sdUuw}u4pITCFTYMz zwSZaxae+-bzrdu3Yp224QS_f0`33l&9;$`T{43)f zgOM2t>GI|EQz_QQ0g?65@Nz#RI^R~RMGf!GFmOs^B$*X6ugit@3&6$MNk^tu%hO-) z7c9i{-c8Q})IK0x!*s!S1d=XE`4Bm6-x`5IMwNA1QZSMZGMA_^lFJb9`_v4q?wAHR zJaz=KxpV!Fe1N8dU!}oq@<|@u(JqzpN*Sjpy$k_C?7k75;6FK#{7~hx>@fIg(}y*7 z<@pz(hbR-ZEG#C>i{otE0}yPK71IGB7gyxsoGrOA52ksq#LDRaKbZSwow{M2(kzH~ zte>&2t{d!1ZhR#3AkxQ2@6G1b7F_#StJO&K3_7Z|Z&1&FXh0{%QOqxwg#Bi}bzN&D zn%iocVKU_J;T~N?UcakUiSUhGy0HP^38Z;DtURJF8RY3H6vgBJt+<&hay=or|8Wmm zor~;q7Oj7(fl-l`+fU`M9U*#@31!bc$W_dNiTf`}X)7KD1ElS741ZTKoGVJv-^{sZ7>msXl zRPB2t6_XGIrqfDR&G^dutjS*D&fhr2vkf<9eCJH@z|e?hh-s($$eHTCB*GTqIF||6jRhGkTC|*<$VI z^>Un7LQbxm_zCPw8$QHZP6cm0dk5UM+drJ7xs@uKQ^D3f`mKc@omFt;0FOLtr2gp z4$G}`hgnH7)VI&ijgVmhoc3{B!|aK5z(W|AQmy(-q03cvUQ1P4NW^b4$2BwpH+3Ds z2*x7fOgbF4D@TT2bXTU5&95tm3c6kI?oj%JuWOdu2l8&L)z$tWeNVjeAc>x{j53k(KPhsZpelD;}S3gl?l2UFTFW~UK zIq1C=g(?ofB`*R@mlC3FJjVZ-Jq5>^{kmLn+^iW)h%$xWr);3u_{r_5Q<1@t3*NCx zp04&nF-BIy>x@u;0XD6U-dM}dpI3q|YbE^8Tg9`ozEBf4e?MF0r~b>^7KJ6$&$>v- zHctaICs<(xII~^*3(w%|rF7!TTPE*yZd;f-yE#GN!n-{Dl_3X?{S?6vqAC7A!m0zJA!5#>T681+ERj_8@}VpO;*2wSjv-v^;Nf) z=i#u};kCqf#1M_)-CL0!NsB$`_P;Yx_L_nzfQz#?t3tikNSaYuV}Acvf4Cw%r{)B3 zb`b{Nq=e4~&iPFnJXa1#4Q$^5AK#c8Fp@6Jv3}EB{1X(U2GTXc!ryK^2B({{3x5tk z6s{Ho&;?ZEg$Pb9Ta_T0-_2RxmJYO$GHOA>^-Gt+E+N!ajPMREW)J6ukSIgMHCO!F ztp@yyJm!!?Rlk$SKE|Oj7(#ISm1T|k-3N_FH?dAL&m;Z+uKtq(9+Mjg;IrTc$!|YC zELIEb7J*>wl9mV%<&DIsf*scX4KL0?=Za&!s(4gL zxRjp$6^r8WCvF5U}K?DQ@x&aYFP`aNzvwLEDyR2nqooG?EZy8_7>9-DCs?><2 zt+Qa`6n4Ph#k<-AhVA$Ou%HHQRK=56Jhb&k837y!8Diebv;vl3({Scd{Eue7u{@yZ zvJ?F$;t!p&IMFf|Ac6OS9cGr6gU2}@zZCVFi5R=Cc?kVDLCoV%s zmsS!#b(ySZ)@=miZxjb8IQtb?a1*S`t?GUU7(zNdu2(G5m16mNtJ{|sMA$!Ax0neT zP9wm6JGS5rV6npxckpd@^R|1x>;+e^Q{vO(L#xWHJTK|^ zsC52V@3uKXIllTnBp2`1a9FwIeNo(JD#n`xjRiwb5|rI+bn6dyH4N-={F7|%nQCD! zIf(MOeR}e|P+Pgucqh z0J6T);4{4ZI^q$LNC^8%kHimqXRlkTf=M7iZ8!J30J!(2Vr|2$BxB~@%*nW48^nsS7E`b+Q0$qEuR>hY|b_3IC?K?`dJQ z-hli?>90WV$FP=#nv{NMWqdF5Xo`@0GSaeigTO<7e^m9 zf5Gc$dxux(pNdA3Lwi_~003NFo}?sQ1@HsIcfm)k!wYe@0?u8fH1Bd~U61*Bp7*Qi zJ8EFP6pM})v8>I(0@2odvpDJuo~Edj#J| zJ9krDH8>T4rj~nV-v(g7*BQ>NlU#<_bIrls9Q4msyILJ5Zwb->d$X7E zu7szF0?rj$0f5Quaq#S(chD}F)RD+H8hk8H=`8C$x*e{+5Gu@HP!D7QZfmJA*Pp zR@hlTwsea>SMb%WQxe!TGeQ;#M%*X3)LyH71}k~AV!2V^i{^=s z?^vE=R!oI)TR(fB%bHoyX+7+_(>(zL4bX}!nRJck6QR&p)s){PZ+=ekZ&b~IBGa{y z@NpNb-xVcoYi-2gGA8<#5A*A8lT3bBKS}7=kUT!jA~Z}8IrYeTKJ`?svdksxcwCxt z15p_T9k_F;^#4Tu{MPQklb7v`9JS)R!(Q1(-O`@})Fj4WI$4$VLF@OZ0Q=UT=3~Rz zZd7kC^Xn-1G*7x&OVM4nyi(y6-q7|8y=%Zzht1~{Xxd_Mlmpb%e8J78?4_h%!hMnn zG5egeu#n&9`{YcW?Ct8QwvA`0_P*Dj&SsJo6uj6vj|bS%|8oTZlzI6Stw!RjV?M9` z@(QIyNTXOeDH>3REkB-m3fF=@W{V!{dWKMv?mpZD$>&(LvrCK!u|aY~%(=YxhcL zVD<9ZQVx|VGW6YrH)-F{dP0|&s|@Sy9{&c zZT{g#aoD5_49^0e|FjrSRX}j#!cFZC+b#ESn8=vkVyuK@Ll9yqP+uE?Bix`>Or`TB zAt7?oH(X5+v$%GBXZz(h_Xo(-&)p=cnRY_!1DZw?3@%Z|xZ2yRU4t(|=r9jLy*iJN zxto^XT~9I9RR(}fAB)MG?`khGy{bQTdWB3X5`rgr47EgoiorjCjl|(ork9GIFRr9mdX9@#5~MWj-Yf)Jj^_P@YSr7=uN3NdO%6ECs0`}?;Vk{<>6TGU))^lDO>Ujv+1 zz|AWleB;nXFj{qjs|=*7_z~bZWsDPHbZ)r8#*NZ8gruazCyJRUOwO*42JJ*&7>Q9w z@|g{HZs(7)AQl8m)0pOL>^IJ}0|WLuhwkWR_I=)BrIUQZU9Ae8NE|e$CkK-4C1wzR z|4#L-JIx5$1#sn-|B-aw@l^l+`%gl4_8xJ}%r`=2vS()Y-eh;k&gO(19NF1haY!5^ zn}j$<(lL|0vgi3eKfm99{o|H;t;h4auE+iI(*{Z~WZ09I+;di}Sn>VW_8W7OJ2Y#F zbG|=cZaEcc=OmPVTe(#=vPIJyPfK?O=^H!6?(co$7@^O%M!abuFaw1EABO&W$5q5g z5(-F8PP6+FstDs96Pfv!v@r`0!MP%)6BQ5~ws|`;SXQ1*g1>4j2l`R|XzPpDLM35x zg$8_&K!v-IcUogRv+mg3my!0(c`0)V{#`m;?KzK50dhSs{#jW zacO_8SIARS(fz&6-t^_bl$8DH?Y!G4(A!vSp%3i9?dtL}efp){mMZjag$Cs$i}oZY zIE|@1^8|lYHn~^Z;E$gKY8=&@Sj*&`4N05aB&`w9DBbh1d}Gv#YId9x6d!%}D<4O< zh3EGnZc#4~*E#gE3#{}JGpsU zu`_ybk3fk}*1zSRcAi=k;q8zPWH|99V0KyUmeO7LpoW#_cVgG4oO1l?od2

      0uLuxG8JsA0q6bs9 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

      4zsG+3; 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ʑw9sCN&F?zD0jgD*NZ3J0k&fZ}F6j2%F$x7OK?z~b=EMpW} zv*`Jbn|9!P%~2x*g0J}9zdmY-XyGYK#1Q1-sj|Ch;4)G(`kNyQd9wIoo)D~wt9H{(3nQL`@FEJi*PvVM-GW*=W z9MifHZAhs?Tpeqb;*$K7J65t|SSJQS`n>M!uvK2YKLtUmK68CiTILykc#k}1mqD7- zWfLRKp*`|iQ{_a67v=nAsF*}|L<2MyG8h*u)3r#fLkmSi<8;}n)R$!bc-@tO?rB7x zG?=unLAiSl9X{ZBKu>c?8q7&$R0}+N#pXtj$GmnP$!fq!n6pEpMxn*xzG+8^?9VlI zj-D>vn1;r!IDV75vun~9O;dC5^({L;W7sa@_^1yOAyDdBaUY!~=Q?Vc{w16For5FZ zbsHv75Ey_maN{-=BQbHG%rXY1^7O%H*{mN;ou^pht{eMxd{}Str;Nh)9@gOMGkUqwHz>WZibl`8 z#t|{MzWZeAAxX6RO}f7WYPY&&d@8qA1=vw?=8OL}Q`IiSSOxS@MDWYmz!*E)u@?ca z4XM*N+O!HM5b7M-l*=)s;b-)infN)WDns^7vR3x~)}q1AYnOCngSM2VY(7{aUAAgJ zF3o#;>!Oq(BnjDF<%GBYq&PD#6p8Ofr#+G?7^J((?Ng~!ERowGLX6G5KRAjsr@4H+ zRd7U@2PB(LF`!SS^z+Xa^y`~cuLv<0)=3KuI%!T{0?-(N*V zDpa9JXTD1Y!~wf@_x`x>>fi6vHl)?_dJQ*_fmQP28E8S%r~S=h9?yQef-QOZ3te|J zVOILifcyFTvY%dlp#7SQno3ctc$3fIvi{kDSQl#QbDZ(_jKlqkPu`h&jnSif0T8;O z`D#lR!oLtxCYAoF5sHYC4BE;&)s8M1WNo2S{?I-z~$=C%rzjNxr_O4Jj)H)DzpjZH@aN6sW=$ z!+tr5H=`whphIeia-zM+iRpGk_a$_K1iMK;QtT-x*=s z>Wt-?V+l9_V(cVaessJu+D+6g3f~@-TN(4D)gV2zdbY|(m7Z*_;yIzC+>pSFB8YGz zc_TFy{(WlLD4|Nxpx;?nIak~XIrmFayOm>9oF$=^xndAjRkPB402_%hs6?m*= zx~^QaI##F+`e9Ye0bdGUj$AzOZH*$@;1Sll=%62g)j2aYHjY1Lj%5WJ z&zylh&VfRYyG^qLX2|jD2T^RCgaN-SUuZL`{@nQNK&DeDCVkjIORAxEr8&W`INXi) zN`r2mDJVdJ?iKT(>SapXT3YjA*JKA3595V>Y`hV<48e8N-=cRDZDUXP_PlAd5l+$5 zN7p9KwpgNAi6dKZuwN>;cFWWK*wh8fk@*XLy78eh>EDWD5`zKx_x8DfO}6yU>(=J|6h{4zG2>AycI@lKx-;`$ zX)93_5a2}Z+4+vGM?-(#v}Mq##Tuy&*{h9dWGchZCjv)QiS1ma9qs5qK%ES;#OT}T z`J*b6&NU@Po#O=(8W(fIqrCPXO1QScz3SAR z#LMq2_MI$Kvi|T5uWnnY#I7VWWNNrgsxDLIS(@bZlH*A9muv#(1A~l(HBHy|F-3G^ zmS;-#zERnQbw@k$5%*ju5^M=m+fJA8)|jdaYhIPoJ*bMdG6wh&UIk-L+D*1da~!wq z>j+6O`;s+Y#DN^GrRkRBdVwk|gw#=0uxBXX?zPgn!!|0^=jVg4;HlL31N8pZCEt?M8HrvAV zv1~;)+@l*$Q-iv^`PeL9ZCIghtera&Qj8_$5!Mc*aYcd8-s{-@KcK!3EGKqC^JV7! z^50msTk(ENuSVipD!5Se-t#GXCT?5Pb`T4Jy8!ndNCgy2Jd&$l*xr-SS}%o?u{^Ay2l_95qnDR_hIaZJdve{Ei;_z21yU}JZ(1fp73zT`bs@-mv!X7l5TBA=E|mBojfdY90M814{j5Ikn$bNc2!T z{wlgLJl&<@h2Cm+beG%Ea0;*YuCfrey4)xJLU15iHg^7)(7g?aK5TFVgI@u zi8_Tu_7+LSq_$9b($G6g_61vj{Kw#~I<0-OL)zRf%9`~jfR~(GeW#rmPxzbKf(J!K z47{3b4f#t@=Yf0CwZ%b8_>ldNYF6@9(+B~P6qlJvPgZ&NW!# zVuvh2PqZU{Mt3k5(t%?x(h;rbAZz=YAHUSqj?+j;MU0 z`oQoKN5nb#K*^I~G=!<9$|fleRkwM0-s@Q_)IR@;X9OVYTNRlZTMJuf89Z|tnQ6XAW zEc#TT-yemn{rNFzn8{21FC92ZdQ~_yFP&@%6>D4FPf*UYJ|35UT#Y9qLV7QIs-sIF z2!_7p7CIiqF^M%y6=|{t&R?V^0;ne6CtkNei+vcYBT)Z0(+0l6fLv4esMpzS_-f#h z%KAJS*<)!W_Vk^#2KsAnpJT_UsPz| zZIaEUp?S4sw$zb!-ga#vH#~?+3{gHlS%!-1+Ha`Ts(rV%cEDTnFeQgJdo9p3es&>th?CuH6n1Cv^>+;h_Eh(5uqP*3>YHNvaZSu_e zUauvIwqj2>#qvs1p&PC7RLY%(GI&Y$bI{r6wy6h+5x8-07cw#QljNL2YZHX=*Ho0B z-*x@s|Dfs~Bi5xX&L{D>uXil!06m3nLo}HX@BNNm^g)_Pc?Jue-PO` z@67w3`|A2}#!HW?8eV&{U0u9ClCig1ese}%ZaBJsp}H<#*X&sgVW7EbN*(PdCR9e` z_-vzXT$QaJR4}kA#adN2Pr8rjZuGidDyd52o|6I#5{zO_Yv=06>$O4Lt13L5{Rjzdp8LpwgM(UxK-4^p;6ak; z!PfaBur{qbVP0FGs_SgLpmLO{o2k0I=4^L%walXA*?0<1R2Aut3p({5qC0wR`s=r1 zkVWvL$xW%y1P6xJ~sNvw&nS3xwi*-_fYiWy#42#ZaeBD_3O8DJxYJ* zj~B8BE{B`wcenUm-&raM*lt7QY<(u0sJneQzHx45(RndSigSg7x?xU}@X@7h8p}ZS zuO>Y0OLr?)6%!1jvDUYZq>W-vKKxm0wDY@&RO)|zxXBsTBX4*n`CXn7dCw>zy5%qP z;BcjiNS6qHP8S@&)H{&g#orK}iC!{pm0*uI?a4RQpQE7A$gl-0zhD`4Q+BMOf80sC zPkWS~Y|fkN8001>-mXHFj=OI@?Mww1r}~@xR0u(cuSkU%S#3XIU!2YoaBUMnQ6+`^ z;ME){$=99p$Cf#gsN`KXU2NCtq8L@%V4acHd5?9&cD8Bunu`*9j~daLyH&t-;fpDC z0gSJ#Q>g#Fm9|k=?0+U#cSMO^*NY!zkC;ty%2B2|?ug~Mu`Qf7jAyM!xMG-ckgORiV5@dKW9IMeoR5}ly=GTBi&SmO86>{_+0iwIZ+Q0ak7 z4$N1b>P=v9wlh*46vI{w_h(w^yD^pH^wgt3mjlHSKY#n}i7phZZ{_$>1>zbgAY+4rLBs6e{>NK{i& zj1Cr!S&HSqS|@A8Rilw_MMP9<*mgh)!h;8#@8|XjG!^FEp1kO}5WxQ|$Jz6Azm{70l3ku+ z(t<-+=UV2uNIk%Jyid;6e4hO9u5JBtD$M{vO56U^Ch?owFfl1 zkV2>W_yZC3%9Q2dI@f7egAD< zC^QU#tR?6fw8`}6JZBfOcdf;xnQ=%+~SIx`qKULr3R!>i-&S&IFoXLMI5Q_jKz0-XVq*b1gC#eyd96?UgLyqmq-go=_W5V@ZG6YPgn`19BGT0T|k{nsLGnZO|w9nNqED`NaKYx>6y zV*$5ZI8a(sVaAgRiPc$nI?n7rJM8LyJvq<( z3gp%ms|TdMcme1a`)~FFcyTO;+?UeoA61)xBr1H3NV^{n`Mb?n9PR$Xfl)A7z!9Hx zR1D@}a7Iu`{(NQlvlasy>RYSsC`~Y{O8~aV$XqJO;5zf0bDQjsS$ze8fRneKk%J`P z=zN(8VN#2gD(&ISb4FDM+bElWlLSO$h5>RQf4E`2nn&MCgEFn?_b-hK;)+%*SrF@} zdm)K3!e~G=c2tbIS|bUeb-tDP$*0$X8>7KizYbf%7wyo_2O^ zb3u79df};6kJ#0wynio7sB9$VGGy~yr|naP$uG@kE-`DKvAmHxsuap4>z_aQghODF zH%Q#6aAsk8R~1y;Ru7c2rjh_R4SiTBoxCG7;P<-oj2h@;O{d!M{AC%7##`!2lj9ZX z1@evgjvZ04)ss)oPoKgd023$Awt^3ZgQG@GGJ>I32c_oA=0)$duc((u3aQ;HF3lt78#eWw{ zL_8fs3%Q1`Zvyg1Cwq}5s;+?h&4vR=_Nrp`6=-vi63g1pRnVu(X7$zhO-IdeQT9UP z$(*uInTdhx-tgz-7Vk21LysaVDr?sA6bdGvFRCEGk`NtzVcZ3?6dGSEP;CAgHHYpW z8|7>fna3VMZSxD06yKZsjSu&i`2s&Be}SgX|4@%=pePb-J~-8KCSG-W?*wc?3dqM` zhfsAZkx!>mr>Nu4s4T>Mtp5gEvRz7ad-ONwAcPhn<*xwME3D ze`WJos(jXa8c&!nJK~?rzf;j2j`6}~8@n4)DSoO>8Iympabx3Lu~ObzHWQMmn05xF z(e7gHnc=!z!(95Q%^)tSk&B&YCS%uq)U`6t`P(KGay)|Io+Q75!L1i zCj`H}DrR2^#t@!et}%gKY*CDO70k;sqTf6N>!Tss=Sq&kKs@5ZnkU@9-s=CRPb>c* zZ{V?lWK4EKcY?wJEZ^!MWGG%oFlPicfiBP`73*fmA%cQKBcEQ`E2kPS1-G38K;tre^9WpD6#1dJ8}!9@fN zNp94=`jJcbh`sIKniZj$r=7x<1|zetwxhG?aeqml9fp|}sG{=VG6edch3+AAB&y%c7#L22NL1`g5z~No_ z%T25YGPQ*RrXS|Nw(6_dKcR4*$=qN%U{L2q$oB}Jo{2+efFt7qmd0`#xpD-Z$pVYi z5(C=T`aSxacJz!slyqQ?eOediM*M{QZ7MBFEMFXnSzW)$=U*H|{dpBqrUsrBh+I!tQ+bnAGxIBJbkj!Wl=;lyqYA zUw7)vM&l{Pjp&)df_Nhd481W2&upvM$+lk^Uf=9oLLETBgjYwzZJ@kb|kR&N2&ZNtAJhH^U7Xi z4rqp`KEhN7v;|vdmuvSFwSKaz-+8fbx=kuAv!Rec_!o^-V;B6@R^>bvc*N)0rl+AJ;n2TXpY$Xet$;e+K55)j+Ve=y_(uM$8Gz+QMYp>8 z4F8N&FnVbs73sVACp$l7SvjFl{F)q>%XX%gcd*{Rn8vqwU9JS9e87G&pM@N7YaRJR@M1Fp86EcwkS07 zbA7?giO13deMGECKfS9NcmK#e18g%nmjDIk#MvpP zYWN?!5KL0sZsUtS&v^f%s(v_t<-jGWzu>M`BF7(;>kQW;-~C|T9!=|@E9`Cl`@Wh< z@VCd5Ab0gLRF5SYVt?alKNtFz!zC~Uz2AO0uXuU1+9k4Sd_8YB9IVM@Hk=SxobFG; zm)ImD$+SjlpoUiQ6Y7VPoE0XmY|>phJzr*ZU0l-!(TBK66o5i!L7RKD>U0{%9@|S3^ix3i0(Ic{sj5((7`(BchE8m3uF>33K z8Y1;EFK5+-rvpPDx~-t2qHT;iX08?+bH=jKr#CES@NlzH4L|hA0~eX6$Ys#ac)SvRFFRi5!9$eY~vW9uZ zYT@ttCOpRp^CfQb*`xdee$h>%m`T?N+{~z1VTQ@x^%%$@-XbQcT{E~ILr{?G(P}5v z_DQ0Aya>lC>5eh>%afvKFkkRs%yOdFr>!vQj%SZVL@Lkc0@g+fhpRe+$y_In8b`qz z-!?Z{PF({VWdwRgf!Guf;+(%qBE+Kil;W?cXOFB$@)ug+hAwh+33q#2x)d0eD{}}$ z%v^7Gg`AqQik7dpLEiGE zhXRFFZMGJ@NH`-^7&Uu7HlsU314(_w^ z5L*UDu1bcy3eV+Ql{;6mis;g(@|C$LZoEZ`oAvgm^4#%4^COB#hbKC*$o=S1;Bp$gS2#~^Ob7fZLwuXgkqEI3@GIw*UFs;=*Ku;#_l@$y3GdewvZ+9<94&XTECCZq*us^YcPk6XL^=2n1i!GB zf&pHN+{EuiVt9ZuT?|?t+xa^b)#<@hkmYalE@0fDHo{3mp9;EpuvVZ^CH`gk$b@ud zK18Ff87=1U?AS%K+a0FU7J=XG#2z=A2+6$oH7kG4S@XG(;-1)e?g-P9gC!F51R*M) zQuR{o=*K~Z1WgK^&Z{dVJTJO?J|qZiZfW>i)G0 zG_{R-hU(oiai0C3UQWe+^&+Di62*(Y5B~U{RnGqzjPY|WTKUHj)k2_cNLFd;USq0r zDym*pIn5d&?(d$wj*Z@#^v$ACHjP&y2v);z>wooq)2G4i-EG0h*>CfSd6t}WM73Rg z==efpA&5;t;Ns$h7DtBtQUmW>97{F~PR=namN2YDL$wF1A>!z<6BaGd*kpP5XjDtC z&ailZ+kmks5<;YM^u~FLL0$&3tKMl3Wj=FPXjF~}53aB)XXvXXa?b;diCpv2`K@JW zuC?)L*r>AOTJY2(9cFhZ@$tLFRb)Ekm40UDsG_e>Kae-DR;)ioshVYqu1t}6_&$gt z62JkwTGfn&KlDuM5?YR8nQAyi*)xNwFxFu%oqU{3)>~X1ln+f3jpo_(cUDG}7RRY# z_6)oP3dn}w9R%?INU6PAqT*C^#IQ>M&pQ#5AEik5w1*8d-7r>xFMX2X{PLPln%s%j z^;OIpNuonYaZWFf`wY9m8pJm^6z*d61HdweyxNRr5$9Qlas{fR;M}5AU}s8G0d}@B zqMZy-5YfWbb?LVVIKKuk#qagZ?R9|*tzzkqAE(O9G2^_-ll|y&i(iuUr&_=LG!MRJ zr9#kseqos7YOG!pMDe&^X%)|h@M{0|x-0oh-oT-aSWwy*+&*qUiw4bZ{5+!d@ruJmI-?`JEAvrkdQb z(Is3h3XeuQ5+4R@i^Cs1dz`#q1?r$;r1HpMoQu}sl2Kz#1oBZhYZZ$*zT$`9=8`||8j%-(3J!RtGW1Ea;STmmpwx^A!$u^OaRH)axvlvVBmu3;b|I;vdVj^ToOiMZi+W zDGOf*TnS0rYLlxM<+lSyvNp0D?@(*jb=;f8dOOWqDJ$(C|M$?* zr0BfoA}SO!Wt63<w$6AUCeJ3TPYE3o}qID zpYC%(=Yy~g&~sv}PiOd8Z+*D&Jjwcw*kCjv%J`-XvxE1^SF@~DvtP`&Z9-|>gPOZ* z-3yb=g#ND@r%kt*UKjszM=_eaPnwN?k;NQXqa%A1l#&p>emz`RFmupb<^t~Vp9`f0 z5e7U(zr2OWmsomWhPy~@IE+vH*3|G%CU^d$kEbPEK-nQ2*^r?{#{r#|^%vK4fc_uMd;*bKcdY)q%R`Tk0H9uoupkksHCXa@1<4neXUkLK?zqQMX5!P zJTz-6X4N@9rbxGjy)(+`&bFclv?O`*FKhw$j6B z{sHeyF3H4Ja?A>gdK84So7SM9Zxqa%)4NQ` zXs-XbkCrv}N@W>U6KSrTL=Bqw%8~D$PQwHAp;sIeD;m!f&_Ua$ zKZ_-l>%UhyYq7}5?%-yu%gbIa$YhrD*gB53r?m)11ZH?w+E~y+w4SRYle(P12kR*} zy*?}LgeI-X-W(AK{LkXC)W%?A!a>?LZh#> zOBQ@K&(w-zuAe#CZIaaMbRe}_1=;!Cb5o@EvMcGqkgo@q=udR))Df|2%kop1scz=N zKOuD7J;Lw+i@?~NX?t_6G4C%+WUYEqqAgucfAIpc-|t*4&ss$C+sA>Wrzg_{gBVqP zPCewCszcdP`EmVE;!r*ZK;+zd(*4GBflOC*b;iW|yx*abIGz4nKi6diO&aAkwQek` ziTAGu3qa01|6=pqc7;$0;uVWi^4cg=2S9(+qDxpgSEb5qd zqUs^G9NHLISYTw;g2IN@tBV&`xA}^X`sJcr!2X3Tx-_d-F^DSNv$>({%py2%$!FHcrLepBSKdJ@$s>ZyBLcP5_b;%CX>~dG| z`IY|c*)+-$7TS!4+p(&VvjwgVj_wKhtsTys0&A*t=}}drhX@A&$c41 zTU1$p78{uNLoF*v#>V41eiR46x;K-n1ka>*k^aSMOQ!4uBF3)WQXv0RuG(FSa8Gn^ zq~GheD679)fg=|1=U4E9$^~VqNDC+no-{n`;caV&zRc?J+ zwe`STZCL_zdCWSCHcDi@Uy7l+W!022D$Nhm<@R4lA6U?}iI-5oI9}jG{GI0T{8Em= z-Ci#lpJ<=qWd2<|6O`x4G`!emqb<)CKtwc6Xe5R-$}zpKO{MLDKC0?~^9qv*Wjq5k7IUZOH0D`azK zXB8oPJG0AHi0r+xIh1v>3)!Qboh{DD3P~52mCoMd?7e=U-~T-j_x*m}pV#~KdcKTk zBV@r5JaxJ23q>XL)x6Vl8*)BMpF$K2tLJB%T0rD9qGOI38OtD6Dw<|TJ~^H;F0_dvDPzfI)fORb)}6e6gpmtwgyP2q-r z?O%&{=ZkpzJ^)hL`eMpg=OPC949G@%N;e# zz_Oh;ukX=$SB@ikpnviCbswkbsSuF5GSuTQQpvG>3uoi_c<{Jw>tUOpHdPepM6!LX zz%R6A!rxp>LuEM9Q9_)yeUkY_Jz2eb*FZ(<

      ux7`=TbVp7QmHdfSEKAlbe$0dzrM*f;0V@2DwSf8k`pd7grFeqF6&PW?H;WkfLUgWq=y-FLh@CCm|9`yH( zF5i8O1=t%)R@&-I1wW4Ei*%R+W00<3bU|p(yjbQz*2PBBuNAVcD!;Fn*G&v^VbgR% za&#}BV&|%GiOW`ng0P3U4q||_m_2!L{zf8CO@VE075?oc7BgPC9Nzmh+GWK@25fVm zE<_v$p@=O3ZDj5vV2}e!1y`&kq+ta`_X3daR^O={C>rWtpZpPVF<*s?mi2Ro=u$yZ z@$hP6OwUpcjyc-Zx#!a(`ZP)>OF;m$NmCBf{a=h^iYRVYc=7CzB9lnXmvf3Pw7hg& zhZz|@X!RpRa`AjHO*-V5T;);m<4N9(Up{=N**+C9HWN(b&sCSd#B_4{Ak>*|jvw3v zSoSSuiPnHY)Yes~nagkHTp(DNqyxQ1;;!l?r5jrD5kE%X8#QHRviltQa87_79HRV1 zgCm(=KrI|yjdbs1CHNj2fc43&l~}Y<-J{kdb1P(%7nC|hmR6_V_N?D(0&A4XNeYQgmKwe_hs+-8sdLKO5!#G4 z$82fMzP)fmR6;4~?L3DGaJgcSS9y6A{iAz5O>S0cVxf}S?z4O%6Mb}g>q_nlGG zbi)sza}YeI1izM<0l^AUTi_eOMLywD&8|6b{AaU<(6_NDk8O}>=W6xBSE7O(e|BVl z=eiky$#&jxHMNc@Rs;R%`9t;2)uF~h{W+u78RuIVQLe8eUcM{!z$(8iDFb$Q$1MFM z{y8bn@{IWFnhE+=@uSA^oaFndO3BJreTVZ>_g^JdYNaR(E5+aHEbMiaK@H*aC&X%? zpP#u|(%Vkl5$s0y72lTGT}V}RQ?8$~_B><3mV(9#ljOYnPkQ^AKNff%EP)A14TL?h z`@_yjGBURPC82zbTz_f3a*( z9U=XZO^PFIcB}E-m#Nz!U08u48)_DrzZccQoX+Cmd(_7q0)}huSZE;2cAZAm)&i zr>;e{@zi~(`MJYZ3SJAGvJYy0I(v4loJVYT3FYu=*oH!2Z`UQ8^=P57j@gS?&dkO4 zo1O}8kYQl}!Ew5Y$I4W6@YUO9jzsx_vFD`MH>>TEYJ|q1&C!f(g$veMR|YOUeJ+P; z8%ACFfhY{=cWftGLk9CEHmM_IiSF`G{%f_K0b9Khl8%V6gm1Xbhay!+`T%l&| zBmmlMFQp;6aJ^e!&({ESQWu0UJ2~5y;WU!y11jIzxw%C;!VXH4WYCG|;Cl-M2bNZ6 zsgVW4_&e$6$9BKH`4^AceNPESN_M@E;D3sLL?jY=tJy(qDe3}lKvBO2(Q>nY-j;gS zX1p?0%zy6YlSmsEQ1TG7xAD=epw!gFW8B@_w;TR6oD~HQ+(rGE`9!1*Xy|~&d%Vbv66Ag3`T(HdzqsavR7OjfN} zb#5dr;Uz&0v4XNabGIYar}Bk3y79?N!iOl|Uypgpn;O{{W;>Ko5Bwd;x%Kzj&o{UHuW)kDTcr?%#OJ-m&v`-Rsq3Zk~fd%i=(}8pM zIrz8&|MAe$9mI>k)yX{Qko0=iGn(s<;bNk=Z#Y4?=5BeZLwf3X+egC>2Xn+`;)L=p z=%S%D&vCaB@#p`71EPxVhi|(~03Ot=pirT@PX!Dmt~eqJ*kp14_x(lBC3f_48P@-p zSwNo5Gn)tw-!QBfe9xO4ov*`M3DX-&_{^(pQ6;s2$4c!ZRp8NtT?_ad7FSETwa+mT zAtIU%2a(1)v;bn97Mede2V;7g`bhDLm#Jb;Z78N-X6$OC-4bp7+d1}$S{c?3ZTj-> zV~5l^*Ri_4!GDH1nTf&;r}1$oT_AJee=_3s^>POTVsvBD|IYXSogoQWu_fR?BJovf zSX9NJ`zGA}ge3py8LfBMf}L%|;-7T6sk{#*ByR0CVu9U0j-MPlS2nmjXsC{FCB5S% zysPUi_gb`2k%@>#<(H3GVB0r+t;~MhEr3{tg}Jv+w_M>RADcPVeZ1PY`)NxzP(m5S zJ|AnO2w#pK41Z})?|sVgOA_%le}XZ&+sf*>(`)x5#SXu5(wV|#SB7^&?u`!svgGq0 zTuexwW%M0ol(@BIFzAg$MmsTqs6W^|fDuH!K>gb{nmd*!!XR{knz~!Lfr|_%i*qmp zNk{J}p5q)%nh3(nB-Q8g_t0H>G$xiO?n=JiU=hl+lwcj93|}ygpWz{Fiz;0MV9NcQ zc0s4ucJ4IV_*-e%vPQ*N$ZH2JH;8NWaV1a@WK<50fq>U zhnxD0pI`v$)m{16FW|VlvRnjw49k}a9H~*1pd1_}{t3ril`iXUJm`N`*4`l(aNMR@ zKSkBLue+55WmFmYdWBC=&j^EPGCkIG6sQ(S2+AFrAho3!+mA%)Pu@_lLbNCdp;3cA z30)yw9*y5iNZmwgv`}(Oe(oj4pS^I!!qQEhl_Oz_WOXzjO$+q`HWq7;yWwZLa(6dI z7u5S|pyc$WNSm?T6u81nEa|pS1S`{Of}p+6{|WrMQ%-)`*b7%K`Fx%kXqEE5hK_U$0i52k;nKo0tYPCWt;!9P;1q_Axa8hj$mwt$Oo*vpJv4K!F{(`{6Dr zXbKH~le`?>ST&hv1g+lu;dPyToxFH7lMBVc6{C1R`#R_o1Ty%gWkPxBN^{5Y;&W)3 z#!O&Pz!48{+Nc?YzL>laN!hwmUtU1sY!zw+()m9$tIKqIymi#?_MsxY2Hm!&=nDNH)Oe<9 z0-sv*H~3AN96ZiMN&UK9^Zn$2Y&Qq302Ia}pf8GE0aP>XFOawbPtJ zo*<@e>h?h^lZ1A_%I}oQt(_Z5ps*(BcWI_i8wXksKu5v$@ukplN0O)nhtrb`OE%cU z(t;TE?U!%2n!+#U|KzRyhj|EMB2}y4V<1i`G5xY>iRA6Zu$Lv zqJyG5U{~3<3;5E`79W)5s5Jhlh=SgS7K3~E1fftk(lNR9RFu}&lQfmM1{%req1-w$ zzaw-N>Wmyfl*x6<;rTqHQ}yZ`nX&hf<2~3L9q@0bAh!La^F&#n+Qvj$$~tBuYOCZx zS0W(rv=AuY&@|aj?)OEjUc-A;=81al<6oMB_QX1d3a8dU-sA?Tm;#0o&`}jo+qG}% zJuJ0&g(w^8l_S~CD{$zxRPVWGFfyVz{^k8cyoH<3?PNmju|(R43tK*Zq9RUX=Beug zrNE@zErlz2W%@V=-Bm13B#f=3j8sEHg%FM8;8HORB_aX!tf%v&vgfM^RWGLaTlvU= zy%+N2HpB?Y`HjIbD~}I!1;Y!>PYvFf8m$}@Jd^s!L_t%dXzN(q{2eSU5+RS*P5f8O z@Ak|+n%QjZ_E1lXJvv(b5WQ){e{Zi}AQ>vRE`t@#H~4;z6=jc6Y`y>ld+yx?@DJ-{ zps3ic1b9rx;o#3+@_>F5om9UV$t|AKSTlv?Nh zs073-kU@2;o2a}eYHBtb%X9vWiz$jd>LOL6KEB++K11QFh1cPPkmN>V-IE*ECX@z0 zklJoR9bJREbJ9>^*HG4DaD%T-mwjpAw7B>6TaD8SZ9eVRq3+wi!=8yGD|d83%`7OE z%pXjpt%1^hh^5OFX}SWtmH)+!O>uiw6@C3oW>>kO-kF7m+9}bC8zLVdA607yHZ3ki z?7h{}eO}KuF*;m$qhVO4=}975tfDx-L+yyoDYmiXlac*s;Djq0@X8-5B~MfsdEc7< z+9xma;1+u7QvrVzR9l3EZ}jyI+@D&u+qZAm+;fo)IhHTOEpf8i4;86o=F8enn1x?a z5FJYS9kFiBUFp8M#uj<4CGaR7u_JUzw0a>kSY_gk&>adM6KK{%3gYH01o_&GpKS+{ zOgD1<-rM9z(c=6iGi{I(oX$8B&{OARLjE0$nni`!2NRxatF~g=DWU>35bavg{<0C( zf;Cz`%&=&@Qi+v;9?B3Ke3iIl^7q++#?ofPW=j=d5hxohEzL-14E-X z1dabr8#IttA!u&hN1$kcPgBo9q%}=z;3iBJOVsgDQxC~OSNZcYIxp+EEF->%;aDvV zzpYP3<~eJM8Qz~5WKm;x;OMKOtyP?1HTn7WQS0B8s%fNPmTPouh6D0zhUuwXubt3G zIo#gqz_c);`794ylnB=2)(m;@0txRemO70Q^{A1vdI>#Sf-8w{z z(GVp=K}+Qi#0sfb7R%cNng4TtrFq;r0b{Z2x0i$8 zu4|F7E1+XOW@=>)Lv)uLtJf$d(P_ELJuNYI9wT*D>)uX=gdBQDwSoE?YPndSBT3I3 zJ7T=664kBo5$=?;Bjfm|<1T5B{b$gw}_3;h*^8_P@=0hX!{)|`5GBxAX z3rc{)%H=j1(;MD2PJ2jf+`geJe`jFJtzw8<`&D&+b*Zyvf<#Sp2L^yP)5+DVa%AT4 zV;oiu&kG&zA2eLcst@42{_|0U<99h0_2Kj$T}06+>nllv>&5>n9DL4Jn)!yQO*Guy z0kn;w^_&1W_@qHmkplxK?N!#|{2i20t{l%ZaGNR<3h56)bC3{#7mDH)$g#{UU04W{ zrKFUJGf@cA5XJc>q4Lqz7<(toau5a+l^9+6$U-nvb@UDjsHei&*#-wv*AsI?} zx3PfNSOCSF@nb*AZ77TXa)??OI>1hTLm|YquB7qragJK+gl)SCsc^QrrJqj^AnW>i z_OGq7z~Jt_j9^KUgBHNvC9mN~S!jxm{_(5?eU@Zj%aP9}(G2J)-_yP%S(|i=(+;i2 zb9$8UBeP5k9MW{Qa{Er&Vp%Fg}5hx0?6% z1t$*pLRSTKUgZyM?DsO&5~{$v7dyQo*7&qRy_AFwGiu6uXFG=N_FEW7yorvh!_jwr zXSHvE-b%cYG)Wnyjm-q9CKV~R#G4)Iduh2I7ua0M%H_OLu(|-g42An@pJ1IslPTXt zHZSST#M4t>lMQ;?A9eQ#!>n3H-v2s&5u|JA<&08IR>oiq(ENWw<|O&oDC~q}l^&7R zNF#2R-18S~s6~qv8T9z9X}M0PZTHI7+ook6A-+$#RhPZ?E>tv>_jTuf(%X?VHKWCg zQOun>X1en8YbzGOgZb7XT8WYfSwzWVrZst8B^a;z+~-bLol4OD3b9Z0;?t6GP(Rfu zcW=9{BD4?}e0G%1mH85#HJf_5o{PBZ+C&B*wBXi@i-Wf9W;M@+gf)K8yUO%t%Xyrf zd{O2(sp8ot%xaiqO}j~bdYIiFQH$@5!>6i25?`F9m%bv_)Yv ztgbvC802@v0}S;EuYhlSPGVu#JWpIkQbi1-KF zM43t>tGVU{yqz?hu!lbNIvEfkQ+cesN+%Ea+=<6?#t=>}z7IfQLTcHNLEc@~-X|IT z7i!mwnRA3&&yLHPeh$-+5Hoz7w~VS>wMyJ<%8T~J&K`0m^NH4Hf@NLmH+|IT!X=iX zuQc3J-#FwrXR7BxyvJJ;0t$*icnmRs_|+N9y}&+cQhq>9G8LldXv7E_{4g4_wIc%S zCI+STsiFNvB4G%K1dH;BU4WYT0zfC^>uGkUipMMNazs6gbrSyz-f~D`^3^*SB5F(U zTpT7tV~Dg|+Bst)D)OYHsb?g+I`Ky;My(uwfSy~(Tk6*?jVt`C$Z&L8HhuT_R*k3) zFm5eNg8QVeFtifkpOD@d>xPG#xXhr>sLnHI^fL(_8oLgQ4@gqE zAD)upuVyV?iApiuOE5mThlF=bLP5hB(9PAOJ9Ja2=~Vo8L~oM^LR7B96u*f5zLVlu z8&QPJRa#*^+3;<*6A8?lvaijOv!bW9HeuJc0-Y2j>M7CKGI6dKk_ra;WT<$w1?Pa3 z$(!Ojs;KKcXgUokm3=b+LeDY-5h~ZOMQqq4)OAk{TJ7 zLxM#Zswqs*aXm~>LsqZHXB>)B#HQQ4&58ZA0S+DAy532!+OhG3hJ%&Y%y)WJzsM^YTg)kdw(L0D!w0u=(;m--o~EhI>D8Zf{I+{jxabWVWE6S7*O0c&<#xydt}T3a=6*PZ8N} z`&S~f!+_udqJ5dF%cvCIHOuSQIjV!}BCdY+B$sp*@I z&Gn&VB(VIc{awAepG4b}bBd=tedg{u$^M&|Ixw$+bF~DK@n@)BNnBXQsLwx&X`;|rX ze6$ea0&{$Pk()^Sp?~u%dH;M1heZ}p@+g*Zl+DdrJgu6B_79U?t?VvZT+sa=o`Mwc zB6pL&a+3s)mhmMax@(+(<4J3PTgcNEv`_`U>ipJK$Lu(GFLr`+B!C)1jKOVtpTV8A z^#NG{hVVOVd99rMHWkGY^mDz3nubWHqCbekY69%%SaV`-slx9@%Gw#_$~@?HJZPx8 zX| z07-3AYpQiSo&{(S{|h`8hLkOi9Z5De*6@R348+J z{o5`wzDdpeQKo1Um*&!bxU03_EMuhX@TSHoM0&%aK}D$Puf3P&rAABiW6h4Iyo67k z49MM~s2{jq-*9=0>LIc>9sQD9Z6}Q!s>Y=W;e`*1PGKBu-moA2i%$P4#{Yr*HTV@- z{r2=xL5o|-HYudiZj`Fq7n?@dq7w>Am4Pn^M|Wv%K+gq?_3=~j9WlSBVCpOXPX;e# zo4B;WF0IG$e^ff?SOe5<51Q@MvUXe0P9ewg`wsQ=BuIxp6^pw(&Pubm5Zh`$y9GM9 z5sCwq9U3GQQjwXeupKN3IO_Qbrv-^Bd59 zKF&D&erQ57elbE4<27U_CSZHi$ze&~x%H1eXXZ~P1g>6-eRb%k#vZ2Ul&H)Ozx#V5 zIxfXkpFX=~W~J$EFK3Yp>0{L%fPLlXlGcLjJ61eKLidj6bF0_1H%iC5WpId@jWvOJ zFasVv!V>0`ERZxBj#Bw! zlx*FyNm6J9kTk-Uf*Ya z-2znv!kheHvz~*gzlkh;*c>#tQ^f=0)HkqeH)Sg$QOS8_YVf#>0gSp2vKOALPbOHe z-#OUf15_H*!dS$3q5aLGRrjo^N2hDzOgQEfpExg16?V;Tv{>ol-KOUowwa3<7lee!i5|wiNG+6bi2&?{!*)T;ybPaoPgu;GuMgV_3lit8 zlx_eynQ*n5tVduh+r6nc; zUeAj{&6P7ysB|9XCc$JDDI{Asgs;tcp-02^;C{zE^GL^S16o4{l&MgK9A5=Kv8wL2 z|1G-yhs19<|0jAGWRZ$ugIE%Q%->%_GvEU-b^k7LSIWG^@fvR4-#4P%qLXg3;*+2v z#Wy8D1jaKM(HLQM<3YLaOaAuxurRM21ha#HMm1-ONQBzlp-;tYOV(2fi3sMJ#j z>a%eH{XKT=d85vShGaW|qSBNH$*L(m3p%`7*yD+(-s3LxImlUms$P0py{zDk`x&M4 ztY!pbDkFEu*Fn|FvOoL#Wrploh7`BU_`@Djh)F<5Q~;hFTaxsdLA9sAe2zUKFlKJ!(gS1}&B z8R?+FK5S(p))2>OcK(su7TQ3B(?4<{~iYPq?K4gLjff z4i4xMfTcg%6bSfz7ehq46uDsRTeWOg!5)Chvci$gJ-;(q;ms$#T_FOnWbg6v(bCd< zN3h8uAF+LK{b{!96M73OCi0I3PNDBBP`-amgTd8o<4>luuO>zmTB<$p9D1+VlZPcP zgEv6H3#T?UqVvdO?Ktfl;;Q{?$EDEa0m83W?nC=~#6v`K`^DrO4($sF8Aa#li^&F> z2Ntx0r>dpxmzgd347)+Q>}Quk2s`hLN@;C1be)3M{A|CKH0;10^IIcql%W$qaDI z=nRj8LptEjw&dadno+4&*64Bc0BA9wc&95w$<3YPF+)zQExmUXO5aHvj25O%qrt5qgSe@oijMz2t0$=i{W<$)tfslC^6opxGH^?sm{u zL#ToUkI#&2s$#?^MlHOor{|98{*s}WVJwITMt(7M@;KWGR7DvPwyCAsS@8!SMDlI} z__-lkjfRNBoL;T2`GU%NX?wo$D%G?wM$d^-RkmK0w5!-1alvWi*2W#f=>yoQeIJsv z69KLn_{6}VEt;WtwCjBqHakJe%O(-Y zxhv7>hRt0VIB}_qloSffHC<0{i4M|CkkW9pj%YBHEe4`yQo=O7qNsU8Y(w z0`S!y{g3(Wo7H_pp9EijsDxSQsOR!}+Sfe+KxKWc zTd-sx;+z&f3c`GrlSNIkQr}dIpECbFtDRZ*N%cX7AQj91ah_Bm?ii#)k}@UU2f!=B zA$;LQTln8%Z+1=|Kwws4fuE+FL5bJzI|@_2Tdu-u0>~FHW;$p3=2lbFz)3EAH+~6e z10=oULAfh8l@@ouP5|9@J^76qS*^{{wFe(6R@arRR(Za&=8=cV|CoUx*=4+PsqTpk zNZpMAWD}N3SQxc&ixOkZ8Pygzskdm%w4!Sccy zEC5@wKi+O^fl~@~LaB46)#d-r2?OBP(EWEkw$mlm>9|L2euKad4Yb8bp0skKM_@ys z%}TVKdy%}k8#CW^2OuOeP=N0-5;?z!ihh&3FeB)tq}h z9UG;~C90J;oS!Ert0X{8r6L&p&B}{TSejZX-p99Z2p4mwBcLPJ;_{B%MOS;l)MjDn z6TIy~xwOVOLlu0SL9OIbZpgJ6 z!2ShBSXWLqr3}}*QDGAMM6zv-s0sXs)v~OSjcR>m*e8#lz=~TVVe1#rKja0cjq3_v zf85)914iTSxpT9&JbXi(^j{Bk_6|`qyu5&?plpNsk5{*QHMI9nuh6YFxVGa2Lt^tL?4n;ko$kbVg4 z*>}wIuTs~Gvj4TwNxzq-zF6bvHNz0HiDGWIGRIBPYk#>d><}2*2&!{V0cx%;K^!bR zepsfzGjjr)@Fbgv3q#%sQ3D>}CFouL`DNPc^wbMD|1Nj7%O~_{h_oM7X*{*=sRNBK zW?z0YX6+uYs(E(>8TQ@my#dmAJy>Rt)KyJ>CqXuW3+CWcw&Bu_aQsynW9*qxWIS@e ztx+wN77*OFf27?2=T%Q4euGQb_kRkUvck9H#broMaV>pnPr&JROFw9P8D~BOJR9)c z__<*;Nd1qc^ZM%?rmSi<7c1X-%7io-yQ=l6$W4B+!o}jCF%jDN=h^q%G(C;; zub+z1stnmT1nO(Zc6Q(j7;Z)Y>{z9V5cfL^1e{wq+%7WAoB)~v1wilNm3{D47;??w z#rN4}S$k41{l@3r?g3qCj`7xY!+J1p%Zu|9s!^b|l>XwvzOpG(uAfk6o)8XHQr=W6 z_>Gc#(&a@|<>7l4rktEZ{Rmm$*@FJglr1a~+~FfhU0!IKg5Q288WS^2m>)Q$lmsZw zxk7^`+|Hsp^^van?!Hb#y$P>I2Y607I~u+Q?9qDAa14;ta8NVJSgS12M@bw+hW@^( zM!C~iO7nqa)>Wwjd+X(?yLOq>w+FfYY`^$GWW^C2pp|tl(K?7!?!IKjiU~^O(wkzE zoc7CS`(?E>D%hv`5hrK9-LQB1r{f8?=&soK>G1nujfeva=`I)CrYZEv@LODf0$AkN zl>+lmvP3|o*hioGy8NFoz3QYd>G#66WZv+u4+>WNN`z|qxATa*Kco`&DZeyi8nKMg5YYQ6CZHK=VwCG%jNDC&qN=As!IeF+fM!dZvteU4b z=F<9Uh}HG3D+jmuC)h}apA{PYCi7qw&gP#A(QM_K%JG5&PTZFi|V<4htp6NswSQKHo1-i>;erIEFDnu;_JlgM+$JysApZXE^<*$i-s~ zh0^B@&qX%&4}0DIjpk*3sSTFERqPoli8CBz2c04=5ufHNf9z!+T&-^*2r{n_0XIUy zv~>R>;M2F;iSJ7Z5lt65k4g>NE*G~p>!Kk_SQp<~z(#Pg+?e%ei3@lR8@@Y@<14Iv z;3^l4I*3F;mnoV}s-GI*4qKS*=)RyESrPIh2dcs52G=inCc>pXrp)8+saA+pO66J;xSs8F1X8*c%U^?iy?=F~ zSZ^!kg0v9A8?Nd1?%DS%(9bm#?9piT#H@_eIKg3W-#yO!NvIeOYzI=;Y8mQPGY7;i zJdSn(6aDa{22OXT5Jw51`W!52lO{z~;k5cA@^EVw*J;wkq#{z&ouS~!!H=nNrNp-1 zRyI^h?(HPm0L-}{B}jRJ&ts$mxU~>gKhlmq=R7c^b8GK7dI11Q(^sq0?g1wm5+vY3 z(8vh|o1KUBxhW80WNES;U)jkgEm-lt;B)iD7@L@(iGgQCOVLp;+(F$R@o7!bqo%X& z$uA)f&fAF;KfWhUFDPOFHUqF^Zhk{eqO77Q(JWq^5xK>h!)h+~=B`s5Ij|K;#It!* zsM0YVO8HC@IdBx!)bfjUkIrj+{Sy1zv>ZjEVAMBQ!3mj=o zxF1u4q4A!X=s>Bb@5LJl`@={m$`=fOznR|=<+<1Lv#vPtr^Xc-jk_!v>lo1ACrPxX zbTWKx_H^4tt%|cCwBQ=H#{PAbaq1qKX!$s~3it7~!C#>V8!^&C%0D0&pkf_ZAtC+X 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
      sT`PlBxm!*FoPh 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
      P>bS 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

      VDw@L+Vd7MHi4ag&RXv!Ml2h1kol1-;$IAA7 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

      muq_O&iYs>7lgPnm zO!D_J8d)}YV|k3SCB;pUn)h|T=YRF#wu84j9fGX~!7Ib6)plo(`spNgTzqZ zoDSazQXx_U4!R|d&JGS;dEI-RGsbc$x0?4O_~RV+H6JHwV%0&wDuC1VX;Rcx@phnUT< zo4U3zqPh{xI(7I3z{uQfCWTL|eQ=h)`6-JCcBsI6;c6;nhb$OjA+7^N_4#bo1;{tq zdy!uL1Y6vG?s}ceHpV8GPY8Ny7hk=kO342EjEq7Ikv;_6ZR4Vwv$2}Mv}H*3JaH8C zOxxxW_(oG4GG*xi1k%X$8leUlUc|JR^1joM1nO@ut=F&LI3e?7a~<`G5jMoA_kf~+ zp(R?X%j2Z^3)cfoK3Iq@b}cZQlvdkp%J_N zgs2>!KjXnx8)#cBlMB9ufLpA!`dA4GFOgu*u3t}a;7FQaXtG7{r$-kRJokQybA)=R z*h>F_c$wsu-J?c)bMYfTt5@Ksj1up5t1}wG3Vvb>J%z*>`b0WB4ejq-cW@oG4L*oc z)XAHfY0RHxh`p>qyQ=g#xP7lVZ18A7#^ynl7_3Pk9{Bm0PfEZ=rQ_KUPnPGH#}MrD zEoI(%k$AB+y-YzZn+$v|(N;F6v8$4eTlpeNN*N&Ul1}w1WNC+7HqzD`-=cvhX?SH1 zXm;aJUQZz1FoWcO{b+$yYI(~xTp zG!w(7@L>q~rQd5umf1`m-RgVvXW77;>JiGQ29i_*O~6k#8jwi$SCb6VL}cxa=7q8L zcJLhdfW8V~d-UMM?oBuqHkfVFHCY#%pi8y91CP&E8+&(sw$Eez{g3Y{m9rV8UPWPw zt^LPJoG`ou$ammMeusEeCk7%Z{lTr420CH*IPH1u-*0QjmBncXdh?$>?W;j*Bdp#D zE!g{-^=YH#oeZS|9Yzql_slmv%8>r=L{FIL0<1g(sLae*!ggiOI5rN!O-E(t(zM69 z!_>F_;K)lK^sP=)y25&&`@%1YzjR9+jT3AxX z_9=~cAkQ4if<-)Dx?qe zS7NijFh_q;WX}b6Vy#Otg84lGSS`^1JE%f>2|5@Qb&5nN9sN#!Ev<>7-y6Rz;-(fW zcV%ZK&cxNKxO#Dk_m#hM0Cn822C(<}!p=5~y3x(FSmJqZtxRe$7w8;ln@CyYNQgCW zBHe8sh#-_y`2*|lsA~ZSnJF8&CbZ$D^($DoJEhx?v-5bBgfdFuD4h|{OeT;fwJYYj-~Yp)ku0VbVbYl4GT z&1<47!SRKcxf|#r8R2^4Km~r>nLfG91)92;dM6w(V9rVoIqojUUi{cv^ay{5A5;;H`as`;QV$r+US53;s}L zh&T6Ezjw$DYPpRD5Y2vr4lDp-g*Y4{uBUKN(a(leEIwHSJRZmrRRU=HnNKeMd7W)={ zt7+C+%W@Q0pWmPtwl4}wpAes7_{yk|f?^^~bE!g9Ufi$rH@lzb`RoFLR;GDwc{Hrg zUJku|a0u%u`ETXTZShV8E9RWhA=uIv>ZLO?^jgbBzjV1f1zW(yOa{-Zk5q z%uU7z(vglY{I~b38c)xXhR2QF&k0j%3~6g-wFVM$u4Yl~H~M{->AnGmR+pq+$5+5D z_BuUwtC)KW%3?(J$QeF~_2HR|zI@HV=rJb1w2{nFv6dvIL%E=1S_D7c(s}6VV`QnA zHQh4JH=y^ld&RESi7>})Osfw~JzymS$-{S62W9OpI?dHkj+#g$U>7iOt6P{8XerXJtMbe6-0%O$P9_GLPVTmm zUQaABL~BApSM3Y079p^JrShGPkZ&cKs0<#0)HdcDKruB%#*H=7ezO_M5Cq9Lz&AKu zkDqR28o4p>?A&u;94|3;wx^W3K3fO08}$}TBNp-+YeS6~Zo(s>OZl6wF&e!fWObbK$Hx=4jZD-voK%lsix$yeylrgJX_qe04|IzlLi3zOfVT%SA z!qop{$L04fN9;P|!~uY;q(WXZ09DyhAHaM;SO!hn*8E{_CNkt2`!?RLfdW}Dyc}2R zCm6E{Ty2ri8>aw<4#I{3$NNw7f3sYJKLUr~FWF+8_V@fQms&#}1Df4}OT=10nFBmC zwuhrNAH;ON-*fOj&jQht|N1NSK>`o#T)oHK;vxi$=C5m&6&K*-NyDP21KJ`R-1I84 zzgKJ$2B%0oPtR7KGO&?*i9oebj0u}z_9SyUmIDUM=kr_R&D5CE}>*5{4}ebK0Y z;PE~naA8SzzqHK(Xu}`g8c1Aw#)9Wqg(NgKHtdwo^P526{-O~QUbAJu6GZS{+Kc%c z0y?9{g$Dl{5GLe#t8knS0EAiX`dex^B>74%HHemizOGT%>jnDE4D0s`o%ku(dwA@F z!o&W?`KT)S_*!_`=P}+S!V}~v+cwGjHBi5zCE2VIP#oh0#SHsNwaXL`fBN@2- zAKsPKN@MS=@gjnEaB5M#Kn}SRV+!O(>^j!8gud=)eed(80;b=)K|eV2vmC|+=ryEh zQYELy&DtP(Of(Y!(?`u>8`iNi69Z=bO8`g>#34y#;Y8b{GPyqAhqn+Avs~HJ6}HC2 z`(E5N=HhRlc?ZTF(;N{sLZTR}MYI^zm0yn`uXX!@jU1ru|Jrj+Y&+Ip zgDy5K#i%k0m&TyWarZ_v_p?J!enKs z+%`+NW{3KTMyL+|Z>-ui{$7vdy6izn;2i$%4(H#HQ1guj7ududGr!#B#GgB|h&N)Q z$w}rSMeK-wGjm+2knvlHN31=~cK6}Wxwgl5M{BX`ij;Ja;ad_NZw8!A1)1LnA{ir# zQAKF!F(~U*6rK(D?(A`WG`b+1EmyUWiE}gN4UT-^5A!&Pu zu6mL}MVBSAwSQX%$e+Hl9p5Rd3N;l?^sO_WBskJ(i|XM*meQSZ>0$xPRi=QS3(tV8 zjh3n1HCgbKov&YIe`g{XkmJ(Y4*BE$FGU?`c!Lx3UfmkZ=cAw8*;V}{;}#Ed$&h9M z16CC==bjdIehXwl#8V+VM2&vFY$eg(c!jX$9N}~8)u0M1_M;$`q>fS|$4NZ@wd{>v zgE>jpL*e$>8Tm&@rT@W{o@cJh4*v4T`-^nU-L1Ik_g4e^&B%&1z}I^lnmZZt({;4J zzvf37?mG*7AXb=dp>rVCrWMO#y{dRPt_>v zbPi3<$3^_0?yVdDZ*Uf&VPG}L#%zled>x#}R{p}vi+N~;7F@x%u-QGdo6f%Ay<3M@Rx^_Ra&%B7 zxvH}dg0)`ZNZ0}1T(?S*oXYzMI^-jMR6@3t{CSSyx zyP+@e?m}kU*OxIQTCe`n+;Q*(0JX3}TB%*3au0`Lb|}`r zF?gLdjRXiCrGuYin8~x{3X(m*sR;me4T^V9H2>^z$b@Vf`EI|FA&Z2BbBs zEq@NJ_IFq}*tZ6Mt+Dt8u|Jy^tiN4P(bH^@6}ry`QY#=gE7DIEJ~V|#>A_=VbifJy zl=_2dN`lU8Nv_sxhO8pE#A92umg$6mS^*quHTm%yHf8<3t83k%RW0bzA&gY}?D#!Z3a&Upfy3r}5 zC_B}kcBL42cy^r4VC|cQ=}ZECf~1f&7$*qw5#^CrGe=&_${Ly!jmakpb$Mx_=0R@} zBfM_35po*KZhmlQ zRU=Sq&{#pYy37NBxBz=aiH}m;>x+;0=lR38^{a0t*<-W$y;ZSf=W+I!eabn;bm_G5 z=FLwr!b|J--$RW}fi(IiH3ItI4hnc`(KwZV=LZ0wXw+`oU@8N~Rw-Ws;3OR3uNo_b2XTjk2EE8CFY~KK!1M^<$)9O@6A-jacH7!sogPumn}c;DpJgD9}@c zNZ_s-*BH@-_FGHJGv!)O*anL+-odO#K&0ebA=G3rOIN~+R@1Le6nYv6#Els_o4V=6-7`*O7-pa`lselgRCxf zfE&Bm3F{td-UJ1m4dcbbYnNCiVqL`GGu>uw>e9OTTSujZ;{923q2^5G=0I~9YH|Yt zrHY(D+`}FIl5*;J3!1x;ojFj%igPD*zwfF}X1uimY=Y;Egi+MFD-Jxqyq&cxSEFA2 zQ?Ozp_&UBg1y^BrDdCE1*5EEVKw`m+f&hMX)3MfN_7{T}27~Hgi_%Q?C%x!yEQz(- zTQ=aF1#RTnc>LgEhXn-J;_NsWG?g*yaZRRfHw{hpz1Y1nriOU|>}z24rE2%Q#aDJT zD0wIRsVSI~jaa=Ad)d7pv2DumtsrJD1xy81rrY*qsj<4j4V3+Fp z#lThtUq(L=%PI2_QsAj9n}X1KlXUx9iZRO*Q2zU#W^RJk<_#Fym(8 z2lR6nI>i?U$s_scu27@w15e)rA2k@X9{dWF?fn(0eC$N0c zF9Y)s^KA)y=J>+#mEYRPIFdauJ=iNX3t&}lE(?9U1%eHP+|a@C1P`sWR|}oe?)b#w zWdIsdPZ?Y$NbuIh08mL}duXDyf|_*tx7UNYsTySL%~O?k-L4Ht8X;M#hHu=bhd@if zOpnNkY3*E8l4bm$m0g2^oQRS zOU8Ksxbob{kwRLp$E7y*dHJPF;g=BVswR|_Hjjk$nNfg^aWz()g`u1c)~vR@Dvix3 z?)3J(O>sA=Cv^MkeBW&VyOecLiyick3)^O~7SYu`x7H~bVY;6s8(g@hsrq$oMalP} zVwf&LXl#?+vZXX>f;@(BQ`|fFY3VcZ{u}=Q)+AS&{@q-?7?M!7)mSA~_)BF2=j)MC zgs><^WW~J96-H#xYdD~|$pacx`f%}zainr0k3Be~-oMTQj+w_v=^Gv@8t-tz_3IP> z{GVtlqdz;O;+j6ZUA;Ru&5ny-nIg@oPv0>i=G8h#c>WUQq2;R=xw1 zdC~e-q#x&9BdcJN{ak74Sgh^k&WgbmpaUHYvV{M4Zy9cbgjXGDlRb|3!6-jC;jBO? z5`njV{+zek#QjfUd>F>M8V%dXP7zWNB@-IV`G{bc2JqXUJ5BbSHPEz0lr8Mb&4JXI z%IhCqhq=AI(&m~XI_`4xx#Bn&2gG`pPScT82fwj9=E=0&QuxL5L4migw1pWY9>px`m1lJe9-#^^PGYT1-vb2_N29LCzlLnp$9Q6E+*FV0}rnm;MtT2Tu%3nzO zkC|b5dtO&=v?mMj!3myR6<9_d%Iw$ZypQtW4F_}9iqPOa0Om_ubh z112Um3Ks9c`2f7LVB-?6D2$ln+z>h6C=hvoLAy4f@OLbdn#Iw#ng(K=o*&L6gAYUX z!VN}sCXfpKge49;`l*slO-U)Xe!ywxgl<3o&occB+U`;d!ZZR;&%2+db>&^c4Y+^& z4rHeH#E{|OR7ljb@jLj;LB}S9htH0zzjLj8xxL>~akO!BwaluMo?(vX;dyeF zV$i_+8AtyBS=D&4Ss7jOsrYhe&rJ1=A(-V}NSZ98Mlw!~40AY|f5JpjTAxtfYv-hm zpAe=?md>gWe$3o2I-pN~(O4ptVTd7L1dxw5mh_+=mk(lMgk%-(gB9~(9cedczu@4b zh;<6$K{aX^!xcwfi0)*OoT*dQn`LZvXRcMd{>%-1x!lN2$MyXQ zym*yjeS@L17W8*%r9zx#Q-2IhY(6j@dXWazJ7VJc=Hfdxs_%DE-IF^ttP-MDjk<}d zXO~COq2Dw0bj*XT#sU2(xB!~6x~9{E2$NNT9yrF5^_OUc)UCfdhu&_g4@gpJzV-dy z5BtoGrPt5o(DP3 zE*kVvt!-exPI(>A-UineWrA#%3gyE%cU1C_?Dj@EAmxIn=n*j5Hz%)4k5{D2y5sfL zkgtE{Zk-RPJbQc}>&_T`8I6qBet;d~(U&Arr1FE7v#b{87s(sXEX-`W1WSp0{I^t^ zz65nLndpJtXUc-;JE5Ct5iSK%q$7$FB6_!zPXtEZ&y;g)Um~Hb)65dT5I<10?sdK< zohM-u0P591-%gUb9h{}EB)<>}Uz4RtDs8%?`_D-YQv|Rnu+Fa^b05Yyr4~~Go7*^k z)RonE2MT;x;Sg&DUeulXTq}I%LPFKBUcy2wUkZ(C?qS32{DrrT^`BpT0RcyaA1?I> zC$6`rv>Igt)(t{Q0KHX)GjKwuuyH)~n2oR8)IsR_7+IYmIj zReQSfN}ULJbH3cnZ~^KNSm%RbAF>PZM{o84htT{V%Dl{fwtG)8=$fW~_vQYNqw4^N z`v2o+Z_eJEIz`Ajd#{X0CnKWFGEUjD4tKIi2w4?6BTVxUE_nnjuKH(sG_$1f9k!9wWxVHHd+)vCQ{3SCj z{$X?W%S^JU?f?8ab2T6`Chxy&{Ssnd4nFsa?H3Emn-`M$eGi1`=16IW$RdZ#V?%M)Be!T zcX1U6H29KAECLS4cQ4GMZhi4t0rlhGOh!iek-;cG-<>tNL`#fpqT+^pQCjh;$0$we zB;HTN`eAJ@vm_t(mpaou-If1nFRKH+t8mko1Q&C;KcU6pm$jcI^FEy)v9PDDfZ%`VnSVB1A%rmU4aSJP_Y-)mq0?cJyT z0f?2jI~;L$_CU2`mRJzaV$i>$SC}%9!vOsK8^h04xZdC6zf9?H%ofqjt^E_#Ik+#L zhB|zo z>?^ywnI8{p8vcDN%-I!5WH==}R#Q>5&B>4nXdL$!jos)y ztk(?@>nQ|l*%XrLmF~A^-0O+X4TdZyn7%W?%I;r>f8J~n4lfm#>8}jA`0xW7&UdU_ z%NoI~ix8f8QarIQzCmyL7w2XDMm6XSh)itg^Z#U{GPsi5-S<=vIf*Df1a&JH& zC-2oX3=A*tRsZqK0C@yJp7UXq3Ol+AHvjExJNH`af)#RiCeW2=Ll8WlrOH^3?HN9Q zRnSs)&EEF@iQN8e!br4U4cL`-)*qZ3fwcmfsUn=zRxj^Rol5`*o!0%Vk!MPNdlqTV zAP%I1kfGNQ<*4jrX#93~HgGJpSenop4FJ__ko#kp7HgxC%5Lnf21Kdg+e0g&U}yqP z{gf+=0G!JGeq^)9S$iFnv+f-pVR$S29~`}Y#yEap!+VBf`zS_lR`!;Mp5K z;29X4jwfky9O3S5oI1$-qE!_WEmBluO^*gem6lF7T3&qiy_6;dW_Mw8;} zA;cn@I`>$wb#zi5B5TKeRe~3vIpyhw&HiN{y_UjmhKRUcP$jh=@wx%aqqq}3eX5r1 zqGa%rGBPB>rP?#tZj{nnO?zcO&x6>-mD13Btm^GGO|h79N4b~_rzDK}8C}9GX=F&W zmm++_5-Q3_$0ZBNor3r*Kib`T@mk38kV8ErhOk4lH1I%}J~Tb(r&~)*Zxp#Bx z(L58Wn}Vl`d~(2`A9LEfn`trwGEiHZj@}xUxCN;Tlt_(}Nyf}-&jYO?Iwzm#{T=$< zn(Jnfoa}CPf_{f)#@x}!L1VoOb`j2=oWmJi#>m=^#fxmsEAh1E^V%b_I^Stb6o#N| zj`KQOa11Xctza{VYog>`!r)hG7z4ydIm3=a|D&)SQ2NIakHU zx{J%F)JnZ-G2$|-61{3`r>=w)?0lJsH1^iwqXl z&+Y}QC$LV|vi_VGe?d$ac7V2n_^x{}sug^nPwZ?bwj|^__P;je+!tf5XF2se@ zkU7hg0lgrQM7)Kf#6L|54uR^%jPMHV(w8=o?9FmSt%yCgiCPM>dczl}OD3uj-q!ig z1TR2E;)d?JqaD{x|Jrd->kc44@Ymi}suS6QdS@E+ z5WhXJ=0_9HbuqQm8c^pkf|_M5 z|AgB&DrU$?VASxrD`gs~F5YMI=F#I+*A!bf z8=m7%i;Q4KQL+p|OoOc>yjg?iWYC0Lu7VMxIq{`fT=$DJg|bV$Vv%~Dwz=Ql)n}kG zvwQ^vMbvp2NDAlO4a`7a>Fm?Eu6V9eX}*nP z#F1w&Xna;S$fz|7(T?8WBeasfXzoCUCBb)Q`43ZA=o$t7)-`sl?0!tu5d_1IzbnMM zA)3Hnc;h+@OP$C5$$IKj>+_kmWrkUa%GNTaUQ_mWFus=l353dLpRsXdz56VaNfPP&-iiR7`R_PRBIvWUmuSt{BY~6M4GXDOi?F=tNE+Rc><^eE5g$*Gl#`y+QLu zx%9TAy@)&0J)h-vg!Mf5Q&j%5VIkDTbRbRk#V>F*K}(&cm?}^DgHdpcbMa6$C`t!v;?hUT))ci_Kg{! zK5O7TiaHy369yD`Bt0ngy;;j@XW`6Jf-iDWNwfp)-ee2~@qit{R*Cl(k>il~DnUd~tK?=SQ7iPg~N%Tl-|IsAZ@gEpi?8 z?r{O4!VQZSzs*Rh4~j49CK4SKN#1=L0L>#={+SaMdnBGqPL1daA8rd-5?Qp0!18+Nd zoIyf(`iFw7xZ{_}(#ot!x|35yz0_?c5B|-RA4E>N`b@zdwoAT1Dm=3`o@qr0|LGRi zPcLpwY-nD%dPUixc3a;3jv0b1PUX>wCSG&g>zR(Z7E=t|BU7s41`7c~^e0w=L}MF8 zimNVsoFL!)K+^1$qQG^7IZDaq^JhTJOrpsmSjH7W{%)NuQa#1F8bChWJ!fVtly6E%6@Mtxz+6h5sQ7(>R++M&ximfza%``_vJ7ZHxpRw|k zVrh}r-|9QAvcqo;Ppl&qJJ3C?%)*-%pi3c1}g8cb4fxqQLpSvC<)cJi(%HRXn@fX9k|p@?Uu- za6DwoYW-SOQq;1#cT!^Fwmb{^roe<%@7P-9!QoHQuurTa`S5A*ke<__K`6Tm#s>-v zCv1i+)q)O8b5(ZL^)0~s#}m-&1VNRXtp8A}ae!qLd3T*H(zy$WQ3tyY2p9-0E=ig> zQH9XKu6<2bfbGzNM&0(4i|nA{GHQgi0Nf)rhUiMkfM6UGSCanoN#QXG!5p^gb8?hR zMCZ*wO^vGhC{=Zgo3)t?G{90-FP7 z9dY|f4Ovelak6ZZfB_T8?27*w76YdqL;L$BquCw&>OswMO^vG?gtDlGeB_jOa$T4- z@e_ZyivBX#y^pC4IRs2Nghh=Wrmz*4a*=i91c>SM1lN_2Fqp&N35)_B| zQ>bnxE(l`c+ae3=#$WQdg@Q`(45x3SnW5C=sDp=`UyTiANdHQWKy*0PdTg50o^hT~ zBow=jU0m=NCh5%t(noc1Zm2iwvXQ~MQFM$Tb$pg%B8LHrpv(3W+Digg{BtGft=BOJ zF9$kwEK4v*KZbO&xct(E^fp_=%>32kYA~qa|HCe`^KESl(d65-;KQ{IX_kV(Q z;C!3Pa@4!P#!i;5pj1i3P%k?=mV}{xxP5Wg_6K7KLth#P)=?900))q%*;7xMZ&9xQ zYpqfqY#^b%@@(E65bq8)^s-U!Zx}aVU=NK2tcRg%mV2NEppOxXwC)7FZa`dOHzhKW%hS~B_Tp+yjhj~OjcC6{cf@9r3vUguET=&UuUvtu; z)Cx!jRr6e?-jK^G?O$5HC9e0tdlU6U?#G9BUn8j|KAdHvlN8!X?!=SMP~OF(hxs3# zBI)eYKs0){P{;f{XX6Azr#1twW@+nddA5|BW4nEiQ3@;F#$UF6BnYAvjAbG|j3_4Z zFQWi!qtOrdgo{9WSq+vz+ zDNf&bi>nb&2pRK#B`m-z#W)hz7P7e42mm z?SaqeZ+9+jXnXMuqv+O8Lnaiuc|#j+=)r&$2VY|IjIypS1hc;86mJq`ndV}Qv!4dM z@|Q13HFik$MaqJh=i|7cwcMvXnh1pNZXiR0dg(!fXxg0GOF7=0;i6O)IaQU(qATyx zL|Nlp1~-s#ExWK$Sy)e6fB%CPb*~Ra6S4TJ?A-e;0m)kdId?~VAFjS(DJ?8DmE$mm zb};Urv)YFr4=m>>G zu^OQ6efHnTQrkv+B;j?rBN@3HK5<{{o=Nbe?6(5E?D_Yfk8Bt|mY*ERmodp;7xEBv z9~W6sx`?OmQ1MUwZ{EO)_jrF*UnIX;T#xTjnscAoOr8y^h5u4gXS&;wBs0FtGp_pl zq>;eS_toFKZb&Y)xv_aFH?Mi}c*;>Y_Ltzm%S1=(?+tdI4R5>jELrj+CScjYW1j3e zDn|a6CAD3jvhLE^+p+F$maMvZ+_&^kca- z6kwh(pTnG=RUXxL1clvrb`$*XM4=}pc~=t`_6oTzg>T)`rW7o%aZX(zTy?A0b#cAd zxl8(XMa<1kc*hRxjY$o1w0QEt2=Cz=8$L9eEIwnERY8q0MJsj9K@3UA(lTO%^~0J* z{a3D8x%UOO=#ll>&%+K?t3^;S!_HmW>hdo`J8F}-jP^EGGV>WA4h6UDP#4+YZ&(~p z&b}(Q$LD<#^EAQF77HRt&|r|4juN4kQv4P{;EcEv2X}(tOv4je1IbNls;0#m(O^<( z*>6yHkWwX@g?sRMJNk{y6F&3k4SeN+d3yUdHR6!Lam8etXL}K9s-Zt;jPTD!YW^h) z^l<%ci7K|GoK(#?%%9!sNMT{Mbd3OY%ki1hRU6?Gs!r$4d@~>my=7Z zB*!w|7p_UsLpp|4uejbT_#D|_TiE%GV-74HY{ZgP6+-XL?(zb^MnsGJC!T?a+YNoh z(Mx7*irD%Hmp|ag3(6~~e6pu!TZmg> zt7l>qn?`Hsh@;U=2j$Yln~=*oZI<9z620W9>E{}`?VShQ98H31m)raht*q{k?o}a& zs=Y&`X(HNp?nYk}5|(fBKH|Emn&}we5HN;zX|@&`xHF%l@7BbajeZz($O+22ItbKY zSv&iu4j$oLjWEaN#`e84(V`YIvdHmu?KCG29F^00355mQg0T>PH00{Q_ZG(*(heD# zc967*-rOh*ATL0WZPvv&A8Js7yC%xT3RaUqH%m!jo?)ITdeCF*OJTucP3;QTWz%1N zbHAX{s(kqAi2!l32(?3ibz&s!nuxVKg;|8i_1JqfSvV?E>qz&2nT^pwlf_*5^&8K` z6-fO{C^oCKk&~L{euEi~E!-XucPo#a;K`5q9?)C?sq;Ss{db1Z8xE*bFiI=h0eWWM z@@;7;xhx)x=|h9$`BN7}pDP`#)*>(W#;*gpZ^2^$9?X;*y5+yq`sHNqs_a8RwQzLZZ=0dDs3g%B6*TkoTUuIed4FOM1PIkga%T~gQV-i zDvSmAcRYR+w!`AX;o$p}YS@LsNmpSI(pkgdUy>{UM-@aCzy?hye0Yd>f~rBuEq&h7 z?7C%V5v001{VCmhPm!=V%)i6s#Nyi@Q@78Ec{+Hu(&cZ@AHiMto`u&y;PlS(h3{Bo z;eTg%eZZK(qi=Q3dT4e}e^4njVUc|%NPcG7WbDZ&^}I(xmz*jC!im~&990}xL9WLV zGgy`+!<`7*XH{g=>%x*Z;RL~7B0t>xN80$Ng{kis!&NrS73kuV-fEVpYw?gnbvS1o zNjj;2Z$Lg*PI$T|n0k{&ILNx1eT8kA4YRJ@AQ^NqjBW*QQc{36srPHkw&&e59`wS@ z>6z~lzll~Pt zYtJ9QI73P*1!_lV+GU4iSxihE{ZGJSGgm}f;K2`v0F%Bz;;s&Ej+bIljnr#{)@+I{ zlHc{Lt4NbJHw0J6>1*@HPA8G5^L2eEXZi+Zjch&WABm8)jY4I+zzsHFX8jbR8I8>W z15L7^qGVwjIVej5j)QV+EWPc#E`6JHd`ydsD1XPcRr4iZ9HG@K zlp&A3)##T+ABLT?Dt!(fSj%5<&@rQUL8UUmZIW6{HJPmbU-<^Ii1e0Npe87dy*UtC zf|;EsHP4~`)F4h)6I`bmF8iOfhF)(*C$jbK#3)AKR0BjL}U{^ghSS zBfs3&|7U(IBa~qdiaAto$?kRZ#iX!SgxX10mAm^1lqszd)of+?FHvdzd7ZC$(~~8L zyzQCWphH8w_vRy7tLG64m6WLq}2GtR}~^ik3>M8k+K zNTwW~`blvNoW5XXky*;j65)m>1M$!`+9dDXX#*PC9G;{0=OlJS^o~|k^(4Qyx%ki| zEe)AoTG_oDo#e9AzQlh~$d|943{U#Filr9v&L_D)HK=6z7nakX-;Tx` zIvc*=j{99zjy$b1sE_hlZfK|zzouY<>a=}skDhpcxO4Bat*2(qo~1q1nym+04*H5~ z<=;$wHJ*F*j+@)s+!Bo+m!-38)R32}VAsv_*1K9#+pzxhk@6e4f$dsL??!2pCqpZ= zBSCzU{A$g1Woe)8iu*}Wb_e?%hT%7pYgx13xGYbI$1}Lk@QRqI{4iX8!h6*qUZ}7` z#XRH=aAMqNUN4g2TZ*>mR=?OzUKo9FiB$=Ad6isNw|3_PDigu+Hn_0@%Py&LuleG^ zzu^bxh^YMi@c%S66Gp^mhL`npZn+>(5YE$;N|gwr|4~ zBX<&l0?5}Ql0w`Gab?7u(llMCXSHoY+(Ge~T3ixrCuNH%S*VOsg61yWY*1>4f5XgU z8_im!HlOC0THEVbcc>}UoGs>|k}74Rh?z~KJl!Y+dBQxUTG=AUGtGUw%JxQJpA^It z>J1K3V90*!7Xyxkq$OEHIWyMRaJ6qgy4sDV)IBtYwon3^auWUO9u7*Xpl~(76UNC6db2_t57Gy(Zxq#e6ZQlbk-hB7?KtaXPX z70I3+^B|U7A09X%DuRd-slj0T9TIRZkv;dOh2n+RMh;UDbk1FO&D`d`^_<=Yhn;|i zbtYgyX2=+$=QJosnd}>8g7|JtcpfAvQ=+2B+i7?dt`~PISAULjv;t5)2+9W@PvhMT zQK&O#WH>~^C}D94XUr&#>KCU?hLbJz(~Eeg-z12>fkC}sLaqFr zIc1504oe_dw4=6jJ;!}%+_+%bNw7WZfT|cX-NK1$6_md^F|ck*8`#iz{6`H+&5WO* zisjo_JWn(dd7=$(60DYOb8G_UY?R2J1DtncG?CaB!z|9Prk%k$_D0SB@`(5BCVHjn zw*ec*+1!|I3Z)1Mi}MPnv`+`5BJyyh<16#@v3ul;p*31C zLOd^%tga6Q(@c9Ef)0Ur=yT4O?Wk=ow-~fUmT~`eo};X)Hiv%ihsob&cS#7dEE|q= zHf*43P%|Z6Ud^^ZkhDXB+kbt8VR^5^OzvQ?`sj@QWsU3dfj;FfPh9s&5uuf1$|wG1 zPv)5Vec?Wftglh)t9+;*d^Ss&l8hZ{zIaW$d!2X=Fwg=7FN8igNl5r@Tn^G&XZm!Es~D0PtyVCT3bK0z3+=<^2tucczb2_66Rv!bL~bhXE&INogRNhvp>0w$y8C|9%J zlQuM`iQ|?>}&3B z9?d6`E4NJtk+!@tZxY9Qb zd#5V21z3MXle=r)&Wo(LuC&IOLGy7CfymNxq`db z%t`FzEob8#TjAzI_@fs!Dn`&i{i7ZVSaDw#uU}#@QQI7SS`qHEvXnT*h#NHo>in9H zoQt{^!A`vP6{|Q})%D$ug~7XkZ!hH8#yt9ZvoQ z)4)RxR=Svz|88#xpWqao2+@Ey!%MhmaVCrvCb19YiYGxfxlUQ_;)7&!;534 z=2?7}9|i}g(V)uhmB>Q9C3r_I49Vk(;zeguJ=nxbR8dUJ(U? zC|FX6)f}gM4~0%4#giXJi>BeECF;@Ple24aD^7Aay=)!IQ1&>y?rOu}n+*%>`XcUd z(2u66=DJ7bp>aUHwZIEufL)l$@|I0ss=hO2pYp+oQ*%6NnIIwUOyh8$*G^&OsZH4%w!pAfxK1I%=MNN`>5hNw$one9c4X05FjXhR_c)SW;pmoltI#9iTe79X z{4;^jq^N*PKohFImLT42p*;3W1nmdI9sD3VW|lu7#fdeD!vU`Ph(|E5BWyonZjRRp zr)P(tBw={70om{Z_Um&l!)4*e6sjQC;q|!lE+x*z4=05b?4kzo*Sn+PD75?xoPHuF zKq^?9lDLdH>}bO~^$M7P+ri|z^|OO}4D|LLX37xf1)&4j>>w@8#6qZW7xg3#jY5{jHC{o* ziX=Tn40ml;_4wf*Zng$l8dWFM_pY4mD*qNpEQc-A70d1<)gAq{<*ExI4dCw?@A){G z^We%{JbT^wmM|O@%`Cc%Mo?Fi+GKw2z3G;r-EdA-IUT02J)mvv^1JFZMf6*CZZ0l> zkgx=&M4{`ifk28u&V(`s;3Jc2tSbt#Mk=oj~WcSI$%_PU&*j zdRDc}-mM}}Ns1rbH-~h-$7w-F%$?p6Wb#C_0bfB{_tZCDI>5e4ZRGY(}}XH(Xcr zJa5E2z|6JCti#Lxm5E&(tf&82H`UqEoXjhDyRUY|zv&hxO7jkz$(@X_=TCQT=9w;j z+Wbj{QA#tBsc>VaXs}aL4PhKGz5Qf*|1EmZp!UtR_@+{IrJlCVcpbxA3=@7T*|}F< zuIT!PoZsmA1;3F7_e0Os_2Q|cjff9n261WUTMU=d>vS%6GJcZ5ME&euZMaxl6wo#a ze_8Y5JkjrFyt7`LoES2Ocr%r9*V&%oXHC7PFr(ILPV?~-_lpzmYdtq5p9EX5l4Uv@ z$^Z!BmEto&$qhBs9NCyD|Gy4ygQD0825;oW&UGOpYM)^3UnfI`Tx7At>?qjGPS1mx zD%*#$%9uf|;~jAzvnQ%BS|-nNxjpc)g&CDC4|bKZfz5(|dT;=_XFQZu)we?ks9-t+ zIQM$hQJ-^eY*rC*MIfX1BefZ7YS^JVdOqqK_bNu!oP0hKsMC5OZrS~v{nh0{Mvu05 z@MoM?LP+-MZ7CZm5yKO8f2o~c*GL%50KLFh$KM=g3GBK~K0hLi(Nurhe2ZGz!y2OT z>rqIR9dROkILOlE8A%S@?+GUksC9w1t|)p^?>H99+owmh{LQPq2cddf<6=r7TLA zo0I6>pv0^bM{QF%>4KC2@`}gB=OmiuQu-$jDwyGwnw3+3BEvg{w(?r}o`28QiACS9 z5q&QNa%ijPmtb|PRygJhNtp{G0tdtPHbXdFY{WRfu#wOn+QP~Gzr@YFt8R~f>Kh30 zV_h^5e$e>TNr@6n$Kmv&;C(W@USt&o9FkV#P-|aM`B-Ht401L0_6v+Gb?Y+~5ySSt zu(#=ucufmG~>vz9Jg3mCz_Wp~o$czqF#~+f<80l14UQ1a8i- zLUQez^f>A|@hopPO#2^+;hTl;0T%#0B z5h3FlkcL`nj~B*30lW?s@A>=U9D1U!a=OD_+KpoTOUL|ng_G3$hu1d^?;lEqKw$u0 zI{q9@gqowzz(=_U6vBF+HQP=JD|vxWG;ImV4l}8@4_!Bn6q>md9kb9EvbvYry8z7Hp~T3r1s{xsJvlqzE8;)EB>EGPUI^owhxx)~88bgT6`uWJ&o z575j6MG}=_sda`@N~m%K6u_drb-)eAkXyUKf6J-#H2mcEmcNQrZ zgOCBaiW?*97xXX7M#rYZwd`LR;A2&tYWIQk==FCQq;zv&q>4$(d+Gn^u?gT;*{z_OEH<|&E zef{$nr~DU;HYF4ly!P}Zu7E@U;>u6w7Xc}zOKVF4VsMX)6jm~9@uOyYjUf~H(kEQd zm%K+c;xR?sW^&AB?Q+%PKmVy8yMoC!GCZREF<3WBG9LgvkpGdoN9(rAj}h-FvpCm} z-^ug?d-KCzbSf8Jqj7RaVa3fhMpE9~kj1%dilz0^drXKrz1sG9m!WMw${Il)l&ume z4FXlz40#|XQRj<{rrs?)8(^~wj}|~OPKC8C@32nd*xa~|Hi$|F?7t{kau+VODSM<) zsO@}Z8j;;w*))9%<#C({Y5Rl|==c;umreZ!?>dMPX3-_WRhy3*58Pwp1T;MBaRe-4 zgf$rdjKiPZ4`1-~u%MdOyEzo~eP53`mMNryXHy+zK;2zWZjSJ!c;uqYG4NWkq+)WY zUT>8@mDOW8^T!(3M)HzJ)$1PylftNBl0Xv*qK=I|1%3y=lU}7e!&2)vRdJYNx~vISf)K!gb!?^(A_i=}O$-m1JvQ-4(2L^FGNkcKBr3HKJUy$13<* zeWK56T4KsM0}oc&1$Y=x7Yz2+9LbILNjwl;S`lX~yKgNIKKXu(|)r_#E&rbyqwDnmop zF%}w@ygdvg_LTLGg~co;_=4EydnH#Xn}m&iFS9wBbgV2~UmKxu5m`wFY`sAmF~o$W z4&HQDc;E8tf?38$zJ+auAYT(e$8&_eK%6uenHoe+XYIPAs8un-ECWSRq$N7*-0_u^6f4$&it|;b4hVU~?okI4e z5<&AFr(SMMSO0Xy+j->HwQN075m>xz@cGqC*+8qX1f{5Z(%DM%{tcxQEA3(fSHCS4 z&-tjUaz7BolwZ>^ALzRX>iPyEuy6mPM_j}445NY{e6%cxFvLOkj^7*6?WcV|KYJa_ z2jjs!ycngsn7)4U0Axf=om~QhwznMB*2hS~lO3)WZpacY`YiLZWB1vCHSqU1e9?0D zr-bz8M#K9Rg;KX}L0_tD1!i5z=n?(?{5Xy$nXG6_143n9cjcjL^dscJ7ZIPZ?G@&W z_RF(y#*6@d_l43Q&K^Z7+4o2Nv7w? zU#MjB1uLnwZplD|U3JkHY-ZN}U^zWDZDlTOb(+(K!e?Ik!55JtJpUYkiUHQ)6cqP) zKgO1z#^?-;TA{^`l!|(4p#%iZ+5({NZLp#my&F;XxE{6(R&;C334G z9{*X3{M^Z?PXvYuul z22^?L!Pdbl7k8x^MNV5UulUWu*ZmTrJM=p2qhspy&D-X$6o1yp z{6>&{S?`|;KO%DHat!v5sq%}F3H+^!#xw8P?zR$2_%+~sSTDgBsIPy91YT%Sq5$2G znnI%1SBbuDYRQX>6f)pfzhWe-bb7C7H75h#u|F~WRwhe|4HfPHk$Iudb5ekj_`H$j zeuYYNkzerIH6;R&NqCgeYU`w8{tyb?l{ZkZHrvS-&H+f9X8LQcDw!-WZEK3zCT7Co zwvug2v8@J#$ezE8hQ!u)%raTQtqcM=Qh8~+ixR~xevFPT+o_Pu!r^m4WmI;LWSb!! zyLBOl6tQu{)9N=v1>dg;{Jx^}BSYYFZu3Go4UWR|Rz;`PQmm4LMy1L%oW$Bi7B7pK z!x;S}s29CZmeWdgk2Y^DV#tPs@kBm(}f*-aUMF3`E5>JlK zv^mAPcy3wZw;`VKUQE~WO zu3FZm<<2D~VI#u(bPTgE9G5X|Zb5Ahovqw3|Hb9ZqP4lldG)=!1{~E3L@LMBplz&W z!rKhN+C4|!=%oP-<4XASprVV)e{@suANh_fSt2pi5Zy4XM)x^L6LQtS;N#{{^K&#H zpDjl>rLx`#BN=Wtc^_7}U$-Z|vP*MxDtEF=^Rqj}IX#FxY3bASCqd>8pFw3+QVj21 zg4WFX?D?FnY%y&}Fty8t2u3#u|%YMH12!K$D4VOl|6|_;>+MN&?7p#GU;!ZVmt;Pk(+h z+EHoHH=Zt9v!Il=+h(3qyaCJ#sJ=OgC`&fZ+SC3{HKc;Ex>-U!~7+$z|G#ak8>oeIx*vw%5uYfJ51?Oqwk(fz*&k z;0eR9y0u|{UNbpS%1^<(QX$*M}`h(mABqstzg`;Aq zY`PFK003I0$=@g1tK7t|f2!XYAtAgGgZ^vTLLb z!u$Tow_S5ShMkvPxkjCyH(^!787J_g7%4_i#c1-9*k~(evSoK`d!urk&OZwqo;3V; zf6uktvcyVD89KRXSSIL9Uf_$t56H~zF=DF zYi@7$^xDqsljzSu?A`0@zAx9nKP}rl-sF`wn=jYGzr3j?URpmj(q!@W&apYCo4KJs zY;-?#<*uoi<~7wDHyR!8mAx1}kzm@q{1alnr20ZCkn{2SIcUZSyaMQyE z8`(z+5u{BFbSe|HU|79haEL~%z|A|AcwXotD$~GQ>aqLufA&H;2;vb# ztDl|rFr9D6BfWvp#z%za7F{M8tMRopYG4leS{4G>B;iD156gf~eELx4I$yk7#RkZN z+Ut-3$=8emq)oG=z_g)|Etn|G<9~gxYDg6h;^B>sgbnSx#f|9I|VzM6*8GHOE>4H=IS1f2>wVn;RlBC>sq_+y1imQ~Za zDtXC3L5_Sqj;fJROn^fSSt6En3y87-BFKY&%M2whXIIF|R|kqzfbi*qVu5#twB}Hs z%VXY?m*X$%jni0l)_>|{Aol*4NLFx`g0Fk~D>W!vK{4StQ9yg}tIyahlR|a03!Edt zrQ-1i;I$?npcypD;XNW|w`LLs^>3DBzi@2lxsyBY2C+xFngd$~SjRc9)=&cV*ewwCZe| zUvQlFV1`K-Xx=IB7b|cjEJ=_iMiu7(F~3SjFDcJe2e@MEzWT*gH&gbswi$bO4uL-v z$b+4ntA9Vi3{q?nLKR|zW|XMT^t(5e%|@N6%4AxA#1hCmPjJ9f0feb(KWV9G4?59W z4gUft=O{A>&J=c+lz5lzsbY7VTlJ*6=7l-(*dmQQ*8*Y&6W1;ZoC9}Vr!q=jgNdRu z;5r;HW586S)R|2L2I*fbUt||7<%&ze+uic-z4`_mX#_4Go+4vrkqt)6fLNT%i`gts z8v~N)$cd5Lu=EToPuiXLZ8V5h-{ic2{d?ue^MmJ|cIwgrW?O2_FLrBcSqW z+*duRk>UB8TCwTN+yokE8gLoo z!nEAgSmMu-FfjmQnb-l3j6fr#3=e=v2&7>`e@sLw_eRkmh3bYt7X7Nc*M-I5#AhYX z&1|~|v*&WuQgrt+L}A4I*oBr2I)Pg^@gbfWNF|b^4ZduzhoRwwktime?-Oku9y;;d zy$_xz0_cGbR^KEYZCTs1M%`=nSM9l;&HT}R^VtLB?ncPi8$PXR=e5)#jjy(v{}PF0 zW1q7_h$Le>U%pc{kVmpBloHMR#FEolv>tSH?y}T7zg5oCPyk0Cl`h^v$u5?OBnIQfRVBDTbo=O9EPM zMBL=6B1L$UYQfFyTYMURIEB3c_eT&@tz0jSq&R(Xbm$Z2hOvUI67pCsF95C8DX)eSJr#{4PGuAnMoJUbQTBk4W52*>^g4r|%7tz8zg@gV&2hjQyHy z>oLw6T$R7+nwAe1!>q6BZtmSQd0x8~uy{;Z$J~7JjW(91Lrqdu^2X@D+V_<-?=5ZG zANks$-&+(joIVZ@FKj|D;lPVrWU>T)|Eq@n?ztxF{Y=Q_H9>g501wtHMR&= zB>qfvhs3udw6y+hx_e}Ocl$n$P8K)si;KjrH%-CPcX64}s zUdBBuGNG9+SyS5))t&DFfTEkXjeqG1-;i%xp65YWBa2`{Tgkaa?sZ|O6y|cYEQaLf zmUj=U(B;dkxISgy(?{FMmn)YfuJDCbEb)8Mj%O->D`uB$MhV;k-S!27I+jjgil1^c z(!*Oo+fwTbL8UOUG|T*tfr_bx9+Kk z!zakb*r9or4g$Gz9%_W;A7((RoZezR^0>&^klco;63<d>)8=t?1(=EuAB$kkp%X+B5tGE8^8~)lhW(jZYKeDL)y@z4(D5#hSJV zf)W5B{sG2cWO4;=Gu?H5aePc8VjgSi-C308{G$Ha(0X#}Pibs*GKS+h#D;MS?~`9vQVjxkB4<6$pSiDL~9s0KDC?#z{&w znKxE3PaiRw@V)Z!I*I=9olWiDyk?hc*Sq=t1lnt4T!|Itj||Xwy(Az|{vdpt$7XkRe+1Lx>$3F_NaqbsYwu! zzAZ0=?hdy&2GQu&g77KuSTs*5i)#gGIEFK=tF-29#}=6~CRzqu@i!QL%DAEb!_Dh& z44Jh6rq}D|F);QA->W--rN?MX4DwQ=IU^ zK?yjp5Y}30h#%j3AeR0N);vPDEfQ|$;~Fj#`uBLSjzFksJn#`(r;p^p;11G&?Jm_8D&Oo z=Mzg?MzZ4NZi@pYNt)t|c{09wFQEBm0VPal<}-zwyDYm`cqsa+Qbg7YU|911k#yei zRKNclxA%7J%~8gwR7c0&hfY~XjygnStE_BgcdW9K>Qu%dbO;?n$958u&>^H_MA>^r z_}-u2@A1$-m37|l_kHgBbzRr~_abJJ;B6bDbE!-ooI;KphL6&n!gc3>A`&0QzkU9-W@t~7z`zz97 zGSaSJx7uv%bk+ZdiGV`O<)nMO;gS90jmHW_-}P*+3Pr?=N$a;f@EK7eWuG+(xs@%M zQKMB`eYM4aY7NN4Cku`EA3SUP$Kow6cWvD8thSoA?%tRpm{>~gEyCZ5f#oxV;s|Z%3Qw_!J`}ESmCQ5 zC-`wk{d!^a2G`044@MMJA91uTvzF4Pt}IY$wD@eL0_I#IjwDxnA4I&5)slSI91UD< zp~v)2bH*7XF4r=k^#`ZI3|prtyh-0g3543=SzwM}8>qs4bngr5S`Buv^={yx!aj#swMW($0_m@VWn;pZYw{-FjDNJ4 zKm1;T^l`1YS&tVgKmDG5;o*w_#%QYN4cTM{hzlLUKT~hK&G(ccRv@15Pr6LsSNb&L zP&HiS&vU=uC>hpCg6%d9I7wbO#!O#Zc5T7x1&9<0%a7f9><9K(OWb1}?N%rTXa7$@ zv7j9yh0q2n-8`((=mNt`PtXC%9Rs^8`tu5(%QgsA6-bpo1ABwQZq1b=ir>KfBY|)E ziLIfAY=-!cli~EhUuJL(nZ@0E#bbIZtSIpml-fT38wl{3x{(mEhTT20FjhNy?R!y- zk?=&HXQf1ePG0?1@w_UZbZ1_juny%9G6@EP=G3YJ*)WUe7qa^*o?;z#3FTMrh{smN*Zs=eXQE!8K zh+0jVAwMe@^+t!upJ)KX~db@~U+3Zq zl?_Yd!{rivPHe!0%a8aZJMR*p@;vvP27*k#Px#3yYq2-!nxN$gvNzxFaiMLJR+r`2 z7$BInK z?1Bo_(ggvLz82Hmj(qM19@oBfJ6u)zEQ!SDcb)(8wNkeGIDAZepLI=#7lZI0fdvF^ zD+1F2(WPDOb`mMBV_Vx6O*gcncIrm15#sg?mZgDeCiyq4@qYUH5<}0yEjDl*K0PH> z=cR;17xB5hUcUW;Enb1isokaXLMn)75{X856HyB*mmj)CsGlKIN+yP;*qIDPW}=Jy zWdRVgVmgx))_BZhm?4{dZlA(#g8KC9kM3vrTZQWny?XEJKrr!2-KC2hp{vmVGhj5d zbuus9F$Y#Ll2y}0VF}=inPvl%kB&qc*;_13=!EamKESaW8%ft!9sj~tOXKzkV~)qO z5ty&qvzLT|>}_kBt{c)A{U^gs4Ch^_qH5y8sjBlKMpn7BM_~16_n6hkFrnP5E0qfc zA;37c5^rAt3!v70)9$`3Vd;j*+RAUVTE5I-Eu)$7Dgtjwca~ zsOE#g58zxN%wARy6aj{&KzEP~RdtI^$4$2iO4n43#@B|LWS+QK&D3$TgLD6 zu60qZpnO=ePIYI$r@G|moLBscKiBHIaD*qFQB1$C?5&2;qkyrvuSRZI23nOE_c%>% z)DMi6`P$q3wLlmQ?B@2J+bYSc4-j@R_i$L;*827Zz*8$5bDhCo9G? zZC9l1hBcg&kz-@9JmciD8P-Y2=e`p;Q!>d!pLlR92zP}|o)IU_D*+_Lh(h)qnP%3K z#kWW6f-GRW)#q*blg29uVh2lnZ1^10XdLn(V=jE&+$av;hbJ(x*`N*~laDI=|x> z_@ig1&+!;)NFUBCf9FNyXA{nA#S+e++}+#aI2d9)aZn;e|@MD z1eS`zQ~qvN@|n>y(Mrp+rXJdnO;5#LDSg}TL%dq4lo5{+sFL;HK$AHj|6xTGSMk8g|##sX2Ud=NPZX!N$`&w6fN{zfVW>?!_rB&ZQUUXSe&f?xhqfZ1Aq7Mdo|+`3i%$ zGuSF)X|5Z+l~b!v4LH9x?RV(6d4wmDVIzm%v}MEU4eidy-K*0##kzU38! zW%6!pI+UkC{6b@|0D(~T!|=IlU?BbIJc+TqRX_zqf{0>CM(NysFHe8YYGZU=Wka5q zy~I)W+Kt_o7UMFqMw42yl<^h-9+EX0V^B%r-%%kAnwMeQ36P`QFI47gU|g+w;QND5 zk+}xUY7OXLPIh8iu{D|t52zSGuM6^)MB8W1rs)g(rlzZ5AB zp8q;8-ZdUDIZYatagf~^xid`UQoqb9Tjt*H_6bL($tM@gc{rS5156${)!U^S_*@Wd zntGXgzTsjHSYB9O^qw!pC(B=+YS8AhY;`$E8XX;?`hS{BZ@nuChB1IVVQx7VbxbdJ zMK^w0W9yGdKbK(HK_Bp~#FW3g)+B3ar(O~-2eew zRGvfEq>Uf%lMlN)v%K~(D8hQ_^j=8S^Ar5=62KcDi4>dy6YmWev)r8s`JNwBdKoAA z8KJjMXr#pt2I9m&`)EFaxoY6mK{kQ+1&fzj_>N*kJo|;=)qb%)m(awK@>RJW6}Bla z5J$tz4Ay9OQERyT#wntf)Fc1z5M<89tZ&)j<4bx+*4L&rdmq=3%BA0aF8_thI#4u+=!hDApKv&8||A9+zBE1i6!%p}yeB^Qo*VuQf}A_6}P5 zvc|^bKhT7_mn)L={XXw)7IO)wE|m05msoADQ%fSY8zu&ZR_!2ulc+SkJ zZ2=84pB|qta_Q=5=1fbvM;q)9zB0)i2j`dpK_C^JvZ{*DrFYFOXTzOhiijlQLf8Rq zf`jM*n89lx37D!NO_$cd&6?I)+i)|p{RMKyvW3(h6f{zoy^Q4o z8Gk9rNdCv$wArzaQ!l5O4%fk({jZr{Lh{FJgRhM#p8ivOc=BzUrhOpL|H#C`*1*AGC@ zj>#!zNNf`HAA*G~CfO9*)H%-G%5r?^TI zLFUGPSK^b%+}7kWLdi&m@LBqET~8#Rk%6-N`~!l4WQ2c&@n8)@CwqPk2#?NjkG7R+ zi&AKn{C^+*ysfFrViU3VuuD7tJU$+v;t)X%nh6%nJ8Y?+T_tG&4F3xa#`@&9@;~4;i!VXPsv0R&I zH1lh34M9FP6mZvRJY)pRR$EwFIczkiL8>+>iz!zme_j~CH2{%H6}X5mVIOW)IT|5g zNz1Xux268TSgupFZ%=*sYN){j=2k$0>0IWBlP#EOl`p%KSgXQuk;sFg=IxWR%G>65 zWRp4U5UT}aj$L;;re{W<$|g96>~MiOhG+2un!qcu>J(sk{8+$R)}vM1CNrU+VtoDH z`l+2oRyXgIsVxXF6?=?;8QD|_dxO5I;}h6?=0{NEh?-OYn=UJ>$>lomkB3u`s4^8> z+b6*tm{;o;qZYDkQmRF6$Z@5qnZKa#Ex+Mh_T z__Han2X&2|lm8SYoNFcS|B0%6)*RHrJQWV&UpZ7{&g+pIE%7%)GfK|FDZth%9r7K2 zO`|=?3xfu>473|NoQ4a%rtiI`CDK;~HtD(k0Bhub{P$Ep+<%x;iKUtqY{TLv`vcve zCb8+0CG;c@U`q#)7O(~NmINpZuz4nFm}37-Y61jgsrz@e`?qEq{C6FS0+QzE0rhJ< zW=#iH!fGgxhr6}o%+ND0$KeR{|E(XVn`y|Jdmz4KZJp9fQ3u3~#$Hgp*D5k`BBKjuQ9-f&?hOae9yjCsv>_%v@#h zmVRu8*;A3MA7c|Oqq(p{KOTh*I^9@0cbde6d0q$$>)fX{7gKiT)O3BdLtnqH z3x5*82?2wVy;slT#yka>Rf%5=2tHc)VwZ_kxQEKuR%1xLtgL9u9)qkT@T9kcF$&V3*NvopR_Ao1!3U(f96#{<*iMp{;+*{!2f+D{#y;n$rN0v(3%f zH691R#?jC8>oii%R`)4?}Mt%Lenk8+kce@4+Fkmj0b?`QDj#r2LoqDvh_X zCxDa$i*IGuQNi~hb1uLOxf4x&HJZJZ!a@&5vbhzbCNG5J0T-iC{cU|QQ36RtWu6F% zTF*+?smp;|1n)N3qaSK<@erxYm`2%*$tu;7lBrAPu01A02EH?M!+ z`nN*i{jj>SIp6K>8@lg4Cj|sJ6{idi!|Y3|^{N~@Uv0CI=#|hOBkEftyTQ2W`kUuk zl$wtZqHl10+WbbV?1A!>kzpyLe=*zZtH<}lx0my-2FzWRG$WFfh~$bg7`v)dw#sVN z8xZwQZ*W)azV!OJ2LMe6M{FY%Q*7Q(=-FW~c70A!jvo>&6jgni9L_9EEtT^$8PjC? z7GcQ?#oj*F_KP`JSXY`WQb=jLWB5SHru|Z0O9rt z^to`jX?Sc&_V+>U+jG@tnqMQaHmEEwNZ8iQhEUV-zZ~DIynua>`1lIhQP0|t?+wu> zTg08?N56kvK_hIyDcYRbum}aQF@$)}NqJ|Ugj*PW=9EA6Euq41f;!cqYA>wWOL``d zR%lmZb}+5kbns6>eOWqqRsS34i&yU341(*IfYMqUdvuz=E%lU2H;3cTsG_E$XB&+d zk*MN;IdpH85*_#|+dC4(g%ggt_ljRf=kJ7>3QoMnyA0@9DdTZkP4rK=QvYDhgQ>-I z1&f^y;3u#k#C*qCJe7&cKm5zw`#9l5rd2SdxNK~<2BG=d8)A()KL_?_D_41I&Wm0_ zXU})Q`BtBzC5Z<&)gAJ zV&Qso{^q90;5JWCU<7JazvXpSdB0_}$#iRBqinxO%U;RW`aw&HiFzqv9^NDPL&m~8 zM{%&Gp$36R=gxXV_OoZh?VldmLNlguEI2RwHe_~XDvgK8*&vd(@gH7?G7 zkaqeFVFBKE{*s2#^mNXT!?QHqpVmVw{jf)+Gzn`bzIorK{G)|5r^X|p|6Wzx&}%xc z%vswUA(hYPdaJX)qfE?Z&v;{nvZuqu&Gdwj559h_^b!F0ZUwyiSul~W@s1ux`xoU< z3%`1q()W{9-h__W0Lj?tDx6lS%nwyToofQ%H{IJggCP;{%km2{yS9is_!DO>rjv?M z7hkQ!d?Obp@QEkVt1q1vV#)>g2;SEww58a@H#ceLEg+nRp@l+u@%~+<5HwY#VA|>FRQ6 zxp+{>(L*0RYE!51Rok=E;3g**+YSZ$Xfu-S?-c`I=3C|0B*M3CiuzEbF}dZyye$B} z<@iHC+7gK-cuNkDVRIcKE%`u*SCFJl+%I}rWSur$s&uJF`z5&Qph3Qdc*!24*qilC z{FPqQy>0H-7RH7BB{@R{Uih6z32Surn~E1T-s0lYwYGL}6=f|91QF`l> zg0o?;MxnhW!@%Q-H>H2XknV%C@V0nU>|i?pSLxw+;`YEU7I~ z)BY`dP3bua zGC0pu8a;xh1$yO}!Y$+@z>w$jEphIhTR))eZ`lgKPh^336a8~Qg~NMwE5$M0-7p+m zkV2%=c%$?CZGT9Zdt-#Nzoo1QBWyF=iQ*Ty|1kg@SYiBDSak`-|*J(h5!z&tIIKGi)Cu#N; z*y-qmkeLh#EM<{DUc4GO*SA2bmP29iVtUJkhPx;dS?wL z(nu!^Ub%bUAA$K8S))icSCMF$+A{lrM`Yq>vN!(6JkKpkkWXj>Q4#qzRlc%w_6%`( zqryhLTFX~P6;r2*R9C^GiLKgpQvp|>zcPI7W&gw-h0O_9{A}+YnuwW^QN5*B!DLAM zEMMk@zAD*wl}LOVF8-865Nb=5xvWz5nzsA|?~#)^o8zAO#69;ZR^Um~KskWYcqyII zYC^wr(Eo#@DX-}L%XsRJrn9KUDqJ_dwuo)fAFUxFLMrZ5)Z0y^ZKE0Z!cln?& zJol5!xB2u9@@XKSkaa*$m;Chvkcv6*a!ONK(WD@%WGnH1y_GQlA~-{KMcQQl1)i3k{= z?ejc*VGnUu5|^CrAIyTbzZG9@T9x&Tc{GzztKjz=2y<2w2zo{gRQz4jziw<7BzfVo z7t5m6ou|BW=>U!ilp-YJKO%VTL0#i9h}F&f120+ZWu>?89L9~+%^#M`0=-4_p-O7N z^)oJ^EPzEv^fAbG%a`lQO5$%@#CH)tUH{-tk2&AQZeD1rk#qf`;2*g(W0_j2S!M~> z$0v#)TF=A;D4MOLNHDlbA;gM6ckaJY{eJ7Zo^0}e?5nuWNDbp!dT^K`dmG!q0g??w z47PAww!%3h(>=Qk?*a zpfGldUn&%gMdc^%%r9R_7?);}gd!ivezwMNHw-Zlik#uv0Dno(1PBKy#KHpZ4LC!q za~RP#ZZ@nG$BoKrW7qlB>KSm+&}ilZa43?>tGY--hE-1T96Hu;wNoq&-^hoxSDQfW zH{fSQ!2(w^bByvMb54Si@%dB!37Rdzsn0JET9LW#`N7P&(^I}z`4riS#pfN1Tny3I zzL52Er|KQ`FxP{qMw!2FbK1>3d)4yMr76b!yqD+|>^Y@us4{T!+Lf?Q&|K7XjU`DR z0Re3ZuOPYDbR}h~`@GKh{kY<@!X}PS*mxWOoW20)POt0#{psTazL0o!0J#O2Ut*>S zp9y_R+4p6k%oYIz9fIw26ZA_*fB> zY%E8^`Bu=0`)nDf#&f@T%{JKF>a-X<%k`MsJyXG={rhb+7^oTCDjv#m7YfF>ZmzQi zeJZh%a;Gl*3Oi;ec^48d0o%9hVOTtH9?_}2lwR_cIoMWcJQNSSh46n`H zn<;sRGRJ5T!1%_x|OB?GPO;`gbc1X5+ zX_xHcy4`wou#pg4)1zZdgU@Z5g0EHE6A7}NmVO@vRPAPh`Ztb#0c5)Z-rfYD2~ zOxz9oz}H@B6L2MB7i8)^#E1|7|W)cKta5mMBwrZhzB=J3|)8@xOZc0Kx=n= zw`61M&&80szAq36@R&gaTw-jU4EQ5rWN&Kd0@{%EcOjA$@0_Eq>*ryb!1^|~Y%<>| z3Gita7T^`0^gm$d3j;mH8c1V5IJhQBM!bLAaD*;?R%uW)wCPz1nALRcZM4eVgHyFtibvKD||5=eY$uhUAKZXBQe+ zLs%a!qlF*#x`C-RN8)cOkj&>d(<|T68gg)V5Bh01WFdNDI$^C5K#2aEj_Y1clJAG- z3o)Nbsd{@i z@ox3Pz_OV^mfS5C+~f0IwTz*4#VE;}QR{K1ef0^adlss&Mv&hRzpJx1xt>rJhxf!m zFFpw!F&eP=0ayRkT7q$$uD>x{O`V+#Z!WfA%vT0o9TrrRPMSFIX;T*D1dw7`M3G{5 zIW8Lc>n*s&mEHZ4(#@B?PdU3%OaX{jK4D>JQ(|kMy0p=O7&*O)rhoqSp@E0{@0Z$Z zI{jmLf^`3{zf>NqS2`W5u1ri#6h!XN{^XY_NJ^V@x&btR_X0@iY)jUrHrvsP)w3=8 zHglScNu*D)Hb6R5&cgLZC^p_Z;mK9DabGRX=#a`bKnTE!NjuaL=xg?uUl`735FvMK+X1*km zJBw7pe;pt*oMdyWt_PqzHJC&qEoJRas5ZwvUp0Itp-c1oQ{S$oUmWjNW7j0{#d1q7 z@xQ9D1mdMRJhLOBZIc0X-lHcU($P5b{@(h=aZ=?r}JkLXZY z$x5i(*ILT3zj8J{gg+cH?I4$Ai zrVJ}d1z#CulOZCun1bLY!RQV0y-xrrvr-DKi{={jmjlQ{w!H~T-Q|MeZV@%Wbh_4< z1m(y)6Ix|unJ>Wu?~Mr^aS4g)_(kz%us~EzRH(iDGW9|G(ah7Ezt*WrT&QYDy{o$1Saf2+a{>isZ-jJj9-`RdBNNNmIshH zKrzNat}XM@3g6hSeq7un&=N}V;(sF^m}a%5$~Sguuboulxkd5|9Pe-;UCOSi?0b$)~$rhq@{Ny#8w~jJ28?Z4>gk zLEXf{tjZBk1uybC%+d6e-sbXD6b~6XJ{gIQ;*5kNGd+P;1mpk`+z6Np{|-F`iXhnf zd5J?%32GeHwTyBW2p4-EC<+I14acNiPu(mxZ~Td!&&_`1vNvyin>%wI+%Xmwvv5y? z3#}4PU+y1g@9PI&7GSySp<$VXx#^!6&DM?IB5ZoP4bH(_&$Ub9|vD&ZSWU|)v6(FiI+{&eWwKlZb(#BSa7rBkGZfyUgNHC+^ zPyO7S!(d0^9LQjCK3_uk`z}JGIV`r=#mgbiMJod%)#l4QCY296uSCR6g|YNVIJaP9 zrs)6}5N{&YxV6vyWt{J1Wpm7s3?;D1l1i?px0TA7b_w1rn0_ZJoC0kht+tX~V}SJ- z{|y@<;iEq~2PJInE1c*9dawlu8dLAcn}C!>0qm|x8~x+ylXK~5K+j1EYKgl&B6Ss6 z_a6?wm%}sfm}RU(_Zu`pDMbp@zdX|ke>8L`6j3O)v#7ao;J}7UhCP}JW8`DAa8zhM zq6-Bq*M&Lxy%%*8gg@aQ%OWAcLv3qO|HKV5gLQBDC4eBiuo&*KV7cBuCcmHrI0v~U zGA9nt(ljo*IL5n%GgIo33=cDCbOaQ>Watv)y|+NV91AT-Hu)9G%nr_#e%e~t+f2t( zoypK>bnw|LC;7|rz*DMqxmA?06(A0($R9yRMeEEzWZm;GHXzb`_=^Yme0rw)GTVP{ zHvXkywJ$s#Pfh7rrd`3NkMxDUMrn061`viVrgqG{1_%|G07>FE!tqw|o=|qr$>?6Wfmm&P?VUDuDahup(UY&}y>yJlS*5!AcKDVqB=Jgs ztkHNO89_dz3yt8i!#G>S>m*xObMUT4w^I9}9zi*z?-;q>9_H=(#a27qIkP7T+A4|> zt?PdQyzl$E%5ByZALpYL&_9_>TnefvXkk|8CK9IQy~ylzz(D^?fpyl(;3rARU{F?T z@6~+q=?3zcPg>hnz3%O+UP<;;62DoZ9Rl_+z3<(J!+wq?IauW|H;xH9rqaio1vvh!bHFK(cp7jL%>m6j!`x zoiL*Ig7!RDxF%|W6hoYMF1JjIk+&+V^=W-?B)HG{tadm^{p(o_k_oBKK1irI_eaBZ zW~zV>Bk2A-?tx1Ikw>G@1A#!${mfIP)0d(9*Lc*+NSAl7{W!_0|Gesv*nWMAaJyg2 zexARV!0T1ZAM%yf=BUH{)CoI;OjJ2bAr{G9R#IZM zNF*+h%YEp!!$O?E7|5(Gw;PX^$mvMy%N@FUTzC8k+xPVvR=AwV`Dua7ubBDZC};bV z*_V0lk*I3t0EilOUA$NAxok>rZ=#Gitp-o(dePl2X!nHqZlmG!mYKy9&qpne2!hfD zAj>qiA{u@-4wzTJ=}Cd2you*ZXi-D;<5kHDEhuW~*`PA^f58gMK7xCT#a-1n#$jM{ zzb#yMmAf+*bPr-N;;5`QUDRUY=i)m_SzRa71iM3Yelf>FkcuVx^2qOVd;c_t+zkVQ z@&Tg3_K7AxdTcPb`o=i*_hRK-m4iUvI=tB5YZL^lUJ}o z>s}TJB@0)1A0;b+ly=?2H#r$5^h4zYz?w{%W|Z1d{l=YG>f#o8|8sS=xZPvKOKa>5 zME7UbXr49MabPz3ufAYkYIez46zNjV*hxNgrXpm?u4wEuiez+W%qHkCt!6w!Bdw6A z;&pF7dx4byx53Xla3|Z2cR2eb`#OVFc#e&b)W!EwS?*85obpMqi&^f(vMd7=%KF1^ z8uFF;gmXPgkBonX$3_$?kRy+E-=9hv62hjL)gol08;aKl#FEq3ZO0a`I6g7Cb2(=@ zWZkVtaZU2Q3FNOH|Jl#qp1mB;Fr9XlH93+J5ta);~Efc=J?JQs%Hs zCPI|DFqOlECKS7va4XPiP#I(|AAG{hR^kkhc?gWkMAL?CMhw!BSRtrxLQo1FwgscO zE^v89Ez|pJO-vw5h@hZA6jnU51XlwWxr*{g zMXATbQt#4=OW^tlVa+LzFaPipc6-LNjZ+{W>2&*G=>?~6XLrbbz$=M;Sse2~%-?RjS zy?CCU!cFeywZ=pbzP?mwiu|%(vz+BXS3o4RLApETlBJ(X!!{*vx@opgzhJUTks8uH zaeBV0zF>Xy{5S5$;NBn;FWSM0i&-Y!Tibp6gDmfUCUX*UL3)K9MII5zLS44KMJ z1F|2j6EU-eWAcaVHp@m=7Xc@dm~S2)hYmZ=6nB!P1u1QX7Nwik+&H5I+Ps6Fw9wJT z(4kBWZF4{M-FWQrY$icjH{P20?dfJO?RZE%PW;lAkOeC) zt|-;V|Myxgp19*%QHsD1IO`OWE4RW@Obf0rQV{CJUmUf2VClkPgo>}l8N ziX19MytI*&x`+v4(9l}C0Dtb7F~5~8!gSLeIS^slsFYbM4%v6$kf}huzfQn;-MeQ= zbjkGAgd`rhKAb32>APrS`}uJK#G;V&rMpH_Yw3H@4r|cSFK`J{!Bi7Cdc{p=ZX8~W zhz5_LEk@`=liW}+(t^?@X^t9d5NEHPvxSH;ALZa4yQUnTdQK7BK516ut@Yd6h&-z6 zaL(?^n7})7@!_(zfO*b)t6HIFce6ZPZ_xpa}y5V!zXe?_y@) z&m;$&@0oME+6rktNR)bi3N36FU18moatSPJoEa`3Oa`sz{JKL9(lHgBzru3CLQVF) zh>!xe99UPJ_`KDg4|Mt+KQO^4*kPa?0$@oYzyQ7l@;7qfQJPnEV~M;~(r;z;boC1; z+qwC&GfHcrMGc25k)1yHSNbOjIX`l`NRbfM$V-JW;yy{!e{rl6`_X$9{4COsJWB>` zE+2)Ug0TX4+$V6IvfOM38@1K{eo@q5_pI4n9Vg)pMw~n4G+L z8iF4u8lK0$LSQpV8YAcZG<x=tFxEB;iopsDpF%U&2)!%zx#lQ@ zwRvt?sY0#yDSeZYIF^!pQ~6S$Vz&?WX}J5fkauIJ%W|ws$>{N@y#k%+ZDhfs=_sG7 zJ;5fUNS=q+opKE*HrPMdukV%aROY=7uzrn_d`D8UC=q!QZufSjQiWEv3FA-&{*O+H zK{L-YJ8t2lF~7s#inZ8P;weSYzcFuVrOi-9dD$uT{pQAx#)Pu*gf z%Y(^hv3vds0f&cKCS#bdC_bu9ZO|J1`F?yxiI+D(^>Ti7&y7Eew1bfC*1Z`+`^yC zrgMhv&e%;g%|Eeu9hiBaaLVxsZ%9nVb27ooZun)q{eufFvCkdJc- zyhooqT~Fwe>+un>!q`^80?TLXx>6H34^I)C``(d_{4{>wu1t4s`Awh*Q?B-D7%urT zJ55g3-?xl-ne+8)?yspGDR3Zj(eg^JhqI$+ly?`(T0TZKeOy}lFHOK_!jBaQkeb>* z`>VmpSx4K`%NV+=rXBZtn4%E(y>2DNsc^|6!N*!2>nctx<-Jq2n5 z*+n7p;o9XC7K`QLcR7fKpUV&1LJmq(KxA9?kpf6uTjfUMcJ+_=btWv#NU(PQKrT-; zlT5{Duk@ME;xrZr_ll|Ut(@1s>bFZhTwm)vW@*y@gO z2v86)0q1p6SLV;_a>T%y#8VoEa}QaNJV-n32NT;4Uif6S5la85YZb$7XIOPjVtFm7 z{j~;@epB2f*Tx$=J5u|O%-^rD&BQ=c9PcoLh8)1GOev0KWCaq@UHKX_`^}K>#Bt|1 z=dq!i_~N!HTDpIFUxpcd>74-^Mjr<-T8b5M)|Pg|FpC>uFj7tT12_v(t&Fl7R6zaF ze^pNP2jD2i;lq}A$T2?Py*qo0{`=q@cW2T+DKOQ5y3ir1{LFepLhH;7JD89Z``rPS zFaMFZ1GNd~cmO>E;Na=%^y&MTgZt%KY(4->y3gV;?7kuFVRocSNyY5Y87XYEV0wt zq((wp)pa-TB$d?|H*n4LwHQwNt3@in^c!Qf^%yz>(xW0<=ehHJSWe%FN~TPIv^;-X z=Q^nCz4s8uHr=gESc`#kRDEb#QIYVKfqqU}8IQjL=Q?qI$#2~7ocWfSpuY~U&zsbP zMboF}era-bc8vYx7?(jXNqlOG@7$K6S%rmRS=UvhXFy}}{w*V$ksM=zdy%yrzIN^PJ1BWQQV+=Tk&ps+_Dld>FR4KPJ8!m`APTaS(RntgC!+lH7W%2CZSTjBa9$(^ zUCrX_H#jiJC`0wkYg^_WfO98_1BTFHNHQ7pT`g6A^?3Y=4+&OZ0o-rr1Ak8Hj)A&y z$cX+4b1m8}0V#6I@Hp!m6(+O^+0i*-ona9m(x#aB)ca+&LkUpIJonjGuUxB_h;9Iw z05O62>KoiQMFsIgMW=y@d8K|_i-RFV(F=FDcef-m$32#}0g0N>fx&XIv=Sv!xy#3@-00h&Hz(t_m@+wzSaB^nFilAd((TKP z2E8%6%sd7G_UDe9c+E=^S`M@)J&lf!D@1lT>n5XDrDBdTdpGF+CCNOHq2r<#qqFqv z{O%jd>L`;R9ps`+itC@~_70>wqip2(x(aSpO21d;fXWUM%~9^?re`?0km5qAZ8};$ z@H_iV`mRgR+*pW=h2z{X$f&xLv*x#DlL=tQE$)+0fk21|bv%9TB*OUg8e)w_Fe+e|K2CNc z?{LF!ZD%a{55SBTc{3qx`mHIt_x}n-?F~oAD82DYHq22km#G-Ydl^_>Sa&z|ApIq6 z@ov);|M$&XJd(VqCsUPA`?(}6{gTLE4ev0f3HHlaekiL0t;m|pWvY^|oC2@9OF1m_0qga~eGUM+>>5@bDY4?CHJcr8 zsEgZC0$7z&A(Kqm;VHs%jXMoOT>llZ&`~7lygm?BWL3qX@2Lt{CmB#m?$>fGQiY41 zjR6BEI5%aZq%z>&e5I^%pxNi~a{r)ph9i&li#X3U#ATDkL|@O7N!Hr8m^WabydpN{ zK8R#O<-X0ufZ7hQH>+xrCUocy9`PY1or5-*fDGGTqt+-#QfmF()7O?PPf|)Kmbf@A zij~YKUfS9hu#ib>7OoE{F z?W;hh=UQ<|*JIJFqSh*@^5(;<`OM9G`bRg`juQ3TYb0-vN2QN?wwQ?H*7l7DF^}Nv zAQlcq#S(~BKlT0{ikonUp-rN7I%u7FlRPIxrKDWzoMd_K1F9=3v%s5$$*|p5*X-Sx z!8VK1rX*$l?6qF!54zUI;2WZ=;um)cM1@1jG)+(}eF2lq&5@axZ^nqfZ23RPs7CX> zKj5)uB*$NKqqkrc6O^?GQA-a#X7MIr>W7twI`W)$bt%*dnVw`1hPS4#y?w*g+U6} zD4H_{xC=VK7W!x}`dE97!vFR3jj8?Rx;ZPWwTr%{LE9{5H;#ls^mkID6d!x8FJC|6 z{Tr9`ggr|KF|Y-F?kM{|md-n#>i>WL$KEr0&zxkB9I`p#BkP@mBkNe%dz0NEim2?& zLWek!5sK3>laLvir(tLB!}rVgjiTD^8NCNlgS%^Yv#B(*Skx=B=*S$6BG*?WfPt!0WLfHKIgc;Ev;` zf9ohcVxEMSH_uu+$&Gs$zCfhw(6L@O52f=p2BlTL#?&|H=-uxbmXqCXA!sIFa8yni zs_9SrS`W*q5cl&6UakmE}3r_8^VBe{iRb?Mc z`l9?B?`?3IYIr%jpG44pr11@Z^D+t%s$3t?f_8rorh?k}*rYMpOVWf+kf8S9K@


      )sMxuW@sPmf2`ed3J-3sAb*Y~4!& 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 diff --git a/App/BlurtiOS/BlurtKeyboard/PrivacyInfo.xcprivacy b/App/BlurtiOS/BlurtKeyboard/PrivacyInfo.xcprivacy new file mode 100644 index 00000000..3ae44d86 --- /dev/null +++ b/App/BlurtiOS/BlurtKeyboard/PrivacyInfo.xcprivacy @@ -0,0 +1,24 @@ + + + + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + NSPrivacyAccessedAPITypes + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryUserDefaults + NSPrivacyAccessedAPITypeReasons + + + 1C8F.1 + + CA92.1 + + + + + diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyCap.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyCap.swift index c1f911fe..cf37f728 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyCap.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyCap.swift @@ -48,7 +48,7 @@ struct KeyCap: View { .foregroundStyle(tint ?? palette.keyText) } else { // A word on a key — 123, ABC, #+=, space, the return label — is the - // brand's eyebrow: Modern Gothic Mono, uppercase, tracked, a step + // brand's eyebrow: the system mono, uppercase, tracked, a step // quieter than a letter. Tracking adds its space after the last // letter too; the same again before the first keeps the word centred. Text((title ?? "").uppercased()) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyGeometry.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyGeometry.swift index 10bce306..b14dd565 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyGeometry.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyGeometry.swift @@ -1,4 +1,4 @@ -import CoreGraphics +import CoreFoundation /// The full keyboard's widths, the iPhone's own: ten letter caps across at /// one width, the side keys taking what seven letters and their gaps leave, diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardRootView.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardRootView.swift index 62699b27..111b6815 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardRootView.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardRootView.swift @@ -57,11 +57,6 @@ struct KeyboardRootView: View { // see and recognises the swipe on the input view itself, which sees // every touch the keyboard gets, the panel's empty space included. // The slide itself is `PanelCarousel`'s. - .onAppear { - // `Font.custom` falls back to the system font in silence; the bundle - // must know the brand's faces (UIAppFonts + Design/fonts). - assert(BlurtType.missing().isEmpty, "fonts not registered: \(BlurtType.missing())") - } } @Environment(\.accessibilityReduceMotion) private var systemReduceMotion diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/MotionHeld.swift b/App/BlurtiOS/BlurtKeyboard/Sources/MotionHeld.swift index ec7f5fa0..d0275dc0 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/MotionHeld.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/MotionHeld.swift @@ -4,7 +4,7 @@ import SwiftUI /// idle wave, the orb's fluid and grain, the caret's blink — is held at time /// zero. Reduce Motion holds it for the user; the gallery's /// `-BlurtGalleryStill` holds it for a capture, so the same state is the same -/// pixels every time (DESIGN.md › Figma). The system value is read-only, so +/// pixels every time (DESIGN.md › Reproducing it). The system value is read-only, so /// this is the switch the views combine it with. private struct KeyboardMotionHeldKey: EnvironmentKey { static let defaultValue = false diff --git a/App/BlurtiOS/BlurtiOS/PrivacyInfo.xcprivacy b/App/BlurtiOS/BlurtiOS/PrivacyInfo.xcprivacy new file mode 100644 index 00000000..3ae44d86 --- /dev/null +++ b/App/BlurtiOS/BlurtiOS/PrivacyInfo.xcprivacy @@ -0,0 +1,24 @@ + + + + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + NSPrivacyAccessedAPITypes + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryUserDefaults + NSPrivacyAccessedAPITypeReasons + + + 1C8F.1 + + CA92.1 + + + + + diff --git a/App/BlurtiOS/BlurtiOS/Sources/AppChrome.swift b/App/BlurtiOS/BlurtiOS/Sources/AppChrome.swift index 33b8adcf..2dabcfda 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/AppChrome.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/AppChrome.swift @@ -59,7 +59,7 @@ extension View { } } -/// An eyebrow: Modern Gothic Mono, uppercase, tracked, muted — the brand's +/// An eyebrow: the system mono, uppercase, tracked, muted — the brand's /// section label, above every group on a screen. struct Eyebrow: View { let text: String diff --git a/App/BlurtiOS/BlurtiOS/Sources/AudioSource.swift b/App/BlurtiOS/BlurtiOS/Sources/AudioSource.swift index e516cb9a..cd697647 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/AudioSource.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/AudioSource.swift @@ -80,12 +80,20 @@ nonisolated final class WindowedAudioSource: NSObject, ListeningSource, @uncheck session.beginConfiguration() defer { session.commitConfiguration() } session.automaticallyConfiguresApplicationAudioSession = false + // A session refused its input or output would still start running — and + // hear nothing, which is worse than failing: the window would open, the + // keyboard would record, and the upload would get no frames. Refused is + // no microphone, said where the user can see it. if session.inputs.isEmpty { guard let device = AVCaptureDevice.default(for: .audio) else { throw ListeningSourceFailure.noInputDevice } let input = try AVCaptureDeviceInput(device: device) - if session.canAddInput(input) { session.addInput(input) } + guard session.canAddInput(input) else { throw ListeningSourceFailure.noInputDevice } + session.addInput(input) + } + if session.outputs.isEmpty { + guard session.canAddOutput(output) else { throw ListeningSourceFailure.noInputDevice } + session.addOutput(output) } - if session.outputs.isEmpty, session.canAddOutput(output) { session.addOutput(output) } } /// Releases the microphone and ends any utterance in flight. diff --git a/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift b/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift index 6d3305a9..4ea9f077 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift @@ -69,6 +69,7 @@ final class DictationCoordinator { // the request — the same signal the Mac reads through Accessibility. hostFocusCapture: DictationSession.HostFocusCapture( frontmost: { nil }, field: { Self.fieldContext() })) + window.onClosingOnItsOwn = { [weak self] in await self?.windowClosingOnItsOwn() } } func start() { @@ -115,6 +116,22 @@ final class DictationCoordinator { publish(.idle) } + /// The window is closing without the user — its time ran out, or a call or + /// Siri took the microphone. Unlike `stopListening`, what was already said + /// still counts: a recording is released, so its words land (on the + /// clipboard when no keyboard is up), and a mic still coming up is + /// cancelled — the keyboard's own rule when it leaves the screen. Awaited + /// before the feed closes, so the release still finds the audio. Without + /// this the session sat in `.recording` over a dead feed until its + /// auto-release, while the keyboard, seeing no app, showed idle. + func windowClosingOnItsOwn() async { + switch phase { + case .recording: await session.release() + case .connecting: await session.cancel() + case .idle, .transcribing, .injecting, .failed, .cancelled, .pasted, .noTarget: break + } + } + func handle(_ url: URL) { if TermPack.looksLikePack(url) { if let pack = TermPack.from(url) { diff --git a/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift b/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift index eb61569a..8d757d63 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift @@ -12,7 +12,7 @@ import BlurtiOSCore /// The last word is a face, `light` or `dark` (the older theme words still /// land: `system` and `paper` are light, `system-dark` and `ink` dark); the /// light face when left out. Two switches make a capture reproducible for the design loop - /// (DESIGN.md › Figma): `-BlurtGalleryStill` holds every motion at time + /// (DESIGN.md › Reproducing it): `-BlurtGalleryStill` holds every motion at time /// zero — the ring, the meter's wave, the orb's fluid and grain — so two /// captures of one state are the same pixels; `-BlurtGalleryBare` draws the /// first row alone, no caption, inside a 2 pt `#FF00FF` registration border @@ -201,7 +201,7 @@ import BlurtiOSCore /// `-BlurtVoice [light|dark]`: one voice /// element by itself, in its slot's box, on the face's surface, inside the - /// registration border — for the review sheet and for Figma. States are + /// registration border — for the review sheet. States are /// the pipeline's plus `off` (not ready) and `landed` (the glint, timed /// for a 3 s screenshot). struct VoiceStillView: View { diff --git a/App/BlurtiOS/BlurtiOS/Sources/ListeningWindow.swift b/App/BlurtiOS/BlurtiOS/Sources/ListeningWindow.swift index 27358b55..9ac7ec81 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/ListeningWindow.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/ListeningWindow.swift @@ -29,6 +29,11 @@ final class ListeningWindow { @ObservationIgnored private var expiry: Task? @ObservationIgnored private var heartbeat: Task? @ObservationIgnored private var interruptions: Task? + /// Run when the window closes on its own — its time ran out, or iOS took + /// the microphone — and awaited *before* the source closes: a dictation + /// riding on the feed has to be ended by whoever owns the session while + /// the feed still holds its audio, not left recording into a closed one. + @ObservationIgnored var onClosingOnItsOwn: (() async -> Void)? var isOpen: Bool { source.isOpen && (until.map { $0 > Date() } ?? false) } @@ -66,7 +71,7 @@ final class ListeningWindow { expiry = Task { [weak self] in try? await Task.sleep(for: .seconds(end.timeIntervalSinceNow)) guard !Task.isCancelled else { return } - await self?.close() + await self?.closeOnItsOwn() } } @@ -97,12 +102,18 @@ final class ListeningWindow { } for await _ in began { guard !Task.isCancelled else { return } - await self?.close() + await self?.closeOnItsOwn() return } } } + /// The window ending without the user asking: the owner hears first. + private func closeOnItsOwn() async { + await onClosingOnItsOwn?() + await close() + } + func close() async { expiry?.cancel() expiry = nil diff --git a/App/BlurtiOS/BlurtiOS/Sources/SetupCard.swift b/App/BlurtiOS/BlurtiOS/Sources/SetupCard.swift index 511f92f8..1d639115 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/SetupCard.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/SetupCard.swift @@ -42,8 +42,12 @@ struct SetupCard: View { } SetupRow(number: "03", done: keyboardSeen, title: "Add the Blurt keyboard") { VStack(alignment: .leading, spacing: DesignTokens.Metrics.appLineGap) { + // The button opens Blurt's own page in Settings — the only Settings + // link Apple allows (the General › Keyboard deep links are private + // API and fail review) — and iOS puts a Keyboards row on that page + // for any app with a keyboard, so the steps start from there. Text( - "Settings → Keyboards: turn on Blurt and Allow Full Access. " + "Open Settings, tap Keyboards, then turn on Blurt and Allow Full Access. " + "Full Access is what lets the keyboard send your words to Blurt." ) .font(BlurtType.body(DesignTokens.Typography.sizeCaption)).foregroundStyle(BlurtBrand.muted) diff --git a/App/BlurtiOS/BlurtiOSCore/DarwinObserver.swift b/App/BlurtiOS/BlurtiOSCore/DarwinObserver.swift index 9e350cad..99c19f04 100644 --- a/App/BlurtiOS/BlurtiOSCore/DarwinObserver.swift +++ b/App/BlurtiOS/BlurtiOSCore/DarwinObserver.swift @@ -1,4 +1,4 @@ -import Foundation +import CoreFoundation /// A Darwin-notification subscription that lives as long as this object does. /// diff --git a/App/BlurtiOS/BlurtiOSCore/KeyboardInteraction.swift b/App/BlurtiOS/BlurtiOSCore/KeyboardInteraction.swift index 05531b18..e2e8eaa7 100644 --- a/App/BlurtiOS/BlurtiOSCore/KeyboardInteraction.swift +++ b/App/BlurtiOS/BlurtiOSCore/KeyboardInteraction.swift @@ -1,5 +1,4 @@ import CoreGraphics -import Foundation /// The keyboard's touch rules, out of the views so they can be tested and /// never drift between layouts (DESIGN.md › The two processes, and every diff --git a/App/BlurtiOS/BlurtiOSCore/KeyboardModel+Field.swift b/App/BlurtiOS/BlurtiOSCore/KeyboardModel+Field.swift index a8bafe77..3b8740b9 100644 --- a/App/BlurtiOS/BlurtiOSCore/KeyboardModel+Field.swift +++ b/App/BlurtiOS/BlurtiOSCore/KeyboardModel+Field.swift @@ -1,4 +1,3 @@ -import Foundation import UIKit // MARK: - What the host field says: the return key, the symbols page, the face diff --git a/App/BlurtiOS/BlurtiOSCore/KeyboardMotion.swift b/App/BlurtiOS/BlurtiOSCore/KeyboardMotion.swift index 9c1e1390..f4b9a254 100644 --- a/App/BlurtiOS/BlurtiOSCore/KeyboardMotion.swift +++ b/App/BlurtiOS/BlurtiOSCore/KeyboardMotion.swift @@ -1,5 +1,4 @@ import BlurtEngine -import Foundation /// The redraw cap for the keyboard's continuous motion — the sheen, the /// meter's idle wave, the glints. The Mac pill reads the same number from diff --git a/App/BlurtiOS/BlurtiOSCore/MicAlignment.swift b/App/BlurtiOS/BlurtiOSCore/MicAlignment.swift index fde1ab02..41cb568f 100644 --- a/App/BlurtiOS/BlurtiOSCore/MicAlignment.swift +++ b/App/BlurtiOS/BlurtiOSCore/MicAlignment.swift @@ -1,5 +1,3 @@ -import Foundation - /// Where the mic key sits across the keyboard, for one hand: at the left /// edge, in the middle (the default), or at the right edge. Left and right /// are the phone's own sides — the side the thumb is on — whatever the diff --git a/App/BlurtiOS/BlurtiOSCore/ThemeFace.swift b/App/BlurtiOS/BlurtiOSCore/ThemeFace.swift index 7e35ecfc..fdfe325a 100644 --- a/App/BlurtiOS/BlurtiOSCore/ThemeFace.swift +++ b/App/BlurtiOS/BlurtiOSCore/ThemeFace.swift @@ -1,5 +1,3 @@ -import Foundation - /// One face of a keyboard theme — its id and whether it is the dark one — /// with no colours attached: the keyboard model holds a choice, and the shell /// turns it into a palette (`KeyboardPalette.resolve`). diff --git a/App/BlurtiOS/BlurtiOSCore/VoiceElementKind.swift b/App/BlurtiOS/BlurtiOSCore/VoiceElementKind.swift index e3b129cd..dd134f3b 100644 --- a/App/BlurtiOS/BlurtiOSCore/VoiceElementKind.swift +++ b/App/BlurtiOS/BlurtiOSCore/VoiceElementKind.swift @@ -1,5 +1,3 @@ -import Foundation - /// The mic control's face — the one part of the keyboard that says what is /// happening, without a word. Three concepts are built side by side behind /// this seam so they can be judged on sight from the same states, the same diff --git a/App/BlurtiOS/BlurtiOSCore/VoiceState.swift b/App/BlurtiOS/BlurtiOSCore/VoiceState.swift index d832ec4e..7f8e50f7 100644 --- a/App/BlurtiOS/BlurtiOSCore/VoiceState.swift +++ b/App/BlurtiOS/BlurtiOSCore/VoiceState.swift @@ -1,5 +1,4 @@ import BlurtEngine -import Foundation /// What the voice control shows, from what the app published: one struct the /// keyboard's key and the app's hero both draw from, so the two never tell a diff --git a/App/BlurtiOS/BlurtiOSTests/APIKeyModelTests.swift b/App/BlurtiOS/BlurtiOSTests/APIKeyModelTests.swift index 9a14e408..87405376 100644 --- a/App/BlurtiOS/BlurtiOSTests/APIKeyModelTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/APIKeyModelTests.swift @@ -1,5 +1,4 @@ import BlurtEngine -import Foundation import Testing @testable import BlurtiOSCore diff --git a/App/BlurtiOS/BlurtiOSTests/BlurtTypeTests.swift b/App/BlurtiOS/BlurtiOSTests/BlurtTypeTests.swift deleted file mode 100644 index ff359663..00000000 --- a/App/BlurtiOS/BlurtiOSTests/BlurtTypeTests.swift +++ /dev/null @@ -1,12 +0,0 @@ -import Testing - -@testable import BlurtiOS - -@Suite("Brand type") -struct BlurtTypeTests { - @Test("every face the tokens name is registered in this bundle") - func registered() { - #expect(BlurtType.missing().isEmpty, "unregistered: \(BlurtType.missing())") - #expect(BlurtType.names.count == 6) - } -} diff --git a/App/BlurtiOS/BlurtiOSTests/DesignTokensTests.swift b/App/BlurtiOS/BlurtiOSTests/DesignTokensTests.swift index d9a970a7..f64cbb8d 100644 --- a/App/BlurtiOS/BlurtiOSTests/DesignTokensTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/DesignTokensTests.swift @@ -1,7 +1,6 @@ import Foundation import SwiftUI import Testing -import UIKit @testable import BlurtiOS @testable import BlurtiOSCore @@ -28,7 +27,7 @@ struct DesignTokensTests { /// rendering the generator writes into `DesignTokens.manifest`. private static func expectedManifest() throws -> [String: String] { let json = try tokensJSON() - let groups = ["brand", "themes", "keyboard", "metrics", "type", "motion", "fonts"] + let groups = ["brand", "themes", "keyboard", "metrics", "type", "motion"] var raw: [String: Any] = [:] for group in groups { let entries = try #require(json[group] as? [String: Any]) @@ -94,7 +93,7 @@ struct DesignTokensTests { #expect(KeyboardLayout.full.height == metrics.layoutFull) } - @Test("the full layout at 402 pt matches the @402 tokens the Figma frames are drawn with") + @Test("the full layout at 402 pt matches the @402 tokens the design is drawn at") func fullLayoutAt402() { // The tokens are written to a thousandth of a point; the row's thirds // round either way at the last digit. @@ -154,14 +153,4 @@ struct DesignTokensTests { #expect(DesignTokens.Themes.lightNotice == DesignTokens.Brand.orange) #expect(DesignTokens.Themes.darkNotice == DesignTokens.Brand.orange) } - - @Test("the fonts are named by PostScript name and the bundle knows them") - func fonts() { - typealias Fonts = DesignTokens.Fonts - for name in [ - Fonts.monoLight, Fonts.monoRegular, Fonts.monoMedium, Fonts.headingRegular, Fonts.bodyRegular, Fonts.bodyBold, - ] { - #expect(UIFont(name: name, size: 12) != nil, "\(name) is not registered (UIAppFonts / Design/fonts)") - } - } } diff --git a/App/BlurtiOS/BlurtiOSTests/KeyboardModelFuzzTests.swift b/App/BlurtiOS/BlurtiOSTests/KeyboardModelFuzzTests.swift index da4faa5a..37e01703 100644 --- a/App/BlurtiOS/BlurtiOSTests/KeyboardModelFuzzTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/KeyboardModelFuzzTests.swift @@ -1,7 +1,6 @@ import Foundation import Testing -@testable import BlurtiOS @testable import BlurtiOSCore /// The keyboard model driven through thousands of random event sequences — diff --git a/App/BlurtiOS/BlurtiOSTests/KeyboardModelGateTests.swift b/App/BlurtiOS/BlurtiOSTests/KeyboardModelGateTests.swift index ccc756e5..5cf91109 100644 --- a/App/BlurtiOS/BlurtiOSTests/KeyboardModelGateTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/KeyboardModelGateTests.swift @@ -1,8 +1,6 @@ import Foundation import Testing -import UIKit -@testable import BlurtiOS @testable import BlurtiOSCore /// The mic key's gate against the app's phases: which phase settles which diff --git a/App/BlurtiOS/BlurtiOSTests/KeyboardModelTests.swift b/App/BlurtiOS/BlurtiOSTests/KeyboardModelTests.swift index 6a5ee0cd..6f9f3e60 100644 --- a/App/BlurtiOS/BlurtiOSTests/KeyboardModelTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/KeyboardModelTests.swift @@ -2,7 +2,6 @@ import Foundation import Testing import UIKit -@testable import BlurtiOS @testable import BlurtiOSCore /// A host text field the model can type into, remembering what it did. diff --git a/App/BlurtiOS/BlurtiOSTests/ProtocolTests.swift b/App/BlurtiOS/BlurtiOSTests/ProtocolTests.swift index 2b3598d2..10245827 100644 --- a/App/BlurtiOS/BlurtiOSTests/ProtocolTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/ProtocolTests.swift @@ -3,7 +3,6 @@ import Foundation import Testing import UIKit -@testable import BlurtiOS @testable import BlurtiOSCore @Suite("The two-process contract", .serialized) diff --git a/App/BlurtiOS/BlurtiOSTests/VoiceRowLayoutTests.swift b/App/BlurtiOS/BlurtiOSTests/VoiceRowLayoutTests.swift index e02ba9d7..14b63e35 100644 --- a/App/BlurtiOS/BlurtiOSTests/VoiceRowLayoutTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/VoiceRowLayoutTests.swift @@ -1,4 +1,4 @@ -import CoreGraphics +import CoreFoundation import Testing @testable import BlurtiOS diff --git a/App/BlurtiOS/DESIGN.md b/App/BlurtiOS/DESIGN.md index d0444acb..d09a961a 100644 --- a/App/BlurtiOS/DESIGN.md +++ b/App/BlurtiOS/DESIGN.md @@ -14,8 +14,7 @@ and the Blurt landing page for the look; `Design/apple-geometry.json` for the keys; `Design/tokens.json` for every value the views draw with. From the tokens, `scripts/design-tokens.swift` writes `Shared/DesignTokens.swift` (what the views read), the tables in this file marked `tokens:begin` / -`tokens:end`, the app's asset-catalog colour sets, and the Figma build's -variables. Edit the JSON, run `scripts/design-sync.sh`, commit; `check.sh` +`tokens:end`, and the app's asset-catalog colour sets. Edit the JSON, run `scripts/design-sync.sh`, commit; `check.sh` runs `design-sync.sh --check` and fails on drift or on a design literal in a view (`// literal-ok: ` for a genuine derivation). @@ -163,7 +162,7 @@ Type: the letters are SF Pro at the iPhone's size, and the glyph keys — shift, delete, globe, the +, × and ✓ — SF Symbols, so the keyboard feels native under the fingers. Every **word** on a key — `123`, `ABC`, `#+=`, `space`, `return` and the field's own `send` / `go` / `done` / `search` / `next` / `join` — -is the brand's eyebrow: Modern Gothic Mono, medium, 12 pt, uppercase, +1.2 +is the brand's eyebrow: the system monospaced face, medium, 12 pt, uppercase, +1.2 tracking, in the face's secondary legend, a step quieter than a letter. Fixed point sizes throughout, as the system keyboard's; no Dynamic Type. @@ -195,31 +194,11 @@ point sizes throughout, as the system keyboard's; no Dynamic Type. -The three faces are bundled in both targets (`Design/fonts/`, registered -through `UIAppFonts` in `project.yml`; an extension cannot read the app's -bundle) and reached only through `BlurtType`, by PostScript name: - - - -| Token | Value | Swift | Use | -| ----------------- | -------------------------- | ---------------------- | ----------------------------------------------- | -| `body/bold` | `UN-11ST-Bold` | `Fonts.bodyBold` | — | -| `body/family` | `UN-11 ST` | `Fonts.bodyFamily` | the app's body text | -| `body/regular` | `UN-11ST-Regular` | `Fonts.bodyRegular` | — | -| `heading/family` | `Oceanic Text` | `Fonts.headingFamily` | the app's serif headlines, sentence case, tight | -| `heading/regular` | `OceanicText-Regular` | `Fonts.headingRegular` | — | -| `mono/family` | `Modern Gothic Mono` | `Fonts.monoFamily` | eyebrows, CTAs, the keyboard's word labels | -| `mono/light` | `ModernGothicMono-Light` | `Fonts.monoLight` | — | -| `mono/medium` | `ModernGothicMono-Medium` | `Fonts.monoMedium` | — | -| `mono/regular` | `ModernGothicMono-Regular` | `Fonts.monoRegular` | — | - - - -`Font.custom` falls back to the system font in silence when a name is wrong, -so the root asserts in debug builds that the bundle knows every face, and -`BlurtTypeTests` pins it. The fonts come from the website's rebrand set; the -licence covers the web, and embedding them in an app that will one day merge -into the public MIT repo is to be settled with Brand Studio first. +No font is bundled: every face is the system's, reached only through +`BlurtType` by role — `mono` (the system's monospaced design) for eyebrows, +CTAs and the keyboard's word labels, `heading` (its serif design) for the +app's headlines, `body` (the default face) for body text — so a call site names +the role and the faces can change in one place. ## The voice element @@ -486,41 +465,40 @@ uses them. `BlurtBrand` keeps a few of the Mac's names as aliases. -The keyboard's semantic colours — what a Figma component binds to — and the -app's catalog colours: +The keyboard's semantic colours and the app's catalog colours: -| Token | Value | Swift | Use | -| ----------------------- | ------------------------------------------ | ----------------------------- | ------------------------------------------------------------------------ | -| `app/accent-dark` | `#67AD82` (`brand.green/400`) | `Keyboard.appAccentDark` | the catalog's AccentColor in dark | -| `app/accent-light` | `#01762F` (`brand.green/700`) | `Keyboard.appAccentLight` | the catalog's AccentColor in light | -| `app/card-border-dark` | `#3A362F` (`brand.ink/600`) | `Keyboard.appCardBorderDark` | the catalog's CardBorder in dark | -| `app/card-border-light` | `#C7C3B2` (`brand.paper/400`) | `Keyboard.appCardBorderLight` | the catalog's CardBorder in light | -| `app/card-fill-dark` | `#26231E` (`brand.ink/800`) | `Keyboard.appCardFillDark` | the catalog's CardFill in dark | -| `app/card-fill-light` | `#F5F3EB` (`brand.paper/tint`) | `Keyboard.appCardFillLight` | the catalog's CardFill in light | -| `app/cta-dark` | `#67AD82` (`brand.green/400`) | `Keyboard.appCtaDark` | the catalog's CTA in dark: the site's button green | -| `app/cta-light` | `#01762F` (`brand.green/700`) | `Keyboard.appCtaLight` | the catalog's CTA in light: the one green button | -| `app/cta-text-dark` | `#1D1B16` (`brand.ink`) | `Keyboard.appCtaTextDark` | the catalog's CTAText in dark: ink on green, as the site | -| `app/cta-text-light` | `#FFFFFF` (`brand.white`) | `Keyboard.appCtaTextLight` | the catalog's CTAText in light | -| `app/muted-dark` | `#A5A4A2` (`brand.neutral/500`) | `Keyboard.appMutedDark` | the catalog's Muted in dark | -| `app/muted-light` | `#777673` (`brand.neutral/700`) | `Keyboard.appMutedLight` | the catalog's Muted in light: eyebrows, captions, secondary text | -| `app/page-dark` | `#1D1B16` (`brand.ink`) | `Keyboard.appPageDark` | the catalog's Page in dark: ink, the website's ground | -| `app/page-light` | `#FDFCF8` (`brand.paper/page`) | `Keyboard.appPageLight` | the catalog's Page in light: the design system's page | -| `app/text-dark` | `#F5F3EB` (`brand.paper/tint`) | `Keyboard.appTextDark` | the catalog's Text in dark | -| `app/text-light` | `#1D1B16` (`brand.ink`) | `Keyboard.appTextLight` | the catalog's Text in light | -| `kb/cancel` | `#E67F36` (`brand.orange`) | `Keyboard.kbCancel` | the panel's cancel × | -| `kb/field` | `#33302A` (`themes.dark/field`) | `Keyboard.kbField` | the key-term field | -| `kb/field-border` | `#3A362F` (`themes.dark/field-border`) | `Keyboard.kbFieldBorder` | the field's hairline | -| `kb/full-access-note` | `#E67F36` (`brand.orange`) | `Keyboard.kbFullAccessNote` | the one line of words the keyboard ever shows | -| `kb/key` | `#33302A` (`themes.dark/key`) | `Keyboard.kbKey` | an ordinary key | -| `kb/key-modifier` | `#26231E` (`themes.dark/key-modifier`) | `Keyboard.kbKeyModifier` | shift, delete, globe, return, 123, cancel | -| `kb/legend` | `#F5F3EB` (`themes.dark/legend`) | `Keyboard.kbLegend` | key legends and bare glyphs | -| `kb/legend-secondary` | `#A5A4A2` (`themes.dark/legend-secondary`) | `Keyboard.kbLegendSecondary` | the mono word labels (123, ABC, return, space) and the + at rest | -| `kb/notice-error` | `#E67F36` (`brand.orange`) | `Keyboard.kbNoticeError` | the solid ring and glyph for an error | -| `kb/popup` | `#33302A` (`themes.dark/popup`) | `Keyboard.kbPopup` | the letter pop-up | -| `kb/signal` | `#67AD82` (`themes.dark/signal`) | `Keyboard.kbSignal` | the wave, the caret, the saved check | -| `kb/surface` | `#1D1B16` (`themes.dark/surface`) | `Keyboard.kbSurface` | the design face's surface (Figma binds to kb/*; Swift reads the palette) | +| Token | Value | Swift | Use | +| ----------------------- | ------------------------------------------ | ----------------------------- | ---------------------------------------------------------------- | +| `app/accent-dark` | `#67AD82` (`brand.green/400`) | `Keyboard.appAccentDark` | the catalog's AccentColor in dark | +| `app/accent-light` | `#01762F` (`brand.green/700`) | `Keyboard.appAccentLight` | the catalog's AccentColor in light | +| `app/card-border-dark` | `#3A362F` (`brand.ink/600`) | `Keyboard.appCardBorderDark` | the catalog's CardBorder in dark | +| `app/card-border-light` | `#C7C3B2` (`brand.paper/400`) | `Keyboard.appCardBorderLight` | the catalog's CardBorder in light | +| `app/card-fill-dark` | `#26231E` (`brand.ink/800`) | `Keyboard.appCardFillDark` | the catalog's CardFill in dark | +| `app/card-fill-light` | `#F5F3EB` (`brand.paper/tint`) | `Keyboard.appCardFillLight` | the catalog's CardFill in light | +| `app/cta-dark` | `#67AD82` (`brand.green/400`) | `Keyboard.appCtaDark` | the catalog's CTA in dark: the site's button green | +| `app/cta-light` | `#01762F` (`brand.green/700`) | `Keyboard.appCtaLight` | the catalog's CTA in light: the one green button | +| `app/cta-text-dark` | `#1D1B16` (`brand.ink`) | `Keyboard.appCtaTextDark` | the catalog's CTAText in dark: ink on green, as the site | +| `app/cta-text-light` | `#FFFFFF` (`brand.white`) | `Keyboard.appCtaTextLight` | the catalog's CTAText in light | +| `app/muted-dark` | `#A5A4A2` (`brand.neutral/500`) | `Keyboard.appMutedDark` | the catalog's Muted in dark | +| `app/muted-light` | `#777673` (`brand.neutral/700`) | `Keyboard.appMutedLight` | the catalog's Muted in light: eyebrows, captions, secondary text | +| `app/page-dark` | `#1D1B16` (`brand.ink`) | `Keyboard.appPageDark` | the catalog's Page in dark: ink, the website's ground | +| `app/page-light` | `#FDFCF8` (`brand.paper/page`) | `Keyboard.appPageLight` | the catalog's Page in light: the design system's page | +| `app/text-dark` | `#F5F3EB` (`brand.paper/tint`) | `Keyboard.appTextDark` | the catalog's Text in dark | +| `app/text-light` | `#1D1B16` (`brand.ink`) | `Keyboard.appTextLight` | the catalog's Text in light | +| `kb/cancel` | `#E67F36` (`brand.orange`) | `Keyboard.kbCancel` | the panel's cancel × | +| `kb/field` | `#33302A` (`themes.dark/field`) | `Keyboard.kbField` | the key-term field | +| `kb/field-border` | `#3A362F` (`themes.dark/field-border`) | `Keyboard.kbFieldBorder` | the field's hairline | +| `kb/full-access-note` | `#E67F36` (`brand.orange`) | `Keyboard.kbFullAccessNote` | the one line of words the keyboard ever shows | +| `kb/key` | `#33302A` (`themes.dark/key`) | `Keyboard.kbKey` | an ordinary key | +| `kb/key-modifier` | `#26231E` (`themes.dark/key-modifier`) | `Keyboard.kbKeyModifier` | shift, delete, globe, return, 123, cancel | +| `kb/legend` | `#F5F3EB` (`themes.dark/legend`) | `Keyboard.kbLegend` | key legends and bare glyphs | +| `kb/legend-secondary` | `#A5A4A2` (`themes.dark/legend-secondary`) | `Keyboard.kbLegendSecondary` | the mono word labels (123, ABC, return, space) and the + at rest | +| `kb/notice-error` | `#E67F36` (`brand.orange`) | `Keyboard.kbNoticeError` | the solid ring and glyph for an error | +| `kb/popup` | `#33302A` (`themes.dark/popup`) | `Keyboard.kbPopup` | the letter pop-up | +| `kb/signal` | `#67AD82` (`themes.dark/signal`) | `Keyboard.kbSignal` | the wave, the caret, the saved check | +| `kb/surface` | `#1D1B16` (`themes.dark/surface`) | `Keyboard.kbSurface` | the design face's surface (Swift reads the palette) | @@ -690,8 +668,8 @@ house curve (`ease/signature`, `cubic-bezier(0.22, 1, 0.36, 1)`). The Blurt landing page on a phone, in the phone's appearance: the page under the brand's grain; the wordmark (tinted with the accent) and the gear across -the top; sections under mono eyebrows; serif headlines (Oceanic Text, 34), -body in UN 11ST (16, captions 14); cards with 12 pt corners and a 1 pt +the top; sections under mono eyebrows; serif headlines (the system serif, 34), +body in the system face (16, captions 14); cards with 12 pt corners and a 1 pt hairline (the hero 16), no shadows; chips and buttons rectangular at 4 pt, buttons 40 pt tall with their label in uppercase mono, one green button per row (Cam's rule) and a hairline one beside it, a colour change on press and @@ -759,7 +737,7 @@ notifications that carry nothing and just say "look" (`BlurtiOSCore/SharedState. Tests pin the rules that can be pinned (`BlurtiOSTests`: the contract, the gate, results, the term field, the feed, the layout arithmetic, Apple's geometry, the interaction rules, the voice state, the home's words, the -fonts, the tokens); anything that gains a number here should gain a line +tokens); anything that gains a number here should gain a line there. ## Where Blurt diverges from the brand system, on purpose @@ -777,5 +755,4 @@ there. The pick between a, b and c; the losers and the `-BlurtGalleryVoice` switch go, and the winner's tokens lose their prefix. Then: the keyboard's autocorrect and suggestion bar; onboarding as a stepped flow once sign-in exists; the -app's cues on the phase edges; the curated themes as brand value sets; the -Figma file rebuilt from the tokens. +app's cues on the phase edges; the curated themes as brand value sets. diff --git a/App/BlurtiOS/Design/figma/README.md b/App/BlurtiOS/Design/figma/README.md deleted file mode 100644 index d063441c..00000000 --- a/App/BlurtiOS/Design/figma/README.md +++ /dev/null @@ -1,84 +0,0 @@ -# The Blurt Keyboard Figma file, from scripts - -The Figma file is built from these scripts, so the scripts — not the file — are -the durable record: a fresh file can be rebuilt in minutes, and the export back -(`tokens.json`) is what the app compiles. `DESIGN.md › Figma` has the loop. - -| File | What | -| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | -| `tokens.js` | **Generated** from `../tokens.json` by `scripts/design-tokens.swift`: every token, alias, scope, iOS code syntax. | -| `lib.js` | The builders, plain Plugin API: `buildFoundations`, `buildComponents`, `buildLayouts`, `themeSheet`, `exportTokens`, `exportBounds`, `measureApple`. | -| `plugin.js` | The development-plugin entry that dispatches `manifest.json`'s menu to those builders. | -| `manifest.json` | The plugin's manifest. `scripts/design-sync.sh` bundles all three JS files into `.build/figma-plugin/code.js`. | - -## Two ways to run the same code - -**Through the Figma MCP (`use_figma`)** — the agent loads the `figma-use` skill -(and `figma-generate-library` for foundations and components, -`figma-generate-design` for layouts), then sends one call per builder whose -script is `tokens.js` + `lib.js` + one line: - -```js -return await buildFoundations(); -``` - -Calls are strictly sequential, every builder is idempotent (it finds by name -before it creates), and every call returns ids and counts. The connector must -be authenticated to the account that owns the file with an editing seat — Neil's -personal Figma, not the AssemblyAI org View seat (6 reads a month, no edits). - -**As a development plugin** (no MCP quota at all): `scripts/design-sync.sh` -writes `.build/figma-plugin/{manifest.json,code.js}`; in Figma desktop, -Plugins → Development → Import plugin from manifest…, then run the menu items -in order. Results print to the plugin console (Plugins → Development → Open console). - -## What the first run taught (2026-09-29) - -- The AssemblyAI View seat **can** write to a draft Neil created, and SF Pro - and the SF Symbol helper are there. It cannot do it for long: after roughly a - dozen `use_figma` calls Figma returned "You've reached the Figma MCP tool call - limit for your View seat on the Organization plan". Writes count. Foundations - and components landed before the cap; layouts did not. Either run the rest as - the development plugin (no quota) or re-authenticate the connector to a - personal Figma account. -- Under the MCP runtime every SF Pro text node reports `hasMissingFont`, and - `setProperties` on a TEXT property then refuses with "the component uses a - font that isn't available", while writing `characters` on the instance's text - node works. The layout builders write labels that way (`setLabel`). -- `componentPropertyDefinitions` must be read on the component **set**, never - on a variant. - -## Order - -1. `buildFoundations` — the six one-mode collections (`Brand`, `Themes`, - `Keyboard`, `Metrics`, `Typography`, `Motion`) with scopes and iOS code syntax; - aliases (`Themes` → `Brand`, `Keyboard` → `Themes`/`Brand`); the five text - styles and `Shadow/Popup`; colour swatches and a token list on `01 Foundations`. - Needs SF Pro installed on the Mac running Figma — it stops if the font is missing. -2. Place the orb stills, if you want real orbs rather than the brand gradient - stand-in: `BLURT_LAUNCH_ARGS="-BlurtOrb 96 idle" scripts/ios-sim.sh --screenshot raw.png` - then `swift scripts/design-diff.swift crop raw.png orb-96-idle.png`, for each of - `40 96 112` × `off idle listening working landed`; upload them into the file - (`upload_assets`, or drag them in) and name each node `orb-still/-` - (`orb-still/Panel-Idle`) on `02 Components`. `buildComponents` picks them up. -3. `buildComponents` — `Key`, `LetterKey`, `AddTermKey`, `CancelKey`, `TermField`, - `Orb/Ring`, `Orb/Disc`, `WaveformMeter`, `MicKey`, `VoiceBar` on `02 Components`, - every fill, stroke, radius and gap bound to a variable. Re-running replaces a set in place. -4. `buildLayouts` — `03 Layouts`: sections `Panel`, `SlimBar`, `Full`, each a - column of frames named `//ink` exactly as the gallery captions - them, 402 pt wide (iPhone 18 Pro, the capture device). Re-running rebuilds the sections. -5. `themeSheet` — re-aliases `kb/*` to each theme in turn, exports the idle - frames at 3× and places them as images in a `Theme sheet` section, then - restores `ink`. This is `KeyboardPalette.resolve(_:dark:)` in Figma; a - Starter file has one variable mode, so themes are value sets, not modes. -6. Paste the Apple `Keyboard` instances (light and dark, iPhone) from the - "iOS and iPadOS 27" kit into a section named `Apple reference` on `03 Layouts`, - lock them, and run `measureApple` — the numbers go into DESIGN.md's Apple geometry table. -7. After a design pass: `exportTokens` → merge its `tokens` object into - `../tokens.json` (keep `gradients` and `figma`) → `scripts/design-sync.sh` → - the views. `exportBounds` gives every named node's rectangle per layout frame - for `scripts/design-diff.swift`'s colour and geometry gates. - -The first run against a real file will surface Plugin API details these scripts -could not be tested against (they were written before the file existed); fix the -builder, re-run it — nothing here is precious except `tokens.json`. diff --git a/App/BlurtiOS/Design/figma/components.js b/App/BlurtiOS/Design/figma/components.js deleted file mode 100644 index b31a2c97..00000000 --- a/App/BlurtiOS/Design/figma/components.js +++ /dev/null @@ -1,510 +0,0 @@ -/* global figma, getPage, variableMap, ensureTokens, loadFonts, FONT, metric, token, autoLayout, textNode, paint, bind, bindRadius, gradientPaint, symbolChar, DEVICE_WIDTH, VARS */ -// --------------------------------------------------------------------------- -// Components (02 Components). Every fill, stroke, radius and gap is bound to a -// variable; the orb's disc is the one image fill (see buildOrbDisc). - -const SIZES = { Bar: "orb/bar", Panel: "orb/panel", Home: "orb/home" }; -const WAVES = { - Bar: ["wave/bar-width", "wave/bar-height"], - Panel: ["wave/panel-width", "wave/panel-height"], - Home: ["wave/home-width", "wave/home-height"], -}; - -async function findComponentSet(page, name) { - return page.findOne((n) => n.type === "COMPONENT_SET" && n.name === name); -} - -async function findComponent(page, name) { - return page.findOne((n) => n.type === "COMPONENT" && n.name === name && n.parent.type !== "COMPONENT_SET"); -} - -async function textStyleId(name) { - const s = (await figma.getLocalTextStylesAsync()).find((x) => x.name === name); - if (!s) throw new Error(`text style ${name} missing — run buildFoundations first`); - return s.id; -} - -async function effectStyleId(name) { - const s = (await figma.getLocalEffectStylesAsync()).find((x) => x.name === name); - if (!s) throw new Error(`effect style ${name} missing — run buildFoundations first`); - return s.id; -} - -/** Replaces a component set (or lone component) of this name, keeping its position. */ -function replaceNamed(page, name, node) { - const old = page.findOne((n) => (n.type === "COMPONENT_SET" || n.type === "COMPONENT") && n.name === name); - if (old) { - node.x = old.x; - node.y = old.y; - old.remove(); - } -} - -/** Lays the variants of a set out in a row and names the set. */ -function finishSet(page, name, variants, x, y) { - const set = figma.combineAsVariants(variants, page); - set.name = name; - set.layoutMode = "HORIZONTAL"; - set.itemSpacing = 24; - set.paddingLeft = set.paddingRight = set.paddingTop = set.paddingBottom = 24; - set.primaryAxisSizingMode = "AUTO"; - set.counterAxisSizingMode = "AUTO"; - set.counterAxisAlignItems = "MIN"; - set.x = x; - set.y = y; - return set; -} - -async function keyCap(props) { - // props: tone "Key"|"Modifier"|"Bare", pressed, label, width (fixed) or null (min width + pad) - const c = figma.createComponent(); - c.name = `Tone=${props.tone}, State=${props.pressed ? "Pressed" : "Up"}`; - c.layoutMode = "HORIZONTAL"; - c.primaryAxisAlignItems = "CENTER"; - c.counterAxisAlignItems = "CENTER"; - c.primaryAxisSizingMode = props.width ? "FIXED" : "AUTO"; - c.counterAxisSizingMode = "FIXED"; - c.resize(props.width || metric("key/min-width"), metric("key/height")); - await bind(c, "height", "Metrics:key/height"); - if (props.width) await bind(c, "width", `Metrics:${props.widthRef}`); - else { - await bind(c, "minWidth", "Metrics:key/min-width"); - await bind(c, "paddingLeft", "Metrics:key/pad"); - await bind(c, "paddingRight", "Metrics:key/pad"); - } - c.fills = props.tone === "Bare" ? [] : [await paint(props.tone === "Modifier" ? "Keyboard:kb/key-modifier" : "Keyboard:kb/key")]; - await bindRadius(c, "Metrics:key/radius"); - const label = await textNode(props.label, { - styleId: await textStyleId(props.letter ? "Key/Letter" : "Key/Legend"), - fillRef: props.tint || "Keyboard:kb/legend", - }); - label.name = "Label"; - c.appendChild(label); - if (props.pressed) { - const shine = figma.createRectangle(); - shine.name = "Pressed"; - shine.fills = [{ type: "SOLID", color: { r: 1, g: 1, b: 1 } }]; - await bind(shine, "opacity", "Metrics:opacity/press-brighten"); - c.appendChild(shine); - shine.layoutPositioning = "ABSOLUTE"; - shine.x = 0; - shine.y = 0; - shine.resize(c.width, c.height); - shine.constraints = { horizontal: "STRETCH", vertical: "STRETCH" }; - await bindRadius(shine, "Metrics:key/radius"); - } - return c; -} - -async function buildKeySet(page, x, y) { - const variants = []; - for (const tone of ["Key", "Modifier", "Bare"]) { - for (const pressed of [false, true]) { - variants.push(await keyCap({ tone, pressed, label: tone === "Bare" ? "×" : "space" })); - } - } - replaceNamed(page, "Key", variants[0]); - const set = finishSet(page, "Key", variants, x, y); - set.description = "One ordinary key: a legend on a cap in the current palette; Modifier a step darker; Bare a glyph with no cap. Flat: no drop, no edge, no gloss."; - const labelProp = set.addComponentProperty("Label", "TEXT", "space"); - for (const v of variants) { - const t = v.findOne((n) => n.type === "TEXT" && n.name === "Label"); - t.componentPropertyReferences = { characters: labelProp }; - } - return set; -} - -async function buildLetterKeySet(page, x, y) { - const variants = []; - for (const pressed of [false, true]) { - const c = await keyCap({ - tone: "Key", - pressed, - label: "q", - letter: true, - width: metric("key/letter-width-402"), - widthRef: "key/letter-width-402", - }); - c.name = `State=${pressed ? "Pressed" : "Up"}`; - if (pressed) { - const popup = figma.createFrame(); - popup.name = "LetterPopup"; - popup.layoutMode = "HORIZONTAL"; - popup.primaryAxisAlignItems = "CENTER"; - popup.counterAxisAlignItems = "CENTER"; - popup.primaryAxisSizingMode = "FIXED"; - popup.counterAxisSizingMode = "FIXED"; - popup.resize(metric("key/letter-width-402") + metric("popup/extra-width"), metric("popup/height")); - await bind(popup, "height", "Metrics:popup/height"); - popup.fills = [await paint("Keyboard:kb/popup")]; - await bindRadius(popup, "Metrics:popup/radius"); - popup.effectStyleId = await effectStyleId("Shadow/Popup"); - const big = await textNode("q", { styleId: await textStyleId("Key/Popup"), fillRef: "Keyboard:kb/legend" }); - big.name = "Popup label"; - popup.appendChild(big); - c.appendChild(popup); - popup.layoutPositioning = "ABSOLUTE"; - popup.x = -metric("popup/extra-width") / 2; - popup.y = -metric("popup/offset"); - } - variants.push(c); - } - replaceNamed(page, "LetterKey", variants[0]); - const set = finishSet(page, "LetterKey", variants, x, y); - set.description = "A letter key with the system keyboard's 22 pt legend and its pop-up while pressed: a 32 pt copy above the key, the one thing that floats."; - const labelProp = set.addComponentProperty("Label", "TEXT", "q"); - for (const v of variants) { - for (const t of v.findAll((n) => n.type === "TEXT")) t.componentPropertyReferences = { characters: labelProp }; - } - return set; -} - -async function glyphButton(name, symbol, fallback, fillRef, opacityRef) { - const c = figma.createComponent(); - c.name = name; - c.layoutMode = "HORIZONTAL"; - c.primaryAxisAlignItems = "CENTER"; - c.counterAxisAlignItems = "CENTER"; - c.primaryAxisSizingMode = "FIXED"; - c.counterAxisSizingMode = "FIXED"; - c.resize(metric("glyph/hit"), metric("glyph/hit")); - await bind(c, "width", "Metrics:glyph/hit"); - await bind(c, "height", "Metrics:glyph/hit"); - const t = await textNode(symbolChar(symbol, fallback), { styleId: await textStyleId("Glyph"), fillRef }); - t.name = "Glyph"; - if (opacityRef) await bind(t, "opacity", opacityRef); - c.appendChild(t); - return c; -} - -async function buildAddTermKey(page, x, y) { - const off = await glyphButton("Saved=False", "plus", "+", "Keyboard:kb/legend", "Metrics:opacity/legend-muted"); - const on = await glyphButton("Saved=True", "checkmark", "✓", "Keyboard:kb/signal", null); - replaceNamed(page, "AddTermKey", off); - const set = finishSet(page, "AddTermKey", [off, on], x, y); - set.description = "The small + beside the orb: a new key term. A bare glyph, quiet until needed; a check for a moment after one was saved."; - return set; -} - -async function buildCancelKey(page, x, y) { - const c = await keyCap({ tone: "Bare", pressed: false, label: symbolChar("xmark", "×"), tint: "Keyboard:kb/cancel" }); - c.name = "CancelKey"; - c.description = "Cancel, in the panel's top-right corner while something is in flight: the orange × on no cap."; - replaceNamed(page, "CancelKey", c); - page.appendChild(c); - c.x = x; - c.y = y; - return c; -} - -async function buildTermField(page, x, y) { - const c = figma.createComponent(); - c.name = "TermField"; - c.description = "The voice bar as a field: × to leave, what has been typed with a caret, ✓ to save."; - c.layoutMode = "HORIZONTAL"; - c.counterAxisAlignItems = "CENTER"; - c.primaryAxisSizingMode = "FIXED"; - c.counterAxisSizingMode = "FIXED"; - c.resize(DEVICE_WIDTH - 2 * metric("margin/side"), metric("voicebar/height")); - await bind(c, "height", "Metrics:voicebar/height"); - await bind(c, "itemSpacing", "Metrics:term/gap"); - await bind(c, "paddingLeft", "Metrics:term/inset"); - await bind(c, "paddingRight", "Metrics:term/inset"); - const cancel = await glyphButton("Cancel", "xmark", "×", "Keyboard:kb/legend", "Metrics:opacity/term-cancel"); - cancel.name = "Cancel"; - const cancelInstance = cancel.createInstance(); - cancel.remove(); - c.appendChild(cancelInstance); - const field = figma.createFrame(); - field.name = "Field"; - field.layoutMode = "HORIZONTAL"; - field.counterAxisAlignItems = "CENTER"; - field.primaryAxisSizingMode = "FIXED"; - field.counterAxisSizingMode = "FIXED"; - field.resize(100, metric("term/height")); - await bind(field, "height", "Metrics:term/height"); - await bind(field, "paddingLeft", "Metrics:term/pad"); - await bind(field, "paddingRight", "Metrics:term/pad"); - field.fills = [await paint("Keyboard:kb/key-modifier")]; - field.cornerRadius = metric("term/height") / 2; // a capsule: half the height - const draft = await textNode("Rizz", { styleId: await textStyleId("Term/Text"), fillRef: "Keyboard:kb/legend" }); - draft.name = "Draft"; - field.appendChild(draft); - const caret = figma.createRectangle(); - caret.name = "Caret"; - caret.resize(metric("caret/width"), metric("caret/height")); - await bind(caret, "width", "Metrics:caret/width"); - await bind(caret, "height", "Metrics:caret/height"); - await bindRadius(caret, "Metrics:caret/radius"); - caret.fills = [await paint("Keyboard:kb/signal")]; - field.appendChild(caret); - c.appendChild(field); - field.layoutSizingHorizontal = "FILL"; - const save = await glyphButton("Save", "checkmark", "✓", "Keyboard:kb/signal", null); - const saveInstance = save.createInstance(); - save.remove(); - c.appendChild(saveInstance); - const draftProp = c.addComponentProperty("Draft", "TEXT", "Rizz"); - draft.componentPropertyReferences = { characters: draftProp }; - replaceNamed(page, "TermField", c); - page.appendChild(c); - c.x = x; - c.y = y; - return c; -} - -async function buildOrbRing(page, x, y) { - const variants = []; - for (const [size, ref] of Object.entries(SIZES)) { - for (const kind of ["Still", "Working", "Ok", "Error"]) { - const c = figma.createComponent(); - c.name = `Kind=${kind}, Size=${size}`; - const d = metric(ref); - c.resize(d, d); - c.fills = []; - const ring = figma.createEllipse(); - ring.name = "Ring"; - ring.resize(d, d); - ring.fills = []; - ring.strokeAlign = "INSIDE"; - if (kind === "Ok" || kind === "Error") { - ring.strokes = [await paint(kind === "Ok" ? "Keyboard:kb/notice-ok" : "Keyboard:kb/notice-error")]; - } else { - ring.strokes = [gradientPaint("orb-ring")]; - } - await bind(ring, "strokeWeight", kind === "Still" ? "Metrics:ring/still" : "Metrics:ring/active"); - c.appendChild(ring); - await bind(c, "width", `Metrics:${ref}`); - await bind(c, "height", `Metrics:${ref}`); - variants.push(c); - } - } - replaceNamed(page, "Orb/Ring", variants[0]); - const set = finishSet(page, "Orb/Ring", variants, x, y); - set.description = "The hairline ring round the orb: green into white, 1 pt at rest and 2 pt while working (it sweeps one turn per 1.6 s); solid green for pasted and copied, orange for an error."; - return set; -} - -/** An orb still the app rendered, if one has been placed in the file. */ -function orbStill(page, size, mood) { - const node = page.findOne((n) => n.name === `orb-still/${size}-${mood}`.toLowerCase()); - if (!node || !("fills" in node)) return null; - const fill = node.fills.find((f) => f.type === "IMAGE"); - return fill ? fill.imageHash : null; -} - -async function buildOrbDisc(page, x, y) { - const variants = []; - let images = 0; - for (const [size, ref] of Object.entries(SIZES)) { - for (const mood of ["Off", "Idle", "Listening", "Working", "Landed"]) { - const c = figma.createComponent(); - c.name = `Size=${size}, Mood=${mood}`; - const d = metric(ref); - c.resize(d, d); - c.fills = []; - const disc = figma.createEllipse(); - disc.name = "Disc"; - disc.resize(d, d); - const hash = orbStill(page, size, mood === "Off" ? "Idle" : mood); - if (hash) { - disc.fills = [{ type: "IMAGE", imageHash: hash, scaleMode: "FILL" }]; - images += 1; - } else { - disc.fills = [gradientPaint("orb")]; - } - if (mood === "Off") { - await bind(disc, "opacity", "Metrics:opacity/dim"); - } - c.appendChild(disc); - await bind(c, "width", `Metrics:${ref}`); - await bind(c, "height", `Metrics:${ref}`); - variants.push(c); - } - } - replaceNamed(page, "Orb/Disc", variants[0]); - const set = finishSet(page, "Orb/Disc", variants, x, y); - set.description = - "The orb's fill. A still the app renders (-BlurtOrb , placed here as orb-still/-); the brand gradient stands in until one is. Off is Idle dimmed."; - return { set, images }; -} - -async function buildWaveformMeter(page, x, y) { - const variants = []; - for (const [size, [wRef, hRef]] of Object.entries(WAVES)) { - const c = figma.createComponent(); - c.name = `Size=${size}`; - const w = metric(wRef); - const h = metric(hRef); - c.resize(w, h); - c.fills = []; - c.layoutMode = "HORIZONTAL"; - c.primaryAxisAlignItems = "CENTER"; - c.counterAxisAlignItems = "CENTER"; - c.primaryAxisSizingMode = "FIXED"; - c.counterAxisSizingMode = "FIXED"; - await bind(c, "itemSpacing", "Metrics:wave/gap"); - await bind(c, "width", `Metrics:${wRef}`); - await bind(c, "height", `Metrics:${hRef}`); - const bar = metric("wave/bar"); - const gap = metric("wave/gap"); - const count = Math.floor((w + gap) / (bar + gap)); - const level = 0.62; - for (let i = 0; i < count; i += 1) { - const t = i / Math.max(count - 1, 1); - // A schematic of the engine's envelope: a soft hump, minimum 12 %, at the gallery's level. - const envelope = 0.12 + 0.88 * level * Math.pow(Math.sin(Math.PI * t), 0.45); - const capsule = figma.createRectangle(); - capsule.name = "Bar"; - capsule.resize(bar, Math.max(bar, h * envelope)); - capsule.cornerRadius = bar / 2; - await bind(capsule, "width", "Metrics:wave/bar"); - capsule.fills = [await paint("Keyboard:kb/signal")]; - c.appendChild(capsule); - } - variants.push(c); - } - replaceNamed(page, "WaveformMeter", variants[0]); - const set = finishSet(page, "WaveformMeter", variants, x, y); - set.description = - "The thin wave: 2 pt bars 2 pt apart, flat on the surface, no container. Heights are the engine's (MeterBarGeometry); this is the schematic at level 0.62 — fidelity frames use app captures."; - return set; -} - -const MIC_STATES = ["Off", "Idle", "Working", "Recording", "Pasted", "Copied", "Error"]; - -async function buildMicKey(page, x, y) { - const disc = await findComponentSet(page, "Orb/Disc"); - const ring = await findComponentSet(page, "Orb/Ring"); - const meter = await findComponentSet(page, "WaveformMeter"); - if (!disc || !ring || !meter) throw new Error("build Orb/Disc, Orb/Ring and WaveformMeter first"); - const pick = (set, props) => - set.children.find((c) => Object.entries(props).every(([k, v]) => c.name.includes(`${k}=${v}`))); - const variants = []; - for (const [size, ref] of Object.entries(SIZES)) { - for (const state of MIC_STATES) { - const c = figma.createComponent(); - c.name = `Size=${size}, State=${state}`; - const d = metric(ref); - const [wRef] = WAVES[size]; - c.resize(Math.max(metric(wRef), d), d); - c.fills = []; - c.layoutMode = "HORIZONTAL"; - c.primaryAxisAlignItems = "CENTER"; - c.counterAxisAlignItems = "CENTER"; - c.primaryAxisSizingMode = "FIXED"; - c.counterAxisSizingMode = "FIXED"; - await bind(c, "height", `Metrics:${ref}`); - if (state === "Recording") { - c.appendChild(pick(meter, { Size: size }).createInstance()); - } else { - const stack = figma.createFrame(); - stack.name = "Orb"; - stack.resize(d, d); - stack.fills = []; - stack.clipsContent = false; - const mood = { Off: "Off", Idle: "Idle", Working: "Working", Pasted: "Landed", Copied: "Idle", Error: "Idle" }[state]; - const kind = { Off: "Still", Idle: "Still", Working: "Working", Pasted: "Ok", Copied: "Ok", Error: "Error" }[state]; - const discInstance = pick(disc, { Size: size, Mood: mood }).createInstance(); - discInstance.name = "Disc"; - stack.appendChild(discInstance); - const ringInstance = pick(ring, { Size: size, Kind: kind }).createInstance(); - ringInstance.name = "Ring"; - stack.appendChild(ringInstance); - if (state === "Copied" || state === "Error") { - const glyph = await textNode( - state === "Copied" ? symbolChar("doc.on.clipboard", "⎘") : symbolChar("exclamationmark", "!"), - { size: d * token("Typography", "ratio/orb-glyph").value, weight: FONT.semibold } - ); - glyph.name = "Glyph"; - glyph.fills = [{ type: "SOLID", color: { r: 1, g: 1, b: 1 } }]; - stack.appendChild(glyph); - glyph.x = (d - glyph.width) / 2; - glyph.y = (d - glyph.height) / 2; - } - if (state === "Off") await bind(stack, "opacity", "Metrics:opacity/dim"); - c.appendChild(stack); - } - variants.push(c); - } - } - replaceNamed(page, "MicKey", variants[0]); - const set = finishSet(page, "MicKey", variants, x, y); - set.description = - "The mic key is the orb, and it says everything without a word: dimmed when Blurt isn't ready; ring sweeping while connecting and transcribing; dissipated into the wave while recording; a green ring when the words landed (with the drop), a clipboard on green when they went to the clipboard, orange and ! for an error."; - return set; -} - -async function buildVoiceBar(page, x, y) { - const mic = await findComponentSet(page, "MicKey"); - const addTerm = await findComponentSet(page, "AddTermKey"); - const termField = await findComponent(page, "TermField"); - if (!mic || !addTerm || !termField) throw new Error("build MicKey, AddTermKey and TermField first"); - const pick = (set, props) => - set.children.find((c) => Object.entries(props).every(([k, v]) => c.name.includes(`${k}=${v}`))); - const variants = []; - for (const mode of ["Orb", "Wave", "Term", "NoFullAccess"]) { - const c = figma.createComponent(); - c.name = `Mode=${mode}`; - c.layoutMode = "HORIZONTAL"; - c.primaryAxisAlignItems = mode === "NoFullAccess" ? "MIN" : "CENTER"; - c.counterAxisAlignItems = "CENTER"; - c.primaryAxisSizingMode = "FIXED"; - c.counterAxisSizingMode = "FIXED"; - c.resize(DEVICE_WIDTH - 2 * metric("margin/side"), metric("voicebar/height")); - await bind(c, "height", "Metrics:voicebar/height"); - c.fills = []; - c.clipsContent = false; - if (mode === "Term") { - const f = termField.createInstance(); - c.appendChild(f); - f.layoutSizingHorizontal = "FILL"; - } else if (mode === "NoFullAccess") { - await bind(c, "itemSpacing", "Metrics:voicebar/note-gap"); - c.appendChild(pick(mic, { Size: "Bar", State: "Off" }).createInstance()); - const note = await textNode("Allow Full Access in Settings → Keyboards", { - size: 13, - fillRef: "Keyboard:kb/full-access-note", - }); - note.name = "Note"; - c.appendChild(note); - } else { - c.appendChild(pick(mic, { Size: "Bar", State: mode === "Wave" ? "Recording" : "Idle" }).createInstance()); - const plus = pick(addTerm, { Saved: "False" }).createInstance(); - c.appendChild(plus); - plus.layoutPositioning = "ABSOLUTE"; - plus.constraints = { horizontal: "MAX", vertical: "CENTER" }; - plus.x = c.width - plus.width; - plus.y = (c.height - plus.height) / 2; - } - variants.push(c); - } - replaceNamed(page, "VoiceBar", variants[0]); - const set = finishSet(page, "VoiceBar", variants, x, y); - set.description = - "The keyboard's voice row, and the only place voice lives: the orb (the mic key) dissipating into the wave while recording; the + for a key term; the field the keys type into; the one line of words, without Full Access."; - return set; -} - -async function buildComponents() { - await ensureTokens(); - const page = await getPage(PAGES.components); - VARS = await variableMap(); - await loadFonts(); - const built = {}; - let y = 0; - const step = 360; - built.key = (await buildKeySet(page, 0, y)).id; - built.letterKey = (await buildLetterKeySet(page, 0, (y += step))).id; - built.addTermKey = (await buildAddTermKey(page, 0, (y += step))).id; - built.cancelKey = (await buildCancelKey(page, 400, y)).id; - built.termField = (await buildTermField(page, 0, (y += step))).id; - built.orbRing = (await buildOrbRing(page, 0, (y += step))).id; - const disc = await buildOrbDisc(page, 0, (y += step)); - built.orbDisc = disc.set.id; - built.orbStillsUsed = disc.images; - built.waveformMeter = (await buildWaveformMeter(page, 0, (y += step))).id; - built.micKey = (await buildMicKey(page, 0, (y += step))).id; - built.voiceBar = (await buildVoiceBar(page, 0, (y += step))).id; - return { page: page.id, built }; -} diff --git a/App/BlurtiOS/Design/figma/core.js b/App/BlurtiOS/Design/figma/core.js deleted file mode 100644 index af8f6791..00000000 --- a/App/BlurtiOS/Design/figma/core.js +++ /dev/null @@ -1,244 +0,0 @@ -// The Blurt Keyboard Figma file, built from the tokens. core.js: names and helpers every module needs. Plain Plugin API, so -// the same functions run two ways (README.md): pasted into a use_figma call -// behind tokens.js with `return await buildFoundations();`, or bundled by -// scripts/design-sync.sh into a development plugin (plugin.js dispatches). -// Everything is idempotent — find by name before create — and every builder -// returns the ids and counts it touched. No `figma.notify`, no console output. -/* global figma, TOKEN_LINES, GROUPS */ - -// --------------------------------------------------------------------------- -// Names - -const PAGES = { foundations: "01 Foundations", components: "02 Components", layouts: "03 Layouts" }; -const FONT = { family: "SF Pro", regular: "Regular", medium: "Medium", semibold: "Semibold" }; -const DEVICE_WIDTH = 402; // iPhone 18 Pro, the simulator this repo captures on -const DESIGN_THEME = "ink"; -const THEMES = ["system-light", "system-dark", "ink", "paper", "lavender", "mint", "midnight", "sunset"]; -const ROLES = ["surface", "key", "key-modifier", "legend", "signal", "popup"]; -const STATES = ["off", "start", "idle", "connecting", "recording", "processing", "pasted", "copied", "error", "term"]; - -// --------------------------------------------------------------------------- -// The tokens. buildFoundations carries them (tokens.js, one line per variable); -// every later builder reads them back from the file's variables, so a call -// stays under use_figma's 50,000-character cap. - -function parseTokenLines(text) { - const collections = {}; - const gradients = {}; - for (const line of text.split("\n")) { - if (!line) continue; - const parts = line.split("|"); - if (parts[0] === "GRADIENT") { - const [, name, start, end, stops, use] = parts; - gradients[name] = { - start, - end, - use, - stops: stops.split(",").map((s) => { - const [value, location] = s.split("@"); - return { value, location: Number(location) }; - }), - }; - continue; - } - const [collection, name, type, raw, alias, scopes, codeSyntax, use] = parts; - if (!collections[collection]) collections[collection] = { mode: "Value", variables: [] }; - collections[collection].variables.push({ - name, - type, - value: type === "FLOAT" ? Number(raw) : raw, - alias: alias || null, - scopes: scopes ? scopes.split(",") : [], - codeSyntax, - use, - }); - } - return { collections, gradients, groups: typeof GROUPS !== "undefined" ? GROUPS : Object.keys(collections) }; -} - -let TOKENS = typeof TOKEN_LINES !== "undefined" ? parseTokenLines(TOKEN_LINES) : null; -const GRADIENT_STYLES = {}; - -function rgbToHex(c) { - return "#" + [c.r, c.g, c.b].map((x) => Math.round(x * 255).toString(16).padStart(2, "0").toUpperCase()).join(""); -} - -/** Loads TOKENS from the file's variables and gradient paint styles when the call carried none. */ -async function ensureTokens() { - const styles = await figma.getLocalPaintStylesAsync(); - for (const s of styles) if (s.name.startsWith("Gradient/")) GRADIENT_STYLES[s.name.slice(9)] = s.paints[0]; - if (TOKENS) return TOKENS; - const map = await variableMap(); - if (map.size === 0) throw new Error("the file has no variables yet — run buildFoundations first"); - const collectionsById = new Map((await figma.variables.getLocalVariableCollectionsAsync()).map((c) => [c.id, c])); - const byId = new Map([...map.values()].map((v) => [v.id, v])); - function resolveValue(v, depth) { - const c = collectionsById.get(v.variableCollectionId); - const raw = v.valuesByMode[c.modes[0].modeId]; - if (raw && typeof raw === "object" && raw.type === "VARIABLE_ALIAS") { - const target = byId.get(raw.id); - return target && depth < 8 ? resolveValue(target, depth + 1) : null; - } - return raw; - } - const collections = {}; - for (const [key, v] of map) { - const i = key.indexOf(":"); - const collection = key.slice(0, i); - const name = key.slice(i + 1); - const raw = resolveValue(v, 0); - const value = v.resolvedType === "COLOR" && raw ? rgbToHex(raw) : raw; - if (!collections[collection]) collections[collection] = { mode: "Value", variables: [] }; - collections[collection].variables.push({ name, type: v.resolvedType, value, alias: null, scopes: v.scopes, use: v.description }); - } - TOKENS = { collections, gradients: {}, groups: Object.keys(collections) }; - return TOKENS; -} - -// --------------------------------------------------------------------------- -// Helpers - -function hexToRGB(hex) { - const n = parseInt(hex.slice(1), 16); - return { r: ((n >> 16) & 255) / 255, g: ((n >> 8) & 255) / 255, b: (n & 255) / 255 }; -} - -function token(collection, name) { - const entry = TOKENS.collections[collection].variables.find((v) => v.name === name); - if (!entry) throw new Error(`no token ${collection}:${name}`); - return entry; -} - -function metric(name) { - return token("Metrics", name).value; -} - -async function getPage(name) { - let page = figma.root.children.find((p) => p.name === name); - if (!page) { - page = figma.createPage(); - page.name = name; - } - await figma.setCurrentPageAsync(page); - return page; -} - -function getSection(page, name, x, y) { - let section = page.children.find((n) => n.type === "SECTION" && n.name === name); - if (!section) { - section = figma.createSection(); - section.name = name; - section.x = x; - section.y = y; - page.appendChild(section); - } - return section; -} - -/** Every local variable, keyed "Collection:name". */ -async function variableMap() { - const collections = await figma.variables.getLocalVariableCollectionsAsync(); - const byId = new Map(collections.map((c) => [c.id, c])); - const map = new Map(); - for (const v of await figma.variables.getLocalVariablesAsync()) { - const collection = byId.get(v.variableCollectionId); - if (collection) map.set(`${collection.name}:${v.name}`, v); - } - return map; -} - -let VARS = null; -async function vars() { - if (!VARS) VARS = await variableMap(); - return VARS; -} - -async function variable(ref) { - const v = (await vars()).get(ref); - if (!v) throw new Error(`variable ${ref} is not in the file — run buildFoundations first`); - return v; -} - -/** A solid paint bound to a colour variable. */ -async function paint(ref) { - const v = await variable(ref); - return figma.variables.setBoundVariableForPaint({ type: "SOLID", color: { r: 0, g: 0, b: 0 } }, "color", v); -} - -async function bind(node, field, ref) { - node.setBoundVariable(field, await variable(ref)); -} - -async function bindRadius(node, ref) { - for (const corner of ["topLeftRadius", "topRightRadius", "bottomLeftRadius", "bottomRightRadius"]) { - await bind(node, corner, ref); - } -} - -async function loadFonts() { - const available = await figma.listAvailableFontsAsync(); - const families = new Set(available.map((f) => f.fontName.family)); - if (!families.has(FONT.family)) { - throw new Error(`${FONT.family} is not available in this file; install SF Pro from developer.apple.com/fonts`); - } - for (const style of [FONT.regular, FONT.medium, FONT.semibold]) { - await figma.loadFontAsync({ family: FONT.family, style }); - } -} - -/** An SF Symbol as a character where the runtime can (the MCP one), else a stand-in. */ -function symbolChar(name, fallback) { - try { - if (figma.util && typeof figma.util.getSfSymbolCharacter === "function") { - return figma.util.getSfSymbolCharacter(name); - } - } catch (_) { - // fall through to the stand-in - } - return fallback; -} - -async function textNode(characters, { size, weight = FONT.regular, fillRef, styleId } = {}) { - const t = figma.createText(); - t.fontName = { family: FONT.family, style: weight }; - t.characters = characters; - if (size) t.fontSize = size; - if (styleId) t.textStyleId = styleId; - if (fillRef) t.fills = [await paint(fillRef)]; - t.textAutoResize = "WIDTH_AND_HEIGHT"; - return t; -} - -function autoLayout(direction, props = {}) { - const frame = figma.createFrame(); - frame.layoutMode = direction; - frame.primaryAxisSizingMode = "AUTO"; - frame.counterAxisSizingMode = "AUTO"; - frame.fills = []; - frame.clipsContent = false; - Object.assign(frame, props); - return frame; -} - -function gradientPaint(gradientName) { - const g = TOKENS && TOKENS.gradients[gradientName]; - if (!g) { - if (GRADIENT_STYLES[gradientName]) return GRADIENT_STYLES[gradientName]; - throw new Error(`no gradient ${gradientName}: run buildFoundations (it saves Gradient/* paint styles)`); - } - const transforms = { - "bottom>top": [ - [0, -1, 1], - [1, 0, 0], - ], - "topLeading>bottomTrailing": [ - [0.5, 0.5, 0], - [-0.5, 0.5, 0.5], - ], - }; - return { - type: "GRADIENT_LINEAR", - gradientTransform: transforms[`${g.start}>${g.end}`] || transforms["bottom>top"], - gradientStops: g.stops.map((s) => ({ position: s.location, color: { ...hexToRGB(s.value), a: 1 } })), - }; -} diff --git a/App/BlurtiOS/Design/figma/exports.js b/App/BlurtiOS/Design/figma/exports.js deleted file mode 100644 index 6a570150..00000000 --- a/App/BlurtiOS/Design/figma/exports.js +++ /dev/null @@ -1,55 +0,0 @@ -/* global figma, getPage, PAGES */ -// --------------------------------------------------------------------------- -// Export: the variables back out as tokens.json's groups - -async function exportTokens() { - const collections = await figma.variables.getLocalVariableCollectionsAsync(); - const byId = new Map(collections.map((c) => [c.id, c])); - const all = await figma.variables.getLocalVariablesAsync(); - const byVarId = new Map(all.map((v) => [v.id, v])); - const groupOf = { Brand: "brand", Themes: "themes", Keyboard: "keyboard", Metrics: "metrics", Typography: "type", Motion: "motion" }; - const out = {}; - for (const v of all) { - const c = byId.get(v.variableCollectionId); - const group = c && groupOf[c.name]; - if (!group) continue; - const modeId = c.modes[0].modeId; - let raw = v.valuesByMode[modeId]; - let value; - if (raw && typeof raw === "object" && raw.type === "VARIABLE_ALIAS") { - const target = byVarId.get(raw.id); - const tc = byId.get(target.variableCollectionId); - value = `{${groupOf[tc.name]}.${target.name}}`; - } else if (raw && typeof raw === "object" && "r" in raw) { - const hex = [raw.r, raw.g, raw.b].map((x) => Math.round(x * 255).toString(16).padStart(2, "0")).join(""); - value = `#${hex.toUpperCase()}`; - } else { - value = raw; - } - out[group] = out[group] || {}; - out[group][v.name] = v.description ? { value, use: v.description } : { value }; - } - return { tokens: out, note: "merge into App/BlurtiOS/Design/tokens.json (keep gradients and figma), then scripts/design-sync.sh" }; -} - -/** The absolute bounds of every named node under the layout frames, in points. */ -async function exportBounds() { - const page = await getPage(PAGES.layouts); - const frames = page.findAll((n) => n.type === "FRAME" && /^(panel|slimBar|full)\//.test(n.name)); - const bounds = {}; - for (const frame of frames) { - const origin = frame.absoluteBoundingBox; - bounds[frame.name] = {}; - for (const node of frame.findAll((n) => n.name && n.absoluteBoundingBox)) { - const b = node.absoluteBoundingBox; - bounds[frame.name][node.name] = { - x: +(b.x - origin.x).toFixed(2), - y: +(b.y - origin.y).toFixed(2), - w: +b.width.toFixed(2), - h: +b.height.toFixed(2), - type: node.type, - }; - } - } - return { frames: frames.length, bounds }; -} diff --git a/App/BlurtiOS/Design/figma/foundations.js b/App/BlurtiOS/Design/figma/foundations.js deleted file mode 100644 index 5958d8bf..00000000 --- a/App/BlurtiOS/Design/figma/foundations.js +++ /dev/null @@ -1,189 +0,0 @@ -/* global figma, TOKENS, getPage, getSection, variableMap, hexToRGB, loadFonts, FONT, metric, autoLayout, textNode, paint, gradientPaint, VARS */ -// --------------------------------------------------------------------------- -// Foundations: variables, styles, specimens - -async function buildFoundations() { - if (!TOKENS) throw new Error("buildFoundations needs tokens.js in the call (scripts/design-figma-call.sh foundations)"); - const page = await getPage(PAGES.foundations); - const existingCollections = await figma.variables.getLocalVariableCollectionsAsync(); - const created = { collections: 0, variables: 0, aliases: 0, textStyles: 0, effectStyles: 0 }; - const collections = {}; - for (const name of TOKENS.groups) { - let c = existingCollections.find((x) => x.name === name); - if (!c) { - c = figma.variables.createVariableCollection(name); - created.collections += 1; - } - c.renameMode(c.modes[0].modeId, TOKENS.collections[name].mode); - collections[name] = c; - } - VARS = await variableMap(); - // Concrete values first, aliases second, so a target always exists. - for (const pass of ["values", "aliases"]) { - for (const name of TOKENS.groups) { - const c = collections[name]; - const modeId = c.modes[0].modeId; - for (const spec of TOKENS.collections[name].variables) { - if ((pass === "aliases") !== Boolean(spec.alias)) continue; - const key = `${name}:${spec.name}`; - let v = VARS.get(key); - if (!v) { - v = figma.variables.createVariable(spec.name, c, spec.type); - VARS.set(key, v); - created.variables += 1; - } - if (spec.alias) { - const target = VARS.get(spec.alias); - if (!target) throw new Error(`${key} aliases ${spec.alias}, which is missing`); - v.setValueForMode(modeId, figma.variables.createVariableAlias(target)); - created.aliases += 1; - } else if (spec.type === "COLOR") { - v.setValueForMode(modeId, { ...hexToRGB(spec.value), a: 1 }); - } else { - v.setValueForMode(modeId, spec.value); - } - v.scopes = spec.scopes; - v.description = spec.use || ""; - v.setVariableCodeSyntax("iOS", spec.codeSyntax); - } - } - } - - await loadFonts(); - const sizes = Object.fromEntries( - TOKENS.collections.Typography.variables.filter((v) => v.name.startsWith("size/")).map((v) => [v.name.slice(5), v.value]) - ); - const weights = Object.fromEntries( - TOKENS.collections.Typography.variables.filter((v) => v.name.startsWith("weight/")).map((v) => [v.name.slice(7), v.value]) - ); - const weightStyle = { regular: FONT.regular, medium: FONT.medium, semibold: FONT.semibold }; - const textStyleSpecs = [ - ["Key/Letter", sizes.letter, weights.letter], - ["Key/Legend", sizes.legend, weights.legend], - ["Key/Popup", sizes.popup, weights.popup], - ["Term/Text", sizes.term, weights.term], - ["Glyph", sizes.glyph, weights.glyph], - ]; - const textStyles = await figma.getLocalTextStylesAsync(); - for (const [name, size, weight] of textStyleSpecs) { - let s = textStyles.find((x) => x.name === name); - if (!s) { - s = figma.createTextStyle(); - s.name = name; - created.textStyles += 1; - } - s.fontName = { family: FONT.family, style: weightStyle[weight] }; - s.fontSize = size; - } - // The two gradients as paint styles, so a later call can draw them without - // carrying the token data (core.js › gradientPaint falls back to these). - const paintStyles = await figma.getLocalPaintStylesAsync(); - for (const name of Object.keys(TOKENS.gradients)) { - let ps = paintStyles.find((x) => x.name === `Gradient/${name}`); - if (!ps) { - ps = figma.createPaintStyle(); - ps.name = `Gradient/${name}`; - created.paintStyles = (created.paintStyles || 0) + 1; - } - ps.paints = [gradientPaint(name)]; - ps.description = TOKENS.gradients[name].use || ""; - } - const effectStyles = await figma.getLocalEffectStylesAsync(); - let shadow = effectStyles.find((x) => x.name === "Shadow/Popup"); - if (!shadow) { - shadow = figma.createEffectStyle(); - shadow.name = "Shadow/Popup"; - created.effectStyles += 1; - } - // Figma's blur is about twice SwiftUI's shadow radius; the generator's - // DESIGN.md note says the same, so the two stay one number apart on purpose. - shadow.effects = [ - { - type: "DROP_SHADOW", - color: { r: 0, g: 0, b: 0, a: metric("opacity/popup-shadow") }, - offset: { x: 0, y: metric("popup/shadow-y") }, - radius: metric("popup/shadow-radius") * 2, - spread: 0, - visible: true, - blendMode: "NORMAL", - }, - ]; - - // Specimens: swatches for every colour, a line per number, all bound. - const ids = []; - const colours = getSection(page, "Colour", 0, 0); - const grid = autoLayout("VERTICAL", { name: "Swatches", itemSpacing: 8 }); - for (const name of ["Brand", "Themes", "Keyboard"]) { - const row = autoLayout("VERTICAL", { name, itemSpacing: 4 }); - row.appendChild(await textNode(name, { size: 14, weight: FONT.medium, fillRef: "Brand:ink" })); - const wrap = autoLayout("HORIZONTAL", { name: `${name} swatches`, itemSpacing: 8 }); - wrap.layoutWrap = "WRAP"; - wrap.counterAxisSpacing = 8; - wrap.resize(1200, 10); - wrap.primaryAxisSizingMode = "FIXED"; - for (const spec of TOKENS.collections[name].variables) { - const cell = autoLayout("VERTICAL", { name: spec.name, itemSpacing: 2 }); - const swatch = figma.createRectangle(); - swatch.resize(64, 40); - swatch.cornerRadius = 4; - swatch.fills = [await paint(`${name}:${spec.name}`)]; - cell.appendChild(swatch); - cell.appendChild(await textNode(spec.name, { size: 9, fillRef: "Brand:ink" })); - cell.appendChild(await textNode(spec.value, { size: 9, fillRef: "Brand:ink" })); - wrap.appendChild(cell); - } - row.appendChild(wrap); - grid.appendChild(row); - } - const oldGrid = colours.children.find((n) => n.name === "Swatches"); - if (oldGrid) oldGrid.remove(); - colours.appendChild(grid); - colours.resizeWithoutConstraints(grid.width + 80, grid.height + 80); - grid.x = 40; - grid.y = 40; - ids.push(grid.id); - - const numbers = getSection(page, "Numbers", 0, colours.height + 80); - const list = autoLayout("VERTICAL", { name: "Tokens", itemSpacing: 2 }); - for (const name of ["Metrics", "Typography", "Motion"]) { - list.appendChild(await textNode(name, { size: 14, weight: FONT.medium, fillRef: "Brand:ink" })); - for (const spec of TOKENS.collections[name].variables) { - list.appendChild( - await textNode(`${spec.name} = ${spec.value} · ${spec.codeSyntax}${spec.use ? " — " + spec.use : ""}`, { - size: 10, - fillRef: "Brand:ink", - }) - ); - } - } - const oldList = numbers.children.find((n) => n.name === "Tokens"); - if (oldList) oldList.remove(); - numbers.appendChild(list); - numbers.resizeWithoutConstraints(list.width + 80, list.height + 80); - list.x = 40; - list.y = 40; - ids.push(list.id); - - const recipe = getSection(page, "Orb recipe", colours.width + 80, 0); - const note = await textNode( - [ - "The orb is the one thing Figma does not draw. It is a 3 × 3 MeshGradient whose edge midpoints and centre", - "drift on slow sines (further with the voice), under a soft upper-left light (opacity/orb-light,", - "orb/light-x, orb/light-y, orb/light-radius) and film grain (opacity/grain; a seeded scatter of 1 pt dots,", - "one per 26 pt²). The words landing pours cobolt in from the centre (drop, drop-rise, drop-hold) with six", - "four-point sparkles. Orb/Disc's fills are stills the app renders (-BlurtOrb ); the", - "parameters above are the variables. Source: App/BlurtiOS/BlurtKeyboard/Sources/PrismOrb.swift.", - ].join("\n"), - { size: 11, fillRef: "Brand:ink" } - ); - note.textAutoResize = "HEIGHT"; - note.resize(720, 10); - const oldNote = recipe.children.find((n) => n.type === "TEXT"); - if (oldNote) oldNote.remove(); - recipe.appendChild(note); - recipe.resizeWithoutConstraints(800, note.height + 80); - note.x = 40; - note.y = 40; - - return { page: page.id, created, specimenIds: ids, variables: VARS.size }; -} diff --git a/App/BlurtiOS/Design/figma/layouts.js b/App/BlurtiOS/Design/figma/layouts.js deleted file mode 100644 index 8ccbcdbc..00000000 --- a/App/BlurtiOS/Design/figma/layouts.js +++ /dev/null @@ -1,222 +0,0 @@ -/* global figma, getPage, getSection, variableMap, ensureTokens, loadFonts, FONT, metric, autoLayout, textNode, paint, bind, symbolChar, DEVICE_WIDTH, DESIGN_THEME, STATES, PAGES, findComponentSet, findComponent, VARS */ -// --------------------------------------------------------------------------- -// Layouts (03 Layouts): the three keyboards as frames of instances, one per -// state, named exactly as the gallery captions them (//) - -/** The instance's label, written on its text node: setProperties refuses a - * text property whose font Figma marks missing, which it does for the local - * SF Pro under the MCP runtime even after loadFontAsync; a direct write goes - * through, and renders the same. */ -function setLabel(instance, label) { - const t = instance.findOne((n) => n.type === "TEXT" && n.name === "Label"); - if (t) t.characters = label; -} - -const STATE_TO_MIC = { - off: "Off", - start: "Off", - idle: "Idle", - connecting: "Working", - recording: "Recording", - processing: "Working", - pasted: "Pasted", - copied: "Copied", - error: "Error", - landed: "Pasted", -}; - -async function layoutRoot(name, height) { - const f = figma.createFrame(); - f.name = name; - f.layoutMode = "VERTICAL"; - f.primaryAxisSizingMode = "FIXED"; - f.counterAxisSizingMode = "FIXED"; - f.resize(DEVICE_WIDTH, height); - f.fills = [await paint("Keyboard:kb/surface")]; - f.clipsContent = true; - await bind(f, "paddingLeft", "Metrics:margin/side"); - await bind(f, "paddingRight", "Metrics:margin/side"); - await bind(f, "paddingTop", "Metrics:margin/vertical"); - await bind(f, "paddingBottom", "Metrics:margin/vertical"); - return f; -} - -async function keyInstance(sets, tone, label, widthRef) { - const variant = sets.key.children.find((c) => c.name.includes(`Tone=${tone}`) && c.name.includes("State=Up")); - const i = variant.createInstance(); - setLabel(i, label); - i.name = label === "space" ? "space" : `key ${label}`; - if (widthRef) { - i.layoutSizingHorizontal = "FIXED"; - i.resize(metric(widthRef), i.height); - await bind(i, "width", `Metrics:${widthRef}`); - } - return i; -} - -async function bottomRow(sets, parent, { withSymbols }) { - const row = autoLayout("HORIZONTAL", { name: "bottom row" }); - await bind(row, "itemSpacing", "Metrics:key/gap"); - row.counterAxisAlignItems = "CENTER"; - parent.appendChild(row); - row.layoutSizingHorizontal = "FILL"; - if (withSymbols) row.appendChild(await keyInstance(sets, "Modifier", "123", "key/side-width-402")); - row.appendChild(await keyInstance(sets, "Modifier", symbolChar("globe", "🌐"), withSymbols ? "key/side-width-402" : null)); - const space = await keyInstance(sets, "Key", "space", null); - row.appendChild(space); - space.layoutSizingHorizontal = "FILL"; - if (!withSymbols) row.appendChild(await keyInstance(sets, "Modifier", symbolChar("delete.left", "⌫"), null)); - row.appendChild( - await keyInstance(sets, "Modifier", symbolChar("return", "↩"), withSymbols ? "key/return-width-402" : null) - ); - return row; -} - -async function buildPanelFrame(sets, state, theme) { - const f = await layoutRoot(`panel/${state}/${theme}`, metric("layout/panel")); - await bind(f, "itemSpacing", "Metrics:panel/spacing"); - const voice = autoLayout("VERTICAL", { name: "voice" }); - voice.primaryAxisAlignItems = "CENTER"; - voice.counterAxisAlignItems = "CENTER"; - f.appendChild(voice); - voice.layoutSizingHorizontal = "FILL"; - voice.layoutSizingVertical = "FILL"; - const mic = sets.micKey.children - .find((c) => c.name.includes("Size=Panel") && c.name.includes(`State=${STATE_TO_MIC[state] || "Idle"}`)) - .createInstance(); - mic.name = "MicKey"; - voice.appendChild(mic); - await bottomRow(sets, f, { withSymbols: false }); - const plus = sets.addTermKey.children.find((c) => c.name.includes("Saved=False")).createInstance(); - plus.name = "AddTermKey"; - f.appendChild(plus); - plus.layoutPositioning = "ABSOLUTE"; - plus.x = metric("addterm/inset"); - plus.y = metric("addterm/inset"); - if (["connecting", "recording", "processing"].includes(state)) { - const cancel = sets.cancelKey.createInstance(); - cancel.name = "CancelKey"; - f.appendChild(cancel); - cancel.layoutPositioning = "ABSOLUTE"; - cancel.constraints = { horizontal: "MAX", vertical: "MIN" }; - cancel.x = DEVICE_WIDTH - metric("margin/side") - cancel.width; - cancel.y = metric("margin/vertical"); - } - return f; -} - -async function voiceBarInstance(sets, state, hasFullAccess) { - const mode = !hasFullAccess ? "NoFullAccess" : state === "term" ? "Term" : state === "recording" ? "Wave" : "Orb"; - const i = sets.voiceBar.children.find((c) => c.name.includes(`Mode=${mode}`)).createInstance(); - i.name = "VoiceBar"; - if (mode === "Orb") { - const mic = i.findOne((n) => n.type === "INSTANCE" && n.name.startsWith("Size=Bar")); - if (mic) { - const target = sets.micKey.children.find( - (c) => c.name.includes("Size=Bar") && c.name.includes(`State=${STATE_TO_MIC[state] || "Idle"}`) - ); - if (target) mic.swapComponent(target); - } - } - return i; -} - -async function buildSlimBarFrame(sets, state, theme) { - const f = await layoutRoot(`slimBar/${state}/${theme}`, metric("layout/slim")); - const row = autoLayout("HORIZONTAL", { name: "row" }); - await bind(row, "itemSpacing", "Metrics:slim/spacing"); - row.counterAxisAlignItems = "CENTER"; - f.appendChild(row); - row.layoutSizingHorizontal = "FILL"; - row.appendChild(await keyInstance(sets, "Modifier", symbolChar("globe", "🌐"), null)); - const bar = await voiceBarInstance(sets, state, state !== "off"); - row.appendChild(bar); - bar.layoutSizingHorizontal = "FILL"; - row.appendChild(await keyInstance(sets, "Modifier", symbolChar("delete.left", "⌫"), null)); - row.appendChild(await keyInstance(sets, "Modifier", symbolChar("return", "↩"), null)); - return f; -} - -async function buildFullFrame(sets, state, theme) { - const f = await layoutRoot(`full/${state}/${theme}`, metric("layout/full")); - await bind(f, "itemSpacing", "Metrics:row/gap"); - const bar = await voiceBarInstance(sets, state, state !== "off"); - f.appendChild(bar); - bar.layoutSizingHorizontal = "FILL"; - const rows = ["qwertyuiop", "asdfghjkl", "zxcvbnm"]; - const letter = (ch) => { - const v = sets.letterKey.children.find((c) => c.name.includes("State=Up")).createInstance(); - setLabel(v, ch); - v.name = `key ${ch}`; - return v; - }; - for (const [index, letters] of rows.entries()) { - const row = autoLayout("HORIZONTAL", { name: `row ${index + 1}` }); - row.primaryAxisAlignItems = "CENTER"; - row.counterAxisAlignItems = "CENTER"; - f.appendChild(row); - row.layoutSizingHorizontal = "FILL"; - if (index === 2) { - row.itemSpacing = metric("key/gap") * metric("key/side-gap-factor"); - row.appendChild(await keyInstance(sets, "Modifier", symbolChar("shift", "⇧"), "key/side-width-402")); - const inner = autoLayout("HORIZONTAL", { name: "letters" }); - await bind(inner, "itemSpacing", "Metrics:key/gap"); - row.appendChild(inner); - for (const ch of letters) inner.appendChild(letter(ch)); - row.appendChild(await keyInstance(sets, "Modifier", symbolChar("delete.left", "⌫"), "key/side-width-402")); - } else { - await bind(row, "itemSpacing", "Metrics:key/gap"); - for (const ch of letters) row.appendChild(letter(ch)); - } - } - await bottomRow(sets, f, { withSymbols: true }); - return f; -} - -async function buildLayouts() { - const components = await getPage(PAGES.components); - const sets = { - key: await findComponentSet(components, "Key"), - letterKey: await findComponentSet(components, "LetterKey"), - addTermKey: await findComponentSet(components, "AddTermKey"), - cancelKey: await findComponent(components, "CancelKey"), - micKey: await findComponentSet(components, "MicKey"), - voiceBar: await findComponentSet(components, "VoiceBar"), - }; - for (const [name, set] of Object.entries(sets)) if (!set) throw new Error(`component ${name} missing — run buildComponents first`); - await ensureTokens(); - const page = await getPage(PAGES.layouts); - VARS = await variableMap(); - await loadFonts(); - const builders = { Panel: buildPanelFrame, SlimBar: buildSlimBarFrame, Full: buildFullFrame }; - const built = {}; - let sectionX = 0; - for (const [name, build] of Object.entries(builders)) { - const section = getSection(page, name, sectionX, 0); - for (const child of [...section.children]) child.remove(); - const states = name === "Panel" ? STATES.filter((s) => s !== "term") : STATES; - let y = 40; - const ids = []; - for (const state of states) { - const caption = await textNode(`${name.charAt(0).toLowerCase() + name.slice(1)} · ${state} · ${DESIGN_THEME}`, { - size: 11, - weight: FONT.medium, - fillRef: "Brand:ink", - }); - section.appendChild(caption); - caption.x = 40; - caption.y = y; - y += 20; - const frame = await build(sets, state, DESIGN_THEME); - section.appendChild(frame); - frame.x = 40; - frame.y = y; - y += frame.height + 40; - ids.push(frame.id); - } - section.resizeWithoutConstraints(DEVICE_WIDTH + 80, y); - built[name] = ids; - sectionX += DEVICE_WIDTH + 160; - } - return { page: page.id, built }; -} diff --git a/App/BlurtiOS/Design/figma/manifest.json b/App/BlurtiOS/Design/figma/manifest.json deleted file mode 100644 index a4903a3d..00000000 --- a/App/BlurtiOS/Design/figma/manifest.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "name": "Blurt Keyboard — build", - "id": "blurt-keyboard-build", - "api": "1.0.0", - "main": "code.js", - "editorType": ["figma"], - "documentAccess": "dynamic-page", - "menu": [ - { "name": "1 · Foundations (variables, styles, specimens)", "command": "foundations" }, - { "name": "2 · Components", "command": "components" }, - { "name": "3 · Layouts (state rows)", "command": "layouts" }, - { "name": "4 · Theme sheet", "command": "theme-sheet" }, - { "separator": true }, - { "name": "Export tokens (console)", "command": "export-tokens" }, - { "name": "Export bounds (console)", "command": "export-bounds" }, - { "name": "Measure Apple reference (console)", "command": "measure-apple" } - ] -} diff --git a/App/BlurtiOS/Design/figma/plugin.js b/App/BlurtiOS/Design/figma/plugin.js deleted file mode 100644 index 0f3c5469..00000000 --- a/App/BlurtiOS/Design/figma/plugin.js +++ /dev/null @@ -1,31 +0,0 @@ -// The development-plugin entry: scripts/design-sync.sh concatenates -// tokens.js + lib.js + this file into .build/figma-plugin/code.js. Each menu -// command in manifest.json runs one builder; the result's first line is shown -// as the plugin closes, the whole thing is in the console. -/* global figma, buildFoundations, buildComponents, buildLayouts, themeSheet, exportTokens, exportBounds, measureApple */ - -const COMMANDS = { - foundations: buildFoundations, - components: buildComponents, - layouts: buildLayouts, - "theme-sheet": themeSheet, - "export-tokens": exportTokens, - "export-bounds": exportBounds, - "measure-apple": measureApple, -}; - -(async () => { - const run = COMMANDS[figma.command]; - if (!run) { - figma.closePlugin(`unknown command ${figma.command}`); - return; - } - try { - const result = await run(); - console.log(JSON.stringify(result, null, 2)); - figma.closePlugin(`${figma.command}: done (result in the console)`); - } catch (error) { - console.error(error); - figma.closePlugin(`${figma.command}: ${error.message}`); - } -})(); diff --git a/App/BlurtiOS/Design/figma/themes.js b/App/BlurtiOS/Design/figma/themes.js deleted file mode 100644 index a9f12770..00000000 --- a/App/BlurtiOS/Design/figma/themes.js +++ /dev/null @@ -1,73 +0,0 @@ -/* global figma, getPage, getSection, variableMap, ensureTokens, DEVICE_WIDTH, DESIGN_THEME, THEMES, ROLES, PAGES, VARS */ -// --------------------------------------------------------------------------- -// Themes: kb/* re-aliased to each theme's set in turn, the idle frames -// exported at 3× and placed as images, then ink restored. This is -// KeyboardPalette.resolve(_:dark:) in Figma — a Starter file has one mode. - -async function setDesignTheme(theme) { - VARS = await variableMap(); - const keyboard = (await figma.variables.getLocalVariableCollectionsAsync()).find((c) => c.name === "Keyboard"); - const modeId = keyboard.modes[0].modeId; - for (const role of ROLES) { - const kb = VARS.get(`Keyboard:kb/${role}`); - const target = VARS.get(`Themes:${theme}/${role}`); - if (!kb || !target) throw new Error(`no variable for kb/${role} → ${theme}`); - kb.setValueForMode(modeId, figma.variables.createVariableAlias(target)); - } -} - -async function themeSheet() { - await ensureTokens(); - const page = await getPage(PAGES.layouts); - const sheet = getSection(page, "Theme sheet", 3 * (DEVICE_WIDTH + 160), 0); - for (const child of [...sheet.children]) child.remove(); - const idle = page.findAll((n) => n.type === "FRAME" && /^(panel|slimBar|full)\/idle\//.test(n.name)); - if (idle.length === 0) throw new Error("no idle layout frames — run buildLayouts first"); - const placed = []; - let y = 40; - try { - for (const theme of THEMES) { - await setDesignTheme(theme); - let x = 40; - let rowHeight = 0; - for (const frame of idle) { - const bytes = await frame.exportAsync({ format: "PNG", constraint: { type: "SCALE", value: 3 } }); - const image = figma.createImage(bytes); - const rect = figma.createRectangle(); - rect.name = frame.name.replace(`/${DESIGN_THEME}`, `/${theme}`); - rect.resize(frame.width, frame.height); - rect.fills = [{ type: "IMAGE", imageHash: image.hash, scaleMode: "FILL" }]; - sheet.appendChild(rect); - rect.x = x; - rect.y = y; - x += frame.width + 40; - rowHeight = Math.max(rowHeight, frame.height); - placed.push(rect.id); - } - y += rowHeight + 60; - } - } finally { - await setDesignTheme(DESIGN_THEME); - } - sheet.resizeWithoutConstraints(idle.reduce((w, f) => w + f.width + 40, 40), y); - return { sheet: sheet.id, placed: placed.length, themes: THEMES.length }; -} - -/** Bounds of whatever was pasted from Apple's kit under "Apple reference". */ -async function measureApple() { - const page = await getPage(PAGES.layouts); - const section = page.children.find((n) => n.type === "SECTION" && n.name === "Apple reference"); - if (!section) throw new Error('no "Apple reference" section — paste the iOS 27 Keyboard instances into one'); - const out = {}; - for (const root of section.children) { - const origin = root.absoluteBoundingBox; - out[root.name] = root - .findAll((n) => n.absoluteBoundingBox && n.name) - .map((n) => { - const b = n.absoluteBoundingBox; - const radius = "cornerRadius" in n && typeof n.cornerRadius === "number" ? n.cornerRadius : null; - return { name: n.name, x: +(b.x - origin.x).toFixed(2), y: +(b.y - origin.y).toFixed(2), w: +b.width.toFixed(2), h: +b.height.toFixed(2), radius }; - }); - } - return out; -} diff --git a/App/BlurtiOS/Design/figma/tokens.js b/App/BlurtiOS/Design/figma/tokens.js deleted file mode 100644 index eeb9ff25..00000000 --- a/App/BlurtiOS/Design/figma/tokens.js +++ /dev/null @@ -1,260 +0,0 @@ -// Generated by scripts/design-tokens.swift from App/BlurtiOS/Design/tokens.json — do not edit. -// One line per variable (collection|name|type|value|alias|scopes|codeSyntax|use) -// and per gradient (GRADIENT|name|start|end|stops|use); core.js parses it. -// scripts/design-figma-call.sh puts it in front of core.js + foundations.js. -const TOKEN_LINES = `Brand|apple/dark-key|COLOR|#6B6B6B|||DesignTokens.Brand.appleDarkKey|the iPhone keyboard's dark key -Brand|apple/dark-modifier|COLOR|#464646|||DesignTokens.Brand.appleDarkModifier|the iPhone keyboard's dark modifier key -Brand|apple/dark-surface|COLOR|#2B2B2B|||DesignTokens.Brand.appleDarkSurface|the iPhone keyboard's dark surface -Brand|apple/light-modifier|COLOR|#ADB3BC|||DesignTokens.Brand.appleLightModifier|the iPhone keyboard's light modifier key -Brand|apple/light-surface|COLOR|#D1D5DB|||DesignTokens.Brand.appleLightSurface|the iPhone keyboard's light surface -Brand|black|COLOR|#000000|||DesignTokens.Brand.black| -Brand|card|COLOR|#EBE8E8|||DesignTokens.Brand.card|the warm card fill; the paper theme's surface -Brand|card-border|COLOR|#DEDBDB|||DesignTokens.Brand.cardBorder|the card's hairline; the paper theme's modifier key -Brand|cobolt|COLOR|#3923C7|||DesignTokens.Brand.cobolt|AssemblyAI's primary violet: the drop, never a key or a surface -Brand|green/100|COLOR|#CCE4D5|||DesignTokens.Brand.green100|the design system's UI-and-code green fill (unused on the phone yet) -Brand|green/200|COLOR|#99C8AC|||DesignTokens.Brand.green200|the design system's UI-and-code green highlight (unused on the phone yet) -Brand|green/400|COLOR|#67AD82|||DesignTokens.Brand.green400|the brand hue lifted for dark chrome: the meter, the ring, the wave on ink -Brand|green/700|COLOR|#01762F|||DesignTokens.Brand.green700|the wordmark green, light chrome (the app's accent in light) -Brand|green/mist|COLOR|#DBF5E6|||DesignTokens.Brand.greenMist|the pale green the orb lightens into -Brand|ink|COLOR|#1D1B16|||DesignTokens.Brand.ink|the brand ink: the Mac pill's body, the ink theme's surface -Brand|ink/600|COLOR|#3A362F|||DesignTokens.Brand.ink600|the Mac's dark card border -Brand|ink/700|COLOR|#33302A|||DesignTokens.Brand.ink700|an ordinary key on ink, one step up -Brand|ink/800|COLOR|#26231E|||DesignTokens.Brand.ink800|a modifier key on ink; the Mac's dark card fill -Brand|material/dark-key|COLOR|#575757|||DesignTokens.Brand.materialDarkKey|a key on the system's dark keyboard material (measured, iOS 27): the container case -Brand|material/dark-modifier|COLOR|#474747|||DesignTokens.Brand.materialDarkModifier|a modifier key on the system's dark material -Brand|material/dark-surface|COLOR|#373737|||DesignTokens.Brand.materialDarkSurface|the system's dark keyboard material (measured, iOS 27) -Brand|material/light-surface|COLOR|#E2E3E8|||DesignTokens.Brand.materialLightSurface|the system's light keyboard material (measured, iOS 27): what the gallery stands under a clear surface -Brand|neutral/300|COLOR|#D2D1D0|||DesignTokens.Brand.neutral300|black-100: the lightest warm grey -Brand|neutral/500|COLOR|#A5A4A2|||DesignTokens.Brand.neutral500|black-200: mono labels on the dark face -Brand|neutral/700|COLOR|#777673|||DesignTokens.Brand.neutral700|black-300: muted text and mono labels on the light face -Brand|neutral/900|COLOR|#4A4945|||DesignTokens.Brand.neutral900|black-400: body text on the light face -Brand|orange|COLOR|#E67F36|||DesignTokens.Brand.orange|the error word and ring, cancel, the Full Access note; never a red body -Brand|paper/200|COLOR|#ECEBE5|||DesignTokens.Brand.paper200|neutral-100: the light face's surface -Brand|paper/300|COLOR|#DAD7CB|||DesignTokens.Brand.paper300|neutral-200: a modifier key on the light face -Brand|paper/400|COLOR|#C7C3B2|||DesignTokens.Brand.paper400|neutral-300: hairlines and field borders on the light face -Brand|paper/page|COLOR|#FDFCF8|||DesignTokens.Brand.paperPage|the design system's page: the app's light ground -Brand|paper/tint|COLOR|#F5F3EB|||DesignTokens.Brand.paperTint|the warm off-white one step in: light cards, dark legends -Brand|violet/iris|COLOR|#887BDD|||DesignTokens.Brand.violetIris|the orb gradient's upper violet stop -Brand|violet/lavender|COLOR|#D7D3F4|||DesignTokens.Brand.violetLavender|the orb's lightest violet: its top and the gradient's ends -Brand|violet/periwinkle|COLOR|#B0A7E9|||DesignTokens.Brand.violetPeriwinkle|the orb's mid violet: the drop's halo -Brand|warm-white|COLOR|#F2EEE6|||DesignTokens.Brand.warmWhite|key legends on ink: warm white on warm ink -Brand|white|COLOR|#FFFFFF|||DesignTokens.Brand.white| -Themes|dark/container-key|COLOR|#575757|Brand:material/dark-key||DesignTokens.Themes.darkContainerKey| -Themes|dark/container-key-modifier|COLOR|#474747|Brand:material/dark-modifier||DesignTokens.Themes.darkContainerKeyModifier| -Themes|dark/field|COLOR|#33302A|Brand:ink/700||DesignTokens.Themes.darkField| -Themes|dark/field-border|COLOR|#3A362F|Brand:ink/600||DesignTokens.Themes.darkFieldBorder| -Themes|dark/key|COLOR|#33302A|Brand:ink/700||DesignTokens.Themes.darkKey| -Themes|dark/key-modifier|COLOR|#26231E|Brand:ink/800||DesignTokens.Themes.darkKeyModifier| -Themes|dark/legend|COLOR|#F5F3EB|Brand:paper/tint||DesignTokens.Themes.darkLegend| -Themes|dark/legend-secondary|COLOR|#A5A4A2|Brand:neutral/500||DesignTokens.Themes.darkLegendSecondary| -Themes|dark/material|COLOR|#373737|Brand:material/dark-surface||DesignTokens.Themes.darkMaterial| -Themes|dark/notice|COLOR|#E67F36|Brand:orange||DesignTokens.Themes.darkNotice| -Themes|dark/popup|COLOR|#33302A|Brand:ink/700||DesignTokens.Themes.darkPopup| -Themes|dark/signal|COLOR|#67AD82|Brand:green/400||DesignTokens.Themes.darkSignal| -Themes|dark/surface|COLOR|#1D1B16|Brand:ink||DesignTokens.Themes.darkSurface| -Themes|light/container-key|COLOR|#FFFFFF|Brand:white||DesignTokens.Themes.lightContainerKey| -Themes|light/container-key-modifier|COLOR|#DAD7CB|Brand:paper/300||DesignTokens.Themes.lightContainerKeyModifier| -Themes|light/field|COLOR|#FFFFFF|Brand:white||DesignTokens.Themes.lightField| -Themes|light/field-border|COLOR|#C7C3B2|Brand:paper/400||DesignTokens.Themes.lightFieldBorder| -Themes|light/key|COLOR|#FFFFFF|Brand:white||DesignTokens.Themes.lightKey| -Themes|light/key-modifier|COLOR|#DAD7CB|Brand:paper/300||DesignTokens.Themes.lightKeyModifier| -Themes|light/legend|COLOR|#1D1B16|Brand:ink||DesignTokens.Themes.lightLegend| -Themes|light/legend-secondary|COLOR|#777673|Brand:neutral/700||DesignTokens.Themes.lightLegendSecondary| -Themes|light/material|COLOR|#E2E3E8|Brand:material/light-surface||DesignTokens.Themes.lightMaterial| -Themes|light/notice|COLOR|#E67F36|Brand:orange||DesignTokens.Themes.lightNotice| -Themes|light/popup|COLOR|#FFFFFF|Brand:white||DesignTokens.Themes.lightPopup| -Themes|light/signal|COLOR|#01762F|Brand:green/700||DesignTokens.Themes.lightSignal| -Themes|light/surface|COLOR|#ECEBE5|Brand:paper/200||DesignTokens.Themes.lightSurface| -Keyboard|app/accent-dark|COLOR|#67AD82|Brand:green/400|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.appAccentDark|the catalog's AccentColor in dark -Keyboard|app/accent-light|COLOR|#01762F|Brand:green/700|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.appAccentLight|the catalog's AccentColor in light -Keyboard|app/card-border-dark|COLOR|#3A362F|Brand:ink/600|STROKE_COLOR|DesignTokens.Keyboard.appCardBorderDark|the catalog's CardBorder in dark -Keyboard|app/card-border-light|COLOR|#C7C3B2|Brand:paper/400|STROKE_COLOR|DesignTokens.Keyboard.appCardBorderLight|the catalog's CardBorder in light -Keyboard|app/card-fill-dark|COLOR|#26231E|Brand:ink/800|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.appCardFillDark|the catalog's CardFill in dark -Keyboard|app/card-fill-light|COLOR|#F5F3EB|Brand:paper/tint|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.appCardFillLight|the catalog's CardFill in light -Keyboard|app/cta-dark|COLOR|#67AD82|Brand:green/400|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.appCtaDark|the catalog's CTA in dark: the site's button green -Keyboard|app/cta-light|COLOR|#01762F|Brand:green/700|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.appCtaLight|the catalog's CTA in light: the one green button -Keyboard|app/cta-text-dark|COLOR|#1D1B16|Brand:ink|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.appCtaTextDark|the catalog's CTAText in dark: ink on green, as the site -Keyboard|app/cta-text-light|COLOR|#FFFFFF|Brand:white|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.appCtaTextLight|the catalog's CTAText in light -Keyboard|app/muted-dark|COLOR|#A5A4A2|Brand:neutral/500|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.appMutedDark|the catalog's Muted in dark -Keyboard|app/muted-light|COLOR|#777673|Brand:neutral/700|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.appMutedLight|the catalog's Muted in light: eyebrows, captions, secondary text -Keyboard|app/page-dark|COLOR|#1D1B16|Brand:ink|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.appPageDark|the catalog's Page in dark: ink, the website's ground -Keyboard|app/page-light|COLOR|#FDFCF8|Brand:paper/page|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.appPageLight|the catalog's Page in light: the design system's page -Keyboard|app/text-dark|COLOR|#F5F3EB|Brand:paper/tint|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.appTextDark|the catalog's Text in dark -Keyboard|app/text-light|COLOR|#1D1B16|Brand:ink|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.appTextLight|the catalog's Text in light -Keyboard|kb/cancel|COLOR|#E67F36|Brand:orange|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.kbCancel|the panel's cancel × -Keyboard|kb/field|COLOR|#33302A|Themes:dark/field|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.kbField|the key-term field -Keyboard|kb/field-border|COLOR|#3A362F|Themes:dark/field-border|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.kbFieldBorder|the field's hairline -Keyboard|kb/full-access-note|COLOR|#E67F36|Brand:orange|TEXT_FILL|DesignTokens.Keyboard.kbFullAccessNote|the one line of words the keyboard ever shows -Keyboard|kb/key|COLOR|#33302A|Themes:dark/key|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.kbKey|an ordinary key -Keyboard|kb/key-modifier|COLOR|#26231E|Themes:dark/key-modifier|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.kbKeyModifier|shift, delete, globe, return, 123, cancel -Keyboard|kb/legend|COLOR|#F5F3EB|Themes:dark/legend|TEXT_FILL|DesignTokens.Keyboard.kbLegend|key legends and bare glyphs -Keyboard|kb/legend-secondary|COLOR|#A5A4A2|Themes:dark/legend-secondary|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.kbLegendSecondary|the mono word labels (123, ABC, return, space) and the + at rest -Keyboard|kb/notice-error|COLOR|#E67F36|Brand:orange|STROKE_COLOR|DesignTokens.Keyboard.kbNoticeError|the solid ring and glyph for an error -Keyboard|kb/popup|COLOR|#33302A|Themes:dark/popup|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.kbPopup|the letter pop-up -Keyboard|kb/signal|COLOR|#67AD82|Themes:dark/signal|SHAPE_FILL,TEXT_FILL|DesignTokens.Keyboard.kbSignal|the wave, the caret, the saved check -Keyboard|kb/surface|COLOR|#1D1B16|Themes:dark/surface|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.kbSurface|the design face's surface (Figma binds to kb/*; Swift reads the palette) -Metrics|addterm/chip-gap|FLOAT|6||GAP|DesignTokens.Metrics.addtermChipGap|between the chip's glyph and the word -Metrics|addterm/chip-min-width|FLOAT|96||WIDTH_HEIGHT|DesignTokens.Metrics.addtermChipMinWidth|the least room a chip needs beside a centred mic; with less, the mic and the chip centre as a pair -Metrics|addterm/chip-pad|FLOAT|10||WIDTH_HEIGHT|DesignTokens.Metrics.addtermChipPad|the selected-word chip's side padding -Metrics|addterm/inset|FLOAT|6||GAP|DesignTokens.Metrics.addtermInset|the cancel × from the panel's far corner when the mic is at an edge -Metrics|app/button-height|FLOAT|40||WIDTH_HEIGHT|DesignTokens.Metrics.appButtonHeight|the brand's button -Metrics|app/button-pad|FLOAT|12||WIDTH_HEIGHT|DesignTokens.Metrics.appButtonPad|its side padding -Metrics|app/card-pad|FLOAT|16||WIDTH_HEIGHT|DesignTokens.Metrics.appCardPad|inside a card -Metrics|app/chip-gap|FLOAT|8||GAP|DesignTokens.Metrics.appChipGap|between chips -Metrics|app/chip-pad-x|FLOAT|12||WIDTH_HEIGHT|DesignTokens.Metrics.appChipPadX|a style chip's side padding -Metrics|app/chip-pad-y|FLOAT|8||WIDTH_HEIGHT|DesignTokens.Metrics.appChipPadY|and its top and bottom -Metrics|app/header-height|FLOAT|44||WIDTH_HEIGHT|DesignTokens.Metrics.appHeaderHeight|the home header: wordmark and gear -Metrics|app/hero-gap|FLOAT|14||GAP|DesignTokens.Metrics.appHeroGap|between the hero's pieces -Metrics|app/hero-pad|FLOAT|20||WIDTH_HEIGHT|DesignTokens.Metrics.appHeroPad|inside the hero card -Metrics|app/icon|FLOAT|20||WIDTH_HEIGHT|DesignTokens.Metrics.appIcon|the header's gear, the copy glyph -Metrics|app/line-gap|FLOAT|6||GAP|DesignTokens.Metrics.appLineGap|between lines of one thought -Metrics|app/page-pad|FLOAT|20||WIDTH_HEIGHT|DesignTokens.Metrics.appPagePad|the screens' side padding -Metrics|app/preview-gap|FLOAT|8||GAP|DesignTokens.Metrics.appPreviewGap|between the theme card's two faces -Metrics|app/section-gap|FLOAT|24||GAP|DesignTokens.Metrics.appSectionGap|between the home screen's sections -Metrics|app/setup-number-width|FLOAT|24||WIDTH_HEIGHT|DesignTokens.Metrics.appSetupNumberWidth|the setup steps' mono numerals -Metrics|app/stack-gap|FLOAT|12||GAP|DesignTokens.Metrics.appStackGap|between a section's eyebrow and its content, and between cards -Metrics|card/border|FLOAT|1||STROKE_FLOAT,WIDTH_HEIGHT|DesignTokens.Metrics.cardBorder|the card's hairline -Metrics|card/radius|FLOAT|12||CORNER_RADIUS|DesignTokens.Metrics.cardRadius|the app's cards (radius/card) -Metrics|caret/height|FLOAT|20||WIDTH_HEIGHT|DesignTokens.Metrics.caretHeight| -Metrics|caret/lead|FLOAT|1||GAP|DesignTokens.Metrics.caretLead|the caret's gap from the text -Metrics|caret/radius|FLOAT|1||CORNER_RADIUS|DesignTokens.Metrics.caretRadius| -Metrics|caret/width|FLOAT|2||STROKE_FLOAT,WIDTH_HEIGHT|DesignTokens.Metrics.caretWidth| -Metrics|glyph/hit|FLOAT|44||WIDTH_HEIGHT|DesignTokens.Metrics.glyphHit|the +, × and ✓ touch targets: the HIG's 44 pt square around a size/glyph symbol -Metrics|grille/bar-height|FLOAT|28||WIDTH_HEIGHT|DesignTokens.Metrics.grilleBarHeight| -Metrics|grille/bar-width|FLOAT|64||WIDTH_HEIGHT|DesignTokens.Metrics.grilleBarWidth|the grille in the voice bar -Metrics|grille/dot|FLOAT|2||WIDTH_HEIGHT|DesignTokens.Metrics.grilleDot|a dot's diameter -Metrics|grille/glint-arm|FLOAT|1.6||WIDTH_HEIGHT|DesignTokens.Metrics.grilleGlintArm|the cross glint's vertical arm, as a fraction of the grille's height -Metrics|grille/glint-width|FLOAT|1||WIDTH_HEIGHT|DesignTokens.Metrics.grilleGlintWidth|the glint's arms -Metrics|grille/home-height|FLOAT|108||WIDTH_HEIGHT|DesignTokens.Metrics.grilleHomeHeight| -Metrics|grille/home-width|FLOAT|240||WIDTH_HEIGHT|DesignTokens.Metrics.grilleHomeWidth|the grille on the home screen -Metrics|grille/panel-height|FLOAT|72||WIDTH_HEIGHT|DesignTokens.Metrics.grillePanelHeight| -Metrics|grille/panel-width|FLOAT|160||WIDTH_HEIGHT|DesignTokens.Metrics.grillePanelWidth|the grille in the panel -Metrics|grille/pitch|FLOAT|4||WIDTH_HEIGHT|DesignTokens.Metrics.grillePitch|the dot lattice: one dot every -Metrics|grille/sheen-width|FLOAT|0.35||WIDTH_HEIGHT|DesignTokens.Metrics.grilleSheenWidth|the sheen's band, as a fraction of the width -Metrics|key/abc-width-402|FLOAT|43.333||WIDTH_HEIGHT|DesignTokens.Metrics.keyAbcWidth402|123 and the globe at 402 pt: the iPhone's -Metrics|key/gap|FLOAT|6||GAP|DesignTokens.Metrics.keyGap|between keys, the iPhone's -Metrics|key/height|FLOAT|43||WIDTH_HEIGHT|DesignTokens.Metrics.keyHeight|every key: the iPhone's cap height (apple-geometry.json) -Metrics|key/letter-width-402|FLOAT|33.5||WIDTH_HEIGHT|DesignTokens.Metrics.keyLetterWidth402|a letter key at 402 pt: (width − 2 × margin/side − 9 × key/gap) / 10 -Metrics|key/min-width|FLOAT|43.333||WIDTH_HEIGHT|DesignTokens.Metrics.keyMinWidth|a key that isn't given a width: the iPhone's 123 key at 402 pt -Metrics|key/pad|FLOAT|4||GAP|DesignTokens.Metrics.keyPad|a legend's side padding on a min-width key -Metrics|key/radius|FLOAT|8||CORNER_RADIUS|DesignTokens.Metrics.keyRadius|flat keys, one colour at this corner: the iPhone's (fitted 8.17) -Metrics|key/reference-width|FLOAT|402||WIDTH_HEIGHT|DesignTokens.Metrics.keyReferenceWidth|the width the @402 tokens were measured at (iPhone 18 Pro); widths scale from it -Metrics|key/return-width-402|FLOAT|92.667||WIDTH_HEIGHT|DesignTokens.Metrics.keyReturnWidth402|return at 402 pt: two 123 keys and a gap -Metrics|key/side-gap|FLOAT|13.667||GAP|DesignTokens.Metrics.keySideGap|shift and delete stand this far from the letters: the iPhone's -Metrics|key/side-width-402|FLOAT|45.583||WIDTH_HEIGHT|DesignTokens.Metrics.keySideWidth402|shift and delete at 402 pt: what seven letters and the side gaps leave, halved (measured 45.5) -Metrics|key/space-width-402|FLOAT|191.667||WIDTH_HEIGHT|DesignTokens.Metrics.keySpaceWidth402|space at 402 pt beside 123, the globe and return: what is left (measured 191.333) -Metrics|layout/full|FLOAT|270||WIDTH_HEIGHT|DesignTokens.Metrics.layoutFull|margin/vertical + voicebar/height + 4 × key/height + 3 × row/gap + margin/bottom-keys -Metrics|layout/panel|FLOAT|216||WIDTH_HEIGHT|DesignTokens.Metrics.layoutPanel|chosen: room for the 96 orb over one key row -Metrics|layout/slim|FLOAT|60||WIDTH_HEIGHT|DesignTokens.Metrics.layoutSlim|2 × margin/vertical + voicebar/height -Metrics|margin/bottom-keys|FLOAT|13||WIDTH_HEIGHT|DesignTokens.Metrics.marginBottomKeys|under a bottom row of keys (the full keyboard, the panel): the iPhone's -Metrics|margin/side|FLOAT|6.5||WIDTH_HEIGHT|DesignTokens.Metrics.marginSide|at the keyboard's sides: the iPhone's cap margin, (402 − 10 letters − 9 gaps) / 2 -Metrics|margin/vertical|FLOAT|8||WIDTH_HEIGHT|DesignTokens.Metrics.marginVertical|the keyboard's top, and the slim bar's bottom -Metrics|opacity/disabled|FLOAT|0.4||OPACITY|DesignTokens.Metrics.opacityDisabled|the + without Full Access -Metrics|opacity/glint|FLOAT|0.95||OPACITY|DesignTokens.Metrics.opacityGlint|the cross glint when the words land -Metrics|opacity/grain-dark|FLOAT|0.14||OPACITY|DesignTokens.Metrics.opacityGrainDark|film grain over the dark face: matte, the brand's texture -Metrics|opacity/grain-light|FLOAT|0.08||OPACITY|DesignTokens.Metrics.opacityGrainLight|film grain over the light face: paper, lighter -Metrics|opacity/grille-rest|FLOAT|0.55||OPACITY|DesignTokens.Metrics.opacityGrilleRest|the dots at rest, over the key colour -Metrics|opacity/hairline|FLOAT|0.5||OPACITY|DesignTokens.Metrics.opacityHairline| -Metrics|opacity/legend|FLOAT|1||OPACITY|DesignTokens.Metrics.opacityLegend|key legends over the cap; below 1 they sit back -Metrics|opacity/legend-muted|FLOAT|0.5||OPACITY|DesignTokens.Metrics.opacityLegendMuted|the + at rest -Metrics|opacity/off|FLOAT|0.6||OPACITY|DesignTokens.Metrics.opacityOff|the element when Blurt isn't ready — dim and still, but there: a tap opens the app -Metrics|opacity/placeholder|FLOAT|0.4||OPACITY|DesignTokens.Metrics.opacityPlaceholder|the field's placeholder -Metrics|opacity/popup-shadow|FLOAT|0.12||OPACITY|DesignTokens.Metrics.opacityPopupShadow| -Metrics|opacity/press-brighten|FLOAT|0.15||OPACITY|DesignTokens.Metrics.opacityPressBrighten|a key lightens this much while pressed -Metrics|opacity/pressed|FLOAT|0.85||OPACITY|DesignTokens.Metrics.opacityPressed|a brand button while pressed: a colour change, no lift -Metrics|opacity/sheen|FLOAT|0.22||OPACITY|DesignTokens.Metrics.opacitySheen|the light passing over the element at rest: chrome catching light -Metrics|opacity/surface-vignette|FLOAT|0||OPACITY|DesignTokens.Metrics.opacitySurfaceVignette|a soft darkening toward the surface's edges; 0 is none -Metrics|opacity/term-cancel|FLOAT|0.7||OPACITY|DesignTokens.Metrics.opacityTermCancel|the field's × -Metrics|panel/spacing|FLOAT|8||GAP|DesignTokens.Metrics.panelSpacing|under the panel's voice row, above its keys: the top margin again, so the mic is centred between the keyboard's top edge and the keys -Metrics|picker/preview-width|FLOAT|393||WIDTH_HEIGHT|DesignTokens.Metrics.pickerPreviewWidth|the theme card draws the keyboard at this width -Metrics|picker/radius|FLOAT|10||CORNER_RADIUS|DesignTokens.Metrics.pickerRadius|the theme card's preview corners -Metrics|picker/scale|FLOAT|0.42|||DesignTokens.Metrics.pickerScale|then scales it to fit two across -Metrics|popup/extra-width|FLOAT|18||WIDTH_HEIGHT|DesignTokens.Metrics.popupExtraWidth|the letter pop-up is the key width plus this -Metrics|popup/height|FLOAT|56||WIDTH_HEIGHT|DesignTokens.Metrics.popupHeight| -Metrics|popup/offset|FLOAT|50||WIDTH_HEIGHT|DesignTokens.Metrics.popupOffset|the pop-up rises this far from the key's top: it overlaps the key by popup/height minus this and stays inside the keyboard on the top row -Metrics|popup/radius|FLOAT|10||CORNER_RADIUS|DesignTokens.Metrics.popupRadius| -Metrics|popup/shadow-radius|FLOAT|8||WIDTH_HEIGHT|DesignTokens.Metrics.popupShadowRadius|the one thing that floats -Metrics|popup/shadow-y|FLOAT|2||WIDTH_HEIGHT|DesignTokens.Metrics.popupShadowY| -Metrics|radius/button|FLOAT|4||WIDTH_HEIGHT|DesignTokens.Metrics.radiusButton|the brand's buttons and the grille: rectangular, never a pill -Metrics|radius/card|FLOAT|12||WIDTH_HEIGHT|DesignTokens.Metrics.radiusCard|the brand's cards -Metrics|radius/hero|FLOAT|16||WIDTH_HEIGHT|DesignTokens.Metrics.radiusHero|the brand's featured cards -Metrics|radius/input|FLOAT|8||WIDTH_HEIGHT|DesignTokens.Metrics.radiusInput|the brand's inputs: the key-term field -Metrics|ribs/rest-height|FLOAT|16||WIDTH_HEIGHT|DesignTokens.Metrics.ribsRestHeight| -Metrics|ribs/rest-width|FLOAT|40||WIDTH_HEIGHT|DesignTokens.Metrics.ribsRestWidth|the ribs asleep: the wave's own bars at rest -Metrics|row/gap|FLOAT|11||GAP|DesignTokens.Metrics.rowGap|between rows, the iPhone's -Metrics|streak/arm|FLOAT|1.4||WIDTH_HEIGHT|DesignTokens.Metrics.streakArm|the landing flash's vertical arm, as a fraction of the box's height -Metrics|streak/height|FLOAT|2||WIDTH_HEIGHT|DesignTokens.Metrics.streakHeight|the light streak while recording -Metrics|streak/line|FLOAT|1||WIDTH_HEIGHT|DesignTokens.Metrics.streakLine|the hairline at rest -Metrics|streak/point|FLOAT|4||WIDTH_HEIGHT|DesignTokens.Metrics.streakPoint|the bright point at the centre -Metrics|surface/paint|FLOAT|0||WIDTH_HEIGHT|DesignTokens.Metrics.surfacePaint|1 paints the face's surface under the keys; 0 leaves it clear, so the host's own keyboard material (iOS 26's rounded container, which insets a third-party keyboard and cannot be painted over) is the surface, seamlessly, and the keys take the container colours -Metrics|surface/vignette-end|FLOAT|0.75||WIDTH_HEIGHT|DesignTokens.Metrics.surfaceVignetteEnd|where it is full -Metrics|surface/vignette-start|FLOAT|0.3||WIDTH_HEIGHT|DesignTokens.Metrics.surfaceVignetteStart|where the vignette begins, as a fraction of the keyboard's width -Metrics|term/border|FLOAT|1||WIDTH_HEIGHT|DesignTokens.Metrics.termBorder|the field's hairline -Metrics|term/gap|FLOAT|8||GAP|DesignTokens.Metrics.termGap|× · field · ✓ -Metrics|term/height|FLOAT|36||WIDTH_HEIGHT|DesignTokens.Metrics.termHeight|the key-term field's capsule -Metrics|term/inset|FLOAT|2||GAP|DesignTokens.Metrics.termInset|the field row's side inset -Metrics|term/pad|FLOAT|14||GAP|DesignTokens.Metrics.termPad|the field's side padding -Metrics|term/radius|FLOAT|8||CORNER_RADIUS|DesignTokens.Metrics.termRadius|the key-term field: the brand's input corners (radius/input) -Metrics|voice/bar-height|FLOAT|32||WIDTH_HEIGHT|DesignTokens.Metrics.voiceBarHeight| -Metrics|voice/bar-width|FLOAT|160||WIDTH_HEIGHT|DesignTokens.Metrics.voiceBarWidth|the voice element's box in the voice bar — the most it takes (the ribs awake, the streak); the + sits beside what shows -Metrics|voice/home-height|FLOAT|112||WIDTH_HEIGHT|DesignTokens.Metrics.voiceHomeHeight| -Metrics|voice/home-width|FLOAT|280||WIDTH_HEIGHT|DesignTokens.Metrics.voiceHomeWidth|the box on the home screen -Metrics|voice/panel-height|FLOAT|88||WIDTH_HEIGHT|DesignTokens.Metrics.voicePanelHeight| -Metrics|voice/panel-width|FLOAT|300||WIDTH_HEIGHT|DesignTokens.Metrics.voicePanelWidth|the box in the panel -Metrics|voice/press-scale|FLOAT|0.94||WIDTH_HEIGHT|DesignTokens.Metrics.voicePressScale|the element while pressed -Metrics|voicebar/addterm-clearance|FLOAT|6||GAP|DesignTokens.Metrics.voicebarAddtermClearance|between the mic key's edge and the add key's box (the + or the chip), the key gap -Metrics|voicebar/height|FLOAT|44||WIDTH_HEIGHT|DesignTokens.Metrics.voicebarHeight|the voice row, where the system puts its suggestion bar -Metrics|voicebar/note-gap|FLOAT|10||GAP|DesignTokens.Metrics.voicebarNoteGap|between the orb and the Full Access note -Metrics|wave/bar|FLOAT|2||STROKE_FLOAT,WIDTH_HEIGHT|DesignTokens.Metrics.waveBar|a wave bar's width -Metrics|wave/bar-height|FLOAT|24||WIDTH_HEIGHT|DesignTokens.Metrics.waveBarHeight| -Metrics|wave/gap|FLOAT|2||GAP|DesignTokens.Metrics.waveGap|between wave bars -Metrics|wave/home-height|FLOAT|44||WIDTH_HEIGHT|DesignTokens.Metrics.waveHomeHeight| -Metrics|wave/panel-height|FLOAT|40||WIDTH_HEIGHT|DesignTokens.Metrics.wavePanelHeight| -Metrics|wordmark/height|FLOAT|22||WIDTH_HEIGHT|DesignTokens.Metrics.wordmarkHeight| -Typography|ratio/voice-glyph|FLOAT|0.34|||DesignTokens.Typography.ratioVoiceGlyph|the clipboard and exclamation glyphs, as a fraction of the voice element's height -Typography|size/body|FLOAT|16||FONT_SIZE|DesignTokens.Typography.sizeBody|the app's body text -Typography|size/caption|FLOAT|14||FONT_SIZE|DesignTokens.Typography.sizeCaption|the app's small text -Typography|size/cta|FLOAT|14||FONT_SIZE|DesignTokens.Typography.sizeCta|a mono button label in the app (E2) -Typography|size/eyebrow|FLOAT|12||FONT_SIZE|DesignTokens.Typography.sizeEyebrow|a mono eyebrow in the app (E1) -Typography|size/glyph|FLOAT|17||FONT_SIZE|DesignTokens.Typography.sizeGlyph|the +, × and ✓ -Typography|size/label|FLOAT|12||FONT_SIZE|DesignTokens.Typography.sizeLabel|the mono word labels on keys: 123, ABC, #+=, space, the return label -Typography|size/legend|FLOAT|16||FONT_SIZE|DesignTokens.Typography.sizeLegend|every other key -Typography|size/letter|FLOAT|24||FONT_SIZE|DesignTokens.Typography.sizeLetter|letter keys: the iPhone's (estimated from the l glyph, apple-geometry.json) -Typography|size/popup|FLOAT|32||FONT_SIZE|DesignTokens.Typography.sizePopup|the letter pop-up -Typography|size/term|FLOAT|17||FONT_SIZE|DesignTokens.Typography.sizeTerm|the key-term field -Typography|size/title|FLOAT|34||FONT_SIZE|DesignTokens.Typography.sizeTitle|the app's serif headline -Typography|tracking/cta|FLOAT|1.4||LETTER_SPACING|DesignTokens.Typography.trackingCta|uppercase mono at 14: the brand's E2 tracking -Typography|tracking/eyebrow|FLOAT|1.2||LETTER_SPACING|DesignTokens.Typography.trackingEyebrow|uppercase mono at 12: the brand's E1 tracking -Typography|weight/glyph|STRING|medium||FONT_STYLE|DesignTokens.Typography.weightGlyph| -Typography|weight/label|STRING|medium||FONT_STYLE|DesignTokens.Typography.weightLabel| -Typography|weight/legend|STRING|medium||FONT_STYLE|DesignTokens.Typography.weightLegend| -Typography|weight/letter|STRING|regular||FONT_STYLE|DesignTokens.Typography.weightLetter| -Typography|weight/popup|STRING|regular||FONT_STYLE|DesignTokens.Typography.weightPopup| -Typography|weight/term|STRING|regular||FONT_STYLE|DesignTokens.Typography.weightTerm| -Typography|weight/voice-glyph|STRING|semibold||FONT_STYLE|DesignTokens.Typography.weightVoiceGlyph| -Motion|caret|FLOAT|0.5|||DesignTokens.Motion.caret|the caret's blink -Motion|chip-hold|FLOAT|0.6|||DesignTokens.Motion.chipHold|holding the chip opens the field instead of adding; longer than a firm tap -Motion|colour|FLOAT|0.2|||DesignTokens.Motion.colour|a colour or fill changing state: the brand's transition -Motion|ease/signature|STRING|0.22,1,0.36,1|||DesignTokens.Motion.easeSignature|the house curve for everything that moves; nothing springs -Motion|flip|FLOAT|0.25|||DesignTokens.Motion.flip|the panel's carousel -Motion|glint-life|FLOAT|0.5|||DesignTokens.Motion.glintLife|a facet's flash while recording -Motion|height-change|FLOAT|0.25|||DesignTokens.Motion.heightChange|the keyboard resizing -Motion|key-press|FLOAT|0.08|||DesignTokens.Motion.keyPress|a key lighting -Motion|landing|FLOAT|0.6|||DesignTokens.Motion.landing|the glint when the words land -Motion|press|FLOAT|0.1|||DesignTokens.Motion.press|the orb's press; the one thing that answers at once -Motion|ring-period|FLOAT|1.6|||DesignTokens.Motion.ringPeriod|one turn of the ring, the Mac's cadence -Motion|sheen|FLOAT|4|||DesignTokens.Motion.sheen|one pass of the light over the element at rest -Motion|sheen-working|FLOAT|1.6|||DesignTokens.Motion.sheenWorking|and while something is happening: the ring's cadence -Motion|state-fade|FLOAT|0.5|||DesignTokens.Motion.stateFade|every other change on the key: the ring, a glyph, the dimming -Motion|term-swap|FLOAT|0.4|||DesignTokens.Motion.termSwap|the voice bar becoming the field -Motion|wave-fade|FLOAT|0.7|||DesignTokens.Motion.waveFade|the orb and the wave crossing, either way -Fonts|body/bold|STRING|UN-11ST-Bold|||DesignTokens.Fonts.bodyBold| -Fonts|body/family|STRING|UN-11 ST||FONT_FAMILY|DesignTokens.Fonts.bodyFamily|the app's body text -Fonts|body/regular|STRING|UN-11ST-Regular|||DesignTokens.Fonts.bodyRegular| -Fonts|heading/family|STRING|Oceanic Text||FONT_FAMILY|DesignTokens.Fonts.headingFamily|the app's serif headlines, sentence case, tight -Fonts|heading/regular|STRING|OceanicText-Regular|||DesignTokens.Fonts.headingRegular| -Fonts|mono/family|STRING|Modern Gothic Mono||FONT_FAMILY|DesignTokens.Fonts.monoFamily|eyebrows, CTAs, the keyboard's word labels -Fonts|mono/light|STRING|ModernGothicMono-Light|||DesignTokens.Fonts.monoLight| -Fonts|mono/medium|STRING|ModernGothicMono-Medium|||DesignTokens.Fonts.monoMedium| -Fonts|mono/regular|STRING|ModernGothicMono-Regular|||DesignTokens.Fonts.monoRegular|`; -const GROUPS = ["Brand", "Themes", "Keyboard", "Metrics", "Typography", "Motion", "Fonts"]; diff --git a/App/BlurtiOS/Design/fonts/ModernGothicMono-Light.ttf b/App/BlurtiOS/Design/fonts/ModernGothicMono-Light.ttf deleted file mode 100644 index 1b39fa83a9d0402eb8501b12967d62b2ba6e3b76..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 56160 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
      UDN?x!+7kxi>9&M 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 BJBR=P diff --git a/App/BlurtiOS/Design/fonts/ModernGothicMono-Medium.ttf b/App/BlurtiOS/Design/fonts/ModernGothicMono-Medium.ttf deleted file mode 100644 index 20f1a54f78a0fbf2755481bf1abe4db2caf60ffb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 59148 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 b(+OrG3@z7LFqtqhF!Nx}!(4QipXvVt$bu|l diff --git a/App/BlurtiOS/Design/fonts/ModernGothicMono-Regular.ttf b/App/BlurtiOS/Design/fonts/ModernGothicMono-Regular.ttf deleted file mode 100644 index c6c87c9f23aff74463763f9061973fa0a6432db6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 58776 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

      d?NE+_?k0HDhjH4NN z9Yjs;Pa$}8L~V>$A>@Ve9t`hg=<|&nc!;5b_docsidr6?Mi^{l&M^3d8u?;;Muq$^ zSmoh7YVVBC)7KRE0=0LhCNb@(u`>ocf{P5iOhQ*MwF_;J@l^~DfZ&Z1HSOCBh9#KV z>|ICr7DhKPwO79hRwWGTgz-HUJc+;$8TuGvKA1MEFqjZ@0o!;CCV6lR4u;LRP({sC zyJP%DO>LQbQY&U^jB$^_A2GF1&4;(Q@-v8a2!&v{HwW`PY60>PVZy+ZB)GfBa0%Xz znlMwVhR5*kMUDDnMy*0WW3W+Xpy!_P`f zhNnnO5<|^U*CQsC#Q`d2Jf<%}s=y;#jK<2Q6`=?j<);9N@?!!Xh8!JYU`oJDM93Ob ztG}VLy=7~77L1rI`HjL%#7x3;Fs5K?K9?pNL;+(X z<{EK5;9`9)w})5pUHDkI7~jL+hot`>ZaSn3s z>m2L+oAXBJ9OnnlrkZ@sIyHY2k=RxY6IY2h#jko7cuE?rpReDmzoNgZe`{b3u7;+D z-wbOFk}=4bZv4%7%=o~?!KI0dzsn$(RF{=52V7pb2DIvq z8(257?&i8Vb???=>$RyjrrykYd+HU{?@&LZ{<-?^>VIj#HR#bGy20262O6Af@MnX! z4f%$S4Qn-Q*)X=@q=w5I9&K3MsCuJrjUpSZX!NbIf8!mE-!=(q^2MW{$2yN3kAFPM zJYzgZcs}!d;rYrd%4@Z^+Pk6mc<*OT9hycrec;3UO!qN06PkH7o7QYov$M^LeRaOx zzWsbNd}sUaYR)vT(Y$f<4$X%)&uqT9`R?YIn-}}F_Z#Xr!Ee3a1;1A<*cNqKv}`fF z#kdx^E$+4W)Y87CdrR+@-COo;Ik;tb%h;BQEhn{{({fqMH7z%_+|hDh%OfpMwJd7+ z*hyMWoQ2%8AS^mrXH~R1JKj44T|GfW=R!plZtva*{X*IOfrdB&! z<+M7}s<3s7)~8#4Yx8rP`2kJ=eFL_&ZPWITwqM&VX?MK6d;13+qB@jyj1RO5tQx2f z^ayMl7#lc0a8sbvN!5w(RIO7;r?Z{@>hz@3r=W&GErMnREekpnbR+0y(Cwf{L4`p@ zL2rV}gN5K`!C}EOf>#C~555%qcksK;s?PO0cj!E*^YG3iIwy6W(s@be^_}l_e%Zyp zOK_LSF5|n*@3NxH#xDE2oau7E%a<-v7ju{LF5kLN>H4Bu|8DQP$96x{{acS7J(l+{ z_hfsz_w?==)pK6Y4LzUrQulK072IoNuf-vnknoUkA?tcq?>)2k$v(JGqdxQcyz6V% zw{_pBz8Crl{qp-W{Tub~+kbrjb^Xuve=|TgAY{O-0gDH09I$J^$pO;OHGV$u^P_>k z4XQq<{h)|J8wTYMDj94wxaQ!-gS!kKJNVIH^N^}T+=e_HYBMx8JTUTIRI?Z<);`u4 z>lxcFwpVOuYX>JPC32NCb*8=&5vQQS-yGwQ~Y3(S$N&&uZJ0M(k z$tjQ;6qX-SfX|WwTuKVM>d+K|ox*v|Zn}$FD9s4P#CD@a%U;k-0)F%Yhu{^AM&JlZ zpS$UV0NEM0Qfmn;1V>gD#6r3!jzR!s56RK8i$=>e%EbUXU;{`~QHPR>x@an-R(~%9 zzQ__yU2-&ncB!a?Hk^{1x|C>SG=7gp#)@cUv_#7vCIrZhD{Y9=ZPf|^P&O=fajXy^ z^Y{cbXW-2)OAfU7P=Fnng}WTgehevnXLGt0IhMv4lZ| zN?zIpmN3X-34>ZJVUVRFOkEkqRED9figYNTA|0};46}kTTlniQI;=EZ6z-btJJ#of z!uDc+c}Gga^2y^b>Jc2#epLr@{l!~<$tm+eug|zGMo%9DClrImY~|iLlkMdhG{sZ- zXohCJPriPh(MlBVoWH6eJIXJ4ib4@B`aNMBh}S>)AB9K6>x+85NNRpnL*%=E*SqnH zS|`9k;~rNegXD6HoBq{-(}*s>jctR*$dO9MG6>QCZRdCcZuYEU4&F->ly z+qnVGe)RRZIc#*&sOUjk#VHeJj&~jfdp?6uD)s%`w(_vGzj!J4ajpXybn)Ru;W2#P znC>EcQaSMTzP(s^gm-|0{fn~*!bZ56Lk4`FrW5|m87~TVbEb1w;h@bR+|J3PUQ$hj z7&zj%nG+_O2A5BRf(momi?fO!z1Uks`V?VulT<%=!BCyAY$&=d!qRfp{s zJc#R2-b~kk>jc~IUPQm^$D(|=LD79gxww<5A`~YSnygxL!ri>9n%U*)N-jD2GHFKR z-+h8(u+NKr<#Nh5^yOy3hWxr%9@vL7%{Z+k_3n5|O{B&Fb)wuITrhfTH8qO%3Klrq~!DTIU?CpK3!)CKlK+)N6vrF7%R>f zr-&r8Jfk8GDwGR}sjO1!Z0@sPjO6~|9+X1QsNv(@z{g2d%!_I80~q)ZN>fQQSgeFk zBzqJ`dY3QO6>EhrJ|YWT+=uUePpO21XWDRAynY{PT2wj%@tS;ETslWTHGP zN=*YlXP1els^!_VOcO1WP7Gr)i76tziyGQq$5$^D$6duusunlBC- zv!3%~Th6}N>#ehJ5)mi!ILLnjK>^3JpoGjUr3e^;hX|6ZIT~O>&{c;J6;w{<%e1~M zNPjc{(q{xfdN`3#?UMO=QTCiNhJ?q+!rCL6^bt*Z5|U0a`=oQg;bo!%7TaP>>KaqJx zOCjXQX^|H3iIl_VzJrlT1am8$rKYmW9BWJJh_@*t*URpd+$sAnFJzb0Y@?XXVKS>s zW!mCc)D9-kjN-cgo20GGH&A1jCIaWnDN-%4X;;?%Q|CU@CAiAJWE77#FRV zG!0nWY&zp;DWoVxTqBabFrwwsvSIQ-I2IPxq{(J8%^(SYm(s{rWe2QVx^X1;KgR+$WB205nLtIUjB zaC8e%FJMgENEi2t1Wwo?iDsPnbUHWdjp;=ie(>plXe&G6aQ6WSxIijtO%c%2m51px z-kpTVX7tWx@&0SKU!^K7oTQJ>KEp(w1y?K%sitehW>%WRwPLdIjW8G{5veN* zEB!?w?y&e{3VJ1=BpONz&V%oYnRi&s02K+!eyWnlKME-`_qR<=i%L!pE@kjWRQ`;Mq_40M6zBXFE8Mit8PB0DCbC zdv_i~<~iiZ94gAFB!c^dBfg-ykviqO>VcZpl(42a!Zv*~DUGg^q)*3hXizBcP(x{OI$Bn}pSvn@Jya z!s4~!_AQwS>-AE+RH6|!W$m7N@VFB>;V7Fe0u+Tlv6YZ=)|JFAT&*+<%Hi9J}Y*paFpe@pfTX&VeXp|sRgsDnXz^T_Z{ z!9&737^D`kZlsc0ugR#_#5Ijxr|ks!5#UH_k#<^QCzoIkCD<9HcElAHI=0L-P)Gcr zh_FDV2tU@=RQjfnGX-wf-Of7>wia$q->s{ph!RO8)yL}}jXjfey7#?%)uVSut_fdc zCG8|vbS*{M>`HI@oP%YUYydsnRGs9+aL?(QX$c``=&tN%^IaND714^69lxl%h`Hv$ zFd9oCmM7D8i6CvsUm+Bmdby{fj<9|GYygzTDYc);DV(R zT`h6AMVtR0B}Pz%o`%B2xGO?C6IitAl$dJvR`QX$+)kPR=Y4u!`h;K=*>7qfM|FcM z&H?V4v%hn$l1ghkz0m79NqGXAq7D3_8A>QB=9Vn-KaSJgQcGxt$V!r`$r#9VzmBLzG1$Gm%R+LY*q8jE$Ip6g8mUCqO_Qll51U}IPJ#S79%ZyN5Rg-YmV`(o)N*mF!MJ1QHl2p@-+ZR^o*d0wo=G*IQbpc?Rs~m>tniVzm+xvJQr)L+>gV2R z_+shN0`e2A{~buy|KQ4arzvq5uTMxyjSK%_2flsn=F^)DC7bdd5j!UfxAGqRV(FHP zk1qT{>-`2TF{X`}tA4?4*eQZ--skeemIgV%T`UbfNG9D3Edwc|C`jL>%;?PVzpoq( zQYJ5eYDWbDigpB|riD1`T`N#n;2h(UFxsSYBylrE=n!GI6kvWPwK6@^fR!1E1^cbb zqI@ZzP9``u5rxBG)|F1px=x6sn9iQe0P(WrxP#u^4ne*%KGPhd`;Rr-#~+N{phTH#-+#t_oTez|YevDj(!BD; zbGh#|m?_@{v$$D>rrCwWM>L&qOjJBq;E)CUxN?OiyFmA`M8d43k!f^JlID`PuFxFU zn3QSFjCr=Eu_>$2tOZ?*mPxnMWGx&b*vPx--JtI$a{W1n8>M7=F>Eatkq53|s@DQ` zh7BPc1fwPDBxqcLBe;XoH;A7A@h55gZct z$f8VU{g=zlb2!pOn*1Y^cOFA|DSA;kl|ZS+;MmE zgB{?Wp0H=y3u>aNnlwrG|Nb^%&%DadgKrx%531WUuOXLt-~ZV+v?dGwhfnRZP|yvc zd+e~asQGKcJtB^;8@~~T1c0T&Tu=x?-q#C_NsAb*-;)xVJ=j?o8PKG6hbB`Dui0bs z)@XcbCQw+kWtOiq?L_k}5<@UIL_Q0ki>-B>-9vqY7eDC7r4~q?r z*nZQ}lSViXO~@%V%+U&~0!TV5d6R*<-Rr}>W*elR*jIBl@80VyHI&xqLdJv+i%$OI zh+Y^KaPi=#%fIQ@&eqswzHIY1`S21fMI3GxH+V~Smk9?+0hp7t>OH()oPn&ZrxjAm z1K(C(yz7r2=e4V25DvPBwDr-0 z-48xRkIFKKh_^)Q`e?dXplT z)ZWxmR|n2~{N8>Jgl{`4xtKpU5;I?t4^K${wCps8-T#m~Z(*jqF(rZZbozOXkS{rg zrLIU_ma?>l#E#jVxoOyIR#*cw zHeaz~zbkB&9#KBS#r3Om~p8>xmCJ}=(yttsa< zg#V=#c1TanCmM;7Ak%F{mFXzSbm1aJIKHJ`0{hSr+Hz=OrpK5A3Ss^Dxp|iL798%M&;im7da~K$e|;5658BOP~Qt zi8siyFK^A=U1S+nH_fGoyu(rXO6O zWShdj{@Gyo|50IOnaThQ+n zNnU1=L#E?n;bJChz9_uRQm%4@SBSVu)ga@YEXescf~+sIXkO)Vry_Sz7Wv0?NmtT? zgB(=vsU=0w+GwT+G*gkB3ABFTsqo`V%GA3oaum$%PQKUlW`B0qNcbbcTH!rD-Zlg&S>|6jso^?@?0r}?FU5J z69+g0{Y!%1{PS+$>;W6){I-wHIX`3|?N5tOKaw;$OuvCr6B1m}h9obr3$e ziUD#R^F?jKL~54YxH)T^CBAqpe*|guT5Mo`1(neY1!@*8e|4XNF%{ok3g7(^zFTMV zlUDnKVpb$|^@m#sH~{_ehT$U|fSP71*KjGzwkgKhr0acJ7o2;7-q_*h>5|ho>1?}{ z1I)v0%cD1JH*;XN70CB$=jgrKMYv@ksphdzpB7SluM^Cj;T+qYlNme>&7r2^;{!QO z+rbXL-wu{dX{`?CR~vH%`)RY zRpFC5UFrP5;nXwlmqh!5XkWrvPghVw21h1F!6xtE!LcJ(hdPIigcq&`;m%R5aLwC1 z<0UKXB<0$@Yj^J3yKH2rUNXM`@4j_A_FB9zO`P`SuoE5iw%NNy5Cn&F;35`m{11bG z*e!x~4`Ij2!+cKSr1qI2gq46~dR*!z%YcK#Knxt{2(A*&VF$F-kYy=4;UK&dxC3Pz z{Lfn@;V8UTqV>S~NQ*Uvri*px>xmEZxQPQYMS5a=Yq#j|^yAgi+!Emtu<{OydDK)4 zE%*EJ*h30=NOUs0`KH#;Tgp3tw(uBAeoLSi-axke%G%8;t^8;p5Kfq&_C?&&kHJ@i zVSVZ;uTL9#l778Jk~B~!thWQ!bL}Aadb`T(%0nx74MVvHg{>HLf}Bh@aUDlq|H+*; z-*p3}iz)`iuwal=^3w1IR)+j3;%xI}8VMR1#JwSA)1?q#45a=X$y)c{mwf+y>1Qx^ z{$HNg?sh>b6uQ)Ox3?&K4L84%St>JK^ydyxrhva$!?;+5KTrz}mi|VL z&M&10p&_P%G7+?cy5RvmB8Jc^6nYOTL=N?Vmft-wU&Y+1g^pWC~^s}*t43C~`%w44ga12^< z>Gty-TPBT#gU~V3Bsd72xbc@QJDfu?RHZhEFLVKJwloyNJ|!((EZQ z7J)GDnyEX!chj*AhC!PTjXv$1f8pB4C5Faq|EcM5QO*P7^GXaPYb8sXhkS7B7dfW? z82z!t@GX6v-FnFHEE}JfR38oV3Uq_V{0VoTXyfgpN7uEJ;D2wM+;Ol0mO&4ap?fyx zkNpRn_ihaJnPY&j$h7Pg_LK@&h*lJ~KZL7~3$T~FLh5_cJ%K*a+*v2wCSW;o#l2TM zc_&c0!+>0GAQ#zC@2mQPXvtxabCl8?ZFD(IF}f3@38k0CH8{7_uf&lQdBIcpq|FAv5SJDh}dhCSP&Ey8=zvxUSia!u|=IF zb0*(!_72pP_j~`}|MO(_*_mg`KGVzd8_}|v_9OM{7-qK=ET?A&j0vqfr@@>;mfa5& zaQfvCFDG*j$-NGB5%CpikV6{~uihf{q9yB*lCg3zBwlQ>C^d=igM}&`!UA6`vw#N3> z7H$vbv0|-LOWofXS+Zy&`kmG#Uc4`ERJNgCQ7e#Ma%CiMwqhC6(r6h!RhcT1oLgdd z#}sCt4Eu?&kD97%#JVoDFW_q@NoH$D`_QWHbgmm2={v@~1KgqD4x6gDw4}7rHoWX3 z1jB5mhiW#IgmxZwYIm|3m(kILdHfL`$HL<{77bf?yZ3qsreC42OTS?4&OVNm!|3rK z7wSya0Xz7|+u>mXrzJS3YL!z#TPYlEy0xcVFTF5Y4d~BHVH@=P9xvYDy z2ks@|+k!tvSxVEX!2vBq9PAjuLjOEsHjw=CNh7R7Vc3KulQIt`G4E$Nbt#5LCFoHD z{A97jZnxu%!%l9%=%ItKqyz;pE4VO@JjZ?9Nw-OE=0yWnv|KVEg>EVYhu;uE6&3*|5g;Y+JqJ+&|!w&a#y;5_Mi&{ zg7tAf(vlRREd}TTo1I!)Jk!}C$KF*CZz<#fMp<&VxIr`(Eh)}K}lqmj$=NvX@sD-#%M z$Sh}qdfMS>dq94YW4;$3(4v1!DmzP=^maB$p25OGBe9hu#qw+H4sHfr$o%wSN!ad6 zf>vQ4H)a*K_G63+unG|LV5-aiNxQlMwYH4Gl3}mM)}*%D1B^)Bfbb!MySnOZh8=Y_ zlXFe}v@@8oc4wWnWCYOfawU^ea=<_aL8J!!+{k?Y#Cy`aQ+=UxySh;3#E3D&WN;RGxU zlWbZ9gAN8IVOh86pU@;M9Tp+Nb+erjwiSP6$IdO81;`Jye_zFt6<+MQn>B2j~OJ;FR6W!|6L9yF(h8HCP(Evox+`f?lRcBeMn* z^fE|eo4+RLWlS14j(1f#_Wr0V><0%K&xsF-|MRepD}2T~G6ScO_C?`9(VaV_v`q~w z;s`aK#+=HzRjV;r9;&6agH>2GxQuy{HOUsAaVL%)J5BLrVZTSRUFLslSdzIgYyJLq1@Y&`!Mp`!KAl ztq5&>%?K!n_12u5%meJZg*f3Lp4h9@HJICovu*($0MQzcce?KN66=kK_Rl}Jvu%y` zb`Din{dJantB!HRchQM9a)ubM8!bt8DrzIVRzm&R6GNK$Qa6KT2Y1~S6;c$;X-Np~ zYNK2ghCA_^rJA(_^qH~SmXK5{zPAk;?$g~5|H%ztu~o8j*_mFX;!WarxzQyIQP+|; za_X-5P3v$7HR$Smy{<&8Hx|5&4Xm+mdTvm&OHZHw2(|KOXne#{WtRO8gS zUOLE)8gU(pjot8t!tllu!w)4l;=NDMF&KDw#z`yEdHIvs@N#`p( z`RXpIe-|@g@>+g=`O>d18eS?}u3@9nWiB^*X1nUvec0Y($9E(hKC)v#r_S()lhMDZ z^&*J=7d{CmI*zi#3`em(S+_E#zx`?dN3=AlOX@trewo{ok$wqVZDv6 zrxS!ZYv#tU^C6WFy?$eL#JIH|u;XO74Lh~th407DA2-&Ae$%T&2`k&X^tiy2`%+=HsR{Yk;X&(ER2x2_(3r(J%yUS`JeH0|Pvup&&h5IAl(@3cor8~$ z6Um2sQQ;;=)&+}KrGAsFgg5-O^u&R4zF8^#TQ=`Aq*@=_=t=0|TbFH1+xSGP;ZJe$ z_9+>2mkfOBg@LWkA3<)kV3xXE26tdyq|PA)^Lq>I;YYDUe#e` zbSO@wt4*l8k!Cw;3Z=$W1$q z>Ob7J4d+70iD!<2hE9%>Z)XT8u?Lbb`QA-!Q@d7|wzcZ?Nz1S^bQ7QtJ*q~mzQp$1 zuf$5e`t}w5ie)6(`k0h_>U9DD6`m+@JXR3yt6k*U&4XHm+2$Kb{kgYq-0{uaGq~3Z z+dBi{CInofUcR)7AN8f9%dcv*xr?pq=F<(y7rsP!{e~1GmMX95*S2vEgKT+TzvG$f zH;R5fcdQDbM23inkMIs$ImM$|9lVJl{dk>f) zWl34nua2?WhmX5WhW+f7OmtP=k%e!oAeC>DNh_JUJ^mJ)RUh9cZudKw)vPf5wgWa}?p2T%&u5>JfF->Ngvho*(Ky-dIG zrAmq7v=FsCEJ41$d2Y|y&9=ElT7Q1cIyHP-1?@gG#a6^Xxwxy1h?g&^@*aK1=%c9o&rMyQb%fd#dFFoF!6K*3h5m z{{;Q%1JIw48V%mU8R!l`To66NwEKxrqKIwH;*2;Yl141bsad3smYnZNM0L^fGMM>> z#{SWylcbXNIX|8!0{a>YK%lb<^z%!L!$M<31XAt<(Wf0bLCUaz^jR%0zt+G9}gW-cL+ctF09+zt>~YY3MP|#OhrLGAzM=1p0~d zN%{IX9V`9-;cBs*C)}l$S(-DVnWc{ZMzs7HuwNuCkO4ft$x|sNlI{>ZY3~%f7ul9= z*$qn%(oa6#h`~u%vL|8Ie;X_iy%%Xtrqij}zh+x|C@C5HcI%0J}BW1-ms(=pBr7xR6DD)sRJsiD+?7mRHEKQ;6tz7E8zi zvL2GohNN2n0|Fdoa`Y3yk`_*}0<m-n#1|7&)d6z5 z4n3>dsbIp&LK+0w;%_KC#UQ`#4Ui@$1db*;7TPQ|5n@vzHHZb}_N#+@V(QEH;)_&$ zMTLwdzH$j=-a%5-Rc@^e^@0RulO`xBV0b}_CTi}G-ZkZ|OM358Ee<9**Z+?-TcTg>Hl4#%k21Rx(iYz!1)e^2U zTg+Kz5rnI}vOogCGLHD7ycR=wg`2ai=7m2>9rBm5noSJnUx{QBX#shEUR)cBsvk-x zfM~MwfM|AWKs5P97A=J(yCKS}Y9;OEQpkQ+!FzGOLpIb0M4TtxFV|a=K0M1eBYj8a zzEQ+SvAk-p^qHqDo~ull9BQ*X8QEipVcVLhkt4@Ojujn>QAu;M zuM7IbE7L2A(~*MfWpOranyB(fgKElaq&A($I;6j9((;_RYweS28Z83p zq!joQ6m>*-MQzQR5u|W8$x&N7vqt4l0xskyku+6@f081V4?z@pY08z7#9YZK3zeUb z04u^ZRLO0F#LPfqX0XJ}KO(C0A!_w|#QQyqcLoa8yog`%IT}*ZWl~@L&4rz2vm~7p zt(F6Wv6!C2z@4m?%X36E8#$w9v#e2Purf0u;vsy$KM!r1rs@kVfvJbG;RVP>@EtZn zBqeTReJD`bIzwTlNu7a&&&W^sLL_{lE8#QH!p)2L?Ng+&>m&_n&q+=?X0sgJH8wFg z#%kG@q5xd(D@n9|N7td z*#od)_#*PPGW}HWIAR4R)m}8nfa%$eK|~)`lT+hK)k8RP7vC34c&>C3vszak02oOd zoB<`7vx#D4sU5MULTv1^ zLVMTmPuwg{9yHDt^_^ge^y@Whud>3iR<@+1A()hS7K{e))zsjO!UiUkGBau>S%4%Z zWLb71J^PTHolS6bNG*kGx|3DYFjh@>x~gdys_9M*{|)|ToxBgZLZ+lEl0-UYS`OMt z1+|Wx7gfC_$AhzcGmmf2+&?NIbeRn&83E3>ZpVHld^7_s1OHAj5@=~7Y;3b8$6y(2 zUm^B#m}Do65~+-3VtcbpEJ@qXA7b>;UZlGb+w|S#r^G|RaVPWilOf|s4UDRe;wyeS z2e~n^+L>7G5bOS5Ay#`wA}YHe0_YFi6t~S#7%G$P6R(i!f^(MDY56jZamsYVW^q!U zOapp_?^Q-RLgc()(osKGr@c~G;H=_B;(Qk*s^xTzqd%TFbdo`#<%?(fIm_Wdh^H>Z z69cHVriS`?;>p+_zMhHaaC{=fvwc4x4mI%{4up6{0gP#c%`z#_4~x7P#W0qFQPXDP zQ%=xs1_t&wn}PksZ}Z*07BGp3#)hrpja^fAyyaA6-0U>6nd-}yRu?lN*e}P4#l$^iDx+y zk6L~~fsI;Wx_mBL0UqQ;+u?=laXfKj%nb3E(iKRMOFuz^JQO$w9Zr6zq>@5JNjp|JQ zdxci;>Yz``Yps4ADBifBsAIGa>P0;zS~;*oG5as|-g0P>T6wyhb1>-`8rhH- zRQ$j*N`nFYdIqlMn&874_+{nX0D0vO!5o2PvO}7OY>McDn?5uBA`t~eTOn`M+4ksoq zTeoh9&(VH+nziULu<2CmWy99R@iFUt*RP&DX3WIND1nEALc8rUY+Vx-9zHf|Bnnp$ zb#pYx5H~s!WXs|1)1bNGlw*kdo+~b#S5n8=zC%xcJ2jZpIy4CVf_+2GnswWJQu^(0{7L>D4shll%RHxS zCI@IaZG{gcB`+tP$vGUrlHf{Luudt6CCl3Go6kT-M+=ANeT80eB*`L((&^dS@+Lcg71;pIDUA% z85!2uXbHVHGbm(yAmAKV-3vTRb&Wb1)nlZZeB0=_;}|5=G^#-WMakZC;?CWm^rlUM zI##c-r^5vsLZODm^6?HVkeNY1v7ciKJVAA>IvGj&aXEC-mK2+%*S$kA+qP_q3GQVD zf6qywBd`XxNb#P`h6xrY940wJZAYLVS&+hQmPTGU+R)t=f>X!@40(NZon#&?6rr zRlGsHuwr&2`uJW9B~tpgY8yBrXryiA1fgTl$i6LnCP1f#h_vqkk@imovO#N+OkM=I z#RE`eCf*9^oFb|#BS_Z>o<#r2b+!YPAx$kNKcU619>aMEUsC(Ph@WWHHp@sup@LyK zZ9uD>4y{6J^#ioF&$Uhh#$%+#O;Y|Aze2sNSMRCQGEk>L9(B>Jm*fXlbkOsc)u*J{qv}&YC{U0l&Kh{h$)LU{w^vXml zvD~Na4Lw7K_Oj8X#^9-wLaoipoHuM)J~`M%ml=C)ADWDr-+gK^gxgmp*hr{xU&Nk1 zE35}stljgYk68-NQra#f0AKn7VnYj|H znA=6BJFAkW9~#r9RiQU+?l1Ni$!OxojAA&LMXbyy3ful-iL?AowT)hlDU~ja~K4NGihQ6IFQBOU}2P*6cGuE_eD}rPonQC zEvO>k=qtJDO}tubXql}HE<3Y&W&z+87_S8Y1>>=F0rf$gH~G?d(HnG@lh#5U$yi?A zRa!cOgID6klkv=UpBf-D6i(trE!69bk+GOlRe%1jI#5r>tAoQ8_LhdXG_B{O=Q(;Vv6WTcA`kqF=#F-Fo%x02l$t2aR5WwpPntp4aKt3{k;wJ2@wLtA9fqFPziJUI)if23IDE=hY%(r~nPz;7t9xy9x6 z%K_U>3f`sdP+*6lz%ECD#f-2;*|Ubt%O{7}Xfz7!FcjE!cWFUG_*7P4M;iBy`+*hM z==dM@`IxJq0%+w`RXQqFe#&j~fG17g=+(YeP+FVhHX%(O(Cw_W`ai%63TvFJur{Gh z{aIlp`+wnyNdC}cOtT-zIDb^Y3D`7Nc+*(nO=E>O4TYB|A9Ff2T+v>gS)Dq{>6n+- zsUP#2*wm^lvk%MI7-2}mgMqPZK(-HYW;QeS|pIcqh8zopRAGnOf-N!HZ{M_Mm)iu_4%}cd>*}N3g zqV3fD0lJC~J296sSl)4wx%Fh=-(N@`+NM?SAx&(wu)*JrRDlMt{lcLkty=UN1UsCW zSUOHkh~SUBBgQPf+Ld&WquK@y>@d|to*Pe0{UIo(gXyJV0ugFlp?tLIdds>->J?eO zBrWMfOa4-lSR$=;v#uM7A^O(!)kH8k3ZIdGPCj#fwUs_GHe1y@~H9g<6=eg!W=)eg*I{S2q>%L{6wR!WDp3pBNf?TW3xm&l+oWFJZbhBEu z+BUCgGcOspZd`812(MEwU!Hr<4n?M@J4qYB!Ph-Tg-zCoMFI&i9=2~Ew5pBiS9~4c z>IyZjG~H}o$4EWwwdVvZT~K zmt!Oam*2s?06q>g$&pib|B$iFO8Xd_tP9D)i40TiF)(4Rh`DrcCjfI&a$i zsn&0SnL)qVO)RBJGv9TqzF!avKeH!Inm5UpdRNbQ8EhkA=V&BD%3i*F#r)`K9};<% zh8bRLyL}qF66Sf2$QN1XGfCSgUc~cN7}EiQ)-mZWFP^t}?qVw`l10BUj5{xorr6t3 zX)nW!^|RK*uM@{D9JOSWtzs)87}hlts4vvd-;xT3`P1jknC{cK&0%rgW3?PsA4uO) zFUf@0z|;yNKg-nWk9#$&Xgu}eCHxUvDcbms(&!FOk>4=l*k~c5klr?ys-Abr7^F#h zHR3t;-^h^tOH!s8Ez^qN z@WyUh>ZQ>#5@%q`WYRL{NtrBaGLmlOF6)N+SG#xq$u~biE#8apFH5~5OIb@^aVDinW02_tYDIt#xT9U%lGHYWq2as}7}W%{*|swf`#6JBAEaNp(oDNe;c1&TvS z=DUvYl=-eBs38nF{AL;G!N?_0H1{c`0p>;H6S z@21RMwpP3LjyU7{Q|7g2&strpYNOp~A9-lR*wI6L2ZZfON!h$7X;(t{&^5MIVFIb| zFAp8NerJSj;-=M`g`H~>5_kG0Z3*hxGc;&`4X7GCL#s+*U=Wir${g56*xSF`x=z6J zs1RRgXFFS`YT5nwoDzb5JUs4LK9 z0z{|=y9VBiSvP-Sto5>S&ZL?1X7~=Bx_S$cJnlSoY%GuB{Zt)G49JKD>SL_uKlP@O zP|x=@&vj$@r6f&(isC69dhD)rq5~G!{i~CSXh0t}Sc%&?D*2E~7hXPne6bYHmRD+3yaCo=o-hWZ<)Odf zrNqS@?1@@FMu%-jU|- z^<*$)oSR6Re@J|voA~IN<5Iat9}+RK==dbJXIi8 z#Ykq7S9At>A*h9)plmj~tJaU;7piDFVzK?7O)yPHtbV2*l7 z((jQ954{edOl>0Ovd__pl~WxuwtovYrCq+aT^`zeR~=tkyhc$R3NP|o31YjKwe#FT z+rCo?4}S9@i)ke&Qq8kMy{pIvNv_xa)Z-^7Pv+b>)xKh-cI~jAuPu(Q$yzr1zHTa0MRucmUV)-kL9CkFurpk0| z@Ej-An2F`C^%t_UM`dTF6F%GWK8=)7>&cdHxjXyLT)7f>x<;*jZ5u$3A+5pwHn*(w zE4oj%m;%(3YM5}-=s4*J6D(r`$XAGWPu#G+{U!_v8Z>d&{sXIb{9q%e9G>!k5fj5F z*b*mJVA}=__O-c|v}tu>oGmvQIsI23<@$g!Iag|D`N6^#lPx9{iJp*}?-yT}Pb< z#@T3i-czKDY_QZR>ZRxG>X$)(U%qGea$ z!L6IOueMpv2PWbzewi5csPj1W&--2*-wl34O1@nD97C@?>NHYN-f=SS#`jN5Wer_s zbe#ybxB{f2VA=l5q2!~td~SBUL2)BWlSUQVZ0h$zZ>uG#X5X%DD)`U>FY1%8t{hF= z2ZVs|eK<+=1(Yl3HT6$<|Hk0neTENiJHi&ad+g3VKFQm*?XymG?3FD^wY#Tfrf=JO z7)lh_nL#8Y#sp93L+E+5 zW^M1~4!Y-c=|%mQWXOy9FDwtqQQDSiVtU-Y^gJUhsn13LsAeSWJe27}xH@~QZnkz> zBh=a$mTj3k1j4JWkzwsYmTbWm|6TY1LkLl#otyfs@X_MzKoQes`iJY_K!rAL5_~?@tuaH_-uAbD76iE%7J}*u} zNGQ&x6r(k0b)2&+Mnh=`)b4VZ^y{+VX+oMmCuS_S_&$X=ngeMFi;BLsg*o!w zW9MJ3!~%WWnIro5^X)eH%=72FPapYl%YfF4Y*!4grgYA(?pwK$KL&`_Oa6~A4%I0a zQ+_#oH|=@~2D+n^p%>))TZ{+4g{EltpM-5o)+O%p**AQ{Km)$ z1R8USTrY0KD84V54HX7@9mrOtbAZ0eld@MynQLr0vb22r{P{b#o1L#&qj|HMHO@7= zW6N8L(vBTTN!y1F7%+S|#xQCVvfK+}41W~eG;$W(npuiw$zv7Zfu2NZHe{7I ztZ^ra1~N(Bq2B)PR^$&i))$gHYI454Y8`jLvp`77rwUFbtfW6{zbBMv+%o>qkMjlBDZ z!|^A4PaGLDXpaqN{ZeqG4^@0Ws(2Kt`2M^qevMV}{ix#Qe|K|zb9veI$>p)YIg;FA z2$m4qJ@QWNbyz8Eh`4MeJ5u=~_kXURvqqq{}FeqHwR4>n2FtLl$e8GEHz4>n~SUt}gq#;V2y@ zTiXA#8~BSTv4&wvl#rW_Mo1DZi;xyS5Uz*$_vkXs@-sb#9Od=MqgNRw6(;bs= z;h5n!r^{QX%RsnbU~gtFEw2cm z`4KC>KQwBCJv!;W;+0!*y%*V(7=EzN(d~&*M~5F+y(j$WBsALPHjPYPbTnw=l9T}( zR~`-8v+wA@O>rAX{@ms0s0~=IV*l_6SOoO$G@!L!G{!X+5)H7L2CHm_ARA!kIDmO@ zoCv6SQr3IXDq)Y|E>kEdiu+tiwfXY4)d?FmOk5Xi>jNwW4p85KiSOpUz60~bu;gP7 zCG?7BFGcZkEU~7>1>|r)(##vSKo0kNK7zS3yRt6A>$3N0t^yq=HhVhlYh z3}f$LETA#EBMA<}WqHL=VYK1RPI;9fX8E)z8*bY1yafaVBIP`8E+gf|7zE8Ti$$?`%fB*9W5z9$7C6E24nDmAaN;@b!ZT9A z>HtKRU zTS?r9f~Vbwv_uQU4e4SIl@+H0J}=KflK>)y&jMV2mf6|cQ7!yWdD&MxdHK(H`8;0! zW4Qmu%lR#gVwcsDiVD8dnQUPBGr73LDOh+rSLRF8QPDAs&X!5LF0`F-wdnj=aJdav zyzy!gHOc8h<7k9@VAJ}YTgR;Gz05Xd;naoEKFgLbUS(yMGC(M?%VtboWIJH6Ok-ZT z-7`lf^!M!-7Ct<9-K1^b*>+D`K5w#*-98f&!vJvDxrk{?V`tcU8(eV(E#5YIzb~#t zz`p>}VF~Vp(8!hBfvaFCu3bbBJzPjJv;>-aJ418YOt9ElOq|1Wx_o%cmSh{@`m#F} zxW=f%#&MIQ#)R8ruYA7i#Co~s&;mQYAhwU`8 ziM%^#u#v=ivj-Ztxv`UCqvFS9c8!@AyC6PdZN%ADagnQ{VkgHYt|1ZcNyHj2a$t32 zT-2JF)f401#w`XN2Wlan(|{og@`qJPt8T2`xO&;Dgf*4`V{!iU?|zSD^_fF;JTtCQ zb7b|Rh#I?50ZJ_Y?;1!oCK~KL1-SWf zoIOQ|Fj%z4)85N|NSJ_2Fc@oWE8)F2${WZ`Y#|2(xbb#ODm!~0G_LG}ZhYlIq0cII za|p-VGsBJc0rn(e6!VMn)5`eFdqK3I)q;QxhJ|((Jw81S*N)(6ADtLe)fC^1Esx`MHVc7+SlU zsGe#fe$Z2oYGST$9>wf5N5(~agB{__iy!x((b_p{CazhsVeGnb@oA)PI%#zHzA_s9 z_pZcn4ET%*3lqn!Ke>KuLd4oho93@syK(v2sEv=-FWWRVaRGYnn(M~i&g;9;nc&;V z4fNcs)Ambr_SpsS4P_E9qJPubaotAU&hlMxlK~w!3b4I2N1E=CS$}QqQ}&>Nb>8SN zP002i!_iCfAo4nFlU-+L{q?=|hO?L9hPdoyH?a=d&P{u6yxj$MApKn3GMtN+-I(8N z>+GEF`6#2KR(p9g64yMiG`C`>@W|WQN3*`!7HObs>dO@OCUVHf0$A2*WKaWXBP{SZ zN@>=1dT)2SP;lc*P z_?_rk*jx0%B}-TMXqCZqVw0?~n8Jq(+sFE^TW?&tbZxM()ft&-Nb{i zWCs#_xff6v3a}MHKiov!kq4T(pB~1y z;uQ^gy$o|m0UQhh$gu>{G)=8J9$L+T-?5nX0;Q36l!C6Vo~9l82-6Cu6EzjbNT|_c z+R~a%>>&E75AO1gP9#}RD=@?su$&=0Pv5@Q(*-U~Pk@4Tc7lQ#&3-`8!FRuXr>Ad$ zyPIMFbS{)7{V)l%@(yp(Ku-^M>#X=Ot>kaV@s6(^=xKZ;&X<%_c={Ux{hlGf`>7vT zB<~PPD$sq30NTe0XdkmCYSQxUO~9V+MOQ|2MK_8h$(!hy%r%jdN7&-;0Fi4aCa}n) zS1V`|&wnRB5I4YcYYcB7Z_*v|X5z+X4a7}8Y{Fm!Dm7L}8#uO~NL!OB>>*Rk4jBGg zo=lx0B|U$Emd6!_b3$ZbWhFr0_<&>*x=pZt&vKtEYY9~#sntXuw+5mHZ$j2of zG7R(Udk~MAG`>Va(t%fYxyjkhS(s9$ot5bx;{5$U_Xw73x+*}Po49Owe2fY3PfLXj zt2eAa=yR&i-WE-I^lLudde*ROQ9|5S-_2_$jtrkPWmKdM>Oj+k5fdkm3HF(0wA{N; zQohu%5vIGb>g-t3XkP3*gNuwc(E+R6t?||W^l+c&A>9#QOLw9@JYFyL@Km1{d@mod z@Mc^Tc;AdcEF9UqN3- z-(25aKLi&S&d|@*AJS*(bKTtBOl~$@TUghvsoN;GiEfMBZVRP_QNm1No)9hU5%vp5 zg&V?c;T74GHhq)We79`8>Se(H!L@-G9()I8j=k!3~vm-8+At6=wmEn ztZ1xiY+>wg3^z_N&M@vV9yA^?rW-SiZ%w>OFnO2?m}Ha9RL)e%RKwK3)ZEn0)XCJt z)ZaA7G}<)LG|4pEw9pi7iZksroi$xB-7wuX{cL(-dTx4a`omptm)yT{_jRw~UeCRe zdq4L>BgrG#GKG@?k5Je0Kl1IpbvV=+3LKuK9X=&2;MSOQmXUDpfu^=w+ns#55s&TJq%HKK;6n zY}>rk#*8Ryc|(yE_gfGjUtIUjkiKoe&UW-P{v#H+)%<@!2L!w0RG~w#L08y7!`Q`DM@S|J_oiugw0N-zF5z&yoJ?OTU#volf(##K1!bU;$ z@!t^MDJ6GSXolcel}(bHDdj{w!m(LySg|8|7#^b|mJJ&jKXM#y>~5BIKG~_h;kuj} zmo2;CbxRq_!T;J&?UE*TUxpMuFKqrK>&x#APPAu91Ci1&t1_Zm;L7S6A#B%`U7#(= zpCUQ}UD0UHo!wEC2oL?#c$^0RBajG;#0Ayt@HaaIZi6M{`}qNIK!e_4(4co2H0TRJ zgR&5wBY-!||MSnhv)uXIcj9_gQYG6l z)USAXK1KVI#*)U!7njD_a?{r8CgDdBTYJ zfxZpe*T=Ftm)7t)a+Vfk=QtV6zC`=VT_Z>J9A+IgLFh5GORvg4RC-be4Vu@hJLIcX zR_M0Zv3DBS%C}X|A2Uzy+q7q+ZDX8}zGvfsvp#Ve#$xRpBIMM&iNiV!-J#oSD02<* zR%??la*UQ6w7_*k0t1M62!M#Iw1}ZwFvExVrrytv+D5gQx8+f8Q?{RNru_jJ`=IH# z_2ZytL4tw!#@&)yC^ZzR!p-*2Zlv!#w96_1*KU|-nZHo96s{>+%4=7#6b5K#>sg{% ze$`HtTu0^u_e-P>!1Xmq>F%UE1YV2|v$b(NmZfh+^TEOGH?;t$M5Q`Z-+gW0ZNqI+ z)QvzFP`T7!)0NmT*($Bww#}(l5NtEcl@zIc5Q<~(8%E1znvX#C@FOBv4lYucW&ube z4~rxZo5Uum`tf-HnUZ>Duqfqe6Y}RJGV0@T$WgB2khlNj7GY}hCpXj1-IM~a(5m%1 z8KtvA@d=_d&vnn5v|FTK8`eVIRlB}Lq9d_a?kCAF;?7;d-nnO`tMp4NUH75sJ96j^ z>N-6n06xx9h}}a{2}h!Wnz!s7gtLg14Cb>zsD86WhCL^Z>^h>7&vc{t6ID^@i(}(H zUCNE_q)1*Q^wmcI4{6lYnGi}^lq|`s0To3GDbKud%r@@^cQb>@S2=aQ@ELqQj#e>+ z?#7y09(Ekms#5QH%98jviI{&r^Xf_Cy(MB%PAxeuFuel|OfM-9Oz-kPf$2?HyKY_F zT8TlY-4_k77m3nhoa9*|$$!`4(;tTFg|qW1gkV-q#~VCpx=30iHcDq@Kd5lG2EK?Gc9mckomaJ>E1~#nsx8ra2k|`b}Wity}>szE^74X zNGWOnYPg6i_ap}777pYz>4s>_HlolVsf7#@Q;6%PeJ*aftC^=WM1qtU8I$V~336$_$!r{U#dv=9x z#o@w`AwgS0QLq?<76ZAG430jrqI8saT$>jm)g9ciMztZwE?R-1;di$NDJG%VIl)3P z>c}yyK!I@H^oLvaq&Z9G&hnW(YtAgI6cL{|%O>p$Umvne((n$64(%C}(N%bH!-Z1P zH3Jbv>3nxwq>Kz+%#7J0lny*az2t;Mlr$CJwNhZ@h>(6h(laqZx-AAm*5WT%_CsAe z31vhH`x01LVvDobL6H_m3Y!c=e-(xrhLjOlb-}Hz(nr5Ds5zNE%?l6J~1^}SwV08v)+eFn`d#l_5DC_zD_ zfOJ(MA%Jj_(4x6vyu@yUmh=tLqG-ASOQ0KIhV~+=xO8?LTEwTK6dN;R!bYpakOGi9 z6^xS1l(U@ULKIICH+i7rkc_0+S>d9QHft%M9{^7D8d1tn(6OcDUo9z7uaY$=K;C9Ua_fFD)B&Cq?@rg4fsBMmtPC#i< zIzfU?O1P(N<2&R_$0C@UG^$7%Nu>E~!HJF~1rJH+=v%oZ&NE8%OQv376|&ISu+GNp zg@b_7ey`Y6DRqG&r4juJ2`g`GRh5&VpmGW4sB25=4mtIvKzQkAJ_|}1YNDjp$JjxM z;3fHI$9kX#0Sm%cnn%oCj!LVRFI$10c0VaE0ZUv>ydlwViC)5$Qj6Y6)!U!LT@UB( z-aFZ-qzzRm0P*-unI@qCXe-oC0?|7OI5I-pe{$Mj@rx1g$GZq-10{{JZ>B{^{B^ax zUQ%bv(r-6^lNb-jdEk%z({bKd9W%qO0Cr7yt|V6p<~LX!;IU)U3}y?iGt6#WAj|>W zD43(U2$&PN`7jr7%V0)x2{046Jus8FV=&XXYcQ{K_hJ6TsW5+s1{cp4$=?!hdT#J90YD-saUvi5Uy8J_z>%Xr9;cZ(&{q z&AufsHQt=S&E(!9HBNc3Z}kF)89XdsBrRY3w0tS6>wy5c)}<2e8+9?J25^kv`p2m40;4+k^*TrqzfgY-MQo0gHe|7B zR9i+#Et$#weWb)da10hhU^1$6KGidy`sn&sYBGF`XW@yA!mfvl3eTth;`(pW$oq2m zPh)-=UtT%=%043 zRkuE;vOaf}R)X&iv(u=D|3=}G)mGj9*GSCK#7h#%4O#x`AG#e4p1Ii3M6KyN$r14{WawBh_$2^8>6cH z7Zmct*;2Fo_((Z(`V+gBQhOE}LIow&%cr{LQ;q*SigCF@arzzLw1FKcski3JDAtQ{ zQdqw0M`}#I-Ar)ImzKa})Wm$so=<&r{VRp*@h1UqLvXVgd6 zzu7&~{5=QvXOwhL`kNhinB5;9Zqggg7bs_|$L#)zlGOi_FF(A$`e6Q@sb{(1;jO)c z%4^~NBUKtcoGk;RDr$Z|r;7f?4k0_+2rV|PjnJs38Xt4jC_FoQv}Sf1)%|}#{fAHx zc3)@6po0EOYIr{1NR8rkEX6#(T8H@oUtKdRV9W?wKN98_PE+IgLUXOkXq~TSQ%SQa z<)k&v{u&*p*|Rdo^Ks0co28kDH2Y@Eo}0~R?vOU-F0T14uDO=bd==Ad#%MNQYGwh= zrjX|PrAC+3%yLdsOY;oPwY+9iK{KmrCd*r%ucFZnwa^+eT4&JgD{5)*XCdgEabY6H zXwANg#$UxrYy9&yvzTV%`zK~&d@+ruq85G~&AyIiQ%B!|b`k+E-N8c>Fc{sv2Eh z^XsqCMVY_*7oA%lKuMFmYI&D5!1{1JKx|*D) zHcxJekl7#W=W5`O^-8Q4Vt;vVdC&Hk?MN*4KUQmIyk=g}%*&d231%V8o7yA18VIW~ zel4|kX4e%nsR5Wpg>hpzJ9g;pt{*~W-|@#P&5YN~E1KC?GcRlAC1&zXHFK6`4rC_x zn`Ww-O-0Qtui0QA!M)c{|7^}(Lz|hhIXA0Y0yw_F4EAfziaBUGt}^#6SBtBUG`HZ| zV(mcRs6l5xu1=eFt^K&5j_um`VO7BCmxsJ1gdt=0YvW2m+TU>1xY}F**970&PUHF# z@-{-oUm_%5&W|gG!#))tm+D*{t^wDSYXyn0(7x2>@Sd2ZeubHP5zL6oa22_#kY8P_ zR5asSa~)iKZk#)3#x=L1DU%|7MPc1a#g1)f^T!Sl4&-znP;ef1?W;{qJTKT^L;d&8(^$ z57&P-#|{{+n>PAi&5@&Zvqz8pXA|XEhd;K)q(g~zwgar+WvfHXETWlyFbkkOnox#B zlwA+he=|yd0hB*4l&OL!%dGe3wHm@!pcrk_%&#<4>p4(D4Y2>3Ick&-C{`PIlyNjv z8mFR}R+P`KydQr{S5ntfH(NhVe?WL|cx4ogC5?@ZLB^TJt;TGlYAR}KYlJzF5N> z%)9XdZ{Ur*iFfBkUc&hwPu|Rb!584a1jl{uF@J;qk>AH3;1BT!`4m2tKg=KD)A*zO zG5$E8&Y$2<@~8OII*YELPDU(j_0A17tQKl@Uv3ch9XFkufz_;8+-z@%-9_x_KUZ@znm(a0ZiMg|oM3`p8hxh1O8P--Wa<5R6O7jg-uEy~55&i)_i@(Re(Yc|Xuso3j$KQWClx+O5e_Dw^dL*2f z``Zupj6)O-{PoADqtvB;5<()lR{r(JCu;uPh4G*N`04OH{S)7VId`Gw=Rbb1=GP?D z`Siy(htKAp_$<$v1iw#zJR76wIiukA@y8c{FE*}leJ}T(GrB$f_`^GMF}P*t{kU7m zvs<6|NQdizydT!H8Nc8b@BDGw!M*(x?r6Bpb^fp#&UoG2#;_k}2dDiLPP7?rf$WD? zh4Ja#TD!GIE5qZD{nPRX3C_h7c7UO4X&*J=C?O8&rvt~X@d$Zv*Ig7IhQf)$y zSBRgiz5DS~o%Z}J?a5jaH-4Inm(_YR$`A8dl%M?x#~c@pmJBH^g2ts7Uku!=-msoY zlcw%Dq;VMUOfsLlT!g<^l-hrC+lR0x<2U;sT~{J~f!c5QKe~_S1U|s^LrwpOxVv%& z-kSd_{f|6VkZ-?#{PAx8$mM}Az5LmawV{9eTK*w&di!5~`~HzL8SN_TZ$AIAow&b; zx&ULCuK(~0{73FU^jM|;@mIyguS0GP;DZqp%hhrGIArB`lt(tU$;(w9BPE{q*4{aU zhTS*x$o=8W_(hFh`i%b({G*0wdt}T9>yJ>g5Q7$%=0ntcupZFayRkWqmn)7kpq;%i z>KjH0e|2ezQ3sQbbFa<7O$9d(`OS0r&$Az<*(ajEW4s^vuj5Upjc-2MR>mCV<6BY8 zQa-*FL_PiZX248_$&HN;KHc*x3m$rMvrKPrQ3Jzo&!4oFYOrSf0F{0Uq8Er^`>l!vtk81;N+cc0mDx%qZFjDRHM=0J?Z24Uni1S73s7+L+F;_NRp z$0!cq`1{Tqvzf&ZR(P{T13qPV?X#TysY2mha#a?7J76;r?*lyZ)_j!WuNAdWtQgzp3d$-ThjRh7f&5SYMc^Tb>o_u3eAIdsi2t^>Tc{r$qGr zeGS$VU8}ZviB8z>G4%6ID322Pu5YXzgBS>^ ziToE~Y#pwJ@+l&JEsnL}9`52i&S40HjP;_dC%cd6y3znH<4W+Fcow(uPT~H|{tZgq B9E<<} diff --git a/App/BlurtiOS/Design/fonts/OceanicText-Regular.otf b/App/BlurtiOS/Design/fonts/OceanicText-Regular.otf deleted file mode 100644 index 5abe1d47eb03064d80fdae11b6a454f1fbdbc9f3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 91688 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 tH&PBIDmgSfGx@~Im{{a_9gGc}X diff --git a/App/BlurtiOS/Design/fonts/UN_11ST_Regular.ttf b/App/BlurtiOS/Design/fonts/UN_11ST_Regular.ttf deleted file mode 100644 index 552ff21facea8dd04da598c5b9608778b0ec3e57..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 92392 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 diff --git a/App/BlurtiOS/Design/tokens.json b/App/BlurtiOS/Design/tokens.json index 3a396b78..29e2f484 100644 --- a/App/BlurtiOS/Design/tokens.json +++ b/App/BlurtiOS/Design/tokens.json @@ -1,10 +1,5 @@ { "version": 1, - "figma": { - "fileKey": null, - "approvedVersion": null, - "exportedAt": null - }, "brand": { "green/700": { "value": "#01762F", @@ -184,7 +179,7 @@ "keyboard": { "kb/surface": { "value": "{themes.dark/surface}", - "use": "the design face's surface (Figma binds to kb/*; Swift reads the palette)" + "use": "the design face's surface (Swift reads the palette)" }, "kb/key": { "value": "{themes.dark/key}", @@ -895,37 +890,5 @@ "value": 0.5, "use": "a facet's flash while recording" } - }, - "fonts": { - "mono/family": { - "value": "Modern Gothic Mono", - "use": "eyebrows, CTAs, the keyboard's word labels" - }, - "mono/light": { - "value": "ModernGothicMono-Light" - }, - "mono/regular": { - "value": "ModernGothicMono-Regular" - }, - "mono/medium": { - "value": "ModernGothicMono-Medium" - }, - "heading/family": { - "value": "Oceanic Text", - "use": "the app's serif headlines, sentence case, tight" - }, - "heading/regular": { - "value": "OceanicText-Regular" - }, - "body/family": { - "value": "UN-11 ST", - "use": "the app's body text" - }, - "body/regular": { - "value": "UN-11ST-Regular" - }, - "body/bold": { - "value": "UN-11ST-Bold" - } } } diff --git a/App/BlurtiOS/README.md b/App/BlurtiOS/README.md index 9b91b33f..eced40f8 100644 --- a/App/BlurtiOS/README.md +++ b/App/BlurtiOS/README.md @@ -84,7 +84,9 @@ The suite holds the same gates as the engine's: warnings are errors, a plain run `BlurtiOSCore` drops below the engine's own line-coverage floor (`MIN_IOS_COVERAGE`, 88%, in the script — raise it as coverage grows, never lower it to land a change), and CI's `ios-sanitizers` job runs it again under ThreadSanitizer and AddressSanitizer (`BLURT_IOS_SANITIZER=thread` or -`address` locally). The views are not in that figure, as the Mac shell's aren't in the engine's: +`address` locally). `scripts/ios-check.sh` runs the whole iPhone bar in one go — the tests and +the coverage gate, then `swiftlint analyze` and periphery over this project — and is what CI's +`ios-build` job and a local `scripts/check.sh` run. The views are not in that figure, as the Mac shell's aren't in the engine's: they are checked on sight, through the gallery and the probe's screenshot flows. ## Testing in the simulator diff --git a/App/BlurtiOS/Shared/BlurtBrand.swift b/App/BlurtiOS/Shared/BlurtBrand.swift index daa0bd37..99da6498 100644 --- a/App/BlurtiOS/Shared/BlurtBrand.swift +++ b/App/BlurtiOS/Shared/BlurtBrand.swift @@ -1,5 +1,3 @@ -import SwiftUI - /// Blurt's brand, as the Mac app defines it (`App/Blurt/Blurt/Branding/BlurtBrand.swift`, /// from the 2026-08-31 comps), plus the handful of shades the keyboard needs /// for a surface the Mac never draws. Compiled into the app and the keyboard. diff --git a/App/BlurtiOS/Shared/BlurtType.swift b/App/BlurtiOS/Shared/BlurtType.swift index c61d2e25..fca8ed98 100644 --- a/App/BlurtiOS/Shared/BlurtType.swift +++ b/App/BlurtiOS/Shared/BlurtType.swift @@ -1,13 +1,11 @@ import SwiftUI -import UIKit -/// The brand's faces, by the names the bundle registered them under -/// (`DesignTokens.Fonts`, PostScript names from the files in `Design/fonts`). -/// The keyboard uses the mono; the app's serif and body faces join when its -/// screens move onto the brand. Fixed point sizes throughout, as the system -/// keyboard's are — no Dynamic Type. `Font.custom` falls back to the system font in silence when a name -/// is wrong, so `missing()` says which names the bundle doesn't know; a test -/// pins it empty and debug builds assert it once. +/// The type roles the app and the keyboard draw with, in the system's own +/// faces — no font is bundled. Each role keeps the design it stands for: mono +/// for eyebrows, CTAs and the keyboard's word labels; serif for the app's +/// headlines; the default face for body text. Call sites name the role, never +/// a face. Fixed point sizes throughout, as the system keyboard's are — no +/// Dynamic Type. enum BlurtType { enum MonoWeight { case light @@ -15,36 +13,24 @@ enum BlurtType { case medium } - private typealias Fonts = DesignTokens.Fonts - - /// Modern Gothic Mono: eyebrows, CTAs, the keyboard's word labels. + /// Eyebrows, CTAs, the keyboard's word labels. nonisolated static func mono(_ size: CGFloat, weight: MonoWeight = .regular) -> Font { - Font.custom(monoName(weight), fixedSize: size) + .system(size: size, weight: fontWeight(weight), design: .monospaced) } - /// Oceanic Text: the app's serif headlines, sentence case, tight. - nonisolated static func heading(_ size: CGFloat) -> Font { Font.custom(Fonts.headingRegular, fixedSize: size) } + /// The app's headlines, sentence case. + nonisolated static func heading(_ size: CGFloat) -> Font { .system(size: size, design: .serif) } - /// UN 11ST: the app's body text. + /// The app's body text. nonisolated static func body(_ size: CGFloat, bold: Bool = false) -> Font { - Font.custom(bold ? Fonts.bodyBold : Fonts.bodyRegular, fixedSize: size) + .system(size: size, weight: bold ? .bold : .regular) } - private nonisolated static func monoName(_ weight: MonoWeight) -> String { + private nonisolated static func fontWeight(_ weight: MonoWeight) -> Font.Weight { switch weight { - case .light: Fonts.monoLight - case .regular: Fonts.monoRegular - case .medium: Fonts.monoMedium + case .light: .light + case .regular: .regular + case .medium: .medium } } - - nonisolated static let names = [ - Fonts.monoLight, Fonts.monoRegular, Fonts.monoMedium, Fonts.headingRegular, Fonts.bodyRegular, Fonts.bodyBold, - ] - - /// The names this process cannot load: empty when the bundle's - /// `UIAppFonts` and `Design/fonts` agree with the tokens. - nonisolated static func missing() -> [String] { - names.filter { UIFont(name: $0, size: 12) == nil } - } } diff --git a/App/BlurtiOS/Shared/DesignTokens.swift b/App/BlurtiOS/Shared/DesignTokens.swift index 0c8b9a75..dad8de06 100644 --- a/App/BlurtiOS/Shared/DesignTokens.swift +++ b/App/BlurtiOS/Shared/DesignTokens.swift @@ -5,11 +5,10 @@ import SwiftUI // swiftlint:disable type_body_length -/// The design's colours and numbers, from the one source Figma exports +/// The design's colours and numbers, from their one source /// (`Design/tokens.json`): what the views draw with, what DESIGN.md's tables /// say, and what the asset catalog holds, all from the same file. Swift names -/// follow the token names by one rule (`kb/key-modifier` → `kbKeyModifier`), -/// the same rule the Figma build script uses for iOS code syntax. +/// follow the token names by one rule (`kb/key-modifier` → `kbKeyModifier`). enum DesignTokens { enum Brand { /// The iPhone keyboard's dark key. @@ -196,7 +195,7 @@ enum DesignTokens { nonisolated static let kbPopup: Color = Themes.darkPopup /// The wave, the caret, the saved check. nonisolated static let kbSignal: Color = Themes.darkSignal - /// The design face's surface (Figma binds to kb/*; Swift reads the palette). + /// The design face's surface (Swift reads the palette). nonisolated static let kbSurface: Color = Themes.darkSurface } @@ -494,21 +493,6 @@ enum DesignTokens { nonisolated static let waveFade: Double = 0.7 } - enum Fonts { - nonisolated static let bodyBold: String = "UN-11ST-Bold" - /// The app's body text. - nonisolated static let bodyFamily: String = "UN-11 ST" - nonisolated static let bodyRegular: String = "UN-11ST-Regular" - /// The app's serif headlines, sentence case, tight. - nonisolated static let headingFamily: String = "Oceanic Text" - nonisolated static let headingRegular: String = "OceanicText-Regular" - /// Eyebrows, CTAs, the keyboard's word labels. - nonisolated static let monoFamily: String = "Modern Gothic Mono" - nonisolated static let monoLight: String = "ModernGothicMono-Light" - nonisolated static let monoMedium: String = "ModernGothicMono-Medium" - nonisolated static let monoRegular: String = "ModernGothicMono-Regular" - } - enum Gradients { } @@ -761,15 +745,6 @@ enum DesignTokens { "motion.state-fade": "0.5", "motion.term-swap": "0.4", "motion.wave-fade": "0.7", - "fonts.body/bold": "UN-11ST-Bold", - "fonts.body/family": "UN-11 ST", - "fonts.body/regular": "UN-11ST-Regular", - "fonts.heading/family": "Oceanic Text", - "fonts.heading/regular": "OceanicText-Regular", - "fonts.mono/family": "Modern Gothic Mono", - "fonts.mono/light": "ModernGothicMono-Light", - "fonts.mono/medium": "ModernGothicMono-Medium", - "fonts.mono/regular": "ModernGothicMono-Regular", ] } // swiftlint:enable type_body_length diff --git a/App/BlurtiOS/Shared/KeyboardLayout+Height.swift b/App/BlurtiOS/Shared/KeyboardLayout+Height.swift index 5fe25539..af27d156 100644 --- a/App/BlurtiOS/Shared/KeyboardLayout+Height.swift +++ b/App/BlurtiOS/Shared/KeyboardLayout+Height.swift @@ -1,5 +1,5 @@ import BlurtiOSCore -import CoreGraphics +import CoreFoundation extension KeyboardLayout { /// The keyboard's height on screen, from the layout's rows at the iPhone diff --git a/App/BlurtiOS/project.yml b/App/BlurtiOS/project.yml index cd50a608..8f45c3f7 100644 --- a/App/BlurtiOS/project.yml +++ b/App/BlurtiOS/project.yml @@ -74,16 +74,15 @@ targets: # The Mac's brand colours (accent, card fill and border), copied verbatim # from App/Blurt/Blurt/Assets.xcassets — JSON can't reference JSON. - path: BlurtiOS/Assets.xcassets + # Apple's required-reason declarations: App Group UserDefaults (1C8F.1) + # and the bundle's own (CA92.1), the only such API either target uses. + - path: BlurtiOS/PrivacyInfo.xcprivacy + buildPhase: resources # The Mac's app icon and ready-screen wordmark, shared rather than copied: # the Icon Composer file targets iOS too (`squares: shared`). - path: ../Blurt/Blurt/AppIcon.icon - path: ../Blurt/Blurt/Branding/blurt-ready-logo.png buildPhase: resources - # The brand's faces (Modern Gothic Mono, UN 11ST, Oceanic Text), from the - # website repo's public/_aai/fonts/rebrand, converted to TTF for iOS. - # The keyboard carries its own copy: an extension can't read the app's. - - path: Design/fonts - buildPhase: resources # The UI both the app and the keyboard draw with (design tokens, type, # brand colours), compiled into each — an extension can't import the # app's module. The App Group contract itself is BlurtiOSCore. @@ -121,14 +120,11 @@ targets: # Keeps the listening window alive while the user is back in the app # they are typing in: iOS ends a backgrounded app's capture without it. UIBackgroundModes: [audio] - UILaunchScreen: {} - UIAppFonts: - - ModernGothicMono-Light.ttf - - ModernGothicMono-Regular.ttf - - ModernGothicMono-Medium.ttf - - UN_11ST_Regular.ttf - - UN_11ST_Bold.ttf - - OceanicText-Regular.otf + # The icon zooms into this before the first frame: the app's own page + # colour (Assets.xcassets › Page, light and dark), not a blank system + # white that reads as a broken icon mid-launch. + UILaunchScreen: + UIColorName: Page UIApplicationSceneManifest: UIApplicationSupportsMultipleScenes: false UISupportedInterfaceOrientations: [UIInterfaceOrientationPortrait] @@ -140,6 +136,10 @@ targets: CFBundleURLSchemes: [blurt] # A shared key-term list (`.blurtterms`, JSON): declared so a tap on # one in Messages offers Blurt, which opens it as an import. + # Not in place: iOS hands the app a copy in its Inbox, which + # `TermPack.from` reads and then deletes — an import, never an edit of + # the sender's file (and no security-scoped access to manage). + LSSupportsOpeningDocumentsInPlace: false CFBundleDocumentTypes: - CFBundleTypeName: Blurt key terms CFBundleTypeRole: Viewer @@ -171,7 +171,7 @@ targets: sources: - path: BlurtKeyboard/Sources - path: Shared - - path: Design/fonts + - path: BlurtKeyboard/PrivacyInfo.xcprivacy buildPhase: resources settings: base: @@ -185,13 +185,6 @@ targets: CFBundleDisplayName: Blurt CFBundleShortVersionString: "0.1.0" CFBundleVersion: "1" - UIAppFonts: - - ModernGothicMono-Light.ttf - - ModernGothicMono-Regular.ttf - - ModernGothicMono-Medium.ttf - - UN_11ST_Regular.ttf - - UN_11ST_Bold.ttf - - OceanicText-Regular.otf NSExtension: NSExtensionPointIdentifier: com.apple.keyboard-service NSExtensionPrincipalClass: $(PRODUCT_MODULE_NAME).KeyboardViewController diff --git a/scripts/check-invariants.sh b/scripts/check-invariants.sh index 907aa423..f1437522 100755 --- a/scripts/check-invariants.sh +++ b/scripts/check-invariants.sh @@ -265,8 +265,12 @@ if [ "${1:-}" = "--self-test" ]; then exit 1 fi + # A here-string, not `printf | grep -q`: the table is ~30 KB, past a macOS + # pipe's 16 KB first buffer, so grep -q exiting at an early match left printf + # writing into a closed pipe — EPIPE, and under pipefail a "missing" row that + # was there all along (seen on CI as rule 3 failing at random). for i in "${!PATTERNS[@]}"; do - if printf '%s\n' "$TABLE" | grep -qF -- "${TABLE_ANCHORS[$i]}"; then + if grep -qF -- "${TABLE_ANCHORS[$i]}" <<<"$TABLE"; then echo " ok rule $i is pinned to its $GUIDE row" else echo " FAIL rule $i has no row in $GUIDE's settled-decisions table:" >&2 diff --git a/scripts/check.sh b/scripts/check.sh index 4bda2811..c7b0bbe0 100755 --- a/scripts/check.sh +++ b/scripts/check.sh @@ -816,6 +816,24 @@ if [ "$PORTABLE" -eq 0 ]; then fi fi +# The iPhone code's gates — its tests with BlurtiOSCore's coverage gate, +# `swiftlint analyze` and periphery over App/BlurtiOS (scripts/ios-check.sh) — so +# a local green covers both platforms. Off CI only: there the ios-build job runs +# the same script, and running it here too would double the macos-26 bill. It +# needs an iPhone simulator on the runtime this Xcode's SDK builds for (an older +# one is refused at the destination); without one it is skipped with a note, as +# the UI suite is, and CI stays the authority. +if [ "$PORTABLE" -eq 0 ] && ! is_ci; then + IOS_SDK_VERSION="$(xcrun --sdk iphonesimulator --show-sdk-version 2>/dev/null || true)" + if [ -n "$IOS_SDK_VERSION" ] && xcrun simctl list runtimes available 2>/dev/null \ + | grep -q "^iOS $IOS_SDK_VERSION "; then + run_check "ios-check (App/BlurtiOS tests, coverage, analyze, periphery)" "$REPO_ROOT/scripts/ios-check.sh" + else + IOS_SKIPPED=1 + echo "==> ios-check skipped: no iOS ${IOS_SDK_VERSION:-?} simulator runtime (xcodebuild -downloadPlatform iOS)" + fi +fi + # The closing line, and only when there is nothing to report — otherwise the exit # trap has the last word. Printing "ok" above a list of failures would be worse # than printing nothing at all. @@ -825,7 +843,7 @@ if [ "${#FAILED_CHECKS[@]}" -eq 0 ]; then elif [ "${INTEGRATION:-0}" -eq 0 ]; then # Say it at the end too, where the reader is deciding whether this run means # "green": everything else passed, but the UI suite and leak scan did not run. - echo "==> ok (UI suite + leak scan NOT run — CI on macos-26 covers those)" + echo "==> ok (UI suite + leak scan NOT run${IOS_SKIPPED:+, nor the iPhone gates} — CI on macos-26 covers those)" else echo "==> ok" fi diff --git a/scripts/design-capture.sh b/scripts/design-capture.sh index 2d8aa5b4..3d8ca68a 100755 --- a/scripts/design-capture.sh +++ b/scripts/design-capture.sh @@ -1,7 +1,7 @@ #!/bin/bash # Capture the keyboard from the simulator, one still per layout × state × theme, # cropped to the keyboard's own pixels — the simulator side of the design loop -# (DESIGN.md › Figma). Each capture is deterministic: the gallery's +# (DESIGN.md › Reproducing it). Each capture is deterministic: the gallery's # -BlurtGalleryStill holds the orb, the ring and the wave at time zero, and # -BlurtGalleryBare draws one row with a magenta registration border that # scripts/design-diff.swift crops to. @@ -12,7 +12,7 @@ # scripts/design-capture.sh --out .build/design/captures --no-build # # Writes /--@3x.png (1206 px wide on iPhone 18 Pro, -# the same pixel size as a Figma export at 3×, so the diff never resamples) +# the same pixel size as any 3× reference, so the diff never resamples) # plus /--.raw.png, the whole screen it was cut from. set -euo pipefail diff --git a/scripts/design-diff.swift b/scripts/design-diff.swift index 28817704..248cb03b 100755 --- a/scripts/design-diff.swift +++ b/scripts/design-diff.swift @@ -4,7 +4,7 @@ // swift scripts/design-diff.swift diff --out --json // [--mask x,y,w,h]... [--threshold 8] // Compares two same-sized images pixel by pixel, both converted to sRGB -// first (a simulator capture carries the display's profile, a Figma +// first (a simulator capture carries the display's profile, a design // export is sRGB). Reports, for the whole image and for everything // outside the masks, the fraction of pixels whose largest channel // difference exceeds the threshold (AE) and the root-mean-square diff --git a/scripts/design-figma-call.sh b/scripts/design-figma-call.sh deleted file mode 100755 index 3936b37a..00000000 --- a/scripts/design-figma-call.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/bash -# Assemble one use_figma call for the Blurt Keyboard Figma build: the tokens, -# core.js, the builder's module and the line that runs it, in one file under -# the tool's 50,000-character cap (App/BlurtiOS/Design/figma/README.md). -# -# scripts/design-figma-call.sh foundations|components|layouts|theme-sheet|export-tokens|export-bounds|measure-apple -# -# Writes .build/figma-call/.js and prints its size. Only foundations -# carries tokens.js; every other builder reads the values back from the file's -# variables, so its call is just core.js and its module. -set -euo pipefail - -REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" -cd "$REPO_ROOT" -BUILDER="${1:?usage: design-figma-call.sh }" -case "$BUILDER" in - foundations) MODULE=foundations FN=buildFoundations ;; - components) MODULE=components FN=buildComponents ;; - layouts) MODULE=layouts FN=buildLayouts ;; - theme-sheet) MODULE=themes FN=themeSheet ;; - measure-apple) MODULE=themes FN=measureApple ;; - export-tokens) MODULE=exports FN=exportTokens ;; - export-bounds) MODULE=exports FN=exportBounds ;; - *) - echo "unknown builder $BUILDER" >&2 - exit 2 - ;; -esac -OUT="$REPO_ROOT/.build/figma-call" -mkdir -p "$OUT" -node - "$BUILDER" "$MODULE" "$FN" "$OUT" <<'JS' -const fs = require("fs"); -const [builder, module, fn, out] = process.argv.slice(2); -const dir = "App/BlurtiOS/Design/figma/"; -// Only foundations carries the data; every other builder reads it back from -// the file's variables and Gradient/* paint styles (core.js › ensureTokens). -const tokens = builder === "foundations" ? fs.readFileSync(dir + "tokens.js", "utf8") : ""; -const strip = (text) => text.replace(/^\/\* global [^*]*\*\/\n/m, ""); -const code = - tokens + - strip(fs.readFileSync(dir + "core.js", "utf8")) + - strip(fs.readFileSync(dir + module + ".js", "utf8")) + - `\nreturn await ${fn}();\n`; -const path = `${out}/${builder}.js`; -fs.writeFileSync(path, code); -const limit = 50000; -console.log(`${path}: ${code.length} chars${code.length > limit ? ` — OVER the ${limit} cap` : ""}`); -if (code.length > limit) process.exit(1); -JS diff --git a/scripts/design-sync.sh b/scripts/design-sync.sh index 04ce8178..cd4c0bcf 100755 --- a/scripts/design-sync.sh +++ b/scripts/design-sync.sh @@ -5,7 +5,7 @@ # scripts/design-sync.sh --check # regenerate into .build/ and diff; non-zero on drift # # `App/BlurtiOS/Design/tokens.json` is the one source for the keyboard's colours -# and numbers (exported from the Figma file — see DESIGN.md › Figma). Everything +# and numbers, edited by hand. Everything # that repeats a value from it is generated by scripts/design-tokens.swift, and # check.sh runs `--check` so a hand edit to a generated file, or a token change # without a regeneration, fails the way a stale .pbxproj does. @@ -46,7 +46,6 @@ OUTPUTS=( App/BlurtiOS/BlurtiOS/Assets.xcassets/Muted.colorset/Contents.json App/BlurtiOS/BlurtiOS/Assets.xcassets/CTA.colorset/Contents.json App/BlurtiOS/BlurtiOS/Assets.xcassets/CTAText.colorset/Contents.json - App/BlurtiOS/Design/figma/tokens.js ) # Format the generated files the way check.sh expects the tree to be formatted, @@ -109,25 +108,10 @@ print(f"design-sync: no design literals in {len(files)} view files") PY } -# The Figma development-plugin bundle: the same scripts a use_figma call -# carries, concatenated behind a manifest, for running from Figma desktop -# without the MCP read quota (Design/figma/README.md). -bundle_plugin() { - local dir="$REPO_ROOT/.build/figma-plugin" - mkdir -p "$dir" - cp App/BlurtiOS/Design/figma/manifest.json "$dir/manifest.json" - ( - cd App/BlurtiOS/Design/figma \ - && cat tokens.js core.js foundations.js components.js layouts.js themes.js exports.js plugin.js - ) >"$dir/code.js" - echo "design-sync: Figma plugin bundled at $dir (Plugins → Development → Import plugin from manifest)" -} - if [ "$CHECK" -eq 0 ]; then swift scripts/design-tokens.swift format_outputs "$REPO_ROOT" lint_literals - bundle_plugin exit 0 fi diff --git a/scripts/design-tokens.swift b/scripts/design-tokens.swift index 469b76b9..b0109256 100755 --- a/scripts/design-tokens.swift +++ b/scripts/design-tokens.swift @@ -1,4 +1,4 @@ -#!/usr/bin/env swift // The design's one source of numbers and colours, fanned out: reads // App/BlurtiOS/Design/tokens.json (exported from the Figma file, hand-written // before it existed) and writes everything that used to repeat those values by // hand — `App/BlurtiOS/Shared/DesignTokens.swift`, the generated tables in // `App/BlurtiOS/DESIGN.md`, and the app's three asset-catalog colour sets. Run +#!/usr/bin/env swift // The design's one source of numbers and colours, fanned out: reads // App/BlurtiOS/Design/tokens.json (hand-edited: it is the // source, not an export) and writes everything that used to repeat those values by // hand — `App/BlurtiOS/Shared/DesignTokens.swift`, the generated tables in // `App/BlurtiOS/DESIGN.md`, and the app's three asset-catalog colour sets. Run // through scripts/design-sync.sh, which also formats the output and, with // --check, fails on drift the way check.sh fails on a stale .pbxproj. // @@ -12,8 +12,7 @@ // to another token in braces ("{brand.green/700}", the DTCG spelling). A value // may be wrapped as {"value": …, "use": "one line for DESIGN.md"}. Swift names // derive from token names by one rule — `kb/key-modifier` → `kbKeyModifier`, -// `green/700` → `green700` — and the Figma build script sets the same string -// as each variable's iOS code syntax, so the two can't disagree. +// `green/700` → `green700`. import Foundation @@ -38,7 +37,6 @@ let tokensPath = "App/BlurtiOS/Design/tokens.json" let swiftPath = "App/BlurtiOS/Shared/DesignTokens.swift" let designPath = "App/BlurtiOS/DESIGN.md" let catalogPath = "App/BlurtiOS/BlurtiOS/Assets.xcassets" -let figmaTokensPath = "App/BlurtiOS/Design/figma/tokens.js" func fail(_ message: String) -> Never { FileHandle.standardError.write(Data("design-tokens: \(message)\n".utf8)) @@ -51,7 +49,6 @@ enum Value { case color(String) // "#RRGGBB" case number(Double) case word(String) // a font weight - case string(String) // a font name (the `fonts` group) case curve([Double]) // a cubic-bezier easing: four numbers case alias(String) // "group.name" } @@ -116,24 +113,20 @@ guard let data = FileManager.default.contents(atPath: tokensURL.path), let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else { fail("could not read \(tokensPath)") } -let groups = ["brand", "themes", "keyboard", "metrics", "type", "motion", "fonts"] +let groups = ["brand", "themes", "keyboard", "metrics", "type", "motion"] var tokens: [Token] = [] var byQualified: [String: Token] = [:] for group in groups { guard let entries = json[group] as? [String: Any] else { fail("tokens.json has no \(group) group") } for name in entries.keys.sorted() { let entry = entries[name]! - var token: Token + let token: Token if let wrapped = entry as? [String: Any] { guard let raw = wrapped["value"] else { fail("\(group).\(name) has no value") } token = Token(group: group, name: name, value: parseValue(raw), use: wrapped["use"] as? String) } else { token = Token(group: group, name: name, value: parseValue(entry), use: nil) } - // A bare word in `fonts` is a font's name, not a weight. - if group == "fonts", case .word(let word) = token.value { - token = Token(group: group, name: name, value: .string(word), use: token.use) - } tokens.append(token) byQualified[token.qualified] = token } @@ -190,7 +183,6 @@ func rendered(_ token: Token) -> String { case .color(let hex): return hex case .number(let number): return format(number) case .word(let word): return word - case .string(let string): return string case .curve(let numbers): return numbers.map(format).joined(separator: ",") case .alias: fatalError("unreachable") } @@ -210,7 +202,6 @@ func swiftLiteral(_ token: Token) -> (type: String, literal: String) { case .word(let word): guard weights.contains(word) else { fail("\(token.qualified): \(word) is not a font weight") } return ("Font.Weight", ".\(word)") - case .string(let string): return ("String", "\"\(string)\"") case .curve(let numbers): let n = numbers.map(format) return ( @@ -248,11 +239,10 @@ var swift = """ import SwiftUI // swiftlint:disable type_body_length - /// The design's colours and numbers, from the one source Figma exports + /// The design's colours and numbers, from their one source /// (`Design/tokens.json`): what the views draw with, what DESIGN.md's tables /// say, and what the asset catalog holds, all from the same file. Swift names - /// follow the token names by one rule (`kb/key-modifier` → `kbKeyModifier`), - /// the same rule the Figma build script uses for iOS code syntax. + /// follow the token names by one rule (`kb/key-modifier` → `kbKeyModifier`). enum DesignTokens { """ @@ -332,7 +322,6 @@ blocks["keyboard"] = tokenRows("keyboard", valueLabel: "Value") blocks["metrics"] = tokenRows("metrics", valueLabel: "Points") blocks["type"] = tokenRows("type", valueLabel: "Value") blocks["motion"] = tokenRows("motion", valueLabel: "Value") -blocks["fonts"] = tokenRows("fonts", valueLabel: "Value") let themeNames = tokens.filter { $0.group == "themes" }.map { String($0.name.split(separator: "/")[0]) } let themeOrder = ["light", "dark"] + Set(themeNames).subtracting(["light", "dark"]).sorted() @@ -436,100 +425,6 @@ let colorSets: [(String, String, String)] = [ ("CTAText", "keyboard.app/cta-text-light", "keyboard.app/cta-text-dark"), ] -// MARK: - Figma - -/// What the Figma build scripts (Design/figma/lib.js) need: every token with -/// its resolved value, its alias if any, the scopes its collection gives it and -/// the iOS code syntax that is its Swift name. Scopes follow the token's role -/// by name, which is the one place that rule is written down. -func figmaScopes(_ token: Token) -> [String] { - let name = token.name - switch token.group { - case "brand", "themes", "motion": return [] - case "keyboard": - if name.hasSuffix("legend") || name.hasSuffix("full-access-note") { return ["TEXT_FILL"] } - if name.contains("notice-") || name.contains("orb-ring-") || name.contains("card-border") { - return ["STROKE_COLOR"] - } - if name.hasSuffix("signal") { return ["SHAPE_FILL", "TEXT_FILL"] } - return ["FRAME_FILL", "SHAPE_FILL"] - case "metrics": - if name.hasPrefix("opacity/") { return ["OPACITY"] } - if name.hasSuffix("/radius") { return ["CORNER_RADIUS"] } - if name.hasSuffix("/gap") || name.hasSuffix("/spacing") || name.hasSuffix("/pad") || name.hasSuffix("/inset") - || name.hasSuffix("/lead") || name.hasSuffix("-gap") || name.hasSuffix("-clearance") - { - return ["GAP"] - } - if name.hasPrefix("ring/") || name == "card/border" || name == "caret/width" || name == "wave/bar" { - return ["STROKE_FLOAT", "WIDTH_HEIGHT"] - } - if name.hasPrefix("press/") || name.hasPrefix("gesture/") || name.contains("factor") || name.contains("light-") - || name.contains("dissipate") || name == "picker/scale" - { - return [] - } - return ["WIDTH_HEIGHT"] - case "type": - if name.hasPrefix("size/") { return ["FONT_SIZE"] } - if name.hasPrefix("weight/") { return ["FONT_STYLE"] } - if name.hasPrefix("tracking/") { return ["LETTER_SPACING"] } - return [] - case "fonts": - return name.hasSuffix("/family") ? ["FONT_FAMILY"] : [] - default: return [] - } -} - -func figmaJSON() -> String { - // One line per variable — collection|name|type|value|alias|scopes|codeSyntax|use — - // and one per gradient, parsed by core.js. Flat on purpose: a use_figma call - // is capped at 50,000 characters and carries this once, for buildFoundations; - // every later builder reads the values back from the file's variables. - var lines: [String] = [] - for group in groups { - for token in tokens where token.group == group { - let value = rendered(token) - let type: String - switch resolve(token).value { - case .color: type = "COLOR" - case .number: type = "FLOAT" - default: type = "STRING" - } - var alias = "" - if case .alias(let target) = token.value, let other = byQualified[target] { - alias = "\(typeName(other.group)):\(other.name)" - } - let use = (token.use ?? "").replacingOccurrences(of: "|", with: "/") - lines.append( - [ - typeName(group), token.name, type, value, alias, figmaScopes(token).joined(separator: ","), - "DesignTokens.\(typeName(group)).\(token.swiftName)", use, - ].joined(separator: "|")) - } - } - for gradient in gradients { - let stops = gradient.stops.map { "\(resolveColor($0.color))@\(format($0.location))" }.joined(separator: ",") - let use = (gradient.use ?? "").replacingOccurrences(of: "|", with: "/") - lines.append(["GRADIENT", gradient.name, gradient.start, gradient.end, stops, use].joined(separator: "|")) - } - let text = lines.joined(separator: "\n").replacingOccurrences(of: "\\", with: "\\\\").replacingOccurrences( - of: "`", with: "\\`") - return """ - // Generated by scripts/design-tokens.swift from App/BlurtiOS/Design/tokens.json — do not edit. - // One line per variable (collection|name|type|value|alias|scopes|codeSyntax|use) - // and per gradient (GRADIENT|name|start|end|stops|use); core.js parses it. - // scripts/design-figma-call.sh puts it in front of core.js + foundations.js. - const TOKEN_LINES = `\(text)`; - const GROUPS = \(groups.map(typeName).map { "\"\($0)\"" }.joined(separator: ", ").wrappedInBrackets); - - """ -} - -extension String { - var wrappedInBrackets: String { "[\(self)]" } -} - // MARK: - Write func write(_ text: String, to relative: String) { @@ -544,7 +439,6 @@ func write(_ text: String, to relative: String) { write(swift, to: swiftPath) write(design, to: designPath) -write(figmaJSON(), to: figmaTokensPath) for (set, light, dark) in colorSets { guard let lightToken = byQualified[light], let darkToken = byQualified[dark] else { fail("\(set) needs \(light) and \(dark)") @@ -554,4 +448,4 @@ for (set, light, dark) in colorSets { } print( "design-tokens: \(tokens.count) tokens, \(gradients.count) gradients → \(swiftPath), \(designPath) " - + "(\(replaced.count) blocks), \(colorSets.count) colour sets, \(figmaTokensPath)") + + "(\(replaced.count) blocks), \(colorSets.count) colour sets") diff --git a/scripts/ios-check.sh b/scripts/ios-check.sh new file mode 100755 index 00000000..96fdda22 --- /dev/null +++ b/scripts/ios-check.sh @@ -0,0 +1,77 @@ +#!/bin/bash +# The iPhone code's quality gates, in one place — what check.sh is for the Mac. +# +# scripts/ios-check.sh +# BLURT_SIM_DEVICE="iPhone 17" scripts/ios-check.sh +# +# The same bar the engine and the Mac shell meet in check.sh, applied to +# App/BlurtiOS: +# 1. BlurtiOSTests on a simulator, warnings as errors, with BlurtiOSCore's +# line-coverage gate (ios-test.sh; the TSan and ASan passes are its +# BLURT_IOS_SANITIZER runs, CI's ios-sanitizers job). +# 2. `swiftlint analyze` — unused imports — over that build's compiler log, +# as check.sh runs it over the Mac app's. +# 3. periphery over the iPhone project — unused declarations. +# swift-format, `swiftlint lint`, the invariants and ios-typecheck.sh already +# cover App/BlurtiOS from check.sh, which reads every tracked Swift file. +# +# CI's ios-build job runs this; check.sh runs it too on a Mac with an iPhone +# simulator, so a local green means the same thing on both platforms. Like +# check.sh, every step reports, so one failure doesn't hide the next. +# +# `swiftlint analyze` sees the files the build actually compiled. CI's build is +# from scratch, so it sees everything; a local incremental one may not — +# delete .build/ios-sim for a full local pass, as with check.sh's app build. +set -euo pipefail + +REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" +cd "$REPO_ROOT" + +for tool in swiftlint periphery xcodegen; do + if ! command -v "$tool" >/dev/null 2>&1; then + echo "ios-check: $tool not found — scripts/bootstrap.sh installs it" >&2 + exit 1 + fi +done + +FAILED=() +BUILD_LOG="$(mktemp -t blurt-ios-build)" +trap 'rm -f "$BUILD_LOG"' EXIT + +echo "==> ios-test (BlurtiOSTests + BlurtiOSCore coverage gate)" +BLURT_IOS_BUILD_LOG="$BUILD_LOG" "$REPO_ROOT/scripts/ios-test.sh" || FAILED+=("ios-test") + +echo "==> swiftlint analyze (unused imports, App/BlurtiOS)" +if [ -s "$BUILD_LOG" ]; then + # App/BlurtiOS only. The log also compiles the engine — for iOS, where its + # `#if os(macOS)` files are inactive and SourceKit can't resolve them — and + # check.sh already analyzes the engine from the Mac build, where they're live. + # SourceKit still loads those engine files to resolve the iPhone ones and + # prints their unresolvable macOS imports to stderr — a diagnostic line, then + # the source line and a caret. They are not findings (violations go to + # stdout, and the exit status is the verdict), so each such block is dropped + # whole; any other line, swiftlint's own errors included, still shows. + swiftlint analyze --strict --quiet --compiler-log-path "$BUILD_LOG" App/BlurtiOS \ + 2> >(awk -v engine="$REPO_ROOT/Sources/BlurtEngine/" ' + /^\// || /^(Error|error|warning|Fatal)/ { skip = (index($0, engine) == 1) } + !skip { print }' >&2) || FAILED+=("swiftlint analyze") +else + echo "error: no build log to analyze — the build above did not run" >&2 + FAILED+=("swiftlint analyze") +fi + +echo "==> periphery (App/BlurtiOS)" +# `--retain-public`: the engine's public API is used by the Mac app this scan +# can't see, and the engine's own findings are excluded from the report, so only +# the iPhone code's dead declarations are reported. BlurtiOSCore's API is +# `package`, not public, so it is still scanned. +periphery scan --project App/BlurtiOS/BlurtiOS.xcodeproj --schemes BlurtiOS \ + --retain-public --retain-unused-protocol-func-params \ + --report-exclude 'Sources/**' --strict --quiet || FAILED+=("periphery") + +if [ "${#FAILED[@]}" -gt 0 ]; then + echo "error: ${#FAILED[@]} iPhone check(s) failed:" >&2 + printf ' %s\n' "${FAILED[@]}" >&2 + exit 1 +fi +echo "==> ios-check: ok" diff --git a/scripts/ios-keyboard-flows.sh b/scripts/ios-keyboard-flows.sh index 6e72db38..fa96d60c 100755 --- a/scripts/ios-keyboard-flows.sh +++ b/scripts/ios-keyboard-flows.sh @@ -58,6 +58,10 @@ while [ $# -gt 0 ]; do esac done +# The runs whose XCUITest failed. The matrix carries on — every other run's +# screenshots are still worth having — and the script exits non-zero at the end. +FAILED_RUNS=() + PICKED="$(ios_pick_device "${BLURT_SIM_DEVICE:-iPhone 18 Pro}")" [ -n "$PICKED" ] || { echo "ios-keyboard-flows: no iPhone simulator available" >&2 @@ -87,7 +91,8 @@ for face in $FACES; do -destination "platform=iOS Simulator,id=$UDID" -derivedDataPath "$DERIVED" \ -resultBundlePath "$dir/flows.xcresult" "${IOS_SIM_SIGNING[@]}" -collect-test-diagnostics never \ 2>&1 | grep -E "^FLOW-|XCTAssertTrue failed|Blurt never came up|error:|TEST BUILD FAILED" | grep -v "XCTAssertTrue failed" | sed "s/^/ /" - if grep -q "FLOW-FAIL\|failed" "$dir/flows.xcresult/Info.plist" 2>/dev/null; then :; fi + # xcodebuild's own verdict, read before any other command replaces it. + if [ "${PIPESTATUS[0]}" -ne 0 ]; then FAILED_RUNS+=("$name"); fi xcrun xcresulttool export attachments --path "$dir/flows.xcresult" --output-path "$dir/attachments" >/dev/null 2>&1 python3 - "$dir" <<'PY' import json, os, shutil, sys @@ -137,3 +142,8 @@ if [ -n "$ALIGN" ]; then echo "ios-keyboard-flows: mic alignment back to the middle" fi fi + +if [ "${#FAILED_RUNS[@]}" -gt 0 ]; then + echo "ios-keyboard-flows: ${#FAILED_RUNS[@]} run(s) failed: ${FAILED_RUNS[*]}" >&2 + exit 1 +fi diff --git a/scripts/ios-record.sh b/scripts/ios-record.sh index f216481a..f9437c1c 100755 --- a/scripts/ios-record.sh +++ b/scripts/ios-record.sh @@ -2,7 +2,7 @@ # Record the keyboard's motion from the simulator: the gallery's `live` state # walks a whole dictation on a clock (about 11.7 s a cycle), this records two # cycles and cuts one clean loop, cropped to the keyboard, for the review packet -# and for the Figma motion page's keyframes (DESIGN.md › Figma). +# (DESIGN.md › Reproducing it). # # scripts/ios-record.sh # panel, dark → .build/design/loops/panel-dark.mp4 # scripts/ios-record.sh --layout slimBar --theme light --out ~/Desktop/blurt-review diff --git a/scripts/ios-test.sh b/scripts/ios-test.sh index f8fbcbbe..1390488d 100755 --- a/scripts/ios-test.sh +++ b/scripts/ios-test.sh @@ -62,7 +62,13 @@ echo "testing on ${PICKED#* }${SANITIZER:+ under the $SANITIZER sanitizer}" ios_wait_booted "$UDID" (cd "$REPO_ROOT/App/BlurtiOS" && xcodegen generate --quiet) -RESULTS="$DERIVED/BlurtiOSTests-$(date +%Y%m%d-%H%M%S).xcresult" +STAMP="$(date +%Y%m%d-%H%M%S)" +RESULTS="$DERIVED/BlurtiOSTests-$STAMP.xcresult" +# The whole xcodebuild log, kept rather than `-quiet`ed away: ios-check.sh feeds +# its compiler invocations to `swiftlint analyze`. Only diagnostics and the +# outcome reach the terminal; the log path is printed at the end. +BUILD_LOG="${BLURT_IOS_BUILD_LOG:-$DERIVED/BlurtiOSTests-$STAMP.log}" +mkdir -p "$(dirname "$BUILD_LOG")" COVERAGE_FLAGS=() [ -z "$SANITIZER" ] && COVERAGE_FLAGS=(-enableCodeCoverage YES) # The `${a[@]+...}` form: macOS bash 3.2 calls an empty array unbound under `set -u`. @@ -71,13 +77,15 @@ COVERAGE_FLAGS=() xcodebuild test -project "$REPO_ROOT/App/BlurtiOS/BlurtiOS.xcodeproj" -scheme BlurtiOS \ -destination "platform=iOS Simulator,id=$UDID" -derivedDataPath "$DERIVED" \ -resultBundlePath "$RESULTS" "${IOS_SIM_SIGNING[@]}" ${COVERAGE_FLAGS[@]+"${COVERAGE_FLAGS[@]}"} ${SANITIZE_FLAGS[@]+"${SANITIZE_FLAGS[@]}"} \ - -parallel-testing-enabled NO -collect-test-diagnostics never -quiet + -parallel-testing-enabled NO -collect-test-diagnostics never 2>&1 \ + | tee "$BUILD_LOG" | { grep -E 'error:|warning:|\*\* (BUILD|TEST) [A-Z]+ \*\*|✘' || true; } xcrun xcresulttool get test-results summary --path "$RESULTS" 2>/dev/null | python3 -c ' import json, sys d = json.load(sys.stdin) print("ios-test:", d.get("passedTests", "?"), "passed,", d.get("failedTests", "?"), "failed,", d.get("skippedTests", 0), "skipped") ' || true echo "results: $RESULTS" +echo "build log: $BUILD_LOG" [ -n "$SANITIZER" ] && exit 0 From 1a2cd8c17b375e08816ba2536246f4381249e6f6 Mon Sep 17 00:00:00 2001 From: Alex Kroman Date: Fri, 2 Oct 2026 13:19:30 -0700 Subject: [PATCH 77/79] Keyboard: never cancel words behind the user's back; build the probe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A fuzz rule now holds the keyboard to it: a cancel over a recording or a transcription comes only from the user — the × key, or the term field opened over a highlighted word. With the earlier bugs put back it catches the cancel on leaving the screen and the swipe off the orb; the + during processing needs a sequence too rare for random events, and keeps its deterministic test. On its first run against the fixed code it found one more: right after the keyboard released a recording (leaving the screen, opening the term field) the picture still says recording, and a swipe across the orb then sent a press and a cancel — the cancel landing on the words being transcribed. undoPress now cancels only a press that could have started a dictation (`pressSentOver`); a press over one the app was still running started nothing, since the engine drops it. Pinned by a gate test. - scripts/ios-check.sh compiles BlurtiOSProbe (build-for-testing). It has its own scheme and nothing else built it, so MicPixels.swift sat broken under Swift 6 isolation; now fixed (main-actor, as XCUIAutomation is). - The setup step names the whole path — Apps › Blurt › Keyboards — since openSettingsURLString lands on Settings' top level in the iOS 26 simulator although Blurt's page exists. README to match. - KeyboardModel's word-list hand-off moves to KeyboardModel+Lexicon.swift (the file was past SwiftLint's length limit); the fuzz test's event table to an extension, for the same reason. Co-Authored-By: Claude Opus 5.5 --- App/BlurtiOS/BlurtiOS/Sources/SetupCard.swift | 12 +- .../BlurtiOSCore/KeyboardModel+Lexicon.swift | 37 ++++ .../BlurtiOSCore/KeyboardModel+Mic.swift | 14 +- App/BlurtiOS/BlurtiOSCore/KeyboardModel.swift | 34 +--- App/BlurtiOS/BlurtiOSProbe/MicPixels.swift | 3 + .../KeyboardModelFuzzTests.swift | 191 ++++++++++-------- .../KeyboardModelGateTests.swift | 22 ++ App/BlurtiOS/README.md | 9 +- scripts/ios-check.sh | 11 + 9 files changed, 208 insertions(+), 125 deletions(-) create mode 100644 App/BlurtiOS/BlurtiOSCore/KeyboardModel+Lexicon.swift diff --git a/App/BlurtiOS/BlurtiOS/Sources/SetupCard.swift b/App/BlurtiOS/BlurtiOS/Sources/SetupCard.swift index 1d639115..4f0f5977 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/SetupCard.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/SetupCard.swift @@ -42,12 +42,14 @@ struct SetupCard: View { } SetupRow(number: "03", done: keyboardSeen, title: "Add the Blurt keyboard") { VStack(alignment: .leading, spacing: DesignTokens.Metrics.appLineGap) { - // The button opens Blurt's own page in Settings — the only Settings - // link Apple allows (the General › Keyboard deep links are private - // API and fail review) — and iOS puts a Keyboards row on that page - // for any app with a keyboard, so the steps start from there. + // The button's link (`openSettingsURLString`) is the only Settings + // link Apple allows — the General › Keyboard deep links are private + // API and fail review. It is meant to land on Blurt's own page, where + // iOS puts a Keyboards row for any app with a keyboard, but not every + // build honours it (the iOS 26 simulator opens Settings' top level), + // so the steps name the whole path, which holds from either screen. Text( - "Open Settings, tap Keyboards, then turn on Blurt and Allow Full Access. " + "In Settings, go to Apps › Blurt › Keyboards, turn on Blurt, then Allow Full Access. " + "Full Access is what lets the keyboard send your words to Blurt." ) .font(BlurtType.body(DesignTokens.Typography.sizeCaption)).foregroundStyle(BlurtBrand.muted) diff --git a/App/BlurtiOS/BlurtiOSCore/KeyboardModel+Lexicon.swift b/App/BlurtiOS/BlurtiOSCore/KeyboardModel+Lexicon.swift new file mode 100644 index 00000000..0620b0b5 --- /dev/null +++ b/App/BlurtiOS/BlurtiOSCore/KeyboardModel+Lexicon.swift @@ -0,0 +1,37 @@ +import Foundation +import UIKit + +// MARK: - The phone's word list, handed to the app + +extension KeyboardModel { + /// The phone's own word list — contact names and text replacements — for + /// the app to spell names right with no setup. Read here because only the + /// keyboard is offered it; the app reads it back out of the App Group. + func requestLexicon() { + let refreshed = SharedStore.lexiconRefreshedAt ?? .distantPast + guard Date().timeIntervalSince(refreshed) > Self.lexiconRefreshInterval else { return } + // UIKit calls back on an XPC queue, not the main thread (a main-actor + // closure here traps), while the lexicon's entries are main-actor in + // Swift's eyes. So: take the callback anywhere, hand the immutable lexicon + // over, and read it on the main actor. + controller?.requestSupplementaryLexicon { @Sendable lexicon in + let handoff = LexiconHandoff(lexicon) + Task { @MainActor in + Self.store(handoff.lexicon.entries.map { LexiconEntry(userInput: $0.userInput, documentText: $0.documentText) }) + } + } + } + + fileprivate nonisolated struct LexiconHandoff: @unchecked Sendable { + let lexicon: UILexicon + init(_ lexicon: UILexicon) { self.lexicon = lexicon } + } + + /// Hands the word list to the app: written to the App Group, stamped, and + /// signalled, so the next dictation spells the names right. + static func store(_ entries: [LexiconEntry]) { + SharedStore.write(entries, forKey: BlurtShared.Key.lexicon) + SharedStore.lexiconRefreshedAt = Date() + SharedStore.post(BlurtShared.Signal.lexicon) + } +} diff --git a/App/BlurtiOS/BlurtiOSCore/KeyboardModel+Mic.swift b/App/BlurtiOS/BlurtiOSCore/KeyboardModel+Mic.swift index b6c1a4cb..f6cfc465 100644 --- a/App/BlurtiOS/BlurtiOSCore/KeyboardModel+Mic.swift +++ b/App/BlurtiOS/BlurtiOSCore/KeyboardModel+Mic.swift @@ -21,7 +21,9 @@ extension KeyboardModel { if hasFullAccess { UINotificationFeedbackGenerator().notificationOccurred(.warning) } return case .idle, .recording, .pasted, .copied, .error: - perform(gate.modifierDown(at: elapsed)) + let action = gate.modifierDown(at: elapsed) + if action == .start { pressSentOver = snapshot.state } + perform(action) } } @@ -103,7 +105,15 @@ extension KeyboardModel { /// a press over a recording a tap had latched only re-latches it, so /// flipping to the keys mid-dictation doesn't throw the words away; a press /// the orb ignored (busy, or Blurt not ready) undoes nothing. + /// + /// Nor does a fresh press sent over a dictation the app was still running: + /// the picture can say recording for a moment after this keyboard released + /// it (leaving the screen, opening the term field), and the engine drops a + /// press then, so it started nothing — a cancel would land on the words + /// being transcribed. package func undoPress() { - perform(gate.otherKeyDown()) + let action = gate.otherKeyDown() + if action == .cancel, pressSentOver == .recording || pressSentOver == .processing { return } + perform(action) } } diff --git a/App/BlurtiOS/BlurtiOSCore/KeyboardModel.swift b/App/BlurtiOS/BlurtiOSCore/KeyboardModel.swift index 97208f93..1048f670 100644 --- a/App/BlurtiOS/BlurtiOSCore/KeyboardModel.swift +++ b/App/BlurtiOS/BlurtiOSCore/KeyboardModel.swift @@ -110,6 +110,9 @@ package final class KeyboardModel { /// the app drops it unread (or was never there to read it), so no answer /// is coming: see `expireUnansweredPress`. @ObservationIgnored package var unansweredPressSentAt: Date? + /// What the picture showed when the orb last sent a press — whether that + /// press could have started a dictation at all (see `undoPress`). + @ObservationIgnored package var pressSentOver: PhaseSnapshot.State? /// The `at` of a notice the keyboard already let go of: a re-read of the /// same snapshot cannot replay it. @ObservationIgnored package var dismissedNoticeAt: Date? @@ -366,35 +369,4 @@ package final class KeyboardModel { } } } - - /// The phone's own word list — contact names and text replacements — for - /// the app to spell names right with no setup. Read here because only the - /// keyboard is offered it; the app reads it back out of the App Group. - private func requestLexicon() { - let refreshed = SharedStore.lexiconRefreshedAt ?? .distantPast - guard Date().timeIntervalSince(refreshed) > Self.lexiconRefreshInterval else { return } - // UIKit calls back on an XPC queue, not the main thread (a main-actor - // closure here traps), while the lexicon's entries are main-actor in - // Swift's eyes. So: take the callback anywhere, hand the immutable lexicon - // over, and read it on the main actor. - controller?.requestSupplementaryLexicon { @Sendable lexicon in - let handoff = LexiconHandoff(lexicon) - Task { @MainActor in - Self.store(handoff.lexicon.entries.map { LexiconEntry(userInput: $0.userInput, documentText: $0.documentText) }) - } - } - } - - private nonisolated struct LexiconHandoff: @unchecked Sendable { - let lexicon: UILexicon - init(_ lexicon: UILexicon) { self.lexicon = lexicon } - } - - /// Hands the word list to the app: written to the App Group, stamped, and - /// signalled, so the next dictation spells the names right. - static func store(_ entries: [LexiconEntry]) { - SharedStore.write(entries, forKey: BlurtShared.Key.lexicon) - SharedStore.lexiconRefreshedAt = Date() - SharedStore.post(BlurtShared.Signal.lexicon) - } } diff --git a/App/BlurtiOS/BlurtiOSProbe/MicPixels.swift b/App/BlurtiOS/BlurtiOSProbe/MicPixels.swift index fcdc778a..20a954ba 100644 --- a/App/BlurtiOS/BlurtiOSProbe/MicPixels.swift +++ b/App/BlurtiOS/BlurtiOSProbe/MicPixels.swift @@ -9,6 +9,9 @@ import XCTest /// the mic key's frame and counts pixels that differ from the frame's own /// corner, which is the host's material: the grille's dots, lit or at rest, /// cover well over a tenth of the box; an empty key covers none. +/// Main-actor: everything it reads — screenshots, element frames — is +/// XCUIAutomation's, which is main-actor in Swift 6. +@MainActor enum MicPixels { /// The least share of differing pixels that counts as the element drawn. static let drawnThreshold = 0.02 diff --git a/App/BlurtiOS/BlurtiOSTests/KeyboardModelFuzzTests.swift b/App/BlurtiOS/BlurtiOSTests/KeyboardModelFuzzTests.swift index 37e01703..cb881326 100644 --- a/App/BlurtiOS/BlurtiOSTests/KeyboardModelFuzzTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/KeyboardModelFuzzTests.swift @@ -15,7 +15,7 @@ struct KeyboardModelFuzzTests { /// One event the fuzz can send. `apply` phases come as the app would /// publish them; the rest are the keyboard's own entry points. enum Event: CaseIterable { - case micDown, micUp, cancel + case micDown, micUp, cancel, swipeOffOrb case phaseIdle, phaseConnecting, phaseRecording, phaseProcessing, phasePasted, phaseCopied, phaseError case answerConnecting, answerError case appNotListening, appListening @@ -87,6 +87,10 @@ struct KeyboardModelFuzzTests { let event = random.pick(Event.allCases) trace.append(event) let before = commands.sent.count + // Read before the event: whether words were in flight, and whether a + // word is highlighted for the term field to open over. + let stateBefore = model.snapshot.state + let seededTerm = KeyboardModel.termCandidate(from: proxy.selectedText) != nil drive(model, proxy, event, &random) if epoch { commands.sent.removeAll() @@ -101,6 +105,18 @@ struct KeyboardModelFuzzTests { pressOpen = command.id case .release, .cancel: pressOpen = nil } + // The user's words are never thrown away behind their back. A cancel + // over a recording or a transcription is only ever theirs to ask for: + // the × key, or the term field opened over a highlighted word (whose + // words would land on the word being fixed). Leaving the screen, a + // swipe across the orb, the plain + — none of them may drop speech. + if command.kind == .cancel, stateBefore == .recording || stateBefore == .processing { + let asked = event == .cancel || (event == .beginTerm && seededTerm) + #expect( + asked, + "words dropped: cancel in \(stateBefore) by \(event) — seed \(seed) step \(step); last 12: \(trace.suffix(12))" + ) + } } if Self.phaseEvents.contains(event), !model.isSettled || model.snapshot.command == pressOpen { pressOpen = nil @@ -111,88 +127,6 @@ struct KeyboardModelFuzzTests { } } - // swiftlint:disable:next cyclomatic_complexity function_body_length - private func drive(_ model: KeyboardModel, _ proxy: FakeProxy, _ event: Event, _ random: inout Random) { - epoch = false - switch event { - case .micDown: model.micDown() - case .micUp: model.micUp() - case .cancel: model.cancel() - case .phaseIdle: model.apply(snapshot(.idle)) - case .phaseConnecting: model.apply(snapshot(.connecting)) - case .phaseRecording: model.apply(snapshot(.recording)) - case .phaseProcessing: model.apply(snapshot(.processing)) - case .phasePasted: model.apply(snapshot(.pasted)) - case .phaseCopied: model.apply(snapshot(.copied)) - case .phaseError: model.apply(snapshot(.error)) - case .answerConnecting: - model.apply(PhaseSnapshot(state: .connecting, message: nil, level: 0, at: Date(), command: model.unansweredPress)) - case .answerError: - model.apply(PhaseSnapshot(state: .error, message: nil, level: 0, at: Date(), command: model.unansweredPress)) - case .appNotListening: - listening(false) - model.apply(model.snapshot) - case .appListening: - listening(true) - model.apply(model.snapshot) - case .beginTerm: model.beginAddingTerm() - case .cancelTerm: model.cancelAddingTerm() - case .saveTerm: model.saveTerm() - case .typeLetter: model.type(random.pick(["a", "B", "z"])) - case .space: model.space() - case .deleteBack: model.deleteBackward() - case .newline: model.newline() - case .selectWord: - proxy.selected = "Rizz" - model.contextChanged() - case .selectOther: - proxy.selected = random.pick(["Gyatt", "neil bisht", " Rizz "]) - model.contextChanged() - case .clearSelection: - proxy.selected = nil - model.contextChanged() - case .addSelected: model.addSelectedTerm() - case .dismissSelected: model.dismissSelection() - case .flipPanel: model.flipPanel(towardsLeading: random.next() % 2 == 0) - case .toggleSymbols: model.toggleSymbols() - case .toggleMore: model.toggleMore() - case .toggleShift: model.toggleShift() - case .appeared: - model.hasFullAccess = true - model.appeared() - case .appearedNoAccess: - // Without Full Access the keyboard can't reach the app: whatever was - // in flight is the app's to end; the command ledger starts over. - model.hasFullAccess = false - model.appeared() - model.hasFullAccess = true - epoch = true - case .disappeared: model.disappeared() - case .contextChanged: model.contextChanged() - case .resultFresh: - SharedStore.write( - DictationResult(id: UUID(), text: "words", deliveredAt: Date(), recipient: nil), forKey: BlurtShared.Key.result) - model.resultArrived() - case .resultStale: - SharedStore.write( - DictationResult(id: UUID(), text: "old", deliveredAt: Date().addingTimeInterval(-60), recipient: nil), - forKey: BlurtShared.Key.result) - model.resultArrived() - case .resultForOther: - SharedStore.write( - DictationResult(id: UUID(), text: "theirs", deliveredAt: Date(), recipient: "someone-else"), - forKey: BlurtShared.Key.result) - model.resultArrived() - case .hostTyped: - proxy.before += "x" - model.contextChanged() - case .hostMovedCursor: - proxy.before += "ab" - proxy.after = String(proxy.after.dropFirst(2)) - model.contextChanged() - } - } - /// The events that apply a phase from the app. static let phaseEvents: Set = [ .phaseIdle, .phaseConnecting, .phaseRecording, .phaseProcessing, .phasePasted, .phaseCopied, .phaseError, @@ -301,3 +235,94 @@ struct KeyboardModelFuzzTests { } } } + +// The event → model call table, apart from the fuzz loop and its checks so +// neither crowds the other. +extension KeyboardModelFuzzTests { + // swiftlint:disable:next cyclomatic_complexity function_body_length + private func drive(_ model: KeyboardModel, _ proxy: FakeProxy, _ event: Event, _ random: inout Random) { + epoch = false + switch event { + case .micDown: model.micDown() + case .micUp: model.micUp() + case .cancel: model.cancel() + case .swipeOffOrb: + // A swipe that began on the orb and travelled after its press went out + // (MicControl's `.cancelSentPress`): the press, then its undo. + model.micDown() + model.undoPress() + case .phaseIdle: model.apply(snapshot(.idle)) + case .phaseConnecting: model.apply(snapshot(.connecting)) + case .phaseRecording: model.apply(snapshot(.recording)) + case .phaseProcessing: model.apply(snapshot(.processing)) + case .phasePasted: model.apply(snapshot(.pasted)) + case .phaseCopied: model.apply(snapshot(.copied)) + case .phaseError: model.apply(snapshot(.error)) + case .answerConnecting: + model.apply(PhaseSnapshot(state: .connecting, message: nil, level: 0, at: Date(), command: model.unansweredPress)) + case .answerError: + model.apply(PhaseSnapshot(state: .error, message: nil, level: 0, at: Date(), command: model.unansweredPress)) + case .appNotListening: + listening(false) + model.apply(model.snapshot) + case .appListening: + listening(true) + model.apply(model.snapshot) + case .beginTerm: model.beginAddingTerm() + case .cancelTerm: model.cancelAddingTerm() + case .saveTerm: model.saveTerm() + case .typeLetter: model.type(random.pick(["a", "B", "z"])) + case .space: model.space() + case .deleteBack: model.deleteBackward() + case .newline: model.newline() + case .selectWord: + proxy.selected = "Rizz" + model.contextChanged() + case .selectOther: + proxy.selected = random.pick(["Gyatt", "neil bisht", " Rizz "]) + model.contextChanged() + case .clearSelection: + proxy.selected = nil + model.contextChanged() + case .addSelected: model.addSelectedTerm() + case .dismissSelected: model.dismissSelection() + case .flipPanel: model.flipPanel(towardsLeading: random.next() % 2 == 0) + case .toggleSymbols: model.toggleSymbols() + case .toggleMore: model.toggleMore() + case .toggleShift: model.toggleShift() + case .appeared: + model.hasFullAccess = true + model.appeared() + case .appearedNoAccess: + // Without Full Access the keyboard can't reach the app: whatever was + // in flight is the app's to end; the command ledger starts over. + model.hasFullAccess = false + model.appeared() + model.hasFullAccess = true + epoch = true + case .disappeared: model.disappeared() + case .contextChanged: model.contextChanged() + case .resultFresh: + SharedStore.write( + DictationResult(id: UUID(), text: "words", deliveredAt: Date(), recipient: nil), forKey: BlurtShared.Key.result) + model.resultArrived() + case .resultStale: + SharedStore.write( + DictationResult(id: UUID(), text: "old", deliveredAt: Date().addingTimeInterval(-60), recipient: nil), + forKey: BlurtShared.Key.result) + model.resultArrived() + case .resultForOther: + SharedStore.write( + DictationResult(id: UUID(), text: "theirs", deliveredAt: Date(), recipient: "someone-else"), + forKey: BlurtShared.Key.result) + model.resultArrived() + case .hostTyped: + proxy.before += "x" + model.contextChanged() + case .hostMovedCursor: + proxy.before += "ab" + proxy.after = String(proxy.after.dropFirst(2)) + model.contextChanged() + } + } +} diff --git a/App/BlurtiOS/BlurtiOSTests/KeyboardModelGateTests.swift b/App/BlurtiOS/BlurtiOSTests/KeyboardModelGateTests.swift index 5cf91109..4cc7b373 100644 --- a/App/BlurtiOS/BlurtiOSTests/KeyboardModelGateTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/KeyboardModelGateTests.swift @@ -198,6 +198,28 @@ struct KeyboardModelGateTests { #expect(commands.sent.map(\.kind) == [.press, .cancel, .press, .release]) } + @Test("a swipe over a recording this keyboard just released cancels nothing: those words are being transcribed") + func undoPressOverReleasedRecording() { + let suite = ScratchSuite() + defer { suite.tearDown() } + let rig = ready() + let model = rig.model + let commands = rig.commands + model.micDown() + model.micUp() + model.apply(snapshot(.recording)) + // Leaving the screen releases it; the app hasn't published `.processing` + // yet, so the picture still says recording and the gate is idle. + model.disappeared() + #expect(commands.sent.map(\.kind) == [.press, .release]) + // A swipe across the orb in that moment: its press went out over a + // dictation the app was still running, so it started nothing to undo. + model.micDown() + model.undoPress() + #expect(commands.sent.map(\.kind) == [.press, .release, .press]) + #expect(model.gate.isIdle) + } + @Test("a press the app never answers stops holding the gate once it is too old for the app to take") func unansweredPressExpires() { let suite = ScratchSuite() diff --git a/App/BlurtiOS/README.md b/App/BlurtiOS/README.md index eced40f8..ae271b0b 100644 --- a/App/BlurtiOS/README.md +++ b/App/BlurtiOS/README.md @@ -103,8 +103,9 @@ scripts/ios-sim.sh --screenshot shot.png # …and capture the screen Xcode 27 replaced Simulator.app with Device Hub (`Xcode.app/Contents/Applications/DeviceHub.app`), which the script opens; turn off its **Always simulate hardware keyboard** setting (Device Hub → -Settings…) or no on-screen keyboard ever appears. Then: Blurt → Open Settings → Keyboards → -Blurt on, Allow Full Access; Start listening; in Notes, hold the globe key, pick Blurt, tap the +Settings…) or no on-screen keyboard ever appears. Then: Blurt → Open Settings, and Apps → Blurt → +Keyboards → Blurt on, Allow Full Access (the simulator's Settings opens at its top level, not on +Blurt's page); Start listening; in Notes, hold the globe key, pick Blurt, tap the mic. The keyboard's crash logs, if any, land in `~/Library/Logs/DiagnosticReports/BlurtKeyboard-*`, and `xcrun simctl spawn booted log show --last 5m --predicate 'process == "BlurtKeyboard"'` shows its console. @@ -133,8 +134,8 @@ shows its console. 4. Plug the phone in (Developer Mode on: Settings → Privacy & Security), pick it as the run destination, run the `BlurtiOS` scheme. On the phone, trust the developer app (Settings → General → VPN & Device Management). In the app: **Use an API key instead** (debug builds - only), **Allow** the microphone, then **Open Settings → Keyboards**: turn on Blurt and - **Allow Full Access**. + only), **Allow** the microphone, then **Open Settings** and go to **Apps › Blurt › Keyboards** + (a phone may open straight on Blurt's page): turn on Blurt and **Allow Full Access**. 5. Back in the app, **Start listening**, then go to Messages, hold the globe key, pick Blurt, and tap the mic. Tap again to stop, or hold it while you talk. The words land in the field. 6. Try the other two layouts from the app's Keyboard picker; the keyboard reads the choice the diff --git a/scripts/ios-check.sh b/scripts/ios-check.sh index 96fdda22..01f27363 100755 --- a/scripts/ios-check.sh +++ b/scripts/ios-check.sh @@ -12,6 +12,9 @@ # 2. `swiftlint analyze` — unused imports — over that build's compiler log, # as check.sh runs it over the Mac app's. # 3. periphery over the iPhone project — unused declarations. +# 4. The probe's XCUITest bundle (BlurtiOSProbe), compiled: its own scheme, +# run only by hand (the screenshot and keyboard-flow scripts), so nothing +# else ever builds it — and it went uncompiled through a Swift 6 change. # swift-format, `swiftlint lint`, the invariants and ios-typecheck.sh already # cover App/BlurtiOS from check.sh, which reads every tracked Swift file. # @@ -60,6 +63,14 @@ else FAILED+=("swiftlint analyze") fi +echo "==> build-for-testing (BlurtiOSProbe)" +# The same derived data as the tests, so only the probe's own files compile. +# shellcheck source=scripts/ios-lib.sh +source "$REPO_ROOT/scripts/ios-lib.sh" +xcodebuild build-for-testing -project App/BlurtiOS/BlurtiOS.xcodeproj -scheme BlurtiOSProbe \ + -destination 'generic/platform=iOS Simulator' -derivedDataPath "${BLURT_DERIVED_DATA:-$REPO_ROOT/.build/ios-sim}" \ + "${IOS_SIM_SIGNING[@]}" -quiet || FAILED+=("build-for-testing (BlurtiOSProbe)") + echo "==> periphery (App/BlurtiOS)" # `--retain-public`: the engine's public API is used by the Mac app this scan # can't see, and the engine's own findings are excluded from the report, so only From ca9aa7a683d4161ac0d16d1e290e03a513758a39 Mon Sep 17 00:00:00 2001 From: Alex Kroman Date: Fri, 2 Oct 2026 13:29:07 -0700 Subject: [PATCH 78/79] Docs: bring CLAUDE.md, the agents and the guides up to the iPhone work MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - CLAUDE.md: running the iPhone app (the matching simulator runtime, ios-sim.sh, enabling the keyboard, the Mac-side microphone the simulator records through), ios-check.sh, the generated iPhone project, and which reviewers cover App/BlurtiOS. - AGENTS.md settled decisions + project-guardrails: logic stays in BlurtiOSCore (no SwiftUI there), no private Settings deep links, no bundled brand fonts; the skill also carries the never-cancel-words rule and the serial iPhone tests. - swift6-concurrency-reviewer: the iPhone's invariants (no audio in the keyboard, nonisolated payloads, system callbacks off the main actor, no cancel on a stale picture, close order, serial tests). - cleanup-reviewer: what on the iPhone is deliberate — the TEMPORARY voice candidates, gallery/probe entry points, package access, seams. - macos-hig-reviewer: Mac only. - CONTRIBUTING.md: an iPhone section; README.md: App/BlurtiOS in the map. Co-Authored-By: Claude Opus 5.5 --- .claude/agents/cleanup-reviewer.md | 20 ++++++++ .claude/agents/macos-hig-reviewer.md | 2 +- .claude/agents/swift6-concurrency-reviewer.md | 37 ++++++++++++-- .claude/skills/project-guardrails/SKILL.md | 12 +++++ AGENTS.md | 49 ++++++++++--------- CLAUDE.md | 29 +++++++++-- CONTRIBUTING.md | 25 ++++++++++ README.md | 7 +++ 8 files changed, 148 insertions(+), 33 deletions(-) diff --git a/.claude/agents/cleanup-reviewer.md b/.claude/agents/cleanup-reviewer.md index 3ff11c76..ca5a0440 100644 --- a/.claude/agents/cleanup-reviewer.md +++ b/.claude/agents/cleanup-reviewer.md @@ -71,6 +71,26 @@ design. Note also that `check.sh` already runs `periphery scan --strict` with `retain_public: false`, so plainly-unreferenced symbols are caught — spend your effort on what periphery cannot see. +On the iPhone (`App/BlurtiOS/`), equally deliberate: + +- **The two losing mic concepts are on purpose.** `VoiceRibs`, `VoiceStreak`, + `VoiceElementKind`'s `.ribs`/`.streak`, `SharedStore.voiceElementKind` and the + `-BlurtGalleryVoice` switch are marked TEMPORARY: three concepts are built side + by side until one is picked (`DESIGN.md` › The voice element), then the losers go + together. Don't propose deleting one piecemeal. +- **The gallery and the probe screens are entry points**, reached by launch + arguments (`-BlurtGallery…`, `-BlurtProbeField`) from `scripts/design-capture.sh`, + `ios-keyboard-shot.sh`, `ios-keyboard-flows.sh` and `apple-geometry.sh` — not + from any view. Likewise the `BlurtiOSProbe` XCUITest helpers. +- **`BlurtiOSCore` uses `package` access, not `public`,** and its explicit + `package init`s exist because a memberwise initializer is only ever internal. + Seams with one production use (`KeyboardModel.transport`, `.urlOpener`, + `.proxyOverride`, `SharedStore.override`) are there for the tests. +- **`SimulatorAudioSource` is the simulator's microphone**, not a duplicate of + `WindowedAudioSource`: `AVCaptureSession` carries no audio in the simulator. +- The iPhone periphery scan is CI's and `ios-check.sh`'s, with `--retain-public`, + so it reports the iPhone code's own dead declarations — `package` ones included. + ## Method Verify every claim by reading the real code; never report a suspicion. For an diff --git a/.claude/agents/macos-hig-reviewer.md b/.claude/agents/macos-hig-reviewer.md index f3c22b71..1514ca49 100644 --- a/.claude/agents/macos-hig-reviewer.md +++ b/.claude/agents/macos-hig-reviewer.md @@ -1,6 +1,6 @@ --- name: macos-hig-reviewer -description: Reviews SwiftUI/AppKit UI changes against macOS Human Interface Guidelines — modality, alerts vs inline validation, grouped-form structure, controls, and native idioms. Use after editing views in App/Blurt (wizard, settings, overlay). +description: Reviews SwiftUI/AppKit UI changes against macOS Human Interface Guidelines — modality, alerts vs inline validation, grouped-form structure, controls, and native idioms. Use after editing views in App/Blurt (wizard, settings, overlay). Mac only — not for App/BlurtiOS, whose views follow App/BlurtiOS/DESIGN.md. tools: Read, Grep, Glob --- diff --git a/.claude/agents/swift6-concurrency-reviewer.md b/.claude/agents/swift6-concurrency-reviewer.md index 4a2c3f15..5c5808fb 100644 --- a/.claude/agents/swift6-concurrency-reviewer.md +++ b/.claude/agents/swift6-concurrency-reviewer.md @@ -1,13 +1,17 @@ --- name: swift6-concurrency-reviewer -description: Reviews Swift changes for Swift 6 strict-concurrency correctness (actor isolation, Sendable, @MainActor, data races) and Blurt's documented audio/pipeline invariants. Use after editing engine or app code that touches actors, async, the mic capture path, or the dictation pipeline. +description: Reviews Swift changes for Swift 6 strict-concurrency correctness (actor isolation, Sendable, @MainActor, data races) and Blurt's documented audio/pipeline invariants. Use after editing engine, Mac app or iPhone (App/BlurtiOS) code that touches actors, async, the mic capture path, the dictation pipeline, or the keyboard's hand-off with the app. tools: Read, Grep, Glob, Bash --- -You are a Swift 6 strict-concurrency reviewer for Blurt, a macOS dictation -app. The engine (`Sources/BlurtEngine/`) is a `swift-tools-version:6.2` -package with **no external dependencies**; the app shell (`App/Blurt/`) is -AppKit/SwiftUI. +You are a Swift 6 strict-concurrency reviewer for Blurt, a dictation app for +macOS and iPhone. The engine (`Sources/BlurtEngine/`) is a `swift-tools-version:6.2` +package with **no external dependencies**; the Mac shell (`App/Blurt/`) is +AppKit/SwiftUI. The iPhone app (`App/BlurtiOS/`) is two processes over one App +Group — the app (listens and transcribes) and a keyboard extension (inserts the +words) — with their shared logic in the `BlurtiOSCore` static framework. Every +iPhone target defaults to the main actor (`SWIFT_DEFAULT_ACTOR_ISOLATION`), so +anything that runs elsewhere is spelled `nonisolated`. ## What to review @@ -51,6 +55,29 @@ Look at the changes (default to the working diff via `git diff` and `BlurtUITests` XCUITest bundle is the exception), and must never touch the real Keychain (`APIKeyStore`) — use an isolated service. +### On the iPhone (`App/BlurtiOS/`) + +- **The keyboard never hears anything:** no `AVFoundation`/`AVFAudio` in + `BlurtKeyboard/`, `Shared/` or `BlurtiOSCore/` (the keyboard links the core). + Capture lives only in the app (`WindowedAudioSource`, `SimulatorAudioSource`). +- **Payloads that cross processes or the capture path are `nonisolated`** — + `SharedStore`, `PhaseSnapshot`, `KeyboardCommand`, `DictationResult` and the + rest in `SharedState.swift`. Flag one that drifts back to the main-actor default. +- **System callbacks arrive off the main actor:** a `DarwinObserver` handler and + `requestSupplementaryLexicon`'s callback (an XPC queue) are `@Sendable` and hop + with `Task { @MainActor in … }`; a main-actor closure there traps at runtime. +- **The keyboard never cancels words behind the user's back:** a `.cancel` over a + recording or a transcription comes only from the × key or the term field opened + over a highlighted word. Ordering bugs between the keyboard's picture (the last + phase it read) and the app's real state are where this breaks — flag a cancel + sent on a stale `.recording`/`.processing` snapshot. +- **An automatic window close ends the session before the feed:** the release has + to find the audio, so `ListeningWindow.onClosingOnItsOwn` is awaited before + `source.close()`. +- **`BlurtiOSTests` run serially** — they swap the global `SharedStore.override`; + an async test suspended mid-await must not see another suite's. Flag a change + that re-enables parallel testing for that bundle. + ## How to report Verify before asserting: read the surrounding code, and if useful run diff --git a/.claude/skills/project-guardrails/SKILL.md b/.claude/skills/project-guardrails/SKILL.md index fc2b7062..cd1fd6c4 100644 --- a/.claude/skills/project-guardrails/SKILL.md +++ b/.claude/skills/project-guardrails/SKILL.md @@ -190,4 +190,16 @@ only one of stt_prompt or prompt; they are the same field`, before the audio is kept open, not a per-press capture — the two rows marked "(macOS shell)" above do not apply. - Insertion is the keyboard's `textDocumentProxy`; the clipboard is only the fallback when no keyboard is there to take the words, and the phase then says "Copied", never "Pasted". +- **Logic lives in `BlurtiOSCore`, UI in the targets** — the Mac's engine/shell split. The + core has no SwiftUI, no views and no audio; its API is `package`, not `public` (periphery + still sees dead code); it is static, linked by both targets. It alone is coverage-gated at + 88%. A UI hook the model needs is a shell-side extension, never SwiftUI in the core. +- **The keyboard never cancels words behind the user's back.** A cancel over a recording or a + transcription comes only from the × key or the term field opened over a highlighted word — + not from leaving the screen, a swipe across the orb, or the plain +. The fuzz test enforces it. +- **No private Settings URLs** (`App-Prefs:`): `openSettingsURLString` only, and the copy names + the whole path (Apps › Blurt › Keyboards). +- **No bundled brand fonts** — removed over their licence; `BlurtType`'s roles use system faces. +- **`BlurtiOSTests` run serially** (scheme + `-parallel-testing-enabled NO`): they swap a global + `SharedStore.override`, which `.serialized` alone doesn't protect across suites. - The full list, with every number, is `App/BlurtiOS/DESIGN.md`. diff --git a/AGENTS.md b/AGENTS.md index 9ff81469..16c3e968 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -393,29 +393,32 @@ a rule that outlives its row keeps firing and keeps citing this table while enfo project has already reversed. Reworded the row? Update the anchor. Reversed the decision? Delete the rule along with the row. -| Don't | Because | -| --------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Add an external SPM dependency to the engine | Dependency-free by rule (biggest supply-chain risk); a `check.sh` guard fails on `.package(` in `Package.swift` or a `url:`/`github:` package in `project.yml`. Extend `BlurtEngine` instead. | -| Use `AVAudioEngine` / `installTap` for capture | A long-lived engine bound its input graph to one device and went stale on a mic↔built-in switch — `-10868` (`kAudioUnitErr_FormatNotSupported`) or all-zero buffers. `MicCapture` builds a fresh `AVCaptureSession` recorder per capture (owner-directed move from `AVAudioRecorder`, 2026-08-25). | -| Pre-open the mic to shave bring-up latency (a warm/prepared recorder) | Measured against `kAudioDevicePropertyDeviceIsRunningSomewhere`: neither building an `AVCaptureSession` nor the retired `AVAudioRecorder.prepareToRecord()` opens the device, so neither pre-pays the 180–600 ms route activation `record()` costs. A warm-recorder lifecycle bought ~15 ms and cost a device-identity check, a pin check, an expiry and a bring-up flag. `MicCapture.warmUp()` is stateless: it absorbs the process's first-touch cost and holds nothing. | -| Add streaming STT | The dictation API returns the full (already rewritten) text in one response; the overlay shows "Transcribing…" then the full text. The one WebSocket allowed is the experimental read-aloud feature's streaming **TTS**, confined to `Sources/BlurtEngine/TTS/AssemblyAISpeechSynthesizer.swift` (the invariant gate exempts only that file). | -| Call the dictation API in a way its docs don't describe | **The reference is the source of truth.** Every path, header, multipart part, `config` key, response key and error key Blurt sends or reads is one it documents. The route has been renamed repeatedly and still answers to names the docs have dropped — `prompt`, `keyterms`, `word_boost`, `language_code`, `llm: null` — so a 200 is not evidence a field is supported, only that it has not been removed yet; treat anything absent from the docs as deprecated. Undocumented behaviour carries no compatibility promise, so a feature resting on it can stop working silently: that is why `llm: null` (the only rewrite off switch there is) and the `message` error field were dropped on 2026-09-11, along with `warmUp()`'s GET at the bare host root in favour of the documented `GET /warm`. Running tighter than a documented cap is fine — `STTPrompt.characterCap` does. Measuring is still how a claim gets settled, and the docs have been wrong twice (see `DictationWireTypes` on unknown fields, `STTPrompt` on the 6000 cap), but a measurement licenses _distrusting_ a documented field, never _sending_ an undocumented one. | -| Add a client-side LLM cleanup pass | Cleanup is the dictation API's server-side rewrite, requested by `config.llm_instruction` on the same `/v1/transcribe/live` call. No LLM Gateway client, no `StylerProtocol`, no styling stage, no second request — transcription steering belongs in `STTPrompt`. | -| Add local models or model downloads | Transcription is a remote AssemblyAI call: no on-device ASR/LLM, no model cache, no download UI. | -| Pin transcription to English, or set a language at all | Hurt non-English transcription; language is left to the model's own detection. **No `config.language_codes`** either — note the plural, which is the documented spelling, though the undocumented singular `language_code` is accepted too (a 200, not the unknown-key 400 a bogus name earns), so both are live and both are pinned absent. Detection was measured to work with neither it nor a prompt set (es/fr/de/ja clips each transcribed in their own language against the live endpoint, rewrite included), and re-measured 2026-09-11: a Spanish clip came back as Spanish with no field, with `language_codes: ["es"]`, **and** with `language_codes: ["en"]` — asking for English did not force English, so the reference's `["en"]` default does not describe this route and omission is not a bet on a default. Setting one would only take working detection away. `KeytermsWireTests` asserts the absence of both spellings. | -| Send `config.prompt` alongside `config.stt_prompt` | They are the same field under two names — the docs give `stt_prompt` as the field and note it is "Also accepted as `prompt`" — and a request carrying both is rejected before the audio is read (`provide only one of stt_prompt or prompt; they are the same field`). So this is never a compatible addition: it is a 400 on _every_ dictation. `stt_prompt` is the documented spelling and the only one to send; `prompt` is the legacy one, and the route's own inner validator still answers under it (see `STTPrompt.characterCap`), which is a reason to treat it as deprecated rather than interchangeable. | -| Bring back `config.conversation_context` | Replaced by `config.stt_prompt` (`STTPrompt`), which carries the same two signals as one string. Both fields still work and can ride the same request, so re-adding the turn list sends the prior text twice rather than failing. `prompt` is `stt_prompt`'s own alias — a request carrying both is a 400 (`they are the same field`) — and a custom prompt replaces the service's managed default, which is the trade this swap accepted. | -| Widen the request's context past history + the prior chunk | `STTPrompt.text` reads exactly two fields of `TranscriptionContext` — `recentTranscripts` and `priorText`. The app name, window title, field label and selected text are captured for the paste path and the developer-mode log and stay on the machine; the app/window/field hints and the `Selected text:` block were removed, not gated. Don't add one back, and don't route that context onto the request by another path. The user's key terms are the exception that proves the rule: they _are_ sent, as the request's own `keyterms_prompt` list (`KeytermsBoost`) — never folded back into the prompt. | -| Add a "remove filler words (um, uh, like)" clause | Not in the STT model's trained instruction set — a no-op, deliberately dropped; disfluency removal is the server-side LLM rewrite's job. | -| Add a keystroke-typing paste path or a length threshold | Injection is **always** clipboard paste (save → write → ⌘V → settle → restore), with the copied-to-clipboard degradation when the target is lost. | -| Add `LSUIElement` or a menu-bar-**only** mode | Blurt is a Dock app first. The `MenuBarExtra` status item is convenience layered on the Dock icon; the notch can hide a status item, so nothing may depend on it. A menu-bar-only variant was reverted twice. | -| Add a `KeyboardShortcuts` package or a key+modifier chord | The trigger is a single lone modifier, home-grown (`CGEventTap` + `DictationKeyGate`), and swallows nothing. | -| Hand-roll an updater beside Sparkle, or start it in a dev build | Updates go through Sparkle (`UpdaterModel`, app-side; EdDSA-signed appcast published per release). The download-only GitHub-API checker it replaced and the earlier `mxcl/AppUpdater` are gone — don't add a second update path, and keep update code out of the engine. Only the shipping bundle id starts the updater: a dev build must never replace itself with the release. | -| Hand-edit `Blurt.xcodeproj/project.pbxproj` | Generated from `project.yml`; `check.sh`'s drift check fails on any manual edit (a Claude PreToolUse hook also blocks it). | -| Redirect the post-build install away from `/Applications` | TCC won't register apps in DerivedData/`/tmp`, so permission toggles never appear. | -| Touch the real Keychain in tests | `APIKeyStore` is the production item — a test that writes it triggers Keychain prompts and corrupts the real item's ACL. Use an isolated service (see `KeychainStoreTests`) or `InMemoryAPIKeyStore`. | -| Add backwards-compat shims for removed types | Deleted types stay deleted — no deprecated re-exports. | -| Give the keyboard extension a microphone or any audio type | iOS lets no keyboard use the microphone, and the design keeps every audio type out of it: the app listens and transcribes over its always-on capture, the keyboard is a remote control that inserts the words (`KeyboardRelayInjector`). An `AVFoundation` import in `App/BlurtiOS/BlurtKeyboard`, `Shared` or `BlurtiOSCore` (which the keyboard links) is that decision being reversed by accident. | +| Don't | Because | +| ------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Add an external SPM dependency to the engine | Dependency-free by rule (biggest supply-chain risk); a `check.sh` guard fails on `.package(` in `Package.swift` or a `url:`/`github:` package in `project.yml`. Extend `BlurtEngine` instead. | +| Use `AVAudioEngine` / `installTap` for capture | A long-lived engine bound its input graph to one device and went stale on a mic↔built-in switch — `-10868` (`kAudioUnitErr_FormatNotSupported`) or all-zero buffers. `MicCapture` builds a fresh `AVCaptureSession` recorder per capture (owner-directed move from `AVAudioRecorder`, 2026-08-25). | +| Pre-open the mic to shave bring-up latency (a warm/prepared recorder) | Measured against `kAudioDevicePropertyDeviceIsRunningSomewhere`: neither building an `AVCaptureSession` nor the retired `AVAudioRecorder.prepareToRecord()` opens the device, so neither pre-pays the 180–600 ms route activation `record()` costs. A warm-recorder lifecycle bought ~15 ms and cost a device-identity check, a pin check, an expiry and a bring-up flag. `MicCapture.warmUp()` is stateless: it absorbs the process's first-touch cost and holds nothing. | +| Add streaming STT | The dictation API returns the full (already rewritten) text in one response; the overlay shows "Transcribing…" then the full text. The one WebSocket allowed is the experimental read-aloud feature's streaming **TTS**, confined to `Sources/BlurtEngine/TTS/AssemblyAISpeechSynthesizer.swift` (the invariant gate exempts only that file). | +| Call the dictation API in a way its docs don't describe | **The reference is the source of truth.** Every path, header, multipart part, `config` key, response key and error key Blurt sends or reads is one it documents. The route has been renamed repeatedly and still answers to names the docs have dropped — `prompt`, `keyterms`, `word_boost`, `language_code`, `llm: null` — so a 200 is not evidence a field is supported, only that it has not been removed yet; treat anything absent from the docs as deprecated. Undocumented behaviour carries no compatibility promise, so a feature resting on it can stop working silently: that is why `llm: null` (the only rewrite off switch there is) and the `message` error field were dropped on 2026-09-11, along with `warmUp()`'s GET at the bare host root in favour of the documented `GET /warm`. Running tighter than a documented cap is fine — `STTPrompt.characterCap` does. Measuring is still how a claim gets settled, and the docs have been wrong twice (see `DictationWireTypes` on unknown fields, `STTPrompt` on the 6000 cap), but a measurement licenses _distrusting_ a documented field, never _sending_ an undocumented one. | +| Add a client-side LLM cleanup pass | Cleanup is the dictation API's server-side rewrite, requested by `config.llm_instruction` on the same `/v1/transcribe/live` call. No LLM Gateway client, no `StylerProtocol`, no styling stage, no second request — transcription steering belongs in `STTPrompt`. | +| Add local models or model downloads | Transcription is a remote AssemblyAI call: no on-device ASR/LLM, no model cache, no download UI. | +| Pin transcription to English, or set a language at all | Hurt non-English transcription; language is left to the model's own detection. **No `config.language_codes`** either — note the plural, which is the documented spelling, though the undocumented singular `language_code` is accepted too (a 200, not the unknown-key 400 a bogus name earns), so both are live and both are pinned absent. Detection was measured to work with neither it nor a prompt set (es/fr/de/ja clips each transcribed in their own language against the live endpoint, rewrite included), and re-measured 2026-09-11: a Spanish clip came back as Spanish with no field, with `language_codes: ["es"]`, **and** with `language_codes: ["en"]` — asking for English did not force English, so the reference's `["en"]` default does not describe this route and omission is not a bet on a default. Setting one would only take working detection away. `KeytermsWireTests` asserts the absence of both spellings. | +| Send `config.prompt` alongside `config.stt_prompt` | They are the same field under two names — the docs give `stt_prompt` as the field and note it is "Also accepted as `prompt`" — and a request carrying both is rejected before the audio is read (`provide only one of stt_prompt or prompt; they are the same field`). So this is never a compatible addition: it is a 400 on _every_ dictation. `stt_prompt` is the documented spelling and the only one to send; `prompt` is the legacy one, and the route's own inner validator still answers under it (see `STTPrompt.characterCap`), which is a reason to treat it as deprecated rather than interchangeable. | +| Bring back `config.conversation_context` | Replaced by `config.stt_prompt` (`STTPrompt`), which carries the same two signals as one string. Both fields still work and can ride the same request, so re-adding the turn list sends the prior text twice rather than failing. `prompt` is `stt_prompt`'s own alias — a request carrying both is a 400 (`they are the same field`) — and a custom prompt replaces the service's managed default, which is the trade this swap accepted. | +| Widen the request's context past history + the prior chunk | `STTPrompt.text` reads exactly two fields of `TranscriptionContext` — `recentTranscripts` and `priorText`. The app name, window title, field label and selected text are captured for the paste path and the developer-mode log and stay on the machine; the app/window/field hints and the `Selected text:` block were removed, not gated. Don't add one back, and don't route that context onto the request by another path. The user's key terms are the exception that proves the rule: they _are_ sent, as the request's own `keyterms_prompt` list (`KeytermsBoost`) — never folded back into the prompt. | +| Add a "remove filler words (um, uh, like)" clause | Not in the STT model's trained instruction set — a no-op, deliberately dropped; disfluency removal is the server-side LLM rewrite's job. | +| Add a keystroke-typing paste path or a length threshold | Injection is **always** clipboard paste (save → write → ⌘V → settle → restore), with the copied-to-clipboard degradation when the target is lost. | +| Add `LSUIElement` or a menu-bar-**only** mode | Blurt is a Dock app first. The `MenuBarExtra` status item is convenience layered on the Dock icon; the notch can hide a status item, so nothing may depend on it. A menu-bar-only variant was reverted twice. | +| Add a `KeyboardShortcuts` package or a key+modifier chord | The trigger is a single lone modifier, home-grown (`CGEventTap` + `DictationKeyGate`), and swallows nothing. | +| Hand-roll an updater beside Sparkle, or start it in a dev build | Updates go through Sparkle (`UpdaterModel`, app-side; EdDSA-signed appcast published per release). The download-only GitHub-API checker it replaced and the earlier `mxcl/AppUpdater` are gone — don't add a second update path, and keep update code out of the engine. Only the shipping bundle id starts the updater: a dev build must never replace itself with the release. | +| Hand-edit `Blurt.xcodeproj/project.pbxproj` | Generated from `project.yml`; `check.sh`'s drift check fails on any manual edit (a Claude PreToolUse hook also blocks it). | +| Redirect the post-build install away from `/Applications` | TCC won't register apps in DerivedData/`/tmp`, so permission toggles never appear. | +| Touch the real Keychain in tests | `APIKeyStore` is the production item — a test that writes it triggers Keychain prompts and corrupts the real item's ACL. Use an isolated service (see `KeychainStoreTests`) or `InMemoryAPIKeyStore`. | +| Add backwards-compat shims for removed types | Deleted types stay deleted — no deprecated re-exports. | +| Give the keyboard extension a microphone or any audio type | iOS lets no keyboard use the microphone, and the design keeps every audio type out of it: the app listens and transcribes over its always-on capture, the keyboard is a remote control that inserts the words (`KeyboardRelayInjector`). An `AVFoundation` import in `App/BlurtiOS/BlurtKeyboard`, `Shared` or `BlurtiOSCore` (which the keyboard links) is that decision being reversed by accident. | +| Move the iPhone's logic back into its UI targets, or views into `BlurtiOSCore` | The iPhone code splits the way the Mac's does: `App/BlurtiOS/BlurtiOSCore` is the logic (the App Group contract, `KeyboardModel`, `VoiceState`, `KeyboardInteraction`, term packs, the relay injector) — no SwiftUI, no views, no audio, `package` access, a static framework both targets link — and it alone carries the 88% coverage gate (`scripts/ios-test.sh`), as the engine alone does on the Mac. Logic in a view file escapes that gate; SwiftUI in the core drags the views' colours and tokens into a module the keyboard's memory budget pays for. A UI hook the model needs becomes a shell-side extension (`KeyboardModel+Palette.swift`). | +| Deep-link into Settings › General › Keyboard (`App-Prefs:`, `prefs:`) | Private URLs: App Review rejects them (2.5.1) and they break between iOS releases. `UIApplication.openSettingsURLString` — Blurt's own page, whose Keyboards row iOS adds for any app with a keyboard — is the only Settings link; the setup step names the whole path (Apps › Blurt › Keyboards) because some builds (the iOS 26 simulator) open Settings at its top level instead. | +| Bundle the brand's fonts in the iPhone app | Modern Gothic Mono, UN 11ST and Oceanic Text were bundled and removed: their licence covers the web, not an app in a public MIT repo. `BlurtType`'s roles (`mono`, `heading`, `body`) map to the system's monospaced, serif and default faces; a face comes back only with written app-embedding rights, through the same roles. | **Platform scope.** Two rows above are the Mac shell's, not the iPhone's, and the iPhone app diverges from them on purpose: "no warm recorder" — on iOS the app keeps the microphone open for a listening window (`App/BlurtiOS/BlurtiOS/Sources/AudioSource.swift`), because iOS refuses to open it from the background and the keyboard, which is where a dictation starts, is in the background of whatever app the user is typing in; and "injection is always a clipboard paste" — on iOS the keyboard inserts through its `textDocumentProxy`, and the clipboard is only the degradation when no keyboard is there to take the words. Neither changes the engine: `MicCapture` and `KeyInjector` stay as they are and are macOS-only; the iOS app supplies its own `MicCaptureProtocol` and `InjectorProtocol` conformances. `App/BlurtiOS/DESIGN.md` is the iPhone's own list. diff --git a/CLAUDE.md b/CLAUDE.md index 44c6b238..1eeac300 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -11,7 +11,7 @@ This file adds only what is specific to Claude Code: the tooling wired up under | Hook | What it does | | ----------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `SessionStart` → `session-start.sh` | Web/Linux sandboxes only (`CLAUDE_CODE_REMOTE=true`): installs the portable linters so `scripts/check.sh --portable` works, then prints a preflight noting CI is the authority on green. SwiftLint and swift-format are _not_ installed — their Linux builds ship as GitHub release binaries, which the default network policy blocks. Local macOS sessions exit immediately. | -| `PreToolUse` → `protect-pbxproj.sh` | Blocks edits to `App/Blurt/Blurt.xcodeproj/project.pbxproj` (exit 2). Edit `App/Blurt/project.yml` and run `xcodegen generate` instead. | +| `PreToolUse` → `protect-pbxproj.sh` | Blocks edits to `App/Blurt/Blurt.xcodeproj/project.pbxproj` (exit 2). Edit `App/Blurt/project.yml` and run `xcodegen generate` instead. (The iPhone project, `App/BlurtiOS/BlurtiOS.xcodeproj`, isn't committed at all: edit `App/BlurtiOS/project.yml`; every script regenerates it.) | | `PostToolUse` → `swift-format.sh` | Formats every edited `*.swift` file with the repo's `.swift-format` config, so edits are CI-clean by construction. No-ops when the tool is absent. | | `PostToolUse` → `swiftlint.sh` | Lints edited Swift files and surfaces violations immediately rather than at `check.sh` time. | @@ -59,9 +59,12 @@ globs go in one invocation so `hook-lib.sh` and `release-lib.sh` are in the inpu ## Subagents (`.claude/agents/`) -- **`swift6-concurrency-reviewer`** — run after editing engine or app code that touches actors, - async, the mic capture path, or the dictation pipeline. +- **`swift6-concurrency-reviewer`** — run after editing engine, Mac app or iPhone code that + touches actors, async, the mic capture path, the dictation pipeline, or the keyboard's hand-off + with the iPhone app (`BlurtiOSCore`'s model, `DictationCoordinator`, `ListeningWindow`). - **`macos-hig-reviewer`** — run after editing views in `App/Blurt/` (wizard, settings, overlay). + Mac only: the iPhone's views answer to `App/BlurtiOS/DESIGN.md`, checked on sight through the + gallery and the probe's screenshots (`scripts/design-capture.sh`, `scripts/ios-keyboard-shot.sh`). - **`cleanup-reviewer`** — quality-only review (reuse, simplification/dead code, efficiency, altitude), one agent per angle. Use it for `/simplify`-style passes instead of writing the guardrails into an ad-hoc prompt: it loads `project-guardrails` itself and already knows the @@ -89,9 +92,27 @@ not raw `brew install` or hand-rolled `xcodebuild` invocations: full Xcode — not just the Command Line Tools, Homebrew, a free Apple Development certificate) and why the scripts work the way they do. +For the iPhone app (`App/BlurtiOS`, the keyboard included), from the repo root: + +1. `xcodebuild -downloadPlatform iOS` — one-time: the simulator runtime **matching this Xcode's + iOS SDK**. An older runtime is refused at the destination ("iOS 26.5 is not installed"), even + with simulators for it listed. +2. `scripts/ios-sim.sh` — build, boot a simulator, install, grant the microphone, launch. + `BLURT_SIM_DEVICE="iPhone Air"` picks one; avoid the one a test run is using. +3. In the simulator: Settings › Apps › Blurt › Keyboards (or General › Keyboard › Keyboards › + Add New Keyboard) — Blurt on, Allow Full Access; then **Start listening** in Blurt. + +The simulator records through the Mac's microphone (`SimulatorAudioSource`), so dictation also +needs macOS to allow the **Simulator** app the microphone (Privacy & Security › Microphone) and +the right input under the Simulator's I/O › Audio Input — a refused microphone records silence +rather than failing. `scripts/ios-check.sh` runs the iPhone's quality gates (tests with the +`BlurtiOSCore` coverage floor, `swiftlint analyze`, periphery, the probe build); `check.sh` runs it +itself when this Mac has the matching runtime. + ## Permissions `.claude/settings.json` pre-allows the read-only and verification commands this repo needs (`swift test`, `swift build`, `xcodegen generate`, the Debug `xcodebuild` invocation, the linters, -`scripts/check.sh` with and without `--portable`, `scripts/dev-build.sh`). If you find yourself +`scripts/check.sh` with and without `--portable`, `scripts/dev-build.sh`, and the iPhone scripts: +`ios-sim.sh`, `ios-test.sh`, `ios-check.sh`, `ios-typecheck.sh`). If you find yourself prompted for a command that belongs in that set, add it there rather than working around it. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ff2deb44..641960eb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -105,6 +105,31 @@ Run `xcodegen generate` and commit the regenerated `Blurt.xcodeproj/project.pbxp alongside it. `check.sh` fails on drift between the two. Never hand-edit the `.pbxproj` — it's generated. +### The iPhone app + +`App/BlurtiOS` is the iPhone app and the keyboard it ships: the app listens and transcribes, the +keyboard inserts the words (iOS lets no keyboard use the microphone). Its logic lives in +`BlurtiOSCore`, apart from its views the way `BlurtEngine` is apart from the Mac shell. + +```bash +xcodebuild -downloadPlatform iOS # one-time: the simulator runtime this Xcode builds for +scripts/ios-sim.sh # build, boot, install, grant the mic, launch (repo root) +scripts/ios-check.sh # its gates: tests + coverage floor, swiftlint analyze, periphery +``` + +No team or signing is needed for the simulator. Two things trip people up: + +- **The runtime has to match Xcode's iOS SDK.** Simulators on an older runtime still show in the + list but are refused at build time. +- **The simulator dictates through your Mac's microphone,** so macOS has to allow the + **Simulator** app the microphone (System Settings › Privacy & Security › Microphone), with the + right input picked under the Simulator's **I/O › Audio Input**. Refused, it records silence + rather than failing. + +To use the keyboard: Settings › Apps › Blurt › Keyboards — turn on Blurt, then Allow Full +Access — and **Start listening** in Blurt. A phone needs a paid team for the App Group; +[`App/BlurtiOS/README.md`](./App/BlurtiOS/README.md) has that, the tests and the design loop. + ### Working without a Mac You can read and edit Swift, and `scripts/check.sh --portable` fully verifies diff --git a/README.md b/README.md index e7f8ea99..e8612d1c 100644 --- a/README.md +++ b/README.md @@ -241,6 +241,13 @@ App/Blurt/ AppKit/SwiftUI shell (Xcode project generated by XcodeG Overlay/, MenuBar/ floating status pill, menu bar dictation indicator Update/ UpdaterModel: the Sparkle updater behind every "Check for Updates" Wizard/ setup wizard + settings window + +App/BlurtiOS/ the iPhone app and its keyboard (in development; README.md there) + BlurtiOSCore/ the logic, apart from the UI: the App Group contract between the + app and the keyboard, the keyboard's model and rules + BlurtiOS/Sources/ the app: listens and transcribes over the engine's pipeline + BlurtKeyboard/Sources/ the keyboard: a remote control that inserts the words, since + iOS lets no keyboard use the microphone ``` The engine is a standalone package you can embed to build your own dictation From 72494f74dc3db5e1d8ea9f6083bf495569905715 Mon Sep 17 00:00:00 2001 From: Alex Kroman Date: Fri, 2 Oct 2026 13:47:37 -0700 Subject: [PATCH 79/79] Simplify: one unanswered press, one rig, scripts on their shared helpers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From a reuse / simplification / efficiency / altitude pass over this branch's work. - DictationCoordinator.windowClosingOnItsOwn decided release-or-cancel from its own copy of the phase, which trails the session and could still say .connecting over a live recording — cancelling it. It now just releases: the session's commands run in order and a release checks the session's own phase on its turn. - The unanswered press is stored whole (a KeyboardCommand), so its id and age can't disagree; KeyboardCommand.isFresh is the one freshness rule the app and the keyboard both read; appeared() and syncGate share letGoOfExpiredPress. KeyboardModel.face resolves like voiceKind does. - BlurtType.mono takes Font.Weight (its own enum mirrored it once the bundled faces went). One KeyboardRig + snapshot() for the four suites that each built their own; a no-op 200 ms test sleep goes. - scripts: one IOS_DERIVED in ios-lib.sh; require_tools and pretty_xcodebuild from release-lib.sh; one TEST_FLAGS array; no placeholder coverage exclude; `swiftlint analyze` reads only the iPhone modules' compile commands, so no stderr filter is needed; here-strings throughout check-invariants.sh; check.sh decides once whether the iPhone gates run and skips the Catalyst typecheck when they do. - CI cost: the probe build uses the tests' destination and flags, so it reuses their build (arm64 only, seconds) instead of rebuilding for a second architecture; CodeQL builds the iPhone code for arm64 only; the duplicate xcodegen step goes; xcbeautify is installed for the logs. Kept as is: periphery's own build. The tests' simulator index reports WindowedAudioSource unused, since the simulator builds SimulatorAudioSource in its place. Co-Authored-By: Claude Opus 5.5 --- .claude/skills/check/SKILL.md | 14 ++-- .github/workflows/check.yml | 22 +++---- .github/workflows/codeql.yml | 5 +- AGENTS.md | 4 +- .../BlurtKeyboard/Sources/KeyCap.swift | 2 +- .../Sources/KeyboardModel+Palette.swift | 7 +- .../Sources/DictationCoordinator.swift | 24 ++++--- .../BlurtiOSCore/KeyboardModel+Mic.swift | 18 ++--- .../BlurtiOSCore/KeyboardModel+Phase.swift | 4 +- App/BlurtiOS/BlurtiOSCore/KeyboardModel.swift | 14 ++-- App/BlurtiOS/BlurtiOSCore/SharedState.swift | 7 ++ .../KeyboardLifecycleTests.swift | 39 +++-------- .../KeyboardModelFuzzTests.swift | 30 +++------ .../KeyboardModelGateTests.swift | 56 ++++++---------- .../BlurtiOSTests/ProtocolTests.swift | 45 +++---------- App/BlurtiOS/BlurtiOSTests/TestSuite.swift | 41 ++++++++++++ App/BlurtiOS/Shared/BlurtType.swift | 18 +---- scripts/apple-geometry.sh | 2 +- scripts/check-invariants.sh | 12 ++-- scripts/check.sh | 46 ++++++++----- scripts/ios-check.sh | 65 ++++++++++--------- scripts/ios-keyboard-flows.sh | 2 +- scripts/ios-keyboard-shot.sh | 2 +- scripts/ios-lib.sh | 6 ++ scripts/ios-sim.sh | 2 +- scripts/ios-test.sh | 39 ++++++----- 26 files changed, 249 insertions(+), 277 deletions(-) diff --git a/.claude/skills/check/SKILL.md b/.claude/skills/check/SKILL.md index 1eb3bc19..6a8b40da 100644 --- a/.claude/skills/check/SKILL.md +++ b/.claude/skills/check/SKILL.md @@ -126,13 +126,13 @@ hides every lint finding behind it — expect to fix a batch, not a queue. ## The iPhone app -`check.sh` covers `App/BlurtiOS` with the dependency guard, the invariants, the linters and -`ios-typecheck.sh`, and — off CI, when an iPhone simulator on this Xcode's iOS runtime exists — -`scripts/ios-check.sh`: the tests with `BlurtiOSCore`'s coverage gate, `swiftlint analyze` and -periphery over the iPhone project. Without that runtime it is skipped with a note (the closing `ok` -line says so) and CI's `ios-build` job, which runs the same script, is the authority. Locally: `scripts/ios-typecheck.sh` -typechecks both iPhone targets on a Mac with only the Command Line Tools (run by `check.sh` when -the SDK carries the Mac Catalyst frameworks), `scripts/ios-test.sh` runs `BlurtiOSTests` on a +`check.sh` covers `App/BlurtiOS` with the dependency guard, the invariants and the linters, and — +off CI, when an iPhone simulator on this Xcode's iOS runtime exists — `scripts/ios-check.sh`: the +tests with `BlurtiOSCore`'s coverage gate, `swiftlint analyze`, the probe build and periphery over +the iPhone project. Without that runtime it is skipped with a note (the closing `ok` line says so) +and CI's `ios-build` job, which runs the same script, is the authority; `check.sh` then runs +`scripts/ios-typecheck.sh` instead, which typechecks the iPhone targets against the Mac Catalyst +frameworks — the stand-in for a Mac with only the Command Line Tools. Locally, `scripts/ios-test.sh` runs `BlurtiOSTests` on a simulator when Xcode is installed and enforces `BlurtiOSCore`'s line-coverage floor (`MIN_IOS_COVERAGE`, 88%; `BLURT_IOS_SANITIZER=thread` or `address` runs the TSan / ASan pass CI's `ios-sanitizers` job runs), and `scripts/ios-sim.sh` builds and launches the app there. diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index f11b6b30..36e1fe78 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -255,17 +255,13 @@ jobs: # is in the Brewfile too, so this is the version check.sh uses. run: brew install xcodegen - - name: Generate the iPhone app's project - working-directory: blurt/App/BlurtiOS - # Generated here rather than committed, unlike App/Blurt/Blurt.xcodeproj: - # that project is committed because people open it; this one is generated - # a second before every build, so it can never go stale against its yml. - run: xcodegen generate --quiet - - - name: Install the iPhone gates' linters - # swiftlint for `swiftlint analyze`, periphery for the unused-code scan; - # both are in the Brewfile too, so these are the versions check.sh uses. - run: brew install swiftlint periphery + - name: Install the iPhone gates' tools + # swiftlint for `swiftlint analyze`, periphery for the unused-code scan, + # xcbeautify for the build output; all in the Brewfile too, so these are + # the versions check.sh uses. The project itself is generated, not + # committed (people open App/Blurt's; this one is regenerated a second + # before every build by ios-test.sh, so it can never go stale). + run: brew install swiftlint periphery xcbeautify - name: Build the iPhone app and its keyboard, and run its quality gates working-directory: blurt @@ -298,8 +294,8 @@ jobs: path: blurt persist-credentials: false - - name: Install XcodeGen - run: brew install xcodegen + - name: Install XcodeGen and xcbeautify + run: brew install xcodegen xcbeautify - name: Run the iPhone unit tests under the ${{ matrix.sanitizer }} sanitizer working-directory: blurt diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index f4183f1b..1cb9fa60 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -134,7 +134,9 @@ jobs: # The iPhone app, its keyboard and BlurtiOSCore, traced in the same # database: CodeQL analyses whatever the job compiles between init and # analyze, so the Mac build alone would leave App/BlurtiOS unscanned. - # Simulator, signing off — nothing here needs a device or a team. + # Simulator, signing off — nothing here needs a device or a team. One + # architecture: CodeQL extracts every compile, and a second slice would + # compile and extract every file again for nothing new. - name: Build Swift (iPhone) working-directory: App/BlurtiOS run: | @@ -144,6 +146,7 @@ jobs: -configuration Debug \ -destination 'generic/platform=iOS Simulator' \ -derivedDataPath "$DERIVED-ios" \ + ARCHS=arm64 ONLY_ACTIVE_ARCH=YES \ CODE_SIGN_IDENTITY="-" \ CODE_SIGNING_REQUIRED=NO \ CODE_SIGNING_ALLOWED=NO \ diff --git a/AGENTS.md b/AGENTS.md index 16c3e968..1f036d24 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -225,8 +225,8 @@ the iPhone code to the bar the engine and the Mac shell meet in `check.sh`: `Blu warnings as errors and a **line-coverage gate** on `BlurtiOSCore`, the iPhone code's logic (≥ `MIN_IOS_COVERAGE` in `scripts/ios-test.sh`, the engine's 88%; raise it as coverage grows), then **`swiftlint analyze`** over that from-scratch build's log and **periphery** over the iPhone -project; `check.sh`'s swift-format, `swiftlint lint`, invariants and `ios-typecheck.sh` already read -every Swift file there. In the sibling +project; `check.sh`'s swift-format, `swiftlint lint` and invariants already read every Swift file +there. In the sibling **`ios-sanitizers`** job, one runner per sanitizer — **ThreadSanitizer** and **AddressSanitizer** passes run the same tests. `codeql.yml`'s Swift analysis builds the iPhone app as well as the Mac one, so both are in its database. `gate` fails unless all of them are green (or skipped for a docs-only change). Two sibling jobs exist purely to shorten the loop for whoever is diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyCap.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyCap.swift index cf37f728..2360179f 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyCap.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyCap.swift @@ -52,7 +52,7 @@ struct KeyCap: View { // quieter than a letter. Tracking adds its space after the last // letter too; the same again before the first keeps the word centred. Text((title ?? "").uppercased()) - .font(BlurtType.mono(DesignTokens.Typography.sizeLabel, weight: .medium)) + .font(BlurtType.mono(DesignTokens.Typography.sizeLabel, weight: DesignTokens.Typography.weightLabel)) .tracking(DesignTokens.Typography.trackingEyebrow) .padding(.leading, DesignTokens.Typography.trackingEyebrow) .foregroundStyle(tint ?? palette.keyTextSecondary) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Palette.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Palette.swift index 8e49ed8d..f4b9e71e 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Palette.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Palette.swift @@ -1,11 +1,8 @@ import BlurtiOSCore extension KeyboardModel { - /// The chosen theme's palette in the host's appearance — or, for a - /// preview, the face it is told (`faceOverride`). - var palette: KeyboardPalette { - .resolve(faceOverride?.themeID ?? themeID, dark: faceOverride?.dark ?? isDark) - } + /// The palette for the face the model draws (`KeyboardModel.face`). + var palette: KeyboardPalette { .resolve(face.themeID, dark: face.dark) } } extension ThemeFace { diff --git a/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift b/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift index 4ea9f077..738df78f 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift @@ -118,18 +118,16 @@ final class DictationCoordinator { /// The window is closing without the user — its time ran out, or a call or /// Siri took the microphone. Unlike `stopListening`, what was already said - /// still counts: a recording is released, so its words land (on the - /// clipboard when no keyboard is up), and a mic still coming up is - /// cancelled — the keyboard's own rule when it leaves the screen. Awaited - /// before the feed closes, so the release still finds the audio. Without - /// this the session sat in `.recording` over a dead feed until its - /// auto-release, while the keyboard, seeing no app, showed idle. - func windowClosingOnItsOwn() async { - switch phase { - case .recording: await session.release() - case .connecting: await session.cancel() - case .idle, .transcribing, .injecting, .failed, .cancelled, .pasted, .noTarget: break - } + /// still counts, so this releases rather than cancels — and leaves the + /// deciding to the session. Its commands run in order and a release checks + /// the session's own phase on its turn: a recording is released and its + /// words land (on the clipboard when no keyboard is up); a mic still coming + /// up finishes, then releases a capture too short to transcribe; anything + /// later is untouched. Not this coordinator's `phase`, a copy that trails + /// the session and could still say `.connecting` over a live recording. + /// Awaited before the feed closes, so the release still finds the audio. + private func windowClosingOnItsOwn() async { + await session.release() } func handle(_ url: URL) { @@ -167,7 +165,7 @@ final class DictationCoordinator { SharedStore.remove(forKey: BlurtShared.Key.command) // A notification held while the app was suspended delivers a press from // minutes ago; the user has long since moved on. - guard Date().timeIntervalSince(command.sentAt) < BlurtShared.commandFreshnessWindow else { return } + guard command.isFresh() else { return } switch command.kind { case .press: Self.pressContext.withLock { diff --git a/App/BlurtiOS/BlurtiOSCore/KeyboardModel+Mic.swift b/App/BlurtiOS/BlurtiOSCore/KeyboardModel+Mic.swift index f6cfc465..d905573e 100644 --- a/App/BlurtiOS/BlurtiOSCore/KeyboardModel+Mic.swift +++ b/App/BlurtiOS/BlurtiOSCore/KeyboardModel+Mic.swift @@ -67,8 +67,7 @@ extension KeyboardModel { id: UUID(), kind: kind, priorText: proxy?.documentContextBeforeInput, selectedText: proxy?.selectedText, sentAt: Date(), keyboard: instanceID) transport(command) - unansweredPress = kind == .press ? command.id : nil - unansweredPressSentAt = kind == .press ? command.sentAt : nil + unansweredPressCommand = kind == .press ? command : nil // A press the app never answers would leave the gate latched over // nothing. Either notification can be missed: first catch up with a phase // the app may have published unheard; if the picture is still as it was, @@ -91,15 +90,18 @@ extension KeyboardModel { /// than `BlurtShared.commandFreshnessWindow` unread, and an app that was /// killed answers nothing — so its latch can't outlive it. True when it did. @discardableResult - package func expireUnansweredPress(now: Date = Date()) -> Bool { - guard unansweredPress != nil, let sentAt = unansweredPressSentAt, - now.timeIntervalSince(sentAt) >= BlurtShared.commandFreshnessWindow - else { return false } - unansweredPress = nil - unansweredPressSentAt = nil + package func expireUnansweredPress() -> Bool { + guard let press = unansweredPressCommand, !press.isFresh() else { return false } + unansweredPressCommand = nil return true } + /// The gate's half of the same rule: a latch held only for an expired + /// press goes with it, once nothing is in flight. + func letGoOfExpiredPress() { + if expireUnansweredPress(), isSettled { gate.reset() } + } + /// A swipe that began on the orb (the panel's carousel) after its press /// went out: undo exactly what that press did. A fresh press is cancelled; /// a press over a recording a tap had latched only re-latches it, so diff --git a/App/BlurtiOS/BlurtiOSCore/KeyboardModel+Phase.swift b/App/BlurtiOS/BlurtiOSCore/KeyboardModel+Phase.swift index 1f42e71b..5a6ccd51 100644 --- a/App/BlurtiOS/BlurtiOSCore/KeyboardModel+Phase.swift +++ b/App/BlurtiOS/BlurtiOSCore/KeyboardModel+Phase.swift @@ -62,8 +62,8 @@ extension KeyboardModel { // in another app, or a previous keyboard process) must latch it, so the // next tap is the stop rather than a press the engine drops. // A press too old for the app to take will never be answered at all. - expireUnansweredPress() - if !isSettled || current.command == unansweredPress { unansweredPress = nil } + letGoOfExpiredPress() + if !isSettled || current.command == unansweredPress { unansweredPressCommand = nil } if isSettled, !gate.isIdle { if unansweredPress == nil { gate.reset() } } else if !isSettled, gate.isIdle, current.state != .processing { diff --git a/App/BlurtiOS/BlurtiOSCore/KeyboardModel.swift b/App/BlurtiOS/BlurtiOSCore/KeyboardModel.swift index 1048f670..690e9819 100644 --- a/App/BlurtiOS/BlurtiOSCore/KeyboardModel.swift +++ b/App/BlurtiOS/BlurtiOSCore/KeyboardModel.swift @@ -105,11 +105,10 @@ package final class KeyboardModel { /// The press the app has not answered yet. A settled phase that does not /// answer it (the previous dictation's notice landing late) leaves the /// gate alone; anything in flight, or a phase carrying its id, answers it. - @ObservationIgnored package var unansweredPress: UUID? - /// When `unansweredPress` went out. Past `BlurtShared.commandFreshnessWindow` - /// the app drops it unread (or was never there to read it), so no answer - /// is coming: see `expireUnansweredPress`. - @ObservationIgnored package var unansweredPressSentAt: Date? + /// Kept whole, so its id and its age can't disagree: one too old for the + /// app to take is never answered (`expireUnansweredPress`). + @ObservationIgnored package var unansweredPressCommand: KeyboardCommand? + package var unansweredPress: UUID? { unansweredPressCommand?.id } /// What the picture showed when the orb last sent a press — whether that /// press could have started a dictation at all (see `undoPress`). @ObservationIgnored package var pressSentOver: PhaseSnapshot.State? @@ -126,6 +125,9 @@ package final class KeyboardModel { package var themeID = SharedStore.themeID /// For a preview: this theme face, whatever Settings and the host say. package var faceOverride: ThemeFace? + /// The face to draw: the preview's, else the chosen theme in the host's + /// appearance — as `voiceKind` and `micAlignment` resolve theirs. + package var face: ThemeFace { faceOverride ?? ThemeFace(themeID: themeID, dark: isDark) } /// TEMPORARY: which mic concept draws, from Settings — or, for a preview /// or a gallery row, whatever it is told. Goes with the losers. package var voiceKind: VoiceElementKind { voiceKindOverride ?? storedVoiceKind } @@ -230,7 +232,7 @@ package final class KeyboardModel { // `refresh` may apply no phase at all (none stored, or a notice already // let go of), so a press the app will never answer is let go of here too: // otherwise its latch would skip hands-free on every appearance after. - if expireUnansweredPress(), isSettled { gate.reset() } + letGoOfExpiredPress() startHeartbeat() requestLexicon() // Words that landed while this keyboard was away, still fresh and meant diff --git a/App/BlurtiOS/BlurtiOSCore/SharedState.swift b/App/BlurtiOS/BlurtiOSCore/SharedState.swift index 1ccb65db..18bff687 100644 --- a/App/BlurtiOS/BlurtiOSCore/SharedState.swift +++ b/App/BlurtiOS/BlurtiOSCore/SharedState.swift @@ -109,6 +109,13 @@ package nonisolated struct KeyboardCommand: Codable, Sendable { /// The keyboard process that sent it (`KeyboardModel.instanceID`): the /// words come back to the field the press was made in, not whichever is up. package let keyboard: String? + + /// Young enough for the app to act on. A notification held while the app + /// was suspended can deliver one from minutes ago, which the app drops + /// unread — so the keyboard stops waiting for an answer to it, too. + package func isFresh(now: Date = Date()) -> Bool { + now.timeIntervalSince(sentAt) < BlurtShared.commandFreshnessWindow + } } /// The words the app got back, for the keyboard to insert. The keyboard joins diff --git a/App/BlurtiOS/BlurtiOSTests/KeyboardLifecycleTests.swift b/App/BlurtiOS/BlurtiOSTests/KeyboardLifecycleTests.swift index f75afddb..8b5ce1d8 100644 --- a/App/BlurtiOS/BlurtiOSTests/KeyboardLifecycleTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/KeyboardLifecycleTests.swift @@ -12,26 +12,6 @@ import UIKit @Suite("Keyboard model: lifecycle and the app's signals", .serialized) @MainActor struct KeyboardLifecycleTests { - final class Commands { - var sent: [KeyboardCommand] = [] - } - - private func ready(_ proxy: FakeProxy = FakeProxy()) -> (KeyboardModel, Commands) { - let model = KeyboardModel() - model.proxyOverride = proxy - model.hasFullAccess = true - let now = Date() - SharedStore.listeningUntil = now.addingTimeInterval(600) - SharedStore.appSeenAt = now - model.isListening = true - let commands = Commands() - model.transport = { commands.sent.append($0) } - return (model, commands) - } - - private func snapshot(_ state: PhaseSnapshot.State) -> PhaseSnapshot { - PhaseSnapshot(state: state, message: nil, level: 0, at: Date()) - } /// Polls until `condition` holds or `timeout` passes; true when it held. private func eventually(_ timeout: Duration = .seconds(3), _ condition: () -> Bool) async -> Bool { @@ -48,15 +28,12 @@ struct KeyboardLifecycleTests { let suite = ScratchSuite() defer { suite.tearDown() } SharedStore.autoDictate = false - let (model, _) = ready() + let model = KeyboardRig().model model.appeared() #expect(await eventually { SharedStore.keyboardSeenAt != nil }) #expect(SharedStore.keyboardInstance == model.instanceID) model.disappeared() #expect(SharedStore.keyboardSeenAt == nil) - // The heartbeat is over: nothing marks the keyboard present again. - try? await Task.sleep(for: .milliseconds(200)) - #expect(SharedStore.keyboardSeenAt == nil) } @Test("attached to its controller, the keyboard follows the app's phase and result signals") @@ -65,7 +42,7 @@ struct KeyboardLifecycleTests { defer { suite.tearDown() } let proxy = FakeProxy() proxy.before = "Hi" - let (model, _) = ready(proxy) + let model = KeyboardRig(proxy: proxy).model let controller = UIInputViewController(nibName: nil, bundle: nil) model.attach(to: controller) SharedStore.write(snapshot(.recording), forKey: BlurtShared.Key.phase) @@ -81,7 +58,7 @@ struct KeyboardLifecycleTests { func noticeDwell() async throws { let suite = ScratchSuite() defer { suite.tearDown() } - let (model, _) = ready() + let model = KeyboardRig().model let pasted = snapshot(.pasted) let dwell = try #require(pasted.noticeDwellSeconds) model.apply(pasted) @@ -98,7 +75,9 @@ struct KeyboardLifecycleTests { func releaseWhileConnecting() { let suite = ScratchSuite() defer { suite.tearDown() } - let (model, commands) = ready() + let rig = KeyboardRig() + let model = rig.model + let commands = rig.commands model.micDown() model.apply(snapshot(.connecting)) // Push-to-talk let go before the mic was up: the engine would drop a @@ -114,7 +93,9 @@ struct KeyboardLifecycleTests { func heldReleaseDroppedOnFailure() { let suite = ScratchSuite() defer { suite.tearDown() } - let (model, commands) = ready() + let rig = KeyboardRig() + let model = rig.model + let commands = rig.commands model.micDown() model.apply(snapshot(.connecting)) model.perform(.stop) @@ -129,7 +110,7 @@ struct KeyboardLifecycleTests { defer { suite.tearDown() } let proxy = FakeProxy() proxy.selected = "Rizz" - let (model, _) = ready(proxy) + let model = KeyboardRig(proxy: proxy).model model.contextChanged() #expect(model.selectedTerm == "Rizz") model.addSelectedTerm() diff --git a/App/BlurtiOS/BlurtiOSTests/KeyboardModelFuzzTests.swift b/App/BlurtiOS/BlurtiOSTests/KeyboardModelFuzzTests.swift index cb881326..815583b7 100644 --- a/App/BlurtiOS/BlurtiOSTests/KeyboardModelFuzzTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/KeyboardModelFuzzTests.swift @@ -40,10 +40,6 @@ struct KeyboardModelFuzzTests { mutating func pick(_ items: [T]) -> T { items[Int(next() % UInt64(items.count))] } } - final class Commands { - var sent: [KeyboardCommand] = [] - } - /// Set by an event after which the command ledger starts over. private final class Flag { var value = false @@ -54,16 +50,6 @@ struct KeyboardModelFuzzTests { nonmutating set { epochFlag.value = newValue } } - private func snapshot(_ state: PhaseSnapshot.State) -> PhaseSnapshot { - PhaseSnapshot(state: state, message: nil, level: 0, at: Date()) - } - - private func listening(_ on: Bool) { - let now = Date() - SharedStore.listeningUntil = on ? now.addingTimeInterval(600) : nil - SharedStore.appSeenAt = on ? now : nil - } - @Test( "ten thousand random events never leave the model in a stale or contradictory state", arguments: [1, 2, 3, 4, 5]) func fuzz(seed: UInt64) { @@ -74,9 +60,9 @@ struct KeyboardModelFuzzTests { let model = KeyboardModel() model.proxyOverride = proxy model.hasFullAccess = true - let commands = Commands() + let commands = KeyboardRig.Commands() model.transport = { commands.sent.append($0) } - listening(true) + KeyboardRig.listening(true) model.appeared() var trace: [Event] = [] // The press the app has not taken yet: closed by our release or cancel, @@ -141,7 +127,7 @@ struct KeyboardModelFuzzTests { /// What must be true after every event, whatever came before. private func check( - _ model: KeyboardModel, _ proxy: FakeProxy, _ commands: Commands, after event: Event, _ context: String + _ model: KeyboardModel, _ proxy: FakeProxy, _ commands: KeyboardRig.Commands, after event: Event, _ context: String ) { // The term field's bookkeeping lives and dies with the field. let fieldOpen = model.termDraft != nil @@ -200,9 +186,9 @@ struct KeyboardModelFuzzTests { let model = KeyboardModel() model.proxyOverride = proxy model.hasFullAccess = true - let commands = Commands() + let commands = KeyboardRig.Commands() model.transport = { commands.sent.append($0) } - listening(true) + KeyboardRig.listening(true) // Hands-free off: a tap must be the press here, not the stop of one the // appearance started. SharedStore.autoDictate = false @@ -212,7 +198,7 @@ struct KeyboardModelFuzzTests { // The keyboard goes away and comes back, the app idle and listening. model.disappeared() SharedStore.write(snapshot(.idle), forKey: BlurtShared.Key.phase) - listening(true) + KeyboardRig.listening(true) model.hasFullAccess = true model.appeared() #expect(model.termDraft == nil, "field open after an appearance (round \(round))") @@ -263,10 +249,10 @@ extension KeyboardModelFuzzTests { case .answerError: model.apply(PhaseSnapshot(state: .error, message: nil, level: 0, at: Date(), command: model.unansweredPress)) case .appNotListening: - listening(false) + KeyboardRig.listening(false) model.apply(model.snapshot) case .appListening: - listening(true) + KeyboardRig.listening(true) model.apply(model.snapshot) case .beginTerm: model.beginAddingTerm() case .cancelTerm: model.cancelAddingTerm() diff --git a/App/BlurtiOS/BlurtiOSTests/KeyboardModelGateTests.swift b/App/BlurtiOS/BlurtiOSTests/KeyboardModelGateTests.swift index 4cc7b373..9ce960ea 100644 --- a/App/BlurtiOS/BlurtiOSTests/KeyboardModelGateTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/KeyboardModelGateTests.swift @@ -9,38 +9,20 @@ import Testing @Suite("Keyboard model: the gate and the app's answers", .serialized) @MainActor struct KeyboardModelGateTests { - struct Rig { - let model: KeyboardModel - let commands: Commands - } - - final class Commands { - var sent: [KeyboardCommand] = [] - } - - private func ready() -> Rig { - let proxy = FakeProxy() - let model = KeyboardModel() - model.proxyOverride = proxy - model.hasFullAccess = true - let now = Date() - SharedStore.listeningUntil = now.addingTimeInterval(600) - SharedStore.appSeenAt = now - model.isListening = true - let commands = Commands() - model.transport = { commands.sent.append($0) } - return Rig(model: model, commands: commands) - } - private func snapshot(_ state: PhaseSnapshot.State, level: Double = 0) -> PhaseSnapshot { - PhaseSnapshot(state: state, message: nil, level: level, at: Date()) + /// The press still out, aged past the window the app would take it in. + private func agePress(_ model: KeyboardModel) { + guard let press = model.unansweredPressCommand else { return } + model.unansweredPressCommand = KeyboardCommand( + id: press.id, kind: press.kind, priorText: press.priorText, selectedText: press.selectedText, + sentAt: Date().addingTimeInterval(-BlurtShared.commandFreshnessWindow - 1), keyboard: press.keyboard) } @Test("a settled phase resets a latched gate — once it answers the press; an older notice does not") func resetOnSettled() { let suite = ScratchSuite() defer { suite.tearDown() } - let rig = ready() + let rig = KeyboardRig() let model = rig.model let commands = rig.commands model.micDown() @@ -73,7 +55,7 @@ struct KeyboardModelGateTests { func commandCarriesSender() { let suite = ScratchSuite() defer { suite.tearDown() } - let rig = ready() + let rig = KeyboardRig() rig.model.micDown() rig.model.micUp() #expect(rig.commands.sent.map(\.keyboard) == [rig.model.instanceID]) @@ -83,7 +65,7 @@ struct KeyboardModelGateTests { func pressRetried() async throws { let suite = ScratchSuite() defer { suite.tearDown() } - let rig = ready() + let rig = KeyboardRig() let model = rig.model let commands = rig.commands model.micDown() @@ -106,7 +88,7 @@ struct KeyboardModelGateTests { func termFieldClosesDictation() { let suite = ScratchSuite() defer { suite.tearDown() } - let rig = ready() + let rig = KeyboardRig() let model = rig.model let commands = rig.commands model.micDown() @@ -135,7 +117,7 @@ struct KeyboardModelGateTests { func termFieldDuringProcessing() { let suite = ScratchSuite() defer { suite.tearDown() } - let rig = ready() + let rig = KeyboardRig() let model = rig.model let commands = rig.commands // A tap latched the gate; the app auto-released, with no finger event. @@ -148,7 +130,7 @@ struct KeyboardModelGateTests { #expect(commands.sent.map(\.kind) == [.press]) #expect(model.gate.isIdle) model.cancelAddingTerm() - (model.proxyOverride as? FakeProxy)?.selected = "Rizz" + rig.proxy.selected = "Rizz" model.beginAddingTerm() #expect(commands.sent.map(\.kind) == [.press, .cancel]) } @@ -157,7 +139,7 @@ struct KeyboardModelGateTests { func disappearDuringProcessing() { let suite = ScratchSuite() defer { suite.tearDown() } - let rig = ready() + let rig = KeyboardRig() let model = rig.model let commands = rig.commands model.micDown() @@ -175,7 +157,7 @@ struct KeyboardModelGateTests { func undoPress() { let suite = ScratchSuite() defer { suite.tearDown() } - let rig = ready() + let rig = KeyboardRig() let model = rig.model let commands = rig.commands // A swipe whose press went out from idle: taken back. @@ -202,7 +184,7 @@ struct KeyboardModelGateTests { func undoPressOverReleasedRecording() { let suite = ScratchSuite() defer { suite.tearDown() } - let rig = ready() + let rig = KeyboardRig() let model = rig.model let commands = rig.commands model.micDown() @@ -224,7 +206,7 @@ struct KeyboardModelGateTests { func unansweredPressExpires() { let suite = ScratchSuite() defer { suite.tearDown() } - let rig = ready() + let rig = KeyboardRig() let model = rig.model model.micDown() model.micUp() @@ -234,7 +216,7 @@ struct KeyboardModelGateTests { model.apply(snapshot(.pasted)) #expect(!model.gate.isIdle) // …and lets it go once the app would drop it unread. - model.unansweredPressSentAt = Date().addingTimeInterval(-BlurtShared.commandFreshnessWindow - 1) + agePress(model) model.apply(snapshot(.idle)) #expect(model.unansweredPress == nil) #expect(model.gate.isIdle) @@ -244,13 +226,13 @@ struct KeyboardModelGateTests { func appearanceExpiresPress() { let suite = ScratchSuite() defer { suite.tearDown() } - let rig = ready() + let rig = KeyboardRig() let model = rig.model let commands = rig.commands SharedStore.autoDictate = true model.micDown() model.micUp() - model.unansweredPressSentAt = Date().addingTimeInterval(-BlurtShared.commandFreshnessWindow - 1) + agePress(model) model.appeared() // Hands-free pressed afresh rather than skipping over a dead latch. #expect(commands.sent.map(\.kind) == [.press, .press]) diff --git a/App/BlurtiOS/BlurtiOSTests/ProtocolTests.swift b/App/BlurtiOS/BlurtiOSTests/ProtocolTests.swift index 10245827..57dc517c 100644 --- a/App/BlurtiOS/BlurtiOSTests/ProtocolTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/ProtocolTests.swift @@ -122,41 +122,12 @@ struct ProtocolTests { @Suite("Keyboard model: the mic, the phase and results", .serialized) @MainActor struct KeyboardModelProtocolTests { - /// A keyboard that is ready to dictate, wired to a fake field and a - /// capture of the commands it sends. - struct Rig { - let model: KeyboardModel - let proxy: FakeProxy - let commands: Commands - } - - private func ready() -> Rig { - let proxy = FakeProxy() - let model = KeyboardModel() - model.proxyOverride = proxy - model.hasFullAccess = true - let now = Date() - SharedStore.listeningUntil = now.addingTimeInterval(600) - SharedStore.appSeenAt = now - model.isListening = true - let commands = Commands() - model.transport = { commands.sent.append($0) } - return Rig(model: model, proxy: proxy, commands: commands) - } - - final class Commands { - var sent: [KeyboardCommand] = [] - } - - private func snapshot(_ state: PhaseSnapshot.State, level: Double = 0) -> PhaseSnapshot { - PhaseSnapshot(state: state, message: nil, level: level, at: Date()) - } @Test("a tap presses and latches; the next tap releases") func tapThenTap() { let suite = ScratchSuite() defer { suite.tearDown() } - let rig = ready() + let rig = KeyboardRig() let model = rig.model let commands = rig.commands model.micDown() @@ -172,7 +143,7 @@ struct KeyboardModelProtocolTests { func latchOnInFlight() { let suite = ScratchSuite() defer { suite.tearDown() } - let rig = ready() + let rig = KeyboardRig() let model = rig.model let commands = rig.commands model.apply(snapshot(.recording)) @@ -186,7 +157,7 @@ struct KeyboardModelProtocolTests { func noPressWhileProcessing() { let suite = ScratchSuite() defer { suite.tearDown() } - let rig = ready() + let rig = KeyboardRig() let model = rig.model let commands = rig.commands model.apply(snapshot(.processing)) @@ -200,7 +171,7 @@ struct KeyboardModelProtocolTests { func disappearEndsDictation() { let suite = ScratchSuite() defer { suite.tearDown() } - let rig = ready() + let rig = KeyboardRig() let model = rig.model let commands = rig.commands model.micDown() @@ -216,7 +187,7 @@ struct KeyboardModelProtocolTests { func results() { let suite = ScratchSuite() defer { suite.tearDown() } - let rig = ready() + let rig = KeyboardRig() let model = rig.model let proxy = rig.proxy proxy.before = "Hi" @@ -244,7 +215,7 @@ struct KeyboardModelProtocolTests { func termFieldIgnoresCursorMoves() { let suite = ScratchSuite() defer { suite.tearDown() } - let rig = ready() + let rig = KeyboardRig() let model = rig.model let proxy = rig.proxy proxy.before = "Hello wor" @@ -270,7 +241,7 @@ struct KeyboardModelProtocolTests { func termReplaceKeepsSpaces() { let suite = ScratchSuite() defer { suite.tearDown() } - let rig = ready() + let rig = KeyboardRig() let model = rig.model let proxy = rig.proxy proxy.before = "he said" @@ -287,7 +258,7 @@ struct KeyboardModelProtocolTests { func shiftModes() { let suite = ScratchSuite() defer { suite.tearDown() } - let rig = ready() + let rig = KeyboardRig() let model = rig.model let proxy = rig.proxy proxy.before = "hello " diff --git a/App/BlurtiOS/BlurtiOSTests/TestSuite.swift b/App/BlurtiOS/BlurtiOSTests/TestSuite.swift index 76a2bbc1..3460a107 100644 --- a/App/BlurtiOS/BlurtiOSTests/TestSuite.swift +++ b/App/BlurtiOS/BlurtiOSTests/TestSuite.swift @@ -19,3 +19,44 @@ struct ScratchSuite { SharedStore.override = nil } } + +/// A keyboard that is ready to dictate — a fake field, Full Access, the app +/// listening for the next ten minutes — with every command it sends captured +/// instead of reaching the App Group. Build it after `ScratchSuite`: the +/// listening window it opens is written to the store. +@MainActor +struct KeyboardRig { + final class Commands { + var sent: [KeyboardCommand] = [] + } + + let model: KeyboardModel + let proxy: FakeProxy + let commands: Commands + + init(proxy: FakeProxy = FakeProxy()) { + let model = KeyboardModel() + model.proxyOverride = proxy + model.hasFullAccess = true + Self.listening(true) + model.isListening = true + let commands = Commands() + model.transport = { commands.sent.append($0) } + self.model = model + self.proxy = proxy + self.commands = commands + } + + /// The app listening — an open window and a fresh heartbeat — or not. + static func listening(_ on: Bool) { + let now = Date() + SharedStore.listeningUntil = on ? now.addingTimeInterval(600) : nil + SharedStore.appSeenAt = on ? now : nil + } +} + +/// A phase as the app would publish it, now. +@MainActor +func snapshot(_ state: PhaseSnapshot.State, level: Double = 0) -> PhaseSnapshot { + PhaseSnapshot(state: state, message: nil, level: level, at: Date()) +} diff --git a/App/BlurtiOS/Shared/BlurtType.swift b/App/BlurtiOS/Shared/BlurtType.swift index fca8ed98..43b19c1e 100644 --- a/App/BlurtiOS/Shared/BlurtType.swift +++ b/App/BlurtiOS/Shared/BlurtType.swift @@ -7,15 +7,9 @@ import SwiftUI /// a face. Fixed point sizes throughout, as the system keyboard's are — no /// Dynamic Type. enum BlurtType { - enum MonoWeight { - case light - case regular - case medium - } - /// Eyebrows, CTAs, the keyboard's word labels. - nonisolated static func mono(_ size: CGFloat, weight: MonoWeight = .regular) -> Font { - .system(size: size, weight: fontWeight(weight), design: .monospaced) + nonisolated static func mono(_ size: CGFloat, weight: Font.Weight = .regular) -> Font { + .system(size: size, weight: weight, design: .monospaced) } /// The app's headlines, sentence case. @@ -25,12 +19,4 @@ enum BlurtType { nonisolated static func body(_ size: CGFloat, bold: Bool = false) -> Font { .system(size: size, weight: bold ? .bold : .regular) } - - private nonisolated static func fontWeight(_ weight: MonoWeight) -> Font.Weight { - switch weight { - case .light: .light - case .regular: .regular - case .medium: .medium - } - } } diff --git a/scripts/apple-geometry.sh b/scripts/apple-geometry.sh index 612a5f8a..59740bb4 100755 --- a/scripts/apple-geometry.sh +++ b/scripts/apple-geometry.sh @@ -18,7 +18,7 @@ REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" cd "$REPO_ROOT" # shellcheck source=scripts/ios-lib.sh source "$REPO_ROOT/scripts/ios-lib.sh" -DERIVED="${BLURT_DERIVED_DATA:-$REPO_ROOT/.build/ios-sim}" +DERIVED="$IOS_DERIVED" OUT="$REPO_ROOT/App/BlurtiOS/Design/apple-geometry.json" WORK="$REPO_ROOT/.build/design/probe" while [ $# -gt 0 ]; do diff --git a/scripts/check-invariants.sh b/scripts/check-invariants.sh index f1437522..b070fc5d 100755 --- a/scripts/check-invariants.sh +++ b/scripts/check-invariants.sh @@ -218,7 +218,7 @@ fi if [ "${1:-}" = "--self-test" ]; then failed=0 for i in "${!PATTERNS[@]}"; do - if printf '%s\n' "${PROBES[$i]}" | grep -qE "${PATTERNS[$i]}"; then + if grep -qE -- "${PATTERNS[$i]}" <<<"${PROBES[$i]}"; then echo " ok rule $i flags: ${PROBES[$i]}" else echo " FAIL rule $i does not match its own probe: ${PROBES[$i]}" >&2 @@ -239,7 +239,7 @@ if [ "${1:-}" = "--self-test" ]; then for good in "${GOOD[@]}"; do hit="" for i in "${!PATTERNS[@]}"; do - if printf '%s\n' "$good" | grep -qE "${PATTERNS[$i]}"; then + if grep -qE -- "${PATTERNS[$i]}" <<<"$good"; then hit="$i" break fi @@ -265,10 +265,10 @@ if [ "${1:-}" = "--self-test" ]; then exit 1 fi - # A here-string, not `printf | grep -q`: the table is ~30 KB, past a macOS - # pipe's 16 KB first buffer, so grep -q exiting at an early match left printf - # writing into a closed pipe — EPIPE, and under pipefail a "missing" row that - # was there all along (seen on CI as rule 3 failing at random). + # Here-strings, never `printf | grep -q`, throughout this file: grep -q + # exits at its first match, and a producer still writing gets EPIPE — + # under pipefail, a false "no match". The table (~30 KB, past a macOS pipe's + # 16 KB first buffer) did exactly that on CI: rule 3 failing at random. for i in "${!PATTERNS[@]}"; do if grep -qF -- "${TABLE_ANCHORS[$i]}" <<<"$TABLE"; then echo " ok rule $i is pinned to its $GUIDE row" diff --git a/scripts/check.sh b/scripts/check.sh index c7b0bbe0..9f877c97 100755 --- a/scripts/check.sh +++ b/scripts/check.sh @@ -267,11 +267,30 @@ check_no_external_deps() { } run_check "no-external-dependencies guard" check_no_external_deps +# Whether this run builds the iPhone app for real (scripts/ios-check.sh, near +# the end): off CI — there the ios-build job runs the same script, and running +# it here too would double the macos-26 bill — and only with an iPhone simulator +# on the runtime this Xcode's SDK builds for (an older one is refused at the +# destination). The list is read into a variable before it is searched: piped +# into `grep -q` under pipefail, an early match could leave simctl writing into +# a closed pipe and read as "no runtime". +IOS_GATES=0 +if [ "$PORTABLE" -eq 0 ] && ! is_ci; then + IOS_SDK_VERSION="$(xcrun --sdk iphonesimulator --show-sdk-version 2>/dev/null || true)" + IOS_RUNTIMES="$(xcrun simctl list runtimes available 2>/dev/null || true)" + if [ -n "$IOS_SDK_VERSION" ] && grep -q "^iOS $IOS_SDK_VERSION " <<<"$IOS_RUNTIMES"; then + IOS_GATES=1 + fi +fi + # The iPhone targets, typechecked against the Mac Catalyst frameworks — the # closest thing to an iOS SDK a Mac without Xcode has (scripts/ios-typecheck.sh -# explains). Skipped, not failed, where those frameworks are absent; CI's -# ios-build job builds and tests the real thing. -if [ -d "$(xcrun --show-sdk-path 2>/dev/null)/System/iOSSupport/System/Library/Frameworks/UIKit.framework" ]; then +# explains). Not when ios-check.sh builds them for real below: that build +# catches all this does. Skipped, not failed, where those frameworks are +# absent; CI's ios-build job builds and tests the real thing. +if [ "$IOS_GATES" -eq 1 ]; then + echo "==> ios-typecheck skipped: ios-check builds App/BlurtiOS for real below" +elif [ -d "$(xcrun --show-sdk-path 2>/dev/null)/System/iOSSupport/System/Library/Frameworks/UIKit.framework" ]; then run_check "ios-typecheck (App/BlurtiOS, Mac Catalyst stand-in)" "$REPO_ROOT/scripts/ios-typecheck.sh" else echo "==> ios-typecheck skipped: no Mac Catalyst frameworks in the selected SDK" @@ -818,20 +837,13 @@ fi # The iPhone code's gates — its tests with BlurtiOSCore's coverage gate, # `swiftlint analyze` and periphery over App/BlurtiOS (scripts/ios-check.sh) — so -# a local green covers both platforms. Off CI only: there the ios-build job runs -# the same script, and running it here too would double the macos-26 bill. It -# needs an iPhone simulator on the runtime this Xcode's SDK builds for (an older -# one is refused at the destination); without one it is skipped with a note, as -# the UI suite is, and CI stays the authority. -if [ "$PORTABLE" -eq 0 ] && ! is_ci; then - IOS_SDK_VERSION="$(xcrun --sdk iphonesimulator --show-sdk-version 2>/dev/null || true)" - if [ -n "$IOS_SDK_VERSION" ] && xcrun simctl list runtimes available 2>/dev/null \ - | grep -q "^iOS $IOS_SDK_VERSION "; then - run_check "ios-check (App/BlurtiOS tests, coverage, analyze, periphery)" "$REPO_ROOT/scripts/ios-check.sh" - else - IOS_SKIPPED=1 - echo "==> ios-check skipped: no iOS ${IOS_SDK_VERSION:-?} simulator runtime (xcodebuild -downloadPlatform iOS)" - fi +# a local green covers both platforms. When IOS_GATES (above) says no, skipped +# with a note, as the UI suite is, and CI stays the authority. +if [ "$IOS_GATES" -eq 1 ]; then + run_check "ios-check (App/BlurtiOS tests, coverage, analyze, periphery)" "$REPO_ROOT/scripts/ios-check.sh" +elif [ "$PORTABLE" -eq 0 ] && ! is_ci; then + IOS_SKIPPED=1 + echo "==> ios-check skipped: no iOS ${IOS_SDK_VERSION:-?} simulator runtime (xcodebuild -downloadPlatform iOS)" fi # The closing line, and only when there is nothing to report — otherwise the exit diff --git a/scripts/ios-check.sh b/scripts/ios-check.sh index 01f27363..cbb796c6 100755 --- a/scripts/ios-check.sh +++ b/scripts/ios-check.sh @@ -15,8 +15,8 @@ # 4. The probe's XCUITest bundle (BlurtiOSProbe), compiled: its own scheme, # run only by hand (the screenshot and keyboard-flow scripts), so nothing # else ever builds it — and it went uncompiled through a Swift 6 change. -# swift-format, `swiftlint lint`, the invariants and ios-typecheck.sh already -# cover App/BlurtiOS from check.sh, which reads every tracked Swift file. +# swift-format, `swiftlint lint` and the invariants already cover App/BlurtiOS +# from check.sh, which reads every tracked Swift file. # # CI's ios-build job runs this; check.sh runs it too on a Mac with an iPhone # simulator, so a local green means the same thing on both platforms. Like @@ -29,53 +29,56 @@ set -euo pipefail REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" cd "$REPO_ROOT" +# shellcheck source=scripts/release-lib.sh +source "$REPO_ROOT/scripts/release-lib.sh" +# shellcheck source=scripts/ios-lib.sh +source "$REPO_ROOT/scripts/ios-lib.sh" -for tool in swiftlint periphery xcodegen; do - if ! command -v "$tool" >/dev/null 2>&1; then - echo "ios-check: $tool not found — scripts/bootstrap.sh installs it" >&2 - exit 1 - fi -done +require_tools --hint='scripts/bootstrap.sh installs it' swiftlint periphery xcodegen FAILED=() BUILD_LOG="$(mktemp -t blurt-ios-build)" -trap 'rm -f "$BUILD_LOG"' EXIT +APP_LOG="$(mktemp -t blurt-ios-build-app)" +trap 'rm -f "$BUILD_LOG" "$APP_LOG"' EXIT echo "==> ios-test (BlurtiOSTests + BlurtiOSCore coverage gate)" BLURT_IOS_BUILD_LOG="$BUILD_LOG" "$REPO_ROOT/scripts/ios-test.sh" || FAILED+=("ios-test") echo "==> swiftlint analyze (unused imports, App/BlurtiOS)" if [ -s "$BUILD_LOG" ]; then - # App/BlurtiOS only. The log also compiles the engine — for iOS, where its - # `#if os(macOS)` files are inactive and SourceKit can't resolve them — and - # check.sh already analyzes the engine from the Mac build, where they're live. - # SourceKit still loads those engine files to resolve the iPhone ones and - # prints their unresolvable macOS imports to stderr — a diagnostic line, then - # the source line and a caret. They are not findings (violations go to - # stdout, and the exit status is the verdict), so each such block is dropped - # whole; any other line, swiftlint's own errors included, still shows. - swiftlint analyze --strict --quiet --compiler-log-path "$BUILD_LOG" App/BlurtiOS \ - 2> >(awk -v engine="$REPO_ROOT/Sources/BlurtEngine/" ' - /^\// || /^(Error|error|warning|Fatal)/ { skip = (index($0, engine) == 1) } - !skip { print }' >&2) || FAILED+=("swiftlint analyze") + # The iPhone modules' compile commands only. The build also compiles the + # engine — for iOS, where its `#if os(macOS)` files are inactive and + # SourceKit can't resolve them — and check.sh analyzes the engine from the + # Mac build, where they are live. + grep -v -- '-module-name BlurtEngine ' "$BUILD_LOG" >"$APP_LOG" || true + swiftlint analyze --strict --quiet --compiler-log-path "$APP_LOG" App/BlurtiOS || FAILED+=("swiftlint analyze") else echo "error: no build log to analyze — the build above did not run" >&2 FAILED+=("swiftlint analyze") fi echo "==> build-for-testing (BlurtiOSProbe)" -# The same derived data as the tests, so only the probe's own files compile. -# shellcheck source=scripts/ios-lib.sh -source "$REPO_ROOT/scripts/ios-lib.sh" -xcodebuild build-for-testing -project App/BlurtiOS/BlurtiOS.xcodeproj -scheme BlurtiOSProbe \ - -destination 'generic/platform=iOS Simulator' -derivedDataPath "${BLURT_DERIVED_DATA:-$REPO_ROOT/.build/ios-sim}" \ - "${IOS_SIM_SIGNING[@]}" -quiet || FAILED+=("build-for-testing (BlurtiOSProbe)") +# The tests' destination, flags and derived data, so the build above is +# reused and only the probe's own files compile (a generic destination would +# rebuild everything for a second architecture). +UDID="$(ios_pick_device "${BLURT_SIM_DEVICE:-iPhone 18 Pro}" | cut -f1)" +if [ -n "$UDID" ]; then + xcodebuild build-for-testing -project App/BlurtiOS/BlurtiOS.xcodeproj -scheme BlurtiOSProbe \ + -destination "platform=iOS Simulator,id=$UDID" -derivedDataPath "$IOS_DERIVED" \ + "${IOS_SIM_SIGNING[@]}" -enableCodeCoverage YES -quiet || FAILED+=("build-for-testing (BlurtiOSProbe)") +else + echo "error: no iPhone simulator to build the probe for" >&2 + FAILED+=("build-for-testing (BlurtiOSProbe)") +fi echo "==> periphery (App/BlurtiOS)" -# `--retain-public`: the engine's public API is used by the Mac app this scan -# can't see, and the engine's own findings are excluded from the report, so only -# the iPhone code's dead declarations are reported. BlurtiOSCore's API is -# `package`, not public, so it is still scanned. +# Its own build, for a device: the tests' simulator index would report the +# phone's capture path (WindowedAudioSource) as unused, since the simulator +# builds SimulatorAudioSource in its place. `--retain-public`: the engine's +# public API is used by the Mac app this scan can't see, and the engine's own +# findings are excluded from the report, so only the iPhone code's dead +# declarations are reported. BlurtiOSCore's API is `package`, not public, so +# it is still scanned. periphery scan --project App/BlurtiOS/BlurtiOS.xcodeproj --schemes BlurtiOS \ --retain-public --retain-unused-protocol-func-params \ --report-exclude 'Sources/**' --strict --quiet || FAILED+=("periphery") diff --git a/scripts/ios-keyboard-flows.sh b/scripts/ios-keyboard-flows.sh index fa96d60c..04415538 100755 --- a/scripts/ios-keyboard-flows.sh +++ b/scripts/ios-keyboard-flows.sh @@ -23,7 +23,7 @@ REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" cd "$REPO_ROOT" || exit 1 # shellcheck source=scripts/ios-lib.sh source "$REPO_ROOT/scripts/ios-lib.sh" -DERIVED="${BLURT_DERIVED_DATA:-$REPO_ROOT/.build/ios-sim}" +DERIVED="$IOS_DERIVED" FACES="light dark" VOICES="a b c" LAYOUTS="panel full slimBar" diff --git a/scripts/ios-keyboard-shot.sh b/scripts/ios-keyboard-shot.sh index 33942620..b29dad4a 100755 --- a/scripts/ios-keyboard-shot.sh +++ b/scripts/ios-keyboard-shot.sh @@ -18,7 +18,7 @@ REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" cd "$REPO_ROOT" # shellcheck source=scripts/ios-lib.sh source "$REPO_ROOT/scripts/ios-lib.sh" -DERIVED="${BLURT_DERIVED_DATA:-$REPO_ROOT/.build/ios-sim}" +DERIVED="$IOS_DERIVED" FACE=light VOICE="" LAYOUT="" diff --git a/scripts/ios-lib.sh b/scripts/ios-lib.sh index 7ea51613..726d584f 100755 --- a/scripts/ios-lib.sh +++ b/scripts/ios-lib.sh @@ -8,6 +8,12 @@ # shellcheck disable=SC2034 # used by the scripts that source this file IOS_SIM_SIGNING=(CODE_SIGN_STYLE=Manual CODE_SIGN_IDENTITY=- CODE_SIGNING_REQUIRED=NO DEVELOPMENT_TEAM=) +# The iPhone build's derived data, shared so each script's build reuses the +# last one's (ios-check.sh's probe build relies on it). Needs REPO_ROOT set by +# the sourcing script; BLURT_DERIVED_DATA moves it (CI puts it in RUNNER_TEMP). +# shellcheck disable=SC2034 # used by the scripts that source this file +IOS_DERIVED="${BLURT_DERIVED_DATA:-$REPO_ROOT/.build/ios-sim}" + # ios_pick_device NAME → prints "udidname" for the available simulator # called NAME on the newest iOS runtime, else for whichever iPhone this Mac # (or CI runner) has; prints nothing if there is none. diff --git a/scripts/ios-sim.sh b/scripts/ios-sim.sh index 728d5412..29c7359c 100755 --- a/scripts/ios-sim.sh +++ b/scripts/ios-sim.sh @@ -21,7 +21,7 @@ set -euo pipefail REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" # shellcheck source=scripts/ios-lib.sh source "$REPO_ROOT/scripts/ios-lib.sh" -DERIVED="${BLURT_DERIVED_DATA:-$REPO_ROOT/.build/ios-sim}" +DERIVED="$IOS_DERIVED" # PRODUCT_BUNDLE_IDENTIFIER in App/BlurtiOS/project.yml. BUNDLE_ID=dev.alex.blurt.ios SHOT="" diff --git a/scripts/ios-test.sh b/scripts/ios-test.sh index 1390488d..53c9ea9c 100755 --- a/scripts/ios-test.sh +++ b/scripts/ios-test.sh @@ -23,6 +23,8 @@ set -euo pipefail REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" +# shellcheck source=scripts/release-lib.sh +source "$REPO_ROOT/scripts/release-lib.sh" # shellcheck source=scripts/ios-lib.sh source "$REPO_ROOT/scripts/ios-lib.sh" @@ -33,24 +35,23 @@ source "$REPO_ROOT/scripts/ios-lib.sh" # the Mac shell is by its XCUITest suite, not by this number. Raise it as # coverage grows; never lower it to land a change. MIN_IOS_COVERAGE=88 +# Every core file counts: nothing in it needs a device. A file that ever does +# gets an exclusion here, with its reason, the way check.sh lists the engine's. IOS_CORE="App/BlurtiOS/BlurtiOSCore/" -# Core files the figure leaves out. None today; keep it that way unless a file -# genuinely cannot run without a device, as check.sh's engine list does. -IOS_COVERAGE_EXCLUDE='^$' - +# A plain run measures coverage; a sanitizer run instruments for its sanitizer +# instead. Exactly one, so the array is never empty. SANITIZER="${BLURT_IOS_SANITIZER:-}" -SANITIZE_FLAGS=() case "$SANITIZER" in - "") ;; - thread) SANITIZE_FLAGS=(-enableThreadSanitizer YES) ;; - address) SANITIZE_FLAGS=(-enableAddressSanitizer YES) ;; + "") TEST_FLAGS=(-enableCodeCoverage YES) ;; + thread) TEST_FLAGS=(-enableThreadSanitizer YES) ;; + address) TEST_FLAGS=(-enableAddressSanitizer YES) ;; *) echo "ios-test: BLURT_IOS_SANITIZER must be thread or address, not '$SANITIZER'" >&2 exit 1 ;; esac -DERIVED="${BLURT_DERIVED_DATA:-$REPO_ROOT/.build/ios-sim}${SANITIZER:+-$SANITIZER}" +DERIVED="$IOS_DERIVED${SANITIZER:+-$SANITIZER}" PICKED="$(ios_pick_device "${BLURT_SIM_DEVICE:-iPhone 18 Pro}")" if [ -z "$PICKED" ]; then @@ -65,20 +66,18 @@ ios_wait_booted "$UDID" STAMP="$(date +%Y%m%d-%H%M%S)" RESULTS="$DERIVED/BlurtiOSTests-$STAMP.xcresult" # The whole xcodebuild log, kept rather than `-quiet`ed away: ios-check.sh feeds -# its compiler invocations to `swiftlint analyze`. Only diagnostics and the -# outcome reach the terminal; the log path is printed at the end. +# its compiler invocations to `swiftlint analyze`. The terminal gets it through +# xcbeautify, as check.sh's app build does; the log path is printed at the end. BUILD_LOG="${BLURT_IOS_BUILD_LOG:-$DERIVED/BlurtiOSTests-$STAMP.log}" mkdir -p "$(dirname "$BUILD_LOG")" -COVERAGE_FLAGS=() -[ -z "$SANITIZER" ] && COVERAGE_FLAGS=(-enableCodeCoverage YES) -# The `${a[@]+...}` form: macOS bash 3.2 calls an empty array unbound under `set -u`. +pretty_xcodebuild # Serial for the reason project.yml's scheme gives (the tests share one global # App Group override); said here too so no test plan or default can undo it. xcodebuild test -project "$REPO_ROOT/App/BlurtiOS/BlurtiOS.xcodeproj" -scheme BlurtiOS \ -destination "platform=iOS Simulator,id=$UDID" -derivedDataPath "$DERIVED" \ - -resultBundlePath "$RESULTS" "${IOS_SIM_SIGNING[@]}" ${COVERAGE_FLAGS[@]+"${COVERAGE_FLAGS[@]}"} ${SANITIZE_FLAGS[@]+"${SANITIZE_FLAGS[@]}"} \ + -resultBundlePath "$RESULTS" "${IOS_SIM_SIGNING[@]}" "${TEST_FLAGS[@]}" \ -parallel-testing-enabled NO -collect-test-diagnostics never 2>&1 \ - | tee "$BUILD_LOG" | { grep -E 'error:|warning:|\*\* (BUILD|TEST) [A-Z]+ \*\*|✘' || true; } + | tee "$BUILD_LOG" | "${PRETTY[@]}" xcrun xcresulttool get test-results summary --path "$RESULTS" 2>/dev/null | python3 -c ' import json, sys d = json.load(sys.stdin) @@ -94,14 +93,14 @@ echo "==> coverage gate (>= ${MIN_IOS_COVERAGE}% BlurtiOSCore lines)" # can appear under either binary: each is counted once, at the better figure # (the tests run in the app's process; the keyboard's copy is never reached). COVERAGE="$(xcrun xccov view --report --json "$RESULTS" | python3 -c ' -import json, re, sys -root, core, exclude = sys.argv[1], sys.argv[2], re.compile(sys.argv[3]) +import json, sys +root, core = sys.argv[1], sys.argv[2] files = {} for target in json.load(sys.stdin)["targets"]: for f in target["files"]: path = f["path"] rel = path[len(root) + 1:] if path.startswith(root + "/") else path - if not rel.startswith(core) or exclude.search(rel): + if not rel.startswith(core): continue best = files.get(rel, (0, 0)) if f["coveredLines"] >= best[0]: @@ -111,7 +110,7 @@ if not files: covered = sum(c for c, _ in files.values()) total = sum(t for _, t in files.values()) print(round(100 * covered / total, 2)) -' "$REPO_ROOT" "$IOS_CORE" "$IOS_COVERAGE_EXCLUDE")" +' "$REPO_ROOT" "$IOS_CORE")" echo "BlurtiOSCore line coverage: ${COVERAGE}%" if ! awk -v c="$COVERAGE" -v min="$MIN_IOS_COVERAGE" 'BEGIN{ exit (c+0 < min+0) }'; then echo "error: coverage ${COVERAGE}% is below the ${MIN_IOS_COVERAGE}% floor" >&2

    RIA9j!Yi9;UyYX)AfD$VO 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%0AKjBRHChkL?jntGIJVdY`bHMd!j1S{n}SA0 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

    U^u(pbV_VwzbJ7{nN5bZq=~+ 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�}BI25!zMoIPAY&`a_y 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 literal 2307387 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

  • R-7Dm_s1L~? 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

    d?NE+_?k0HDhjH4NN z9Yjs;Pa$}8L~V>$A>@Ve9t`hg=<|&nc!;5b_docsidr6?Mi^{l&M^3d8u?;;Muq$^ zSmoh7YVVBC)7KRE0=0LhCNb@(u`>ocf{P5iOhQ*MwF_;J@l^~DfZ&Z1HSOCBh9#KV z>|ICr7DhKPwO79hRwWGTgz-HUJc+;$8TuGvKA1MEFqjZ@0o!;CCV6lR4u;LRP({sC zyJP%DO>LQbQY&U^jB$^_A2GF1&4;(Q@-v8a2!&v{HwW`PY60>PVZy+ZB)GfBa0%Xz znlMwVhR5*kMUDDnMy*0WW3W+Xpy!_P`f zhNnnO5<|^U*CQsC#Q`d2Jf<%}s=y;#jK<2Q6`=?j<);9N@?!!Xh8!JYU`oJDM93Ob ztG}VLy=7~77L1rI`HjL%#7x3;Fs5K?K9?pNL;+(X z<{EK5;9`9)w})5pUHDkI7~jL+hot`>ZaSn3s z>m2L+oAXBJ9OnnlrkZ@sIyHY2k=RxY6IY2h#jko7cuE?rpReDmzoNgZe`{b3u7;+D z-wbOFk}=4bZv4%7%=o~?!KI0dzsn$(RF{=52V7pb2DIvq z8(257?&i8Vb???=>$RyjrrykYd+HU{?@&LZ{<-?^>VIj#HR#bGy20262O6Af@MnX! z4f%$S4Qn-Q*)X=@q=w5I9&K3MsCuJrjUpSZX!NbIf8!mE-!=(q^2MW{$2yN3kAFPM zJYzgZcs}!d;rYrd%4@Z^+Pk6mc<*OT9hycrec;3UO!qN06PkH7o7QYov$M^LeRaOx zzWsbNd}sUaYR)vT(Y$f<4$X%)&uqT9`R?YIn-}}F_Z#Xr!Ee3a1;1A<*cNqKv}`fF z#kdx^E$+4W)Y87CdrR+@-COo;Ik;tb%h;BQEhn{{({fqMH7z%_+|hDh%OfpMwJd7+ z*hyMWoQ2%8AS^mrXH~R1JKj44T|GfW=R!plZtva*{X*IOfrdB&! z<+M7}s<3s7)~8#4Yx8rP`2kJ=eFL_&ZPWITwqM&VX?MK6d;13+qB@jyj1RO5tQx2f z^ayMl7#lc0a8sbvN!5w(RIO7;r?Z{@>hz@3r=W&GErMnREekpnbR+0y(Cwf{L4`p@ zL2rV}gN5K`!C}EOf>#C~555%qcksK;s?PO0cj!E*^YG3iIwy6W(s@be^_}l_e%Zyp zOK_LSF5|n*@3NxH#xDE2oau7E%a<-v7ju{LF5kLN>H4Bu|8DQP$96x{{acS7J(l+{ z_hfsz_w?==)pK6Y4LzUrQulK072IoNuf-vnknoUkA?tcq?>)2k$v(JGqdxQcyz6V% zw{_pBz8Crl{qp-W{Tub~+kbrjb^Xuve=|TgAY{O-0gDH09I$J^$pO;OHGV$u^P_>k z4XQq<{h)|J8wTYMDj94wxaQ!-gS!kKJNVIH^N^}T+=e_HYBMx8JTUTIRI?Z<);`u4 z>lxcFwpVOuYX>JPC32NCb*8=&5vQQS-yGwQ~Y3(S$N&&uZJ0M(k z$tjQ;6qX-SfX|WwTuKVM>d+K|ox*v|Zn}$FD9s4P#CD@a%U;k-0)F%Yhu{^AM&JlZ zpS$UV0NEM0Qfmn;1V>gD#6r3!jzR!s56RK8i$=>e%EbUXU;{`~QHPR>x@an-R(~%9 zzQ__yU2-&ncB!a?Hk^{1x|C>SG=7gp#)@cUv_#7vCIrZhD{Y9=ZPf|^P&O=fajXy^ z^Y{cbXW-2)OAfU7P=Fnng}WTgehevnXLGt0IhMv4lZ| zN?zIpmN3X-34>ZJVUVRFOkEkqRED9figYNTA|0};46}kTTlniQI;=EZ6z-btJJ#of z!uDc+c}Gga^2y^b>Jc2#epLr@{l!~<$tm+eug|zGMo%9DClrImY~|iLlkMdhG{sZ- zXohCJPriPh(MlBVoWH6eJIXJ4ib4@B`aNMBh}S>)AB9K6>x+85NNRpnL*%=E*SqnH zS|`9k;~rNegXD6HoBq{-(}*s>jctR*$dO9MG6>QCZRdCcZuYEU4&F->ly z+qnVGe)RRZIc#*&sOUjk#VHeJj&~jfdp?6uD)s%`w(_vGzj!J4ajpXybn)Ru;W2#P znC>EcQaSMTzP(s^gm-|0{fn~*!bZ56Lk4`FrW5|m87~TVbEb1w;h@bR+|J3PUQ$hj z7&zj%nG+_O2A5BRf(momi?fO!z1Uks`V?VulT<%=!BCyAY$&=d!qRfp{s zJc#R2-b~kk>jc~IUPQm^$D(|=LD79gxww<5A`~YSnygxL!ri>9n%U*)N-jD2GHFKR z-+h8(u+NKr<#Nh5^yOy3hWxr%9@vL7%{Z+k_3n5|O{B&Fb)wuITrhfTH8qO%3Klrq~!DTIU?CpK3!)CKlK+)N6vrF7%R>f zr-&r8Jfk8GDwGR}sjO1!Z0@sPjO6~|9+X1QsNv(@z{g2d%!_I80~q)ZN>fQQSgeFk zBzqJ`dY3QO6>EhrJ|YWT+=uUePpO21XWDRAynY{PT2wj%@tS;ETslWTHGP zN=*YlXP1els^!_VOcO1WP7Gr)i76tziyGQq$5$^D$6duusunlBC- zv!3%~Th6}N>#ehJ5)mi!ILLnjK>^3JpoGjUr3e^;hX|6ZIT~O>&{c;J6;w{<%e1~M zNPjc{(q{xfdN`3#?UMO=QTCiNhJ?q+!rCL6^bt*Z5|U0a`=oQg;bo!%7TaP>>KaqJx zOCjXQX^|H3iIl_VzJrlT1am8$rKYmW9BWJJh_@*t*URpd+$sAnFJzb0Y@?XXVKS>s zW!mCc)D9-kjN-cgo20GGH&A1jCIaWnDN-%4X;;?%Q|CU@CAiAJWE77#FRV zG!0nWY&zp;DWoVxTqBabFrwwsvSIQ-I2IPxq{(J8%^(SYm(s{rWe2QVx^X1;KgR+$WB205nLtIUjB zaC8e%FJMgENEi2t1Wwo?iDsPnbUHWdjp;=ie(>plXe&G6aQ6WSxIijtO%c%2m51px z-kpTVX7tWx@&0SKU!^K7oTQJ>KEp(w1y?K%sitehW>%WRwPLdIjW8G{5veN* zEB!?w?y&e{3VJ1=BpONz&V%oYnRi&s02K+!eyWnlKME-`_qR<=i%L!pE@kjWRQ`;Mq_40M6zBXFE8Mit8PB0DCbC zdv_i~<~iiZ94gAFB!c^dBfg-ykviqO>VcZpl(42a!Zv*~DUGg^q)*3hXizBcP(x{OI$Bn}pSvn@Jya z!s4~!_AQwS>-AE+RH6|!W$m7N@VFB>;V7Fe0u+Tlv6YZ=)|JFAT&*+<%Hi9J}Y*paFpe@pfTX&VeXp|sRgsDnXz^T_Z{ z!9&737^D`kZlsc0ugR#_#5Ijxr|ks!5#UH_k#<^QCzoIkCD<9HcElAHI=0L-P)Gcr zh_FDV2tU@=RQjfnGX-wf-Of7>wia$q->s{ph!RO8)yL}}jXjfey7#?%)uVSut_fdc zCG8|vbS*{M>`HI@oP%YUYydsnRGs9+aL?(QX$c``=&tN%^IaND714^69lxl%h`Hv$ zFd9oCmM7D8i6CvsUm+Bmdby{fj<9|GYygzTDYc);DV(R zT`h6AMVtR0B}Pz%o`%B2xGO?C6IitAl$dJvR`QX$+)kPR=Y4u!`h;K=*>7qfM|FcM z&H?V4v%hn$l1ghkz0m79NqGXAq7D3_8A>QB=9Vn-KaSJgQcGxt$V!r`$r#9VzmBLzG1$Gm%R+LY*q8jE$Ip6g8mUCqO_Qll51U}IPJ#S79%ZyN5Rg-YmV`(o)N*mF!MJ1QHl2p@-+ZR^o*d0wo=G*IQbpc?Rs~m>tniVzm+xvJQr)L+>gV2R z_+shN0`e2A{~buy|KQ4arzvq5uTMxyjSK%_2flsn=F^)DC7bdd5j!UfxAGqRV(FHP zk1qT{>-`2TF{X`}tA4?4*eQZ--skeemIgV%T`UbfNG9D3Edwc|C`jL>%;?PVzpoq( zQYJ5eYDWbDigpB|riD1`T`N#n;2h(UFxsSYBylrE=n!GI6kvWPwK6@^fR!1E1^cbb zqI@ZzP9``u5rxBG)|F1px=x6sn9iQe0P(WrxP#u^4ne*%KGPhd`;Rr-#~+N{phTH#-+#t_oTez|YevDj(!BD; zbGh#|m?_@{v$$D>rrCwWM>L&qOjJBq;E)CUxN?OiyFmA`M8d43k!f^JlID`PuFxFU zn3QSFjCr=Eu_>$2tOZ?*mPxnMWGx&b*vPx--JtI$a{W1n8>M7=F>Eatkq53|s@DQ` zh7BPc1fwPDBxqcLBe;XoH;A7A@h55gZct z$f8VU{g=zlb2!pOn*1Y^cOFA|DSA;kl|ZS+;MmE zgB{?Wp0H=y3u>aNnlwrG|Nb^%&%DadgKrx%531WUuOXLt-~ZV+v?dGwhfnRZP|yvc zd+e~asQGKcJtB^;8@~~T1c0T&Tu=x?-q#C_NsAb*-;)xVJ=j?o8PKG6hbB`Dui0bs z)@XcbCQw+kWtOiq?L_k}5<@UIL_Q0ki>-B>-9vqY7eDC7r4~q?r z*nZQ}lSViXO~@%V%+U&~0!TV5d6R*<-Rr}>W*elR*jIBl@80VyHI&xqLdJv+i%$OI zh+Y^KaPi=#%fIQ@&eqswzHIY1`S21fMI3GxH+V~Smk9?+0hp7t>OH()oPn&ZrxjAm z1K(C(yz7r2=e4V25DvPBwDr-0 z-48xRkIFKKh_^)Q`e?dXplT z)ZWxmR|n2~{N8>Jgl{`4xtKpU5;I?t4^K${wCps8-T#m~Z(*jqF(rZZbozOXkS{rg zrLIU_ma?>l#E#jVxoOyIR#*cw zHeaz~zbkB&9#KBS#r3Om~p8>xmCJ}=(yttsa< zg#V=#c1TanCmM;7Ak%F{mFXzSbm1aJIKHJ`0{hSr+Hz=OrpK5A3Ss^Dxp|iL798%M&;im7da~K$e|;5658BOP~Qt zi8siyFK^A=U1S+nH_fGoyu(rXO6O zWShdj{@Gyo|50IOnaThQ+n zNnU1=L#E?n;bJChz9_uRQm%4@SBSVu)ga@YEXescf~+sIXkO)Vry_Sz7Wv0?NmtT? zgB(=vsU=0w+GwT+G*gkB3ABFTsqo`V%GA3oaum$%PQKUlW`B0qNcbbcTH!rD-Zlg&S>|6jso^?@?0r}?FU5J z69+g0{Y!%1{PS+$>;W6){I-wHIX`3|?N5tOKaw;$OuvCr6B1m}h9obr3$e ziUD#R^F?jKL~54YxH)T^CBAqpe*|guT5Mo`1(neY1!@*8e|4XNF%{ok3g7(^zFTMV zlUDnKVpb$|^@m#sH~{_ehT$U|fSP71*KjGzwkgKhr0acJ7o2;7-q_*h>5|ho>1?}{ z1I)v0%cD1JH*;XN70CB$=jgrKMYv@ksphdzpB7SluM^Cj;T+qYlNme>&7r2^;{!QO z+rbXL-wu{dX{`?CR~vH%`)RY zRpFC5UFrP5;nXwlmqh!5XkWrvPghVw21h1F!6xtE!LcJ(hdPIigcq&`;m%R5aLwC1 z<0UKXB<0$@Yj^J3yKH2rUNXM`@4j_A_FB9zO`P`SuoE5iw%NNy5Cn&F;35`m{11bG z*e!x~4`Ij2!+cKSr1qI2gq46~dR*!z%YcK#Knxt{2(A*&VF$F-kYy=4;UK&dxC3Pz z{Lfn@;V8UTqV>S~NQ*Uvri*px>xmEZxQPQYMS5a=Yq#j|^yAgi+!Emtu<{OydDK)4 zE%*EJ*h30=NOUs0`KH#;Tgp3tw(uBAeoLSi-axke%G%8;t^8;p5Kfq&_C?&&kHJ@i zVSVZ;uTL9#l778Jk~B~!thWQ!bL}Aadb`T(%0nx74MVvHg{>HLf}Bh@aUDlq|H+*; z-*p3}iz)`iuwal=^3w1IR)+j3;%xI}8VMR1#JwSA)1?q#45a=X$y)c{mwf+y>1Qx^ z{$HNg?sh>b6uQ)Ox3?&K4L84%St>JK^ydyxrhva$!?;+5KTrz}mi|VL z&M&10p&_P%G7+?cy5RvmB8Jc^6nYOTL=N?Vmft-wU&Y+1g^pWC~^s}*t43C~`%w44ga12^< z>Gty-TPBT#gU~V3Bsd72xbc@QJDfu?RHZhEFLVKJwloyNJ|!((EZQ z7J)GDnyEX!chj*AhC!PTjXv$1f8pB4C5Faq|EcM5QO*P7^GXaPYb8sXhkS7B7dfW? z82z!t@GX6v-FnFHEE}JfR38oV3Uq_V{0VoTXyfgpN7uEJ;D2wM+;Ol0mO&4ap?fyx zkNpRn_ihaJnPY&j$h7Pg_LK@&h*lJ~KZL7~3$T~FLh5_cJ%K*a+*v2wCSW;o#l2TM zc_&c0!+>0GAQ#zC@2mQPXvtxabCl8?ZFD(IF}f3@38k0CH8{7_uf&lQdBIcpq|FAv5SJDh}dhCSP&Ey8=zvxUSia!u|=IF zb0*(!_72pP_j~`}|MO(_*_mg`KGVzd8_}|v_9OM{7-qK=ET?A&j0vqfr@@>;mfa5& zaQfvCFDG*j$-NGB5%CpikV6{~uihf{q9yB*lCg3zBwlQ>C^d=igM}&`!UA6`vw#N3> z7H$vbv0|-LOWofXS+Zy&`kmG#Uc4`ERJNgCQ7e#Ma%CiMwqhC6(r6h!RhcT1oLgdd z#}sCt4Eu?&kD97%#JVoDFW_q@NoH$D`_QWHbgmm2={v@~1KgqD4x6gDw4}7rHoWX3 z1jB5mhiW#IgmxZwYIm|3m(kILdHfL`$HL<{77bf?yZ3qsreC42OTS?4&OVNm!|3rK z7wSya0Xz7|+u>mXrzJS3YL!z#TPYlEy0xcVFTF5Y4d~BHVH@=P9xvYDy z2ks@|+k!tvSxVEX!2vBq9PAjuLjOEsHjw=CNh7R7Vc3KulQIt`G4E$Nbt#5LCFoHD z{A97jZnxu%!%l9%=%ItKqyz;pE4VO@JjZ?9Nw-OE=0yWnv|KVEg>EVYhu;uE6&3*|5g;Y+JqJ+&|!w&a#y;5_Mi&{ zg7tAf(vlRREd}TTo1I!)Jk!}C$KF*CZz<#fMp<&VxIr`(Eh)}K}lqmj$=NvX@sD-#%M z$Sh}qdfMS>dq94YW4;$3(4v1!DmzP=^maB$p25OGBe9hu#qw+H4sHfr$o%wSN!ad6 zf>vQ4H)a*K_G63+unG|LV5-aiNxQlMwYH4Gl3}mM)}*%D1B^)Bfbb!MySnOZh8=Y_ zlXFe}v@@8oc4wWnWCYOfawU^ea=<_aL8J!!+{k?Y#Cy`aQ+=UxySh;3#E3D&WN;RGxU zlWbZ9gAN8IVOh86pU@;M9Tp+Nb+erjwiSP6$IdO81;`Jye_zFt6<+MQn>B2j~OJ;FR6W!|6L9yF(h8HCP(Evox+`f?lRcBeMn* z^fE|eo4+RLWlS14j(1f#_Wr0V><0%K&xsF-|MRepD}2T~G6ScO_C?`9(VaV_v`q~w z;s`aK#+=HzRjV;r9;&6agH>2GxQuy{HOUsAaVL%)J5BLrVZTSRUFLslSdzIgYyJLq1@Y&`!Mp`!KAl ztq5&>%?K!n_12u5%meJZg*f3Lp4h9@HJICovu*($0MQzcce?KN66=kK_Rl}Jvu%y` zb`Din{dJantB!HRchQM9a)ubM8!bt8DrzIVRzm&R6GNK$Qa6KT2Y1~S6;c$;X-Np~ zYNK2ghCA_^rJA(_^qH~SmXK5{zPAk;?$g~5|H%ztu~o8j*_mFX;!WarxzQyIQP+|; za_X-5P3v$7HR$Smy{<&8Hx|5&4Xm+mdTvm&OHZHw2(|KOXne#{WtRO8gS zUOLE)8gU(pjot8t!tllu!w)4l;=NDMF&KDw#z`yEdHIvs@N#`p( z`RXpIe-|@g@>+g=`O>d18eS?}u3@9nWiB^*X1nUvec0Y($9E(hKC)v#r_S()lhMDZ z^&*J=7d{CmI*zi#3`em(S+_E#zx`?dN3=AlOX@trewo{ok$wqVZDv6 zrxS!ZYv#tU^C6WFy?$eL#JIH|u;XO74Lh~th407DA2-&Ae$%T&2`k&X^tiy2`%+=HsR{Yk;X&(ER2x2_(3r(J%yUS`JeH0|Pvup&&h5IAl(@3cor8~$ z6Um2sQQ;;=)&+}KrGAsFgg5-O^u&R4zF8^#TQ=`Aq*@=_=t=0|TbFH1+xSGP;ZJe$ z_9+>2mkfOBg@LWkA3<)kV3xXE26tdyq|PA)^Lq>I;YYDUe#e` zbSO@wt4*l8k!Cw;3Z=$W1$q z>Ob7J4d+70iD!<2hE9%>Z)XT8u?Lbb`QA-!Q@d7|wzcZ?Nz1S^bQ7QtJ*q~mzQp$1 zuf$5e`t}w5ie)6(`k0h_>U9DD6`m+@JXR3yt6k*U&4XHm+2$Kb{kgYq-0{uaGq~3Z z+dBi{CInofUcR)7AN8f9%dcv*xr?pq=F<(y7rsP!{e~1GmMX95*S2vEgKT+TzvG$f zH;R5fcdQDbM23inkMIs$ImM$|9lVJl{dk>f) zWl34nua2?WhmX5WhW+f7OmtP=k%e!oAeC>DNh_JUJ^mJ)RUh9cZudKw)vPf5wgWa}?p2T%&u5>JfF->Ngvho*(Ky-dIG zrAmq7v=FsCEJ41$d2Y|y&9=ElT7Q1cIyHP-1?@gG#a6^Xxwxy1h?g&^@*aK1=%c9o&rMyQb%fd#dFFoF!6K*3h5m z{{;Q%1JIw48V%mU8R!l`To66NwEKxrqKIwH;*2;Yl141bsad3smYnZNM0L^fGMM>> z#{SWylcbXNIX|8!0{a>YK%lb<^z%!L!$M<31XAt<(Wf0bLCUaz^jR%0zt+G9}gW-cL+ctF09+zt>~YY3MP|#OhrLGAzM=1p0~d zN%{IX9V`9-;cBs*C)}l$S(-DVnWc{ZMzs7HuwNuCkO4ft$x|sNlI{>ZY3~%f7ul9= z*$qn%(oa6#h`~u%vL|8Ie;X_iy%%Xtrqij}zh+x|C@C5HcI%0J}BW1-ms(=pBr7xR6DD)sRJsiD+?7mRHEKQ;6tz7E8zi zvL2GohNN2n0|Fdoa`Y3yk`_*}0<m-n#1|7&)d6z5 z4n3>dsbIp&LK+0w;%_KC#UQ`#4Ui@$1db*;7TPQ|5n@vzHHZb}_N#+@V(QEH;)_&$ zMTLwdzH$j=-a%5-Rc@^e^@0RulO`xBV0b}_CTi}G-ZkZ|OM358Ee<9**Z+?-TcTg>Hl4#%k21Rx(iYz!1)e^2U zTg+Kz5rnI}vOogCGLHD7ycR=wg`2ai=7m2>9rBm5noSJnUx{QBX#shEUR)cBsvk-x zfM~MwfM|AWKs5P97A=J(yCKS}Y9;OEQpkQ+!FzGOLpIb0M4TtxFV|a=K0M1eBYj8a zzEQ+SvAk-p^qHqDo~ull9BQ*X8QEipVcVLhkt4@Ojujn>QAu;M zuM7IbE7L2A(~*MfWpOranyB(fgKElaq&A($I;6j9((;_RYweS28Z83p zq!joQ6m>*-MQzQR5u|W8$x&N7vqt4l0xskyku+6@f081V4?z@pY08z7#9YZK3zeUb z04u^ZRLO0F#LPfqX0XJ}KO(C0A!_w|#QQyqcLoa8yog`%IT}*ZWl~@L&4rz2vm~7p zt(F6Wv6!C2z@4m?%X36E8#$w9v#e2Purf0u;vsy$KM!r1rs@kVfvJbG;RVP>@EtZn zBqeTReJD`bIzwTlNu7a&&&W^sLL_{lE8#QH!p)2L?Ng+&>m&_n&q+=?X0sgJH8wFg z#%kG@q5xd(D@n9|N7td z*#od)_#*PPGW}HWIAR4R)m}8nfa%$eK|~)`lT+hK)k8RP7vC34c&>C3vszak02oOd zoB<`7vx#D4sU5MULTv1^ zLVMTmPuwg{9yHDt^_^ge^y@Whud>3iR<@+1A()hS7K{e))zsjO!UiUkGBau>S%4%Z zWLb71J^PTHolS6bNG*kGx|3DYFjh@>x~gdys_9M*{|)|ToxBgZLZ+lEl0-UYS`OMt z1+|Wx7gfC_$AhzcGmmf2+&?NIbeRn&83E3>ZpVHld^7_s1OHAj5@=~7Y;3b8$6y(2 zUm^B#m}Do65~+-3VtcbpEJ@qXA7b>;UZlGb+w|S#r^G|RaVPWilOf|s4UDRe;wyeS z2e~n^+L>7G5bOS5Ay#`wA}YHe0_YFi6t~S#7%G$P6R(i!f^(MDY56jZamsYVW^q!U zOapp_?^Q-RLgc()(osKGr@c~G;H=_B;(Qk*s^xTzqd%TFbdo`#<%?(fIm_Wdh^H>Z z69cHVriS`?;>p+_zMhHaaC{=fvwc4x4mI%{4up6{0gP#c%`z#_4~x7P#W0qFQPXDP zQ%=xs1_t&wn}PksZ}Z*07BGp3#)hrpja^fAyyaA6-0U>6nd-}yRu?lN*e}P4#l$^iDx+y zk6L~~fsI;Wx_mBL0UqQ;+u?=laXfKj%nb3E(iKRMOFuz^JQO$w9Zr6zq>@5JNjp|JQ zdxci;>Yz``Yps4ADBifBsAIGa>P0;zS~;*oG5as|-g0P>T6wyhb1>-`8rhH- zRQ$j*N`nFYdIqlMn&874_+{nX0D0vO!5o2PvO}7OY>McDn?5uBA`t~eTOn`M+4ksoq zTeoh9&(VH+nziULu<2CmWy99R@iFUt*RP&DX3WIND1nEALc8rUY+Vx-9zHf|Bnnp$ zb#pYx5H~s!WXs|1)1bNGlw*kdo+~b#S5n8=zC%xcJ2jZpIy4CVf_+2GnswWJQu^(0{7L>D4shll%RHxS zCI@IaZG{gcB`+tP$vGUrlHf{Luudt6CCl3Go6kT-M+=ANeT80eB*`L((&^dS@+Lcg71;pIDUA% z85!2uXbHVHGbm(yAmAKV-3vTRb&Wb1)nlZZeB0=_;}|5=G^#-WMakZC;?CWm^rlUM zI##c-r^5vsLZODm^6?HVkeNY1v7ciKJVAA>IvGj&aXEC-mK2+%*S$kA+qP_q3GQVD zf6qywBd`XxNb#P`h6xrY940wJZAYLVS&+hQmPTGU+R)t=f>X!@40(NZon#&?6rr zRlGsHuwr&2`uJW9B~tpgY8yBrXryiA1fgTl$i6LnCP1f#h_vqkk@imovO#N+OkM=I z#RE`eCf*9^oFb|#BS_Z>o<#r2b+!YPAx$kNKcU619>aMEUsC(Ph@WWHHp@sup@LyK zZ9uD>4y{6J^#ioF&$Uhh#$%+#O;Y|Aze2sNSMRCQGEk>L9(B>Jm*fXlbkOsc)u*J{qv}&YC{U0l&Kh{h$)LU{w^vXml zvD~Na4Lw7K_Oj8X#^9-wLaoipoHuM)J~`M%ml=C)ADWDr-+gK^gxgmp*hr{xU&Nk1 zE35}stljgYk68-NQra#f0AKn7VnYj|H znA=6BJFAkW9~#r9RiQU+?l1Ni$!OxojAA&LMXbyy3ful-iL?AowT)hlDU~ja~K4NGihQ6IFQBOU}2P*6cGuE_eD}rPonQC zEvO>k=qtJDO}tubXql}HE<3Y&W&z+87_S8Y1>>=F0rf$gH~G?d(HnG@lh#5U$yi?A zRa!cOgID6klkv=UpBf-D6i(trE!69bk+GOlRe%1jI#5r>tAoQ8_LhdXG_B{O=Q(;Vv6WTcA`kqF=#F-Fo%x02l$t2aR5WwpPntp4aKt3{k;wJ2@wLtA9fqFPziJUI)if23IDE=hY%(r~nPz;7t9xy9x6 z%K_U>3f`sdP+*6lz%ECD#f-2;*|Ubt%O{7}Xfz7!FcjE!cWFUG_*7P4M;iBy`+*hM z==dM@`IxJq0%+w`RXQqFe#&j~fG17g=+(YeP+FVhHX%(O(Cw_W`ai%63TvFJur{Gh z{aIlp`+wnyNdC}cOtT-zIDb^Y3D`7Nc+*(nO=E>O4TYB|A9Ff2T+v>gS)Dq{>6n+- zsUP#2*wm^lvk%MI7-2}mgMqPZK(-HYW;QeS|pIcqh8zopRAGnOf-N!HZ{M_Mm)iu_4%}cd>*}N3g zqV3fD0lJC~J296sSl)4wx%Fh=-(N@`+NM?SAx&(wu)*JrRDlMt{lcLkty=UN1UsCW zSUOHkh~SUBBgQPf+Ld&WquK@y>@d|to*Pe0{UIo(gXyJV0ugFlp?tLIdds>->J?eO zBrWMfOa4-lSR$=;v#uM7A^O(!)kH8k3ZIdGPCj#fwUs_GHe1y@~H9g<6=eg!W=)eg*I{S2q>%L{6wR!WDp3pBNf?TW3xm&l+oWFJZbhBEu z+BUCgGcOspZd`812(MEwU!Hr<4n?M@J4qYB!Ph-Tg-zCoMFI&i9=2~Ew5pBiS9~4c z>IyZjG~H}o$4EWwwdVvZT~K zmt!Oam*2s?06q>g$&pib|B$iFO8Xd_tP9D)i40TiF)(4Rh`DrcCjfI&a$i zsn&0SnL)qVO)RBJGv9TqzF!avKeH!Inm5UpdRNbQ8EhkA=V&BD%3i*F#r)`K9};<% zh8bRLyL}qF66Sf2$QN1XGfCSgUc~cN7}EiQ)-mZWFP^t}?qVw`l10BUj5{xorr6t3 zX)nW!^|RK*uM@{D9JOSWtzs)87}hlts4vvd-;xT3`P1jknC{cK&0%rgW3?PsA4uO) zFUf@0z|;yNKg-nWk9#$&Xgu}eCHxUvDcbms(&!FOk>4=l*k~c5klr?ys-Abr7^F#h zHR3t;-^h^tOH!s8Ez^qN z@WyUh>ZQ>#5@%q`WYRL{NtrBaGLmlOF6)N+SG#xq$u~biE#8apFH5~5OIb@^aVDinW02_tYDIt#xT9U%lGHYWq2as}7}W%{*|swf`#6JBAEaNp(oDNe;c1&TvS z=DUvYl=-eBs38nF{AL;G!N?_0H1{c`0p>;H6S z@21RMwpP3LjyU7{Q|7g2&strpYNOp~A9-lR*wI6L2ZZfON!h$7X;(t{&^5MIVFIb| zFAp8NerJSj;-=M`g`H~>5_kG0Z3*hxGc;&`4X7GCL#s+*U=Wir${g56*xSF`x=z6J zs1RRgXFFS`YT5nwoDzb5JUs4LK9 z0z{|=y9VBiSvP-Sto5>S&ZL?1X7~=Bx_S$cJnlSoY%GuB{Zt)G49JKD>SL_uKlP@O zP|x=@&vj$@r6f&(isC69dhD)rq5~G!{i~CSXh0t}Sc%&?D*2E~7hXPne6bYHmRD+3yaCo=o-hWZ<)Odf zrNqS@?1@@FMu%-jU|- z^<*$)oSR6Re@J|voA~IN<5Iat9}+RK==dbJXIi8 z#Ykq7S9At>A*h9)plmj~tJaU;7piDFVzK?7O)yPHtbV2*l7 z((jQ954{edOl>0Ovd__pl~WxuwtovYrCq+aT^`zeR~=tkyhc$R3NP|o31YjKwe#FT z+rCo?4}S9@i)ke&Qq8kMy{pIvNv_xa)Z-^7Pv+b>)xKh-cI~jAuPu(Q$yzr1zHTa0MRucmUV)-kL9CkFurpk0| z@Ej-An2F`C^%t_UM`dTF6F%GWK8=)7>&cdHxjXyLT)7f>x<;*jZ5u$3A+5pwHn*(w zE4oj%m;%(3YM5}-=s4*J6D(r`$XAGWPu#G+{U!_v8Z>d&{sXIb{9q%e9G>!k5fj5F z*b*mJVA}=__O-c|v}tu>oGmvQIsI23<@$g!Iag|D`N6^#lPx9{iJp*}?-yT}Pb< z#@T3i-czKDY_QZR>ZRxG>X$)(U%qGea$ z!L6IOueMpv2PWbzewi5csPj1W&--2*-wl34O1@nD97C@?>NHYN-f=SS#`jN5Wer_s zbe#ybxB{f2VA=l5q2!~td~SBUL2)BWlSUQVZ0h$zZ>uG#X5X%DD)`U>FY1%8t{hF= z2ZVs|eK<+=1(Yl3HT6$<|Hk0neTENiJHi&ad+g3VKFQm*?XymG?3FD^wY#Tfrf=JO z7)lh_nL#8Y#sp93L+E+5 zW^M1~4!Y-c=|%mQWXOy9FDwtqQQDSiVtU-Y^gJUhsn13LsAeSWJe27}xH@~QZnkz> zBh=a$mTj3k1j4JWkzwsYmTbWm|6TY1LkLl#otyfs@X_MzKoQes`iJY_K!rAL5_~?@tuaH_-uAbD76iE%7J}*u} zNGQ&x6r(k0b)2&+Mnh=`)b4VZ^y{+VX+oMmCuS_S_&$X=ngeMFi;BLsg*o!w zW9MJ3!~%WWnIro5^X)eH%=72FPapYl%YfF4Y*!4grgYA(?pwK$KL&`_Oa6~A4%I0a zQ+_#oH|=@~2D+n^p%>))TZ{+4g{EltpM-5o)+O%p**AQ{Km)$ z1R8USTrY0KD84V54HX7@9mrOtbAZ0eld@MynQLr0vb22r{P{b#o1L#&qj|HMHO@7= zW6N8L(vBTTN!y1F7%+S|#xQCVvfK+}41W~eG;$W(npuiw$zv7Zfu2NZHe{7I ztZ^ra1~N(Bq2B)PR^$&i))$gHYI454Y8`jLvp`77rwUFbtfW6{zbBMv+%o>qkMjlBDZ z!|^A4PaGLDXpaqN{ZeqG4^@0Ws(2Kt`2M^qevMV}{ix#Qe|K|zb9veI$>p)YIg;FA z2$m4qJ@QWNbyz8Eh`4MeJ5u=~_kXURvqqq{}FeqHwR4>n2FtLl$e8GEHz4>n~SUt}gq#;V2y@ zTiXA#8~BSTv4&wvl#rW_Mo1DZi;xyS5Uz*$_vkXs@-sb#9Od=MqgNRw6(;bs= z;h5n!r^{QX%RsnbU~gtFEw2cm z`4KC>KQwBCJv!;W;+0!*y%*V(7=EzN(d~&*M~5F+y(j$WBsALPHjPYPbTnw=l9T}( zR~`-8v+wA@O>rAX{@ms0s0~=IV*l_6SOoO$G@!L!G{!X+5)H7L2CHm_ARA!kIDmO@ zoCv6SQr3IXDq)Y|E>kEdiu+tiwfXY4)d?FmOk5Xi>jNwW4p85KiSOpUz60~bu;gP7 zCG?7BFGcZkEU~7>1>|r)(##vSKo0kNK7zS3yRt6A>$3N0t^yq=HhVhlYh z3}f$LETA#EBMA<}WqHL=VYK1RPI;9fX8E)z8*bY1yafaVBIP`8E+gf|7zE8Ti$$?`%fB*9W5z9$7C6E24nDmAaN;@b!ZT9A z>HtKRU zTS?r9f~Vbwv_uQU4e4SIl@+H0J}=KflK>)y&jMV2mf6|cQ7!yWdD&MxdHK(H`8;0! zW4Qmu%lR#gVwcsDiVD8dnQUPBGr73LDOh+rSLRF8QPDAs&X!5LF0`F-wdnj=aJdav zyzy!gHOc8h<7k9@VAJ}YTgR;Gz05Xd;naoEKFgLbUS(yMGC(M?%VtboWIJH6Ok-ZT z-7`lf^!M!-7Ct<9-K1^b*>+D`K5w#*-98f&!vJvDxrk{?V`tcU8(eV(E#5YIzb~#t zz`p>}VF~Vp(8!hBfvaFCu3bbBJzPjJv;>-aJ418YOt9ElOq|1Wx_o%cmSh{@`m#F} zxW=f%#&MIQ#)R8ruYA7i#Co~s&;mQYAhwU`8 ziM%^#u#v=ivj-Ztxv`UCqvFS9c8!@AyC6PdZN%ADagnQ{VkgHYt|1ZcNyHj2a$t32 zT-2JF)f401#w`XN2Wlan(|{og@`qJPt8T2`xO&;Dgf*4`V{!iU?|zSD^_fF;JTtCQ zb7b|Rh#I?50ZJ_Y?;1!oCK~KL1-SWf zoIOQ|Fj%z4)85N|NSJ_2Fc@oWE8)F2${WZ`Y#|2(xbb#ODm!~0G_LG}ZhYlIq0cII za|p-VGsBJc0rn(e6!VMn)5`eFdqK3I)q;QxhJ|((Jw81S*N)(6ADtLe)fC^1Esx`MHVc7+SlU zsGe#fe$Z2oYGST$9>wf5N5(~agB{__iy!x((b_p{CazhsVeGnb@oA)PI%#zHzA_s9 z_pZcn4ET%*3lqn!Ke>KuLd4oho93@syK(v2sEv=-FWWRVaRGYnn(M~i&g;9;nc&;V z4fNcs)Ambr_SpsS4P_E9qJPubaotAU&hlMxlK~w!3b4I2N1E=CS$}QqQ}&>Nb>8SN zP002i!_iCfAo4nFlU-+L{q?=|hO?L9hPdoyH?a=d&P{u6yxj$MApKn3GMtN+-I(8N z>+GEF`6#2KR(p9g64yMiG`C`>@W|WQN3*`!7HObs>dO@OCUVHf0$A2*WKaWXBP{SZ zN@>=1dT)2SP;lc*P z_?_rk*jx0%B}-TMXqCZqVw0?~n8Jq(+sFE^TW?&tbZxM()ft&-Nb{i zWCs#_xff6v3a}MHKiov!kq4T(pB~1y z;uQ^gy$o|m0UQhh$gu>{G)=8J9$L+T-?5nX0;Q36l!C6Vo~9l82-6Cu6EzjbNT|_c z+R~a%>>&E75AO1gP9#}RD=@?su$&=0Pv5@Q(*-U~Pk@4Tc7lQ#&3-`8!FRuXr>Ad$ zyPIMFbS{)7{V)l%@(yp(Ku-^M>#X=Ot>kaV@s6(^=xKZ;&X<%_c={Ux{hlGf`>7vT zB<~PPD$sq30NTe0XdkmCYSQxUO~9V+MOQ|2MK_8h$(!hy%r%jdN7&-;0Fi4aCa}n) zS1V`|&wnRB5I4YcYYcB7Z_*v|X5z+X4a7}8Y{Fm!Dm7L}8#uO~NL!OB>>*Rk4jBGg zo=lx0B|U$Emd6!_b3$ZbWhFr0_<&>*x=pZt&vKtEYY9~#sntXuw+5mHZ$j2of zG7R(Udk~MAG`>Va(t%fYxyjkhS(s9$ot5bx;{5$U_Xw73x+*}Po49Owe2fY3PfLXj zt2eAa=yR&i-WE-I^lLudde*ROQ9|5S-_2_$jtrkPWmKdM>Oj+k5fdkm3HF(0wA{N; zQohu%5vIGb>g-t3XkP3*gNuwc(E+R6t?||W^l+c&A>9#QOLw9@JYFyL@Km1{d@mod z@Mc^Tc;AdcEF9UqN3- z-(25aKLi&S&d|@*AJS*(bKTtBOl~$@TUghvsoN;GiEfMBZVRP_QNm1No)9hU5%vp5 zg&V?c;T74GHhq)We79`8>Se(H!L@-G9()I8j=k!3~vm-8+At6=wmEn ztZ1xiY+>wg3^z_N&M@vV9yA^?rW-SiZ%w>OFnO2?m}Ha9RL)e%RKwK3)ZEn0)XCJt z)ZaA7G}<)LG|4pEw9pi7iZksroi$xB-7wuX{cL(-dTx4a`omptm)yT{_jRw~UeCRe zdq4L>BgrG#GKG@?k5Je0Kl1IpbvV=+3LKuK9X=&2;MSOQmXUDpfu^=w+ns#55s&TJq%HKK;6n zY}>rk#*8Ryc|(yE_gfGjUtIUjkiKoe&UW-P{v#H+)%<@!2L!w0RG~w#L08y7!`Q`DM@S|J_oiugw0N-zF5z&yoJ?OTU#volf(##K1!bU;$ z@!t^MDJ6GSXolcel}(bHDdj{w!m(LySg|8|7#^b|mJJ&jKXM#y>~5BIKG~_h;kuj} zmo2;CbxRq_!T;J&?UE*TUxpMuFKqrK>&x#APPAu91Ci1&t1_Zm;L7S6A#B%`U7#(= zpCUQ}UD0UHo!wEC2oL?#c$^0RBajG;#0Ayt@HaaIZi6M{`}qNIK!e_4(4co2H0TRJ zgR&5wBY-!||MSnhv)uXIcj9_gQYG6l z)USAXK1KVI#*)U!7njD_a?{r8CgDdBTYJ zfxZpe*T=Ftm)7t)a+Vfk=QtV6zC`=VT_Z>J9A+IgLFh5GORvg4RC-be4Vu@hJLIcX zR_M0Zv3DBS%C}X|A2Uzy+q7q+ZDX8}zGvfsvp#Ve#$xRpBIMM&iNiV!-J#oSD02<* zR%??la*UQ6w7_*k0t1M62!M#Iw1}ZwFvExVrrytv+D5gQx8+f8Q?{RNru_jJ`=IH# z_2ZytL4tw!#@&)yC^ZzR!p-*2Zlv!#w96_1*KU|-nZHo96s{>+%4=7#6b5K#>sg{% ze$`HtTu0^u_e-P>!1Xmq>F%UE1YV2|v$b(NmZfh+^TEOGH?;t$M5Q`Z-+gW0ZNqI+ z)QvzFP`T7!)0NmT*($Bww#}(l5NtEcl@zIc5Q<~(8%E1znvX#C@FOBv4lYucW&ube z4~rxZo5Uum`tf-HnUZ>Duqfqe6Y}RJGV0@T$WgB2khlNj7GY}hCpXj1-IM~a(5m%1 z8KtvA@d=_d&vnn5v|FTK8`eVIRlB}Lq9d_a?kCAF;?7;d-nnO`tMp4NUH75sJ96j^ z>N-6n06xx9h}}a{2}h!Wnz!s7gtLg14Cb>zsD86WhCL^Z>^h>7&vc{t6ID^@i(}(H zUCNE_q)1*Q^wmcI4{6lYnGi}^lq|`s0To3GDbKud%r@@^cQb>@S2=aQ@ELqQj#e>+ z?#7y09(Ekms#5QH%98jviI{&r^Xf_Cy(MB%PAxeuFuel|OfM-9Oz-kPf$2?HyKY_F zT8TlY-4_k77m3nhoa9*|$$!`4(;tTFg|qW1gkV-q#~VCpx=30iHcDq@Kd5lG2EK?Gc9mckomaJ>E1~#nsx8ra2k|`b}Wity}>szE^74X zNGWOnYPg6i_ap}777pYz>4s>_HlolVsf7#@Q;6%PeJ*aftC^=WM1qtU8I$V~336$_$!r{U#dv=9x z#o@w`AwgS0QLq?<76ZAG430jrqI8saT$>jm)g9ciMztZwE?R-1;di$NDJG%VIl)3P z>c}yyK!I@H^oLvaq&Z9G&hnW(YtAgI6cL{|%O>p$Umvne((n$64(%C}(N%bH!-Z1P zH3Jbv>3nxwq>Kz+%#7J0lny*az2t;Mlr$CJwNhZ@h>(6h(laqZx-AAm*5WT%_CsAe z31vhH`x01LVvDobL6H_m3Y!c=e-(xrhLjOlb-}Hz(nr5Ds5zNE%?l6J~1^}SwV08v)+eFn`d#l_5DC_zD_ zfOJ(MA%Jj_(4x6vyu@yUmh=tLqG-ASOQ0KIhV~+=xO8?LTEwTK6dN;R!bYpakOGi9 z6^xS1l(U@ULKIICH+i7rkc_0+S>d9QHft%M9{^7D8d1tn(6OcDUo9z7uaY$=K;C9Ua_fFD)B&Cq?@rg4fsBMmtPC#i< zIzfU?O1P(N<2&R_$0C@UG^$7%Nu>E~!HJF~1rJH+=v%oZ&NE8%OQv376|&ISu+GNp zg@b_7ey`Y6DRqG&r4juJ2`g`GRh5&VpmGW4sB25=4mtIvKzQkAJ_|}1YNDjp$JjxM z;3fHI$9kX#0Sm%cnn%oCj!LVRFI$10c0VaE0ZUv>ydlwViC)5$Qj6Y6)!U!LT@UB( z-aFZ-qzzRm0P*-unI@qCXe-oC0?|7OI5I-pe{$Mj@rx1g$GZq-10{{JZ>B{^{B^ax zUQ%bv(r-6^lNb-jdEk%z({bKd9W%qO0Cr7yt|V6p<~LX!;IU)U3}y?iGt6#WAj|>W zD43(U2$&PN`7jr7%V0)x2{046Jus8FV=&XXYcQ{K_hJ6TsW5+s1{cp4$=?!hdT#J90YD-saUvi5Uy8J_z>%Xr9;cZ(&{q z&AufsHQt=S&E(!9HBNc3Z}kF)89XdsBrRY3w0tS6>wy5c)}<2e8+9?J25^kv`p2m40;4+k^*TrqzfgY-MQo0gHe|7B zR9i+#Et$#weWb)da10hhU^1$6KGidy`sn&sYBGF`XW@yA!mfvl3eTth;`(pW$oq2m zPh)-=UtT%=%043 zRkuE;vOaf}R)X&iv(u=D|3=}G)mGj9*GSCK#7h#%4O#x`AG#e4p1Ii3M6KyN$r14{WawBh_$2^8>6cH z7Zmct*;2Fo_((Z(`V+gBQhOE}LIow&%cr{LQ;q*SigCF@arzzLw1FKcski3JDAtQ{ zQdqw0M`}#I-Ar)ImzKa})Wm$so=<&r{VRp*@h1UqLvXVgd6 zzu7&~{5=QvXOwhL`kNhinB5;9Zqggg7bs_|$L#)zlGOi_FF(A$`e6Q@sb{(1;jO)c z%4^~NBUKtcoGk;RDr$Z|r;7f?4k0_+2rV|PjnJs38Xt4jC_FoQv}Sf1)%|}#{fAHx zc3)@6po0EOYIr{1NR8rkEX6#(T8H@oUtKdRV9W?wKN98_PE+IgLUXOkXq~TSQ%SQa z<)k&v{u&*p*|Rdo^Ks0co28kDH2Y@Eo}0~R?vOU-F0T14uDO=bd==Ad#%MNQYGwh= zrjX|PrAC+3%yLdsOY;oPwY+9iK{KmrCd*r%ucFZnwa^+eT4&JgD{5)*XCdgEabY6H zXwANg#$UxrYy9&yvzTV%`zK~&d@+ruq85G~&AyIiQ%B!|b`k+E-N8c>Fc{sv2Eh z^XsqCMVY_*7oA%lKuMFmYI&D5!1{1JKx|*D) zHcxJekl7#W=W5`O^-8Q4Vt;vVdC&Hk?MN*4KUQmIyk=g}%*&d231%V8o7yA18VIW~ zel4|kX4e%nsR5Wpg>hpzJ9g;pt{*~W-|@#P&5YN~E1KC?GcRlAC1&zXHFK6`4rC_x zn`Ww-O-0Qtui0QA!M)c{|7^}(Lz|hhIXA0Y0yw_F4EAfziaBUGt}^#6SBtBUG`HZ| zV(mcRs6l5xu1=eFt^K&5j_um`VO7BCmxsJ1gdt=0YvW2m+TU>1xY}F**970&PUHF# z@-{-oUm_%5&W|gG!#))tm+D*{t^wDSYXyn0(7x2>@Sd2ZeubHP5zL6oa22_#kY8P_ zR5asSa~)iKZk#)3#x=L1DU%|7MPc1a#g1)f^T!Sl4&-znP;ef1?W;{qJTKT^L;d&8(^$ z57&P-#|{{+n>PAi&5@&Zvqz8pXA|XEhd;K)q(g~zwgar+WvfHXETWlyFbkkOnox#B zlwA+he=|yd0hB*4l&OL!%dGe3wHm@!pcrk_%&#<4>p4(D4Y2>3Ick&-C{`PIlyNjv z8mFR}R+P`KydQr{S5ntfH(NhVe?WL|cx4ogC5?@ZLB^TJt;TGlYAR}KYlJzF5N> z%)9XdZ{Ur*iFfBkUc&hwPu|Rb!584a1jl{uF@J;qk>AH3;1BT!`4m2tKg=KD)A*zO zG5$E8&Y$2<@~8OII*YELPDU(j_0A17tQKl@Uv3ch9XFkufz_;8+-z@%-9_x_KUZ@znm(a0ZiMg|oM3`p8hxh1O8P--Wa<5R6O7jg-uEy~55&i)_i@(Re(Yc|Xuso3j$KQWClx+O5e_Dw^dL*2f z``Zupj6)O-{PoADqtvB;5<()lR{r(JCu;uPh4G*N`04OH{S)7VId`Gw=Rbb1=GP?D z`Siy(htKAp_$<$v1iw#zJR76wIiukA@y8c{FE*}leJ}T(GrB$f_`^GMF}P*t{kU7m zvs<6|NQdizydT!H8Nc8b@BDGw!M*(x?r6Bpb^fp#&UoG2#;_k}2dDiLPP7?rf$WD? zh4Ja#TD!GIE5qZD{nPRX3C_h7c7UO4X&*J=C?O8&rvt~X@d$Zv*Ig7IhQf)$y zSBRgiz5DS~o%Z}J?a5jaH-4Inm(_YR$`A8dl%M?x#~c@pmJBH^g2ts7Uku!=-msoY zlcw%Dq;VMUOfsLlT!g<^l-hrC+lR0x<2U;sT~{J~f!c5QKe~_S1U|s^LrwpOxVv%& z-kSd_{f|6VkZ-?#{PAx8$mM}Az5LmawV{9eTK*w&di!5~`~HzL8SN_TZ$AIAow&b; zx&ULCuK(~0{73FU^jM|;@mIyguS0GP;DZqp%hhrGIArB`lt(tU$;(w9BPE{q*4{aU zhTS*x$o=8W_(hFh`i%b({G*0wdt}T9>yJ>g5Q7$%=0ntcupZFayRkWqmn)7kpq;%i z>KjH0e|2ezQ3sQbbFa<7O$9d(`OS0r&$Az<*(ajEW4s^vuj5Upjc-2MR>mCV<6BY8 zQa-*FL_PiZX248_$&HN;KHc*x3m$rMvrKPrQ3Jzo&!4oFYOrSf0F{0Uq8Er^`>l!vtk81;N+cc0mDx%qZFjDRHM=0J?Z24Uni1S73s7+L+F;_NRp z$0!cq`1{Tqvzf&ZR(P{T13qPV?X#TysY2mha#a?7J76;r?*lyZ)_j!WuNAdWtQgzp3d$-ThjRh7f&5SYMc^Tb>o_u3eAIdsi2t^>Tc{r$qGr zeGS$VU8}ZviB8z>G4%6ID322Pu5YXzgBS>^ ziToE~Y#pwJ@+l&JEsnL}9`52i&S40HjP;_dC%cd6y3znH<4W+Fcow(uPT~H|{tZgq B9E<<} literal 0 HcmV?d00001 diff --git a/App/BlurtiOS/Design/fonts/OceanicText-Regular.otf b/App/BlurtiOS/Design/fonts/OceanicText-Regular.otf new file mode 100644 index 0000000000000000000000000000000000000000..5abe1d47eb03064d80fdae11b6a454f1fbdbc9f3 GIT binary patch literal 91688 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 tH&PBIDmgSfGx@~Im{{a_9gGc}X literal 0 HcmV?d00001 diff --git a/App/BlurtiOS/Design/fonts/UN_11ST_Regular.ttf b/App/BlurtiOS/Design/fonts/UN_11ST_Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..552ff21facea8dd04da598c5b9608778b0ec3e57 GIT binary patch literal 92392 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 literal 0 HcmV?d00001 diff --git a/App/BlurtiOS/project.yml b/App/BlurtiOS/project.yml index 6c8949bb..8307b58b 100644 --- a/App/BlurtiOS/project.yml +++ b/App/BlurtiOS/project.yml @@ -52,6 +52,11 @@ targets: - path: ../Blurt/Blurt/AppIcon.icon - path: ../Blurt/Blurt/Branding/blurt-ready-logo.png buildPhase: resources + # The brand's faces (Modern Gothic Mono, UN 11ST, Oceanic Text), from the + # website repo's public/_aai/fonts/rebrand, converted to TTF for iOS. + # The keyboard carries its own copy: an extension can't read the app's. + - path: Design/fonts + buildPhase: resources # The App Group contract, compiled into BOTH the app and the keyboard (an # extension can't import the app's module) — one source, no duplication, # the same shape as App/Blurt/Shared. @@ -90,6 +95,13 @@ targets: # they are typing in: iOS ends a backgrounded app's capture without it. UIBackgroundModes: [audio] UILaunchScreen: {} + UIAppFonts: + - ModernGothicMono-Light.ttf + - ModernGothicMono-Regular.ttf + - ModernGothicMono-Medium.ttf + - UN_11ST_Regular.ttf + - UN_11ST_Bold.ttf + - OceanicText-Regular.otf UIApplicationSceneManifest: UIApplicationSupportsMultipleScenes: false UISupportedInterfaceOrientations: [UIInterfaceOrientationPortrait] @@ -130,6 +142,8 @@ targets: sources: - path: BlurtKeyboard/Sources - path: Shared + - path: Design/fonts + buildPhase: resources settings: base: PRODUCT_BUNDLE_IDENTIFIER: dev.alex.blurt.ios.keyboard @@ -142,6 +156,13 @@ targets: CFBundleDisplayName: Blurt CFBundleShortVersionString: "0.1.0" CFBundleVersion: "1" + UIAppFonts: + - ModernGothicMono-Light.ttf + - ModernGothicMono-Regular.ttf + - ModernGothicMono-Medium.ttf + - UN_11ST_Regular.ttf + - UN_11ST_Bold.ttf + - OceanicText-Regular.otf NSExtension: NSExtensionPointIdentifier: com.apple.keyboard-service NSExtensionPrincipalClass: $(PRODUCT_MODULE_NAME).KeyboardViewController From 5f96337238b12a4663950feb4155705298c57374 Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Tue, 29 Sep 2026 16:01:52 -0400 Subject: [PATCH 50/79] Design: tokens for the brand's two faces, its fonts and its curve MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The eight keyboard themes become two faces of one theme — `light` (paper #ECEBE5, white keys, ink legends, the wordmark green) and `dark` (ink #1D1B16, #33302A keys, warm-white legends, the lifted green) — with ten roles each: the six the keys had plus a secondary legend for the mono word labels, the key-term field and its hairline, and the orange notice. `KeyboardPalette` keeps its shape (`all`, `resolve(_:dark:)`) so the curated themes can come back as value sets; an unknown or retired id (the old `system` default) resolves to the brand's face for the host app's appearance, and two palettes are equal only when face and id agree. The brand's warm neutrals join `brand` (paper/* and neutral/*, from the design system's white, neutral and black scales); the app's light cards move onto them. `type` gains the mono label, eyebrow, CTA and app sizes and the E1/E2 tracking; `motion` gains the 0.2 s colour transition, the landing glint and the house curve as a cubic-bezier token (a four-number value the generator now renders as a `UnitCurve`); a new `fonts` group carries the three faces by PostScript name, checked against the bundle by a test. The gallery and the capture scripts speak in faces (`light` / `dark`); the older theme words still land on one. No view draws differently yet except in colour. Co-Authored-By: Claude Fable 5.1 --- .../Sources/KeyboardPalette.swift | 125 ++++---- .../CardBorder.colorset/Contents.json | 6 +- .../CardFill.colorset/Contents.json | 6 +- .../Sources/KeyboardGalleryView.swift | 14 +- .../BlurtiOS/Sources/ThemePickerView.swift | 8 +- .../BlurtiOSTests/DesignTokensTests.swift | 90 +++--- .../BlurtiOSTests/FeedAndLayoutTests.swift | 14 +- .../BlurtiOSTests/SharedStateTests.swift | 12 +- App/BlurtiOS/DESIGN.md | 163 ++++++---- App/BlurtiOS/Design/figma/tokens.js | 120 ++++---- App/BlurtiOS/Design/tokens.json | 222 ++++++++++---- App/BlurtiOS/Shared/DesignTokens.swift | 289 ++++++++++-------- scripts/design-capture.sh | 6 +- scripts/design-tokens.swift | 59 ++-- scripts/ios-record.sh | 6 +- 15 files changed, 659 insertions(+), 481 deletions(-) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift index dbf7358d..aacc8ec3 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift @@ -1,17 +1,24 @@ import SwiftUI -/// The colors the keys draw with — a theme. The default is the iPhone -/// keyboard's own, light or dark with the app being typed in, so Blurt's keys -/// sit on Apple's globe-and-mic bar as one keyboard and the brand lives in the -/// orb. Then Blurt's ink and five more cut from the same cloth (the orb's -/// lavender and green, a warm paper, a midnight, a sunset), each contemporary -/// and fun and none off-brand, picked in the app Partiful-style from live -/// previews. The spacing never changes (the iPhone keyboard's own — 6 pt -/// between keys, 11 between rows, 3 at the edges), so a theme changes how -/// the keyboard looks and never how it types. The keys are flat: one colour -/// at 8 pt corners, no drop, no edge, no gloss. +/// The colours the keys draw with: the brand's two faces. The keyboard follows +/// the field it is typing into — ink with the brand's film grain when the +/// host app is dark, warm paper when it is light — so Blurt sits on any app +/// as one keyboard, on the brand and off Apple's grey. The spacing never +/// changes (the iPhone keyboard's own — 6 pt between keys, 11 between rows, +/// 3 at the edges), so a face changes how the keyboard looks and never how it +/// types. The keys are flat: one colour, no drop, no edge, no gloss. +/// +/// One theme for now, with two faces. The curated themes come back later as +/// value sets through the same shape: `all` is the picker's list, `resolve` +/// the keyboard's lookup, and neither needs to change for a third entry. struct KeyboardPalette: Equatable, Identifiable { + enum Face: String { + case light + case dark + } + let id: String + let face: Face let name: String /// One line for the picker. let vibe: String @@ -19,10 +26,19 @@ struct KeyboardPalette: Equatable, Identifiable { let key: Color let keyDark: Color let keyText: Color - /// The voice on this surface: the wave while recording. The brand green - /// that reads on it — the wordmark's on light, the lifted one on dark. + /// The word labels (123, ABC, return, space) in mono, and the + at rest: + /// a step quieter than a letter. + let keyTextSecondary: Color + /// The voice on this surface: the wave, the caret, the saved check. The + /// brand green that reads on it — the wordmark's on paper, the lifted one + /// on ink. let signal: Color let popupFill: Color + /// The key-term field and its hairline. + let field: Color + let fieldBorder: Color + /// The error word, the cancel ×, the Full Access note: orange on both faces. + let notice: Color static let keyGap = DesignTokens.Metrics.keyGap static let rowGap = DesignTokens.Metrics.rowGap @@ -31,62 +47,39 @@ struct KeyboardPalette: Equatable, Identifiable { private typealias Themes = DesignTokens.Themes - /// The iPhone's light keyboard: `#D1D5DB` surface, white keys, `#ADB3BC` - /// modifiers, black legends. - static let systemLight = KeyboardPalette( - id: "system", name: "iPhone", vibe: "Matches the iPhone keyboard, light or dark with the app you're in", - surface: Themes.systemLightSurface, key: Themes.systemLightKey, keyDark: Themes.systemLightKeyModifier, - keyText: Themes.systemLightLegend, signal: Themes.systemLightSignal, popupFill: Themes.systemLightPopup) - - /// The iPhone's dark keyboard: `#2B2B2B` surface, `#6B6B6B` keys, `#464646` - /// modifiers, white legends. - static let systemDark = KeyboardPalette( - id: "system", name: "iPhone", vibe: "Matches the iPhone keyboard, light or dark with the app you're in", - surface: Themes.systemDarkSurface, key: Themes.systemDarkKey, keyDark: Themes.systemDarkKeyModifier, - keyText: Themes.systemDarkLegend, signal: Themes.systemDarkSignal, popupFill: Themes.systemDarkPopup) - - static let ink = KeyboardPalette( - id: "ink", name: "Ink", vibe: "Blurt's own", - surface: Themes.inkSurface, key: Themes.inkKey, keyDark: Themes.inkKeyModifier, keyText: Themes.inkLegend, - signal: Themes.inkSignal, popupFill: Themes.inkPopup) - - static let paper = KeyboardPalette( - id: "paper", name: "Paper", vibe: "Warm and light", - surface: Themes.paperSurface, key: Themes.paperKey, keyDark: Themes.paperKeyModifier, keyText: Themes.paperLegend, - signal: Themes.paperSignal, popupFill: Themes.paperPopup) - - static let lavender = KeyboardPalette( - id: "lavender", name: "Lavender", vibe: "The orb's violet", - surface: Themes.lavenderSurface, key: Themes.lavenderKey, keyDark: Themes.lavenderKeyModifier, - keyText: Themes.lavenderLegend, signal: Themes.lavenderSignal, popupFill: Themes.lavenderPopup) - - static let mint = KeyboardPalette( - id: "mint", name: "Mint", vibe: "The orb's green", - surface: Themes.mintSurface, key: Themes.mintKey, keyDark: Themes.mintKeyModifier, - keyText: Themes.mintLegend, signal: Themes.mintSignal, popupFill: Themes.mintPopup) - - static let midnight = KeyboardPalette( - id: "midnight", name: "Midnight", vibe: "Deep blue-black", - surface: Themes.midnightSurface, key: Themes.midnightKey, keyDark: Themes.midnightKeyModifier, - keyText: Themes.midnightLegend, signal: Themes.midnightSignal, popupFill: Themes.midnightPopup) - - static let sunset = KeyboardPalette( - id: "sunset", name: "Sunset", vibe: "Warm and loud", - surface: Themes.sunsetSurface, key: Themes.sunsetKey, keyDark: Themes.sunsetKeyModifier, - keyText: Themes.sunsetLegend, signal: Themes.sunsetSignal, popupFill: Themes.sunsetPopup) - - /// The picker's order: the iPhone's own first (shown in the picker's own - /// appearance), then Blurt's. - static let all: [KeyboardPalette] = [systemLight, ink, paper, lavender, mint, midnight, sunset] - - /// The theme with this id in the given appearance — only the iPhone theme - /// has two faces — or the iPhone's for an id that no longer exists. + /// The brand theme's id, and what any unknown id resolves to. + static let brandID = "blurt" + private static let brandName = "Blurt" + private static let brandVibe = "Ink or paper, with the app you're in" + + /// The light face: paper `#ECEBE5`, white keys, `#DAD7CB` modifiers, ink + /// legends, the wordmark green. + static let brandLight = KeyboardPalette( + id: brandID, face: .light, name: brandName, vibe: brandVibe, + surface: Themes.lightSurface, key: Themes.lightKey, keyDark: Themes.lightKeyModifier, + keyText: Themes.lightLegend, keyTextSecondary: Themes.lightLegendSecondary, signal: Themes.lightSignal, + popupFill: Themes.lightPopup, field: Themes.lightField, fieldBorder: Themes.lightFieldBorder, + notice: Themes.lightNotice) + + /// The dark face: ink `#1D1B16`, `#33302A` keys, `#26231E` modifiers, warm + /// white legends, the lifted green. + static let brandDark = KeyboardPalette( + id: brandID, face: .dark, name: brandName, vibe: brandVibe, + surface: Themes.darkSurface, key: Themes.darkKey, keyDark: Themes.darkKeyModifier, + keyText: Themes.darkLegend, keyTextSecondary: Themes.darkLegendSecondary, signal: Themes.darkSignal, + popupFill: Themes.darkPopup, field: Themes.darkField, fieldBorder: Themes.darkFieldBorder, + notice: Themes.darkNotice) + + /// The picker's list, one entry per theme (a theme's two faces share an id). + static let all: [KeyboardPalette] = [brandLight] + + /// The theme with this id in the given appearance, or the brand's for an id + /// that no longer exists (the old `system` default, a retired theme). static func resolve(_ id: String, dark: Bool) -> KeyboardPalette { - if id == systemLight.id { return dark ? systemDark : systemLight } - return all.first { $0.id == id } ?? (dark ? systemDark : systemLight) + dark ? brandDark : brandLight } - static func == (lhs: KeyboardPalette, rhs: KeyboardPalette) -> Bool { lhs.id == rhs.id } + static func == (lhs: KeyboardPalette, rhs: KeyboardPalette) -> Bool { lhs.id == rhs.id && lhs.face == rhs.face } } extension Color { @@ -99,7 +92,7 @@ extension Color { } private struct KeyboardPaletteKey: EnvironmentKey { - static let defaultValue = KeyboardPalette.systemLight + static let defaultValue = KeyboardPalette.brandLight } extension EnvironmentValues { diff --git a/App/BlurtiOS/BlurtiOS/Assets.xcassets/CardBorder.colorset/Contents.json b/App/BlurtiOS/BlurtiOS/Assets.xcassets/CardBorder.colorset/Contents.json index 0c5b7df4..573af17f 100644 --- a/App/BlurtiOS/BlurtiOS/Assets.xcassets/CardBorder.colorset/Contents.json +++ b/App/BlurtiOS/BlurtiOS/Assets.xcassets/CardBorder.colorset/Contents.json @@ -5,9 +5,9 @@ "color-space" : "srgb", "components" : { "alpha" : "1.000", - "blue" : "0xDB", - "green" : "0xDB", - "red" : "0xDE" + "blue" : "0xB2", + "green" : "0xC3", + "red" : "0xC7" } }, "idiom" : "universal" diff --git a/App/BlurtiOS/BlurtiOS/Assets.xcassets/CardFill.colorset/Contents.json b/App/BlurtiOS/BlurtiOS/Assets.xcassets/CardFill.colorset/Contents.json index 8c14171d..cd845c54 100644 --- a/App/BlurtiOS/BlurtiOS/Assets.xcassets/CardFill.colorset/Contents.json +++ b/App/BlurtiOS/BlurtiOS/Assets.xcassets/CardFill.colorset/Contents.json @@ -5,9 +5,9 @@ "color-space" : "srgb", "components" : { "alpha" : "1.000", - "blue" : "0xE8", - "green" : "0xE8", - "red" : "0xEB" + "blue" : "0xEB", + "green" : "0xF3", + "red" : "0xF5" } }, "idiom" : "universal" diff --git a/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift b/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift index 04976840..cacc97dc 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift @@ -7,9 +7,9 @@ /// /// -BlurtGallery [,…] [theme] [-BlurtGalleryStill] [-BlurtGalleryBare] /// - /// The last word is a theme id (`system`, `system-dark`, `ink`, `paper`, - /// `lavender`, `mint`, `midnight`, `sunset`); the iPhone's light face when - /// left out. Two switches make a capture reproducible for the design loop + /// The last word is a face, `light` or `dark` (the older theme words still + /// land: `system` and `paper` are light, `system-dark` and `ink` dark); the + /// light face when left out. Two switches make a capture reproducible for the design loop /// (DESIGN.md › Figma): `-BlurtGalleryStill` holds every motion at time /// zero — the ring, the meter's wave, the orb's fluid and grain — so two /// captures of one state are the same pixels; `-BlurtGalleryBare` draws the @@ -101,7 +101,7 @@ let layout = KeyboardLayout(rawValue: arguments[flag + 1]) else { return [] } // The theme is the next word unless it is a switch. - let theme = arguments.count > flag + 3 && !arguments[flag + 3].hasPrefix("-") ? arguments[flag + 3] : "system" + let theme = arguments.count > flag + 3 && !arguments[flag + 3].hasPrefix("-") ? arguments[flag + 3] : "light" return arguments[flag + 2].split(separator: ",").map { name in Row( caption: "\(layout.rawValue) · \(name) · \(theme)", @@ -109,11 +109,13 @@ } } + /// The words that ask for the dark face; anything else is the light one. + static let darkFaces: Set = ["dark", "system-dark", "ink"] + private static func model(layout: KeyboardLayout, state: String, theme: String) -> KeyboardModel { let model = KeyboardModel() model.layout = layout - // `system` is the iPhone's light face, `system-dark` its dark one. - model.paletteOverride = .resolve(theme == "system-dark" ? "system" : theme, dark: theme == "system-dark") + model.paletteOverride = .resolve(KeyboardPalette.brandID, dark: Self.darkFaces.contains(theme)) // `keys` shows the panel's carousel flipped to its keyboard page; // `term` the voice bar as the key-term field, mid-typing. model.panelShowsKeys = state == "keys" diff --git a/App/BlurtiOS/BlurtiOS/Sources/ThemePickerView.swift b/App/BlurtiOS/BlurtiOS/Sources/ThemePickerView.swift index a3f58c02..54c52f50 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/ThemePickerView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/ThemePickerView.swift @@ -4,7 +4,7 @@ import SwiftUI /// each the real keyboard drawn small in that theme, the chosen one ringed /// in the accent. The keyboard picks it up the next time it comes up. struct ThemePickerView: View { - @State private var chosen = SharedStore.themeID + @State private var chosen = KeyboardPalette.resolve(SharedStore.themeID, dark: false).id @Environment(\.colorScheme) private var colorScheme private let columns = [GridItem(.flexible(), spacing: 14), GridItem(.flexible(), spacing: 14)] @@ -13,9 +13,9 @@ struct ThemePickerView: View { ScrollView { LazyVGrid(columns: columns, spacing: 14) { ForEach(KeyboardPalette.all) { palette in - // The iPhone theme has two faces; the card shows the one this - // screen is in, which is the one the keyboard would show in an app - // that looks like it. + // A theme has two faces; the card shows the one this screen is in, + // which is the one the keyboard would show in an app that looks + // like it. ThemeCard( palette: KeyboardPalette.resolve(palette.id, dark: colorScheme == .dark), chosen: palette.id == chosen ) { diff --git a/App/BlurtiOS/BlurtiOSTests/DesignTokensTests.swift b/App/BlurtiOS/BlurtiOSTests/DesignTokensTests.swift index 19295da0..c1a7b1e1 100644 --- a/App/BlurtiOS/BlurtiOSTests/DesignTokensTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/DesignTokensTests.swift @@ -1,6 +1,7 @@ import Foundation import SwiftUI import Testing +import UIKit @testable import BlurtiOS @@ -26,7 +27,7 @@ struct DesignTokensTests { /// rendering the generator writes into `DesignTokens.manifest`. private static func expectedManifest() throws -> [String: String] { let json = try tokensJSON() - let groups = ["brand", "themes", "keyboard", "metrics", "type", "motion"] + let groups = ["brand", "themes", "keyboard", "metrics", "type", "motion", "fonts"] var raw: [String: Any] = [:] for group in groups { let entries = try #require(json[group] as? [String: Any]) @@ -38,6 +39,7 @@ struct DesignTokensTests { let value = try #require(raw[qualified], "\(qualified) is not a token") try #require(depth < 8, "alias cycle at \(qualified)") if let number = value as? NSNumber { return format(number.doubleValue) } + if let curve = value as? [NSNumber] { return curve.map { format($0.doubleValue) }.joined(separator: ",") } let string = try #require(value as? String) if string.hasPrefix("{"), string.hasSuffix("}") { return try render(String(string.dropFirst().dropLast()), depth: depth + 1) @@ -103,73 +105,59 @@ struct DesignTokensTests { #expect(abs(sideWidth * 2 + gap - DesignTokens.Metrics.keyReturnWidth402) < 0.001) } - /// Each palette beside the six theme tokens it must equal, in role order: - /// surface, key, modifier, legend, signal, pop-up. + /// Each face beside the ten theme tokens it must equal, in role order: + /// surface, key, modifier, legend, secondary legend, signal, pop-up, field, + /// field border, notice. private static let paletteTokens: [(KeyboardPalette, [Color])] = { typealias Themes = DesignTokens.Themes return [ ( - .systemLight, + .brandLight, [ - Themes.systemLightSurface, Themes.systemLightKey, Themes.systemLightKeyModifier, Themes.systemLightLegend, - Themes.systemLightSignal, Themes.systemLightPopup, + Themes.lightSurface, Themes.lightKey, Themes.lightKeyModifier, Themes.lightLegend, + Themes.lightLegendSecondary, Themes.lightSignal, Themes.lightPopup, Themes.lightField, + Themes.lightFieldBorder, Themes.lightNotice, ] ), ( - .systemDark, + .brandDark, [ - Themes.systemDarkSurface, Themes.systemDarkKey, Themes.systemDarkKeyModifier, Themes.systemDarkLegend, - Themes.systemDarkSignal, Themes.systemDarkPopup, - ] - ), - ( - .ink, - [Themes.inkSurface, Themes.inkKey, Themes.inkKeyModifier, Themes.inkLegend, Themes.inkSignal, Themes.inkPopup] - ), - ( - .paper, - [ - Themes.paperSurface, Themes.paperKey, Themes.paperKeyModifier, Themes.paperLegend, Themes.paperSignal, - Themes.paperPopup, - ] - ), - ( - .lavender, - [ - Themes.lavenderSurface, Themes.lavenderKey, Themes.lavenderKeyModifier, Themes.lavenderLegend, - Themes.lavenderSignal, Themes.lavenderPopup, - ] - ), - ( - .mint, - [ - Themes.mintSurface, Themes.mintKey, Themes.mintKeyModifier, Themes.mintLegend, Themes.mintSignal, - Themes.mintPopup, - ] - ), - ( - .midnight, - [ - Themes.midnightSurface, Themes.midnightKey, Themes.midnightKeyModifier, Themes.midnightLegend, - Themes.midnightSignal, Themes.midnightPopup, - ] - ), - ( - .sunset, - [ - Themes.sunsetSurface, Themes.sunsetKey, Themes.sunsetKeyModifier, Themes.sunsetLegend, Themes.sunsetSignal, - Themes.sunsetPopup, + Themes.darkSurface, Themes.darkKey, Themes.darkKeyModifier, Themes.darkLegend, Themes.darkLegendSecondary, + Themes.darkSignal, Themes.darkPopup, Themes.darkField, Themes.darkFieldBorder, Themes.darkNotice, ] ), ] }() - @Test("every palette is its theme's tokens, role by role") + @Test("every face is its theme's tokens, role by role") func palettes() { #expect(Self.paletteTokens.count == KeyboardPalette.all.count + 1) for (palette, colors) in Self.paletteTokens { - let roles = [palette.surface, palette.key, palette.keyDark, palette.keyText, palette.signal, palette.popupFill] - #expect(roles == colors, "\(palette.id)") + let roles = [ + palette.surface, palette.key, palette.keyDark, palette.keyText, palette.keyTextSecondary, palette.signal, + palette.popupFill, palette.field, palette.fieldBorder, palette.notice, + ] + #expect(roles == colors, "\(palette.id) \(palette.face)") + } + } + + @Test("the brand's faces carry the brand: ink under the dark face, paper under the light, green as the signal") + func faces() { + #expect(DesignTokens.Themes.darkSurface == DesignTokens.Brand.ink) + #expect(DesignTokens.Themes.lightSurface == DesignTokens.Brand.paper200) + #expect(DesignTokens.Themes.darkSignal == DesignTokens.Brand.green400) + #expect(DesignTokens.Themes.lightSignal == DesignTokens.Brand.green700) + #expect(DesignTokens.Themes.lightNotice == DesignTokens.Brand.orange) + #expect(DesignTokens.Themes.darkNotice == DesignTokens.Brand.orange) + } + + @Test("the fonts are named by PostScript name and the bundle knows them") + func fonts() { + typealias Fonts = DesignTokens.Fonts + for name in [ + Fonts.monoLight, Fonts.monoRegular, Fonts.monoMedium, Fonts.headingRegular, Fonts.bodyRegular, Fonts.bodyBold, + ] { + #expect(UIFont(name: name, size: 12) != nil, "\(name) is not registered (UIAppFonts / Design/fonts)") } } diff --git a/App/BlurtiOS/BlurtiOSTests/FeedAndLayoutTests.swift b/App/BlurtiOS/BlurtiOSTests/FeedAndLayoutTests.swift index 3e1a9862..1e55c709 100644 --- a/App/BlurtiOS/BlurtiOSTests/FeedAndLayoutTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/FeedAndLayoutTests.swift @@ -50,21 +50,25 @@ struct LayoutArithmeticTests { #expect(KeyboardGalleryView.rows(from: ["app"]).isEmpty) #expect(KeyboardGalleryView.rows(from: ["app", "-BlurtGallery", "panel"]).isEmpty) #expect(KeyboardGalleryView.rows(from: ["app", "-BlurtGallery", "nope", "idle"]).isEmpty) - let rows = KeyboardGalleryView.rows(from: ["app", "-BlurtGallery", "panel", "idle,keys,term", "mint"]) + let rows = KeyboardGalleryView.rows(from: ["app", "-BlurtGallery", "panel", "idle,keys,term", "dark"]) #expect(rows.count == 3) #expect(rows[1].model.effectiveLayout == .full) #expect(rows[2].model.termDraft == "Rizz") - #expect(rows[0].model.palette.id == "mint") + #expect(rows[0].model.palette.face == .dark) + // The old theme words still land on a face, so a capture script never breaks. let dark = KeyboardGalleryView.rows(from: ["app", "-BlurtGallery", "full", "idle", "system-dark"]) - #expect(dark[0].model.palette.keyText == DesignTokens.Brand.white) + #expect(dark[0].model.palette.keyText == DesignTokens.Themes.darkLegend) + let ink = KeyboardGalleryView.rows(from: ["app", "-BlurtGallery", "full", "idle", "ink"]) + #expect(ink[0].model.palette.face == .dark) + #expect(KeyboardGalleryView.rows(from: ["app", "-BlurtGallery", "full", "idle", "paper"])[0].model.palette.face == .light) } @Test("the capture switches ride along, and a switch where the theme would be is not a theme") func galleryOptions() { let args = ["app", "-BlurtGallery", "panel", "idle", "-BlurtGalleryStill", "-BlurtGalleryBare"] - #expect(KeyboardGalleryView.rows(from: args)[0].model.palette.id == "system") + #expect(KeyboardGalleryView.rows(from: args)[0].model.palette.face == .light) #expect(KeyboardGalleryView.Options.parse(args) == .init(still: true, bare: true)) - #expect(KeyboardGalleryView.Options.parse(["app", "-BlurtGallery", "panel", "idle", "ink"]) == .init()) + #expect(KeyboardGalleryView.Options.parse(["app", "-BlurtGallery", "panel", "idle", "dark"]) == .init()) #expect(KeyboardGalleryView.OrbStillView.parse(args) == nil) let orb = KeyboardGalleryView.OrbStillView.parse(["app", "-BlurtOrb", "96", "landed"]) #expect(orb?.size == 96) diff --git a/App/BlurtiOS/BlurtiOSTests/SharedStateTests.swift b/App/BlurtiOS/BlurtiOSTests/SharedStateTests.swift index 151d7a49..233206bc 100644 --- a/App/BlurtiOS/BlurtiOSTests/SharedStateTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/SharedStateTests.swift @@ -77,13 +77,15 @@ struct LayoutTests { #expect(LetterLayout.forPreferredLanguages([]) == LetterLayout.qwerty) } - @Test("every theme has a distinct id; the iPhone theme has two faces; an unknown id is the iPhone's") + @Test("every theme has a distinct id; the brand has two faces; an unknown or retired id is the brand's") func palettes() { let ids = KeyboardPalette.all.map(\.id) #expect(Set(ids).count == ids.count) - #expect(KeyboardPalette.resolve("lavender", dark: true).id == "lavender") - #expect(KeyboardPalette.resolve("system", dark: false).keyText == DesignTokens.Brand.black) - #expect(KeyboardPalette.resolve("system", dark: true).keyText == DesignTokens.Brand.white) - #expect(KeyboardPalette.resolve("nope", dark: false).id == "system") + #expect(KeyboardPalette.resolve("blurt", dark: true).face == .dark) + #expect(KeyboardPalette.resolve("blurt", dark: false).keyText == DesignTokens.Themes.lightLegend) + #expect(KeyboardPalette.resolve("blurt", dark: true).keyText == DesignTokens.Themes.darkLegend) + #expect(KeyboardPalette.resolve("nope", dark: false).id == "blurt") + #expect(KeyboardPalette.resolve("system", dark: true) == .brandDark) + #expect(KeyboardPalette.brandLight != KeyboardPalette.brandDark) } } diff --git a/App/BlurtiOS/DESIGN.md b/App/BlurtiOS/DESIGN.md index 31860b77..c85195b3 100644 --- a/App/BlurtiOS/DESIGN.md +++ b/App/BlurtiOS/DESIGN.md @@ -142,16 +142,10 @@ Group): -| Theme | Surface | Key | Modifier | Legend | Signal | Pop-up | -| -------------- | --------- | --------- | --------- | --------- | --------- | --------- | -| `system-light` | `#D1D5DB` | `#FFFFFF` | `#ADB3BC` | `#000000` | `#01762F` | `#FFFFFF` | -| `system-dark` | `#2B2B2B` | `#6B6B6B` | `#464646` | `#FFFFFF` | `#67AD82` | `#6B6B6B` | -| `ink` | `#1D1B16` | `#33302A` | `#26231E` | `#F2EEE6` | `#67AD82` | `#33302A` | -| `paper` | `#EBE8E8` | `#FFFFFF` | `#DEDBDB` | `#1D1B16` | `#01762F` | `#FFFFFF` | -| `lavender` | `#2C2557` | `#3F3777` | `#352E68` | `#F1EEFF` | `#67AD82` | `#3F3777` | -| `mint` | `#10231B` | `#1E3F31` | `#183429` | `#E9F5EE` | `#67AD82` | `#1E3F31` | -| `midnight` | `#0E1220` | `#1D2440` | `#161B33` | `#E8ECFF` | `#67AD82` | `#1D2440` | -| `sunset` | `#2B1912` | `#4B2B20` | `#3B2119` | `#FFEFE6` | `#67AD82` | `#4B2B20` | +| Face | Surface | Key | Modifier | Legend | Secondary | Signal | Pop-up | Field | Field border | Notice | +| ------- | --------- | --------- | --------- | --------- | --------- | --------- | --------- | --------- | ------------ | --------- | +| `light` | `#ECEBE5` | `#FFFFFF` | `#DAD7CB` | `#1D1B16` | `#777673` | `#01762F` | `#FFFFFF` | `#FFFFFF` | `#C7C3B2` | `#E67F36` | +| `dark` | `#1D1B16` | `#33302A` | `#26231E` | `#F5F3EB` | `#A5A4A2` | `#67AD82` | `#33302A` | `#33302A` | `#3A362F` | `#E67F36` | @@ -268,8 +262,16 @@ these, so the Mac's vocabulary still reads at the call sites. | `ink/600` | `#3A362F` | `Brand.ink600` | the Mac's dark card border | | `ink/700` | `#33302A` | `Brand.ink700` | an ordinary key on ink, one step up | | `ink/800` | `#26231E` | `Brand.ink800` | a modifier key on ink; the Mac's dark card fill | +| `neutral/300` | `#D2D1D0` | `Brand.neutral300` | black-100: the lightest warm grey | +| `neutral/500` | `#A5A4A2` | `Brand.neutral500` | black-200: mono labels on the dark face | +| `neutral/700` | `#777673` | `Brand.neutral700` | black-300: muted text and mono labels on the light face | +| `neutral/900` | `#4A4945` | `Brand.neutral900` | black-400: body text on the light face | | `orange` | `#E67F36` | `Brand.orange` | the error word and ring, cancel, the Full Access note; never a red body | -| `page` | `#FDFCF8` | `Brand.page` | the design system's page background (unused on the phone) | +| `paper/200` | `#ECEBE5` | `Brand.paper200` | neutral-100: the light face's surface | +| `paper/300` | `#DAD7CB` | `Brand.paper300` | neutral-200: a modifier key on the light face | +| `paper/400` | `#C7C3B2` | `Brand.paper400` | neutral-300: hairlines and field borders on the light face | +| `paper/page` | `#FDFCF8` | `Brand.paperPage` | the design system's page: the app's light ground | +| `paper/tint` | `#F5F3EB` | `Brand.paperTint` | the warm off-white one step in: light cards, dark legends | | `violet/iris` | `#887BDD` | `Brand.violetIris` | the orb gradient's upper violet stop | | `violet/lavender` | `#D7D3F4` | `Brand.violetLavender` | the orb's lightest violet: its top and the gradient's ends | | `violet/periwinkle` | `#B0A7E9` | `Brand.violetPeriwinkle` | the orb's mid violet: the drop's halo | @@ -284,26 +286,29 @@ theme's (ink) values, and the app's catalog colours. -| Token | Value | Swift | Use | -| ----------------------- | ------------------------------------- | ----------------------------- | ------------------------------------------------------------------------- | -| `app/accent-dark` | `#67AD82` (`brand.green/400`) | `Keyboard.appAccentDark` | the catalog's AccentColor in dark | -| `app/accent-light` | `#01762F` (`brand.green/700`) | `Keyboard.appAccentLight` | the catalog's AccentColor in light | -| `app/card-border-dark` | `#3A362F` (`brand.ink/600`) | `Keyboard.appCardBorderDark` | the catalog's CardBorder in dark | -| `app/card-border-light` | `#DEDBDB` (`brand.card-border`) | `Keyboard.appCardBorderLight` | the catalog's CardBorder in light | -| `app/card-fill-dark` | `#26231E` (`brand.ink/800`) | `Keyboard.appCardFillDark` | the catalog's CardFill in dark | -| `app/card-fill-light` | `#EBE8E8` (`brand.card`) | `Keyboard.appCardFillLight` | the catalog's CardFill in light | -| `kb/cancel` | `#E67F36` (`brand.orange`) | `Keyboard.kbCancel` | the panel's cancel × | -| `kb/full-access-note` | `#E67F36` (`brand.orange`) | `Keyboard.kbFullAccessNote` | the one line of words the keyboard ever shows | -| `kb/key` | `#33302A` (`themes.ink/key`) | `Keyboard.kbKey` | an ordinary key | -| `kb/key-modifier` | `#26231E` (`themes.ink/key-modifier`) | `Keyboard.kbKeyModifier` | shift, delete, globe, return, 123, cancel | -| `kb/legend` | `#F2EEE6` (`themes.ink/legend`) | `Keyboard.kbLegend` | key legends and bare glyphs | -| `kb/notice-error` | `#E67F36` (`brand.orange`) | `Keyboard.kbNoticeError` | the solid ring and glyph for an error | -| `kb/notice-ok` | `#67AD82` (`brand.green/400`) | `Keyboard.kbNoticeOk` | the solid ring for pasted and copied | -| `kb/orb-ring-end` | `#FFFFFF` (`brand.white`) | `Keyboard.kbOrbRingEnd` | the sweeping ring's gradient, bottom-trailing | -| `kb/orb-ring-start` | `#01762F` (`brand.green/700`) | `Keyboard.kbOrbRingStart` | the sweeping ring's gradient, top-leading | -| `kb/popup` | `#33302A` (`themes.ink/popup`) | `Keyboard.kbPopup` | the letter pop-up | -| `kb/signal` | `#67AD82` (`themes.ink/signal`) | `Keyboard.kbSignal` | the wave, the caret, the saved check | -| `kb/surface` | `#1D1B16` (`themes.ink/surface`) | `Keyboard.kbSurface` | the design theme's surface (Figma binds to kb/*; Swift reads the palette) | +| Token | Value | Swift | Use | +| ----------------------- | ------------------------------------------ | ----------------------------- | ------------------------------------------------------------------------ | +| `app/accent-dark` | `#67AD82` (`brand.green/400`) | `Keyboard.appAccentDark` | the catalog's AccentColor in dark | +| `app/accent-light` | `#01762F` (`brand.green/700`) | `Keyboard.appAccentLight` | the catalog's AccentColor in light | +| `app/card-border-dark` | `#3A362F` (`brand.ink/600`) | `Keyboard.appCardBorderDark` | the catalog's CardBorder in dark | +| `app/card-border-light` | `#C7C3B2` (`brand.paper/400`) | `Keyboard.appCardBorderLight` | the catalog's CardBorder in light | +| `app/card-fill-dark` | `#26231E` (`brand.ink/800`) | `Keyboard.appCardFillDark` | the catalog's CardFill in dark | +| `app/card-fill-light` | `#F5F3EB` (`brand.paper/tint`) | `Keyboard.appCardFillLight` | the catalog's CardFill in light | +| `kb/cancel` | `#E67F36` (`brand.orange`) | `Keyboard.kbCancel` | the panel's cancel × | +| `kb/field` | `#33302A` (`themes.dark/field`) | `Keyboard.kbField` | the key-term field | +| `kb/field-border` | `#3A362F` (`themes.dark/field-border`) | `Keyboard.kbFieldBorder` | the field's hairline | +| `kb/full-access-note` | `#E67F36` (`brand.orange`) | `Keyboard.kbFullAccessNote` | the one line of words the keyboard ever shows | +| `kb/key` | `#33302A` (`themes.dark/key`) | `Keyboard.kbKey` | an ordinary key | +| `kb/key-modifier` | `#26231E` (`themes.dark/key-modifier`) | `Keyboard.kbKeyModifier` | shift, delete, globe, return, 123, cancel | +| `kb/legend` | `#F5F3EB` (`themes.dark/legend`) | `Keyboard.kbLegend` | key legends and bare glyphs | +| `kb/legend-secondary` | `#A5A4A2` (`themes.dark/legend-secondary`) | `Keyboard.kbLegendSecondary` | the mono word labels (123, ABC, return, space) and the + at rest | +| `kb/notice-error` | `#E67F36` (`brand.orange`) | `Keyboard.kbNoticeError` | the solid ring and glyph for an error | +| `kb/notice-ok` | `#67AD82` (`brand.green/400`) | `Keyboard.kbNoticeOk` | the solid ring for pasted and copied | +| `kb/orb-ring-end` | `#FFFFFF` (`brand.white`) | `Keyboard.kbOrbRingEnd` | the sweeping ring's gradient, bottom-trailing | +| `kb/orb-ring-start` | `#01762F` (`brand.green/700`) | `Keyboard.kbOrbRingStart` | the sweeping ring's gradient, top-leading | +| `kb/popup` | `#33302A` (`themes.dark/popup`) | `Keyboard.kbPopup` | the letter pop-up | +| `kb/signal` | `#67AD82` (`themes.dark/signal`) | `Keyboard.kbSignal` | the wave, the caret, the saved check | +| `kb/surface` | `#1D1B16` (`themes.dark/surface`) | `Keyboard.kbSurface` | the design face's surface (Figma binds to kb/*; Swift reads the palette) | @@ -329,23 +334,56 @@ Inter). Sizes are fixed points, not Dynamic Type, as the system keyboard's are. -| Token | Value | Swift | Use | -| ------------------ | ---------- | --------------------------- | -------------------------------------------------------------- | -| `ratio/orb-glyph` | `0.34` | `Typography.ratioOrbGlyph` | the clipboard and exclamation glyphs, as a fraction of the orb | -| `size/glyph` | `17` | `Typography.sizeGlyph` | the +, × and ✓ | -| `size/legend` | `16` | `Typography.sizeLegend` | every other key | -| `size/letter` | `22` | `Typography.sizeLetter` | letter keys | -| `size/popup` | `32` | `Typography.sizePopup` | the letter pop-up | -| `size/term` | `17` | `Typography.sizeTerm` | the key-term field | -| `weight/glyph` | `medium` | `Typography.weightGlyph` | — | -| `weight/legend` | `medium` | `Typography.weightLegend` | — | -| `weight/letter` | `regular` | `Typography.weightLetter` | — | -| `weight/orb-glyph` | `semibold` | `Typography.weightOrbGlyph` | — | -| `weight/popup` | `regular` | `Typography.weightPopup` | — | -| `weight/term` | `regular` | `Typography.weightTerm` | — | +| Token | Value | Swift | Use | +| ------------------ | ---------- | ---------------------------- | -------------------------------------------------------------------- | +| `ratio/orb-glyph` | `0.34` | `Typography.ratioOrbGlyph` | the clipboard and exclamation glyphs, as a fraction of the orb | +| `size/body` | `16` | `Typography.sizeBody` | the app's body text | +| `size/caption` | `14` | `Typography.sizeCaption` | the app's small text | +| `size/cta` | `14` | `Typography.sizeCta` | a mono button label in the app (E2) | +| `size/eyebrow` | `12` | `Typography.sizeEyebrow` | a mono eyebrow in the app (E1) | +| `size/glyph` | `17` | `Typography.sizeGlyph` | the +, × and ✓ | +| `size/label` | `12` | `Typography.sizeLabel` | the mono word labels on keys: 123, ABC, #+=, space, the return label | +| `size/legend` | `16` | `Typography.sizeLegend` | every other key | +| `size/letter` | `22` | `Typography.sizeLetter` | letter keys | +| `size/popup` | `32` | `Typography.sizePopup` | the letter pop-up | +| `size/term` | `17` | `Typography.sizeTerm` | the key-term field | +| `size/title` | `34` | `Typography.sizeTitle` | the app's serif headline | +| `tracking/cta` | `1.4` | `Typography.trackingCta` | uppercase mono at 14: the brand's E2 tracking | +| `tracking/eyebrow` | `1.2` | `Typography.trackingEyebrow` | uppercase mono at 12: the brand's E1 tracking | +| `weight/glyph` | `medium` | `Typography.weightGlyph` | — | +| `weight/label` | `medium` | `Typography.weightLabel` | — | +| `weight/legend` | `medium` | `Typography.weightLegend` | — | +| `weight/letter` | `regular` | `Typography.weightLetter` | — | +| `weight/orb-glyph` | `semibold` | `Typography.weightOrbGlyph` | — | +| `weight/popup` | `regular` | `Typography.weightPopup` | — | +| `weight/term` | `regular` | `Typography.weightTerm` | — | +## Fonts (`Design/fonts/`, `DesignTokens.Fonts`) + +The brand's three faces, bundled in both targets and named by PostScript name +(what `Font.custom` takes). Letter keys stay in SF Pro; everything that is a +word label on the keyboard, and the app's eyebrows and buttons, is Modern +Gothic Mono in uppercase; the app's headlines are Oceanic Text, its body +UN 11ST. + + + +| Token | Value | Swift | Use | +| ----------------- | -------------------------- | ---------------------- | ----------------------------------------------- | +| `body/bold` | `UN-11ST-Bold` | `Fonts.bodyBold` | — | +| `body/family` | `UN-11 ST` | `Fonts.bodyFamily` | the app's body text | +| `body/regular` | `UN-11ST-Regular` | `Fonts.bodyRegular` | — | +| `heading/family` | `Oceanic Text` | `Fonts.headingFamily` | the app's serif headlines, sentence case, tight | +| `heading/regular` | `OceanicText-Regular` | `Fonts.headingRegular` | — | +| `mono/family` | `Modern Gothic Mono` | `Fonts.monoFamily` | eyebrows, CTAs, the keyboard's word labels | +| `mono/light` | `ModernGothicMono-Light` | `Fonts.monoLight` | — | +| `mono/medium` | `ModernGothicMono-Medium` | `Fonts.monoMedium` | — | +| `mono/regular` | `ModernGothicMono-Regular` | `Fonts.monoRegular` | — | + + + ## Components (`BlurtKeyboard/Sources/`) **Voice bar** (`VoiceBar.swift`) — the only place voice lives, and it has no @@ -509,22 +547,25 @@ Motion, in seconds. Nothing springs or snaps; only the press answers at once. -| Token | Seconds | Swift | Use | -| --------------- | ------- | --------------------- | ------------------------------------------------------------- | -| `caret` | `0.5` | `Motion.caret` | the caret's blink | -| `drop` | `2.4` | `Motion.drop` | the violet drop is gone by | -| `drop-hold` | `0.9` | `Motion.dropHold` | and held to | -| `drop-rise` | `0.5` | `Motion.dropRise` | the drop is up in | -| `drop-spread` | `1` | `Motion.dropSpread` | the bloom reaches its full spread in | -| `flip` | `0.25` | `Motion.flip` | the panel's carousel | -| `height-change` | `0.25` | `Motion.heightChange` | the keyboard resizing | -| `key-press` | `0.08` | `Motion.keyPress` | a key lighting | -| `mood` | `0.8` | `Motion.mood` | the orb's colour moving between moods | -| `press` | `0.1` | `Motion.press` | the orb's press; the one thing that answers at once | -| `ring-period` | `1.6` | `Motion.ringPeriod` | one turn of the ring, the Mac's cadence | -| `state-fade` | `0.5` | `Motion.stateFade` | every other change on the key: the ring, a glyph, the dimming | -| `term-swap` | `0.4` | `Motion.termSwap` | the voice bar becoming the field | -| `wave-fade` | `0.7` | `Motion.waveFade` | the orb and the wave crossing, either way | +| Token | Value | Swift | Use | +| ---------------- | --------------- | ---------------------- | ------------------------------------------------------------- | +| `caret` | `0.5` | `Motion.caret` | the caret's blink | +| `colour` | `0.2` | `Motion.colour` | a colour or fill changing state: the brand's transition | +| `drop` | `2.4` | `Motion.drop` | the violet drop is gone by | +| `drop-hold` | `0.9` | `Motion.dropHold` | and held to | +| `drop-rise` | `0.5` | `Motion.dropRise` | the drop is up in | +| `drop-spread` | `1` | `Motion.dropSpread` | the bloom reaches its full spread in | +| `ease/signature` | `0.22,1,0.36,1` | `Motion.easeSignature` | the house curve for everything that moves; nothing springs | +| `flip` | `0.25` | `Motion.flip` | the panel's carousel | +| `height-change` | `0.25` | `Motion.heightChange` | the keyboard resizing | +| `key-press` | `0.08` | `Motion.keyPress` | a key lighting | +| `landing` | `0.6` | `Motion.landing` | the glint when the words land | +| `mood` | `0.8` | `Motion.mood` | the orb's colour moving between moods | +| `press` | `0.1` | `Motion.press` | the orb's press; the one thing that answers at once | +| `ring-period` | `1.6` | `Motion.ringPeriod` | one turn of the ring, the Mac's cadence | +| `state-fade` | `0.5` | `Motion.stateFade` | every other change on the key: the ring, a glyph, the dimming | +| `term-swap` | `0.4` | `Motion.termSwap` | the voice bar becoming the field | +| `wave-fade` | `0.7` | `Motion.waveFade` | the orb and the wave crossing, either way | diff --git a/App/BlurtiOS/Design/figma/tokens.js b/App/BlurtiOS/Design/figma/tokens.js index 162193d3..f9d57fad 100644 --- a/App/BlurtiOS/Design/figma/tokens.js +++ b/App/BlurtiOS/Design/figma/tokens.js @@ -20,79 +20,62 @@ Brand|ink|COLOR|#1D1B16|||DesignTokens.Brand.ink|the brand ink: the Mac pill's b Brand|ink/600|COLOR|#3A362F|||DesignTokens.Brand.ink600|the Mac's dark card border Brand|ink/700|COLOR|#33302A|||DesignTokens.Brand.ink700|an ordinary key on ink, one step up Brand|ink/800|COLOR|#26231E|||DesignTokens.Brand.ink800|a modifier key on ink; the Mac's dark card fill +Brand|neutral/300|COLOR|#D2D1D0|||DesignTokens.Brand.neutral300|black-100: the lightest warm grey +Brand|neutral/500|COLOR|#A5A4A2|||DesignTokens.Brand.neutral500|black-200: mono labels on the dark face +Brand|neutral/700|COLOR|#777673|||DesignTokens.Brand.neutral700|black-300: muted text and mono labels on the light face +Brand|neutral/900|COLOR|#4A4945|||DesignTokens.Brand.neutral900|black-400: body text on the light face Brand|orange|COLOR|#E67F36|||DesignTokens.Brand.orange|the error word and ring, cancel, the Full Access note; never a red body -Brand|page|COLOR|#FDFCF8|||DesignTokens.Brand.page|the design system's page background (unused on the phone) +Brand|paper/200|COLOR|#ECEBE5|||DesignTokens.Brand.paper200|neutral-100: the light face's surface +Brand|paper/300|COLOR|#DAD7CB|||DesignTokens.Brand.paper300|neutral-200: a modifier key on the light face +Brand|paper/400|COLOR|#C7C3B2|||DesignTokens.Brand.paper400|neutral-300: hairlines and field borders on the light face +Brand|paper/page|COLOR|#FDFCF8|||DesignTokens.Brand.paperPage|the design system's page: the app's light ground +Brand|paper/tint|COLOR|#F5F3EB|||DesignTokens.Brand.paperTint|the warm off-white one step in: light cards, dark legends Brand|violet/iris|COLOR|#887BDD|||DesignTokens.Brand.violetIris|the orb gradient's upper violet stop Brand|violet/lavender|COLOR|#D7D3F4|||DesignTokens.Brand.violetLavender|the orb's lightest violet: its top and the gradient's ends Brand|violet/periwinkle|COLOR|#B0A7E9|||DesignTokens.Brand.violetPeriwinkle|the orb's mid violet: the drop's halo Brand|warm-white|COLOR|#F2EEE6|||DesignTokens.Brand.warmWhite|key legends on ink: warm white on warm ink Brand|white|COLOR|#FFFFFF|||DesignTokens.Brand.white| -Themes|ink/key|COLOR|#33302A|Brand:ink/700||DesignTokens.Themes.inkKey| -Themes|ink/key-modifier|COLOR|#26231E|Brand:ink/800||DesignTokens.Themes.inkKeyModifier| -Themes|ink/legend|COLOR|#F2EEE6|Brand:warm-white||DesignTokens.Themes.inkLegend| -Themes|ink/popup|COLOR|#33302A|Brand:ink/700||DesignTokens.Themes.inkPopup| -Themes|ink/signal|COLOR|#67AD82|Brand:green/400||DesignTokens.Themes.inkSignal| -Themes|ink/surface|COLOR|#1D1B16|Brand:ink||DesignTokens.Themes.inkSurface| -Themes|lavender/key|COLOR|#3F3777|||DesignTokens.Themes.lavenderKey| -Themes|lavender/key-modifier|COLOR|#352E68|||DesignTokens.Themes.lavenderKeyModifier| -Themes|lavender/legend|COLOR|#F1EEFF|||DesignTokens.Themes.lavenderLegend| -Themes|lavender/popup|COLOR|#3F3777|||DesignTokens.Themes.lavenderPopup| -Themes|lavender/signal|COLOR|#67AD82|Brand:green/400||DesignTokens.Themes.lavenderSignal| -Themes|lavender/surface|COLOR|#2C2557|||DesignTokens.Themes.lavenderSurface| -Themes|midnight/key|COLOR|#1D2440|||DesignTokens.Themes.midnightKey| -Themes|midnight/key-modifier|COLOR|#161B33|||DesignTokens.Themes.midnightKeyModifier| -Themes|midnight/legend|COLOR|#E8ECFF|||DesignTokens.Themes.midnightLegend| -Themes|midnight/popup|COLOR|#1D2440|||DesignTokens.Themes.midnightPopup| -Themes|midnight/signal|COLOR|#67AD82|Brand:green/400||DesignTokens.Themes.midnightSignal| -Themes|midnight/surface|COLOR|#0E1220|||DesignTokens.Themes.midnightSurface| -Themes|mint/key|COLOR|#1E3F31|||DesignTokens.Themes.mintKey| -Themes|mint/key-modifier|COLOR|#183429|||DesignTokens.Themes.mintKeyModifier| -Themes|mint/legend|COLOR|#E9F5EE|||DesignTokens.Themes.mintLegend| -Themes|mint/popup|COLOR|#1E3F31|||DesignTokens.Themes.mintPopup| -Themes|mint/signal|COLOR|#67AD82|Brand:green/400||DesignTokens.Themes.mintSignal| -Themes|mint/surface|COLOR|#10231B|||DesignTokens.Themes.mintSurface| -Themes|paper/key|COLOR|#FFFFFF|Brand:white||DesignTokens.Themes.paperKey| -Themes|paper/key-modifier|COLOR|#DEDBDB|Brand:card-border||DesignTokens.Themes.paperKeyModifier| -Themes|paper/legend|COLOR|#1D1B16|Brand:ink||DesignTokens.Themes.paperLegend| -Themes|paper/popup|COLOR|#FFFFFF|Brand:white||DesignTokens.Themes.paperPopup| -Themes|paper/signal|COLOR|#01762F|Brand:green/700||DesignTokens.Themes.paperSignal| -Themes|paper/surface|COLOR|#EBE8E8|Brand:card||DesignTokens.Themes.paperSurface| -Themes|sunset/key|COLOR|#4B2B20|||DesignTokens.Themes.sunsetKey| -Themes|sunset/key-modifier|COLOR|#3B2119|||DesignTokens.Themes.sunsetKeyModifier| -Themes|sunset/legend|COLOR|#FFEFE6|||DesignTokens.Themes.sunsetLegend| -Themes|sunset/popup|COLOR|#4B2B20|||DesignTokens.Themes.sunsetPopup| -Themes|sunset/signal|COLOR|#67AD82|Brand:green/400||DesignTokens.Themes.sunsetSignal| -Themes|sunset/surface|COLOR|#2B1912|||DesignTokens.Themes.sunsetSurface| -Themes|system-dark/key|COLOR|#6B6B6B|Brand:apple/dark-key||DesignTokens.Themes.systemDarkKey| -Themes|system-dark/key-modifier|COLOR|#464646|Brand:apple/dark-modifier||DesignTokens.Themes.systemDarkKeyModifier| -Themes|system-dark/legend|COLOR|#FFFFFF|Brand:white||DesignTokens.Themes.systemDarkLegend| -Themes|system-dark/popup|COLOR|#6B6B6B|Brand:apple/dark-key||DesignTokens.Themes.systemDarkPopup| -Themes|system-dark/signal|COLOR|#67AD82|Brand:green/400||DesignTokens.Themes.systemDarkSignal| -Themes|system-dark/surface|COLOR|#2B2B2B|Brand:apple/dark-surface||DesignTokens.Themes.systemDarkSurface| -Themes|system-light/key|COLOR|#FFFFFF|Brand:white||DesignTokens.Themes.systemLightKey| -Themes|system-light/key-modifier|COLOR|#ADB3BC|Brand:apple/light-modifier||DesignTokens.Themes.systemLightKeyModifier| -Themes|system-light/legend|COLOR|#000000|Brand:black||DesignTokens.Themes.systemLightLegend| -Themes|system-light/popup|COLOR|#FFFFFF|Brand:white||DesignTokens.Themes.systemLightPopup| -Themes|system-light/signal|COLOR|#01762F|Brand:green/700||DesignTokens.Themes.systemLightSignal| -Themes|system-light/surface|COLOR|#D1D5DB|Brand:apple/light-surface||DesignTokens.Themes.systemLightSurface| +Themes|dark/field|COLOR|#33302A|Brand:ink/700||DesignTokens.Themes.darkField| +Themes|dark/field-border|COLOR|#3A362F|Brand:ink/600||DesignTokens.Themes.darkFieldBorder| +Themes|dark/key|COLOR|#33302A|Brand:ink/700||DesignTokens.Themes.darkKey| +Themes|dark/key-modifier|COLOR|#26231E|Brand:ink/800||DesignTokens.Themes.darkKeyModifier| +Themes|dark/legend|COLOR|#F5F3EB|Brand:paper/tint||DesignTokens.Themes.darkLegend| +Themes|dark/legend-secondary|COLOR|#A5A4A2|Brand:neutral/500||DesignTokens.Themes.darkLegendSecondary| +Themes|dark/notice|COLOR|#E67F36|Brand:orange||DesignTokens.Themes.darkNotice| +Themes|dark/popup|COLOR|#33302A|Brand:ink/700||DesignTokens.Themes.darkPopup| +Themes|dark/signal|COLOR|#67AD82|Brand:green/400||DesignTokens.Themes.darkSignal| +Themes|dark/surface|COLOR|#1D1B16|Brand:ink||DesignTokens.Themes.darkSurface| +Themes|light/field|COLOR|#FFFFFF|Brand:white||DesignTokens.Themes.lightField| +Themes|light/field-border|COLOR|#C7C3B2|Brand:paper/400||DesignTokens.Themes.lightFieldBorder| +Themes|light/key|COLOR|#FFFFFF|Brand:white||DesignTokens.Themes.lightKey| +Themes|light/key-modifier|COLOR|#DAD7CB|Brand:paper/300||DesignTokens.Themes.lightKeyModifier| +Themes|light/legend|COLOR|#1D1B16|Brand:ink||DesignTokens.Themes.lightLegend| +Themes|light/legend-secondary|COLOR|#777673|Brand:neutral/700||DesignTokens.Themes.lightLegendSecondary| +Themes|light/notice|COLOR|#E67F36|Brand:orange||DesignTokens.Themes.lightNotice| +Themes|light/popup|COLOR|#FFFFFF|Brand:white||DesignTokens.Themes.lightPopup| +Themes|light/signal|COLOR|#01762F|Brand:green/700||DesignTokens.Themes.lightSignal| +Themes|light/surface|COLOR|#ECEBE5|Brand:paper/200||DesignTokens.Themes.lightSurface| Keyboard|app/accent-dark|COLOR|#67AD82|Brand:green/400|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.appAccentDark|the catalog's AccentColor in dark Keyboard|app/accent-light|COLOR|#01762F|Brand:green/700|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.appAccentLight|the catalog's AccentColor in light Keyboard|app/card-border-dark|COLOR|#3A362F|Brand:ink/600|STROKE_COLOR|DesignTokens.Keyboard.appCardBorderDark|the catalog's CardBorder in dark -Keyboard|app/card-border-light|COLOR|#DEDBDB|Brand:card-border|STROKE_COLOR|DesignTokens.Keyboard.appCardBorderLight|the catalog's CardBorder in light +Keyboard|app/card-border-light|COLOR|#C7C3B2|Brand:paper/400|STROKE_COLOR|DesignTokens.Keyboard.appCardBorderLight|the catalog's CardBorder in light Keyboard|app/card-fill-dark|COLOR|#26231E|Brand:ink/800|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.appCardFillDark|the catalog's CardFill in dark -Keyboard|app/card-fill-light|COLOR|#EBE8E8|Brand:card|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.appCardFillLight|the catalog's CardFill in light +Keyboard|app/card-fill-light|COLOR|#F5F3EB|Brand:paper/tint|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.appCardFillLight|the catalog's CardFill in light Keyboard|kb/cancel|COLOR|#E67F36|Brand:orange|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.kbCancel|the panel's cancel × +Keyboard|kb/field|COLOR|#33302A|Themes:dark/field|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.kbField|the key-term field +Keyboard|kb/field-border|COLOR|#3A362F|Themes:dark/field-border|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.kbFieldBorder|the field's hairline Keyboard|kb/full-access-note|COLOR|#E67F36|Brand:orange|TEXT_FILL|DesignTokens.Keyboard.kbFullAccessNote|the one line of words the keyboard ever shows -Keyboard|kb/key|COLOR|#33302A|Themes:ink/key|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.kbKey|an ordinary key -Keyboard|kb/key-modifier|COLOR|#26231E|Themes:ink/key-modifier|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.kbKeyModifier|shift, delete, globe, return, 123, cancel -Keyboard|kb/legend|COLOR|#F2EEE6|Themes:ink/legend|TEXT_FILL|DesignTokens.Keyboard.kbLegend|key legends and bare glyphs +Keyboard|kb/key|COLOR|#33302A|Themes:dark/key|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.kbKey|an ordinary key +Keyboard|kb/key-modifier|COLOR|#26231E|Themes:dark/key-modifier|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.kbKeyModifier|shift, delete, globe, return, 123, cancel +Keyboard|kb/legend|COLOR|#F5F3EB|Themes:dark/legend|TEXT_FILL|DesignTokens.Keyboard.kbLegend|key legends and bare glyphs +Keyboard|kb/legend-secondary|COLOR|#A5A4A2|Themes:dark/legend-secondary|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.kbLegendSecondary|the mono word labels (123, ABC, return, space) and the + at rest Keyboard|kb/notice-error|COLOR|#E67F36|Brand:orange|STROKE_COLOR|DesignTokens.Keyboard.kbNoticeError|the solid ring and glyph for an error Keyboard|kb/notice-ok|COLOR|#67AD82|Brand:green/400|STROKE_COLOR|DesignTokens.Keyboard.kbNoticeOk|the solid ring for pasted and copied Keyboard|kb/orb-ring-end|COLOR|#FFFFFF|Brand:white|STROKE_COLOR|DesignTokens.Keyboard.kbOrbRingEnd|the sweeping ring's gradient, bottom-trailing Keyboard|kb/orb-ring-start|COLOR|#01762F|Brand:green/700|STROKE_COLOR|DesignTokens.Keyboard.kbOrbRingStart|the sweeping ring's gradient, top-leading -Keyboard|kb/popup|COLOR|#33302A|Themes:ink/popup|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.kbPopup|the letter pop-up -Keyboard|kb/signal|COLOR|#67AD82|Themes:ink/signal|SHAPE_FILL,TEXT_FILL|DesignTokens.Keyboard.kbSignal|the wave, the caret, the saved check -Keyboard|kb/surface|COLOR|#1D1B16|Themes:ink/surface|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.kbSurface|the design theme's surface (Figma binds to kb/*; Swift reads the palette) +Keyboard|kb/popup|COLOR|#33302A|Themes:dark/popup|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.kbPopup|the letter pop-up +Keyboard|kb/signal|COLOR|#67AD82|Themes:dark/signal|SHAPE_FILL,TEXT_FILL|DesignTokens.Keyboard.kbSignal|the wave, the caret, the saved check +Keyboard|kb/surface|COLOR|#1D1B16|Themes:dark/surface|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.kbSurface|the design face's surface (Figma binds to kb/*; Swift reads the palette) Metrics|addterm/inset|FLOAT|6||GAP|DesignTokens.Metrics.addtermInset|the + from the panel's corner Metrics|card/border|FLOAT|1||STROKE_FLOAT,WIDTH_HEIGHT|DesignTokens.Metrics.cardBorder|the card's hairline Metrics|card/radius|FLOAT|16||CORNER_RADIUS|DesignTokens.Metrics.cardRadius|the app's cards @@ -173,31 +156,52 @@ Metrics|wave/panel-height|FLOAT|40||WIDTH_HEIGHT|DesignTokens.Metrics.wavePanelH Metrics|wave/panel-width|FLOAT|300||WIDTH_HEIGHT|DesignTokens.Metrics.wavePanelWidth| Metrics|wordmark/height|FLOAT|22||WIDTH_HEIGHT|DesignTokens.Metrics.wordmarkHeight| Typography|ratio/orb-glyph|FLOAT|0.34|||DesignTokens.Typography.ratioOrbGlyph|the clipboard and exclamation glyphs, as a fraction of the orb +Typography|size/body|FLOAT|16||FONT_SIZE|DesignTokens.Typography.sizeBody|the app's body text +Typography|size/caption|FLOAT|14||FONT_SIZE|DesignTokens.Typography.sizeCaption|the app's small text +Typography|size/cta|FLOAT|14||FONT_SIZE|DesignTokens.Typography.sizeCta|a mono button label in the app (E2) +Typography|size/eyebrow|FLOAT|12||FONT_SIZE|DesignTokens.Typography.sizeEyebrow|a mono eyebrow in the app (E1) Typography|size/glyph|FLOAT|17||FONT_SIZE|DesignTokens.Typography.sizeGlyph|the +, × and ✓ +Typography|size/label|FLOAT|12||FONT_SIZE|DesignTokens.Typography.sizeLabel|the mono word labels on keys: 123, ABC, #+=, space, the return label Typography|size/legend|FLOAT|16||FONT_SIZE|DesignTokens.Typography.sizeLegend|every other key Typography|size/letter|FLOAT|22||FONT_SIZE|DesignTokens.Typography.sizeLetter|letter keys Typography|size/popup|FLOAT|32||FONT_SIZE|DesignTokens.Typography.sizePopup|the letter pop-up Typography|size/term|FLOAT|17||FONT_SIZE|DesignTokens.Typography.sizeTerm|the key-term field +Typography|size/title|FLOAT|34||FONT_SIZE|DesignTokens.Typography.sizeTitle|the app's serif headline +Typography|tracking/cta|FLOAT|1.4||LETTER_SPACING|DesignTokens.Typography.trackingCta|uppercase mono at 14: the brand's E2 tracking +Typography|tracking/eyebrow|FLOAT|1.2||LETTER_SPACING|DesignTokens.Typography.trackingEyebrow|uppercase mono at 12: the brand's E1 tracking Typography|weight/glyph|STRING|medium||FONT_STYLE|DesignTokens.Typography.weightGlyph| +Typography|weight/label|STRING|medium||FONT_STYLE|DesignTokens.Typography.weightLabel| Typography|weight/legend|STRING|medium||FONT_STYLE|DesignTokens.Typography.weightLegend| Typography|weight/letter|STRING|regular||FONT_STYLE|DesignTokens.Typography.weightLetter| Typography|weight/orb-glyph|STRING|semibold||FONT_STYLE|DesignTokens.Typography.weightOrbGlyph| Typography|weight/popup|STRING|regular||FONT_STYLE|DesignTokens.Typography.weightPopup| Typography|weight/term|STRING|regular||FONT_STYLE|DesignTokens.Typography.weightTerm| Motion|caret|FLOAT|0.5|||DesignTokens.Motion.caret|the caret's blink +Motion|colour|FLOAT|0.2|||DesignTokens.Motion.colour|a colour or fill changing state: the brand's transition Motion|drop|FLOAT|2.4|||DesignTokens.Motion.drop|the violet drop is gone by Motion|drop-hold|FLOAT|0.9|||DesignTokens.Motion.dropHold|and held to Motion|drop-rise|FLOAT|0.5|||DesignTokens.Motion.dropRise|the drop is up in Motion|drop-spread|FLOAT|1|||DesignTokens.Motion.dropSpread|the bloom reaches its full spread in +Motion|ease/signature|STRING|0.22,1,0.36,1|||DesignTokens.Motion.easeSignature|the house curve for everything that moves; nothing springs Motion|flip|FLOAT|0.25|||DesignTokens.Motion.flip|the panel's carousel Motion|height-change|FLOAT|0.25|||DesignTokens.Motion.heightChange|the keyboard resizing Motion|key-press|FLOAT|0.08|||DesignTokens.Motion.keyPress|a key lighting +Motion|landing|FLOAT|0.6|||DesignTokens.Motion.landing|the glint when the words land Motion|mood|FLOAT|0.8|||DesignTokens.Motion.mood|the orb's colour moving between moods Motion|press|FLOAT|0.1|||DesignTokens.Motion.press|the orb's press; the one thing that answers at once Motion|ring-period|FLOAT|1.6|||DesignTokens.Motion.ringPeriod|one turn of the ring, the Mac's cadence Motion|state-fade|FLOAT|0.5|||DesignTokens.Motion.stateFade|every other change on the key: the ring, a glyph, the dimming Motion|term-swap|FLOAT|0.4|||DesignTokens.Motion.termSwap|the voice bar becoming the field Motion|wave-fade|FLOAT|0.7|||DesignTokens.Motion.waveFade|the orb and the wave crossing, either way +Fonts|body/bold|STRING|UN-11ST-Bold|||DesignTokens.Fonts.bodyBold| +Fonts|body/family|STRING|UN-11 ST||FONT_FAMILY|DesignTokens.Fonts.bodyFamily|the app's body text +Fonts|body/regular|STRING|UN-11ST-Regular|||DesignTokens.Fonts.bodyRegular| +Fonts|heading/family|STRING|Oceanic Text||FONT_FAMILY|DesignTokens.Fonts.headingFamily|the app's serif headlines, sentence case, tight +Fonts|heading/regular|STRING|OceanicText-Regular|||DesignTokens.Fonts.headingRegular| +Fonts|mono/family|STRING|Modern Gothic Mono||FONT_FAMILY|DesignTokens.Fonts.monoFamily|eyebrows, CTAs, the keyboard's word labels +Fonts|mono/light|STRING|ModernGothicMono-Light|||DesignTokens.Fonts.monoLight| +Fonts|mono/medium|STRING|ModernGothicMono-Medium|||DesignTokens.Fonts.monoMedium| +Fonts|mono/regular|STRING|ModernGothicMono-Regular|||DesignTokens.Fonts.monoRegular| GRADIENT|orb|bottom|top|#D7D3F4@0,#B0A7E9@0.0673,#67AD82@0.1442,#01762F@0.3029,#3923C7@0.5962,#887BDD@0.75,#D7D3F4@0.8942,#FFFFFF@1|the Mac orb's fill, the design's own stops (App elements/Recording.svg), swept bottom to top GRADIENT|orb-ring|topLeading|bottomTrailing|#01762F@0,#FFFFFF@1|the ring round the orb: green into white, corner to corner; spun while something is happening`; -const GROUPS = ["Brand", "Themes", "Keyboard", "Metrics", "Typography", "Motion"]; +const GROUPS = ["Brand", "Themes", "Keyboard", "Metrics", "Typography", "Motion", "Fonts"]; diff --git a/App/BlurtiOS/Design/tokens.json b/App/BlurtiOS/Design/tokens.json index 59fc4515..3e091bee 100644 --- a/App/BlurtiOS/Design/tokens.json +++ b/App/BlurtiOS/Design/tokens.json @@ -62,10 +62,6 @@ "value": "#F2EEE6", "use": "key legends on ink: warm white on warm ink" }, - "page": { - "value": "#FDFCF8", - "use": "the design system's page background (unused on the phone)" - }, "card": { "value": "#EBE8E8", "use": "the warm card fill; the paper theme's surface" @@ -103,81 +99,89 @@ "apple/dark-modifier": { "value": "#464646", "use": "the iPhone keyboard's dark modifier key" + }, + "paper/page": { + "value": "#FDFCF8", + "use": "the design system's page: the app's light ground" + }, + "paper/tint": { + "value": "#F5F3EB", + "use": "the warm off-white one step in: light cards, dark legends" + }, + "paper/200": { + "value": "#ECEBE5", + "use": "neutral-100: the light face's surface" + }, + "paper/300": { + "value": "#DAD7CB", + "use": "neutral-200: a modifier key on the light face" + }, + "paper/400": { + "value": "#C7C3B2", + "use": "neutral-300: hairlines and field borders on the light face" + }, + "neutral/900": { + "value": "#4A4945", + "use": "black-400: body text on the light face" + }, + "neutral/700": { + "value": "#777673", + "use": "black-300: muted text and mono labels on the light face" + }, + "neutral/500": { + "value": "#A5A4A2", + "use": "black-200: mono labels on the dark face" + }, + "neutral/300": { + "value": "#D2D1D0", + "use": "black-100: the lightest warm grey" } }, "themes": { - "system-light/surface": "{brand.apple/light-surface}", - "system-light/key": "{brand.white}", - "system-light/key-modifier": "{brand.apple/light-modifier}", - "system-light/legend": "{brand.black}", - "system-light/signal": "{brand.green/700}", - "system-light/popup": "{brand.white}", - "system-dark/surface": "{brand.apple/dark-surface}", - "system-dark/key": "{brand.apple/dark-key}", - "system-dark/key-modifier": "{brand.apple/dark-modifier}", - "system-dark/legend": "{brand.white}", - "system-dark/signal": "{brand.green/400}", - "system-dark/popup": "{brand.apple/dark-key}", - "ink/surface": "{brand.ink}", - "ink/key": "{brand.ink/700}", - "ink/key-modifier": "{brand.ink/800}", - "ink/legend": "{brand.warm-white}", - "ink/signal": "{brand.green/400}", - "ink/popup": "{brand.ink/700}", - "paper/surface": "{brand.card}", - "paper/key": "{brand.white}", - "paper/key-modifier": "{brand.card-border}", - "paper/legend": "{brand.ink}", - "paper/signal": "{brand.green/700}", - "paper/popup": "{brand.white}", - "lavender/surface": "#2C2557", - "lavender/key": "#3F3777", - "lavender/key-modifier": "#352E68", - "lavender/legend": "#F1EEFF", - "lavender/signal": "{brand.green/400}", - "lavender/popup": "#3F3777", - "mint/surface": "#10231B", - "mint/key": "#1E3F31", - "mint/key-modifier": "#183429", - "mint/legend": "#E9F5EE", - "mint/signal": "{brand.green/400}", - "mint/popup": "#1E3F31", - "midnight/surface": "#0E1220", - "midnight/key": "#1D2440", - "midnight/key-modifier": "#161B33", - "midnight/legend": "#E8ECFF", - "midnight/signal": "{brand.green/400}", - "midnight/popup": "#1D2440", - "sunset/surface": "#2B1912", - "sunset/key": "#4B2B20", - "sunset/key-modifier": "#3B2119", - "sunset/legend": "#FFEFE6", - "sunset/signal": "{brand.green/400}", - "sunset/popup": "#4B2B20" + "light/surface": "{brand.paper/200}", + "light/key": "{brand.white}", + "light/key-modifier": "{brand.paper/300}", + "light/legend": "{brand.ink}", + "light/legend-secondary": "{brand.neutral/700}", + "light/signal": "{brand.green/700}", + "light/popup": "{brand.white}", + "light/field": "{brand.white}", + "light/field-border": "{brand.paper/400}", + "light/notice": "{brand.orange}", + "dark/surface": "{brand.ink}", + "dark/key": "{brand.ink/700}", + "dark/key-modifier": "{brand.ink/800}", + "dark/legend": "{brand.paper/tint}", + "dark/legend-secondary": "{brand.neutral/500}", + "dark/signal": "{brand.green/400}", + "dark/popup": "{brand.ink/700}", + "dark/field": "{brand.ink/700}", + "dark/field-border": "{brand.ink/600}", + "dark/notice": "{brand.orange}" }, "keyboard": { "kb/surface": { - "value": "{themes.ink/surface}", - "use": "the design theme's surface (Figma binds to kb/*; Swift reads the palette)" + "value": "{themes.dark/surface}", + "use": "the design face's surface (Figma binds to kb/*; Swift reads the palette)" }, "kb/key": { - "value": "{themes.ink/key}", + "value": "{themes.dark/key}", "use": "an ordinary key" }, "kb/key-modifier": { - "value": "{themes.ink/key-modifier}", + "value": "{themes.dark/key-modifier}", "use": "shift, delete, globe, return, 123, cancel" }, "kb/legend": { - "value": "{themes.ink/legend}", + "value": "{themes.dark/legend}", "use": "key legends and bare glyphs" }, "kb/signal": { - "value": "{themes.ink/signal}", + "value": "{themes.dark/signal}", "use": "the wave, the caret, the saved check" }, "kb/popup": { - "value": "{themes.ink/popup}", + "value": "{themes.dark/popup}", "use": "the letter pop-up" }, "kb/notice-ok": { @@ -213,7 +217,7 @@ "use": "the catalog's AccentColor in dark" }, "app/card-fill-light": { - "value": "{brand.card}", + "value": "{brand.paper/tint}", "use": "the catalog's CardFill in light" }, "app/card-fill-dark": { @@ -221,12 +225,24 @@ "use": "the catalog's CardFill in dark" }, "app/card-border-light": { - "value": "{brand.card-border}", + "value": "{brand.paper/400}", "use": "the catalog's CardBorder in light" }, "app/card-border-dark": { "value": "{brand.ink/600}", "use": "the catalog's CardBorder in dark" + }, + "kb/legend-secondary": { + "value": "{themes.dark/legend-secondary}", + "use": "the mono word labels (123, ABC, return, space) and the + at rest" + }, + "kb/field": { + "value": "{themes.dark/field}", + "use": "the key-term field" + }, + "kb/field-border": { + "value": "{themes.dark/field-border}", + "use": "the field's hairline" } }, "gradients": { @@ -629,6 +645,41 @@ }, "weight/orb-glyph": { "value": "semibold" + }, + "size/label": { + "value": 12, + "use": "the mono word labels on keys: 123, ABC, #+=, space, the return label" + }, + "size/eyebrow": { + "value": 12, + "use": "a mono eyebrow in the app (E1)" + }, + "size/cta": { + "value": 14, + "use": "a mono button label in the app (E2)" + }, + "size/title": { + "value": 34, + "use": "the app's serif headline" + }, + "size/body": { + "value": 16, + "use": "the app's body text" + }, + "size/caption": { + "value": 14, + "use": "the app's small text" + }, + "weight/label": { + "value": "medium" + }, + "tracking/eyebrow": { + "value": 1.2, + "use": "uppercase mono at 12: the brand's E1 tracking" + }, + "tracking/cta": { + "value": 1.4, + "use": "uppercase mono at 14: the brand's E2 tracking" } }, "motion": { @@ -687,6 +738,55 @@ "height-change": { "value": 0.25, "use": "the keyboard resizing" + }, + "colour": { + "value": 0.2, + "use": "a colour or fill changing state: the brand's transition" + }, + "landing": { + "value": 0.6, + "use": "the glint when the words land" + }, + "ease/signature": { + "value": [ + 0.22, + 1, + 0.36, + 1 + ], + "use": "the house curve for everything that moves; nothing springs" + } + }, + "fonts": { + "mono/family": { + "value": "Modern Gothic Mono", + "use": "eyebrows, CTAs, the keyboard's word labels" + }, + "mono/light": { + "value": "ModernGothicMono-Light" + }, + "mono/regular": { + "value": "ModernGothicMono-Regular" + }, + "mono/medium": { + "value": "ModernGothicMono-Medium" + }, + "heading/family": { + "value": "Oceanic Text", + "use": "the app's serif headlines, sentence case, tight" + }, + "heading/regular": { + "value": "OceanicText-Regular" + }, + "body/family": { + "value": "UN-11 ST", + "use": "the app's body text" + }, + "body/regular": { + "value": "UN-11ST-Regular" + }, + "body/bold": { + "value": "UN-11ST-Bold" } } } diff --git a/App/BlurtiOS/Shared/DesignTokens.swift b/App/BlurtiOS/Shared/DesignTokens.swift index bf57b8d0..4cd847c7 100644 --- a/App/BlurtiOS/Shared/DesignTokens.swift +++ b/App/BlurtiOS/Shared/DesignTokens.swift @@ -47,10 +47,26 @@ enum DesignTokens { nonisolated static let ink700: Color = Color(hex: 0x33302A) /// A modifier key on ink; the Mac's dark card fill. nonisolated static let ink800: Color = Color(hex: 0x26231E) + /// Black-100: the lightest warm grey. + nonisolated static let neutral300: Color = Color(hex: 0xD2D1D0) + /// Black-200: mono labels on the dark face. + nonisolated static let neutral500: Color = Color(hex: 0xA5A4A2) + /// Black-300: muted text and mono labels on the light face. + nonisolated static let neutral700: Color = Color(hex: 0x777673) + /// Black-400: body text on the light face. + nonisolated static let neutral900: Color = Color(hex: 0x4A4945) /// The error word and ring, cancel, the Full Access note; never a red body. nonisolated static let orange: Color = Color(hex: 0xE67F36) - /// The design system's page background (unused on the phone). - nonisolated static let page: Color = Color(hex: 0xFDFCF8) + /// Neutral-100: the light face's surface. + nonisolated static let paper200: Color = Color(hex: 0xECEBE5) + /// Neutral-200: a modifier key on the light face. + nonisolated static let paper300: Color = Color(hex: 0xDAD7CB) + /// Neutral-300: hairlines and field borders on the light face. + nonisolated static let paper400: Color = Color(hex: 0xC7C3B2) + /// The design system's page: the app's light ground. + nonisolated static let paperPage: Color = Color(hex: 0xFDFCF8) + /// The warm off-white one step in: light cards, dark legends. + nonisolated static let paperTint: Color = Color(hex: 0xF5F3EB) /// The orb gradient's upper violet stop. nonisolated static let violetIris: Color = Color(hex: 0x887BDD) /// The orb's lightest violet: its top and the gradient's ends. @@ -64,81 +80,45 @@ enum DesignTokens { enum Themes { /// `brand.ink/700`. - nonisolated static let inkKey: Color = Brand.ink700 + nonisolated static let darkField: Color = Brand.ink700 + /// `brand.ink/600`. + nonisolated static let darkFieldBorder: Color = Brand.ink600 + /// `brand.ink/700`. + nonisolated static let darkKey: Color = Brand.ink700 /// `brand.ink/800`. - nonisolated static let inkKeyModifier: Color = Brand.ink800 - /// `brand.warm-white`. - nonisolated static let inkLegend: Color = Brand.warmWhite + nonisolated static let darkKeyModifier: Color = Brand.ink800 + /// `brand.paper/tint`. + nonisolated static let darkLegend: Color = Brand.paperTint + /// `brand.neutral/500`. + nonisolated static let darkLegendSecondary: Color = Brand.neutral500 + /// `brand.orange`. + nonisolated static let darkNotice: Color = Brand.orange /// `brand.ink/700`. - nonisolated static let inkPopup: Color = Brand.ink700 + nonisolated static let darkPopup: Color = Brand.ink700 /// `brand.green/400`. - nonisolated static let inkSignal: Color = Brand.green400 + nonisolated static let darkSignal: Color = Brand.green400 /// `brand.ink`. - nonisolated static let inkSurface: Color = Brand.ink - nonisolated static let lavenderKey: Color = Color(hex: 0x3F3777) - nonisolated static let lavenderKeyModifier: Color = Color(hex: 0x352E68) - nonisolated static let lavenderLegend: Color = Color(hex: 0xF1EEFF) - nonisolated static let lavenderPopup: Color = Color(hex: 0x3F3777) - /// `brand.green/400`. - nonisolated static let lavenderSignal: Color = Brand.green400 - nonisolated static let lavenderSurface: Color = Color(hex: 0x2C2557) - nonisolated static let midnightKey: Color = Color(hex: 0x1D2440) - nonisolated static let midnightKeyModifier: Color = Color(hex: 0x161B33) - nonisolated static let midnightLegend: Color = Color(hex: 0xE8ECFF) - nonisolated static let midnightPopup: Color = Color(hex: 0x1D2440) - /// `brand.green/400`. - nonisolated static let midnightSignal: Color = Brand.green400 - nonisolated static let midnightSurface: Color = Color(hex: 0x0E1220) - nonisolated static let mintKey: Color = Color(hex: 0x1E3F31) - nonisolated static let mintKeyModifier: Color = Color(hex: 0x183429) - nonisolated static let mintLegend: Color = Color(hex: 0xE9F5EE) - nonisolated static let mintPopup: Color = Color(hex: 0x1E3F31) - /// `brand.green/400`. - nonisolated static let mintSignal: Color = Brand.green400 - nonisolated static let mintSurface: Color = Color(hex: 0x10231B) - /// `brand.white`. - nonisolated static let paperKey: Color = Brand.white - /// `brand.card-border`. - nonisolated static let paperKeyModifier: Color = Brand.cardBorder - /// `brand.ink`. - nonisolated static let paperLegend: Color = Brand.ink - /// `brand.white`. - nonisolated static let paperPopup: Color = Brand.white - /// `brand.green/700`. - nonisolated static let paperSignal: Color = Brand.green700 - /// `brand.card`. - nonisolated static let paperSurface: Color = Brand.card - nonisolated static let sunsetKey: Color = Color(hex: 0x4B2B20) - nonisolated static let sunsetKeyModifier: Color = Color(hex: 0x3B2119) - nonisolated static let sunsetLegend: Color = Color(hex: 0xFFEFE6) - nonisolated static let sunsetPopup: Color = Color(hex: 0x4B2B20) - /// `brand.green/400`. - nonisolated static let sunsetSignal: Color = Brand.green400 - nonisolated static let sunsetSurface: Color = Color(hex: 0x2B1912) - /// `brand.apple/dark-key`. - nonisolated static let systemDarkKey: Color = Brand.appleDarkKey - /// `brand.apple/dark-modifier`. - nonisolated static let systemDarkKeyModifier: Color = Brand.appleDarkModifier + nonisolated static let darkSurface: Color = Brand.ink /// `brand.white`. - nonisolated static let systemDarkLegend: Color = Brand.white - /// `brand.apple/dark-key`. - nonisolated static let systemDarkPopup: Color = Brand.appleDarkKey - /// `brand.green/400`. - nonisolated static let systemDarkSignal: Color = Brand.green400 - /// `brand.apple/dark-surface`. - nonisolated static let systemDarkSurface: Color = Brand.appleDarkSurface + nonisolated static let lightField: Color = Brand.white + /// `brand.paper/400`. + nonisolated static let lightFieldBorder: Color = Brand.paper400 /// `brand.white`. - nonisolated static let systemLightKey: Color = Brand.white - /// `brand.apple/light-modifier`. - nonisolated static let systemLightKeyModifier: Color = Brand.appleLightModifier - /// `brand.black`. - nonisolated static let systemLightLegend: Color = Brand.black + nonisolated static let lightKey: Color = Brand.white + /// `brand.paper/300`. + nonisolated static let lightKeyModifier: Color = Brand.paper300 + /// `brand.ink`. + nonisolated static let lightLegend: Color = Brand.ink + /// `brand.neutral/700`. + nonisolated static let lightLegendSecondary: Color = Brand.neutral700 + /// `brand.orange`. + nonisolated static let lightNotice: Color = Brand.orange /// `brand.white`. - nonisolated static let systemLightPopup: Color = Brand.white + nonisolated static let lightPopup: Color = Brand.white /// `brand.green/700`. - nonisolated static let systemLightSignal: Color = Brand.green700 - /// `brand.apple/light-surface`. - nonisolated static let systemLightSurface: Color = Brand.appleLightSurface + nonisolated static let lightSignal: Color = Brand.green700 + /// `brand.paper/200`. + nonisolated static let lightSurface: Color = Brand.paper200 } enum Keyboard { @@ -149,21 +129,27 @@ enum DesignTokens { /// The catalog's CardBorder in dark. nonisolated static let appCardBorderDark: Color = Brand.ink600 /// The catalog's CardBorder in light. - nonisolated static let appCardBorderLight: Color = Brand.cardBorder + nonisolated static let appCardBorderLight: Color = Brand.paper400 /// The catalog's CardFill in dark. nonisolated static let appCardFillDark: Color = Brand.ink800 /// The catalog's CardFill in light. - nonisolated static let appCardFillLight: Color = Brand.card + nonisolated static let appCardFillLight: Color = Brand.paperTint /// The panel's cancel ×. nonisolated static let kbCancel: Color = Brand.orange + /// The key-term field. + nonisolated static let kbField: Color = Themes.darkField + /// The field's hairline. + nonisolated static let kbFieldBorder: Color = Themes.darkFieldBorder /// The one line of words the keyboard ever shows. nonisolated static let kbFullAccessNote: Color = Brand.orange /// An ordinary key. - nonisolated static let kbKey: Color = Themes.inkKey + nonisolated static let kbKey: Color = Themes.darkKey /// Shift, delete, globe, return, 123, cancel. - nonisolated static let kbKeyModifier: Color = Themes.inkKeyModifier + nonisolated static let kbKeyModifier: Color = Themes.darkKeyModifier /// Key legends and bare glyphs. - nonisolated static let kbLegend: Color = Themes.inkLegend + nonisolated static let kbLegend: Color = Themes.darkLegend + /// The mono word labels (123, ABC, return, space) and the + at rest. + nonisolated static let kbLegendSecondary: Color = Themes.darkLegendSecondary /// The solid ring and glyph for an error. nonisolated static let kbNoticeError: Color = Brand.orange /// The solid ring for pasted and copied. @@ -173,11 +159,11 @@ enum DesignTokens { /// The sweeping ring's gradient, top-leading. nonisolated static let kbOrbRingStart: Color = Brand.green700 /// The letter pop-up. - nonisolated static let kbPopup: Color = Themes.inkPopup + nonisolated static let kbPopup: Color = Themes.darkPopup /// The wave, the caret, the saved check. - nonisolated static let kbSignal: Color = Themes.inkSignal - /// The design theme's surface (Figma binds to kb/*; Swift reads the palette). - nonisolated static let kbSurface: Color = Themes.inkSurface + nonisolated static let kbSignal: Color = Themes.darkSignal + /// The design face's surface (Figma binds to kb/*; Swift reads the palette). + nonisolated static let kbSurface: Color = Themes.darkSurface } enum Metrics { @@ -328,8 +314,18 @@ enum DesignTokens { enum Typography { /// The clipboard and exclamation glyphs, as a fraction of the orb. nonisolated static let ratioOrbGlyph: CGFloat = 0.34 + /// The app's body text. + nonisolated static let sizeBody: CGFloat = 16 + /// The app's small text. + nonisolated static let sizeCaption: CGFloat = 14 + /// A mono button label in the app (E2). + nonisolated static let sizeCta: CGFloat = 14 + /// A mono eyebrow in the app (E1). + nonisolated static let sizeEyebrow: CGFloat = 12 /// The +, × and ✓. nonisolated static let sizeGlyph: CGFloat = 17 + /// The mono word labels on keys: 123, ABC, #+=, space, the return label. + nonisolated static let sizeLabel: CGFloat = 12 /// Every other key. nonisolated static let sizeLegend: CGFloat = 16 /// Letter keys. @@ -338,7 +334,14 @@ enum DesignTokens { nonisolated static let sizePopup: CGFloat = 32 /// The key-term field. nonisolated static let sizeTerm: CGFloat = 17 + /// The app's serif headline. + nonisolated static let sizeTitle: CGFloat = 34 + /// Uppercase mono at 14: the brand's E2 tracking. + nonisolated static let trackingCta: CGFloat = 1.4 + /// Uppercase mono at 12: the brand's E1 tracking. + nonisolated static let trackingEyebrow: CGFloat = 1.2 nonisolated static let weightGlyph: Font.Weight = .medium + nonisolated static let weightLabel: Font.Weight = .medium nonisolated static let weightLegend: Font.Weight = .medium nonisolated static let weightLetter: Font.Weight = .regular nonisolated static let weightOrbGlyph: Font.Weight = .semibold @@ -349,6 +352,8 @@ enum DesignTokens { enum Motion { /// The caret's blink. nonisolated static let caret: Double = 0.5 + /// A colour or fill changing state: the brand's transition. + nonisolated static let colour: Double = 0.2 /// The violet drop is gone by. nonisolated static let drop: Double = 2.4 /// And held to. @@ -357,12 +362,17 @@ enum DesignTokens { nonisolated static let dropRise: Double = 0.5 /// The bloom reaches its full spread in. nonisolated static let dropSpread: Double = 1 + /// The house curve for everything that moves; nothing springs. + nonisolated static let easeSignature: UnitCurve = UnitCurve.bezier( + startControlPoint: UnitPoint(x: 0.22, y: 1), endControlPoint: UnitPoint(x: 0.36, y: 1)) /// The panel's carousel. nonisolated static let flip: Double = 0.25 /// The keyboard resizing. nonisolated static let heightChange: Double = 0.25 /// A key lighting. nonisolated static let keyPress: Double = 0.08 + /// The glint when the words land. + nonisolated static let landing: Double = 0.6 /// The orb's colour moving between moods. nonisolated static let mood: Double = 0.8 /// The orb's press; the one thing that answers at once. @@ -377,6 +387,21 @@ enum DesignTokens { nonisolated static let waveFade: Double = 0.7 } + enum Fonts { + nonisolated static let bodyBold: String = "UN-11ST-Bold" + /// The app's body text. + nonisolated static let bodyFamily: String = "UN-11 ST" + nonisolated static let bodyRegular: String = "UN-11ST-Regular" + /// The app's serif headlines, sentence case, tight. + nonisolated static let headingFamily: String = "Oceanic Text" + nonisolated static let headingRegular: String = "OceanicText-Regular" + /// Eyebrows, CTAs, the keyboard's word labels. + nonisolated static let monoFamily: String = "Modern Gothic Mono" + nonisolated static let monoLight: String = "ModernGothicMono-Light" + nonisolated static let monoMedium: String = "ModernGothicMono-Medium" + nonisolated static let monoRegular: String = "ModernGothicMono-Regular" + } + enum Gradients { /// The Mac orb's fill, the design's own stops (App elements/Recording.svg), swept bottom to top. nonisolated static let orb = LinearGradient( @@ -421,72 +446,55 @@ enum DesignTokens { "brand.ink/600": "#3A362F", "brand.ink/700": "#33302A", "brand.ink/800": "#26231E", + "brand.neutral/300": "#D2D1D0", + "brand.neutral/500": "#A5A4A2", + "brand.neutral/700": "#777673", + "brand.neutral/900": "#4A4945", "brand.orange": "#E67F36", - "brand.page": "#FDFCF8", + "brand.paper/200": "#ECEBE5", + "brand.paper/300": "#DAD7CB", + "brand.paper/400": "#C7C3B2", + "brand.paper/page": "#FDFCF8", + "brand.paper/tint": "#F5F3EB", "brand.violet/iris": "#887BDD", "brand.violet/lavender": "#D7D3F4", "brand.violet/periwinkle": "#B0A7E9", "brand.warm-white": "#F2EEE6", "brand.white": "#FFFFFF", - "themes.ink/key": "#33302A", - "themes.ink/key-modifier": "#26231E", - "themes.ink/legend": "#F2EEE6", - "themes.ink/popup": "#33302A", - "themes.ink/signal": "#67AD82", - "themes.ink/surface": "#1D1B16", - "themes.lavender/key": "#3F3777", - "themes.lavender/key-modifier": "#352E68", - "themes.lavender/legend": "#F1EEFF", - "themes.lavender/popup": "#3F3777", - "themes.lavender/signal": "#67AD82", - "themes.lavender/surface": "#2C2557", - "themes.midnight/key": "#1D2440", - "themes.midnight/key-modifier": "#161B33", - "themes.midnight/legend": "#E8ECFF", - "themes.midnight/popup": "#1D2440", - "themes.midnight/signal": "#67AD82", - "themes.midnight/surface": "#0E1220", - "themes.mint/key": "#1E3F31", - "themes.mint/key-modifier": "#183429", - "themes.mint/legend": "#E9F5EE", - "themes.mint/popup": "#1E3F31", - "themes.mint/signal": "#67AD82", - "themes.mint/surface": "#10231B", - "themes.paper/key": "#FFFFFF", - "themes.paper/key-modifier": "#DEDBDB", - "themes.paper/legend": "#1D1B16", - "themes.paper/popup": "#FFFFFF", - "themes.paper/signal": "#01762F", - "themes.paper/surface": "#EBE8E8", - "themes.sunset/key": "#4B2B20", - "themes.sunset/key-modifier": "#3B2119", - "themes.sunset/legend": "#FFEFE6", - "themes.sunset/popup": "#4B2B20", - "themes.sunset/signal": "#67AD82", - "themes.sunset/surface": "#2B1912", - "themes.system-dark/key": "#6B6B6B", - "themes.system-dark/key-modifier": "#464646", - "themes.system-dark/legend": "#FFFFFF", - "themes.system-dark/popup": "#6B6B6B", - "themes.system-dark/signal": "#67AD82", - "themes.system-dark/surface": "#2B2B2B", - "themes.system-light/key": "#FFFFFF", - "themes.system-light/key-modifier": "#ADB3BC", - "themes.system-light/legend": "#000000", - "themes.system-light/popup": "#FFFFFF", - "themes.system-light/signal": "#01762F", - "themes.system-light/surface": "#D1D5DB", + "themes.dark/field": "#33302A", + "themes.dark/field-border": "#3A362F", + "themes.dark/key": "#33302A", + "themes.dark/key-modifier": "#26231E", + "themes.dark/legend": "#F5F3EB", + "themes.dark/legend-secondary": "#A5A4A2", + "themes.dark/notice": "#E67F36", + "themes.dark/popup": "#33302A", + "themes.dark/signal": "#67AD82", + "themes.dark/surface": "#1D1B16", + "themes.light/field": "#FFFFFF", + "themes.light/field-border": "#C7C3B2", + "themes.light/key": "#FFFFFF", + "themes.light/key-modifier": "#DAD7CB", + "themes.light/legend": "#1D1B16", + "themes.light/legend-secondary": "#777673", + "themes.light/notice": "#E67F36", + "themes.light/popup": "#FFFFFF", + "themes.light/signal": "#01762F", + "themes.light/surface": "#ECEBE5", "keyboard.app/accent-dark": "#67AD82", "keyboard.app/accent-light": "#01762F", "keyboard.app/card-border-dark": "#3A362F", - "keyboard.app/card-border-light": "#DEDBDB", + "keyboard.app/card-border-light": "#C7C3B2", "keyboard.app/card-fill-dark": "#26231E", - "keyboard.app/card-fill-light": "#EBE8E8", + "keyboard.app/card-fill-light": "#F5F3EB", "keyboard.kb/cancel": "#E67F36", + "keyboard.kb/field": "#33302A", + "keyboard.kb/field-border": "#3A362F", "keyboard.kb/full-access-note": "#E67F36", "keyboard.kb/key": "#33302A", "keyboard.kb/key-modifier": "#26231E", - "keyboard.kb/legend": "#F2EEE6", + "keyboard.kb/legend": "#F5F3EB", + "keyboard.kb/legend-secondary": "#A5A4A2", "keyboard.kb/notice-error": "#E67F36", "keyboard.kb/notice-ok": "#67AD82", "keyboard.kb/orb-ring-end": "#FFFFFF", @@ -574,31 +582,52 @@ enum DesignTokens { "metrics.wave/panel-width": "300", "metrics.wordmark/height": "22", "type.ratio/orb-glyph": "0.34", + "type.size/body": "16", + "type.size/caption": "14", + "type.size/cta": "14", + "type.size/eyebrow": "12", "type.size/glyph": "17", + "type.size/label": "12", "type.size/legend": "16", "type.size/letter": "22", "type.size/popup": "32", "type.size/term": "17", + "type.size/title": "34", + "type.tracking/cta": "1.4", + "type.tracking/eyebrow": "1.2", "type.weight/glyph": "medium", + "type.weight/label": "medium", "type.weight/legend": "medium", "type.weight/letter": "regular", "type.weight/orb-glyph": "semibold", "type.weight/popup": "regular", "type.weight/term": "regular", "motion.caret": "0.5", + "motion.colour": "0.2", "motion.drop": "2.4", "motion.drop-hold": "0.9", "motion.drop-rise": "0.5", "motion.drop-spread": "1", + "motion.ease/signature": "0.22,1,0.36,1", "motion.flip": "0.25", "motion.height-change": "0.25", "motion.key-press": "0.08", + "motion.landing": "0.6", "motion.mood": "0.8", "motion.press": "0.1", "motion.ring-period": "1.6", "motion.state-fade": "0.5", "motion.term-swap": "0.4", "motion.wave-fade": "0.7", + "fonts.body/bold": "UN-11ST-Bold", + "fonts.body/family": "UN-11 ST", + "fonts.body/regular": "UN-11ST-Regular", + "fonts.heading/family": "Oceanic Text", + "fonts.heading/regular": "OceanicText-Regular", + "fonts.mono/family": "Modern Gothic Mono", + "fonts.mono/light": "ModernGothicMono-Light", + "fonts.mono/medium": "ModernGothicMono-Medium", + "fonts.mono/regular": "ModernGothicMono-Regular", "gradients.orb": "#D7D3F4@0 #B0A7E9@0.0673 #67AD82@0.1442 #01762F@0.3029 #3923C7@0.5962 #887BDD@0.75 #D7D3F4@0.8942 #FFFFFF@1 bottom>top", "gradients.orb-ring": "#01762F@0 #FFFFFF@1 topLeading>bottomTrailing", diff --git a/scripts/design-capture.sh b/scripts/design-capture.sh index 0a449f27..69395017 100755 --- a/scripts/design-capture.sh +++ b/scripts/design-capture.sh @@ -6,8 +6,8 @@ # -BlurtGalleryBare draws one row with a magenta registration border that # scripts/design-diff.swift crops to. # -# scripts/design-capture.sh # panel × the golden states × three themes -# scripts/design-capture.sh --layout full --states idle,recording,error --themes ink +# scripts/design-capture.sh # panel × the golden states × both faces +# scripts/design-capture.sh --layout full --states idle,recording,error --themes dark # scripts/design-capture.sh --out .build/design/captures --no-build # # Writes /--@3x.png (1206 px wide on iPhone 18 Pro, @@ -20,7 +20,7 @@ cd "$REPO_ROOT" LAYOUT=panel STATES=idle,recording,error,term -THEMES=system,system-dark,ink +THEMES=light,dark OUT="$REPO_ROOT/.build/design/captures" BUILD=1 while [ $# -gt 0 ]; do diff --git a/scripts/design-tokens.swift b/scripts/design-tokens.swift index 7059fe40..885a201d 100755 --- a/scripts/design-tokens.swift +++ b/scripts/design-tokens.swift @@ -51,14 +51,16 @@ enum Value { case color(String) // "#RRGGBB" case number(Double) case word(String) // a font weight + case string(String) // a font name (the `fonts` group) + case curve([Double]) // a cubic-bezier easing: four numbers case alias(String) // "group.name" } struct Token { - let group: String - let name: String - let value: Value - let use: String? + var group: String + var name: String + var value: Value + var use: String? var qualified: String { "\(group).\(name)" } var swiftName: String { camel(name) } @@ -94,6 +96,10 @@ func parseValue(_ raw: Any) -> Value { if let number = raw as? NSNumber, CFGetTypeID(number) != CFBooleanGetTypeID() { return .number(number.doubleValue) } + if let numbers = raw as? [NSNumber] { + guard numbers.count == 4 else { fail("a curve is four numbers, got \(numbers)") } + return .curve(numbers.map(\.doubleValue)) + } guard let string = raw as? String else { fail("a token value must be a string or a number, got \(raw)") } if string.hasPrefix("{"), string.hasSuffix("}") { return .alias(String(string.dropFirst().dropLast())) } if string.hasPrefix("#") { @@ -110,20 +116,24 @@ guard let data = FileManager.default.contents(atPath: tokensURL.path), let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else { fail("could not read \(tokensPath)") } -let groups = ["brand", "themes", "keyboard", "metrics", "type", "motion"] +let groups = ["brand", "themes", "keyboard", "metrics", "type", "motion", "fonts"] var tokens: [Token] = [] var byQualified: [String: Token] = [:] for group in groups { guard let entries = json[group] as? [String: Any] else { fail("tokens.json has no \(group) group") } for name in entries.keys.sorted() { let entry = entries[name]! - let token: Token + var token: Token if let wrapped = entry as? [String: Any] { guard let raw = wrapped["value"] else { fail("\(group).\(name) has no value") } token = Token(group: group, name: name, value: parseValue(raw), use: wrapped["use"] as? String) } else { token = Token(group: group, name: name, value: parseValue(entry), use: nil) } + // A bare word in `fonts` is a font's name, not a weight. + if group == "fonts", case .word(let word) = token.value { + token = Token(group: group, name: name, value: .string(word), use: token.use) + } tokens.append(token) byQualified[token.qualified] = token } @@ -180,6 +190,8 @@ func rendered(_ token: Token) -> String { case .color(let hex): return hex case .number(let number): return format(number) case .word(let word): return word + case .string(let string): return string + case .curve(let numbers): return numbers.map(format).joined(separator: ",") case .alias: fatalError("unreachable") } } @@ -198,6 +210,14 @@ func swiftLiteral(_ token: Token) -> (type: String, literal: String) { case .word(let word): guard weights.contains(word) else { fail("\(token.qualified): \(word) is not a font weight") } return ("Font.Weight", ".\(word)") + case .string(let string): return ("String", "\"\(string)\"") + case .curve(let numbers): + let n = numbers.map(format) + return ( + "UnitCurve", + "UnitCurve.bezier(startControlPoint: UnitPoint(x: \(n[0]), y: \(n[1])), " + + "endControlPoint: UnitPoint(x: \(n[2]), y: \(n[3])))" + ) case .alias(let target): guard let other = byQualified[target] else { fail("\(target) does not exist") } return (swiftLiteral(other).type, "\(typeName(other.group)).\(other.swiftName)") @@ -311,18 +331,16 @@ blocks["brand"] = tokenRows("brand", valueLabel: "Value") blocks["keyboard"] = tokenRows("keyboard", valueLabel: "Value") blocks["metrics"] = tokenRows("metrics", valueLabel: "Points") blocks["type"] = tokenRows("type", valueLabel: "Value") -blocks["motion"] = tokenRows("motion", valueLabel: "Seconds") +blocks["motion"] = tokenRows("motion", valueLabel: "Value") +blocks["fonts"] = tokenRows("fonts", valueLabel: "Value") let themeNames = tokens.filter { $0.group == "themes" }.map { String($0.name.split(separator: "/")[0]) } -let themeOrder = - ["system-light", "system-dark", "ink", "paper", "lavender", "mint", "midnight", "sunset"] - + Set(themeNames).subtracting([ - "system-light", "system-dark", "ink", "paper", "lavender", "mint", "midnight", "sunset", - ]) - .sorted() -let roles = ["surface", "key", "key-modifier", "legend", "signal", "popup"] +let themeOrder = ["light", "dark"] + Set(themeNames).subtracting(["light", "dark"]).sorted() +let roles = [ + "surface", "key", "key-modifier", "legend", "legend-secondary", "signal", "popup", "field", "field-border", "notice", +] blocks["themes"] = table( - ["Theme", "Surface", "Key", "Modifier", "Legend", "Signal", "Pop-up"], + ["Face", "Surface", "Key", "Modifier", "Legend", "Secondary", "Signal", "Pop-up", "Field", "Field border", "Notice"], themeOrder.compactMap { theme -> [String]? in let cells = roles.compactMap { role in byQualified["themes.\(theme)/\(role)"].map { code(rendered($0)) } } guard cells.count == roles.count else { return nil } @@ -446,7 +464,10 @@ func figmaScopes(_ token: Token) -> [String] { case "type": if name.hasPrefix("size/") { return ["FONT_SIZE"] } if name.hasPrefix("weight/") { return ["FONT_STYLE"] } + if name.hasPrefix("tracking/") { return ["LETTER_SPACING"] } return [] + case "fonts": + return name.hasSuffix("/family") ? ["FONT_FAMILY"] : [] default: return [] } } @@ -459,13 +480,7 @@ func figmaJSON() -> String { var lines: [String] = [] for group in groups { for token in tokens where token.group == group { - var value = "" - switch resolve(token).value { - case .color(let hex): value = hex - case .number(let number): value = format(number) - case .word(let word): value = word - case .alias: fatalError("unreachable") - } + let value = rendered(token) let type: String switch resolve(token).value { case .color: type = "COLOR" diff --git a/scripts/ios-record.sh b/scripts/ios-record.sh index 9051fc1c..a492e11b 100755 --- a/scripts/ios-record.sh +++ b/scripts/ios-record.sh @@ -4,8 +4,8 @@ # cycles and cuts one clean loop, cropped to the keyboard, for the review packet # and for the Figma motion page's keyframes (DESIGN.md › Figma). # -# scripts/ios-record.sh # panel, ink → .build/design/loops/panel-ink.mp4 -# scripts/ios-record.sh --layout slimBar --theme system --out ~/Desktop/blurt-review +# scripts/ios-record.sh # panel, dark → .build/design/loops/panel-dark.mp4 +# scripts/ios-record.sh --layout slimBar --theme light --out ~/Desktop/blurt-review # scripts/ios-record.sh --frames 0,0.35,0.7 # also grab stills at these seconds into the loop # # Needs ffmpeg (Brewfile). The crop comes from a still capture of the same @@ -18,7 +18,7 @@ cd "$REPO_ROOT" source "$REPO_ROOT/scripts/ios-lib.sh" LAYOUT=panel -THEME=ink +THEME=dark OUT="$REPO_ROOT/.build/design/loops" FRAMES="" CYCLE=11.7 From b32cc990c69ac0d694d7c3a9bc74fd6ad43510d9 Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Tue, 29 Sep 2026 16:51:13 -0400 Subject: [PATCH 51/79] iOS: measure the iPhone's keyboard, and pin the keys to it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The key tokens were an assumption (34.8 pt letters on a 402 pt row that the root's 3 pt padding had already narrowed to 396). Now they are measured: `scripts/apple-geometry.sh` runs one XCUITest (`BlurtiOSProbe`, its own scheme, never in the app's test run or the periphery scan) that launches the app on `-BlurtProbeField light|dark`, a bare text field that takes the system keyboard, reads every key's frame off it, and screenshots both faces; a new `design-diff.swift measure` command reads the caps off the screenshot — XCUITest reports touch cells, which tile a row with no gaps — and the script writes `Design/apple-geometry.json`. iPhone 18 Pro, iOS 27, 402 pt: caps 33.5 wide and 43 tall, 6 between, 6.5 at the sides, 11 between rows, corners fitted at 8; shift and delete 45.58 with a 13.67 gap to the letters; 123 and the globe 43.33, return two of those and a gap (92.67); a 52 pt band above the keys (where the voice row goes: 8 + 44) and 13 under them; 270 in all. The dark face is identical. The letter legend estimates at 24 from the l glyph. `KeyGeometry` is the arithmetic between the tokens — ten letters and nine gaps across the row, the side keys taking what seven letters leave, the bottom row's widths scaling from the reference width — and the full keyboard draws from it; the first key row starts right under the voice row, as the iPhone's does under its suggestions, and the bottom margin under a key row is the iPhone's 13. `AppleGeometryTests` ties the tokens to the measured file, `DesignTokensTests` the geometry to the tokens. `ios-test.sh` and the probe pass `-collect-test-diagnostics never`: a failing test otherwise spends ten minutes in sysdiagnose on this simulator. Co-Authored-By: Claude Fable 5.1 --- .../Sources/FullKeyboardView.swift | 65 +++--- .../BlurtKeyboard/Sources/KeyGeometry.swift | 38 ++++ .../BlurtKeyboard/Sources/KeyboardViews.swift | 7 +- .../BlurtiOS/Sources/BlurtiOSApp.swift | 4 +- .../BlurtiOS/Sources/KeyboardProbeView.swift | 54 +++++ .../BlurtiOSProbe/AppleKeyboardProbe.swift | 62 +++++ .../BlurtiOSTests/AppleGeometryTests.swift | 77 +++++++ .../BlurtiOSTests/DesignTokensTests.swift | 20 +- .../BlurtiOSTests/FeedAndLayoutTests.swift | 6 +- .../BlurtiOSTests/SharedStateTests.swift | 2 +- App/BlurtiOS/DESIGN.md | 212 +++++++++--------- App/BlurtiOS/Design/apple-geometry.json | 58 +++++ App/BlurtiOS/Design/figma/tokens.js | 26 ++- App/BlurtiOS/Design/tokens.json | 60 +++-- App/BlurtiOS/Shared/DesignTokens.swift | 70 +++--- App/BlurtiOS/Shared/SharedState.swift | 4 +- App/BlurtiOS/project.yml | 33 +++ scripts/apple-geometry.sh | 171 ++++++++++++++ scripts/design-diff.swift | 167 +++++++++++++- scripts/ios-test.sh | 6 +- 20 files changed, 921 insertions(+), 221 deletions(-) create mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/KeyGeometry.swift create mode 100644 App/BlurtiOS/BlurtiOS/Sources/KeyboardProbeView.swift create mode 100644 App/BlurtiOS/BlurtiOSProbe/AppleKeyboardProbe.swift create mode 100644 App/BlurtiOS/BlurtiOSTests/AppleGeometryTests.swift create mode 100644 App/BlurtiOS/Design/apple-geometry.json create mode 100755 scripts/apple-geometry.sh diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift b/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift index 1f0f0d84..bcd191bb 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift @@ -3,8 +3,9 @@ import SwiftUI /// A complete keyboard laid out as the iPhone's own — ten letter keys across /// at one width, the middle row centred, shift and delete flanking the bottom /// letters, then 123 · globe · space · return, at the system keyboard's -/// spacing — with the voice bar where the suggestion bar would be. Every key is 42 pt tall. Letters pop up -/// while pressed, sentences capitalise themselves, a double space ends one. +/// measured spacing (`KeyGeometry`) — with the voice bar where the suggestion +/// bar would be. Letters pop up while pressed, sentences capitalise +/// themselves, a double space ends one. /// No autocorrect or suggestions yet. iOS swaps in its own keyboard for /// password fields, so those never reach here. struct FullKeyboardView: View { @@ -14,38 +15,44 @@ struct FullKeyboardView: View { var body: some View { GeometryReader { geo in - let gap = KeyboardPalette.keyGap - // Ten keys and nine gaps across the row. - let keyWidth = (geo.size.width - 9 * gap) / 10 - // Shift and delete take what seven letters leave, standing a little - // further from them than letters stand from each other. - let sideGap = gap * DesignTokens.Metrics.keySideGapFactor - let sideWidth = (geo.size.width - 7 * keyWidth - 6 * gap - 2 * sideGap) / 2 - VStack(spacing: KeyboardPalette.rowGap) { + // The root has already taken the side margins off; the rest is the row. + let geometry = KeyGeometry(rowWidth: geo.size.width) + let gap = geometry.gap + VStack(spacing: 0) { + // The voice row sits where the system's suggestion bar does, and the + // first key row starts right under it, as the iPhone's does. VoiceBar(model: model) - ForEach(Array(rows.enumerated()), id: \.offset) { index, row in - HStack(spacing: index == 2 ? sideGap : gap) { // literal-ok: the third row carries shift and delete - if index == 2 { modifierKey(width: sideWidth) } // literal-ok: the third row - HStack(spacing: gap) { - ForEach(Array(row), id: \.self) { character in - LetterKey(label: label(for: character), width: keyWidth) { model.type(label(for: character)) } + VStack(spacing: KeyboardPalette.rowGap) { + ForEach(Array(rows.enumerated()), id: \.offset) { index, row in + HStack(spacing: index == 2 ? geometry.sideGap : gap) { // literal-ok: the third row carries shift and delete + if index == 2 { modifierKey(width: geometry.sideWidth) } // literal-ok: the third row + HStack(spacing: gap) { + ForEach(Array(row), id: \.self) { character in + LetterKey(label: label(for: character), width: geometry.letterWidth) { + model.type(label(for: character)) + } + } } + if index == 2 { + KeyCap(systemImage: "delete.left", dark: true, width: geometry.sideWidth) { model.deleteBackward() } + } + } + .frame(maxWidth: .infinity) + } + // The stock bottom row; voice lives only in the bar above. + HStack(spacing: gap) { + KeyCap(title: model.symbolsPage ? "ABC" : "123", dark: true, width: geometry.abcWidth) { + model.toggleSymbols() } - if index == 2 { - KeyCap(systemImage: "delete.left", dark: true, width: sideWidth) { model.deleteBackward() } + if model.needsGlobe { + KeyCap(systemImage: "globe", dark: true, width: geometry.abcWidth) { model.globe() } } + KeyCap(title: "space", flexible: true) { model.space() } + KeyCap( + title: model.returnLabel, systemImage: model.returnLabel == nil ? "return" : nil, dark: true, + width: geometry.returnWidth + ) { model.newline() } } - .frame(maxWidth: .infinity) - } - // The stock bottom row; voice lives only in the bar above. - HStack(spacing: gap) { - KeyCap(title: model.symbolsPage ? "ABC" : "123", dark: true, width: sideWidth) { model.toggleSymbols() } - if model.needsGlobe { KeyCap(systemImage: "globe", dark: true, width: sideWidth) { model.globe() } } - KeyCap(title: "space", flexible: true) { model.space() } - KeyCap( - title: model.returnLabel, systemImage: model.returnLabel == nil ? "return" : nil, dark: true, - width: sideWidth * 2 + gap // literal-ok: return is two modifiers wide - ) { model.newline() } } } } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyGeometry.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyGeometry.swift new file mode 100644 index 00000000..547f9e0f --- /dev/null +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyGeometry.swift @@ -0,0 +1,38 @@ +import CoreGraphics + +/// The full keyboard's widths, the iPhone's own: ten letter caps across at +/// one width, the side keys taking what seven letters and their gaps leave, +/// the bottom row's 123 and globe at the width the iPhone gives them and +/// return two of those wide. The numbers were read off the system keyboard +/// on the iPhone 18 Pro (`Design/apple-geometry.json`, scripts/apple-geometry.sh) +/// and live in the tokens; this is the arithmetic between them, unit-tested, +/// so the views carry none of it. +nonisolated struct KeyGeometry: Equatable { + private typealias Metrics = DesignTokens.Metrics + + /// The width inside the side margins — what a row of keys has. + let rowWidth: CGFloat + + init(rowWidth: CGFloat) { self.rowWidth = rowWidth } + + /// From the keyboard's whole width, margins included. + init(width: CGFloat) { self.init(rowWidth: width - 2 * Metrics.marginSide) } + + var gap: CGFloat { Metrics.keyGap } + /// Ten keys and nine gaps across the row. + var letterWidth: CGFloat { (rowWidth - 9 * gap) / 10 } + /// Shift and delete stand a little further from the letters than letters + /// stand from each other. + var sideGap: CGFloat { Metrics.keySideGap } + var sideWidth: CGFloat { (rowWidth - 7 * letterWidth - 6 * gap - 2 * sideGap) / 2 } + /// The widths measured at the reference width scale with the keyboard. + private var scale: CGFloat { (rowWidth + 2 * Metrics.marginSide) / Metrics.keyReferenceWidth } + /// 123 (or ABC), and the globe when there is one. + var abcWidth: CGFloat { Metrics.keyAbcWidth402 * scale } + /// Return: two 123 keys and a gap. + var returnWidth: CGFloat { 2 * abcWidth + gap } + /// Space takes what the bottom row leaves. + func spaceWidth(globe: Bool) -> CGFloat { + rowWidth - abcWidth - (globe ? abcWidth + gap : 0) - returnWidth - 2 * gap + } +} diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift index 1fa9385a..25324ac0 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift @@ -9,9 +9,11 @@ import SwiftUI struct KeyboardRootView: View { var model: KeyboardModel - /// The keyboard's top and bottom margin: the arithmetic in + /// The keyboard's top margin (and the slim bar's bottom): the arithmetic in /// `KeyboardLayout.height` is built on it and the palette's row gap. static let verticalMargin = DesignTokens.Metrics.marginVertical + /// Under a bottom row of keys, the iPhone's own margin. + static let bottomMarginKeys = DesignTokens.Metrics.marginBottomKeys var body: some View { Group { @@ -28,7 +30,8 @@ struct KeyboardRootView: View { } } .padding(.horizontal, KeyboardPalette.margin) - .padding(.vertical, Self.verticalMargin) + .padding(.top, Self.verticalMargin) + .padding(.bottom, model.effectiveLayout == .slimBar ? Self.verticalMargin : Self.bottomMarginKeys) .frame(maxWidth: .infinity, maxHeight: .infinity) .background { SurfaceFinish.Ground(surface: model.palette.surface) } .overlay { SurfaceFinish.Grain() } diff --git a/App/BlurtiOS/BlurtiOS/Sources/BlurtiOSApp.swift b/App/BlurtiOS/BlurtiOS/Sources/BlurtiOSApp.swift index f56384fd..88a3fd25 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/BlurtiOSApp.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/BlurtiOSApp.swift @@ -39,7 +39,9 @@ struct BlurtiOSApp: App { WindowGroup { #if DEBUG let rows = KeyboardGalleryView.rows(from: CommandLine.arguments) - if let orb = KeyboardGalleryView.OrbStillView.parse(CommandLine.arguments) { + if let probe = KeyboardProbeView.parse(CommandLine.arguments) { + probe + } else if let orb = KeyboardGalleryView.OrbStillView.parse(CommandLine.arguments) { orb } else if rows.isEmpty { home diff --git a/App/BlurtiOS/BlurtiOS/Sources/KeyboardProbeView.swift b/App/BlurtiOS/BlurtiOS/Sources/KeyboardProbeView.swift new file mode 100644 index 00000000..38940e00 --- /dev/null +++ b/App/BlurtiOS/BlurtiOS/Sources/KeyboardProbeView.swift @@ -0,0 +1,54 @@ +#if DEBUG + import SwiftUI + import UIKit + + /// `-BlurtProbeField light|dark`: a bare text field that takes the system + /// keyboard on launch, so the `BlurtiOSProbe` UI test can read that + /// keyboard's geometry off this simulator — the numbers + /// `Design/apple-geometry.json` records and the `key/*` tokens are pinned + /// to (`scripts/apple-geometry.sh`, DESIGN.md › Apple's geometry). Debug + /// builds only; the keyboard itself never runs here. + struct KeyboardProbeView: View { + let dark: Bool + + static func parse(_ arguments: [String]) -> KeyboardProbeView? { + guard let flag = arguments.firstIndex(of: "-BlurtProbeField") else { return nil } + let face = arguments.count > flag + 1 ? arguments[flag + 1] : "light" + guard face == "light" || face == "dark" else { return nil } + return KeyboardProbeView(dark: face == "dark") + } + + var body: some View { + VStack { + ProbeField(dark: dark) + .frame(height: DesignTokens.Metrics.keyMinWidth) + .padding() + Spacer(minLength: 0) + } + .frame(maxWidth: .infinity, maxHeight: .infinity) + .background(dark ? Color.black : Color.white) + } + } + + /// A UIKit field, since `keyboardAppearance` and `autocorrectionType` are + /// what decide which keyboard iOS shows: the appearance picks the face, and + /// autocorrection brings the predictive bar up, which is the band the + /// keyboard's voice row stands in for. + private struct ProbeField: UIViewRepresentable { + let dark: Bool + + func makeUIView(context: Context) -> UITextField { + let field = UITextField() + field.accessibilityIdentifier = "probe-field" + field.keyboardAppearance = dark ? .dark : .light + field.autocorrectionType = .yes + field.autocapitalizationType = .none + field.borderStyle = .roundedRect + field.placeholder = "probe" + DispatchQueue.main.async { field.becomeFirstResponder() } + return field + } + + func updateUIView(_ uiView: UITextField, context: Context) {} + } +#endif diff --git a/App/BlurtiOS/BlurtiOSProbe/AppleKeyboardProbe.swift b/App/BlurtiOS/BlurtiOSProbe/AppleKeyboardProbe.swift new file mode 100644 index 00000000..872ffcf2 --- /dev/null +++ b/App/BlurtiOS/BlurtiOSProbe/AppleKeyboardProbe.swift @@ -0,0 +1,62 @@ +import XCTest + +/// Reads the system keyboard's geometry on this simulator: every key's frame, +/// the keyboard's own, and whatever else sits in it (the predictive bar), on +/// both faces. `scripts/apple-geometry.sh` runs this and turns the attachment +/// into `Design/apple-geometry.json`, which the `key/*` tokens are pinned to. +/// XCTest, because XCUIAutomation needs it (the one exception AGENTS.md makes). +final class AppleKeyboardProbe: XCTestCase { + @MainActor + func testMeasure() throws { + for face in ["light", "dark"] { + let app = XCUIApplication() + app.launchArguments = ["-BlurtProbeField", face] + app.launch() + let keyboard = app.keyboards.firstMatch + XCTAssertTrue( + keyboard.waitForExistence(timeout: 15), + "no on-screen keyboard: turn off 'simulate hardware keyboard' in Device Hub / Simulator") + // Let the predictive bar and the key pop-in settle. + Thread.sleep(forTimeInterval: 1.5) + var out: [String: Any] = [ + "face": face, + "window": rect(app.windows.firstMatch.frame), + "keyboard": rect(keyboard.frame), + ] + var keys: [String: Any] = [:] + for key in keyboard.keys.allElementsBoundByIndex { + let name = key.identifier.isEmpty ? key.label : key.identifier + guard !name.isEmpty, keys[name] == nil else { continue } + keys[name] = rect(key.frame) + } + out["keys"] = keys + var others: [String: Any] = [:] + for element in keyboard.otherElements.allElementsBoundByIndex.prefix(24) { + let name = element.identifier.isEmpty ? element.label : element.identifier + guard !name.isEmpty, others[name] == nil else { continue } + others[name] = rect(element.frame) + } + for element in keyboard.buttons.allElementsBoundByIndex.prefix(24) { + let name = "button:" + (element.identifier.isEmpty ? element.label : element.identifier) + guard others[name] == nil else { continue } + others[name] = rect(element.frame) + } + out["others"] = others + let data = try JSONSerialization.data(withJSONObject: out, options: [.prettyPrinted, .sortedKeys]) + let text = String(decoding: data, as: UTF8.self) + let json = XCTAttachment(string: text) + json.name = "apple-geometry-\(face).json" + json.lifetime = .keepAlways + add(json) + let shot = XCTAttachment(screenshot: app.screenshot()) + shot.name = "apple-keyboard-\(face).png" + shot.lifetime = .keepAlways + add(shot) + app.terminate() + } + } + + private func rect(_ r: CGRect) -> [String: Double] { + ["x": r.minX, "y": r.minY, "w": r.width, "h": r.height] + } +} diff --git a/App/BlurtiOS/BlurtiOSTests/AppleGeometryTests.swift b/App/BlurtiOS/BlurtiOSTests/AppleGeometryTests.swift new file mode 100644 index 00000000..ce973c4a --- /dev/null +++ b/App/BlurtiOS/BlurtiOSTests/AppleGeometryTests.swift @@ -0,0 +1,77 @@ +import Foundation +import Testing + +@testable import BlurtiOS + +/// The key tokens against what scripts/apple-geometry.sh read off the +/// iPhone's own keyboard (`Design/apple-geometry.json`): the design's numbers +/// are Apple's, measured, and a change to either side has to be a decision. +/// Tolerances are the measurement's: pixels come in thirds of a point, the +/// surface's edge is anti-aliased, the radius is a fit. +@Suite("Apple's keyboard geometry") +struct AppleGeometryTests { + private final class BundleToken {} + + private static func measured() throws -> [String: Double] { + let url = try #require(Bundle(for: BundleToken.self).url(forResource: "apple-geometry", withExtension: "json")) + let json = try #require(JSONSerialization.jsonObject(with: Data(contentsOf: url)) as? [String: Any]) + let cap = try #require(json["cap"] as? [String: Any]) + var numbers: [String: Double] = [:] + for (key, value) in cap { + if let number = value as? NSNumber { numbers[key] = number.doubleValue } + } + return numbers + } + + private static func value(_ numbers: [String: Double], _ key: String) throws -> Double { + try #require(numbers[key], "apple-geometry.json has no cap.\(key)") + } + + @Test("the keys are the iPhone's: width, height, gaps, margins, radius") + func keys() throws { + let cap = try Self.measured() + let metrics = DesignTokens.Metrics.self + #expect(abs(try Self.value(cap, "letter") - metrics.keyLetterWidth402) < 0.05) + #expect(try Self.value(cap, "height") == metrics.keyHeight) + #expect(try Self.value(cap, "gap") == metrics.keyGap) + #expect(try Self.value(cap, "rowGap") == metrics.rowGap) + #expect(abs(try Self.value(cap, "marginSide") - metrics.marginSide) < 0.2) + #expect(abs(try Self.value(cap, "radius") - metrics.keyRadius) < 0.5) + #expect(abs(try Self.value(cap, "side") - metrics.keySideWidth402) < 0.1) + #expect(abs(try Self.value(cap, "sideGap") - metrics.keySideGap) < 0.05) + #expect(abs(try Self.value(cap, "abc") - metrics.keyAbcWidth402) < 0.05) + #expect(abs(try Self.value(cap, "return") - metrics.keyReturnWidth402) < 0.5) + #expect(abs(try Self.value(cap, "space") - metrics.keySpaceWidth402) < 0.5) + } + + @Test("the rows are the iPhone's: the band above the keys, the margin under them, the whole height") + func rows() throws { + let cap = try Self.measured() + let metrics = DesignTokens.Metrics.self + #expect(abs(try Self.value(cap, "topBand") - (metrics.marginVertical + metrics.voicebarHeight)) < 1) + #expect(try Self.value(cap, "bottomMargin") == metrics.marginBottomKeys) + #expect(abs(try Self.value(cap, "keyboardHeight") - metrics.layoutFull) < 1) + } + + @Test("the geometry reproduces the measured row at the reference width") + func arithmetic() throws { + let cap = try Self.measured() + let width = DesignTokens.Metrics.keyReferenceWidth + let geometry = KeyGeometry(width: width) + #expect(abs(geometry.letterWidth - (try Self.value(cap, "letter"))) < 0.05) + #expect(abs(geometry.sideWidth - (try Self.value(cap, "side"))) < 0.1) + #expect(abs(geometry.returnWidth - (try Self.value(cap, "return"))) < 0.5) + // The rows add up to the width, margins included. + let margin = DesignTokens.Metrics.marginSide + #expect(abs(10 * geometry.letterWidth + 9 * geometry.gap + 2 * margin - width) < 0.001) + #expect( + abs( + 2 * geometry.sideWidth + 2 * geometry.sideGap + 7 * geometry.letterWidth + 6 * geometry.gap + 2 * margin - width + ) + < 0.001) + #expect( + abs( + 2 * geometry.abcWidth + geometry.spaceWidth(globe: true) + geometry.returnWidth + 3 * geometry.gap + 2 * margin + - width) < 0.001) + } +} diff --git a/App/BlurtiOS/BlurtiOSTests/DesignTokensTests.swift b/App/BlurtiOS/BlurtiOSTests/DesignTokensTests.swift index c1a7b1e1..55bb5195 100644 --- a/App/BlurtiOS/BlurtiOSTests/DesignTokensTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/DesignTokensTests.swift @@ -88,21 +88,21 @@ struct DesignTokensTests { #expect(KeyboardLayout.panel.height == metrics.layoutPanel) #expect( KeyboardLayout.full.height - == 2 * metrics.marginVertical + metrics.voicebarHeight + 4 * metrics.rowGap + 4 * metrics.keyHeight) + == metrics.marginVertical + metrics.voicebarHeight + 4 * metrics.keyHeight + 3 * metrics.rowGap + + metrics.marginBottomKeys) #expect(KeyboardLayout.full.height == metrics.layoutFull) } @Test("the full layout at 402 pt matches the @402 tokens the Figma frames are drawn with") func fullLayoutAt402() { - let width: CGFloat = 402 - let gap = DesignTokens.Metrics.keyGap - // The same arithmetic as FullKeyboardView. - let keyWidth = (width - 9 * gap) / 10 - let sideGap = gap * DesignTokens.Metrics.keySideGapFactor - let sideWidth = (width - 7 * keyWidth - 6 * gap - 2 * sideGap) / 2 - #expect(abs(keyWidth - DesignTokens.Metrics.keyLetterWidth402) < 0.001) - #expect(abs(sideWidth - DesignTokens.Metrics.keySideWidth402) < 0.001) - #expect(abs(sideWidth * 2 + gap - DesignTokens.Metrics.keyReturnWidth402) < 0.001) + // The tokens are written to a thousandth of a point; the row's thirds + // round either way at the last digit. + let geometry = KeyGeometry(width: DesignTokens.Metrics.keyReferenceWidth) + #expect(abs(geometry.letterWidth - DesignTokens.Metrics.keyLetterWidth402) < 0.005) + #expect(abs(geometry.sideWidth - DesignTokens.Metrics.keySideWidth402) < 0.005) + #expect(abs(geometry.abcWidth - DesignTokens.Metrics.keyAbcWidth402) < 0.005) + #expect(abs(geometry.returnWidth - DesignTokens.Metrics.keyReturnWidth402) < 0.005) + #expect(abs(geometry.spaceWidth(globe: true) - DesignTokens.Metrics.keySpaceWidth402) < 0.005) } /// Each face beside the ten theme tokens it must equal, in role order: diff --git a/App/BlurtiOS/BlurtiOSTests/FeedAndLayoutTests.swift b/App/BlurtiOS/BlurtiOSTests/FeedAndLayoutTests.swift index 1e55c709..f915c635 100644 --- a/App/BlurtiOS/BlurtiOSTests/FeedAndLayoutTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/FeedAndLayoutTests.swift @@ -41,7 +41,8 @@ struct LayoutArithmeticTests { @Test("the full layout's height is its rows at the theme spacing (DESIGN.md)") func fullHeight() { let expected = - 2 * KeyboardRootView.verticalMargin + VoiceBar.height + 4 * KeyboardPalette.rowGap + 4 * KeyCap.height + KeyboardRootView.verticalMargin + VoiceBar.height + 4 * KeyCap.height + 3 * KeyboardPalette.rowGap + + KeyboardRootView.bottomMarginKeys #expect(KeyboardLayout.full.height == expected) } @@ -60,7 +61,8 @@ struct LayoutArithmeticTests { #expect(dark[0].model.palette.keyText == DesignTokens.Themes.darkLegend) let ink = KeyboardGalleryView.rows(from: ["app", "-BlurtGallery", "full", "idle", "ink"]) #expect(ink[0].model.palette.face == .dark) - #expect(KeyboardGalleryView.rows(from: ["app", "-BlurtGallery", "full", "idle", "paper"])[0].model.palette.face == .light) + #expect( + KeyboardGalleryView.rows(from: ["app", "-BlurtGallery", "full", "idle", "paper"])[0].model.palette.face == .light) } @Test("the capture switches ride along, and a switch where the theme would be is not a theme") diff --git a/App/BlurtiOS/BlurtiOSTests/SharedStateTests.swift b/App/BlurtiOS/BlurtiOSTests/SharedStateTests.swift index 233206bc..4a830199 100644 --- a/App/BlurtiOS/BlurtiOSTests/SharedStateTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/SharedStateTests.swift @@ -65,7 +65,7 @@ struct LayoutTests { func heights() { #expect(KeyboardLayout.slimBar.height == 60) #expect(KeyboardLayout.panel.height == 216) - #expect(KeyboardLayout.full.height == 272) + #expect(KeyboardLayout.full.height == 270) } @Test("letter rows follow the phone's first language") diff --git a/App/BlurtiOS/DESIGN.md b/App/BlurtiOS/DESIGN.md index c85195b3..aad4487c 100644 --- a/App/BlurtiOS/DESIGN.md +++ b/App/BlurtiOS/DESIGN.md @@ -334,29 +334,29 @@ Inter). Sizes are fixed points, not Dynamic Type, as the system keyboard's are. -| Token | Value | Swift | Use | -| ------------------ | ---------- | ---------------------------- | -------------------------------------------------------------------- | -| `ratio/orb-glyph` | `0.34` | `Typography.ratioOrbGlyph` | the clipboard and exclamation glyphs, as a fraction of the orb | -| `size/body` | `16` | `Typography.sizeBody` | the app's body text | -| `size/caption` | `14` | `Typography.sizeCaption` | the app's small text | -| `size/cta` | `14` | `Typography.sizeCta` | a mono button label in the app (E2) | -| `size/eyebrow` | `12` | `Typography.sizeEyebrow` | a mono eyebrow in the app (E1) | -| `size/glyph` | `17` | `Typography.sizeGlyph` | the +, × and ✓ | -| `size/label` | `12` | `Typography.sizeLabel` | the mono word labels on keys: 123, ABC, #+=, space, the return label | -| `size/legend` | `16` | `Typography.sizeLegend` | every other key | -| `size/letter` | `22` | `Typography.sizeLetter` | letter keys | -| `size/popup` | `32` | `Typography.sizePopup` | the letter pop-up | -| `size/term` | `17` | `Typography.sizeTerm` | the key-term field | -| `size/title` | `34` | `Typography.sizeTitle` | the app's serif headline | -| `tracking/cta` | `1.4` | `Typography.trackingCta` | uppercase mono at 14: the brand's E2 tracking | -| `tracking/eyebrow` | `1.2` | `Typography.trackingEyebrow` | uppercase mono at 12: the brand's E1 tracking | -| `weight/glyph` | `medium` | `Typography.weightGlyph` | — | -| `weight/label` | `medium` | `Typography.weightLabel` | — | -| `weight/legend` | `medium` | `Typography.weightLegend` | — | -| `weight/letter` | `regular` | `Typography.weightLetter` | — | -| `weight/orb-glyph` | `semibold` | `Typography.weightOrbGlyph` | — | -| `weight/popup` | `regular` | `Typography.weightPopup` | — | -| `weight/term` | `regular` | `Typography.weightTerm` | — | +| Token | Value | Swift | Use | +| ------------------ | ---------- | ---------------------------- | --------------------------------------------------------------------------- | +| `ratio/orb-glyph` | `0.34` | `Typography.ratioOrbGlyph` | the clipboard and exclamation glyphs, as a fraction of the orb | +| `size/body` | `16` | `Typography.sizeBody` | the app's body text | +| `size/caption` | `14` | `Typography.sizeCaption` | the app's small text | +| `size/cta` | `14` | `Typography.sizeCta` | a mono button label in the app (E2) | +| `size/eyebrow` | `12` | `Typography.sizeEyebrow` | a mono eyebrow in the app (E1) | +| `size/glyph` | `17` | `Typography.sizeGlyph` | the +, × and ✓ | +| `size/label` | `12` | `Typography.sizeLabel` | the mono word labels on keys: 123, ABC, #+=, space, the return label | +| `size/legend` | `16` | `Typography.sizeLegend` | every other key | +| `size/letter` | `24` | `Typography.sizeLetter` | letter keys: the iPhone's (estimated from the l glyph, apple-geometry.json) | +| `size/popup` | `32` | `Typography.sizePopup` | the letter pop-up | +| `size/term` | `17` | `Typography.sizeTerm` | the key-term field | +| `size/title` | `34` | `Typography.sizeTitle` | the app's serif headline | +| `tracking/cta` | `1.4` | `Typography.trackingCta` | uppercase mono at 14: the brand's E2 tracking | +| `tracking/eyebrow` | `1.2` | `Typography.trackingEyebrow` | uppercase mono at 12: the brand's E1 tracking | +| `weight/glyph` | `medium` | `Typography.weightGlyph` | — | +| `weight/label` | `medium` | `Typography.weightLabel` | — | +| `weight/legend` | `medium` | `Typography.weightLegend` | — | +| `weight/letter` | `regular` | `Typography.weightLetter` | — | +| `weight/orb-glyph` | `semibold` | `Typography.weightOrbGlyph` | — | +| `weight/popup` | `regular` | `Typography.weightPopup` | — | +| `weight/term` | `regular` | `Typography.weightTerm` | — | @@ -459,87 +459,91 @@ derivation. -| Token | Points | Swift | Use | -| ----------------------------- | ------- | ---------------------------------- | ------------------------------------------------------------------------------------------- | -| `addterm/inset` | `6` | `Metrics.addtermInset` | the + from the panel's corner | -| `card/border` | `1` | `Metrics.cardBorder` | the card's hairline | -| `card/radius` | `16` | `Metrics.cardRadius` | the app's cards | -| `caret/height` | `20` | `Metrics.caretHeight` | — | -| `caret/lead` | `1` | `Metrics.caretLead` | the caret's gap from the text | -| `caret/radius` | `1` | `Metrics.caretRadius` | — | -| `caret/width` | `2` | `Metrics.caretWidth` | — | -| `gesture/swipe-min` | `24` | `Metrics.gestureSwipeMin` | the carousel gesture's minimum distance | -| `glyph/hit` | `32` | `Metrics.glyphHit` | the +, × and ✓ touch targets | -| `key/gap` | `6` | `Metrics.keyGap` | between keys, the iPhone's | -| `key/height` | `42` | `Metrics.keyHeight` | every key | -| `key/letter-width-402` | `34.8` | `Metrics.keyLetterWidth402` | a letter key at 402 pt (iPhone 18 Pro): (width − 9 × key/gap) / 10 | -| `key/min-width` | `44` | `Metrics.keyMinWidth` | a key that isn't given a width | -| `key/pad` | `4` | `Metrics.keyPad` | a legend's side padding on a min-width key | -| `key/radius` | `8` | `Metrics.keyRadius` | flat keys, one colour at this corner | -| `key/return-width-402` | `104.4` | `Metrics.keyReturnWidth402` | return at 402 pt: two side keys and a gap | -| `key/side-gap-factor` | `2` | `Metrics.keySideGapFactor` | shift and delete stand this many key gaps from the letters | -| `key/side-width-402` | `49.2` | `Metrics.keySideWidth402` | shift, delete, 123 and globe at 402 pt: what seven letters leave, halved | -| `layout/full` | `272` | `Metrics.layoutFull` | 2 × margin/vertical + voicebar/height + 4 × row/gap + 4 × key/height | -| `layout/panel` | `216` | `Metrics.layoutPanel` | chosen: room for the 96 orb over one key row | -| `layout/slim` | `60` | `Metrics.layoutSlim` | 2 × margin/vertical + voicebar/height | -| `margin/side` | `3` | `Metrics.marginSide` | at the keyboard's sides | -| `margin/vertical` | `8` | `Metrics.marginVertical` | the keyboard's top and bottom | -| `opacity/dim` | `0.8` | `Metrics.opacityDim` | the orb when Blurt isn't ready | -| `opacity/dim-saturation` | `0.35` | `Metrics.opacityDimSaturation` | and its saturation | -| `opacity/disabled` | `0.4` | `Metrics.opacityDisabled` | the + without Full Access | -| `opacity/grain` | `0.5` | `Metrics.opacityGrain` | — | -| `opacity/home-dim-saturation` | `0.45` | `Metrics.opacityHomeDimSaturation` | the home hero's saturation when not listening | -| `opacity/legend` | `1` | `Metrics.opacityLegend` | key legends over the cap; below 1 they sit back | -| `opacity/legend-muted` | `0.5` | `Metrics.opacityLegendMuted` | the + at rest | -| `opacity/orb-light` | `0.3` | `Metrics.opacityOrbLight` | — | -| `opacity/placeholder` | `0.4` | `Metrics.opacityPlaceholder` | the field's placeholder | -| `opacity/popup-shadow` | `0.12` | `Metrics.opacityPopupShadow` | — | -| `opacity/press-brighten` | `0.15` | `Metrics.opacityPressBrighten` | a key lightens this much while pressed | -| `opacity/surface-grain` | `0.14` | `Metrics.opacitySurfaceGrain` | film grain over the whole keyboard surface: matte, the brand's texture | -| `opacity/surface-vignette` | `0` | `Metrics.opacitySurfaceVignette` | a soft darkening toward the surface's edges; 0 is none | -| `opacity/term-cancel` | `0.7` | `Metrics.opacityTermCancel` | the field's × | -| `orb/bar` | `40` | `Metrics.orbBar` | the orb in the voice bar | -| `orb/dissipate-blur` | `0.16` | `Metrics.orbDissipateBlur` | and blurs to this fraction of its size | -| `orb/dissipate-scale` | `1.25` | `Metrics.orbDissipateScale` | the orb swells to this while dissipating | -| `orb/home` | `112` | `Metrics.orbHome` | the orb on the home screen | -| `orb/light-reach` | `0.9` | `Metrics.orbLightReach` | the soft light's reach, as a fraction of the orb (was a fixed 110 pt, flat on a 40 pt orb) | -| `orb/light-x` | `0.3` | `Metrics.orbLightX` | the soft light's centre, as a fraction of the orb | -| `orb/light-y` | `0.22` | `Metrics.orbLightY` | — | -| `orb/panel` | `96` | `Metrics.orbPanel` | the orb in the panel | -| `panel/spacing` | `12` | `Metrics.panelSpacing` | between the panel's orb and its key row | -| `picker/preview-width` | `393` | `Metrics.pickerPreviewWidth` | the theme card draws the keyboard at this width | -| `picker/radius` | `10` | `Metrics.pickerRadius` | the theme card's preview corners | -| `picker/scale` | `0.42` | `Metrics.pickerScale` | then scales it to fit two across | -| `popup/extra-width` | `18` | `Metrics.popupExtraWidth` | the letter pop-up is the key width plus this | -| `popup/height` | `56` | `Metrics.popupHeight` | — | -| `popup/offset` | `58` | `Metrics.popupOffset` | the pop-up sits this far above the key | -| `popup/radius` | `10` | `Metrics.popupRadius` | — | -| `popup/shadow-radius` | `8` | `Metrics.popupShadowRadius` | the one thing that floats | -| `popup/shadow-y` | `2` | `Metrics.popupShadowY` | — | -| `press/scale` | `0.94` | `Metrics.pressScale` | the orb while pressed | -| `ring/active` | `2` | `Metrics.ringActive` | the ring while working or noticing; the home ring | -| `ring/still` | `1` | `Metrics.ringStill` | the ring at rest | -| `row/gap` | `11` | `Metrics.rowGap` | between rows, the iPhone's | -| `slim/spacing` | `8` | `Metrics.slimSpacing` | between the slim bar's keys | -| `surface/vignette-end` | `0.75` | `Metrics.surfaceVignetteEnd` | where it is full | -| `surface/vignette-start` | `0.3` | `Metrics.surfaceVignetteStart` | where the vignette begins, as a fraction of the keyboard's width | -| `term/gap` | `8` | `Metrics.termGap` | × · field · ✓ | -| `term/height` | `36` | `Metrics.termHeight` | the key-term field's capsule | -| `term/inset` | `2` | `Metrics.termInset` | the field row's side inset | -| `term/pad` | `14` | `Metrics.termPad` | the field's side padding | -| `voicebar/addterm-clearance` | `12` | `Metrics.voicebarAddtermClearance` | the wave stays this clear of the + at the trailing edge | -| `voicebar/height` | `44` | `Metrics.voicebarHeight` | the voice row, where the system puts its suggestion bar | -| `voicebar/note-gap` | `10` | `Metrics.voicebarNoteGap` | between the orb and the Full Access note | -| `wave/bar` | `2` | `Metrics.waveBar` | a wave bar's width | -| `wave/bar-height` | `24` | `Metrics.waveBarHeight` | — | -| `wave/bar-width` | `240` | `Metrics.waveBarWidth` | the wave in the voice bar, at most | -| `wave/gap` | `2` | `Metrics.waveGap` | between wave bars | -| `wave/home-height` | `44` | `Metrics.waveHomeHeight` | — | -| `wave/home-width` | `280` | `Metrics.waveHomeWidth` | — | -| `wave/liquid` | `0` | `Metrics.waveLiquid` | 1 draws the wave as one liquid shape through the bar heights instead of the bars themselves | -| `wave/panel-height` | `40` | `Metrics.wavePanelHeight` | — | -| `wave/panel-width` | `300` | `Metrics.wavePanelWidth` | — | -| `wordmark/height` | `22` | `Metrics.wordmarkHeight` | — | +| Token | Points | Swift | Use | +| ----------------------------- | --------- | ---------------------------------- | ---------------------------------------------------------------------------------------------- | +| `addterm/inset` | `6` | `Metrics.addtermInset` | the + from the panel's corner | +| `card/border` | `1` | `Metrics.cardBorder` | the card's hairline | +| `card/radius` | `16` | `Metrics.cardRadius` | the app's cards | +| `caret/height` | `20` | `Metrics.caretHeight` | — | +| `caret/lead` | `1` | `Metrics.caretLead` | the caret's gap from the text | +| `caret/radius` | `1` | `Metrics.caretRadius` | — | +| `caret/width` | `2` | `Metrics.caretWidth` | — | +| `gesture/swipe-min` | `24` | `Metrics.gestureSwipeMin` | the carousel gesture's minimum distance | +| `glyph/hit` | `32` | `Metrics.glyphHit` | the +, × and ✓ touch targets | +| `key/abc-width-402` | `43.333` | `Metrics.keyAbcWidth402` | 123 and the globe at 402 pt: the iPhone's | +| `key/gap` | `6` | `Metrics.keyGap` | between keys, the iPhone's | +| `key/height` | `43` | `Metrics.keyHeight` | every key: the iPhone's cap height (apple-geometry.json) | +| `key/letter-width-402` | `33.5` | `Metrics.keyLetterWidth402` | a letter key at 402 pt: (width − 2 × margin/side − 9 × key/gap) / 10 | +| `key/min-width` | `43.333` | `Metrics.keyMinWidth` | a key that isn't given a width: the iPhone's 123 key at 402 pt | +| `key/pad` | `4` | `Metrics.keyPad` | a legend's side padding on a min-width key | +| `key/radius` | `8` | `Metrics.keyRadius` | flat keys, one colour at this corner: the iPhone's (fitted 8.17) | +| `key/reference-width` | `402` | `Metrics.keyReferenceWidth` | the width the @402 tokens were measured at (iPhone 18 Pro); widths scale from it | +| `key/return-width-402` | `92.667` | `Metrics.keyReturnWidth402` | return at 402 pt: two 123 keys and a gap | +| `key/side-gap` | `13.667` | `Metrics.keySideGap` | shift and delete stand this far from the letters: the iPhone's | +| `key/side-width-402` | `45.583` | `Metrics.keySideWidth402` | shift and delete at 402 pt: what seven letters and the side gaps leave, halved (measured 45.5) | +| `key/space-width-402` | `191.667` | `Metrics.keySpaceWidth402` | space at 402 pt beside 123, the globe and return: what is left (measured 191.333) | +| `layout/full` | `270` | `Metrics.layoutFull` | margin/vertical + voicebar/height + 4 × key/height + 3 × row/gap + margin/bottom-keys | +| `layout/panel` | `216` | `Metrics.layoutPanel` | chosen: room for the 96 orb over one key row | +| `layout/slim` | `60` | `Metrics.layoutSlim` | 2 × margin/vertical + voicebar/height | +| `margin/bottom-keys` | `13` | `Metrics.marginBottomKeys` | under a bottom row of keys (the full keyboard, the panel): the iPhone's | +| `margin/side` | `6.5` | `Metrics.marginSide` | at the keyboard's sides: the iPhone's cap margin, (402 − 10 letters − 9 gaps) / 2 | +| `margin/vertical` | `8` | `Metrics.marginVertical` | the keyboard's top, and the slim bar's bottom | +| `opacity/dim` | `0.8` | `Metrics.opacityDim` | the orb when Blurt isn't ready | +| `opacity/dim-saturation` | `0.35` | `Metrics.opacityDimSaturation` | and its saturation | +| `opacity/disabled` | `0.4` | `Metrics.opacityDisabled` | the + without Full Access | +| `opacity/grain` | `0.5` | `Metrics.opacityGrain` | — | +| `opacity/home-dim-saturation` | `0.45` | `Metrics.opacityHomeDimSaturation` | the home hero's saturation when not listening | +| `opacity/legend` | `1` | `Metrics.opacityLegend` | key legends over the cap; below 1 they sit back | +| `opacity/legend-muted` | `0.5` | `Metrics.opacityLegendMuted` | the + at rest | +| `opacity/orb-light` | `0.3` | `Metrics.opacityOrbLight` | — | +| `opacity/placeholder` | `0.4` | `Metrics.opacityPlaceholder` | the field's placeholder | +| `opacity/popup-shadow` | `0.12` | `Metrics.opacityPopupShadow` | — | +| `opacity/press-brighten` | `0.15` | `Metrics.opacityPressBrighten` | a key lightens this much while pressed | +| `opacity/surface-grain` | `0.14` | `Metrics.opacitySurfaceGrain` | film grain over the whole keyboard surface: matte, the brand's texture | +| `opacity/surface-vignette` | `0` | `Metrics.opacitySurfaceVignette` | a soft darkening toward the surface's edges; 0 is none | +| `opacity/term-cancel` | `0.7` | `Metrics.opacityTermCancel` | the field's × | +| `orb/bar` | `40` | `Metrics.orbBar` | the orb in the voice bar | +| `orb/dissipate-blur` | `0.16` | `Metrics.orbDissipateBlur` | and blurs to this fraction of its size | +| `orb/dissipate-scale` | `1.25` | `Metrics.orbDissipateScale` | the orb swells to this while dissipating | +| `orb/home` | `112` | `Metrics.orbHome` | the orb on the home screen | +| `orb/light-reach` | `0.9` | `Metrics.orbLightReach` | the soft light's reach, as a fraction of the orb (was a fixed 110 pt, flat on a 40 pt orb) | +| `orb/light-x` | `0.3` | `Metrics.orbLightX` | the soft light's centre, as a fraction of the orb | +| `orb/light-y` | `0.22` | `Metrics.orbLightY` | — | +| `orb/panel` | `96` | `Metrics.orbPanel` | the orb in the panel | +| `panel/spacing` | `12` | `Metrics.panelSpacing` | between the panel's orb and its key row | +| `picker/preview-width` | `393` | `Metrics.pickerPreviewWidth` | the theme card draws the keyboard at this width | +| `picker/radius` | `10` | `Metrics.pickerRadius` | the theme card's preview corners | +| `picker/scale` | `0.42` | `Metrics.pickerScale` | then scales it to fit two across | +| `popup/extra-width` | `18` | `Metrics.popupExtraWidth` | the letter pop-up is the key width plus this | +| `popup/height` | `56` | `Metrics.popupHeight` | — | +| `popup/offset` | `58` | `Metrics.popupOffset` | the pop-up sits this far above the key | +| `popup/radius` | `10` | `Metrics.popupRadius` | — | +| `popup/shadow-radius` | `8` | `Metrics.popupShadowRadius` | the one thing that floats | +| `popup/shadow-y` | `2` | `Metrics.popupShadowY` | — | +| `press/scale` | `0.94` | `Metrics.pressScale` | the orb while pressed | +| `ring/active` | `2` | `Metrics.ringActive` | the ring while working or noticing; the home ring | +| `ring/still` | `1` | `Metrics.ringStill` | the ring at rest | +| `row/gap` | `11` | `Metrics.rowGap` | between rows, the iPhone's | +| `slim/spacing` | `8` | `Metrics.slimSpacing` | between the slim bar's keys | +| `surface/vignette-end` | `0.75` | `Metrics.surfaceVignetteEnd` | where it is full | +| `surface/vignette-start` | `0.3` | `Metrics.surfaceVignetteStart` | where the vignette begins, as a fraction of the keyboard's width | +| `term/gap` | `8` | `Metrics.termGap` | × · field · ✓ | +| `term/height` | `36` | `Metrics.termHeight` | the key-term field's capsule | +| `term/inset` | `2` | `Metrics.termInset` | the field row's side inset | +| `term/pad` | `14` | `Metrics.termPad` | the field's side padding | +| `voicebar/addterm-clearance` | `12` | `Metrics.voicebarAddtermClearance` | the wave stays this clear of the + at the trailing edge | +| `voicebar/height` | `44` | `Metrics.voicebarHeight` | the voice row, where the system puts its suggestion bar | +| `voicebar/note-gap` | `10` | `Metrics.voicebarNoteGap` | between the orb and the Full Access note | +| `wave/bar` | `2` | `Metrics.waveBar` | a wave bar's width | +| `wave/bar-height` | `24` | `Metrics.waveBarHeight` | — | +| `wave/bar-width` | `240` | `Metrics.waveBarWidth` | the wave in the voice bar, at most | +| `wave/gap` | `2` | `Metrics.waveGap` | between wave bars | +| `wave/home-height` | `44` | `Metrics.waveHomeHeight` | — | +| `wave/home-width` | `280` | `Metrics.waveHomeWidth` | — | +| `wave/liquid` | `0` | `Metrics.waveLiquid` | 1 draws the wave as one liquid shape through the bar heights instead of the bars themselves | +| `wave/panel-height` | `40` | `Metrics.wavePanelHeight` | — | +| `wave/panel-width` | `300` | `Metrics.wavePanelWidth` | — | +| `wordmark/height` | `22` | `Metrics.wordmarkHeight` | — | diff --git a/App/BlurtiOS/Design/apple-geometry.json b/App/BlurtiOS/Design/apple-geometry.json new file mode 100644 index 00000000..df7df064 --- /dev/null +++ b/App/BlurtiOS/Design/apple-geometry.json @@ -0,0 +1,58 @@ +{ + "cap": { + "abc": 43.333, + "bottomMargin": 13.0, + "gap": 6.0, + "height": 43, + "keyboardHeight": 270.667, + "letter": 33.5, + "marginRight": 6.333, + "marginSide": 6.667, + "radius": 8.17, + "return": 93, + "rowGap": 11.0, + "side": 45.5, + "sideGap": 13.667, + "space": 191.333, + "systemBarBelow": 58.0, + "topBand": 52.667 + }, + "cell": { + "delete": 51.667, + "firstRowTop": 597.0, + "keyboardHeight": 226.0, + "keyboardTop": 590.0, + "letter": 39.333, + "more": 49.333, + "return": 99.0, + "row": 54.0, + "shift": 51.333, + "space": 197.333 + }, + "colors": { + "dark": { + "key": "#575757", + "modifier": "#575757", + "surface": "#373737" + }, + "light": { + "key": "#FFFFFF", + "modifier": "#FFFFFF", + "surface": "#E2E3E8" + } + }, + "darkFaceIdentical": true, + "device": "iPhone 18 Pro", + "legend": { + "lHeight": 17.667, + "pointSizeEstimate": 24.201 + }, + "measured": "2026-09-29", + "sources": { + "caps": "pixel scan of the light screenshot (scripts/design-diff.swift measure)", + "cells": "XCUITest key frames (BlurtiOSProbe) \u2014 touch cells, no gaps", + "legend": "the l glyph's height on the light face; the point size is an estimate (\u00f7 0.73, SF's ascender)", + "radius": "circle fitted to the top-left inset of the q cap over its first 12 pt (\u00b10.25)" + }, + "width": 402 +} diff --git a/App/BlurtiOS/Design/figma/tokens.js b/App/BlurtiOS/Design/figma/tokens.js index f9d57fad..1a7a991a 100644 --- a/App/BlurtiOS/Design/figma/tokens.js +++ b/App/BlurtiOS/Design/figma/tokens.js @@ -85,20 +85,24 @@ Metrics|caret/radius|FLOAT|1||CORNER_RADIUS|DesignTokens.Metrics.caretRadius| Metrics|caret/width|FLOAT|2||STROKE_FLOAT,WIDTH_HEIGHT|DesignTokens.Metrics.caretWidth| Metrics|gesture/swipe-min|FLOAT|24|||DesignTokens.Metrics.gestureSwipeMin|the carousel gesture's minimum distance Metrics|glyph/hit|FLOAT|32||WIDTH_HEIGHT|DesignTokens.Metrics.glyphHit|the +, × and ✓ touch targets +Metrics|key/abc-width-402|FLOAT|43.333||WIDTH_HEIGHT|DesignTokens.Metrics.keyAbcWidth402|123 and the globe at 402 pt: the iPhone's Metrics|key/gap|FLOAT|6||GAP|DesignTokens.Metrics.keyGap|between keys, the iPhone's -Metrics|key/height|FLOAT|42||WIDTH_HEIGHT|DesignTokens.Metrics.keyHeight|every key -Metrics|key/letter-width-402|FLOAT|34.8||WIDTH_HEIGHT|DesignTokens.Metrics.keyLetterWidth402|a letter key at 402 pt (iPhone 18 Pro): (width − 9 × key/gap) / 10 -Metrics|key/min-width|FLOAT|44||WIDTH_HEIGHT|DesignTokens.Metrics.keyMinWidth|a key that isn't given a width +Metrics|key/height|FLOAT|43||WIDTH_HEIGHT|DesignTokens.Metrics.keyHeight|every key: the iPhone's cap height (apple-geometry.json) +Metrics|key/letter-width-402|FLOAT|33.5||WIDTH_HEIGHT|DesignTokens.Metrics.keyLetterWidth402|a letter key at 402 pt: (width − 2 × margin/side − 9 × key/gap) / 10 +Metrics|key/min-width|FLOAT|43.333||WIDTH_HEIGHT|DesignTokens.Metrics.keyMinWidth|a key that isn't given a width: the iPhone's 123 key at 402 pt Metrics|key/pad|FLOAT|4||GAP|DesignTokens.Metrics.keyPad|a legend's side padding on a min-width key -Metrics|key/radius|FLOAT|8||CORNER_RADIUS|DesignTokens.Metrics.keyRadius|flat keys, one colour at this corner -Metrics|key/return-width-402|FLOAT|104.4||WIDTH_HEIGHT|DesignTokens.Metrics.keyReturnWidth402|return at 402 pt: two side keys and a gap -Metrics|key/side-gap-factor|FLOAT|2|||DesignTokens.Metrics.keySideGapFactor|shift and delete stand this many key gaps from the letters -Metrics|key/side-width-402|FLOAT|49.2||WIDTH_HEIGHT|DesignTokens.Metrics.keySideWidth402|shift, delete, 123 and globe at 402 pt: what seven letters leave, halved -Metrics|layout/full|FLOAT|272||WIDTH_HEIGHT|DesignTokens.Metrics.layoutFull|2 × margin/vertical + voicebar/height + 4 × row/gap + 4 × key/height +Metrics|key/radius|FLOAT|8||CORNER_RADIUS|DesignTokens.Metrics.keyRadius|flat keys, one colour at this corner: the iPhone's (fitted 8.17) +Metrics|key/reference-width|FLOAT|402||WIDTH_HEIGHT|DesignTokens.Metrics.keyReferenceWidth|the width the @402 tokens were measured at (iPhone 18 Pro); widths scale from it +Metrics|key/return-width-402|FLOAT|92.667||WIDTH_HEIGHT|DesignTokens.Metrics.keyReturnWidth402|return at 402 pt: two 123 keys and a gap +Metrics|key/side-gap|FLOAT|13.667||GAP|DesignTokens.Metrics.keySideGap|shift and delete stand this far from the letters: the iPhone's +Metrics|key/side-width-402|FLOAT|45.583||WIDTH_HEIGHT|DesignTokens.Metrics.keySideWidth402|shift and delete at 402 pt: what seven letters and the side gaps leave, halved (measured 45.5) +Metrics|key/space-width-402|FLOAT|191.667||WIDTH_HEIGHT|DesignTokens.Metrics.keySpaceWidth402|space at 402 pt beside 123, the globe and return: what is left (measured 191.333) +Metrics|layout/full|FLOAT|270||WIDTH_HEIGHT|DesignTokens.Metrics.layoutFull|margin/vertical + voicebar/height + 4 × key/height + 3 × row/gap + margin/bottom-keys Metrics|layout/panel|FLOAT|216||WIDTH_HEIGHT|DesignTokens.Metrics.layoutPanel|chosen: room for the 96 orb over one key row Metrics|layout/slim|FLOAT|60||WIDTH_HEIGHT|DesignTokens.Metrics.layoutSlim|2 × margin/vertical + voicebar/height -Metrics|margin/side|FLOAT|3||WIDTH_HEIGHT|DesignTokens.Metrics.marginSide|at the keyboard's sides -Metrics|margin/vertical|FLOAT|8||WIDTH_HEIGHT|DesignTokens.Metrics.marginVertical|the keyboard's top and bottom +Metrics|margin/bottom-keys|FLOAT|13||WIDTH_HEIGHT|DesignTokens.Metrics.marginBottomKeys|under a bottom row of keys (the full keyboard, the panel): the iPhone's +Metrics|margin/side|FLOAT|6.5||WIDTH_HEIGHT|DesignTokens.Metrics.marginSide|at the keyboard's sides: the iPhone's cap margin, (402 − 10 letters − 9 gaps) / 2 +Metrics|margin/vertical|FLOAT|8||WIDTH_HEIGHT|DesignTokens.Metrics.marginVertical|the keyboard's top, and the slim bar's bottom Metrics|opacity/dim|FLOAT|0.8||OPACITY|DesignTokens.Metrics.opacityDim|the orb when Blurt isn't ready Metrics|opacity/dim-saturation|FLOAT|0.35||OPACITY|DesignTokens.Metrics.opacityDimSaturation|and its saturation Metrics|opacity/disabled|FLOAT|0.4||OPACITY|DesignTokens.Metrics.opacityDisabled|the + without Full Access @@ -163,7 +167,7 @@ Typography|size/eyebrow|FLOAT|12||FONT_SIZE|DesignTokens.Typography.sizeEyebrow| Typography|size/glyph|FLOAT|17||FONT_SIZE|DesignTokens.Typography.sizeGlyph|the +, × and ✓ Typography|size/label|FLOAT|12||FONT_SIZE|DesignTokens.Typography.sizeLabel|the mono word labels on keys: 123, ABC, #+=, space, the return label Typography|size/legend|FLOAT|16||FONT_SIZE|DesignTokens.Typography.sizeLegend|every other key -Typography|size/letter|FLOAT|22||FONT_SIZE|DesignTokens.Typography.sizeLetter|letter keys +Typography|size/letter|FLOAT|24||FONT_SIZE|DesignTokens.Typography.sizeLetter|letter keys: the iPhone's (estimated from the l glyph, apple-geometry.json) Typography|size/popup|FLOAT|32||FONT_SIZE|DesignTokens.Typography.sizePopup|the letter pop-up Typography|size/term|FLOAT|17||FONT_SIZE|DesignTokens.Typography.sizeTerm|the key-term field Typography|size/title|FLOAT|34||FONT_SIZE|DesignTokens.Typography.sizeTitle|the app's serif headline diff --git a/App/BlurtiOS/Design/tokens.json b/App/BlurtiOS/Design/tokens.json index 3e091bee..45bd516a 100644 --- a/App/BlurtiOS/Design/tokens.json +++ b/App/BlurtiOS/Design/tokens.json @@ -303,8 +303,8 @@ }, "metrics": { "key/height": { - "value": 42, - "use": "every key" + "value": 43, + "use": "every key: the iPhone's cap height (apple-geometry.json)" }, "key/gap": { "value": 6, @@ -315,40 +315,36 @@ "use": "between rows, the iPhone's" }, "margin/side": { - "value": 3, - "use": "at the keyboard's sides" + "value": 6.5, + "use": "at the keyboard's sides: the iPhone's cap margin, (402 − 10 letters − 9 gaps) / 2" }, "margin/vertical": { "value": 8, - "use": "the keyboard's top and bottom" + "use": "the keyboard's top, and the slim bar's bottom" }, "key/radius": { "value": 8, - "use": "flat keys, one colour at this corner" + "use": "flat keys, one colour at this corner: the iPhone's (fitted 8.17)" }, "key/min-width": { - "value": 44, - "use": "a key that isn't given a width" + "value": 43.333, + "use": "a key that isn't given a width: the iPhone's 123 key at 402 pt" }, "key/pad": { "value": 4, "use": "a legend's side padding on a min-width key" }, - "key/side-gap-factor": { - "value": 2, - "use": "shift and delete stand this many key gaps from the letters" - }, "key/letter-width-402": { - "value": 34.8, - "use": "a letter key at 402 pt (iPhone 18 Pro): (width − 9 × key/gap) / 10" + "value": 33.5, + "use": "a letter key at 402 pt: (width − 2 × margin/side − 9 × key/gap) / 10" }, "key/side-width-402": { - "value": 49.2, - "use": "shift, delete, 123 and globe at 402 pt: what seven letters leave, halved" + "value": 45.583, + "use": "shift and delete at 402 pt: what seven letters and the side gaps leave, halved (measured 45.5)" }, "key/return-width-402": { - "value": 104.4, - "use": "return at 402 pt: two side keys and a gap" + "value": 92.667, + "use": "return at 402 pt: two 123 keys and a gap" }, "voicebar/height": { "value": 44, @@ -511,8 +507,8 @@ "use": "chosen: room for the 96 orb over one key row" }, "layout/full": { - "value": 272, - "use": "2 × margin/vertical + voicebar/height + 4 × row/gap + 4 × key/height" + "value": 270, + "use": "margin/vertical + voicebar/height + 4 × key/height + 3 × row/gap + margin/bottom-keys" }, "orb/light-x": { "value": 0.3, @@ -601,12 +597,32 @@ "gesture/swipe-min": { "value": 24, "use": "the carousel gesture's minimum distance" + }, + "margin/bottom-keys": { + "value": 13, + "use": "under a bottom row of keys (the full keyboard, the panel): the iPhone's" + }, + "key/side-gap": { + "value": 13.667, + "use": "shift and delete stand this far from the letters: the iPhone's" + }, + "key/reference-width": { + "value": 402, + "use": "the width the @402 tokens were measured at (iPhone 18 Pro); widths scale from it" + }, + "key/abc-width-402": { + "value": 43.333, + "use": "123 and the globe at 402 pt: the iPhone's" + }, + "key/space-width-402": { + "value": 191.667, + "use": "space at 402 pt beside 123, the globe and return: what is left (measured 191.333)" } }, "type": { "size/letter": { - "value": 22, - "use": "letter keys" + "value": 24, + "use": "letter keys: the iPhone's (estimated from the l glyph, apple-geometry.json)" }, "size/legend": { "value": 16, diff --git a/App/BlurtiOS/Shared/DesignTokens.swift b/App/BlurtiOS/Shared/DesignTokens.swift index 4cd847c7..16b72507 100644 --- a/App/BlurtiOS/Shared/DesignTokens.swift +++ b/App/BlurtiOS/Shared/DesignTokens.swift @@ -182,33 +182,41 @@ enum DesignTokens { nonisolated static let gestureSwipeMin: CGFloat = 24 /// The +, × and ✓ touch targets. nonisolated static let glyphHit: CGFloat = 32 + /// 123 and the globe at 402 pt: the iPhone's. + nonisolated static let keyAbcWidth402: CGFloat = 43.333 /// Between keys, the iPhone's. nonisolated static let keyGap: CGFloat = 6 - /// Every key. - nonisolated static let keyHeight: CGFloat = 42 - /// A letter key at 402 pt (iPhone 18 Pro): (width − 9 × key/gap) / 10. - nonisolated static let keyLetterWidth402: CGFloat = 34.8 - /// A key that isn't given a width. - nonisolated static let keyMinWidth: CGFloat = 44 + /// Every key: the iPhone's cap height (apple-geometry.json). + nonisolated static let keyHeight: CGFloat = 43 + /// A letter key at 402 pt: (width − 2 × margin/side − 9 × key/gap) / 10. + nonisolated static let keyLetterWidth402: CGFloat = 33.5 + /// A key that isn't given a width: the iPhone's 123 key at 402 pt. + nonisolated static let keyMinWidth: CGFloat = 43.333 /// A legend's side padding on a min-width key. nonisolated static let keyPad: CGFloat = 4 - /// Flat keys, one colour at this corner. + /// Flat keys, one colour at this corner: the iPhone's (fitted 8.17). nonisolated static let keyRadius: CGFloat = 8 - /// Return at 402 pt: two side keys and a gap. - nonisolated static let keyReturnWidth402: CGFloat = 104.4 - /// Shift and delete stand this many key gaps from the letters. - nonisolated static let keySideGapFactor: CGFloat = 2 - /// Shift, delete, 123 and globe at 402 pt: what seven letters leave, halved. - nonisolated static let keySideWidth402: CGFloat = 49.2 - /// 2 × margin/vertical + voicebar/height + 4 × row/gap + 4 × key/height. - nonisolated static let layoutFull: CGFloat = 272 + /// The width the @402 tokens were measured at (iPhone 18 Pro); widths scale from it. + nonisolated static let keyReferenceWidth: CGFloat = 402 + /// Return at 402 pt: two 123 keys and a gap. + nonisolated static let keyReturnWidth402: CGFloat = 92.667 + /// Shift and delete stand this far from the letters: the iPhone's. + nonisolated static let keySideGap: CGFloat = 13.667 + /// Shift and delete at 402 pt: what seven letters and the side gaps leave, halved (measured 45.5). + nonisolated static let keySideWidth402: CGFloat = 45.583 + /// Space at 402 pt beside 123, the globe and return: what is left (measured 191.333). + nonisolated static let keySpaceWidth402: CGFloat = 191.667 + /// Margin/vertical + voicebar/height + 4 × key/height + 3 × row/gap + margin/bottom-keys. + nonisolated static let layoutFull: CGFloat = 270 /// Chosen: room for the 96 orb over one key row. nonisolated static let layoutPanel: CGFloat = 216 /// 2 × margin/vertical + voicebar/height. nonisolated static let layoutSlim: CGFloat = 60 - /// At the keyboard's sides. - nonisolated static let marginSide: CGFloat = 3 - /// The keyboard's top and bottom. + /// Under a bottom row of keys (the full keyboard, the panel): the iPhone's. + nonisolated static let marginBottomKeys: CGFloat = 13 + /// At the keyboard's sides: the iPhone's cap margin, (402 − 10 letters − 9 gaps) / 2. + nonisolated static let marginSide: CGFloat = 6.5 + /// The keyboard's top, and the slim bar's bottom. nonisolated static let marginVertical: CGFloat = 8 /// The orb when Blurt isn't ready. nonisolated static let opacityDim: CGFloat = 0.8 @@ -328,8 +336,8 @@ enum DesignTokens { nonisolated static let sizeLabel: CGFloat = 12 /// Every other key. nonisolated static let sizeLegend: CGFloat = 16 - /// Letter keys. - nonisolated static let sizeLetter: CGFloat = 22 + /// Letter keys: the iPhone's (estimated from the l glyph, apple-geometry.json). + nonisolated static let sizeLetter: CGFloat = 24 /// The letter pop-up. nonisolated static let sizePopup: CGFloat = 32 /// The key-term field. @@ -511,19 +519,23 @@ enum DesignTokens { "metrics.caret/width": "2", "metrics.gesture/swipe-min": "24", "metrics.glyph/hit": "32", + "metrics.key/abc-width-402": "43.333", "metrics.key/gap": "6", - "metrics.key/height": "42", - "metrics.key/letter-width-402": "34.8", - "metrics.key/min-width": "44", + "metrics.key/height": "43", + "metrics.key/letter-width-402": "33.5", + "metrics.key/min-width": "43.333", "metrics.key/pad": "4", "metrics.key/radius": "8", - "metrics.key/return-width-402": "104.4", - "metrics.key/side-gap-factor": "2", - "metrics.key/side-width-402": "49.2", - "metrics.layout/full": "272", + "metrics.key/reference-width": "402", + "metrics.key/return-width-402": "92.667", + "metrics.key/side-gap": "13.667", + "metrics.key/side-width-402": "45.583", + "metrics.key/space-width-402": "191.667", + "metrics.layout/full": "270", "metrics.layout/panel": "216", "metrics.layout/slim": "60", - "metrics.margin/side": "3", + "metrics.margin/bottom-keys": "13", + "metrics.margin/side": "6.5", "metrics.margin/vertical": "8", "metrics.opacity/dim": "0.8", "metrics.opacity/dim-saturation": "0.35", @@ -589,7 +601,7 @@ enum DesignTokens { "type.size/glyph": "17", "type.size/label": "12", "type.size/legend": "16", - "type.size/letter": "22", + "type.size/letter": "24", "type.size/popup": "32", "type.size/term": "17", "type.size/title": "34", diff --git a/App/BlurtiOS/Shared/SharedState.swift b/App/BlurtiOS/Shared/SharedState.swift index 65511727..0a6fd1a9 100644 --- a/App/BlurtiOS/Shared/SharedState.swift +++ b/App/BlurtiOS/Shared/SharedState.swift @@ -83,7 +83,9 @@ nonisolated enum KeyboardLayout: String, CaseIterable, Codable, Sendable, Identi return switch self { case .slimBar: 2 * metrics.marginVertical + metrics.voicebarHeight case .panel: metrics.layoutPanel - case .full: 2 * metrics.marginVertical + metrics.voicebarHeight + 4 * metrics.rowGap + 4 * metrics.keyHeight + case .full: + metrics.marginVertical + metrics.voicebarHeight + 4 * metrics.keyHeight + 3 * metrics.rowGap + + metrics.marginBottomKeys } } } diff --git a/App/BlurtiOS/project.yml b/App/BlurtiOS/project.yml index 8307b58b..9aa77f1f 100644 --- a/App/BlurtiOS/project.yml +++ b/App/BlurtiOS/project.yml @@ -191,6 +191,10 @@ targets: # compiled DesignTokens.swift to the file it was generated from. - path: Design/tokens.json buildPhase: resources + # The iPhone keyboard's measured geometry, so AppleGeometryTests can pin + # the key/* tokens to what scripts/apple-geometry.sh read off the phone. + - path: Design/apple-geometry.json + buildPhase: resources dependencies: - target: BlurtiOS settings: @@ -199,6 +203,24 @@ targets: GENERATE_INFOPLIST_FILE: YES SWIFT_TREAT_WARNINGS_AS_ERRORS: YES SWIFT_DEFAULT_ACTOR_ISOLATION: MainActor + # The Apple-keyboard probe: one XCUITest that launches the app on + # `-BlurtProbeField` and reads the system keyboard's key frames, so the + # keyboard's geometry tokens are measured, not assumed + # (scripts/apple-geometry.sh → Design/apple-geometry.json). Its own scheme, + # so `xcodebuild test -scheme BlurtiOS` and the periphery scan never see it. + BlurtiOSProbe: + type: bundle.ui-testing + platform: iOS + sources: + - path: BlurtiOSProbe + dependencies: + - target: BlurtiOS + settings: + base: + PRODUCT_BUNDLE_IDENTIFIER: dev.alex.blurt.ios.probe + TEST_TARGET_NAME: BlurtiOS + GENERATE_INFOPLIST_FILE: YES + SWIFT_TREAT_WARNINGS_AS_ERRORS: YES # XcodeGen emits a scheme only where one is declared, and `xcodebuild -scheme` # needs a shared one. Building the app builds the keyboard it embeds; testing # runs the unit tests against it. @@ -214,3 +236,14 @@ schemes: config: Debug targets: - BlurtiOSTests + BlurtiOSProbe: + build: + targets: + BlurtiOS: all + BlurtiOSProbe: [test] + run: + config: Debug + test: + config: Debug + targets: + - BlurtiOSProbe diff --git a/scripts/apple-geometry.sh b/scripts/apple-geometry.sh new file mode 100755 index 00000000..612a5f8a --- /dev/null +++ b/scripts/apple-geometry.sh @@ -0,0 +1,171 @@ +#!/bin/bash +# Measure the iPhone's own keyboard on the simulator and write what it found: +# the BlurtiOSProbe UI test launches the app on `-BlurtProbeField`, reads every +# key's frame off the system keyboard (both faces), and this turns the +# attachment into App/BlurtiOS/Design/apple-geometry.json — the table the +# keyboard's `key/*`, `row/gap` and `margin/*` tokens are pinned to +# (AppleGeometryTests) and the crop scripts/design-diff.swift measures the +# corner radius from. +# +# scripts/apple-geometry.sh # iPhone 18 Pro, writes the JSON and prints the table +# BLURT_SIM_DEVICE="iPhone 17" scripts/apple-geometry.sh --out /tmp/geometry.json +# +# Needs the on-screen keyboard: in Device Hub / Simulator, "Always simulate +# hardware keyboard" must be off, or no keyboard ever appears and the test fails. +set -euo pipefail + +REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" +cd "$REPO_ROOT" +# shellcheck source=scripts/ios-lib.sh +source "$REPO_ROOT/scripts/ios-lib.sh" +DERIVED="${BLURT_DERIVED_DATA:-$REPO_ROOT/.build/ios-sim}" +OUT="$REPO_ROOT/App/BlurtiOS/Design/apple-geometry.json" +WORK="$REPO_ROOT/.build/design/probe" +while [ $# -gt 0 ]; do + case "$1" in + --out) + OUT="${2:?}" + shift 2 + ;; + *) + echo "usage: apple-geometry.sh [--out FILE.json]" >&2 + exit 2 + ;; + esac +done + +PICKED="$(ios_pick_device "${BLURT_SIM_DEVICE:-iPhone 18 Pro}")" +[ -n "$PICKED" ] || { + echo "apple-geometry: no iPhone simulator available" >&2 + exit 1 +} +UDID="${PICKED%% *}" +NAME="${PICKED#* }" +ios_wait_booted "$UDID" +rm -rf "$WORK" +mkdir -p "$WORK" + +echo "==> measuring the system keyboard on $NAME" +(cd "$REPO_ROOT/App/BlurtiOS" && xcodegen generate --quiet) +RESULTS="$WORK/probe.xcresult" +xcodebuild test -project "$REPO_ROOT/App/BlurtiOS/BlurtiOS.xcodeproj" -scheme BlurtiOSProbe \ + -destination "platform=iOS Simulator,id=$UDID" -derivedDataPath "$DERIVED" \ + -resultBundlePath "$RESULTS" "${IOS_SIM_SIGNING[@]}" -collect-test-diagnostics never -quiet +xcrun xcresulttool export attachments --path "$RESULTS" --output-path "$WORK/attachments" >/dev/null + +# The attachments come out under generated names; the manifest maps them back. +# XCUITest reports touch cells, which tile a row with no gaps, so the caps +# themselves — widths, gaps, height, radius, the surface's top edge and the +# margins — are read off the light screenshot by design-diff.swift measure, +# with the probes placed inside the caps from the cells. +python3 - "$WORK/attachments" "$OUT" "$NAME" "$WORK" "$REPO_ROOT" <<'PY' +import json, os, shutil, subprocess, sys +from datetime import date +attachments, out, device, work, root = sys.argv[1:6] +manifest = json.load(open(os.path.join(attachments, "manifest.json"))) +found = {} +for test in manifest: + for a in test.get("attachments", []): + found[a["suggestedHumanReadableName"]] = os.path.join(attachments, a["exportedFileName"]) +faces, shots = {}, {} +for face in ("light", "dark"): + name = next(k for k in found if k.startswith(f"apple-geometry-{face}")) + faces[face] = json.load(open(found[name])) + shot = next(k for k in found if k.startswith(f"apple-keyboard-{face}")) + shots[face] = os.path.join(work, f"apple-keyboard-{face}.png") + shutil.copy(found[shot], shots[face]) + +light = faces["light"] +keys, kb, win = light["keys"], light["keyboard"], light["window"] +def cell(name): + if name not in keys: + raise SystemExit(f"apple-geometry: the keyboard has no key called {name!r}; keys: {sorted(keys)}") + return keys[name] +q, w, a, z, space, more = cell("q"), cell("w"), cell("a"), cell("z"), cell("space"), cell("more") +others = light.get("others", {}) +shift = others.get("button:shift") or cell("shift") +ret = next((v for k, v in others.items() if k.lower().startswith("button:return")), None) +r3 = lambda v: round(v * 1000) / 1000 + +# Probes at each cell's centre: the cap's middle, which the scan reads +# through (a glyph is inside the cap; the edges are found past it). +def probe(c): + return f'{c["x"] + c["w"] / 2},{c["y"] + c["h"] / 2}' +scale = 3 # the iPhone 18 Pro; the capture's pixels per point +def measure(face, probes, columns): + args = ["swift", os.path.join(root, "scripts/design-diff.swift"), "measure", shots[face], "--scale", str(scale), + "--surface", f'{space["x"] + space["w"] / 2},{q["y"] - 3}'] + for p in probes: args += ["--probe", p] + for c in columns: args += ["--column", c] + return json.loads(subprocess.run(args, capture_output=True, text=True, check=True).stdout) +row_l = {"w": keys["l"]["w"], "x": keys["l"]["x"], "y": keys["l"]["y"]} +# The surface's top edge is read down the keyboard's middle (its top corners +# are rounded); the l glyph's height down the column nearest its stroke. +mid = f'{win["w"] / 2}' +l_cx = keys["l"]["x"] + keys["l"]["w"] / 2 +l_columns = [f'{l_cx + dx / 3}:{keys["l"]["y"]}:{keys["l"]["y"] + keys["l"]["h"]}' for dx in range(-4, 5)] +m = measure("light", [probe(q), probe(shift), probe(space), probe(ret) if ret else probe(more), probe(more)], + [f'{mid}:{q["y"] - 80}:{q["y"]}'] + l_columns) +dark = measure("dark", [probe(q), probe(more)], [f'{mid}:{q["y"] - 80}:{q["y"]}']) +caps = {c["probe"]: c for c in m["caps"] if "error" not in c} +missing = [c for c in m["caps"] if "error" in c] +if missing: + raise SystemExit(f"apple-geometry: probes missed a cap: {missing}") +letter, side, spacebar, returnkey, abc = (caps[probe(q)], caps[probe(shift)], caps[probe(space)], + caps[probe(ret)] if ret else None, caps[probe(more)]) +row1 = letter["row"] +surface_top = m["columns"][0]["changes"][0]["y"] +# Four changes down the column: cap top, glyph top, glyph bottom, cap bottom. +glyph_height = None +for column in m["columns"][1:]: + changes = column["changes"] + if len(changes) >= 4: + glyph_height = changes[-2]["y"] - changes[1]["y"] + break +cap = { + "letter": r3(sum(c["width"] for c in row1) / len(row1)), + "height": letter["height"], + "gap": r3(sum(letter["gaps"]) / len(letter["gaps"])), + "marginSide": row1[0]["left"], + "marginRight": r3(win["w"] - row1[-1]["left"] - row1[-1]["width"]), + "rowGap": r3(a["y"] - q["y"] - letter["height"]), + "radius": letter["radius"], + "side": r3((side["row"][0]["width"] + side["row"][-1]["width"]) / 2), + "sideGap": side["gaps"][0], + "abc": abc["width"], + "space": spacebar["width"], + "return": returnkey["width"] if returnkey else None, + "topBand": r3(letter["top"] - surface_top), + "bottomMargin": r3(kb["y"] + kb["h"] - letter["bottom"] - 3 * (a["y"] - q["y"])), + "keyboardHeight": r3(kb["y"] + kb["h"] - surface_top), + "systemBarBelow": r3(win["h"] - kb["y"] - kb["h"]), +} +geometry = { + "device": device, "width": win["w"], "measured": date.today().isoformat(), + "sources": { + "cells": "XCUITest key frames (BlurtiOSProbe) — touch cells, no gaps", + "caps": "pixel scan of the light screenshot (scripts/design-diff.swift measure)", + "radius": "circle fitted to the top-left inset of the q cap over its first 12 pt (±0.25)", + "legend": "the l glyph's height on the light face; the point size is an estimate (÷ 0.73, SF's ascender)", + }, + "cell": {"letter": r3(q["w"]), "row": r3(a["y"] - q["y"]), "shift": r3(shift["w"]), "delete": r3(cell("delete")["w"]), + "more": r3(more["w"]), "space": r3(space["w"]), "return": r3(ret["w"]) if ret else None, + "firstRowTop": r3(q["y"]), "keyboardTop": r3(kb["y"]), "keyboardHeight": r3(kb["h"])}, + "cap": cap, + "legend": {"lHeight": r3(glyph_height) if glyph_height else None, + "pointSizeEstimate": r3(glyph_height / 0.73) if glyph_height else None}, + "colors": {"light": {"surface": m["surface"], "key": letter["fill"], "modifier": abc["fill"]}, + "dark": {"surface": dark["surface"], "key": dark["caps"][0]["fill"], "modifier": dark["caps"][1]["fill"]}}, + "darkFaceIdentical": all( + abs(faces["dark"]["keys"].get(n, {}).get(kk, -1) - vv) < 0.01 for n, v in keys.items() for kk, vv in v.items()), +} +json.dump(geometry, open(out, "w"), indent=2, sort_keys=True) +open(out, "a").write("\n") +print(f"apple-geometry: {out}") +for k, v in cap.items(): + print(f" cap.{k}: {v}") +print(f" legend: {geometry['legend']}") +print(f" colors: {geometry['colors']}") +print(f" dark face identical: {geometry['darkFaceIdentical']}") +PY +echo "screenshots: $WORK/apple-keyboard-light.png, $WORK/apple-keyboard-dark.png" diff --git a/scripts/design-diff.swift b/scripts/design-diff.swift index 9b9f865e..28817704 100755 --- a/scripts/design-diff.swift +++ b/scripts/design-diff.swift @@ -1,9 +1,4 @@ -#!/usr/bin/env swift // Pixel tools for the design loop, with no dependencies beyond AppKit — the // same shape as beautify.swift and screenshot.swift. Three commands: -// -// swift scripts/design-diff.swift crop [--expect-height ] -// Cuts the keyboard out of a whole-screen simulator capture: finds the -// magenta (#FF00FF) registration border the gallery's -BlurtGalleryBare -// mode draws round the row and writes what is inside it. With +#!/usr/bin/env swift // Pixel tools for the design loop, with no dependencies beyond AppKit — the // same shape as beautify.swift and screenshot.swift. Four commands: // // swift scripts/design-diff.swift crop [--expect-height ] // Cuts the keyboard out of a whole-screen simulator capture: finds the // magenta (#FF00FF) registration border the gallery's -BlurtGalleryBare // mode draws round the row and writes what is inside it. With // --expect-height, fails unless the crop is that tall (±1 px). // // swift scripts/design-diff.swift diff --out --json @@ -20,6 +15,10 @@ // swift scripts/design-diff.swift sheet --out --columns [--scale ] =... // A contact sheet: the images in a grid with their captions under them. // +// swift scripts/design-diff.swift measure --scale 3 --surface x,y --probe x,y... [--column x:y0:y1]... +// The visual geometry of the keys in a screenshot of the system keyboard +// (widths, gaps, heights, corner radius, the surface's edges), in points. +// // Every image is read into an 8-bit sRGB RGBA buffer through CoreGraphics, so // the numbers do not depend on how the PNG was tagged. @@ -286,12 +285,166 @@ func sheet(_ args: [String]) { // MARK: - main +// MARK: - measure + +/// The system keyboard's visual geometry off a screenshot, for +/// scripts/apple-geometry.sh: XCUITest reports touch cells, which tile the +/// row with no gaps, so the caps' widths, gaps, heights and corner radius are +/// read from the pixels. Every coordinate on the command line is in points; +/// `--scale` is the capture's pixels per point. +/// +/// measure --scale 3 --surface x,y --probe x,y [--probe x,y]... [--column x:y0:y1]... +/// +/// `--surface` samples the keyboard's ground colour; a pixel that differs +/// from it by more than the threshold is part of a cap. Each `--probe` names a +/// point inside a cap: the cap's top and bottom are found up and down that +/// column, then the row 3 pt below the top is scanned for every cap on it +/// (left, width, and the gap to the next), and the corner radius is fitted +/// from the cap's top-left inset over its first rows. `--column` lists where +/// the colour changes along a column, for finding the surface's top edge. +func measure(_ args: [String]) { + var args = args + guard let scaleText = flag("--scale", in: &args), let scale = Double(scaleText), + let surfaceText = flag("--surface", in: &args) + else { fail("measure --scale --surface x,y [--probe x,y]... [--column x:y0:y1]...") } + let probes = flags("--probe", in: &args) + let columns = flags("--column", in: &args) + guard args.count == 1 else { fail("measure: one png") } + let image = load(args[0]) + func point(_ text: String) -> (x: Int, y: Int) { + let parts = text.split(separator: ",").compactMap { Double($0) } + guard parts.count == 2 else { fail("measure: a point is x,y in points, got \(text)") } + return (Int((parts[0] * scale).rounded()), Int((parts[1] * scale).rounded())) + } + let surfaceAt = point(surfaceText) + let surface = image[surfaceAt.x, surfaceAt.y] + let threshold = 14 + func isCap(_ x: Int, _ y: Int) -> Bool { + guard x >= 0, y >= 0, x < image.width, y < image.height else { return false } + let p = image[x, y] + return max(abs(p.r - surface.r), abs(p.g - surface.g), abs(p.b - surface.b)) > threshold + } + func pt(_ px: Int) -> Double { (Double(px) / scale * 1000).rounded() / 1000 } + var report: [String: Any] = [ + "surface": String(format: "#%02X%02X%02X", surface.r, surface.g, surface.b), "scale": scale, + ] + var caps: [[String: Any]] = [] + for probeText in probes { + let probe = point(probeText) + guard isCap(probe.x, probe.y) else { + caps.append(["probe": probeText, "error": "not on a cap"]) + continue + } + // The cap's top and bottom along the probe's column. A glyph's + // anti-aliased edge can land on the surface's colour for a pixel, so an + // edge is only an edge when the surface holds for a few pixels. + let hold = Int(scale) + 1 + func surfaceHolds(_ x: Int, _ y: Int, step: Int) -> Bool { + (0.. 0, !surfaceHolds(probe.x, top - 1, step: -1) { top -= 1 } + var bottom = probe.y + while bottom < image.height - 1, !surfaceHolds(probe.x, bottom + 1, step: 1) { bottom += 1 } + // Every cap along the row through the cap's middle (a glyph is inside a + // cap, never the surface's colour for long): runs of cap pixels, merged + // across glyph pixels, with the gaps between. + let scanY = (top + bottom) / 2 + var runs: [(left: Int, right: Int)] = [] + var x = 0 + while x < image.width { + guard isCap(x, scanY) else { + x += 1 + continue + } + let left = x + var lastCap = x + while x < image.width { + if isCap(x, scanY) { + lastCap = x + } else if x - lastCap >= hold { + break + } + x += 1 + } + runs.append((left, lastCap)) + x = lastCap + 1 + } + guard let own = runs.first(where: { $0.left <= probe.x && probe.x <= $0.right }) else { + caps.append(["probe": probeText, "error": "no run under the probe"]) + continue + } + // The top-left corner: the inset of the first cap pixel on each of the + // first rows, fitted to a circle of radius r (inset = r − √(2ry − y²)). + var insets: [(y: Double, inset: Double)] = [] + let rowsToFit = Int(12 * scale) + for i in 0..= candidate ? 0 : candidate - (2 * candidate * sample.y - sample.y * sample.y).squareRoot() + return sum + (predicted - sample.inset) * (predicted - sample.inset) + } + if error < bestError { + bestError = error + bestRadius = candidate + } + candidate += 0.25 + } + // The fill, read just under the top edge where no glyph is. + let color = image[probe.x, min(bottom, top + Int(3 * scale))] + caps.append([ + "probe": probeText, + "fill": String(format: "#%02X%02X%02X", color.r, color.g, color.b), + "top": pt(top), "bottom": pt(bottom + 1), "height": pt(bottom + 1 - top), + "left": pt(own.left), "width": pt(own.right + 1 - own.left), + "radius": (bestRadius / scale * 100).rounded() / 100, + "row": runs.map { ["left": pt($0.left), "width": pt($0.right + 1 - $0.left)] }, + "gaps": zip(runs, runs.dropFirst()).map { pt($1.left - $0.right - 1) }, + ]) + } + report["caps"] = caps + var edges: [[String: Any]] = [] + for columnText in columns { + let parts = columnText.split(separator: ":").compactMap { Double($0) } + guard parts.count == 3 else { fail("measure: a column is x:y0:y1 in points") } + let x = Int((parts[0] * scale).rounded()) + var changes: [[String: Any]] = [] + let y0 = max(0, min(Int((parts[1] * scale).rounded()), image.height - 1)) + let y1 = max(y0, min(Int((parts[2] * scale).rounded()), image.height - 1)) + var previous = image[x, y0] + for y in y0...y1 { + let p = image[x, y] + if max(abs(p.r - previous.r), abs(p.g - previous.g), abs(p.b - previous.b)) > threshold { + changes.append(["y": pt(y), "to": String(format: "#%02X%02X%02X", p.r, p.g, p.b)]) + } + previous = p + } + edges.append(["column": columnText, "changes": changes]) + } + report["columns"] = edges + guard let data = try? JSONSerialization.data(withJSONObject: report, options: [.prettyPrinted, .sortedKeys]) else { + fail("measure: could not encode the report") + } + print(String(decoding: data, as: UTF8.self)) +} + var arguments = Array(CommandLine.arguments.dropFirst()) -guard let command = arguments.first else { fail("usage: design-diff.swift crop|diff|sheet …") } +guard let command = arguments.first else { fail("usage: design-diff.swift crop|diff|sheet|measure …") } arguments.removeFirst() switch command { case "crop": crop(arguments) case "diff": diff(arguments) case "sheet": sheet(arguments) +case "measure": measure(arguments) default: fail("unknown command \(command)") } diff --git a/scripts/ios-test.sh b/scripts/ios-test.sh index e4627257..e235c057 100755 --- a/scripts/ios-test.sh +++ b/scripts/ios-test.sh @@ -8,7 +8,9 @@ # this Mac (or CI runner) has. The engine's own tests are `swift test` # (scripts/check.sh); these cover the iPhone code's pure logic — the App Group # contract, the keyboard's rules, term packs. The per-test log is in the -# result bundle the last line names. +# result bundle the last line names. A failure never triggers xcodebuild's +# sysdiagnose collection (`-collect-test-diagnostics never`): that step takes +# ten minutes on this simulator and the result bundle already says what failed. set -euo pipefail REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" @@ -29,7 +31,7 @@ ios_wait_booted "$UDID" RESULTS="$DERIVED/BlurtiOSTests-$(date +%Y%m%d-%H%M%S).xcresult" xcodebuild test -project "$REPO_ROOT/App/BlurtiOS/BlurtiOS.xcodeproj" -scheme BlurtiOS \ -destination "platform=iOS Simulator,id=$UDID" -derivedDataPath "$DERIVED" \ - -resultBundlePath "$RESULTS" "${IOS_SIM_SIGNING[@]}" -quiet + -resultBundlePath "$RESULTS" "${IOS_SIM_SIGNING[@]}" -collect-test-diagnostics never -quiet xcrun xcresulttool get test-results summary --path "$RESULTS" 2>/dev/null | python3 -c ' import json, sys d = json.load(sys.stdin) From a9c9b9b1916f99e30346498d0b7f7acfb33713d3 Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Tue, 29 Sep 2026 17:01:40 -0400 Subject: [PATCH 52/79] iOS: the rules out of the views, no visual change MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The keyboard's and the home screen's logic now lives in files with no view bodies, unit-tested, and the views only draw: - `KeyboardInteraction` — the touch rules: a key acts on release under 12 pt of travel, the mic cancels past 24, a swipe flips the panel past 48 pt sideways and 1.5× the vertical; `MicPressSequencer` walks the mic's press (the 90 ms wait before a press, the tap quicker than that, the swipe that cancels the timer or undoes a press that went out). - `VoiceState` — what the voice control shows, from the App Group's phase snapshot on the keyboard and the engine's overlay state in the app: the ring (still, sweeping, solid green or orange), a glyph, dimming, whether the meter is up, what VoiceOver says. One struct for both, so the key and the hero cannot tell different stories. - `KeyboardMotion` — the ring's period and the redraw cap (from BrandOrb, whose view had no caller). - `HomeStatus` — the home screen's words: headline, subline, setup, landed. `KeyboardViews.swift` is split into KeyboardRootView, SlimBarView, PanelView, MicControl (the gesture host, on the sequencer) and KeyCap (with KeyChrome's press style); VoiceBar keeps only the bar, with AddTermKey, TermField and WaveformMeter (its liquid variant and `wave/liquid` dropped) in their own files. HomeView keeps state and composition; HomeHero, SetupCard, StyleChips and RecentSection draw. The design-literal lint now globs the keyboard's sources minus its logic files, so a new view is linted by default and a deleted one no longer breaks the check. Gate: 26 stills (panel/full/slim × light/dark × the golden states) before and after are byte-identical; 68 tests; periphery clean. Co-Authored-By: Claude Fable 5.1 --- .../BlurtKeyboard/Sources/AddTermKey.swift | 28 ++ .../BlurtKeyboard/Sources/BrandOrb.swift | 54 --- .../Sources/FullKeyboardView.swift | 3 +- .../BlurtKeyboard/Sources/KeyCap.swift | 102 +++++ .../BlurtKeyboard/Sources/KeyChrome.swift | 19 - .../Sources/KeyboardInteraction.swift | 94 +++++ .../Sources/KeyboardModel+Mic.swift | 3 + .../Sources/KeyboardMotion.swift | 14 + .../Sources/KeyboardPalette.swift | 4 +- .../Sources/KeyboardRootView.swift | 66 +++ .../BlurtKeyboard/Sources/KeyboardViews.swift | 386 ------------------ .../BlurtKeyboard/Sources/MicControl.swift | 155 +++++++ .../BlurtKeyboard/Sources/PanelView.swift | 31 ++ .../BlurtKeyboard/Sources/PrismOrb.swift | 1 - .../BlurtKeyboard/Sources/SlimBarView.swift | 15 + .../BlurtKeyboard/Sources/TermField.swift | 66 +++ .../BlurtKeyboard/Sources/VoiceBar.swift | 187 +-------- .../BlurtKeyboard/Sources/VoiceState.swift | 144 +++++++ .../BlurtKeyboard/Sources/WaveformMeter.swift | 50 +++ App/BlurtiOS/BlurtiOS/Sources/HomeHero.swift | 114 ++++++ .../BlurtiOS/Sources/HomeStatus.swift | 44 ++ App/BlurtiOS/BlurtiOS/Sources/HomeView.swift | 322 +-------------- .../BlurtiOS/Sources/RecentSection.swift | 44 ++ App/BlurtiOS/BlurtiOS/Sources/SetupCard.swift | 80 ++++ .../BlurtiOS/Sources/StyleChips.swift | 58 +++ .../BlurtiOSProbe/AppleKeyboardProbe.swift | 2 +- .../BlurtiOSTests/HomeStatusTests.swift | 45 ++ .../KeyboardInteractionTests.swift | 79 ++++ .../BlurtiOSTests/VoiceStateTests.swift | 64 +++ App/BlurtiOS/DESIGN.md | 1 - App/BlurtiOS/Design/figma/tokens.js | 1 - App/BlurtiOS/Design/tokens.json | 4 - App/BlurtiOS/Shared/BlurtBrand.swift | 17 - App/BlurtiOS/Shared/DesignTokens.swift | 3 - scripts/design-sync.sh | 31 +- 35 files changed, 1336 insertions(+), 995 deletions(-) create mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/AddTermKey.swift delete mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/BrandOrb.swift create mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/KeyCap.swift delete mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/KeyChrome.swift create mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/KeyboardInteraction.swift create mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/KeyboardMotion.swift create mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/KeyboardRootView.swift delete mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift create mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/MicControl.swift create mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/PanelView.swift create mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/SlimBarView.swift create mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/TermField.swift create mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/VoiceState.swift create mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/WaveformMeter.swift create mode 100644 App/BlurtiOS/BlurtiOS/Sources/HomeHero.swift create mode 100644 App/BlurtiOS/BlurtiOS/Sources/HomeStatus.swift create mode 100644 App/BlurtiOS/BlurtiOS/Sources/RecentSection.swift create mode 100644 App/BlurtiOS/BlurtiOS/Sources/SetupCard.swift create mode 100644 App/BlurtiOS/BlurtiOS/Sources/StyleChips.swift create mode 100644 App/BlurtiOS/BlurtiOSTests/HomeStatusTests.swift create mode 100644 App/BlurtiOS/BlurtiOSTests/KeyboardInteractionTests.swift create mode 100644 App/BlurtiOS/BlurtiOSTests/VoiceStateTests.swift diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/AddTermKey.swift b/App/BlurtiOS/BlurtKeyboard/Sources/AddTermKey.swift new file mode 100644 index 00000000..83f34fad --- /dev/null +++ b/App/BlurtiOS/BlurtKeyboard/Sources/AddTermKey.swift @@ -0,0 +1,28 @@ +import SwiftUI + +/// The small + beside the orb (and in the panel's corner): a new key term. +/// A bare glyph, quiet until it is needed; a check for a moment after one +/// was saved. +struct AddTermKey: View { + var model: KeyboardModel + @Environment(\.keyboardPalette) private var palette + + var body: some View { + Button { + model.beginAddingTerm() + } label: { + Image(systemName: model.termSavedAt == nil ? "plus" : "checkmark") + .font(.system(size: DesignTokens.Typography.sizeGlyph, weight: DesignTokens.Typography.weightGlyph)) + .foregroundStyle( + model.termSavedAt == nil ? palette.keyText.opacity(DesignTokens.Metrics.opacityLegendMuted) : palette.signal + ) + .frame(width: DesignTokens.Metrics.glyphHit, height: DesignTokens.Metrics.glyphHit) + .contentShape(Circle()) + .contentTransition(.symbolEffect(.replace)) + } + .buttonStyle(KeyPressStyle()) + .accessibilityLabel("Add a key term") + .disabled(!model.hasFullAccess) + .opacity(model.hasFullAccess ? 1 : DesignTokens.Metrics.opacityDisabled) + } +} diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/BrandOrb.swift b/App/BlurtiOS/BlurtKeyboard/Sources/BrandOrb.swift deleted file mode 100644 index 24b55872..00000000 --- a/App/BlurtiOS/BlurtKeyboard/Sources/BrandOrb.swift +++ /dev/null @@ -1,54 +0,0 @@ -import BlurtEngine -import SwiftUI - -/// The redraw cap for the keyboard's continuous motion — the ring's sweep, the -/// meter's idle wave. The Mac pill reads the same number from the engine: the -/// level feed moves at this cadence, so drawing faster only burns the -/// keyboard's tight energy and memory budget. -let keyboardAnimationInterval = MicCapture.meterIntervalSeconds - -/// The brand orb, as the Mac pill draws it (`App/Blurt/Blurt/Overlay/BrandOrb.swift`): -/// the gradient disc, and a hairline ring that sweeps round it while something -/// is happening. It spins rather than pulses — a pulse says "alive", a sweep -/// says "working, and still going" — and the disc underneath never moves. -/// -/// Sized by the caller: the app's home screen draws it as the hero; the -/// keyboard's mic key draws its own capsule so it can grow into the wave. -struct BrandOrb: View { - var diameter: CGFloat - /// Whether the ring sweeps. Off under Reduce Motion, where the ring is still - /// drawn — it is part of the mark — but holds still. - var animated: Bool - var ringWidth = DesignTokens.Metrics.ringStill - - /// One turn every 1.6 s: the Mac's cadence. - static let period = DesignTokens.Motion.ringPeriod - - var body: some View { - Circle() - .fill(BlurtBrand.orbGradient) - .frame(width: diameter, height: diameter) - .overlay { ring } - .accessibilityHidden(true) - } - - @ViewBuilder private var ring: some View { - if animated { - // The angle is a pure function of the clock (engine geometry), so the - // sweep can't drift or restart mid-turn when the state beside it changes. - TimelineView(.animation(minimumInterval: keyboardAnimationInterval)) { timeline in - ringShape.rotationEffect( - .degrees( - MeterBarGeometry.rotationDegrees( - time: timeline.date.timeIntervalSinceReferenceDate, period: Self.period))) - } - } else { - ringShape - } - } - - /// `strokeBorder` so the ring sits inside the disc instead of fringing it. - private var ringShape: some View { - Circle().strokeBorder(BlurtBrand.orbRingGradient, lineWidth: ringWidth) - } -} diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift b/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift index bcd191bb..1f3d7c4b 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift @@ -103,8 +103,7 @@ private struct LetterKey: View { .onEnded { value in pressed = false // A touch that travelled was a swipe (the panel's carousel), not a tap. - guard abs(value.translation.width) < KeyPress.tapTravel, abs(value.translation.height) < KeyPress.tapTravel - else { return } + guard KeyboardInteraction.isTap(value.translation) else { return } action() } ) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyCap.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyCap.swift new file mode 100644 index 00000000..1e99fe0b --- /dev/null +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyCap.swift @@ -0,0 +1,102 @@ +import SwiftUI + +/// One ordinary key: a legend on a cap in the current palette; `dark` for the +/// modifier keys, a step darker as on the system keyboard; `bare` for a glyph +/// with no cap at all (the panel's cancel). `flexible` keys (the space bar) +/// take the width they're given, `width` fixes one, and the rest are the +/// iPhone's 123 key wide. +struct KeyCap: View { + var title: String? + var systemImage: String? + var tint: Color? + var flexible = false + var dark = false + var bare = false + var width: CGFloat? + var action: () -> Void + @Environment(\.keyboardPalette) private var palette + + static let height = DesignTokens.Metrics.keyHeight + + init( + title: String? = nil, systemImage: String? = nil, tint: Color? = nil, flexible: Bool = false, + dark: Bool = false, bare: Bool = false, width: CGFloat? = nil, action: @escaping () -> Void + ) { + self.title = title + self.systemImage = systemImage + self.tint = tint + self.flexible = flexible + self.dark = dark + self.bare = bare + self.width = width + self.action = action + } + + var body: some View { + Group { + if let systemImage { + Image(systemName: systemImage) + } else { + Text(title ?? "") + } + } + .font(.system(size: DesignTokens.Typography.sizeLegend, weight: DesignTokens.Typography.weightLegend)) + .foregroundStyle(tint ?? palette.keyText) + .opacity(DesignTokens.Metrics.opacityLegend) + .frame(maxWidth: flexible ? .infinity : nil) + .frame(width: width) + .frame(minWidth: width == nil ? DesignTokens.Metrics.keyMinWidth : nil, minHeight: Self.height) + .padding(.horizontal, flexible || width != nil ? 0 : DesignTokens.Metrics.keyPad) + .keyCap(bare ? .clear : dark ? palette.keyDark : palette.key) + .keyPress(action) + .accessibilityLabel(title ?? systemImage ?? "") + } +} + +extension View { + /// The cap under a key's legend: the palette's fill at the corner radius and + /// nothing else — flat. No drop, no edge, no gloss. + func keyCap(_ fill: Color) -> some View { + background(fill, in: RoundedRectangle(cornerRadius: KeyboardPalette.keyRadius)) + } + + /// A key's touch: lights while the finger is down, acts on release — and + /// only if the finger didn't travel, so a swipe across a key (the panel's + /// carousel) never types. The system keyboard's own rule + /// (`KeyboardInteraction.isTap`). + func keyPress(_ action: @escaping () -> Void) -> some View { + modifier(KeyPress(action: action)) + } +} + +struct KeyPress: ViewModifier { + let action: () -> Void + @State private var pressed = false + + func body(content: Content) -> some View { + content + .brightness(pressed ? DesignTokens.Metrics.opacityPressBrighten : 0) + .animation(.easeOut(duration: DesignTokens.Motion.keyPress), value: pressed) + .contentShape(Rectangle()) + .accessibilityAddTraits(.isButton) + .simultaneousGesture( + DragGesture(minimumDistance: 0) + .onChanged { _ in pressed = true } + .onEnded { value in + pressed = false + guard KeyboardInteraction.isTap(value.translation) else { return } + action() + } + ) + } +} + +/// A key lightens while the finger is on it, the way the system's change +/// shade, instead of the default button dimming. +struct KeyPressStyle: ButtonStyle { + func makeBody(configuration: Configuration) -> some View { + configuration.label + .brightness(configuration.isPressed ? DesignTokens.Metrics.opacityPressBrighten : 0) + .animation(.easeOut(duration: DesignTokens.Motion.keyPress), value: configuration.isPressed) + } +} diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyChrome.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyChrome.swift deleted file mode 100644 index d2e2f885..00000000 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyChrome.swift +++ /dev/null @@ -1,19 +0,0 @@ -import SwiftUI - -extension View { - /// The cap under a key's legend: the palette's fill at the corner radius and - /// nothing else — flat. No drop, no edge, no gloss. - func keyCap(_ fill: Color) -> some View { - background(fill, in: RoundedRectangle(cornerRadius: KeyboardPalette.keyRadius)) - } -} - -/// A key lightens while the finger is on it, the way the system's change -/// shade, instead of the default button dimming. -struct KeyPressStyle: ButtonStyle { - func makeBody(configuration: Configuration) -> some View { - configuration.label - .brightness(configuration.isPressed ? DesignTokens.Metrics.opacityPressBrighten : 0) - .animation(.easeOut(duration: DesignTokens.Motion.keyPress), value: configuration.isPressed) - } -} diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardInteraction.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardInteraction.swift new file mode 100644 index 00000000..5a7a332a --- /dev/null +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardInteraction.swift @@ -0,0 +1,94 @@ +import CoreGraphics +import Foundation + +/// The keyboard's touch rules, out of the views so they can be tested and +/// never drift between layouts (DESIGN.md › The two processes, and every +/// number): a key acts on release and only if the finger didn't travel; the +/// mic key waits a beat before it presses, so a swipe that starts on it never +/// starts a dictation it must then cancel; a horizontal swipe flips the +/// panel's carousel. +nonisolated enum KeyboardInteraction { + /// The most a touch may travel and still be a tap on a key. + static let tapTravel: CGFloat = 12 + /// A touch on the mic that travelled this far was a swipe, not a press. + static let micTravel: CGFloat = 24 + /// A swipe flips the panel once it has gone this far sideways… + static let swipeDistance: CGFloat = 48 + /// …and more sideways than up or down, by this factor. + static let swipeRatio: CGFloat = 1.5 + /// How long a touch must stay before it counts as a press rather than the + /// start of a swipe — well under a tap's own duration for a hold. + static let micPressDelay: Duration = .milliseconds(90) + + enum FlipDirection: Equatable { + /// The finger moved left: the incoming page arrives from the trailing edge. + case towardsLeading + case towardsTrailing + } + + /// Which way the panel flips for this drag, or nil if the drag was not a swipe. + static func flip(_ translation: CGSize) -> FlipDirection? { + let dx = translation.width + guard abs(dx) > swipeDistance, abs(dx) > abs(translation.height) * swipeRatio else { return nil } + return dx < 0 ? .towardsLeading : .towardsTrailing + } + + static func isTap(_ translation: CGSize) -> Bool { + abs(translation.width) < tapTravel && abs(translation.height) < tapTravel + } + + static func micTravelled(_ translation: CGSize) -> Bool { + abs(translation.width) > micTravel || abs(translation.height) > micTravel + } +} + +/// The mic key's press, step by step: finger down arms a timer; the timer +/// firing sends the press; finger up decides. A tap quicker than the delay is +/// still a tap (press and release together); a swipe cancels the timer, or +/// undoes a press that already went out; nothing else happens. The view owns +/// the timer and the model calls; this owns the decisions. +nonisolated struct MicPressSequencer: Equatable { + enum Outcome: Equatable { + /// Release the key: send the press first if the timer never fired. + case tap(needsDown: Bool) + /// A swipe after the press went out: undo it. + case cancelSentPress + /// A swipe before the press went out: nothing to undo. + case nothing + } + + private(set) var pressed = false + private(set) var timerArmed = false + private(set) var pressSent = false + + /// The finger touched (or moved, again). True the first time: arm the timer. + mutating func began() -> Bool { + guard !pressed else { return false } + pressed = true + timerArmed = true + return true + } + + /// The finger moved. True when the timer must be cancelled: it travelled + /// before the press went out. + mutating func moved(travelled: Bool) -> Bool { + guard travelled, timerArmed, !pressSent else { return false } + timerArmed = false + return true + } + + /// The timer fired. True when the press goes out now. + mutating func delayFired() -> Bool { + guard pressed, timerArmed else { return false } + timerArmed = false + pressSent = true + return true + } + + /// The finger lifted. + mutating func ended(travelled: Bool) -> Outcome { + defer { self = MicPressSequencer() } + if travelled { return pressSent ? .cancelSentPress : .nothing } + return .tap(needsDown: !pressSent) + } +} diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Mic.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Mic.swift index 674719ca..2603945c 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Mic.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Mic.swift @@ -8,6 +8,9 @@ extension KeyboardModel { /// Whether a tap on the orb can do anything but open the app. var isReady: Bool { hasFullAccess && isListening } + /// What the voice control shows, from the phase the app published. + var voiceState: VoiceState { VoiceState(snapshot: snapshot, isReady: isReady) } + /// Finger down on the orb. Ignored, with a buzz, while the last dictation /// is still being transcribed: a press then would be dropped by the engine /// and the user would talk into nothing. diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardMotion.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardMotion.swift new file mode 100644 index 00000000..0233eee4 --- /dev/null +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardMotion.swift @@ -0,0 +1,14 @@ +import BlurtEngine +import Foundation + +/// The redraw cap for the keyboard's continuous motion — the ring's sweep, the +/// meter's idle wave. The Mac pill reads the same number from the engine: the +/// level feed moves at this cadence, so drawing faster only burns the +/// keyboard's tight energy and memory budget. +let keyboardAnimationInterval = MicCapture.meterIntervalSeconds + +/// The keyboard's clocks, in one place. +nonisolated enum KeyboardMotion { + /// One turn of the ring every 1.6 s: the Mac's cadence. + static let ringPeriod = DesignTokens.Motion.ringPeriod +} diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift index aacc8ec3..15e36361 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift @@ -76,7 +76,9 @@ struct KeyboardPalette: Equatable, Identifiable { /// The theme with this id in the given appearance, or the brand's for an id /// that no longer exists (the old `system` default, a retired theme). static func resolve(_ id: String, dark: Bool) -> KeyboardPalette { - dark ? brandDark : brandLight + // One theme so far: a known id and a retired one land in the same place. + guard all.contains(where: { $0.id == id }) else { return dark ? brandDark : brandLight } + return dark ? brandDark : brandLight } static func == (lhs: KeyboardPalette, rhs: KeyboardPalette) -> Bool { lhs.id == rhs.id && lhs.face == rhs.face } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardRootView.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardRootView.swift new file mode 100644 index 00000000..0c2870b6 --- /dev/null +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardRootView.swift @@ -0,0 +1,66 @@ +import SwiftUI + +/// Picks the layout the user chose. All three share the voice bar and the +/// mic control, `KeyCap`, and the same model underneath; they differ in how +/// much keyboard surrounds the mic. The surface is the face's, fixed whatever +/// the host app's appearance — the keyboard floats over whichever app the +/// user is typing in, like the Mac pill — at the iPhone keyboard's own +/// spacing. +struct KeyboardRootView: View { + var model: KeyboardModel + + /// The keyboard's top margin (and the slim bar's bottom): the arithmetic in + /// `KeyboardLayout.height` is built on it and the palette's row gap. + static let verticalMargin = DesignTokens.Metrics.marginVertical + /// Under a bottom row of keys, the iPhone's own margin. + static let bottomMarginKeys = DesignTokens.Metrics.marginBottomKeys + + var body: some View { + Group { + switch model.effectiveLayout { + case .slimBar: SlimBarView(model: model) + case .panel: + PanelView(model: model) + .id("panel") + .transition(flip) + case .full: + FullKeyboardView(model: model) + .id(model.layout == .panel ? "panel-keys" : "full") + .transition(flip) + } + } + .padding(.horizontal, KeyboardPalette.margin) + .padding(.top, Self.verticalMargin) + .padding(.bottom, model.effectiveLayout == .slimBar ? Self.verticalMargin : Self.bottomMarginKeys) + .frame(maxWidth: .infinity, maxHeight: .infinity) + .background { SurfaceFinish.Ground(surface: model.palette.surface) } + .overlay { SurfaceFinish.Grain() } + .clipped() + .environment(\.keyboardPalette, model.palette) + .simultaneousGesture(swipe, including: model.layout == .panel ? .all : .subviews) + .animation(reduceMotion ? nil : .easeInOut(duration: DesignTokens.Motion.flip), value: model.panelShowsKeys) + } + + @Environment(\.accessibilityReduceMotion) private var systemReduceMotion + @Environment(\.keyboardMotionHeld) private var motionHeld + private var reduceMotion: Bool { systemReduceMotion || motionHeld } + + /// The carousel's slide: the incoming page arrives from the side the finger + /// moved towards, the outgoing one leaves the other way. + private var flip: AnyTransition { + model.flipTowardsLeading + ? .asymmetric(insertion: .move(edge: .trailing), removal: .move(edge: .leading)) + : .asymmetric(insertion: .move(edge: .leading), removal: .move(edge: .trailing)) + } + + /// A horizontal swipe anywhere on the panel flips it; taps and holds on keys + /// never travel this far, and the keys ignore a touch that did + /// (`KeyboardInteraction`). + private var swipe: some Gesture { + DragGesture(minimumDistance: DesignTokens.Metrics.gestureSwipeMin) + .onEnded { value in + guard let direction = KeyboardInteraction.flip(value.translation) else { return } + model.flipPanel(towardsLeading: direction == .towardsLeading) + } + } +} diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift deleted file mode 100644 index 25324ac0..00000000 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift +++ /dev/null @@ -1,386 +0,0 @@ -import BlurtEngine -import SwiftUI - -/// Picks the layout the user chose. All three share `VoiceBar`/`MicKey` and -/// `KeyCap`, and the same model underneath; they differ in how much keyboard -/// surrounds the mic. The surface is the theme's, fixed whatever the host -/// app's appearance — the keyboard floats over whichever app the user is -/// typing in, like the Mac pill — at the iPhone keyboard's own spacing. -struct KeyboardRootView: View { - var model: KeyboardModel - - /// The keyboard's top margin (and the slim bar's bottom): the arithmetic in - /// `KeyboardLayout.height` is built on it and the palette's row gap. - static let verticalMargin = DesignTokens.Metrics.marginVertical - /// Under a bottom row of keys, the iPhone's own margin. - static let bottomMarginKeys = DesignTokens.Metrics.marginBottomKeys - - var body: some View { - Group { - switch model.effectiveLayout { - case .slimBar: SlimBarView(model: model) - case .panel: - PanelView(model: model) - .id("panel") - .transition(flip) - case .full: - FullKeyboardView(model: model) - .id(model.layout == .panel ? "panel-keys" : "full") - .transition(flip) - } - } - .padding(.horizontal, KeyboardPalette.margin) - .padding(.top, Self.verticalMargin) - .padding(.bottom, model.effectiveLayout == .slimBar ? Self.verticalMargin : Self.bottomMarginKeys) - .frame(maxWidth: .infinity, maxHeight: .infinity) - .background { SurfaceFinish.Ground(surface: model.palette.surface) } - .overlay { SurfaceFinish.Grain() } - .clipped() - .environment(\.keyboardPalette, model.palette) - .simultaneousGesture(swipe, including: model.layout == .panel ? .all : .subviews) - .animation(reduceMotion ? nil : .easeInOut(duration: DesignTokens.Motion.flip), value: model.panelShowsKeys) - } - - @Environment(\.accessibilityReduceMotion) private var systemReduceMotion - @Environment(\.keyboardMotionHeld) private var motionHeld - private var reduceMotion: Bool { systemReduceMotion || motionHeld } - - /// The carousel's slide: the incoming page arrives from the side the finger - /// moved towards, the outgoing one leaves the other way. - private var flip: AnyTransition { - model.flipTowardsLeading - ? .asymmetric(insertion: .move(edge: .trailing), removal: .move(edge: .leading)) - : .asymmetric(insertion: .move(edge: .leading), removal: .move(edge: .trailing)) - } - - /// A horizontal swipe anywhere on the panel flips it; taps and holds on keys - /// never travel this far, and the keys ignore a touch that did. - private var swipe: some Gesture { - DragGesture(minimumDistance: DesignTokens.Metrics.gestureSwipeMin) - .onEnded { value in - let dx = value.translation.width - guard abs(dx) > 48, abs(dx) > abs(value.translation.height) * 1.5 else { return } - model.flipPanel(towardsLeading: dx < 0) - } - } -} - -/// One row: the globe, the voice bar, delete and return. 60 pt. -struct SlimBarView: View { - var model: KeyboardModel - - var body: some View { - HStack(spacing: DesignTokens.Metrics.slimSpacing) { - if model.needsGlobe { KeyCap(systemImage: "globe", dark: true) { model.globe() } } - VoiceBar(model: model) - KeyCap(systemImage: "delete.left", dark: true) { model.deleteBackward() } - KeyCap(systemImage: "return", dark: true) { model.newline() } - } - } -} - -/// A big orb, centred, that dissipates into the wave while recording; cancel -/// in the corner while something is in flight; one row of keys. 216 pt. -struct PanelView: View { - var model: KeyboardModel - - var body: some View { - VStack(spacing: DesignTokens.Metrics.panelSpacing) { - Spacer(minLength: 0) - MicKey( - model: model, size: DesignTokens.Metrics.orbPanel, - wave: CGSize(width: DesignTokens.Metrics.wavePanelWidth, height: DesignTokens.Metrics.wavePanelHeight)) - Spacer(minLength: 0) - HStack(spacing: KeyboardPalette.keyGap) { - if model.needsGlobe { KeyCap(systemImage: "globe", dark: true) { model.globe() } } - KeyCap(title: "space", flexible: true) { model.space() } - KeyCap(systemImage: "delete.left", dark: true) { model.deleteBackward() } - KeyCap(systemImage: "return", dark: true) { model.newline() } - } - } - .overlay(alignment: .topTrailing) { - if !model.isSettled { - KeyCap(systemImage: "xmark", tint: BlurtBrand.errorOrange, bare: true) { model.cancel() } - .accessibilityLabel("Cancel dictation") - .transition(.opacity) - } - } - .overlay(alignment: .topLeading) { AddTermKey(model: model).padding(DesignTokens.Metrics.addtermInset) } - } -} - -/// The mic key is the brand orb, and it says everything without a word or a -/// glyph. Finger down starts, finger up decides tap (latched) or hold -/// (push-to-talk) — `KeyboardModel` runs the engine's gate. What it does: -/// dimmed when Blurt isn't ready (no Full Access, or the app isn't listening; -/// the tap opens Blurt); on a tap the ring sweeps as the app's orb does while -/// the mic comes up; then the orb dissipates — swells a little, softens to a -/// haze, is gone — and in its place the voice is a thin wave, flat on the -/// surface, for as long as you talk, and the wave is the key; on the stop -/// the wave fades and the orb condenses back with the ring sweeping while -/// the words come; then a green ring for a moment when they landed (the -/// violet drop with it), a clipboard on a green ring when they went to the -/// clipboard instead, an orange ring and an exclamation mark when something -/// failed. Each also has its haptic. -/// -/// Nothing snaps or springs: the orb and the wave cross over `waveFade`, -/// every other change over `stateFade`. Only the press itself answers at -/// once. -struct MicKey: View { - var model: KeyboardModel - var size: CGFloat - /// The wave the orb dissipates into while recording — wide and slim — - /// or nil for none (the orb stays). The key's frame is the wave's width - /// throughout, so nothing moves while the two cross; only the circle - /// answers a touch until the wave is up, then the wave's band does. - var wave: CGSize? - @State private var pressed = false - @Environment(\.accessibilityReduceMotion) private var systemReduceMotion - @Environment(\.keyboardMotionHeld) private var motionHeld - @Environment(\.keyboardPalette) private var palette - private var reduceMotion: Bool { systemReduceMotion || motionHeld } - - /// The orb and the wave crossing, either way. - static let waveFade = DesignTokens.Motion.waveFade - /// Every other change on the key: the ring, a glyph, the dimming. - static let stateFade = DesignTokens.Motion.stateFade - - var body: some View { - ZStack { - if let wave, isRecording { - WaveformMeter( - level: Float(model.snapshot.level), animated: !reduceMotion, color: palette.signal, - barWidth: WaveformMeter.slimBar, barSpacing: WaveformMeter.slimGap - ) - .frame(width: wave.width, height: wave.height) - .transition(.opacity) - } else { - PrismOrb(mood: mood, landedAt: model.resultLandedAt, animated: !reduceMotion) - .clipShape(Circle()) - .overlay { ring } - .frame(width: size, height: size) - .saturation(isReady ? 1 : DesignTokens.Metrics.opacityDimSaturation) - .opacity(isReady ? 1 : DesignTokens.Metrics.opacityDim) - .transition(reduceMotion ? .opacity : .dissipate(size: size)) - } - if let glyph { - Image(systemName: glyph) - .font( - .system(size: size * DesignTokens.Typography.ratioOrbGlyph, weight: DesignTokens.Typography.weightOrbGlyph) - ) - .foregroundStyle(.white) - .transition(.opacity) - } - } - .frame(width: wave.map { max($0.width, size) } ?? size, height: size) - .animation(.easeInOut(duration: Self.waveFade), value: isRecording) - .animation(.easeInOut(duration: Self.stateFade), value: model.snapshot.state) - .animation(.easeInOut(duration: Self.stateFade), value: isReady) - .scaleEffect(pressed ? DesignTokens.Metrics.pressScale : 1) - .animation(.easeOut(duration: DesignTokens.Motion.press), value: pressed) - .contentShape(showsWave ? AnyShape(Capsule()) : AnyShape(Circle())) - .accessibilityLabel(isReady ? (isRecording ? "Stop dictation" : "Dictate") : "Start Blurt") - .accessibilityValue(model.snapshot.state == .error ? model.snapshot.message ?? "Dictation failed." : "") - .accessibilityAddTraits(.isButton) - .simultaneousGesture( - DragGesture(minimumDistance: 0) - .onChanged { value in - if !pressed { - pressed = true - // The press waits a beat, so a swipe that starts on the orb (the - // panel's carousel) never starts a dictation it must then cancel. - pressTask = Task { [model] in - try? await Task.sleep(for: Self.pressDelay) - guard !Task.isCancelled else { return } - pressSent = true - model.micDown() - } - } - if Self.travelled(value), !pressSent { - pressTask?.cancel() - pressTask = nil - } - } - .onEnded { value in - pressed = false - pressTask?.cancel() - pressTask = nil - defer { pressSent = false } - if Self.travelled(value) { - // A swipe: undo a press that did go out, otherwise nothing. - if pressSent { model.cancel() } - return - } - // A tap quicker than the delay is still a tap. - if !pressSent { model.micDown() } - model.micUp() - } - ) - } - - /// How long a touch must stay before it counts as a press rather than the - /// start of a swipe — well under a tap's own duration for a hold. - static let pressDelay: Duration = .milliseconds(90) - @State private var pressTask: Task? - @State private var pressSent = false - - private static func travelled(_ value: DragGesture.Value) -> Bool { - abs(value.translation.width) > 24 || abs(value.translation.height) > 24 - } - - /// The ring: the app orb's sweep (one turn per 1.6 s, engine geometry) - /// while the mic comes up and while the words come; still, and solid green - /// or orange, for a notice; still while recording. - @ViewBuilder private var ring: some View { - let width = isWorking || isNotice ? DesignTokens.Metrics.ringActive : DesignTokens.Metrics.ringStill - if isWorking, !isRecording, !reduceMotion { - TimelineView(.animation(minimumInterval: keyboardAnimationInterval)) { timeline in - Circle() - .strokeBorder(BlurtBrand.orbRingGradient, lineWidth: width) - .rotationEffect( - .degrees( - MeterBarGeometry.rotationDegrees( - time: timeline.date.timeIntervalSinceReferenceDate, period: BrandOrb.period))) - } - } else if let ringColor { - Circle().strokeBorder(ringColor, lineWidth: width) - } else { - Circle().strokeBorder(BlurtBrand.orbRingGradient, lineWidth: width) - } - } - - private var isReady: Bool { model.isReady } - /// The wave is up, and is the key. - private var showsWave: Bool { isRecording && wave != nil } - - /// The orb's story from the phase: green, greener with the voice; the - /// violet drop is keyed to the moment the words landed, not to a phase. - private var mood: PrismOrb.Mood { - guard isReady else { return .off } - switch model.snapshot.state { - case .idle, .error, .pasted, .copied: return .idle - case .connecting: return .listening(level: 0) - case .recording: return .listening(level: Float(model.snapshot.level)) - case .processing: return .working - } - } - private var isRecording: Bool { isReady && model.snapshot.state == .recording } - private var isWorking: Bool { - switch model.snapshot.state { - case .connecting, .recording, .processing: isReady - case .idle, .pasted, .copied, .error: false - } - } - - private var isNotice: Bool { - switch model.snapshot.state { - case .pasted, .copied, .error: true - case .idle, .connecting, .recording, .processing: false - } - } - - private var ringColor: Color? { - switch model.snapshot.state { - case .error: BlurtBrand.errorOrange - case .pasted, .copied: BlurtBrand.greenOnDark - case .idle, .connecting, .recording, .processing: nil - } - } - - /// Only the two notices that need saying carry a glyph. - private var glyph: String? { - guard isReady else { return nil } - switch model.snapshot.state { - case .copied: return "doc.on.clipboard" - case .error: return "exclamationmark" - case .idle, .connecting, .recording, .processing, .pasted: return nil - } - } -} - -/// One ordinary key: a legend on a cap in the current palette; `dark` for the -/// modifier keys, a step darker as on the system keyboard; `bare` for a glyph -/// with no cap at all (the panel's cancel). `flexible` keys (the space bar) -/// take the width they're given, `width` fixes one, and the rest are 44 wide. -struct KeyCap: View { - var title: String? - var systemImage: String? - var tint: Color? - var flexible = false - var dark = false - var bare = false - var width: CGFloat? - var action: () -> Void - @Environment(\.keyboardPalette) private var palette - - static let height = DesignTokens.Metrics.keyHeight - - init( - title: String? = nil, systemImage: String? = nil, tint: Color? = nil, flexible: Bool = false, - dark: Bool = false, bare: Bool = false, width: CGFloat? = nil, action: @escaping () -> Void - ) { - self.title = title - self.systemImage = systemImage - self.tint = tint - self.flexible = flexible - self.dark = dark - self.bare = bare - self.width = width - self.action = action - } - - var body: some View { - Group { - if let systemImage { - Image(systemName: systemImage) - } else { - Text(title ?? "") - } - } - .font(.system(size: DesignTokens.Typography.sizeLegend, weight: DesignTokens.Typography.weightLegend)) - .foregroundStyle(tint ?? palette.keyText) - .opacity(DesignTokens.Metrics.opacityLegend) - .frame(maxWidth: flexible ? .infinity : nil) - .frame(width: width) - .frame(minWidth: width == nil ? DesignTokens.Metrics.keyMinWidth : nil, minHeight: Self.height) - .padding(.horizontal, flexible || width != nil ? 0 : DesignTokens.Metrics.keyPad) - .keyCap(bare ? .clear : dark ? palette.keyDark : palette.key) - .keyPress(action) - .accessibilityLabel(title ?? systemImage ?? "") - } -} - -extension View { - /// A key's touch: lights while the finger is down, acts on release — and - /// only if the finger didn't travel, so a swipe across a key (the panel's - /// carousel) never types. The system keyboard's own rule. - func keyPress(_ action: @escaping () -> Void) -> some View { - modifier(KeyPress(action: action)) - } -} - -struct KeyPress: ViewModifier { - let action: () -> Void - @State private var pressed = false - - /// The most a touch may travel and still be a tap. - static let tapTravel: CGFloat = 12 - - func body(content: Content) -> some View { - content - .brightness(pressed ? DesignTokens.Metrics.opacityPressBrighten : 0) - .animation(.easeOut(duration: DesignTokens.Motion.keyPress), value: pressed) - .contentShape(Rectangle()) - .accessibilityAddTraits(.isButton) - .simultaneousGesture( - DragGesture(minimumDistance: 0) - .onChanged { _ in pressed = true } - .onEnded { value in - pressed = false - guard abs(value.translation.width) < Self.tapTravel, abs(value.translation.height) < Self.tapTravel - else { return } - action() - } - ) - } -} diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/MicControl.swift b/App/BlurtiOS/BlurtKeyboard/Sources/MicControl.swift new file mode 100644 index 00000000..4ec4b02c --- /dev/null +++ b/App/BlurtiOS/BlurtKeyboard/Sources/MicControl.swift @@ -0,0 +1,155 @@ +import BlurtEngine +import SwiftUI + +/// The mic key is the brand orb, and it says everything without a word or a +/// glyph. Finger down starts, finger up decides tap (latched) or hold +/// (push-to-talk) — `KeyboardModel` runs the engine's gate, `MicPressSequencer` +/// the press's steps, `VoiceState` what shows. What it does: dimmed when +/// Blurt isn't ready (no Full Access, or the app isn't listening; the tap +/// opens Blurt); on a tap the ring sweeps as the app's orb does while the mic +/// comes up; then the orb dissipates — swells a little, softens to a haze, is +/// gone — and in its place the voice is a thin wave, flat on the surface, for +/// as long as you talk, and the wave is the key; on the stop the wave fades +/// and the orb condenses back with the ring sweeping while the words come; +/// then a green ring for a moment when they landed (the violet drop with it), +/// a clipboard on a green ring when they went to the clipboard instead, an +/// orange ring and an exclamation mark when something failed. Each also has +/// its haptic. +/// +/// Nothing snaps or springs: the orb and the wave cross over `wave-fade`, +/// every other change over `state-fade`. Only the press itself answers at +/// once. +struct MicControl: View { + var model: KeyboardModel + var size: CGFloat + /// The wave the orb dissipates into while recording — wide and slim — + /// or nil for none (the orb stays). The key's frame is the wave's width + /// throughout, so nothing moves while the two cross; only the circle + /// answers a touch until the wave is up, then the wave's band does. + var wave: CGSize? + @State private var pressed = false + @State private var press = MicPressSequencer() + @State private var pressTask: Task? + @Environment(\.accessibilityReduceMotion) private var systemReduceMotion + @Environment(\.keyboardMotionHeld) private var motionHeld + @Environment(\.keyboardPalette) private var palette + private var reduceMotion: Bool { systemReduceMotion || motionHeld } + + var body: some View { + let state = model.voiceState + let showsWave = state.isRecording && wave != nil + ZStack { + if let wave, state.isRecording { + WaveformMeter( + level: state.level, animated: !reduceMotion, color: palette.signal, + barWidth: WaveformMeter.slimBar, barSpacing: WaveformMeter.slimGap + ) + .frame(width: wave.width, height: wave.height) + .transition(.opacity) + } else { + PrismOrb(mood: Self.mood(state), landedAt: model.resultLandedAt, animated: !reduceMotion) + .clipShape(Circle()) + .overlay { ring(state) } + .frame(width: size, height: size) + .saturation(state.isReady ? 1 : DesignTokens.Metrics.opacityDimSaturation) + .opacity(state.isReady ? 1 : DesignTokens.Metrics.opacityDim) + .transition(reduceMotion ? .opacity : .dissipate(size: size)) + } + if let glyph = state.glyph { + Image(systemName: Self.symbol(glyph)) + .font( + .system(size: size * DesignTokens.Typography.ratioOrbGlyph, weight: DesignTokens.Typography.weightOrbGlyph) + ) + .foregroundStyle(.white) + .transition(.opacity) + } + } + .frame(width: wave.map { max($0.width, size) } ?? size, height: size) + .animation(.easeInOut(duration: DesignTokens.Motion.waveFade), value: state.isRecording) + .animation(.easeInOut(duration: DesignTokens.Motion.stateFade), value: state.phase) + .animation(.easeInOut(duration: DesignTokens.Motion.stateFade), value: state.isReady) + .scaleEffect(pressed ? DesignTokens.Metrics.pressScale : 1) + .animation(.easeOut(duration: DesignTokens.Motion.press), value: pressed) + .contentShape(showsWave ? AnyShape(Capsule()) : AnyShape(Circle())) + .accessibilityLabel(state.accessibilityLabel) + .accessibilityValue(state.accessibilityValue) + .accessibilityAddTraits(.isButton) + .simultaneousGesture( + DragGesture(minimumDistance: 0) + .onChanged { value in + pressed = true + if press.began() { + // The press waits a beat, so a swipe that starts on the orb (the + // panel's carousel) never starts a dictation it must then cancel. + pressTask = Task { [model] in + try? await Task.sleep(for: KeyboardInteraction.micPressDelay) + guard !Task.isCancelled else { return } + if press.delayFired() { model.micDown() } + } + } + if press.moved(travelled: KeyboardInteraction.micTravelled(value.translation)) { + pressTask?.cancel() + pressTask = nil + } + } + .onEnded { value in + pressed = false + pressTask?.cancel() + pressTask = nil + switch press.ended(travelled: KeyboardInteraction.micTravelled(value.translation)) { + case .tap(let needsDown): + // A tap quicker than the delay is still a tap. + if needsDown { model.micDown() } + model.micUp() + case .cancelSentPress: + model.cancel() + case .nothing: + break + } + } + ) + } + + /// The ring: the app orb's sweep (one turn per 1.6 s, engine geometry) + /// while the mic comes up and while the words come; still, and solid green + /// or orange, for a notice; still while recording. + @ViewBuilder private func ring(_ state: VoiceState) -> some View { + let width = state.isWorking || state.isNotice ? DesignTokens.Metrics.ringActive : DesignTokens.Metrics.ringStill + switch state.ring { + case .sweeping where !reduceMotion: + TimelineView(.animation(minimumInterval: keyboardAnimationInterval)) { timeline in + Circle() + .strokeBorder(BlurtBrand.orbRingGradient, lineWidth: width) + .rotationEffect( + .degrees( + MeterBarGeometry.rotationDegrees( + time: timeline.date.timeIntervalSinceReferenceDate, period: KeyboardMotion.ringPeriod))) + } + case .solid(.error): + Circle().strokeBorder(BlurtBrand.errorOrange, lineWidth: width) + case .solid(.ok): + Circle().strokeBorder(BlurtBrand.greenOnDark, lineWidth: width) + case .still, .sweeping: + Circle().strokeBorder(BlurtBrand.orbRingGradient, lineWidth: width) + } + } + + /// The orb's story from the phase: green, greener with the voice; the + /// violet drop is keyed to the moment the words landed, not to a phase. + static func mood(_ state: VoiceState) -> PrismOrb.Mood { + guard state.isReady else { return .off } + switch state.phase { + case .idle, .error, .pasted, .copied: return .idle + case .connecting: return .listening(level: 0) + case .recording: return .listening(level: state.level) + case .processing: return .working + } + } + + private static func symbol(_ glyph: VoiceState.Glyph) -> String { + switch glyph { + case .clipboard: "doc.on.clipboard" + case .exclamation: "exclamationmark" + } + } +} diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/PanelView.swift b/App/BlurtiOS/BlurtKeyboard/Sources/PanelView.swift new file mode 100644 index 00000000..e54936d3 --- /dev/null +++ b/App/BlurtiOS/BlurtKeyboard/Sources/PanelView.swift @@ -0,0 +1,31 @@ +import SwiftUI + +/// A big orb, centred, that dissipates into the wave while recording; cancel +/// in the corner while something is in flight; one row of keys. 216 pt. +struct PanelView: View { + var model: KeyboardModel + + var body: some View { + VStack(spacing: DesignTokens.Metrics.panelSpacing) { + Spacer(minLength: 0) + MicControl( + model: model, size: DesignTokens.Metrics.orbPanel, + wave: CGSize(width: DesignTokens.Metrics.wavePanelWidth, height: DesignTokens.Metrics.wavePanelHeight)) + Spacer(minLength: 0) + HStack(spacing: KeyboardPalette.keyGap) { + if model.needsGlobe { KeyCap(systemImage: "globe", dark: true) { model.globe() } } + KeyCap(title: "space", flexible: true) { model.space() } + KeyCap(systemImage: "delete.left", dark: true) { model.deleteBackward() } + KeyCap(systemImage: "return", dark: true) { model.newline() } + } + } + .overlay(alignment: .topTrailing) { + if model.voiceState.canCancel { + KeyCap(systemImage: "xmark", tint: BlurtBrand.errorOrange, bare: true) { model.cancel() } + .accessibilityLabel("Cancel dictation") + .transition(.opacity) + } + } + .overlay(alignment: .topLeading) { AddTermKey(model: model).padding(DesignTokens.Metrics.addtermInset) } + } +} diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/PrismOrb.swift b/App/BlurtiOS/BlurtKeyboard/Sources/PrismOrb.swift index c7bd5856..cf7c9c8a 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/PrismOrb.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/PrismOrb.swift @@ -1,4 +1,3 @@ -import BlurtEngine import SwiftUI /// The brand's artwork in motion. In the illustration a green beam goes into diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/SlimBarView.swift b/App/BlurtiOS/BlurtKeyboard/Sources/SlimBarView.swift new file mode 100644 index 00000000..30df9f88 --- /dev/null +++ b/App/BlurtiOS/BlurtKeyboard/Sources/SlimBarView.swift @@ -0,0 +1,15 @@ +import SwiftUI + +/// One row: the globe, the voice bar, delete and return. 60 pt. +struct SlimBarView: View { + var model: KeyboardModel + + var body: some View { + HStack(spacing: DesignTokens.Metrics.slimSpacing) { + if model.needsGlobe { KeyCap(systemImage: "globe", dark: true) { model.globe() } } + VoiceBar(model: model) + KeyCap(systemImage: "delete.left", dark: true) { model.deleteBackward() } + KeyCap(systemImage: "return", dark: true) { model.newline() } + } + } +} diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/TermField.swift b/App/BlurtiOS/BlurtKeyboard/Sources/TermField.swift new file mode 100644 index 00000000..f99f9104 --- /dev/null +++ b/App/BlurtiOS/BlurtKeyboard/Sources/TermField.swift @@ -0,0 +1,66 @@ +import SwiftUI + +/// The voice bar as a field: × to leave, what has been typed with a caret, +/// ✓ to save. Return saves too. +struct TermField: View { + var model: KeyboardModel + @Environment(\.keyboardPalette) private var palette + + var body: some View { + HStack(spacing: DesignTokens.Metrics.termGap) { + round("xmark", tint: palette.keyText.opacity(DesignTokens.Metrics.opacityTermCancel)) { model.cancelAddingTerm() } + .accessibilityLabel("Cancel") + HStack(spacing: 0) { + if let draft = model.termDraft, !draft.isEmpty { + Text(draft).foregroundStyle(palette.keyText) + } else { + Text("New key term").foregroundStyle(palette.keyText.opacity(DesignTokens.Metrics.opacityPlaceholder)) + } + Caret() + Spacer(minLength: 0) + } + .font(.system(size: DesignTokens.Typography.sizeTerm, weight: DesignTokens.Typography.weightTerm)) + .lineLimit(1) + .padding(.horizontal, DesignTokens.Metrics.termPad) + .frame(maxWidth: .infinity) + .frame(height: DesignTokens.Metrics.termHeight) + .background(Capsule().fill(palette.keyDark)) + .accessibilityElement(children: .ignore) + .accessibilityLabel("Key term: \(model.termDraft ?? "")") + round("checkmark", tint: palette.signal) { model.saveTerm() } + .accessibilityLabel("Save the key term") + .disabled(model.termDraft?.trimmingCharacters(in: .whitespaces).isEmpty ?? true) + } + .padding(.horizontal, DesignTokens.Metrics.termInset) + } + + /// × and ✓: bare glyphs, as the + is. + private func round(_ symbol: String, tint: Color, action: @escaping () -> Void) -> some View { + Button(action: action) { + Image(systemName: symbol) + .font(.system(size: DesignTokens.Typography.sizeGlyph, weight: DesignTokens.Typography.weightGlyph)) + .foregroundStyle(tint) + .frame(width: DesignTokens.Metrics.glyphHit, height: DesignTokens.Metrics.glyphHit) + .contentShape(Circle()) + } + .buttonStyle(KeyPressStyle()) + } +} + +/// A blinking caret, as a text field's; held on while motion is held. +private struct Caret: View { + @Environment(\.keyboardPalette) private var palette + @Environment(\.keyboardMotionHeld) private var motionHeld + + var body: some View { + TimelineView(.periodic(from: .now, by: DesignTokens.Motion.caret)) { timeline in + let on = motionHeld || Int(timeline.date.timeIntervalSinceReferenceDate / DesignTokens.Motion.caret) % 2 == 0 + RoundedRectangle(cornerRadius: DesignTokens.Metrics.caretRadius) + .fill(palette.signal) + .frame(width: DesignTokens.Metrics.caretWidth, height: DesignTokens.Metrics.caretHeight) + .opacity(on ? 1 : 0) + .padding(.leading, DesignTokens.Metrics.caretLead) + } + .accessibilityHidden(true) + } +} diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift index 435d7d69..7dbc3684 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift @@ -4,7 +4,7 @@ import SwiftUI /// The keyboard's voice row, and the only place voice lives: the orb, which /// is the mic key — tap to start and stop, hold to talk — dissipating into /// the wave while recording. No words: the orb's ring and colour, or the -/// wave, say what is happening, and the haptics confirm it (see `MicKey`). +/// wave, say what is happening, and the haptics confirm it (see `MicControl`). /// Beside it, a small /// + for the one thing people want the instant Blurt mishears a word: add it /// as a key term. The bar then becomes the field the keys type into. @@ -23,7 +23,7 @@ struct VoiceBar: View { // The one state the orb can't show on its own: without Full Access // nothing here can work, and the user has to be told where to go. HStack(spacing: DesignTokens.Metrics.voicebarNoteGap) { - MicKey(model: model, size: DesignTokens.Metrics.orbBar, wave: nil) + MicControl(model: model, size: DesignTokens.Metrics.orbBar, wave: nil) Text("Allow Full Access in Settings → Keyboards") .font(.footnote) .foregroundStyle(BlurtBrand.errorOrange) @@ -34,7 +34,7 @@ struct VoiceBar: View { } else { // The wave stays clear of the + at the trailing edge, on both sides so it stays centred. let clearance = DesignTokens.Metrics.glyphHit + DesignTokens.Metrics.voicebarAddtermClearance - MicKey( + MicControl( model: model, size: DesignTokens.Metrics.orbBar, wave: CGSize( width: min(DesignTokens.Metrics.waveBarWidth, geo.size.width - 2 * clearance), // literal-ok: both sides @@ -52,184 +52,3 @@ struct VoiceBar: View { .animation(.easeInOut(duration: DesignTokens.Motion.termSwap), value: model.termDraft == nil) } } - -/// The small + beside the orb (and in the panel's corner): a new key term. -/// A bare glyph, quiet until it is needed; a check for a moment after one -/// was saved. -struct AddTermKey: View { - var model: KeyboardModel - @Environment(\.keyboardPalette) private var palette - - var body: some View { - Button { - model.beginAddingTerm() - } label: { - Image(systemName: model.termSavedAt == nil ? "plus" : "checkmark") - .font(.system(size: DesignTokens.Typography.sizeGlyph, weight: DesignTokens.Typography.weightGlyph)) - .foregroundStyle( - model.termSavedAt == nil ? palette.keyText.opacity(DesignTokens.Metrics.opacityLegendMuted) : palette.signal - ) - .frame(width: DesignTokens.Metrics.glyphHit, height: DesignTokens.Metrics.glyphHit) - .contentShape(Circle()) - .contentTransition(.symbolEffect(.replace)) - } - .buttonStyle(KeyPressStyle()) - .accessibilityLabel("Add a key term") - .disabled(!model.hasFullAccess) - .opacity(model.hasFullAccess ? 1 : DesignTokens.Metrics.opacityDisabled) - } -} - -/// The voice bar as a field: × to leave, what has been typed with a caret, -/// ✓ to save. Return saves too. -private struct TermField: View { - var model: KeyboardModel - @Environment(\.keyboardPalette) private var palette - - var body: some View { - HStack(spacing: DesignTokens.Metrics.termGap) { - round("xmark", tint: palette.keyText.opacity(DesignTokens.Metrics.opacityTermCancel)) { model.cancelAddingTerm() } - .accessibilityLabel("Cancel") - HStack(spacing: 0) { - if let draft = model.termDraft, !draft.isEmpty { - Text(draft).foregroundStyle(palette.keyText) - } else { - Text("New key term").foregroundStyle(palette.keyText.opacity(DesignTokens.Metrics.opacityPlaceholder)) - } - Caret() - Spacer(minLength: 0) - } - .font(.system(size: DesignTokens.Typography.sizeTerm, weight: DesignTokens.Typography.weightTerm)) - .lineLimit(1) - .padding(.horizontal, DesignTokens.Metrics.termPad) - .frame(maxWidth: .infinity) - .frame(height: DesignTokens.Metrics.termHeight) - .background(Capsule().fill(palette.keyDark)) - .accessibilityElement(children: .ignore) - .accessibilityLabel("Key term: \(model.termDraft ?? "")") - round("checkmark", tint: palette.signal) { model.saveTerm() } - .accessibilityLabel("Save the key term") - .disabled(model.termDraft?.trimmingCharacters(in: .whitespaces).isEmpty ?? true) - } - .padding(.horizontal, DesignTokens.Metrics.termInset) - } - - /// × and ✓: bare glyphs, as the + is. - private func round(_ symbol: String, tint: Color, action: @escaping () -> Void) -> some View { - Button(action: action) { - Image(systemName: symbol) - .font(.system(size: DesignTokens.Typography.sizeGlyph, weight: DesignTokens.Typography.weightGlyph)) - .foregroundStyle(tint) - .frame(width: DesignTokens.Metrics.glyphHit, height: DesignTokens.Metrics.glyphHit) - .contentShape(Circle()) - } - .buttonStyle(KeyPressStyle()) - } -} - -/// A blinking caret, as a text field's; held on while motion is held. -private struct Caret: View { - @Environment(\.keyboardPalette) private var palette - @Environment(\.keyboardMotionHeld) private var motionHeld - - var body: some View { - TimelineView(.periodic(from: .now, by: DesignTokens.Motion.caret)) { timeline in - let on = motionHeld || Int(timeline.date.timeIntervalSinceReferenceDate / DesignTokens.Motion.caret) % 2 == 0 - RoundedRectangle(cornerRadius: DesignTokens.Metrics.caretRadius) - .fill(palette.signal) - .frame(width: DesignTokens.Metrics.caretWidth, height: DesignTokens.Metrics.caretHeight) - .opacity(on ? 1 : 0) - .padding(.leading, DesignTokens.Metrics.caretLead) - } - .accessibilityHidden(true) - } -} - -/// The Mac pill's live meter: a row of bars that fills the width it is given -/// and tracks the current level, with the engine's envelope and idle wave -/// (`MeterBarGeometry`, unit-tested there). The keyboard hears the level from -/// the app at ~12 Hz; the wave keeps the row alive between ticks. The pitch -/// is the Mac's unless the caller sets its own: the keyboard's wave is thin — -/// `slimBar` wide, `slimGap` apart — and dense, a fine signal rather than a -/// bank of bars. -struct WaveformMeter: View { - let level: Float - let animated: Bool - let color: Color - var barWidth: CGFloat = MeterBarGeometry.barWidth - var barSpacing: CGFloat = MeterBarGeometry.barSpacing - - /// The keyboard's pitch: 2 pt bars, 2 pt apart. - static let slimBar = DesignTokens.Metrics.waveBar - static let slimGap = DesignTokens.Metrics.waveGap - - var body: some View { - GeometryReader { geo in - let count = Int((geo.size.width + barSpacing) / (barWidth + barSpacing)) - let layout = MeterBarRow(count: count, availableHeight: geo.size.height) - Group { - if animated { - TimelineView(.animation(minimumInterval: keyboardAnimationInterval)) { timeline in - bars(layout: layout, time: timeline.date.timeIntervalSinceReferenceDate) - } - } else { - bars(layout: layout, time: 0) - } - } - .frame(width: geo.size.width, height: geo.size.height) - } - .accessibilityHidden(true) - } - - @ViewBuilder private func bars(layout: MeterBarRow, time: TimeInterval) -> some View { - if DesignTokens.Metrics.waveLiquid > 0 { - liquid(layout: layout, time: time) - } else { - HStack(spacing: barSpacing) { - ForEach(0.. some View { - GeometryReader { geo in - let pitch = barWidth + barSpacing - // literal-ok: centring the row, and the middle of the bar - let inset = (geo.size.width - CGFloat(layout.count) * pitch + barSpacing) / 2 + barWidth / 2 // literal-ok: ½ - let mid = geo.size.height / 2 // literal-ok: the middle - let points = (0.. CGPoint in - let h = layout.height(at: index, level: level, time: time, animated: animated) - return CGPoint(x: inset + CGFloat(index) * pitch, y: h / 2) // literal-ok: half height - } - Path { path in - guard let first = points.first, let last = points.last else { return } - path.move(to: CGPoint(x: first.x, y: mid - first.y)) - for i in 1.. some View { + HStack(spacing: barSpacing) { + ForEach(0.. String { + switch overlay { + case .connecting: "Connecting…" + case .recording: "Listening…" + case .processing: "Transcribing…" + case .pasted: "Pasted" + case .noTarget: "Copied" + case .error(let message): message + case .idle: windowOpen ? "Ready to dictate" : "Not listening" + } + } +} diff --git a/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift b/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift index 66fe8ec1..462c0bf5 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift @@ -1,7 +1,6 @@ import AVFoundation import BlurtEngine import SwiftUI -import UIKit /// The app's one screen, in the shape of the Mac's ready screen: the wordmark, /// the orb as the hero with the listening state under it, the style chips, @@ -10,29 +9,31 @@ import UIKit struct HomeView: View { var coordinator: DictationCoordinator @Environment(\.scenePhase) private var scenePhase - @Environment(\.accessibilityReduceMotion) private var reduceMotion @State private var microphoneGranted = AVAudioApplication.shared.recordPermission == .granted @State private var keyboardSeen = SharedStore.keyboardEverSeen @State private var showsKeyEntry = false @State private var showsSettings = false /// When the last dictation's words landed — the hero's drop. @State private var landedAt: Date? - @AppStorage(StyleProfileStore.defaultsKey) private var profilesRaw = "" - @AppStorage(StyleProfileStore.activeDefaultsKey) private var activeRaw = "" - private let styles = StyleProfileStore() - private var isSetUp: Bool { coordinator.apiKey.hasAPIKey && microphoneGranted && keyboardSeen } - private var profiles: [StyleProfile] { styles.profiles(decoding: profilesRaw) } - private var activeStyle: StyleProfile? { StyleProfileStore.active(in: profiles, id: activeRaw) } + private var status: HomeStatus { + HomeStatus( + overlay: coordinator.phase.overlayState, windowOpen: coordinator.window.isOpen, until: coordinator.window.until, + hasKey: coordinator.apiKey.hasAPIKey, micGranted: microphoneGranted, keyboardSeen: keyboardSeen) + } var body: some View { NavigationStack { ScrollView { VStack(spacing: 20) { - if !isSetUp { setupCard } - hero - styleChips - recent + if !status.isSetUp { + SetupCard( + hasKey: coordinator.apiKey.hasAPIKey, microphoneGranted: microphoneGranted, keyboardSeen: keyboardSeen, + enterKey: { showsKeyEntry = true }, refresh: refreshStatus) + } + HomeHero(coordinator: coordinator, status: status, landedAt: landedAt) + StyleChips() + RecentSection(coordinator: coordinator) poweredBy } .padding(.horizontal, 20) @@ -68,11 +69,8 @@ struct HomeView: View { .onChange(of: scenePhase) { _, phase in if phase == .active { refreshStatus() } } - .onChange(of: coordinator.phase) { _, phase in - switch phase.overlayState { - case .pasted, .noTarget: landedAt = Date() - default: break - } + .onChange(of: coordinator.phase) { _, _ in + if status.landed { landedAt = Date() } } } .tint(BlurtBrand.accent) @@ -84,145 +82,6 @@ struct HomeView: View { coordinator.apiKey.refreshStatus() } - // MARK: - The orb and the listening state - - private static let orbSize = DesignTokens.Metrics.orbHome - /// The wave at hero size: wide and slim, inside the card at any phone width. - private static let waveReach = DesignTokens.Metrics.waveHomeWidth - private static let waveHeight = DesignTokens.Metrics.waveHomeHeight - private var isRecording: Bool { coordinator.phase == .recording } - private var orbWorking: Bool { coordinator.window.isOpen || coordinator.phase.isCapturing } - - private var hero: some View { - VStack(spacing: 18) { - // The keyboard's mic key at hero size: the orb, dissipating into the - // thin wave while recording and condensing back after, as the key does. - ZStack { - if isRecording { - WaveformMeter( - level: coordinator.level, animated: !reduceMotion, color: BlurtBrand.accent, - barWidth: WaveformMeter.slimBar, barSpacing: WaveformMeter.slimGap - ) - .frame(width: Self.waveReach, height: Self.waveHeight) - .transition(.opacity) - } else { - PrismOrb(mood: heroMood, landedAt: landedAt, animated: !reduceMotion) - .frame(width: Self.orbSize, height: Self.orbSize) - .clipShape(Circle()) - .overlay { HeroRing(animated: orbWorking && !reduceMotion) } - .saturation(coordinator.window.isOpen ? 1 : DesignTokens.Metrics.opacityHomeDimSaturation) - .transition(reduceMotion ? .opacity : .dissipate(size: Self.orbSize)) - } - } - // The wave's width throughout, so nothing shifts while the two cross. - .frame(width: Self.waveReach, height: Self.orbSize) - .animation(.easeInOut(duration: MicKey.waveFade), value: isRecording) - .animation(.easeInOut(duration: MicKey.stateFade), value: coordinator.window.isOpen) - .padding(.top, 6) - VStack(spacing: 4) { - Text(heroTitle).font(.title2.weight(.semibold)).multilineTextAlignment(.center) - Text(heroSubtitle).font(.callout).foregroundStyle(.secondary).multilineTextAlignment(.center) - } - if coordinator.window.isOpen { - Button(role: .destructive) { - Task { await coordinator.stopListening() } - } label: { - Text("Stop listening").frame(maxWidth: .infinity) - } - .buttonStyle(.bordered) - .controlSize(.large) - } else { - Button { - Task { await coordinator.startListening() } - } label: { - Text("Start listening").frame(maxWidth: .infinity) - } - .buttonStyle(.borderedProminent) - .controlSize(.large) - .disabled(!coordinator.apiKey.hasAPIKey) - } - Button(coordinator.phase.isCapturing ? "Stop and transcribe" : "Dictate here, to the clipboard") { - coordinator.toggleDictation() - } - .font(.callout) - .disabled(!coordinator.window.isOpen) - if let error = coordinator.window.lastError { - Text(error).font(.footnote).foregroundStyle(BlurtBrand.errorOrange).multilineTextAlignment(.center) - } - if coordinator.microphoneDenied { - Text("Blurt needs the microphone. Allow it in Settings.") - .font(.footnote).foregroundStyle(BlurtBrand.errorOrange) - } - if coordinator.needsKey { - Text("Add your API key first (Settings → Account).") - .font(.footnote).foregroundStyle(BlurtBrand.errorOrange) - } - } - .padding(20) - .frame(maxWidth: .infinity) - .card() - } - - private var heroMood: PrismOrb.Mood { - guard coordinator.window.isOpen else { return .off } - switch coordinator.phase.overlayState { - case .idle, .error, .pasted, .noTarget: return .idle - case .connecting: return .listening(level: 0) - case .recording: return .listening(level: coordinator.level) - case .processing: return .working - } - } - - private var heroTitle: String { - switch coordinator.phase.overlayState { - case .connecting: return "Connecting…" - case .recording: return "Listening…" - case .processing: return "Transcribing…" - case .pasted: return "Pasted" - case .noTarget: return "Copied" - case .error(let message): return message - case .idle: return coordinator.window.isOpen ? "Ready to dictate" : "Not listening" - } - } - - private var heroSubtitle: String { - guard coordinator.window.isOpen else { - return "Open the mic so the Blurt keyboard can dictate anywhere you type." - } - if let until = coordinator.window.until, until != .distantFuture { - return "Until \(until.formatted(date: .omitted, time: .shortened)) · tap the mic on the Blurt keyboard." - } - return "Until you stop it · tap the mic on the Blurt keyboard." - } - - // MARK: - Styles - - private var styleChips: some View { - VStack(alignment: .leading, spacing: 10) { - Text("Style").font(.headline) - ScrollView(.horizontal, showsIndicators: false) { - HStack(spacing: 8) { - StyleChip(name: StyleProfileStore.defaultStyleName, selected: activeStyle == nil) { styles.activateDefault() } - ForEach(profiles) { profile in - StyleChip(name: profile.name, selected: activeStyle?.id == profile.id) { styles.activate(profile) } - } - NavigationLink { - StylesView() - } label: { - Label("Edit", systemImage: "slider.horizontal.3") - .font(.subheadline.weight(.medium)) - .padding(.horizontal, 14) - .padding(.vertical, 8) - .background(Capsule().strokeBorder(BlurtBrand.cardBorder, lineWidth: 1)) - } - } - .padding(.vertical, 2) - } - } - } - - private var recent: some View { RecentSection(coordinator: coordinator) } - private var poweredBy: some View { HStack(spacing: 3) { Text("Powered by").foregroundStyle(.secondary) @@ -231,155 +90,4 @@ struct HomeView: View { .font(.caption) .padding(.top, 4) } - - // MARK: - Setup - - private var setupCard: some View { - VStack(alignment: .leading, spacing: 14) { - Text("Set up Blurt").font(.headline) - SetupRow(done: coordinator.apiKey.hasAPIKey, title: "Sign in with AssemblyAI") { - VStack(alignment: .leading, spacing: 6) { - Text("Coming soon — sign-in needs the AssemblyAI login service.") - .font(.footnote).foregroundStyle(.secondary) - #if DEBUG - Button("Use an API key instead") { showsKeyEntry = true } - #endif - } - } - SetupRow(done: microphoneGranted, title: "Allow the microphone") { - if AVAudioApplication.shared.recordPermission == .denied { - // iOS asks once; after a refusal only Settings can change it. - Button("Allow in Settings") { openAppSettings() } - } else { - Button("Allow") { - Task { - _ = await AVAudioApplication.requestRecordPermission() - refreshStatus() - } - } - } - } - SetupRow(done: keyboardSeen, title: "Add the Blurt keyboard") { - VStack(alignment: .leading, spacing: 6) { - Text( - "Settings → Keyboards: turn on Blurt and Allow Full Access. " - + "Full Access is what lets the keyboard send your words to Blurt." - ) - .font(.footnote).foregroundStyle(.secondary) - Button("Open Settings") { openAppSettings() } - } - } - } - .padding(20) - .frame(maxWidth: .infinity, alignment: .leading) - .card() - } - - private func openAppSettings() { - guard let url = URL(string: UIApplication.openSettingsURLString) else { return } - UIApplication.shared.open(url) - } -} - -/// One style, as a chip: filled with the accent while active. -private struct StyleChip: View { - let name: String - let selected: Bool - let activate: () -> Void - - var body: some View { - Button(action: activate) { - Text(name) - .font(.subheadline.weight(.medium)) - .padding(.horizontal, 14) - .padding(.vertical, 8) - .foregroundStyle(selected ? Color.white : Color.primary) - .background(Capsule().fill(selected ? BlurtBrand.accent : BlurtBrand.cardFill)) - .overlay(Capsule().strokeBorder(selected ? Color.clear : BlurtBrand.cardBorder, lineWidth: 1)) - } - .buttonStyle(.plain) - .accessibilityAddTraits(selected ? .isSelected : []) - } -} - -/// One line of the setup checklist: a check or a circle, the step, and its -/// control while it is still to do. -private struct SetupRow: View { - let done: Bool - let title: String - @ViewBuilder let action: () -> Action - - var body: some View { - HStack(alignment: .top, spacing: 12) { - Image(systemName: done ? "checkmark.circle.fill" : "circle") - .foregroundStyle(done ? BlurtBrand.accent : Color.secondary) - VStack(alignment: .leading, spacing: 6) { - Text(title) - if !done { action() } - } - } - } -} - -/// The hero orb's ring: the brand orb's sweep, on its own so the prism can -/// be the fill. -private struct HeroRing: View { - let animated: Bool - - var body: some View { - if animated { - TimelineView(.animation(minimumInterval: keyboardAnimationInterval)) { timeline in - Circle() - .strokeBorder(BlurtBrand.orbRingGradient, lineWidth: DesignTokens.Metrics.ringActive) - .rotationEffect( - .degrees( - MeterBarGeometry.rotationDegrees( - time: timeline.date.timeIntervalSinceReferenceDate, period: BrandOrb.period))) - } - } else { - Circle().strokeBorder(BlurtBrand.orbRingGradient, lineWidth: DesignTokens.Metrics.ringActive) - } - } -} - -/// The recent dictations as cards, with a copy button each. -private struct RecentSection: View { - var coordinator: DictationCoordinator - - var body: some View { - VStack(alignment: .leading, spacing: 10) { - Text("Recent").font(.headline) - if coordinator.recent.displayed.isEmpty { - Text("Your recent blurts will appear here.") - .font(.callout).foregroundStyle(.secondary) - .frame(maxWidth: .infinity, alignment: .leading) - .padding(16) - .card() - } - ForEach(coordinator.recent.displayed) { entry in - VStack(alignment: .leading, spacing: 8) { - Text(entry.text).font(.body).lineLimit(3) - HStack(spacing: 8) { - if let style = entry.style { - Text(style) - .font(.caption.weight(.medium)) - .padding(.horizontal, 8).padding(.vertical, 3) - .background(Capsule().fill(BlurtBrand.accent.opacity(0.15))) - } - Text(entry.relativeLabel(now: Date())).font(.caption).foregroundStyle(.secondary) - Spacer() - Button { - UIPasteboard.general.string = entry.text - } label: { - Image(systemName: "doc.on.doc") - } - .buttonStyle(.borderless) - .accessibilityLabel("Copy") - } - } - .padding(16) - .card() - } - } - } } diff --git a/App/BlurtiOS/BlurtiOS/Sources/RecentSection.swift b/App/BlurtiOS/BlurtiOS/Sources/RecentSection.swift new file mode 100644 index 00000000..4c1a389d --- /dev/null +++ b/App/BlurtiOS/BlurtiOS/Sources/RecentSection.swift @@ -0,0 +1,44 @@ +import SwiftUI +import UIKit + +/// The recent dictations as cards, with a copy button each. +struct RecentSection: View { + var coordinator: DictationCoordinator + + var body: some View { + VStack(alignment: .leading, spacing: 10) { + Text("Recent").font(.headline) + if coordinator.recent.displayed.isEmpty { + Text("Your recent blurts will appear here.") + .font(.callout).foregroundStyle(.secondary) + .frame(maxWidth: .infinity, alignment: .leading) + .padding(16) + .card() + } + ForEach(coordinator.recent.displayed) { entry in + VStack(alignment: .leading, spacing: 8) { + Text(entry.text).font(.body).lineLimit(3) + HStack(spacing: 8) { + if let style = entry.style { + Text(style) + .font(.caption.weight(.medium)) + .padding(.horizontal, 8).padding(.vertical, 3) + .background(Capsule().fill(BlurtBrand.accent.opacity(0.15))) + } + Text(entry.relativeLabel(now: Date())).font(.caption).foregroundStyle(.secondary) + Spacer() + Button { + UIPasteboard.general.string = entry.text + } label: { + Image(systemName: "doc.on.doc") + } + .buttonStyle(.borderless) + .accessibilityLabel("Copy") + } + } + .padding(16) + .card() + } + } + } +} diff --git a/App/BlurtiOS/BlurtiOS/Sources/SetupCard.swift b/App/BlurtiOS/BlurtiOS/Sources/SetupCard.swift new file mode 100644 index 00000000..aae67401 --- /dev/null +++ b/App/BlurtiOS/BlurtiOS/Sources/SetupCard.swift @@ -0,0 +1,80 @@ +import AVFoundation +import SwiftUI +import UIKit + +/// The setup checklist, on top of the home screen while anything is missing: +/// sign in (a key, in debug builds), the microphone, the keyboard. +struct SetupCard: View { + let hasKey: Bool + let microphoneGranted: Bool + let keyboardSeen: Bool + /// Debug builds take an API key in place of the sign-in that doesn't exist yet. + let enterKey: () -> Void + /// Re-read the permissions after one was asked for. + let refresh: () -> Void + + var body: some View { + VStack(alignment: .leading, spacing: 14) { + Text("Set up Blurt").font(.headline) + SetupRow(done: hasKey, title: "Sign in with AssemblyAI") { + VStack(alignment: .leading, spacing: 6) { + Text("Coming soon — sign-in needs the AssemblyAI login service.") + .font(.footnote).foregroundStyle(.secondary) + #if DEBUG + Button("Use an API key instead") { enterKey() } + #endif + } + } + SetupRow(done: microphoneGranted, title: "Allow the microphone") { + if AVAudioApplication.shared.recordPermission == .denied { + // iOS asks once; after a refusal only Settings can change it. + Button("Allow in Settings") { Self.openAppSettings() } + } else { + Button("Allow") { + Task { + _ = await AVAudioApplication.requestRecordPermission() + refresh() + } + } + } + } + SetupRow(done: keyboardSeen, title: "Add the Blurt keyboard") { + VStack(alignment: .leading, spacing: 6) { + Text( + "Settings → Keyboards: turn on Blurt and Allow Full Access. " + + "Full Access is what lets the keyboard send your words to Blurt." + ) + .font(.footnote).foregroundStyle(.secondary) + Button("Open Settings") { Self.openAppSettings() } + } + } + } + .padding(20) + .frame(maxWidth: .infinity, alignment: .leading) + .card() + } + + static func openAppSettings() { + guard let url = URL(string: UIApplication.openSettingsURLString) else { return } + UIApplication.shared.open(url) + } +} + +/// One line of the setup checklist: a check or a circle, the step, and its +/// control while it is still to do. +private struct SetupRow: View { + let done: Bool + let title: String + @ViewBuilder let action: () -> Action + + var body: some View { + HStack(alignment: .top, spacing: 12) { + Image(systemName: done ? "checkmark.circle.fill" : "circle") + .foregroundStyle(done ? BlurtBrand.accent : Color.secondary) + VStack(alignment: .leading, spacing: 6) { + Text(title) + if !done { action() } + } + } + } +} diff --git a/App/BlurtiOS/BlurtiOS/Sources/StyleChips.swift b/App/BlurtiOS/BlurtiOS/Sources/StyleChips.swift new file mode 100644 index 00000000..adffada2 --- /dev/null +++ b/App/BlurtiOS/BlurtiOS/Sources/StyleChips.swift @@ -0,0 +1,58 @@ +import BlurtEngine +import SwiftUI + +/// The output styles as chips: Default and each profile, the active one +/// filled with the accent; Edit opens the styles editor. +struct StyleChips: View { + @AppStorage(StyleProfileStore.defaultsKey) private var profilesRaw = "" + @AppStorage(StyleProfileStore.activeDefaultsKey) private var activeRaw = "" + private let styles = StyleProfileStore() + + private var profiles: [StyleProfile] { styles.profiles(decoding: profilesRaw) } + private var activeStyle: StyleProfile? { StyleProfileStore.active(in: profiles, id: activeRaw) } + + var body: some View { + VStack(alignment: .leading, spacing: 10) { + Text("Style").font(.headline) + ScrollView(.horizontal, showsIndicators: false) { + HStack(spacing: 8) { + StyleChip(name: StyleProfileStore.defaultStyleName, selected: activeStyle == nil) { styles.activateDefault() } + ForEach(profiles) { profile in + StyleChip(name: profile.name, selected: activeStyle?.id == profile.id) { styles.activate(profile) } + } + NavigationLink { + StylesView() + } label: { + Label("Edit", systemImage: "slider.horizontal.3") + .font(.subheadline.weight(.medium)) + .padding(.horizontal, 14) + .padding(.vertical, 8) + .background(Capsule().strokeBorder(BlurtBrand.cardBorder, lineWidth: 1)) + } + } + .padding(.vertical, 2) + } + } + } +} + +/// One style, as a chip: filled with the accent while active. +private struct StyleChip: View { + let name: String + let selected: Bool + let activate: () -> Void + + var body: some View { + Button(action: activate) { + Text(name) + .font(.subheadline.weight(.medium)) + .padding(.horizontal, 14) + .padding(.vertical, 8) + .foregroundStyle(selected ? Color.white : Color.primary) + .background(Capsule().fill(selected ? BlurtBrand.accent : BlurtBrand.cardFill)) + .overlay(Capsule().strokeBorder(selected ? Color.clear : BlurtBrand.cardBorder, lineWidth: 1)) + } + .buttonStyle(.plain) + .accessibilityAddTraits(selected ? .isSelected : []) + } +} diff --git a/App/BlurtiOS/BlurtiOSProbe/AppleKeyboardProbe.swift b/App/BlurtiOS/BlurtiOSProbe/AppleKeyboardProbe.swift index 872ffcf2..309687fd 100644 --- a/App/BlurtiOS/BlurtiOSProbe/AppleKeyboardProbe.swift +++ b/App/BlurtiOS/BlurtiOSProbe/AppleKeyboardProbe.swift @@ -43,7 +43,7 @@ final class AppleKeyboardProbe: XCTestCase { } out["others"] = others let data = try JSONSerialization.data(withJSONObject: out, options: [.prettyPrinted, .sortedKeys]) - let text = String(decoding: data, as: UTF8.self) + let text = try XCTUnwrap(String(bytes: data, encoding: .utf8)) let json = XCTAttachment(string: text) json.name = "apple-geometry-\(face).json" json.lifetime = .keepAlways diff --git a/App/BlurtiOS/BlurtiOSTests/HomeStatusTests.swift b/App/BlurtiOS/BlurtiOSTests/HomeStatusTests.swift new file mode 100644 index 00000000..b7a25665 --- /dev/null +++ b/App/BlurtiOS/BlurtiOSTests/HomeStatusTests.swift @@ -0,0 +1,45 @@ +import BlurtEngine +import Foundation +import Testing + +@testable import BlurtiOS + +@Suite("Home status") +struct HomeStatusTests { + private func status( + _ overlay: OverlayUIState, open: Bool = true, until: Date? = nil, key: Bool = true, mic: Bool = true, + keyboard: Bool = true + ) -> HomeStatus { + HomeStatus(overlay: overlay, windowOpen: open, until: until, hasKey: key, micGranted: mic, keyboardSeen: keyboard) + } + + @Test("the headline follows the phase, and says whether the mic is open at rest") + func titles() { + #expect(status(.idle).title == "Ready to dictate") + #expect(status(.idle, open: false).title == "Not listening") + #expect(status(.connecting).title == "Connecting…") + #expect(status(.recording).title == "Listening…") + #expect(status(.processing).title == "Transcribing…") + #expect(status(.pasted).title == "Pasted") + #expect(status(.noTarget).title == "Copied") + #expect(status(.error(message: "No network.")).title == "No network.") + } + + @Test("the line under it says how long the mic stays open") + func subtitles() { + #expect(status(.idle, open: false).subtitle.hasPrefix("Open the mic")) + #expect(status(.idle, until: .distantFuture).subtitle.hasPrefix("Until you stop it")) + #expect(status(.idle, until: Date()).subtitle.hasPrefix("Until ")) + #expect(!status(.idle, until: Date()).subtitle.hasPrefix("Until you")) + } + + @Test("setup needs the key, the microphone and the keyboard; landed means pasted or copied") + func setupAndLanded() { + #expect(status(.idle).isSetUp) + #expect(!status(.idle, key: false).isSetUp) + #expect(!status(.idle, mic: false).isSetUp) + #expect(!status(.idle, keyboard: false).isSetUp) + #expect(status(.pasted).landed && status(.noTarget).landed) + #expect(!status(.idle).landed && !status(.error(message: "x")).landed) + } +} diff --git a/App/BlurtiOS/BlurtiOSTests/KeyboardInteractionTests.swift b/App/BlurtiOS/BlurtiOSTests/KeyboardInteractionTests.swift new file mode 100644 index 00000000..447da843 --- /dev/null +++ b/App/BlurtiOS/BlurtiOSTests/KeyboardInteractionTests.swift @@ -0,0 +1,79 @@ +import CoreGraphics +import Testing + +@testable import BlurtiOS + +@Suite("Keyboard interaction rules") +struct KeyboardInteractionTests { + @Test("a swipe flips the panel past 48 pt sideways and 1.5× the vertical, the way the finger went") + func flip() { + #expect(KeyboardInteraction.flip(CGSize(width: 47, height: 0)) == nil) + #expect(KeyboardInteraction.flip(CGSize(width: 49, height: 0)) == .towardsTrailing) + #expect(KeyboardInteraction.flip(CGSize(width: -49, height: 0)) == .towardsLeading) + #expect(KeyboardInteraction.flip(CGSize(width: 49, height: 40)) == nil) + #expect(KeyboardInteraction.flip(CGSize(width: 60, height: 39)) == .towardsTrailing) + } + + @Test("a key acts only under 12 pt of travel; the mic cancels past 24") + func travel() { + #expect(KeyboardInteraction.isTap(CGSize(width: 11.9, height: 11.9))) + #expect(!KeyboardInteraction.isTap(CGSize(width: 12, height: 0))) + #expect(!KeyboardInteraction.isTap(CGSize(width: 0, height: -12))) + #expect(!KeyboardInteraction.micTravelled(CGSize(width: 24, height: 24))) + #expect(KeyboardInteraction.micTravelled(CGSize(width: 24.1, height: 0))) + #expect(KeyboardInteraction.micTravelled(CGSize(width: 0, height: -24.1))) + } + + // `#expect` captures its expression immutably, so each mutating step lands + // in a local first. + @Test("a quick tap presses and releases together") + func quickTap() { + var press = MicPressSequencer() + let armed = press.began() + #expect(armed) + let armedAgain = press.began() + #expect(!armedAgain) + let outcome = press.ended(travelled: false) + #expect(outcome == .tap(needsDown: true)) + #expect(press == MicPressSequencer()) + } + + @Test("a hold presses when the timer fires and releases on the lift") + func hold() { + var press = MicPressSequencer() + _ = press.began() + let fired = press.delayFired() + #expect(fired) + let firedAgain = press.delayFired() + #expect(!firedAgain) + let outcome = press.ended(travelled: false) + #expect(outcome == .tap(needsDown: false)) + } + + @Test("a swipe before the timer fires cancels it and does nothing") + func swipeBeforePress() { + var press = MicPressSequencer() + _ = press.began() + let stayed = press.moved(travelled: false) + #expect(!stayed) + let cancelled = press.moved(travelled: true) + #expect(cancelled) + let cancelledAgain = press.moved(travelled: true) + #expect(!cancelledAgain) + let fired = press.delayFired() + #expect(!fired) + let outcome = press.ended(travelled: true) + #expect(outcome == .nothing) + } + + @Test("a swipe after the press went out undoes it") + func swipeAfterPress() { + var press = MicPressSequencer() + _ = press.began() + _ = press.delayFired() + let cancelled = press.moved(travelled: true) + #expect(!cancelled) + let outcome = press.ended(travelled: true) + #expect(outcome == .cancelSentPress) + } +} diff --git a/App/BlurtiOS/BlurtiOSTests/VoiceStateTests.swift b/App/BlurtiOS/BlurtiOSTests/VoiceStateTests.swift new file mode 100644 index 00000000..0693d68e --- /dev/null +++ b/App/BlurtiOS/BlurtiOSTests/VoiceStateTests.swift @@ -0,0 +1,64 @@ +import BlurtEngine +import Foundation +import Testing + +@testable import BlurtiOS + +@Suite("Voice state") +struct VoiceStateTests { + private func snapshot(_ state: PhaseSnapshot.State, level: Double = 0, message: String? = nil) -> PhaseSnapshot { + PhaseSnapshot(state: state, message: message, level: level, at: Date()) + } + + @Test("ready and idle: the circle, still, nothing else") + func idle() { + let state = VoiceState(snapshot: snapshot(.idle), isReady: true) + #expect(state.ring == .still) + #expect(state.glyph == nil) + #expect(!state.isRecording && !state.isWorking && !state.isNotice && !state.dimmed && !state.canCancel) + #expect(state.accessibilityLabel == "Dictate") + #expect(state.accessibilityValue == "") + } + + @Test("the mic coming up and the words being made sweep the ring; recording is the meter, ring still") + func inFlight() { + let connecting = VoiceState(snapshot: snapshot(.connecting), isReady: true) + #expect(connecting.ring == .sweeping && connecting.isWorking && connecting.canCancel && !connecting.isRecording) + let recording = VoiceState(snapshot: snapshot(.recording, level: 0.62), isReady: true) + #expect(recording.ring == .still && recording.isRecording && recording.isWorking && recording.level == 0.62) + #expect(recording.accessibilityLabel == "Stop dictation") + let processing = VoiceState(snapshot: snapshot(.processing), isReady: true) + #expect(processing.ring == .sweeping && processing.isWorking && !processing.isRecording) + } + + @Test("the notices: green ring for the words landing, a clipboard when copied, orange and an exclamation on error") + func notices() { + let pasted = VoiceState(snapshot: snapshot(.pasted), isReady: true) + #expect(pasted.ring == .solid(.ok) && pasted.glyph == nil && pasted.isNotice && !pasted.canCancel) + let copied = VoiceState(snapshot: snapshot(.copied), isReady: true) + #expect(copied.ring == .solid(.ok) && copied.glyph == .clipboard) + let error = VoiceState(snapshot: snapshot(.error, message: "The microphone didn't start."), isReady: true) + #expect(error.ring == .solid(.error) && error.glyph == .exclamation) + #expect(error.accessibilityValue == "The microphone didn't start.") + #expect(VoiceState(snapshot: snapshot(.error), isReady: true).accessibilityValue == "Dictation failed.") + } + + @Test("not ready: dimmed, no meter, no glyph, no sweep; a tap starts Blurt") + func notReady() { + for phase in [PhaseSnapshot.State.idle, .connecting, .recording, .processing, .copied] { + let state = VoiceState(snapshot: snapshot(phase, level: 0.5), isReady: false) + #expect(state.dimmed && !state.isRecording && !state.isWorking && state.glyph == nil) + #expect(state.ring != .sweeping) + #expect(state.accessibilityLabel == "Start Blurt") + } + } + + @Test("the app's overlay state maps onto the same phases; no target is copied") + func overlay() { + #expect(VoiceState(overlay: .noTarget, windowOpen: true, level: 0).phase == .copied) + #expect(VoiceState(overlay: .error(message: "x"), windowOpen: true, level: 0).message == "x") + #expect(VoiceState(overlay: .recording, windowOpen: true, level: 0.4).level == 0.4) + #expect(VoiceState(overlay: .idle, windowOpen: false, level: 0).dimmed) + #expect(VoiceState(overlay: .processing, windowOpen: true, level: 0).ring == .sweeping) + } +} diff --git a/App/BlurtiOS/DESIGN.md b/App/BlurtiOS/DESIGN.md index aad4487c..7bb51bfc 100644 --- a/App/BlurtiOS/DESIGN.md +++ b/App/BlurtiOS/DESIGN.md @@ -540,7 +540,6 @@ derivation. | `wave/gap` | `2` | `Metrics.waveGap` | between wave bars | | `wave/home-height` | `44` | `Metrics.waveHomeHeight` | — | | `wave/home-width` | `280` | `Metrics.waveHomeWidth` | — | -| `wave/liquid` | `0` | `Metrics.waveLiquid` | 1 draws the wave as one liquid shape through the bar heights instead of the bars themselves | | `wave/panel-height` | `40` | `Metrics.wavePanelHeight` | — | | `wave/panel-width` | `300` | `Metrics.wavePanelWidth` | — | | `wordmark/height` | `22` | `Metrics.wordmarkHeight` | — | diff --git a/App/BlurtiOS/Design/figma/tokens.js b/App/BlurtiOS/Design/figma/tokens.js index 1a7a991a..42174757 100644 --- a/App/BlurtiOS/Design/figma/tokens.js +++ b/App/BlurtiOS/Design/figma/tokens.js @@ -155,7 +155,6 @@ Metrics|wave/bar-width|FLOAT|240||WIDTH_HEIGHT|DesignTokens.Metrics.waveBarWidth Metrics|wave/gap|FLOAT|2||GAP|DesignTokens.Metrics.waveGap|between wave bars Metrics|wave/home-height|FLOAT|44||WIDTH_HEIGHT|DesignTokens.Metrics.waveHomeHeight| Metrics|wave/home-width|FLOAT|280||WIDTH_HEIGHT|DesignTokens.Metrics.waveHomeWidth| -Metrics|wave/liquid|FLOAT|0||WIDTH_HEIGHT|DesignTokens.Metrics.waveLiquid|1 draws the wave as one liquid shape through the bar heights instead of the bars themselves Metrics|wave/panel-height|FLOAT|40||WIDTH_HEIGHT|DesignTokens.Metrics.wavePanelHeight| Metrics|wave/panel-width|FLOAT|300||WIDTH_HEIGHT|DesignTokens.Metrics.wavePanelWidth| Metrics|wordmark/height|FLOAT|22||WIDTH_HEIGHT|DesignTokens.Metrics.wordmarkHeight| diff --git a/App/BlurtiOS/Design/tokens.json b/App/BlurtiOS/Design/tokens.json index 45bd516a..eb8cc70b 100644 --- a/App/BlurtiOS/Design/tokens.json +++ b/App/BlurtiOS/Design/tokens.json @@ -397,10 +397,6 @@ "value": 2, "use": "between wave bars" }, - "wave/liquid": { - "value": 0, - "use": "1 draws the wave as one liquid shape through the bar heights instead of the bars themselves" - }, "ring/still": { "value": 1, "use": "the ring at rest" diff --git a/App/BlurtiOS/Shared/BlurtBrand.swift b/App/BlurtiOS/Shared/BlurtBrand.swift index 24d992e0..1f33a6a8 100644 --- a/App/BlurtiOS/Shared/BlurtBrand.swift +++ b/App/BlurtiOS/Shared/BlurtBrand.swift @@ -20,26 +20,9 @@ enum BlurtBrand { /// `#67AD82` — the brand hue lifted for dark chrome: the pill's text and /// meter, the ring, the wordmark on the icon. nonisolated static let greenOnDark = DesignTokens.Brand.green400 - /// `#1D1B16` — the brand ink: the pill's body in every state, and the - /// keyboard's surface. - nonisolated static let ink = DesignTokens.Brand.ink /// `#E67F36` — the error word. The body stays ink; the word carries the alarm. nonisolated static let errorOrange = DesignTokens.Brand.orange - // MARK: Keyboard surface — the ink family, one and two steps up - - /// `#33302A` — an ordinary key on the ink surface. - nonisolated static let key = DesignTokens.Brand.ink700 - /// `#26231E` — a modifier key (shift, delete, globe, return): a step darker - /// than a letter, as the system keyboard does it. The Mac's dark card fill. - nonisolated static let keyDark = DesignTokens.Brand.ink800 - /// `#F2EEE6` — key legends: a warm white, not a cold one, on the warm ink. - nonisolated static let keyText = DesignTokens.Brand.warmWhite - - /// The orb's fill: the design's own stops (`App elements/Recording.svg`), - /// swept bottom to top. - nonisolated static let orbGradient = DesignTokens.Gradients.orb - /// The ring round the orb: green into white, corner to corner; spun while /// something is happening. nonisolated static let orbRingGradient = DesignTokens.Gradients.orbRing diff --git a/App/BlurtiOS/Shared/DesignTokens.swift b/App/BlurtiOS/Shared/DesignTokens.swift index 16b72507..80bf119f 100644 --- a/App/BlurtiOS/Shared/DesignTokens.swift +++ b/App/BlurtiOS/Shared/DesignTokens.swift @@ -312,8 +312,6 @@ enum DesignTokens { nonisolated static let waveGap: CGFloat = 2 nonisolated static let waveHomeHeight: CGFloat = 44 nonisolated static let waveHomeWidth: CGFloat = 280 - /// 1 draws the wave as one liquid shape through the bar heights instead of the bars themselves. - nonisolated static let waveLiquid: CGFloat = 0 nonisolated static let wavePanelHeight: CGFloat = 40 nonisolated static let wavePanelWidth: CGFloat = 300 nonisolated static let wordmarkHeight: CGFloat = 22 @@ -589,7 +587,6 @@ enum DesignTokens { "metrics.wave/gap": "2", "metrics.wave/home-height": "44", "metrics.wave/home-width": "280", - "metrics.wave/liquid": "0", "metrics.wave/panel-height": "40", "metrics.wave/panel-width": "300", "metrics.wordmark/height": "22", diff --git a/scripts/design-sync.sh b/scripts/design-sync.sh index caee5eda..e59e9e1f 100755 --- a/scripts/design-sync.sh +++ b/scripts/design-sync.sh @@ -58,22 +58,25 @@ format_outputs() { fi } -# The design-literal lint. Scope: the keyboard's view files. PrismOrb.swift is -# deliberately out — its body is the orb's recipe (mesh drift, sparkle spots, -# grain density), documented as text in Figma, and only its parameters are -# tokens. Numbers 0 and 1 pass: `Spacer(minLength: 0)`, `.opacity(on ? 1 : 0)` -# and `scaleEffect(1 + …)` are structure, not design. +# The design-literal lint. Scope: every file under the keyboard's sources +# that draws — new views are linted by default — minus the logic (the model, +# the host controller, the palette, the geometry and interaction rules, the +# voice state) and PrismOrb.swift, whose body is the orb's recipe (mesh drift, +# sparkle spots, grain density), documented as text in Figma, with only its +# parameters as tokens. Numbers 0 and 1 pass: `Spacer(minLength: 0)`, +# `.opacity(on ? 1 : 0)` and `scaleEffect(1 + …)` are structure, not design. lint_literals() { python3 - <<'PY' -import re, sys -files = [ - "App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViews.swift", - "App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift", - "App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift", - "App/BlurtiOS/BlurtKeyboard/Sources/Dissipate.swift", - "App/BlurtiOS/BlurtKeyboard/Sources/BrandOrb.swift", - "App/BlurtiOS/BlurtKeyboard/Sources/SurfaceFinish.swift", -] +import glob, os, re, sys +exempt = { + "KeyboardModel.swift", "KeyboardModel+Mic.swift", "KeyboardModel+Phase.swift", "KeyboardModel+Typing.swift", + "KeyboardViewController.swift", "KeyboardPalette.swift", "KeyGeometry.swift", "KeyboardInteraction.swift", + "VoiceState.swift", "KeyboardMotion.swift", "MotionHeld.swift", "PrismOrb.swift", +} +files = sorted( + path for path in glob.glob("App/BlurtiOS/BlurtKeyboard/Sources/**/*.swift", recursive=True) + if os.path.basename(path) not in exempt +) modifiers = re.compile( r"\.(padding|frame|font|blur|scaleEffect|offset|shadow|opacity|cornerRadius|saturation|brightness" r"|strokeBorder|stroke|lineWidth)\(|\b(spacing|duration|minimumDistance|lineWidth|radius|size|width|height|by):" From 203644cc6a942a51ba7556331dbcaeedb2a6ebb1 Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Tue, 29 Sep 2026 17:22:20 -0400 Subject: [PATCH 53/79] Keyboard: three mic concepts behind one seam, for the pick MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The orb is out. `VoiceElementView` is the seam: every candidate draws from the same `VoiceElementInputs` — the voice state, the level, the moment the words landed, whether motion is allowed, the face, the slot (bar, panel, home) — and nothing else, so the three can be judged from the same states on the same clock. `-BlurtGalleryVoice a|b|c` picks which draws; `-BlurtVoice [light|dark]` renders one by itself; `design-capture.sh --voice` and `ios-record.sh --voice` carry it. - a, the grille (`VoiceGrille`): a dot-matrix mic head that never changes shape. A sheen crosses it at rest; while recording its columns light bottom-up with the engine's meter envelope, quantised to whole dots, and facets on the peaks flash white; one dot runs the perimeter while the mic comes up or the words are made; a thin white cross glint with a faint prismatic fringe sweeps across when the words land; orange on a failure. - b, the ribs (`VoiceRibs`): the thin wave asleep as a ribbed block at rest, awake as the wave, so there is no circle anywhere; a glint runs the ribs on landing. - c, the streak (`VoiceStreak`): a hairline with a bright point that blooms into a light streak with the voice, a short streak sweeping while working, the cross's vertical arm flashing on landing. The mic control is the gesture host around the seam and carries the two glyphs that need saying (clipboard, exclamation); the home hero draws the same element in the app's face. The Full Access row is the note itself, a tap opening Blurt. The orb's tokens, gradients, drop and dissipate are retired; every new number is a token (voice/*, grille/*, ribs/*, streak/*, opacity/sheen|glint|off|grille-rest|hairline, motion sheen|sheen-working| glint-life, radius/*). `VoiceClock` holds the shared clocks (landing, sheen, the facet hash), tested. Review packet: ~/Desktop/blurt-mic-review (sheets per candidate and face, one 11.7 s loop each, every still). 71 tests; periphery clean. Co-Authored-By: Claude Fable 5.1 --- .../BlurtKeyboard/Sources/Dissipate.swift | 22 -- .../BlurtKeyboard/Sources/Grain.swift | 27 ++ .../Sources/KeyboardMotion.swift | 14 +- .../BlurtKeyboard/Sources/MicControl.swift | 111 ++----- .../BlurtKeyboard/Sources/PanelView.swift | 11 +- .../BlurtKeyboard/Sources/PrismOrb.swift | 217 ------------ .../BlurtKeyboard/Sources/VoiceBar.swift | 28 +- .../BlurtKeyboard/Sources/VoiceElement.swift | 106 ++++++ .../BlurtKeyboard/Sources/VoiceGrille.swift | 177 ++++++++++ .../BlurtKeyboard/Sources/VoiceRibs.swift | 102 ++++++ .../BlurtKeyboard/Sources/VoiceStreak.swift | 111 +++++++ .../BlurtiOS/Sources/BlurtiOSApp.swift | 4 +- App/BlurtiOS/BlurtiOS/Sources/HomeHero.swift | 62 +--- .../Sources/KeyboardGalleryView.swift | 107 +++--- .../BlurtiOSTests/DesignTokensTests.swift | 9 - .../BlurtiOSTests/FeedAndLayoutTests.swift | 20 +- .../BlurtiOSTests/VoiceElementTests.swift | 48 +++ App/BlurtiOS/DESIGN.md | 242 +++++++------- App/BlurtiOS/Design/figma/tokens.js | 71 ++-- App/BlurtiOS/Design/tokens.json | 310 ++++++++---------- App/BlurtiOS/Shared/BlurtBrand.swift | 7 - App/BlurtiOS/Shared/DesignTokens.swift | 209 ++++++------ scripts/design-capture.sh | 12 +- scripts/design-sync.sh | 7 +- scripts/ios-record.sh | 16 +- 25 files changed, 1147 insertions(+), 903 deletions(-) delete mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/Dissipate.swift create mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/Grain.swift delete mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/PrismOrb.swift create mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/VoiceElement.swift create mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/VoiceGrille.swift create mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/VoiceRibs.swift create mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/VoiceStreak.swift create mode 100644 App/BlurtiOS/BlurtiOSTests/VoiceElementTests.swift diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/Dissipate.swift b/App/BlurtiOS/BlurtKeyboard/Sources/Dissipate.swift deleted file mode 100644 index db100283..00000000 --- a/App/BlurtiOS/BlurtKeyboard/Sources/Dissipate.swift +++ /dev/null @@ -1,22 +0,0 @@ -import SwiftUI - -/// The orb dissipating: it swells a little, softens to a haze and is gone — -/// mist, not a pop — and condenses back the same way. `size` scales the haze. -private struct Dissipate: ViewModifier { - let amount: Double - let size: CGFloat - - func body(content: Content) -> some View { - content - .scaleEffect(1 + (DesignTokens.Metrics.orbDissipateScale - 1) * amount) - .blur(radius: size * DesignTokens.Metrics.orbDissipateBlur * amount) - .opacity(1 - amount) - } -} - -extension AnyTransition { - /// See `Dissipate`. - static func dissipate(size: CGFloat) -> AnyTransition { - .modifier(active: Dissipate(amount: 1, size: size), identity: Dissipate(amount: 0, size: size)) - } -} diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/Grain.swift b/App/BlurtiOS/BlurtKeyboard/Sources/Grain.swift new file mode 100644 index 00000000..22d622ab --- /dev/null +++ b/App/BlurtiOS/BlurtKeyboard/Sources/Grain.swift @@ -0,0 +1,27 @@ +import SwiftUI + +/// Film grain: a scatter of faint dots drawn from a seed, so a frame is +/// reproducible — the brand's texture, on the keyboard's surface +/// (`SurfaceFinish`), still, one seed. +struct BlurtiOSGrain: View { + let seed: Int + + var body: some View { + Canvas(rendersAsynchronously: true) { context, size in + var state = UInt64(truncatingIfNeeded: seed &* 6_364_136_223_846_793_005 &+ 1) + func next() -> CGFloat { + state = state &* 6_364_136_223_846_793_005 &+ 1_442_695_040_888_963_407 + return CGFloat(state >> 40) / CGFloat(1 << 24) + } + let count = Int(size.width * size.height / 26) + for _ in 0.. 0.5 ? .white.opacity(0.18) : .black.opacity(0.22))) + } + } + .accessibilityHidden(true) + } +} diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardMotion.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardMotion.swift index 0233eee4..833b7734 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardMotion.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardMotion.swift @@ -1,14 +1,8 @@ import BlurtEngine import Foundation -/// The redraw cap for the keyboard's continuous motion — the ring's sweep, the -/// meter's idle wave. The Mac pill reads the same number from the engine: the -/// level feed moves at this cadence, so drawing faster only burns the -/// keyboard's tight energy and memory budget. +/// The redraw cap for the keyboard's continuous motion — the sheen, the +/// meter's idle wave, the glints. The Mac pill reads the same number from +/// the engine: the level feed moves at this cadence, so drawing faster only +/// burns the keyboard's tight energy and memory budget. let keyboardAnimationInterval = MicCapture.meterIntervalSeconds - -/// The keyboard's clocks, in one place. -nonisolated enum KeyboardMotion { - /// One turn of the ring every 1.6 s: the Mac's cadence. - static let ringPeriod = DesignTokens.Motion.ringPeriod -} diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/MicControl.swift b/App/BlurtiOS/BlurtKeyboard/Sources/MicControl.swift index 4ec4b02c..6ab0788c 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/MicControl.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/MicControl.swift @@ -1,32 +1,22 @@ -import BlurtEngine import SwiftUI -/// The mic key is the brand orb, and it says everything without a word or a -/// glyph. Finger down starts, finger up decides tap (latched) or hold -/// (push-to-talk) — `KeyboardModel` runs the engine's gate, `MicPressSequencer` -/// the press's steps, `VoiceState` what shows. What it does: dimmed when -/// Blurt isn't ready (no Full Access, or the app isn't listening; the tap -/// opens Blurt); on a tap the ring sweeps as the app's orb does while the mic -/// comes up; then the orb dissipates — swells a little, softens to a haze, is -/// gone — and in its place the voice is a thin wave, flat on the surface, for -/// as long as you talk, and the wave is the key; on the stop the wave fades -/// and the orb condenses back with the ring sweeping while the words come; -/// then a green ring for a moment when they landed (the violet drop with it), -/// a clipboard on a green ring when they went to the clipboard instead, an -/// orange ring and an exclamation mark when something failed. Each also has -/// its haptic. +/// The mic key. Finger down starts, finger up decides tap (latched) or hold +/// (push-to-talk) — `KeyboardModel` runs the engine's gate, +/// `MicPressSequencer` the press's steps, `VoiceState` what shows, and the +/// voice element draws it (`VoiceElementView`): dimmed when Blurt isn't +/// ready (the tap opens Blurt), working while the mic comes up and the +/// words are made, the meter while you talk, a glint when the words land, +/// orange when something failed. Only the two notices that need saying carry +/// a glyph — a clipboard when the words went there, an exclamation mark on a +/// failure. Each state also has its haptic. /// -/// Nothing snaps or springs: the orb and the wave cross over `wave-fade`, -/// every other change over `state-fade`. Only the press itself answers at -/// once. +/// Nothing snaps or springs: every change on the key fades over `state-fade`. +/// Only the press itself answers at once. struct MicControl: View { var model: KeyboardModel - var size: CGFloat - /// The wave the orb dissipates into while recording — wide and slim — - /// or nil for none (the orb stays). The key's frame is the wave's width - /// throughout, so nothing moves while the two cross; only the circle - /// answers a touch until the wave is up, then the wave's band does. - var wave: CGSize? + let slot: VoiceSlot + /// A narrower box than the slot's, when the bar hasn't the room. + var width: CGFloat? @State private var pressed = false @State private var press = MicPressSequencer() @State private var pressTask: Task? @@ -37,40 +27,27 @@ struct MicControl: View { var body: some View { let state = model.voiceState - let showsWave = state.isRecording && wave != nil + let box = CGSize(width: width ?? slot.box.width, height: slot.box.height) ZStack { - if let wave, state.isRecording { - WaveformMeter( - level: state.level, animated: !reduceMotion, color: palette.signal, - barWidth: WaveformMeter.slimBar, barSpacing: WaveformMeter.slimGap - ) - .frame(width: wave.width, height: wave.height) - .transition(.opacity) - } else { - PrismOrb(mood: Self.mood(state), landedAt: model.resultLandedAt, animated: !reduceMotion) - .clipShape(Circle()) - .overlay { ring(state) } - .frame(width: size, height: size) - .saturation(state.isReady ? 1 : DesignTokens.Metrics.opacityDimSaturation) - .opacity(state.isReady ? 1 : DesignTokens.Metrics.opacityDim) - .transition(reduceMotion ? .opacity : .dissipate(size: size)) - } + VoiceElementView( + inputs: VoiceElementInputs( + state: state, landedAt: model.resultLandedAt, animated: !reduceMotion, palette: palette, slot: slot)) if let glyph = state.glyph { Image(systemName: Self.symbol(glyph)) .font( - .system(size: size * DesignTokens.Typography.ratioOrbGlyph, weight: DesignTokens.Typography.weightOrbGlyph) + .system( + size: box.height * DesignTokens.Typography.ratioVoiceGlyph, + weight: DesignTokens.Typography.weightVoiceGlyph) ) - .foregroundStyle(.white) + .foregroundStyle(palette.keyText) .transition(.opacity) } } - .frame(width: wave.map { max($0.width, size) } ?? size, height: size) - .animation(.easeInOut(duration: DesignTokens.Motion.waveFade), value: state.isRecording) + .frame(width: box.width, height: box.height) .animation(.easeInOut(duration: DesignTokens.Motion.stateFade), value: state.phase) - .animation(.easeInOut(duration: DesignTokens.Motion.stateFade), value: state.isReady) - .scaleEffect(pressed ? DesignTokens.Metrics.pressScale : 1) + .scaleEffect(pressed ? DesignTokens.Metrics.voicePressScale : 1) .animation(.easeOut(duration: DesignTokens.Motion.press), value: pressed) - .contentShape(showsWave ? AnyShape(Capsule()) : AnyShape(Circle())) + .contentShape(Rectangle()) .accessibilityLabel(state.accessibilityLabel) .accessibilityValue(state.accessibilityValue) .accessibilityAddTraits(.isButton) @@ -79,7 +56,7 @@ struct MicControl: View { .onChanged { value in pressed = true if press.began() { - // The press waits a beat, so a swipe that starts on the orb (the + // The press waits a beat, so a swipe that starts on the key (the // panel's carousel) never starts a dictation it must then cancel. pressTask = Task { [model] in try? await Task.sleep(for: KeyboardInteraction.micPressDelay) @@ -110,42 +87,6 @@ struct MicControl: View { ) } - /// The ring: the app orb's sweep (one turn per 1.6 s, engine geometry) - /// while the mic comes up and while the words come; still, and solid green - /// or orange, for a notice; still while recording. - @ViewBuilder private func ring(_ state: VoiceState) -> some View { - let width = state.isWorking || state.isNotice ? DesignTokens.Metrics.ringActive : DesignTokens.Metrics.ringStill - switch state.ring { - case .sweeping where !reduceMotion: - TimelineView(.animation(minimumInterval: keyboardAnimationInterval)) { timeline in - Circle() - .strokeBorder(BlurtBrand.orbRingGradient, lineWidth: width) - .rotationEffect( - .degrees( - MeterBarGeometry.rotationDegrees( - time: timeline.date.timeIntervalSinceReferenceDate, period: KeyboardMotion.ringPeriod))) - } - case .solid(.error): - Circle().strokeBorder(BlurtBrand.errorOrange, lineWidth: width) - case .solid(.ok): - Circle().strokeBorder(BlurtBrand.greenOnDark, lineWidth: width) - case .still, .sweeping: - Circle().strokeBorder(BlurtBrand.orbRingGradient, lineWidth: width) - } - } - - /// The orb's story from the phase: green, greener with the voice; the - /// violet drop is keyed to the moment the words landed, not to a phase. - static func mood(_ state: VoiceState) -> PrismOrb.Mood { - guard state.isReady else { return .off } - switch state.phase { - case .idle, .error, .pasted, .copied: return .idle - case .connecting: return .listening(level: 0) - case .recording: return .listening(level: state.level) - case .processing: return .working - } - } - private static func symbol(_ glyph: VoiceState.Glyph) -> String { switch glyph { case .clipboard: "doc.on.clipboard" diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/PanelView.swift b/App/BlurtiOS/BlurtKeyboard/Sources/PanelView.swift index e54936d3..715ae9ae 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/PanelView.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/PanelView.swift @@ -1,16 +1,15 @@ import SwiftUI -/// A big orb, centred, that dissipates into the wave while recording; cancel -/// in the corner while something is in flight; one row of keys. 216 pt. +/// The voice element, centred, big; cancel in the corner while something is +/// in flight; one row of keys. 216 pt. struct PanelView: View { var model: KeyboardModel + @Environment(\.keyboardPalette) private var palette var body: some View { VStack(spacing: DesignTokens.Metrics.panelSpacing) { Spacer(minLength: 0) - MicControl( - model: model, size: DesignTokens.Metrics.orbPanel, - wave: CGSize(width: DesignTokens.Metrics.wavePanelWidth, height: DesignTokens.Metrics.wavePanelHeight)) + MicControl(model: model, slot: .panel) Spacer(minLength: 0) HStack(spacing: KeyboardPalette.keyGap) { if model.needsGlobe { KeyCap(systemImage: "globe", dark: true) { model.globe() } } @@ -21,7 +20,7 @@ struct PanelView: View { } .overlay(alignment: .topTrailing) { if model.voiceState.canCancel { - KeyCap(systemImage: "xmark", tint: BlurtBrand.errorOrange, bare: true) { model.cancel() } + KeyCap(systemImage: "xmark", tint: palette.notice, bare: true) { model.cancel() } .accessibilityLabel("Cancel dictation") .transition(.opacity) } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/PrismOrb.swift b/App/BlurtiOS/BlurtKeyboard/Sources/PrismOrb.swift deleted file mode 100644 index cf7c9c8a..00000000 --- a/App/BlurtiOS/BlurtKeyboard/Sources/PrismOrb.swift +++ /dev/null @@ -1,217 +0,0 @@ -import SwiftUI - -/// The brand's artwork in motion. In the illustration a green beam goes into -/// the prism and a violet, starlit one comes out: green is the input, the -/// voice; violet is the magic, the words. The orb lives green — calm at rest, -/// swelling with the voice while you talk — and the moment the words land in -/// the field a violet drop falls into it: a glittering pulse that blooms from -/// the centre with the haptic, then flows back out into the green. Liquid in -/// its motion (a mesh gradient whose points drift), airy in its look (soft -/// light, low contrast), matte under film grain, as the artwork is. -/// -/// A fill: the caller clips it to a circle or a capsule and puts the ring on -/// top. Under Reduce Motion the fluid holds still and the drop simply fades. -struct PrismOrb: View { - enum Mood: Equatable { - /// Blurt is not ready: the calm green, dimmed by the caller. - case off - /// Resting: the calm green, breathing. - case idle - /// The voice going in: greener and moving with the level (0…1). - case listening(level: Float) - /// The words being made: the calm green, working. - case working - } - - var mood: Mood - /// When the words landed — the drop falls then and is gone 2.4 s later. - var landedAt: Date? - var animated: Bool - - /// The drop's life: up in 0.5 s, held to 0.9 s, gone by 2.4 s — an event, - /// but a soft one. - static let dropDuration: TimeInterval = DesignTokens.Motion.drop - static let dropRise: TimeInterval = DesignTokens.Motion.dropRise - static let dropHold: TimeInterval = DesignTokens.Motion.dropHold - - var body: some View { - TimelineView(.animation(minimumInterval: keyboardAnimationInterval, paused: !animated)) { timeline in - let time = animated ? timeline.date.timeIntervalSinceReferenceDate : 0 - let elapsed = landedAt.map { timeline.date.timeIntervalSince($0) } ?? .infinity - let drop = Self.dropAmount(at: elapsed) - ZStack { - Rectangle().fill(mesh(at: time, drop: drop)) - // A soft light from the upper left, so the disc reads as a body, not - // a flat swatch — airy, not glossy. - GeometryReader { geo in - Rectangle().fill( - RadialGradient( - colors: [.white.opacity(DesignTokens.Metrics.opacityOrbLight), .clear], - center: UnitPoint(x: DesignTokens.Metrics.orbLightX, y: DesignTokens.Metrics.orbLightY), startRadius: 0, - endRadius: min(geo.size.width, geo.size.height) * DesignTokens.Metrics.orbLightReach)) - } - if drop > 0 { - Drop(amount: drop, elapsed: elapsed) - Sparkles(elapsed: elapsed) // invariant-ok: the orb's star glyphs, not the Sparkle updater - } - BlurtiOSGrain(seed: animated ? Int(time * 24) : 7).opacity(DesignTokens.Metrics.opacityGrain).blendMode( - .overlay) - } - } - .animation(.easeInOut(duration: DesignTokens.Motion.mood), value: mood) - } - - /// How much violet is in the orb `elapsed` seconds after the words landed: - /// a quick bloom, a moment held, a slow flow back to green. - static func dropAmount(at elapsed: TimeInterval) -> Double { - guard elapsed >= 0, elapsed < dropDuration else { return 0 } - func smooth(_ x: Double) -> Double { - let t = min(max(x, 0), 1) - return t * t * (3 - 2 * t) - } - if elapsed < dropRise { return smooth(elapsed / dropRise) } - if elapsed < dropHold { return 1 } - return 1 - smooth((elapsed - dropHold) / (dropDuration - dropHold)) - } - - // MARK: The fluid - - /// A 3 × 3 mesh. The corners stay put; the edge midpoints and the centre - /// drift on slow sines, further with the voice. - private func mesh(at time: TimeInterval, drop: Double) -> MeshGradient { - let level = CGFloat(self.level) - let sway = 0.10 + 0.16 * level - func drift(_ base: Float, _ phase: Double, _ speed: Double) -> Float { - base + Float(sway * sin(time * speed + phase)) - } - let points: [SIMD2] = [ - [0, 0], [drift(0.5, 0.0, 0.9), 0], [1, 0], - [0, drift(0.5, 1.7, 0.7)], [drift(0.5, 3.1, 1.1), drift(0.5, 0.6, 0.8)], [1, drift(0.5, 4.2, 0.6)], - [0, 1], [drift(0.5, 2.3, 1.0), 1], [1, 1], - ] - // The drop soaks the centre first and the corners least. - let soak: [Double] = [0.45, 0.75, 0.45, 0.75, 1, 0.75, 0.45, 0.75, 0.45] - let colors = zip(green, soak).map { base, weight in - base.mix(with: Palette.violet, by: drop * weight) - } - return MeshGradient(width: 3, height: 3, points: points, colors: colors) - } - - private var level: Float { - if case .listening(let level) = mood { return level } - return 0 - } - - /// Row-major, top to bottom: the green the orb lives in, with the brand's - /// pale lavender as the light on top so it stays airy. - private var green: [Color] { - switch mood { - case .off, .idle, .working: - return [ - Palette.lavender, Palette.mist, Palette.lavender, - Palette.greenLight, Palette.greenLight, Palette.greenLight, - Palette.green, Palette.greenLight, Palette.green, - ] - case .listening(let level): - // Greener and brighter the louder: the beam going in. - let bright = Palette.greenLight.mix(with: Palette.mist, by: 0.25 + 0.45 * Double(level)) - return [ - Palette.mist, bright, Palette.mist, - Palette.greenLight, bright, Palette.greenLight, - Palette.green, Palette.greenLight, Palette.green, - ] - } - } - - /// The orb's colours, by the part they play; the values are the brand's. - private enum Palette { - static let mist = DesignTokens.Brand.greenMist - static let lavender = DesignTokens.Brand.violetLavender - static let periwinkle = DesignTokens.Brand.violetPeriwinkle - static let violet = DesignTokens.Brand.cobolt - static let green = DesignTokens.Brand.green700 - static let greenLight = DesignTokens.Brand.green400 - } - - /// The drop itself: a violet bloom that grows from the centre and thins as - /// it spreads, so the colour reads as poured in rather than switched. - private struct Drop: View { - let amount: Double - let elapsed: TimeInterval - - var body: some View { - let spread = min(1, elapsed / DesignTokens.Motion.dropSpread) - Circle() - .fill( - RadialGradient( - colors: [Palette.violet.opacity(0.9), Palette.periwinkle.opacity(0.55), .clear], - center: .center, startRadius: 0, endRadius: 90) - ) - .scaleEffect(0.15 + 1.6 * spread) - .opacity(amount * (1 - 0.5 * spread)) - .blendMode(.plusLighter) - } - } -} - -/// Film grain: a scatter of faint dots, a new scatter each frame so it -/// shimmers the way grain does, drawn from a seed so a frame is reproducible. -/// The orb's, and — still, one seed — the keyboard surface's (`SurfaceFinish`). -struct BlurtiOSGrain: View { - let seed: Int - - var body: some View { - Canvas(rendersAsynchronously: true) { context, size in - var state = UInt64(truncatingIfNeeded: seed &* 6_364_136_223_846_793_005 &+ 1) - func next() -> CGFloat { - state = state &* 6_364_136_223_846_793_005 &+ 1_442_695_040_888_963_407 - return CGFloat(state >> 40) / CGFloat(1 << 24) - } - let count = Int(size.width * size.height / 26) - for _ in 0.. 0.5 ? .white.opacity(0.18) : .black.opacity(0.22))) - } - } - .accessibilityHidden(true) - } -} - -/// The artwork's stars: six four-point sparkles that burst once with the -/// drop — each a beat after the last — and are gone with it. -private struct Sparkles: View { // invariant-ok: the orb's star glyphs, not the Sparkle updater - let elapsed: TimeInterval - - private struct Spot { - let x: CGFloat - let y: CGFloat - let size: CGFloat - let delay: Double - } - - private static let spots: [Spot] = [ - Spot(x: 0.5, y: 0.5, size: 0.14, delay: 0.08), Spot(x: 0.24, y: 0.3, size: 0.16, delay: 0.24), - Spot(x: 0.76, y: 0.22, size: 0.11, delay: 0.4), Spot(x: 0.8, y: 0.64, size: 0.14, delay: 0.5), - Spot(x: 0.3, y: 0.74, size: 0.1, delay: 0.64), Spot(x: 0.56, y: 0.84, size: 0.12, delay: 0.77), - ] - - var body: some View { - GeometryReader { geo in - ForEach(Array(Self.spots.enumerated()), id: \.offset) { _, spot in - let life = (elapsed - spot.delay) / 1.3 - let up = min(max(life, 0), 1) - let shine = up < 0.3 ? up / 0.3 : max(0, 1 - (up - 0.3) / 0.7) - Image(systemName: "sparkle") - .font(.system(size: min(geo.size.width, geo.size.height) * spot.size, weight: .regular)) - .foregroundStyle(.white) - .opacity(shine) - .scaleEffect(0.4 + 0.9 * shine) - .position(x: geo.size.width * spot.x, y: geo.size.height * spot.y) - } - } - .accessibilityHidden(true) - } -} diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift index 7dbc3684..79264336 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift @@ -1,4 +1,3 @@ -import BlurtEngine import SwiftUI /// The keyboard's voice row, and the only place voice lives: the orb, which @@ -10,6 +9,7 @@ import SwiftUI /// as a key term. The bar then becomes the field the keys type into. struct VoiceBar: View { var model: KeyboardModel + @Environment(\.keyboardPalette) private var palette static let height = DesignTokens.Metrics.voicebarHeight @@ -20,25 +20,29 @@ struct VoiceBar: View { TermField(model: model) .transition(.opacity) } else if !model.hasFullAccess { - // The one state the orb can't show on its own: without Full Access - // nothing here can work, and the user has to be told where to go. - HStack(spacing: DesignTokens.Metrics.voicebarNoteGap) { - MicControl(model: model, size: DesignTokens.Metrics.orbBar, wave: nil) + // The one state the element can't show on its own: without Full + // Access nothing here can work, and the user has to be told where + // to go. The line is the key: a tap opens Blurt, whose checklist + // says the rest. + Button { + model.openApp() + } label: { Text("Allow Full Access in Settings → Keyboards") .font(.footnote) - .foregroundStyle(BlurtBrand.errorOrange) + .foregroundStyle(palette.notice) .lineLimit(1) - .minimumScaleFactor(0.8) + .minimumScaleFactor(0.8) // literal-ok: the note may shrink a little on a narrow phone + .frame(maxWidth: .infinity, maxHeight: .infinity) } + .buttonStyle(KeyPressStyle()) + .accessibilityLabel("Start Blurt") .transition(.opacity) } else { - // The wave stays clear of the + at the trailing edge, on both sides so it stays centred. + // The element stays clear of the + at the trailing edge, on both sides so it stays centred. let clearance = DesignTokens.Metrics.glyphHit + DesignTokens.Metrics.voicebarAddtermClearance MicControl( - model: model, size: DesignTokens.Metrics.orbBar, - wave: CGSize( - width: min(DesignTokens.Metrics.waveBarWidth, geo.size.width - 2 * clearance), // literal-ok: both sides - height: DesignTokens.Metrics.waveBarHeight) + model: model, slot: .bar, + width: min(DesignTokens.Metrics.voiceBarWidth, geo.size.width - 2 * clearance) // literal-ok: both sides ) .transition(.opacity) } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceElement.swift b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceElement.swift new file mode 100644 index 00000000..f45961ce --- /dev/null +++ b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceElement.swift @@ -0,0 +1,106 @@ +import SwiftUI + +/// The mic control's face — the one part of the keyboard that says what is +/// happening, without a word. Three concepts are built side by side behind +/// this seam so they can be judged on sight from the same states, the same +/// level and the same landing moment; the one that ships stays, the others +/// go. Pick with `-BlurtGalleryVoice a|b|c` (DESIGN.md › The voice element). +nonisolated enum VoiceElementKind: String, CaseIterable, Sendable { + /// A: the grille — a dot-matrix mic head that lights as a stepped meter. + case grille = "a" + /// B: the ribs — the thin wave asleep as a ribbed grille, awake as the wave. + case ribs = "b" + /// C: the streak — a hairline with a bright point that blooms into a light streak. + case streak = "c" + + static let shipped = VoiceElementKind.grille + + /// `-BlurtGalleryVoice a|b|c`, or nil when the arguments don't say. + static func parse(_ arguments: [String]) -> VoiceElementKind? { + guard let flag = arguments.firstIndex(of: "-BlurtGalleryVoice"), arguments.count > flag + 1 else { return nil } + return VoiceElementKind(rawValue: arguments[flag + 1]) + } +} + +/// Where the element sits, for the sizes that differ. +nonisolated enum VoiceSlot: String, CaseIterable, Sendable { + case bar + case panel + case home + + /// The box the element is given (`voice/*` tokens). + var box: CGSize { + let metrics = DesignTokens.Metrics.self + return switch self { + case .bar: CGSize(width: metrics.voiceBarWidth, height: metrics.voiceBarHeight) + case .panel: CGSize(width: metrics.voicePanelWidth, height: metrics.voicePanelHeight) + case .home: CGSize(width: metrics.voiceHomeWidth, height: metrics.voiceHomeHeight) + } + } +} + +/// Everything a candidate draws from — nothing else reaches it: the state, +/// the level inside it, the moment the words landed, whether motion is +/// allowed, the face's colours, and where it sits. +struct VoiceElementInputs { + let state: VoiceState + let landedAt: Date? + let animated: Bool + let palette: KeyboardPalette + let slot: VoiceSlot +} + +/// The seam: draws whichever kind the environment names. +struct VoiceElementView: View { + let inputs: VoiceElementInputs + @Environment(\.voiceElementKind) private var kind + + var body: some View { + switch kind { + case .grille: VoiceGrille(inputs: inputs) + case .ribs: VoiceRibs(inputs: inputs) + case .streak: VoiceStreak(inputs: inputs) + } + } +} + +private struct VoiceElementKindKey: EnvironmentKey { + static let defaultValue = VoiceElementKind.shipped +} + +extension EnvironmentValues { + var voiceElementKind: VoiceElementKind { + get { self[VoiceElementKindKey.self] } + set { self[VoiceElementKindKey.self] = newValue } + } +} + +/// The clocks the candidates share, so their motion cannot drift apart. +nonisolated enum VoiceClock { + /// The landing glint's progress, 0 → 1 over `motion.landing` after the + /// words landed; nil before and after. + static func landing(landedAt: Date?, now: Date) -> Double? { + guard let landedAt else { return nil } + let elapsed = now.timeIntervalSince(landedAt) + guard elapsed >= 0, elapsed < DesignTokens.Motion.landing else { return nil } + return elapsed / DesignTokens.Motion.landing + } + + /// Where the sheen's band is, 0 → 1 across the element and back to 0, on + /// the rest period or the working one. + static func sheen(time: TimeInterval, working: Bool) -> Double { + let period = working ? DesignTokens.Motion.sheenWorking : DesignTokens.Motion.sheen + return (time.truncatingRemainder(dividingBy: period)) / period + } + + /// A small deterministic number in 0…1 for a facet and a moment — the + /// glints are random to the eye and the same in every capture. + static func hash(_ index: Int, _ tick: Int) -> Double { + var state = UInt64( + truncatingIfNeeded: index &* 6_364_136_223_846_793_005 &+ tick &* 1_442_695_040_888_963_407 &+ 17) + state ^= state >> 29 + state = state &* 0x9E37_79B9_7F4A_7C15 + state ^= state >> 32 + return Double(state >> 40) / Double(1 << 24) + } +} diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceGrille.swift b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceGrille.swift new file mode 100644 index 00000000..ecf984db --- /dev/null +++ b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceGrille.swift @@ -0,0 +1,177 @@ +import BlurtEngine +import SwiftUI + +/// Candidate A — the grille. A dot-matrix mic head: a lattice of small dots +/// in a rectangle with the brand's corners, reading as a mic grille, a +/// rhinestone mesh and the brand's halftone grain at once. It never changes +/// shape; only its dots light. At rest a slow sheen crosses it, the chrome +/// catching light. While recording the lattice is the meter: columns light +/// bottom-up with the level in stepped green (the brand's dithered gradient, +/// an LED VU), and on the peaks a few dots flash white — the facets +/// glistening. While the mic comes up or the words are made, one lit dot +/// runs the perimeter on the ring's cadence. When the words land a thin +/// white cross glint sweeps across it once; a failure turns it orange. +struct VoiceGrille: View { + let inputs: VoiceElementInputs + + private typealias Metrics = DesignTokens.Metrics + + var body: some View { + let box = Self.box(inputs.slot) + TimelineView(.animation(minimumInterval: keyboardAnimationInterval, paused: !inputs.animated)) { timeline in + let now = inputs.animated ? timeline.date : Date(timeIntervalSinceReferenceDate: 0) + Canvas(rendersAsynchronously: true) { context, size in + draw(&context, size: size, now: now) + } + } + .frame(width: box.width, height: box.height) + .opacity(inputs.state.isReady ? 1 : Metrics.opacityOff) + .animation(.easeInOut(duration: DesignTokens.Motion.stateFade), value: inputs.state.isReady) + .accessibilityHidden(true) + } + + static func box(_ slot: VoiceSlot) -> CGSize { + switch slot { + case .bar: CGSize(width: Metrics.grilleBarWidth, height: Metrics.grilleBarHeight) + case .panel: CGSize(width: Metrics.grillePanelWidth, height: Metrics.grillePanelHeight) + case .home: CGSize(width: Metrics.grilleHomeWidth, height: Metrics.grilleHomeHeight) + } + } + + private func draw(_ context: inout GraphicsContext, size: CGSize, now: Date) { + let state = inputs.state + let palette = inputs.palette + let time = now.timeIntervalSinceReferenceDate + let pitch = Metrics.grillePitch + let dot = Metrics.grilleDot + let lattice = Self.lattice(size, pitch: pitch) + let columns = lattice.columns + let rows = lattice.rows + let origin = lattice.origin + // The lattice is the meter: the engine's envelope and idle wave give each + // column a height, quantised to whole dots from the bottom. + let meter = MeterBarRow(count: columns, availableHeight: size.height) + let level = state.isRecording ? state.level : 0 + let sheenPhase = VoiceClock.sheen(time: time, working: state.isWorking && !state.isRecording) + let sheenBand = size.width * Metrics.grilleSheenWidth + let sheenCentre = sheenPhase * (size.width + size.height + sheenBand) - sheenBand + let runner = Self.runnerIndex(time: time, columns: columns, rows: rows) + let (glintTick, glintPhase) = Self.glintClock(time) + let (restColour, restOpacity) = Self.rest(state: state, palette: palette) + let sheen = inputs.animated && !state.isRecording ? (centre: sheenCentre, band: sheenBand) : nil + for column in 0.. 0.35 && VoiceClock.hash(column, glintTick) < Double(level) * 0.5 // literal-ok: how often a facet catches the light + for row in 0.. 0, fromBottom <= lit { + colour = palette.signal + opacity = 1 + // The top of a loud column glistens: a facet catches the light. + if fromBottom == lit, glints { + colour = DesignTokens.Brand.white + opacity = 1 - glintPhase + } + } else if let runner, runner == Self.perimeterIndex(column: column, row: row, columns: columns, rows: rows) { + colour = palette.signal + opacity = 1 + } else if let sheen { + // The sheen: a diagonal band of light passing over the lattice. + let distance = abs(x + y - sheen.centre) + if distance < sheen.band / 2 { opacity += Metrics.opacitySheen * (1 - distance / (sheen.band / 2)) } // literal-ok: half the band each side + } + let rect = CGRect(x: x - dot / 2, y: y - dot / 2, width: dot, height: dot) // literal-ok: centred dots + context.fill(Path(ellipseIn: rect), with: .color(colour.opacity(min(1, opacity)))) + } + } + if let progress = VoiceClock.landing(landedAt: inputs.landedAt, now: now) { + Self.glint(&context, size: size, progress: progress) + } + } + + /// How many dots fit, and where the first one sits so the lattice is centred. + private struct Lattice { + let columns: Int + let rows: Int + let origin: CGPoint + } + + private static func lattice(_ size: CGSize, pitch: CGFloat) -> Lattice { + let columns = max(1, Int(size.width / pitch)) + let rows = max(1, Int(size.height / pitch)) + return Lattice( + columns: columns, rows: rows, + origin: CGPoint( + x: (size.width - CGFloat(columns - 1) * pitch) / 2, y: (size.height - CGFloat(rows - 1) * pitch) / 2)) // literal-ok: centred + } + + /// Which flash we are in, and how far through it. + private static func glintClock(_ time: TimeInterval) -> (Int, Double) { + let life = DesignTokens.Motion.glintLife + return (Int(time / life), time.truncatingRemainder(dividingBy: life) / life) + } + + /// The lattice's colour when nothing is lit: quiet at rest, green for a + /// landing, orange for a failure. + private static func rest(state: VoiceState, palette: KeyboardPalette) -> (Color, Double) { + switch state.phase { + case .error: (palette.notice, 1) + case .pasted, .copied: (palette.signal, 1) + case .idle, .connecting, .recording, .processing: (palette.keyText, Metrics.opacityGrilleRest) + } + } + + /// The perimeter dot the runner is on while something is happening. + private static func runnerIndex(time: TimeInterval, columns: Int, rows: Int) -> Int? { + let perimeter = max(1, 2 * columns + 2 * rows - 4) + let phase = VoiceClock.sheen(time: time, working: true) + return Int(phase * Double(perimeter)) % perimeter + } + + /// A dot's place on the perimeter, clockwise from the top-left, or nil inside. + private static func perimeterIndex(column: Int, row: Int, columns: Int, rows: Int) -> Int? { + if row == 0 { return column } + if column == columns - 1 { return columns - 1 + row } + if row == rows - 1 { return columns - 1 + rows - 1 + (columns - 1 - column) } + if column == 0 { return 2 * (columns - 1) + rows - 1 + (rows - 1 - row) } + return nil + } + + /// The cross glint: a thin white four-point flare that sweeps left to right + /// as the words land, its vertical arm taller than the grille, with a + /// faint prismatic fringe — the photograph's lens flare, once. + private static func glint(_ context: inout GraphicsContext, size: CGSize, progress: Double) { + let alpha = Metrics.opacityGlint * (1 - progress) + let x = size.width * progress + let arm = size.height * Metrics.grilleGlintArm + let width = Metrics.grilleGlintWidth + let midY = size.height / 2 + func line(_ from: CGPoint, _ to: CGPoint, colour: Color, opacity: Double) { + var path = Path() + path.move(to: from) + path.addLine(to: to) + context.stroke(path, with: .color(colour.opacity(opacity)), lineWidth: width) + } + let fringe = alpha * 0.4 // literal-ok: the fringe is a fraction of the flare + line( + CGPoint(x: x + width, y: midY - arm / 2), CGPoint(x: x + width, y: midY + arm / 2), + colour: DesignTokens.Brand.violetIris, opacity: fringe) + line( + CGPoint(x: x - width, y: midY - arm / 2), CGPoint(x: x - width, y: midY + arm / 2), + colour: DesignTokens.Brand.green400, opacity: fringe) + line( + CGPoint(x: x, y: midY - arm / 2), CGPoint(x: x, y: midY + arm / 2), colour: DesignTokens.Brand.white, + opacity: alpha) + line( + CGPoint(x: 0, y: midY), CGPoint(x: size.width, y: midY), colour: DesignTokens.Brand.white, opacity: alpha * 0.7) // literal-ok: the horizontal arm sits back + let core = Metrics.grilleDot * 2 // literal-ok: the flare's centre is a double dot + context.fill( + Path(ellipseIn: CGRect(x: x - core / 2, y: midY - core / 2, width: core, height: core)), // literal-ok: centred + with: .color(DesignTokens.Brand.white.opacity(alpha))) + } +} diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceRibs.swift b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceRibs.swift new file mode 100644 index 00000000..b1f63c64 --- /dev/null +++ b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceRibs.swift @@ -0,0 +1,102 @@ +import SwiftUI + +/// Candidate B — the ribs. The mic at rest is a short block of vertical ribs: +/// the thin wave's own bars, still, under a symmetric envelope — the art-deco +/// grille of a Shure 55, the ribbon of an RCA 77. While recording the ribs +/// are the wave: they widen to the box and follow the voice. So there is no +/// circle anywhere, ever, and the element the recording shows is the one +/// that was there all along. A sheen passes over the ribs at rest; a white +/// glint runs them when the words land; a failure turns them orange. +struct VoiceRibs: View { + let inputs: VoiceElementInputs + + private typealias Metrics = DesignTokens.Metrics + + var body: some View { + let state = inputs.state + let box = inputs.slot.box + let awake = state.isRecording + let waveHeight: CGFloat = + switch inputs.slot { + case .bar: Metrics.waveBarHeight + case .panel: Metrics.wavePanelHeight + case .home: Metrics.waveHomeHeight + } + ZStack { + if awake { + WaveformMeter( + level: state.level, animated: inputs.animated, color: inputs.palette.signal, + barWidth: WaveformMeter.slimBar, barSpacing: WaveformMeter.slimGap + ) + .frame(width: box.width, height: waveHeight) + .transition(.opacity) + } else { + TimelineView(.animation(minimumInterval: keyboardAnimationInterval, paused: !inputs.animated)) { timeline in + let now = inputs.animated ? timeline.date : Date(timeIntervalSinceReferenceDate: 0) + Canvas(rendersAsynchronously: true) { context, size in + Self.ribs(&context, size: size, inputs: inputs, now: now) + } + } + .frame(width: Metrics.ribsRestWidth, height: Metrics.ribsRestHeight) + .transition(.opacity) + } + } + .frame(width: box.width, height: box.height) + .animation(.easeInOut(duration: DesignTokens.Motion.waveFade), value: awake) + .opacity(state.isReady ? 1 : Metrics.opacityOff) + .animation(.easeInOut(duration: DesignTokens.Motion.stateFade), value: state.isReady) + .overlay { + TimelineView(.animation(minimumInterval: keyboardAnimationInterval, paused: !inputs.animated)) { timeline in + Canvas { context, size in + if let progress = VoiceClock.landing(landedAt: inputs.landedAt, now: timeline.date) { + Self.glint(&context, size: size, progress: progress) + } + } + } + .allowsHitTesting(false) + } + .accessibilityHidden(true) + } + + /// The ribs asleep: bars at the wave's pitch under a cosine envelope, in + /// the face's quiet legend colour (orange for a failure, green for a + /// landing), with the sheen passing over them. + private static func ribs(_ context: inout GraphicsContext, size: CGSize, inputs: VoiceElementInputs, now: Date) { + let state = inputs.state + let pitch = WaveformMeter.slimBar + WaveformMeter.slimGap + let count = max(1, Int((size.width + WaveformMeter.slimGap) / pitch)) + let inset = (size.width - CGFloat(count) * pitch + WaveformMeter.slimGap) / 2 // literal-ok: centred + let time = now.timeIntervalSinceReferenceDate + let sheen = VoiceClock.sheen(time: time, working: state.isWorking) + let colour: Color + switch state.phase { + case .error: colour = inputs.palette.notice + case .pasted, .copied: colour = inputs.palette.signal + default: colour = inputs.palette.keyTextSecondary + } + for index in 0.. [,…] [theme] [-BlurtGalleryStill] [-BlurtGalleryBare] + /// -BlurtGallery [,…] [face] [-BlurtGalleryStill] [-BlurtGalleryBare] [-BlurtGalleryVoice a|b|c] /// /// The last word is a face, `light` or `dark` (the older theme words still /// land: `system` and `paper` are light, `system-dark` and `ink` dark); the @@ -14,8 +14,9 @@ /// zero — the ring, the meter's wave, the orb's fluid and grain — so two /// captures of one state are the same pixels; `-BlurtGalleryBare` draws the /// first row alone, no caption, inside a 2 pt `#FF00FF` registration border - /// that `scripts/design-diff.swift crop` cuts to. `-BlurtOrb ` - /// renders one orb fill by itself the same way, for Figma's image fills. + /// that `scripts/design-diff.swift crop` cuts to. `-BlurtGalleryVoice a|b|c` + /// picks which mic concept draws (`VoiceElementKind`); `-BlurtVoice + /// [light|dark]` renders that element by itself. /// where a state is `off` (no Full Access), `start` (app not listening), /// `idle`, `connecting`, `recording`, `processing`, `pasted`, `copied`, /// `error`, `landed` (the drop, timed for a screenshot) or `live` (a whole @@ -42,9 +43,13 @@ var still = false /// One row, no caption, a registration border round the keyboard. var bare = false + /// Which mic concept draws. + var voice = VoiceElementKind.shipped static func parse(_ arguments: [String]) -> Options { - Options(still: arguments.contains("-BlurtGalleryStill"), bare: arguments.contains("-BlurtGalleryBare")) + Options( + still: arguments.contains("-BlurtGalleryStill"), bare: arguments.contains("-BlurtGalleryBare"), + voice: VoiceElementKind.parse(arguments) ?? .shipped) } } @@ -92,6 +97,7 @@ .frame(height: row.model.effectiveLayout.height) .clipped() .environment(\.keyboardMotionHeld, options.still) + .environment(\.voiceElementKind, options.voice) } /// The rows named by the launch arguments; empty when they don't ask for @@ -112,6 +118,13 @@ /// The words that ask for the dark face; anything else is the light one. static let darkFaces: Set = ["dark", "system-dark", "ink"] + /// The pipeline's phases by gallery name; `landed` is pasted, the moment + /// the words went in. + private static let phases: [String: PhaseSnapshot.State] = [ + "connecting": .connecting, "recording": .recording, "processing": .processing, "pasted": .pasted, + "copied": .copied, "error": .error, "landed": .pasted, + ] + private static func model(layout: KeyboardLayout, state: String, theme: String) -> KeyboardModel { let model = KeyboardModel() model.layout = layout @@ -120,22 +133,13 @@ // `term` the voice bar as the key-term field, mid-typing. model.panelShowsKeys = state == "keys" if state == "term" { model.termDraft = "Rizz" } - // `landed`: the words go in 2.4 s after launch, so a screenshot taken 3 s - // in (scripts/ios-sim.sh) catches the drop at its fullest. - if state == "landed" { model.resultLandedAt = Date().addingTimeInterval(2.4) } + // `landed`: the words go in 2.75 s after launch, so a screenshot taken + // 3 s in (scripts/ios-sim.sh) catches the glint mid-sweep. + if state == "landed" { model.resultLandedAt = Date().addingTimeInterval(2.75) } if state == "live" { walk(model) } model.hasFullAccess = state != "off" model.isListening = state != "off" && state != "start" - let phase: PhaseSnapshot.State = - switch state { - case "connecting": .connecting - case "recording": .recording - case "processing": .processing - case "pasted": .pasted - case "copied": .copied - case "error": .error - default: .idle - } + let phase = Self.phases[state] ?? .idle model.snapshot = PhaseSnapshot( state: phase, message: phase == .error ? "The microphone didn't start." : nil, level: phase == .recording ? 0.62 : 0, at: Date()) @@ -175,43 +179,62 @@ } } - /// `-BlurtOrb `: one orb fill, - /// still, on the ink surface, inside the registration border — the image - /// Figma's `Orb/Disc` component uses, since a mesh gradient under grain is - /// nothing Figma can draw natively (DESIGN.md › Figma). `landed` is the - /// drop at its peak; `listening` is the gallery's level, 0.62. - struct OrbStillView: View { - let size: CGFloat - let mood: PrismOrb.Mood + /// `-BlurtVoice [light|dark]`: one voice + /// element by itself, in its slot's box, on the face's surface, inside the + /// registration border — for the review sheet and for Figma. States are + /// the pipeline's plus `off` (not ready) and `landed` (the glint, timed + /// for a 3 s screenshot). + struct VoiceStillView: View { + let kind: VoiceElementKind + let slot: VoiceSlot + let state: VoiceState let landedAt: Date? + let dark: Bool var body: some View { + let palette: KeyboardPalette = dark ? .brandDark : .brandLight VStack { Spacer(minLength: 0) - PrismOrb(mood: mood, landedAt: landedAt, animated: false) - .frame(width: size, height: size) - .clipShape(Circle()) - .padding(KeyboardGalleryView.registrationWidth) - .background(KeyboardGalleryView.registration) + VoiceElementView( + inputs: VoiceElementInputs(state: state, landedAt: landedAt, animated: true, palette: palette, slot: slot) + ) + .frame(width: slot.box.width, height: slot.box.height) + .padding(KeyboardGalleryView.registrationWidth) + .background(KeyboardGalleryView.registration) + .environment(\.voiceElementKind, kind) Spacer(minLength: 0) } .frame(maxWidth: .infinity, maxHeight: .infinity) - .background(DesignTokens.Brand.ink) + .background(palette.surface) .ignoresSafeArea() } - static func parse(_ arguments: [String]) -> OrbStillView? { - guard let flag = arguments.firstIndex(of: "-BlurtOrb"), arguments.count > flag + 2, - let size = Double(arguments[flag + 1]) + static func parse(_ arguments: [String]) -> VoiceStillView? { + guard let flag = arguments.firstIndex(of: "-BlurtVoice"), arguments.count > flag + 3, + let kind = VoiceElementKind(rawValue: arguments[flag + 1]), + let slot = VoiceSlot(rawValue: arguments[flag + 2]) else { return nil } - switch arguments[flag + 2] { - case "off": return OrbStillView(size: size, mood: .off, landedAt: nil) - case "idle": return OrbStillView(size: size, mood: .idle, landedAt: nil) - case "listening": return OrbStillView(size: size, mood: .listening(level: 0.62), landedAt: nil) - case "working": return OrbStillView(size: size, mood: .working, landedAt: nil) - case "landed": return OrbStillView(size: size, mood: .idle, landedAt: Date().addingTimeInterval(-0.6)) - default: return nil - } + let dark = arguments.count > flag + 4 && darkFaces.contains(arguments[flag + 4]) + guard let (state, landedAt) = Self.state(named: arguments[flag + 3]) else { return nil } + return VoiceStillView(kind: kind, slot: slot, state: state, landedAt: landedAt, dark: dark) + } + + /// The states by name: the pipeline's, `off` (not ready) and `landed` + /// (pasted, with the glint timed for the screenshot). + private static func state(named name: String) -> (VoiceState, Date?)? { + let states: [String: VoiceState] = [ + "off": VoiceState(phase: .idle, isReady: false), + "idle": VoiceState(phase: .idle, isReady: true), + "connecting": VoiceState(phase: .connecting, isReady: true), + "recording": VoiceState(phase: .recording, isReady: true, level: 0.62), + "processing": VoiceState(phase: .processing, isReady: true), + "pasted": VoiceState(phase: .pasted, isReady: true), + "copied": VoiceState(phase: .copied, isReady: true), + "error": VoiceState(phase: .error, isReady: true, message: "The microphone didn't start."), + "landed": VoiceState(phase: .pasted, isReady: true), + ] + guard let state = states[name] else { return nil } + return (state, name == "landed" ? Date().addingTimeInterval(2.75) : nil) } } } diff --git a/App/BlurtiOS/BlurtiOSTests/DesignTokensTests.swift b/App/BlurtiOS/BlurtiOSTests/DesignTokensTests.swift index 55bb5195..98c8e7e9 100644 --- a/App/BlurtiOS/BlurtiOSTests/DesignTokensTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/DesignTokensTests.swift @@ -160,13 +160,4 @@ struct DesignTokensTests { #expect(UIFont(name: name, size: 12) != nil, "\(name) is not registered (UIAppFonts / Design/fonts)") } } - - @Test("the drop is up at drop-rise, held to drop-hold, gone at drop") - func drop() { - #expect(PrismOrb.dropAmount(at: 0) == 0) - #expect(PrismOrb.dropAmount(at: DesignTokens.Motion.dropRise) == 1) - #expect(PrismOrb.dropAmount(at: DesignTokens.Motion.dropHold) == 1) - #expect(PrismOrb.dropAmount(at: DesignTokens.Motion.drop) == 0) - #expect(PrismOrb.dropAmount(at: -1) == 0) - } } diff --git a/App/BlurtiOS/BlurtiOSTests/FeedAndLayoutTests.swift b/App/BlurtiOS/BlurtiOSTests/FeedAndLayoutTests.swift index f915c635..11ded56e 100644 --- a/App/BlurtiOS/BlurtiOSTests/FeedAndLayoutTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/FeedAndLayoutTests.swift @@ -71,11 +71,19 @@ struct LayoutArithmeticTests { #expect(KeyboardGalleryView.rows(from: args)[0].model.palette.face == .light) #expect(KeyboardGalleryView.Options.parse(args) == .init(still: true, bare: true)) #expect(KeyboardGalleryView.Options.parse(["app", "-BlurtGallery", "panel", "idle", "dark"]) == .init()) - #expect(KeyboardGalleryView.OrbStillView.parse(args) == nil) - let orb = KeyboardGalleryView.OrbStillView.parse(["app", "-BlurtOrb", "96", "landed"]) - #expect(orb?.size == 96) - #expect(orb?.landedAt != nil) - #expect(KeyboardGalleryView.OrbStillView.parse(["app", "-BlurtOrb", "96", "nope"]) == nil) - #expect(KeyboardGalleryView.OrbStillView.parse(["app", "-BlurtOrb", "big", "idle"]) == nil) + #expect(KeyboardGalleryView.Options.parse(args).voice == .shipped) + #expect(KeyboardGalleryView.Options.parse(args + ["-BlurtGalleryVoice", "b"]).voice == .ribs) + #expect(KeyboardGalleryView.Options.parse(args + ["-BlurtGalleryVoice", "z"]).voice == .shipped) + #expect(KeyboardGalleryView.VoiceStillView.parse(args) == nil) + let voice = KeyboardGalleryView.VoiceStillView.parse(["app", "-BlurtVoice", "a", "panel", "landed", "dark"]) + #expect(voice?.kind == .grille) + #expect(voice?.slot == .panel) + #expect(voice?.landedAt != nil) + #expect(voice?.dark == true) + #expect( + KeyboardGalleryView.VoiceStillView.parse(["app", "-BlurtVoice", "c", "bar", "recording"])?.state.level == 0.62) + #expect(KeyboardGalleryView.VoiceStillView.parse(["app", "-BlurtVoice", "a", "bar", "nope"]) == nil) + #expect(KeyboardGalleryView.VoiceStillView.parse(["app", "-BlurtVoice", "d", "bar", "idle"]) == nil) + #expect(KeyboardGalleryView.VoiceStillView.parse(["app", "-BlurtVoice", "a", "desk", "idle"]) == nil) } } diff --git a/App/BlurtiOS/BlurtiOSTests/VoiceElementTests.swift b/App/BlurtiOS/BlurtiOSTests/VoiceElementTests.swift new file mode 100644 index 00000000..cfcc9d2c --- /dev/null +++ b/App/BlurtiOS/BlurtiOSTests/VoiceElementTests.swift @@ -0,0 +1,48 @@ +import Foundation +import Testing + +@testable import BlurtiOS + +@Suite("Voice element") +struct VoiceElementTests { + @Test("the kind is read from -BlurtGalleryVoice, and only a, b or c") + func kind() { + #expect(VoiceElementKind.parse(["app"]) == nil) + #expect(VoiceElementKind.parse(["app", "-BlurtGalleryVoice"]) == nil) + #expect(VoiceElementKind.parse(["app", "-BlurtGalleryVoice", "a"]) == .grille) + #expect(VoiceElementKind.parse(["app", "-BlurtGalleryVoice", "b"]) == .ribs) + #expect(VoiceElementKind.parse(["app", "-BlurtGalleryVoice", "c"]) == .streak) + #expect(VoiceElementKind.parse(["app", "-BlurtGalleryVoice", "d"]) == nil) + } + + @Test("the landing glint runs 0 → 1 over motion.landing and is gone after") + func landing() { + let landedAt = Date() + #expect(VoiceClock.landing(landedAt: nil, now: landedAt) == nil) + #expect(VoiceClock.landing(landedAt: landedAt, now: landedAt.addingTimeInterval(-0.1)) == nil) + #expect(VoiceClock.landing(landedAt: landedAt, now: landedAt) == 0) + let half = VoiceClock.landing(landedAt: landedAt, now: landedAt.addingTimeInterval(DesignTokens.Motion.landing / 2)) + #expect(half != nil && abs((half ?? 0) - 0.5) < 0.001) + #expect( + VoiceClock.landing(landedAt: landedAt, now: landedAt.addingTimeInterval(DesignTokens.Motion.landing)) == nil) + } + + @Test("the sheen runs on the rest period, faster while working, and the facet hash is stable") + func clocks() { + #expect(VoiceClock.sheen(time: 0, working: false) == 0) + #expect(abs(VoiceClock.sheen(time: DesignTokens.Motion.sheen / 2, working: false) - 0.5) < 0.001) + #expect(abs(VoiceClock.sheen(time: DesignTokens.Motion.sheenWorking / 4, working: true) - 0.25) < 0.001) + #expect(VoiceClock.hash(3, 7) == VoiceClock.hash(3, 7)) + #expect(VoiceClock.hash(3, 7) != VoiceClock.hash(4, 7)) + #expect((0..<64).allSatisfy { (0...1).contains(VoiceClock.hash($0, 1)) }) + } + + @Test("every slot has a box, from the tokens") + func slots() { + #expect(VoiceSlot.bar.box.width == DesignTokens.Metrics.voiceBarWidth) + #expect(VoiceSlot.panel.box.height == DesignTokens.Metrics.voicePanelHeight) + #expect( + VoiceSlot.home.box + == CGSize(width: DesignTokens.Metrics.voiceHomeWidth, height: DesignTokens.Metrics.voiceHomeHeight)) + } +} diff --git a/App/BlurtiOS/DESIGN.md b/App/BlurtiOS/DESIGN.md index 7bb51bfc..ce2994b9 100644 --- a/App/BlurtiOS/DESIGN.md +++ b/App/BlurtiOS/DESIGN.md @@ -303,9 +303,6 @@ theme's (ink) values, and the app's catalog colours. | `kb/legend` | `#F5F3EB` (`themes.dark/legend`) | `Keyboard.kbLegend` | key legends and bare glyphs | | `kb/legend-secondary` | `#A5A4A2` (`themes.dark/legend-secondary`) | `Keyboard.kbLegendSecondary` | the mono word labels (123, ABC, return, space) and the + at rest | | `kb/notice-error` | `#E67F36` (`brand.orange`) | `Keyboard.kbNoticeError` | the solid ring and glyph for an error | -| `kb/notice-ok` | `#67AD82` (`brand.green/400`) | `Keyboard.kbNoticeOk` | the solid ring for pasted and copied | -| `kb/orb-ring-end` | `#FFFFFF` (`brand.white`) | `Keyboard.kbOrbRingEnd` | the sweeping ring's gradient, bottom-trailing | -| `kb/orb-ring-start` | `#01762F` (`brand.green/700`) | `Keyboard.kbOrbRingStart` | the sweeping ring's gradient, top-leading | | `kb/popup` | `#33302A` (`themes.dark/popup`) | `Keyboard.kbPopup` | the letter pop-up | | `kb/signal` | `#67AD82` (`themes.dark/signal`) | `Keyboard.kbSignal` | the wave, the caret, the saved check | | `kb/surface` | `#1D1B16` (`themes.dark/surface`) | `Keyboard.kbSurface` | the design face's surface (Figma binds to kb/*; Swift reads the palette) | @@ -316,9 +313,6 @@ Gradients: -- `orb` (`Gradients.orb`, bottom → top): `#D7D3F4` at 0, `#B0A7E9` at 0.0673, `#67AD82` at 0.1442, `#01762F` at 0.3029, `#3923C7` at 0.5962, `#887BDD` at 0.75, `#D7D3F4` at 0.8942, `#FFFFFF` at 1 — the Mac orb's fill, the design's own stops (App elements/Recording.svg), swept bottom to top -- `orb-ring` (`Gradients.orbRing`, topLeading → bottomTrailing): `#01762F` at 0, `#FFFFFF` at 1 — the ring round the orb: green into white, corner to corner; spun while something is happening - The default theme follows the host app's light or dark appearance, as the @@ -334,29 +328,29 @@ Inter). Sizes are fixed points, not Dynamic Type, as the system keyboard's are. -| Token | Value | Swift | Use | -| ------------------ | ---------- | ---------------------------- | --------------------------------------------------------------------------- | -| `ratio/orb-glyph` | `0.34` | `Typography.ratioOrbGlyph` | the clipboard and exclamation glyphs, as a fraction of the orb | -| `size/body` | `16` | `Typography.sizeBody` | the app's body text | -| `size/caption` | `14` | `Typography.sizeCaption` | the app's small text | -| `size/cta` | `14` | `Typography.sizeCta` | a mono button label in the app (E2) | -| `size/eyebrow` | `12` | `Typography.sizeEyebrow` | a mono eyebrow in the app (E1) | -| `size/glyph` | `17` | `Typography.sizeGlyph` | the +, × and ✓ | -| `size/label` | `12` | `Typography.sizeLabel` | the mono word labels on keys: 123, ABC, #+=, space, the return label | -| `size/legend` | `16` | `Typography.sizeLegend` | every other key | -| `size/letter` | `24` | `Typography.sizeLetter` | letter keys: the iPhone's (estimated from the l glyph, apple-geometry.json) | -| `size/popup` | `32` | `Typography.sizePopup` | the letter pop-up | -| `size/term` | `17` | `Typography.sizeTerm` | the key-term field | -| `size/title` | `34` | `Typography.sizeTitle` | the app's serif headline | -| `tracking/cta` | `1.4` | `Typography.trackingCta` | uppercase mono at 14: the brand's E2 tracking | -| `tracking/eyebrow` | `1.2` | `Typography.trackingEyebrow` | uppercase mono at 12: the brand's E1 tracking | -| `weight/glyph` | `medium` | `Typography.weightGlyph` | — | -| `weight/label` | `medium` | `Typography.weightLabel` | — | -| `weight/legend` | `medium` | `Typography.weightLegend` | — | -| `weight/letter` | `regular` | `Typography.weightLetter` | — | -| `weight/orb-glyph` | `semibold` | `Typography.weightOrbGlyph` | — | -| `weight/popup` | `regular` | `Typography.weightPopup` | — | -| `weight/term` | `regular` | `Typography.weightTerm` | — | +| Token | Value | Swift | Use | +| -------------------- | ---------- | ----------------------------- | --------------------------------------------------------------------------------- | +| `ratio/voice-glyph` | `0.34` | `Typography.ratioVoiceGlyph` | the clipboard and exclamation glyphs, as a fraction of the voice element's height | +| `size/body` | `16` | `Typography.sizeBody` | the app's body text | +| `size/caption` | `14` | `Typography.sizeCaption` | the app's small text | +| `size/cta` | `14` | `Typography.sizeCta` | a mono button label in the app (E2) | +| `size/eyebrow` | `12` | `Typography.sizeEyebrow` | a mono eyebrow in the app (E1) | +| `size/glyph` | `17` | `Typography.sizeGlyph` | the +, × and ✓ | +| `size/label` | `12` | `Typography.sizeLabel` | the mono word labels on keys: 123, ABC, #+=, space, the return label | +| `size/legend` | `16` | `Typography.sizeLegend` | every other key | +| `size/letter` | `24` | `Typography.sizeLetter` | letter keys: the iPhone's (estimated from the l glyph, apple-geometry.json) | +| `size/popup` | `32` | `Typography.sizePopup` | the letter pop-up | +| `size/term` | `17` | `Typography.sizeTerm` | the key-term field | +| `size/title` | `34` | `Typography.sizeTitle` | the app's serif headline | +| `tracking/cta` | `1.4` | `Typography.trackingCta` | uppercase mono at 14: the brand's E2 tracking | +| `tracking/eyebrow` | `1.2` | `Typography.trackingEyebrow` | uppercase mono at 12: the brand's E1 tracking | +| `weight/glyph` | `medium` | `Typography.weightGlyph` | — | +| `weight/label` | `medium` | `Typography.weightLabel` | — | +| `weight/legend` | `medium` | `Typography.weightLegend` | — | +| `weight/letter` | `regular` | `Typography.weightLetter` | — | +| `weight/popup` | `regular` | `Typography.weightPopup` | — | +| `weight/term` | `regular` | `Typography.weightTerm` | — | +| `weight/voice-glyph` | `semibold` | `Typography.weightVoiceGlyph` | — | @@ -459,90 +453,104 @@ derivation. -| Token | Points | Swift | Use | -| ----------------------------- | --------- | ---------------------------------- | ---------------------------------------------------------------------------------------------- | -| `addterm/inset` | `6` | `Metrics.addtermInset` | the + from the panel's corner | -| `card/border` | `1` | `Metrics.cardBorder` | the card's hairline | -| `card/radius` | `16` | `Metrics.cardRadius` | the app's cards | -| `caret/height` | `20` | `Metrics.caretHeight` | — | -| `caret/lead` | `1` | `Metrics.caretLead` | the caret's gap from the text | -| `caret/radius` | `1` | `Metrics.caretRadius` | — | -| `caret/width` | `2` | `Metrics.caretWidth` | — | -| `gesture/swipe-min` | `24` | `Metrics.gestureSwipeMin` | the carousel gesture's minimum distance | -| `glyph/hit` | `32` | `Metrics.glyphHit` | the +, × and ✓ touch targets | -| `key/abc-width-402` | `43.333` | `Metrics.keyAbcWidth402` | 123 and the globe at 402 pt: the iPhone's | -| `key/gap` | `6` | `Metrics.keyGap` | between keys, the iPhone's | -| `key/height` | `43` | `Metrics.keyHeight` | every key: the iPhone's cap height (apple-geometry.json) | -| `key/letter-width-402` | `33.5` | `Metrics.keyLetterWidth402` | a letter key at 402 pt: (width − 2 × margin/side − 9 × key/gap) / 10 | -| `key/min-width` | `43.333` | `Metrics.keyMinWidth` | a key that isn't given a width: the iPhone's 123 key at 402 pt | -| `key/pad` | `4` | `Metrics.keyPad` | a legend's side padding on a min-width key | -| `key/radius` | `8` | `Metrics.keyRadius` | flat keys, one colour at this corner: the iPhone's (fitted 8.17) | -| `key/reference-width` | `402` | `Metrics.keyReferenceWidth` | the width the @402 tokens were measured at (iPhone 18 Pro); widths scale from it | -| `key/return-width-402` | `92.667` | `Metrics.keyReturnWidth402` | return at 402 pt: two 123 keys and a gap | -| `key/side-gap` | `13.667` | `Metrics.keySideGap` | shift and delete stand this far from the letters: the iPhone's | -| `key/side-width-402` | `45.583` | `Metrics.keySideWidth402` | shift and delete at 402 pt: what seven letters and the side gaps leave, halved (measured 45.5) | -| `key/space-width-402` | `191.667` | `Metrics.keySpaceWidth402` | space at 402 pt beside 123, the globe and return: what is left (measured 191.333) | -| `layout/full` | `270` | `Metrics.layoutFull` | margin/vertical + voicebar/height + 4 × key/height + 3 × row/gap + margin/bottom-keys | -| `layout/panel` | `216` | `Metrics.layoutPanel` | chosen: room for the 96 orb over one key row | -| `layout/slim` | `60` | `Metrics.layoutSlim` | 2 × margin/vertical + voicebar/height | -| `margin/bottom-keys` | `13` | `Metrics.marginBottomKeys` | under a bottom row of keys (the full keyboard, the panel): the iPhone's | -| `margin/side` | `6.5` | `Metrics.marginSide` | at the keyboard's sides: the iPhone's cap margin, (402 − 10 letters − 9 gaps) / 2 | -| `margin/vertical` | `8` | `Metrics.marginVertical` | the keyboard's top, and the slim bar's bottom | -| `opacity/dim` | `0.8` | `Metrics.opacityDim` | the orb when Blurt isn't ready | -| `opacity/dim-saturation` | `0.35` | `Metrics.opacityDimSaturation` | and its saturation | -| `opacity/disabled` | `0.4` | `Metrics.opacityDisabled` | the + without Full Access | -| `opacity/grain` | `0.5` | `Metrics.opacityGrain` | — | -| `opacity/home-dim-saturation` | `0.45` | `Metrics.opacityHomeDimSaturation` | the home hero's saturation when not listening | -| `opacity/legend` | `1` | `Metrics.opacityLegend` | key legends over the cap; below 1 they sit back | -| `opacity/legend-muted` | `0.5` | `Metrics.opacityLegendMuted` | the + at rest | -| `opacity/orb-light` | `0.3` | `Metrics.opacityOrbLight` | — | -| `opacity/placeholder` | `0.4` | `Metrics.opacityPlaceholder` | the field's placeholder | -| `opacity/popup-shadow` | `0.12` | `Metrics.opacityPopupShadow` | — | -| `opacity/press-brighten` | `0.15` | `Metrics.opacityPressBrighten` | a key lightens this much while pressed | -| `opacity/surface-grain` | `0.14` | `Metrics.opacitySurfaceGrain` | film grain over the whole keyboard surface: matte, the brand's texture | -| `opacity/surface-vignette` | `0` | `Metrics.opacitySurfaceVignette` | a soft darkening toward the surface's edges; 0 is none | -| `opacity/term-cancel` | `0.7` | `Metrics.opacityTermCancel` | the field's × | -| `orb/bar` | `40` | `Metrics.orbBar` | the orb in the voice bar | -| `orb/dissipate-blur` | `0.16` | `Metrics.orbDissipateBlur` | and blurs to this fraction of its size | -| `orb/dissipate-scale` | `1.25` | `Metrics.orbDissipateScale` | the orb swells to this while dissipating | -| `orb/home` | `112` | `Metrics.orbHome` | the orb on the home screen | -| `orb/light-reach` | `0.9` | `Metrics.orbLightReach` | the soft light's reach, as a fraction of the orb (was a fixed 110 pt, flat on a 40 pt orb) | -| `orb/light-x` | `0.3` | `Metrics.orbLightX` | the soft light's centre, as a fraction of the orb | -| `orb/light-y` | `0.22` | `Metrics.orbLightY` | — | -| `orb/panel` | `96` | `Metrics.orbPanel` | the orb in the panel | -| `panel/spacing` | `12` | `Metrics.panelSpacing` | between the panel's orb and its key row | -| `picker/preview-width` | `393` | `Metrics.pickerPreviewWidth` | the theme card draws the keyboard at this width | -| `picker/radius` | `10` | `Metrics.pickerRadius` | the theme card's preview corners | -| `picker/scale` | `0.42` | `Metrics.pickerScale` | then scales it to fit two across | -| `popup/extra-width` | `18` | `Metrics.popupExtraWidth` | the letter pop-up is the key width plus this | -| `popup/height` | `56` | `Metrics.popupHeight` | — | -| `popup/offset` | `58` | `Metrics.popupOffset` | the pop-up sits this far above the key | -| `popup/radius` | `10` | `Metrics.popupRadius` | — | -| `popup/shadow-radius` | `8` | `Metrics.popupShadowRadius` | the one thing that floats | -| `popup/shadow-y` | `2` | `Metrics.popupShadowY` | — | -| `press/scale` | `0.94` | `Metrics.pressScale` | the orb while pressed | -| `ring/active` | `2` | `Metrics.ringActive` | the ring while working or noticing; the home ring | -| `ring/still` | `1` | `Metrics.ringStill` | the ring at rest | -| `row/gap` | `11` | `Metrics.rowGap` | between rows, the iPhone's | -| `slim/spacing` | `8` | `Metrics.slimSpacing` | between the slim bar's keys | -| `surface/vignette-end` | `0.75` | `Metrics.surfaceVignetteEnd` | where it is full | -| `surface/vignette-start` | `0.3` | `Metrics.surfaceVignetteStart` | where the vignette begins, as a fraction of the keyboard's width | -| `term/gap` | `8` | `Metrics.termGap` | × · field · ✓ | -| `term/height` | `36` | `Metrics.termHeight` | the key-term field's capsule | -| `term/inset` | `2` | `Metrics.termInset` | the field row's side inset | -| `term/pad` | `14` | `Metrics.termPad` | the field's side padding | -| `voicebar/addterm-clearance` | `12` | `Metrics.voicebarAddtermClearance` | the wave stays this clear of the + at the trailing edge | -| `voicebar/height` | `44` | `Metrics.voicebarHeight` | the voice row, where the system puts its suggestion bar | -| `voicebar/note-gap` | `10` | `Metrics.voicebarNoteGap` | between the orb and the Full Access note | -| `wave/bar` | `2` | `Metrics.waveBar` | a wave bar's width | -| `wave/bar-height` | `24` | `Metrics.waveBarHeight` | — | -| `wave/bar-width` | `240` | `Metrics.waveBarWidth` | the wave in the voice bar, at most | -| `wave/gap` | `2` | `Metrics.waveGap` | between wave bars | -| `wave/home-height` | `44` | `Metrics.waveHomeHeight` | — | -| `wave/home-width` | `280` | `Metrics.waveHomeWidth` | — | -| `wave/panel-height` | `40` | `Metrics.wavePanelHeight` | — | -| `wave/panel-width` | `300` | `Metrics.wavePanelWidth` | — | -| `wordmark/height` | `22` | `Metrics.wordmarkHeight` | — | +| Token | Points | Swift | Use | +| ---------------------------- | --------- | ---------------------------------- | ---------------------------------------------------------------------------------------------- | +| `addterm/inset` | `6` | `Metrics.addtermInset` | the + from the panel's corner | +| `card/border` | `1` | `Metrics.cardBorder` | the card's hairline | +| `card/radius` | `16` | `Metrics.cardRadius` | the app's cards | +| `caret/height` | `20` | `Metrics.caretHeight` | — | +| `caret/lead` | `1` | `Metrics.caretLead` | the caret's gap from the text | +| `caret/radius` | `1` | `Metrics.caretRadius` | — | +| `caret/width` | `2` | `Metrics.caretWidth` | — | +| `gesture/swipe-min` | `24` | `Metrics.gestureSwipeMin` | the carousel gesture's minimum distance | +| `glyph/hit` | `32` | `Metrics.glyphHit` | the +, × and ✓ touch targets | +| `grille/bar-height` | `28` | `Metrics.grilleBarHeight` | — | +| `grille/bar-width` | `64` | `Metrics.grilleBarWidth` | the grille in the voice bar | +| `grille/dot` | `2` | `Metrics.grilleDot` | a dot's diameter | +| `grille/glint-arm` | `1.6` | `Metrics.grilleGlintArm` | the cross glint's vertical arm, as a fraction of the grille's height | +| `grille/glint-width` | `1` | `Metrics.grilleGlintWidth` | the glint's arms | +| `grille/home-height` | `108` | `Metrics.grilleHomeHeight` | — | +| `grille/home-width` | `240` | `Metrics.grilleHomeWidth` | the grille on the home screen | +| `grille/panel-height` | `72` | `Metrics.grillePanelHeight` | — | +| `grille/panel-width` | `160` | `Metrics.grillePanelWidth` | the grille in the panel | +| `grille/pitch` | `4` | `Metrics.grillePitch` | the dot lattice: one dot every | +| `grille/sheen-width` | `0.35` | `Metrics.grilleSheenWidth` | the sheen's band, as a fraction of the width | +| `key/abc-width-402` | `43.333` | `Metrics.keyAbcWidth402` | 123 and the globe at 402 pt: the iPhone's | +| `key/gap` | `6` | `Metrics.keyGap` | between keys, the iPhone's | +| `key/height` | `43` | `Metrics.keyHeight` | every key: the iPhone's cap height (apple-geometry.json) | +| `key/letter-width-402` | `33.5` | `Metrics.keyLetterWidth402` | a letter key at 402 pt: (width − 2 × margin/side − 9 × key/gap) / 10 | +| `key/min-width` | `43.333` | `Metrics.keyMinWidth` | a key that isn't given a width: the iPhone's 123 key at 402 pt | +| `key/pad` | `4` | `Metrics.keyPad` | a legend's side padding on a min-width key | +| `key/radius` | `8` | `Metrics.keyRadius` | flat keys, one colour at this corner: the iPhone's (fitted 8.17) | +| `key/reference-width` | `402` | `Metrics.keyReferenceWidth` | the width the @402 tokens were measured at (iPhone 18 Pro); widths scale from it | +| `key/return-width-402` | `92.667` | `Metrics.keyReturnWidth402` | return at 402 pt: two 123 keys and a gap | +| `key/side-gap` | `13.667` | `Metrics.keySideGap` | shift and delete stand this far from the letters: the iPhone's | +| `key/side-width-402` | `45.583` | `Metrics.keySideWidth402` | shift and delete at 402 pt: what seven letters and the side gaps leave, halved (measured 45.5) | +| `key/space-width-402` | `191.667` | `Metrics.keySpaceWidth402` | space at 402 pt beside 123, the globe and return: what is left (measured 191.333) | +| `layout/full` | `270` | `Metrics.layoutFull` | margin/vertical + voicebar/height + 4 × key/height + 3 × row/gap + margin/bottom-keys | +| `layout/panel` | `216` | `Metrics.layoutPanel` | chosen: room for the 96 orb over one key row | +| `layout/slim` | `60` | `Metrics.layoutSlim` | 2 × margin/vertical + voicebar/height | +| `margin/bottom-keys` | `13` | `Metrics.marginBottomKeys` | under a bottom row of keys (the full keyboard, the panel): the iPhone's | +| `margin/side` | `6.5` | `Metrics.marginSide` | at the keyboard's sides: the iPhone's cap margin, (402 − 10 letters − 9 gaps) / 2 | +| `margin/vertical` | `8` | `Metrics.marginVertical` | the keyboard's top, and the slim bar's bottom | +| `opacity/disabled` | `0.4` | `Metrics.opacityDisabled` | the + without Full Access | +| `opacity/glint` | `0.95` | `Metrics.opacityGlint` | the cross glint when the words land | +| `opacity/grille-rest` | `0.55` | `Metrics.opacityGrilleRest` | the dots at rest, over the key colour | +| `opacity/hairline` | `0.5` | `Metrics.opacityHairline` | — | +| `opacity/legend` | `1` | `Metrics.opacityLegend` | key legends over the cap; below 1 they sit back | +| `opacity/legend-muted` | `0.5` | `Metrics.opacityLegendMuted` | the + at rest | +| `opacity/off` | `0.45` | `Metrics.opacityOff` | the element when Blurt isn't ready: a tap opens the app | +| `opacity/placeholder` | `0.4` | `Metrics.opacityPlaceholder` | the field's placeholder | +| `opacity/popup-shadow` | `0.12` | `Metrics.opacityPopupShadow` | — | +| `opacity/press-brighten` | `0.15` | `Metrics.opacityPressBrighten` | a key lightens this much while pressed | +| `opacity/sheen` | `0.22` | `Metrics.opacitySheen` | the light passing over the element at rest: chrome catching light | +| `opacity/surface-grain` | `0.14` | `Metrics.opacitySurfaceGrain` | film grain over the whole keyboard surface: matte, the brand's texture | +| `opacity/surface-vignette` | `0` | `Metrics.opacitySurfaceVignette` | a soft darkening toward the surface's edges; 0 is none | +| `opacity/term-cancel` | `0.7` | `Metrics.opacityTermCancel` | the field's × | +| `panel/spacing` | `12` | `Metrics.panelSpacing` | between the panel's orb and its key row | +| `picker/preview-width` | `393` | `Metrics.pickerPreviewWidth` | the theme card draws the keyboard at this width | +| `picker/radius` | `10` | `Metrics.pickerRadius` | the theme card's preview corners | +| `picker/scale` | `0.42` | `Metrics.pickerScale` | then scales it to fit two across | +| `popup/extra-width` | `18` | `Metrics.popupExtraWidth` | the letter pop-up is the key width plus this | +| `popup/height` | `56` | `Metrics.popupHeight` | — | +| `popup/offset` | `58` | `Metrics.popupOffset` | the pop-up sits this far above the key | +| `popup/radius` | `10` | `Metrics.popupRadius` | — | +| `popup/shadow-radius` | `8` | `Metrics.popupShadowRadius` | the one thing that floats | +| `popup/shadow-y` | `2` | `Metrics.popupShadowY` | — | +| `radius/button` | `4` | `Metrics.radiusButton` | the brand's buttons and the grille: rectangular, never a pill | +| `radius/card` | `12` | `Metrics.radiusCard` | the brand's cards | +| `radius/hero` | `16` | `Metrics.radiusHero` | the brand's featured cards | +| `radius/input` | `8` | `Metrics.radiusInput` | the brand's inputs: the key-term field | +| `ribs/rest-height` | `16` | `Metrics.ribsRestHeight` | — | +| `ribs/rest-width` | `40` | `Metrics.ribsRestWidth` | the ribs asleep: the wave's own bars at rest | +| `row/gap` | `11` | `Metrics.rowGap` | between rows, the iPhone's | +| `slim/spacing` | `8` | `Metrics.slimSpacing` | between the slim bar's keys | +| `streak/arm` | `1.4` | `Metrics.streakArm` | the landing flash's vertical arm, as a fraction of the box's height | +| `streak/height` | `2` | `Metrics.streakHeight` | the light streak while recording | +| `streak/line` | `1` | `Metrics.streakLine` | the hairline at rest | +| `streak/point` | `4` | `Metrics.streakPoint` | the bright point at the centre | +| `surface/vignette-end` | `0.75` | `Metrics.surfaceVignetteEnd` | where it is full | +| `surface/vignette-start` | `0.3` | `Metrics.surfaceVignetteStart` | where the vignette begins, as a fraction of the keyboard's width | +| `term/gap` | `8` | `Metrics.termGap` | × · field · ✓ | +| `term/height` | `36` | `Metrics.termHeight` | the key-term field's capsule | +| `term/inset` | `2` | `Metrics.termInset` | the field row's side inset | +| `term/pad` | `14` | `Metrics.termPad` | the field's side padding | +| `voice/bar-height` | `32` | `Metrics.voiceBarHeight` | — | +| `voice/bar-width` | `240` | `Metrics.voiceBarWidth` | the voice element's box in the voice bar: what the wave gets | +| `voice/home-height` | `112` | `Metrics.voiceHomeHeight` | — | +| `voice/home-width` | `280` | `Metrics.voiceHomeWidth` | the box on the home screen | +| `voice/panel-height` | `88` | `Metrics.voicePanelHeight` | — | +| `voice/panel-width` | `300` | `Metrics.voicePanelWidth` | the box in the panel | +| `voice/press-scale` | `0.94` | `Metrics.voicePressScale` | the element while pressed | +| `voicebar/addterm-clearance` | `12` | `Metrics.voicebarAddtermClearance` | the wave stays this clear of the + at the trailing edge | +| `voicebar/height` | `44` | `Metrics.voicebarHeight` | the voice row, where the system puts its suggestion bar | +| `voicebar/note-gap` | `10` | `Metrics.voicebarNoteGap` | between the orb and the Full Access note | +| `wave/bar` | `2` | `Metrics.waveBar` | a wave bar's width | +| `wave/bar-height` | `24` | `Metrics.waveBarHeight` | — | +| `wave/gap` | `2` | `Metrics.waveGap` | between wave bars | +| `wave/home-height` | `44` | `Metrics.waveHomeHeight` | — | +| `wave/panel-height` | `40` | `Metrics.wavePanelHeight` | — | +| `wordmark/height` | `22` | `Metrics.wordmarkHeight` | — | @@ -554,18 +562,16 @@ Motion, in seconds. Nothing springs or snaps; only the press answers at once. | ---------------- | --------------- | ---------------------- | ------------------------------------------------------------- | | `caret` | `0.5` | `Motion.caret` | the caret's blink | | `colour` | `0.2` | `Motion.colour` | a colour or fill changing state: the brand's transition | -| `drop` | `2.4` | `Motion.drop` | the violet drop is gone by | -| `drop-hold` | `0.9` | `Motion.dropHold` | and held to | -| `drop-rise` | `0.5` | `Motion.dropRise` | the drop is up in | -| `drop-spread` | `1` | `Motion.dropSpread` | the bloom reaches its full spread in | | `ease/signature` | `0.22,1,0.36,1` | `Motion.easeSignature` | the house curve for everything that moves; nothing springs | | `flip` | `0.25` | `Motion.flip` | the panel's carousel | +| `glint-life` | `0.5` | `Motion.glintLife` | a facet's flash while recording | | `height-change` | `0.25` | `Motion.heightChange` | the keyboard resizing | | `key-press` | `0.08` | `Motion.keyPress` | a key lighting | | `landing` | `0.6` | `Motion.landing` | the glint when the words land | -| `mood` | `0.8` | `Motion.mood` | the orb's colour moving between moods | | `press` | `0.1` | `Motion.press` | the orb's press; the one thing that answers at once | | `ring-period` | `1.6` | `Motion.ringPeriod` | one turn of the ring, the Mac's cadence | +| `sheen` | `4` | `Motion.sheen` | one pass of the light over the element at rest | +| `sheen-working` | `1.6` | `Motion.sheenWorking` | and while something is happening: the ring's cadence | | `state-fade` | `0.5` | `Motion.stateFade` | every other change on the key: the ring, a glyph, the dimming | | `term-swap` | `0.4` | `Motion.termSwap` | the voice bar becoming the field | | `wave-fade` | `0.7` | `Motion.waveFade` | the orb and the wave crossing, either way | diff --git a/App/BlurtiOS/Design/figma/tokens.js b/App/BlurtiOS/Design/figma/tokens.js index 42174757..0265cbd0 100644 --- a/App/BlurtiOS/Design/figma/tokens.js +++ b/App/BlurtiOS/Design/figma/tokens.js @@ -70,9 +70,6 @@ Keyboard|kb/key-modifier|COLOR|#26231E|Themes:dark/key-modifier|FRAME_FILL,SHAPE Keyboard|kb/legend|COLOR|#F5F3EB|Themes:dark/legend|TEXT_FILL|DesignTokens.Keyboard.kbLegend|key legends and bare glyphs Keyboard|kb/legend-secondary|COLOR|#A5A4A2|Themes:dark/legend-secondary|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.kbLegendSecondary|the mono word labels (123, ABC, return, space) and the + at rest Keyboard|kb/notice-error|COLOR|#E67F36|Brand:orange|STROKE_COLOR|DesignTokens.Keyboard.kbNoticeError|the solid ring and glyph for an error -Keyboard|kb/notice-ok|COLOR|#67AD82|Brand:green/400|STROKE_COLOR|DesignTokens.Keyboard.kbNoticeOk|the solid ring for pasted and copied -Keyboard|kb/orb-ring-end|COLOR|#FFFFFF|Brand:white|STROKE_COLOR|DesignTokens.Keyboard.kbOrbRingEnd|the sweeping ring's gradient, bottom-trailing -Keyboard|kb/orb-ring-start|COLOR|#01762F|Brand:green/700|STROKE_COLOR|DesignTokens.Keyboard.kbOrbRingStart|the sweeping ring's gradient, top-leading Keyboard|kb/popup|COLOR|#33302A|Themes:dark/popup|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.kbPopup|the letter pop-up Keyboard|kb/signal|COLOR|#67AD82|Themes:dark/signal|SHAPE_FILL,TEXT_FILL|DesignTokens.Keyboard.kbSignal|the wave, the caret, the saved check Keyboard|kb/surface|COLOR|#1D1B16|Themes:dark/surface|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.kbSurface|the design face's surface (Figma binds to kb/*; Swift reads the palette) @@ -85,6 +82,17 @@ Metrics|caret/radius|FLOAT|1||CORNER_RADIUS|DesignTokens.Metrics.caretRadius| Metrics|caret/width|FLOAT|2||STROKE_FLOAT,WIDTH_HEIGHT|DesignTokens.Metrics.caretWidth| Metrics|gesture/swipe-min|FLOAT|24|||DesignTokens.Metrics.gestureSwipeMin|the carousel gesture's minimum distance Metrics|glyph/hit|FLOAT|32||WIDTH_HEIGHT|DesignTokens.Metrics.glyphHit|the +, × and ✓ touch targets +Metrics|grille/bar-height|FLOAT|28||WIDTH_HEIGHT|DesignTokens.Metrics.grilleBarHeight| +Metrics|grille/bar-width|FLOAT|64||WIDTH_HEIGHT|DesignTokens.Metrics.grilleBarWidth|the grille in the voice bar +Metrics|grille/dot|FLOAT|2||WIDTH_HEIGHT|DesignTokens.Metrics.grilleDot|a dot's diameter +Metrics|grille/glint-arm|FLOAT|1.6||WIDTH_HEIGHT|DesignTokens.Metrics.grilleGlintArm|the cross glint's vertical arm, as a fraction of the grille's height +Metrics|grille/glint-width|FLOAT|1||WIDTH_HEIGHT|DesignTokens.Metrics.grilleGlintWidth|the glint's arms +Metrics|grille/home-height|FLOAT|108||WIDTH_HEIGHT|DesignTokens.Metrics.grilleHomeHeight| +Metrics|grille/home-width|FLOAT|240||WIDTH_HEIGHT|DesignTokens.Metrics.grilleHomeWidth|the grille on the home screen +Metrics|grille/panel-height|FLOAT|72||WIDTH_HEIGHT|DesignTokens.Metrics.grillePanelHeight| +Metrics|grille/panel-width|FLOAT|160||WIDTH_HEIGHT|DesignTokens.Metrics.grillePanelWidth|the grille in the panel +Metrics|grille/pitch|FLOAT|4||WIDTH_HEIGHT|DesignTokens.Metrics.grillePitch|the dot lattice: one dot every +Metrics|grille/sheen-width|FLOAT|0.35||WIDTH_HEIGHT|DesignTokens.Metrics.grilleSheenWidth|the sheen's band, as a fraction of the width Metrics|key/abc-width-402|FLOAT|43.333||WIDTH_HEIGHT|DesignTokens.Metrics.keyAbcWidth402|123 and the globe at 402 pt: the iPhone's Metrics|key/gap|FLOAT|6||GAP|DesignTokens.Metrics.keyGap|between keys, the iPhone's Metrics|key/height|FLOAT|43||WIDTH_HEIGHT|DesignTokens.Metrics.keyHeight|every key: the iPhone's cap height (apple-geometry.json) @@ -103,28 +111,20 @@ Metrics|layout/slim|FLOAT|60||WIDTH_HEIGHT|DesignTokens.Metrics.layoutSlim|2 × Metrics|margin/bottom-keys|FLOAT|13||WIDTH_HEIGHT|DesignTokens.Metrics.marginBottomKeys|under a bottom row of keys (the full keyboard, the panel): the iPhone's Metrics|margin/side|FLOAT|6.5||WIDTH_HEIGHT|DesignTokens.Metrics.marginSide|at the keyboard's sides: the iPhone's cap margin, (402 − 10 letters − 9 gaps) / 2 Metrics|margin/vertical|FLOAT|8||WIDTH_HEIGHT|DesignTokens.Metrics.marginVertical|the keyboard's top, and the slim bar's bottom -Metrics|opacity/dim|FLOAT|0.8||OPACITY|DesignTokens.Metrics.opacityDim|the orb when Blurt isn't ready -Metrics|opacity/dim-saturation|FLOAT|0.35||OPACITY|DesignTokens.Metrics.opacityDimSaturation|and its saturation Metrics|opacity/disabled|FLOAT|0.4||OPACITY|DesignTokens.Metrics.opacityDisabled|the + without Full Access -Metrics|opacity/grain|FLOAT|0.5||OPACITY|DesignTokens.Metrics.opacityGrain| -Metrics|opacity/home-dim-saturation|FLOAT|0.45||OPACITY|DesignTokens.Metrics.opacityHomeDimSaturation|the home hero's saturation when not listening +Metrics|opacity/glint|FLOAT|0.95||OPACITY|DesignTokens.Metrics.opacityGlint|the cross glint when the words land +Metrics|opacity/grille-rest|FLOAT|0.55||OPACITY|DesignTokens.Metrics.opacityGrilleRest|the dots at rest, over the key colour +Metrics|opacity/hairline|FLOAT|0.5||OPACITY|DesignTokens.Metrics.opacityHairline| Metrics|opacity/legend|FLOAT|1||OPACITY|DesignTokens.Metrics.opacityLegend|key legends over the cap; below 1 they sit back Metrics|opacity/legend-muted|FLOAT|0.5||OPACITY|DesignTokens.Metrics.opacityLegendMuted|the + at rest -Metrics|opacity/orb-light|FLOAT|0.3||OPACITY|DesignTokens.Metrics.opacityOrbLight| +Metrics|opacity/off|FLOAT|0.45||OPACITY|DesignTokens.Metrics.opacityOff|the element when Blurt isn't ready: a tap opens the app Metrics|opacity/placeholder|FLOAT|0.4||OPACITY|DesignTokens.Metrics.opacityPlaceholder|the field's placeholder Metrics|opacity/popup-shadow|FLOAT|0.12||OPACITY|DesignTokens.Metrics.opacityPopupShadow| Metrics|opacity/press-brighten|FLOAT|0.15||OPACITY|DesignTokens.Metrics.opacityPressBrighten|a key lightens this much while pressed +Metrics|opacity/sheen|FLOAT|0.22||OPACITY|DesignTokens.Metrics.opacitySheen|the light passing over the element at rest: chrome catching light Metrics|opacity/surface-grain|FLOAT|0.14||OPACITY|DesignTokens.Metrics.opacitySurfaceGrain|film grain over the whole keyboard surface: matte, the brand's texture Metrics|opacity/surface-vignette|FLOAT|0||OPACITY|DesignTokens.Metrics.opacitySurfaceVignette|a soft darkening toward the surface's edges; 0 is none Metrics|opacity/term-cancel|FLOAT|0.7||OPACITY|DesignTokens.Metrics.opacityTermCancel|the field's × -Metrics|orb/bar|FLOAT|40||WIDTH_HEIGHT|DesignTokens.Metrics.orbBar|the orb in the voice bar -Metrics|orb/dissipate-blur|FLOAT|0.16|||DesignTokens.Metrics.orbDissipateBlur|and blurs to this fraction of its size -Metrics|orb/dissipate-scale|FLOAT|1.25|||DesignTokens.Metrics.orbDissipateScale|the orb swells to this while dissipating -Metrics|orb/home|FLOAT|112||WIDTH_HEIGHT|DesignTokens.Metrics.orbHome|the orb on the home screen -Metrics|orb/light-reach|FLOAT|0.9|||DesignTokens.Metrics.orbLightReach|the soft light's reach, as a fraction of the orb (was a fixed 110 pt, flat on a 40 pt orb) -Metrics|orb/light-x|FLOAT|0.3|||DesignTokens.Metrics.orbLightX|the soft light's centre, as a fraction of the orb -Metrics|orb/light-y|FLOAT|0.22|||DesignTokens.Metrics.orbLightY| -Metrics|orb/panel|FLOAT|96||WIDTH_HEIGHT|DesignTokens.Metrics.orbPanel|the orb in the panel Metrics|panel/spacing|FLOAT|12||GAP|DesignTokens.Metrics.panelSpacing|between the panel's orb and its key row Metrics|picker/preview-width|FLOAT|393||WIDTH_HEIGHT|DesignTokens.Metrics.pickerPreviewWidth|the theme card draws the keyboard at this width Metrics|picker/radius|FLOAT|10||CORNER_RADIUS|DesignTokens.Metrics.pickerRadius|the theme card's preview corners @@ -135,30 +135,41 @@ Metrics|popup/offset|FLOAT|58||WIDTH_HEIGHT|DesignTokens.Metrics.popupOffset|the Metrics|popup/radius|FLOAT|10||CORNER_RADIUS|DesignTokens.Metrics.popupRadius| Metrics|popup/shadow-radius|FLOAT|8||WIDTH_HEIGHT|DesignTokens.Metrics.popupShadowRadius|the one thing that floats Metrics|popup/shadow-y|FLOAT|2||WIDTH_HEIGHT|DesignTokens.Metrics.popupShadowY| -Metrics|press/scale|FLOAT|0.94|||DesignTokens.Metrics.pressScale|the orb while pressed -Metrics|ring/active|FLOAT|2||STROKE_FLOAT,WIDTH_HEIGHT|DesignTokens.Metrics.ringActive|the ring while working or noticing; the home ring -Metrics|ring/still|FLOAT|1||STROKE_FLOAT,WIDTH_HEIGHT|DesignTokens.Metrics.ringStill|the ring at rest +Metrics|radius/button|FLOAT|4||WIDTH_HEIGHT|DesignTokens.Metrics.radiusButton|the brand's buttons and the grille: rectangular, never a pill +Metrics|radius/card|FLOAT|12||WIDTH_HEIGHT|DesignTokens.Metrics.radiusCard|the brand's cards +Metrics|radius/hero|FLOAT|16||WIDTH_HEIGHT|DesignTokens.Metrics.radiusHero|the brand's featured cards +Metrics|radius/input|FLOAT|8||WIDTH_HEIGHT|DesignTokens.Metrics.radiusInput|the brand's inputs: the key-term field +Metrics|ribs/rest-height|FLOAT|16||WIDTH_HEIGHT|DesignTokens.Metrics.ribsRestHeight| +Metrics|ribs/rest-width|FLOAT|40||WIDTH_HEIGHT|DesignTokens.Metrics.ribsRestWidth|the ribs asleep: the wave's own bars at rest Metrics|row/gap|FLOAT|11||GAP|DesignTokens.Metrics.rowGap|between rows, the iPhone's Metrics|slim/spacing|FLOAT|8||GAP|DesignTokens.Metrics.slimSpacing|between the slim bar's keys +Metrics|streak/arm|FLOAT|1.4||WIDTH_HEIGHT|DesignTokens.Metrics.streakArm|the landing flash's vertical arm, as a fraction of the box's height +Metrics|streak/height|FLOAT|2||WIDTH_HEIGHT|DesignTokens.Metrics.streakHeight|the light streak while recording +Metrics|streak/line|FLOAT|1||WIDTH_HEIGHT|DesignTokens.Metrics.streakLine|the hairline at rest +Metrics|streak/point|FLOAT|4||WIDTH_HEIGHT|DesignTokens.Metrics.streakPoint|the bright point at the centre Metrics|surface/vignette-end|FLOAT|0.75||WIDTH_HEIGHT|DesignTokens.Metrics.surfaceVignetteEnd|where it is full Metrics|surface/vignette-start|FLOAT|0.3||WIDTH_HEIGHT|DesignTokens.Metrics.surfaceVignetteStart|where the vignette begins, as a fraction of the keyboard's width Metrics|term/gap|FLOAT|8||GAP|DesignTokens.Metrics.termGap|× · field · ✓ Metrics|term/height|FLOAT|36||WIDTH_HEIGHT|DesignTokens.Metrics.termHeight|the key-term field's capsule Metrics|term/inset|FLOAT|2||GAP|DesignTokens.Metrics.termInset|the field row's side inset Metrics|term/pad|FLOAT|14||GAP|DesignTokens.Metrics.termPad|the field's side padding +Metrics|voice/bar-height|FLOAT|32||WIDTH_HEIGHT|DesignTokens.Metrics.voiceBarHeight| +Metrics|voice/bar-width|FLOAT|240||WIDTH_HEIGHT|DesignTokens.Metrics.voiceBarWidth|the voice element's box in the voice bar: what the wave gets +Metrics|voice/home-height|FLOAT|112||WIDTH_HEIGHT|DesignTokens.Metrics.voiceHomeHeight| +Metrics|voice/home-width|FLOAT|280||WIDTH_HEIGHT|DesignTokens.Metrics.voiceHomeWidth|the box on the home screen +Metrics|voice/panel-height|FLOAT|88||WIDTH_HEIGHT|DesignTokens.Metrics.voicePanelHeight| +Metrics|voice/panel-width|FLOAT|300||WIDTH_HEIGHT|DesignTokens.Metrics.voicePanelWidth|the box in the panel +Metrics|voice/press-scale|FLOAT|0.94||WIDTH_HEIGHT|DesignTokens.Metrics.voicePressScale|the element while pressed Metrics|voicebar/addterm-clearance|FLOAT|12||GAP|DesignTokens.Metrics.voicebarAddtermClearance|the wave stays this clear of the + at the trailing edge Metrics|voicebar/height|FLOAT|44||WIDTH_HEIGHT|DesignTokens.Metrics.voicebarHeight|the voice row, where the system puts its suggestion bar Metrics|voicebar/note-gap|FLOAT|10||GAP|DesignTokens.Metrics.voicebarNoteGap|between the orb and the Full Access note Metrics|wave/bar|FLOAT|2||STROKE_FLOAT,WIDTH_HEIGHT|DesignTokens.Metrics.waveBar|a wave bar's width Metrics|wave/bar-height|FLOAT|24||WIDTH_HEIGHT|DesignTokens.Metrics.waveBarHeight| -Metrics|wave/bar-width|FLOAT|240||WIDTH_HEIGHT|DesignTokens.Metrics.waveBarWidth|the wave in the voice bar, at most Metrics|wave/gap|FLOAT|2||GAP|DesignTokens.Metrics.waveGap|between wave bars Metrics|wave/home-height|FLOAT|44||WIDTH_HEIGHT|DesignTokens.Metrics.waveHomeHeight| -Metrics|wave/home-width|FLOAT|280||WIDTH_HEIGHT|DesignTokens.Metrics.waveHomeWidth| Metrics|wave/panel-height|FLOAT|40||WIDTH_HEIGHT|DesignTokens.Metrics.wavePanelHeight| -Metrics|wave/panel-width|FLOAT|300||WIDTH_HEIGHT|DesignTokens.Metrics.wavePanelWidth| Metrics|wordmark/height|FLOAT|22||WIDTH_HEIGHT|DesignTokens.Metrics.wordmarkHeight| -Typography|ratio/orb-glyph|FLOAT|0.34|||DesignTokens.Typography.ratioOrbGlyph|the clipboard and exclamation glyphs, as a fraction of the orb +Typography|ratio/voice-glyph|FLOAT|0.34|||DesignTokens.Typography.ratioVoiceGlyph|the clipboard and exclamation glyphs, as a fraction of the voice element's height Typography|size/body|FLOAT|16||FONT_SIZE|DesignTokens.Typography.sizeBody|the app's body text Typography|size/caption|FLOAT|14||FONT_SIZE|DesignTokens.Typography.sizeCaption|the app's small text Typography|size/cta|FLOAT|14||FONT_SIZE|DesignTokens.Typography.sizeCta|a mono button label in the app (E2) @@ -176,23 +187,21 @@ Typography|weight/glyph|STRING|medium||FONT_STYLE|DesignTokens.Typography.weight Typography|weight/label|STRING|medium||FONT_STYLE|DesignTokens.Typography.weightLabel| Typography|weight/legend|STRING|medium||FONT_STYLE|DesignTokens.Typography.weightLegend| Typography|weight/letter|STRING|regular||FONT_STYLE|DesignTokens.Typography.weightLetter| -Typography|weight/orb-glyph|STRING|semibold||FONT_STYLE|DesignTokens.Typography.weightOrbGlyph| Typography|weight/popup|STRING|regular||FONT_STYLE|DesignTokens.Typography.weightPopup| Typography|weight/term|STRING|regular||FONT_STYLE|DesignTokens.Typography.weightTerm| +Typography|weight/voice-glyph|STRING|semibold||FONT_STYLE|DesignTokens.Typography.weightVoiceGlyph| Motion|caret|FLOAT|0.5|||DesignTokens.Motion.caret|the caret's blink Motion|colour|FLOAT|0.2|||DesignTokens.Motion.colour|a colour or fill changing state: the brand's transition -Motion|drop|FLOAT|2.4|||DesignTokens.Motion.drop|the violet drop is gone by -Motion|drop-hold|FLOAT|0.9|||DesignTokens.Motion.dropHold|and held to -Motion|drop-rise|FLOAT|0.5|||DesignTokens.Motion.dropRise|the drop is up in -Motion|drop-spread|FLOAT|1|||DesignTokens.Motion.dropSpread|the bloom reaches its full spread in Motion|ease/signature|STRING|0.22,1,0.36,1|||DesignTokens.Motion.easeSignature|the house curve for everything that moves; nothing springs Motion|flip|FLOAT|0.25|||DesignTokens.Motion.flip|the panel's carousel +Motion|glint-life|FLOAT|0.5|||DesignTokens.Motion.glintLife|a facet's flash while recording Motion|height-change|FLOAT|0.25|||DesignTokens.Motion.heightChange|the keyboard resizing Motion|key-press|FLOAT|0.08|||DesignTokens.Motion.keyPress|a key lighting Motion|landing|FLOAT|0.6|||DesignTokens.Motion.landing|the glint when the words land -Motion|mood|FLOAT|0.8|||DesignTokens.Motion.mood|the orb's colour moving between moods Motion|press|FLOAT|0.1|||DesignTokens.Motion.press|the orb's press; the one thing that answers at once Motion|ring-period|FLOAT|1.6|||DesignTokens.Motion.ringPeriod|one turn of the ring, the Mac's cadence +Motion|sheen|FLOAT|4|||DesignTokens.Motion.sheen|one pass of the light over the element at rest +Motion|sheen-working|FLOAT|1.6|||DesignTokens.Motion.sheenWorking|and while something is happening: the ring's cadence Motion|state-fade|FLOAT|0.5|||DesignTokens.Motion.stateFade|every other change on the key: the ring, a glyph, the dimming Motion|term-swap|FLOAT|0.4|||DesignTokens.Motion.termSwap|the voice bar becoming the field Motion|wave-fade|FLOAT|0.7|||DesignTokens.Motion.waveFade|the orb and the wave crossing, either way @@ -204,7 +213,5 @@ Fonts|heading/regular|STRING|OceanicText-Regular|||DesignTokens.Fonts.headingReg Fonts|mono/family|STRING|Modern Gothic Mono||FONT_FAMILY|DesignTokens.Fonts.monoFamily|eyebrows, CTAs, the keyboard's word labels Fonts|mono/light|STRING|ModernGothicMono-Light|||DesignTokens.Fonts.monoLight| Fonts|mono/medium|STRING|ModernGothicMono-Medium|||DesignTokens.Fonts.monoMedium| -Fonts|mono/regular|STRING|ModernGothicMono-Regular|||DesignTokens.Fonts.monoRegular| -GRADIENT|orb|bottom|top|#D7D3F4@0,#B0A7E9@0.0673,#67AD82@0.1442,#01762F@0.3029,#3923C7@0.5962,#887BDD@0.75,#D7D3F4@0.8942,#FFFFFF@1|the Mac orb's fill, the design's own stops (App elements/Recording.svg), swept bottom to top -GRADIENT|orb-ring|topLeading|bottomTrailing|#01762F@0,#FFFFFF@1|the ring round the orb: green into white, corner to corner; spun while something is happening`; +Fonts|mono/regular|STRING|ModernGothicMono-Regular|||DesignTokens.Fonts.monoRegular|`; const GROUPS = ["Brand", "Themes", "Keyboard", "Metrics", "Typography", "Motion", "Fonts"]; diff --git a/App/BlurtiOS/Design/tokens.json b/App/BlurtiOS/Design/tokens.json index eb8cc70b..d5ff8c9d 100644 --- a/App/BlurtiOS/Design/tokens.json +++ b/App/BlurtiOS/Design/tokens.json @@ -184,10 +184,6 @@ "value": "{themes.dark/popup}", "use": "the letter pop-up" }, - "kb/notice-ok": { - "value": "{brand.green/400}", - "use": "the solid ring for pasted and copied" - }, "kb/notice-error": { "value": "{brand.orange}", "use": "the solid ring and glyph for an error" @@ -200,14 +196,6 @@ "value": "{brand.orange}", "use": "the one line of words the keyboard ever shows" }, - "kb/orb-ring-start": { - "value": "{brand.green/700}", - "use": "the sweeping ring's gradient, top-leading" - }, - "kb/orb-ring-end": { - "value": "{brand.white}", - "use": "the sweeping ring's gradient, bottom-trailing" - }, "app/accent-light": { "value": "{brand.green/700}", "use": "the catalog's AccentColor in light" @@ -245,62 +233,7 @@ "use": "the field's hairline" } }, - "gradients": { - "orb": { - "use": "the Mac orb's fill, the design's own stops (App elements/Recording.svg), swept bottom to top", - "start": "bottom", - "end": "top", - "stops": [ - { - "color": "{brand.violet/lavender}", - "location": 0 - }, - { - "color": "{brand.violet/periwinkle}", - "location": 0.0673 - }, - { - "color": "{brand.green/400}", - "location": 0.1442 - }, - { - "color": "{brand.green/700}", - "location": 0.3029 - }, - { - "color": "{brand.cobolt}", - "location": 0.5962 - }, - { - "color": "{brand.violet/iris}", - "location": 0.75 - }, - { - "color": "{brand.violet/lavender}", - "location": 0.8942 - }, - { - "color": "{brand.white}", - "location": 1 - } - ] - }, - "orb-ring": { - "use": "the ring round the orb: green into white, corner to corner; spun while something is happening", - "start": "topLeading", - "end": "bottomTrailing", - "stops": [ - { - "color": "{brand.green/700}", - "location": 0 - }, - { - "color": "{brand.white}", - "location": 1 - } - ] - } - }, + "gradients": {}, "metrics": { "key/height": { "value": 43, @@ -358,34 +291,12 @@ "value": 12, "use": "the wave stays this clear of the + at the trailing edge" }, - "orb/bar": { - "value": 40, - "use": "the orb in the voice bar" - }, - "orb/panel": { - "value": 96, - "use": "the orb in the panel" - }, - "orb/home": { - "value": 112, - "use": "the orb on the home screen" - }, - "wave/bar-width": { - "value": 240, - "use": "the wave in the voice bar, at most" - }, "wave/bar-height": { "value": 24 }, - "wave/panel-width": { - "value": 300 - }, "wave/panel-height": { "value": 40 }, - "wave/home-width": { - "value": 280 - }, "wave/home-height": { "value": 44 }, @@ -397,14 +308,6 @@ "value": 2, "use": "between wave bars" }, - "ring/still": { - "value": 1, - "use": "the ring at rest" - }, - "ring/active": { - "value": 2, - "use": "the ring while working or noticing; the home ring" - }, "popup/extra-width": { "value": 18, "use": "the letter pop-up is the key width plus this" @@ -506,37 +409,6 @@ "value": 270, "use": "margin/vertical + voicebar/height + 4 × key/height + 3 × row/gap + margin/bottom-keys" }, - "orb/light-x": { - "value": 0.3, - "use": "the soft light's centre, as a fraction of the orb" - }, - "orb/light-y": { - "value": 0.22 - }, - "orb/light-reach": { - "value": 0.9, - "use": "the soft light's reach, as a fraction of the orb (was a fixed 110 pt, flat on a 40 pt orb)" - }, - "orb/dissipate-scale": { - "value": 1.25, - "use": "the orb swells to this while dissipating" - }, - "orb/dissipate-blur": { - "value": 0.16, - "use": "and blurs to this fraction of its size" - }, - "opacity/dim": { - "value": 0.8, - "use": "the orb when Blurt isn't ready" - }, - "opacity/dim-saturation": { - "value": 0.35, - "use": "and its saturation" - }, - "opacity/home-dim-saturation": { - "value": 0.45, - "use": "the home hero's saturation when not listening" - }, "opacity/legend-muted": { "value": 0.5, "use": "the + at rest" @@ -564,12 +436,6 @@ "opacity/popup-shadow": { "value": 0.12 }, - "opacity/orb-light": { - "value": 0.3 - }, - "opacity/grain": { - "value": 0.5 - }, "opacity/surface-grain": { "value": 0.14, "use": "film grain over the whole keyboard surface: matte, the brand's texture" @@ -586,10 +452,6 @@ "value": 0.75, "use": "where it is full" }, - "press/scale": { - "value": 0.94, - "use": "the orb while pressed" - }, "gesture/swipe-min": { "value": 24, "use": "the carousel gesture's minimum distance" @@ -613,6 +475,130 @@ "key/space-width-402": { "value": 191.667, "use": "space at 402 pt beside 123, the globe and return: what is left (measured 191.333)" + }, + "voice/bar-width": { + "value": 240, + "use": "the voice element's box in the voice bar: what the wave gets" + }, + "voice/bar-height": { + "value": 32 + }, + "voice/panel-width": { + "value": 300, + "use": "the box in the panel" + }, + "voice/panel-height": { + "value": 88 + }, + "voice/home-width": { + "value": 280, + "use": "the box on the home screen" + }, + "voice/home-height": { + "value": 112 + }, + "voice/press-scale": { + "value": 0.94, + "use": "the element while pressed" + }, + "opacity/off": { + "value": 0.45, + "use": "the element when Blurt isn't ready: a tap opens the app" + }, + "opacity/sheen": { + "value": 0.22, + "use": "the light passing over the element at rest: chrome catching light" + }, + "opacity/glint": { + "value": 0.95, + "use": "the cross glint when the words land" + }, + "radius/button": { + "value": 4, + "use": "the brand's buttons and the grille: rectangular, never a pill" + }, + "radius/input": { + "value": 8, + "use": "the brand's inputs: the key-term field" + }, + "radius/card": { + "value": 12, + "use": "the brand's cards" + }, + "radius/hero": { + "value": 16, + "use": "the brand's featured cards" + }, + "grille/pitch": { + "value": 4, + "use": "the dot lattice: one dot every" + }, + "grille/dot": { + "value": 2, + "use": "a dot's diameter" + }, + "grille/bar-width": { + "value": 64, + "use": "the grille in the voice bar" + }, + "grille/bar-height": { + "value": 28 + }, + "grille/panel-width": { + "value": 160, + "use": "the grille in the panel" + }, + "grille/panel-height": { + "value": 72 + }, + "grille/home-width": { + "value": 240, + "use": "the grille on the home screen" + }, + "grille/home-height": { + "value": 108 + }, + "opacity/grille-rest": { + "value": 0.55, + "use": "the dots at rest, over the key colour" + }, + "grille/glint-arm": { + "value": 1.6, + "use": "the cross glint's vertical arm, as a fraction of the grille's height" + }, + "grille/glint-width": { + "value": 1, + "use": "the glint's arms" + }, + "grille/sheen-width": { + "value": 0.35, + "use": "the sheen's band, as a fraction of the width" + }, + "ribs/rest-width": { + "value": 40, + "use": "the ribs asleep: the wave's own bars at rest" + }, + "ribs/rest-height": { + "value": 16 + }, + "streak/line": { + "value": 1, + "use": "the hairline at rest" + }, + "streak/height": { + "value": 2, + "use": "the light streak while recording" + }, + "streak/point": { + "value": 4, + "use": "the bright point at the centre" + }, + "streak/arm": { + "value": 1.4, + "use": "the landing flash's vertical arm, as a fraction of the box's height" + }, + "opacity/hairline": { + "value": 0.5 } }, "type": { @@ -636,10 +622,6 @@ "value": 17, "use": "the +, × and ✓" }, - "ratio/orb-glyph": { - "value": 0.34, - "use": "the clipboard and exclamation glyphs, as a fraction of the orb" - }, "weight/letter": { "value": "regular" }, @@ -655,9 +637,6 @@ "weight/glyph": { "value": "medium" }, - "weight/orb-glyph": { - "value": "semibold" - }, "size/label": { "value": 12, "use": "the mono word labels on keys: 123, ABC, #+=, space, the return label" @@ -692,6 +671,13 @@ "tracking/cta": { "value": 1.4, "use": "uppercase mono at 14: the brand's E2 tracking" + }, + "ratio/voice-glyph": { + "value": 0.34, + "use": "the clipboard and exclamation glyphs, as a fraction of the voice element's height" + }, + "weight/voice-glyph": { + "value": "semibold" } }, "motion": { @@ -715,30 +701,10 @@ "value": 0.08, "use": "a key lighting" }, - "mood": { - "value": 0.8, - "use": "the orb's colour moving between moods" - }, "ring-period": { "value": 1.6, "use": "one turn of the ring, the Mac's cadence" }, - "drop": { - "value": 2.4, - "use": "the violet drop is gone by" - }, - "drop-rise": { - "value": 0.5, - "use": "the drop is up in" - }, - "drop-hold": { - "value": 0.9, - "use": "and held to" - }, - "drop-spread": { - "value": 1, - "use": "the bloom reaches its full spread in" - }, "caret": { "value": 0.5, "use": "the caret's blink" @@ -767,6 +733,18 @@ 1 ], "use": "the house curve for everything that moves; nothing springs" + }, + "sheen": { + "value": 4, + "use": "one pass of the light over the element at rest" + }, + "sheen-working": { + "value": 1.6, + "use": "and while something is happening: the ring's cadence" + }, + "glint-life": { + "value": 0.5, + "use": "a facet's flash while recording" } }, "fonts": { diff --git a/App/BlurtiOS/Shared/BlurtBrand.swift b/App/BlurtiOS/Shared/BlurtBrand.swift index 1f33a6a8..daa0bd37 100644 --- a/App/BlurtiOS/Shared/BlurtBrand.swift +++ b/App/BlurtiOS/Shared/BlurtBrand.swift @@ -17,13 +17,6 @@ import SwiftUI enum BlurtBrand { /// `#01762F` — the wordmark green, for light chrome. nonisolated static let green = DesignTokens.Brand.green700 - /// `#67AD82` — the brand hue lifted for dark chrome: the pill's text and - /// meter, the ring, the wordmark on the icon. - nonisolated static let greenOnDark = DesignTokens.Brand.green400 /// `#E67F36` — the error word. The body stays ink; the word carries the alarm. nonisolated static let errorOrange = DesignTokens.Brand.orange - - /// The ring round the orb: green into white, corner to corner; spun while - /// something is happening. - nonisolated static let orbRingGradient = DesignTokens.Gradients.orbRing } diff --git a/App/BlurtiOS/Shared/DesignTokens.swift b/App/BlurtiOS/Shared/DesignTokens.swift index 80bf119f..bfa1c6d7 100644 --- a/App/BlurtiOS/Shared/DesignTokens.swift +++ b/App/BlurtiOS/Shared/DesignTokens.swift @@ -152,12 +152,6 @@ enum DesignTokens { nonisolated static let kbLegendSecondary: Color = Themes.darkLegendSecondary /// The solid ring and glyph for an error. nonisolated static let kbNoticeError: Color = Brand.orange - /// The solid ring for pasted and copied. - nonisolated static let kbNoticeOk: Color = Brand.green400 - /// The sweeping ring's gradient, bottom-trailing. - nonisolated static let kbOrbRingEnd: Color = Brand.white - /// The sweeping ring's gradient, top-leading. - nonisolated static let kbOrbRingStart: Color = Brand.green700 /// The letter pop-up. nonisolated static let kbPopup: Color = Themes.darkPopup /// The wave, the caret, the saved check. @@ -182,6 +176,25 @@ enum DesignTokens { nonisolated static let gestureSwipeMin: CGFloat = 24 /// The +, × and ✓ touch targets. nonisolated static let glyphHit: CGFloat = 32 + nonisolated static let grilleBarHeight: CGFloat = 28 + /// The grille in the voice bar. + nonisolated static let grilleBarWidth: CGFloat = 64 + /// A dot's diameter. + nonisolated static let grilleDot: CGFloat = 2 + /// The cross glint's vertical arm, as a fraction of the grille's height. + nonisolated static let grilleGlintArm: CGFloat = 1.6 + /// The glint's arms. + nonisolated static let grilleGlintWidth: CGFloat = 1 + nonisolated static let grilleHomeHeight: CGFloat = 108 + /// The grille on the home screen. + nonisolated static let grilleHomeWidth: CGFloat = 240 + nonisolated static let grillePanelHeight: CGFloat = 72 + /// The grille in the panel. + nonisolated static let grillePanelWidth: CGFloat = 160 + /// The dot lattice: one dot every. + nonisolated static let grillePitch: CGFloat = 4 + /// The sheen's band, as a fraction of the width. + nonisolated static let grilleSheenWidth: CGFloat = 0.35 /// 123 and the globe at 402 pt: the iPhone's. nonisolated static let keyAbcWidth402: CGFloat = 43.333 /// Between keys, the iPhone's. @@ -218,46 +231,32 @@ enum DesignTokens { nonisolated static let marginSide: CGFloat = 6.5 /// The keyboard's top, and the slim bar's bottom. nonisolated static let marginVertical: CGFloat = 8 - /// The orb when Blurt isn't ready. - nonisolated static let opacityDim: CGFloat = 0.8 - /// And its saturation. - nonisolated static let opacityDimSaturation: CGFloat = 0.35 /// The + without Full Access. nonisolated static let opacityDisabled: CGFloat = 0.4 - nonisolated static let opacityGrain: CGFloat = 0.5 - /// The home hero's saturation when not listening. - nonisolated static let opacityHomeDimSaturation: CGFloat = 0.45 + /// The cross glint when the words land. + nonisolated static let opacityGlint: CGFloat = 0.95 + /// The dots at rest, over the key colour. + nonisolated static let opacityGrilleRest: CGFloat = 0.55 + nonisolated static let opacityHairline: CGFloat = 0.5 /// Key legends over the cap; below 1 they sit back. nonisolated static let opacityLegend: CGFloat = 1 /// The + at rest. nonisolated static let opacityLegendMuted: CGFloat = 0.5 - nonisolated static let opacityOrbLight: CGFloat = 0.3 + /// The element when Blurt isn't ready: a tap opens the app. + nonisolated static let opacityOff: CGFloat = 0.45 /// The field's placeholder. nonisolated static let opacityPlaceholder: CGFloat = 0.4 nonisolated static let opacityPopupShadow: CGFloat = 0.12 /// A key lightens this much while pressed. nonisolated static let opacityPressBrighten: CGFloat = 0.15 + /// The light passing over the element at rest: chrome catching light. + nonisolated static let opacitySheen: CGFloat = 0.22 /// Film grain over the whole keyboard surface: matte, the brand's texture. nonisolated static let opacitySurfaceGrain: CGFloat = 0.14 /// A soft darkening toward the surface's edges; 0 is none. nonisolated static let opacitySurfaceVignette: CGFloat = 0 /// The field's ×. nonisolated static let opacityTermCancel: CGFloat = 0.7 - /// The orb in the voice bar. - nonisolated static let orbBar: CGFloat = 40 - /// And blurs to this fraction of its size. - nonisolated static let orbDissipateBlur: CGFloat = 0.16 - /// The orb swells to this while dissipating. - nonisolated static let orbDissipateScale: CGFloat = 1.25 - /// The orb on the home screen. - nonisolated static let orbHome: CGFloat = 112 - /// The soft light's reach, as a fraction of the orb (was a fixed 110 pt, flat on a 40 pt orb). - nonisolated static let orbLightReach: CGFloat = 0.9 - /// The soft light's centre, as a fraction of the orb. - nonisolated static let orbLightX: CGFloat = 0.3 - nonisolated static let orbLightY: CGFloat = 0.22 - /// The orb in the panel. - nonisolated static let orbPanel: CGFloat = 96 /// Between the panel's orb and its key row. nonisolated static let panelSpacing: CGFloat = 12 /// The theme card draws the keyboard at this width. @@ -275,16 +274,29 @@ enum DesignTokens { /// The one thing that floats. nonisolated static let popupShadowRadius: CGFloat = 8 nonisolated static let popupShadowY: CGFloat = 2 - /// The orb while pressed. - nonisolated static let pressScale: CGFloat = 0.94 - /// The ring while working or noticing; the home ring. - nonisolated static let ringActive: CGFloat = 2 - /// The ring at rest. - nonisolated static let ringStill: CGFloat = 1 + /// The brand's buttons and the grille: rectangular, never a pill. + nonisolated static let radiusButton: CGFloat = 4 + /// The brand's cards. + nonisolated static let radiusCard: CGFloat = 12 + /// The brand's featured cards. + nonisolated static let radiusHero: CGFloat = 16 + /// The brand's inputs: the key-term field. + nonisolated static let radiusInput: CGFloat = 8 + nonisolated static let ribsRestHeight: CGFloat = 16 + /// The ribs asleep: the wave's own bars at rest. + nonisolated static let ribsRestWidth: CGFloat = 40 /// Between rows, the iPhone's. nonisolated static let rowGap: CGFloat = 11 /// Between the slim bar's keys. nonisolated static let slimSpacing: CGFloat = 8 + /// The landing flash's vertical arm, as a fraction of the box's height. + nonisolated static let streakArm: CGFloat = 1.4 + /// The light streak while recording. + nonisolated static let streakHeight: CGFloat = 2 + /// The hairline at rest. + nonisolated static let streakLine: CGFloat = 1 + /// The bright point at the centre. + nonisolated static let streakPoint: CGFloat = 4 /// Where it is full. nonisolated static let surfaceVignetteEnd: CGFloat = 0.75 /// Where the vignette begins, as a fraction of the keyboard's width. @@ -297,6 +309,17 @@ enum DesignTokens { nonisolated static let termInset: CGFloat = 2 /// The field's side padding. nonisolated static let termPad: CGFloat = 14 + nonisolated static let voiceBarHeight: CGFloat = 32 + /// The voice element's box in the voice bar: what the wave gets. + nonisolated static let voiceBarWidth: CGFloat = 240 + nonisolated static let voiceHomeHeight: CGFloat = 112 + /// The box on the home screen. + nonisolated static let voiceHomeWidth: CGFloat = 280 + nonisolated static let voicePanelHeight: CGFloat = 88 + /// The box in the panel. + nonisolated static let voicePanelWidth: CGFloat = 300 + /// The element while pressed. + nonisolated static let voicePressScale: CGFloat = 0.94 /// The wave stays this clear of the + at the trailing edge. nonisolated static let voicebarAddtermClearance: CGFloat = 12 /// The voice row, where the system puts its suggestion bar. @@ -306,20 +329,16 @@ enum DesignTokens { /// A wave bar's width. nonisolated static let waveBar: CGFloat = 2 nonisolated static let waveBarHeight: CGFloat = 24 - /// The wave in the voice bar, at most. - nonisolated static let waveBarWidth: CGFloat = 240 /// Between wave bars. nonisolated static let waveGap: CGFloat = 2 nonisolated static let waveHomeHeight: CGFloat = 44 - nonisolated static let waveHomeWidth: CGFloat = 280 nonisolated static let wavePanelHeight: CGFloat = 40 - nonisolated static let wavePanelWidth: CGFloat = 300 nonisolated static let wordmarkHeight: CGFloat = 22 } enum Typography { - /// The clipboard and exclamation glyphs, as a fraction of the orb. - nonisolated static let ratioOrbGlyph: CGFloat = 0.34 + /// The clipboard and exclamation glyphs, as a fraction of the voice element's height. + nonisolated static let ratioVoiceGlyph: CGFloat = 0.34 /// The app's body text. nonisolated static let sizeBody: CGFloat = 16 /// The app's small text. @@ -350,9 +369,9 @@ enum DesignTokens { nonisolated static let weightLabel: Font.Weight = .medium nonisolated static let weightLegend: Font.Weight = .medium nonisolated static let weightLetter: Font.Weight = .regular - nonisolated static let weightOrbGlyph: Font.Weight = .semibold nonisolated static let weightPopup: Font.Weight = .regular nonisolated static let weightTerm: Font.Weight = .regular + nonisolated static let weightVoiceGlyph: Font.Weight = .semibold } enum Motion { @@ -360,31 +379,27 @@ enum DesignTokens { nonisolated static let caret: Double = 0.5 /// A colour or fill changing state: the brand's transition. nonisolated static let colour: Double = 0.2 - /// The violet drop is gone by. - nonisolated static let drop: Double = 2.4 - /// And held to. - nonisolated static let dropHold: Double = 0.9 - /// The drop is up in. - nonisolated static let dropRise: Double = 0.5 - /// The bloom reaches its full spread in. - nonisolated static let dropSpread: Double = 1 /// The house curve for everything that moves; nothing springs. nonisolated static let easeSignature: UnitCurve = UnitCurve.bezier( startControlPoint: UnitPoint(x: 0.22, y: 1), endControlPoint: UnitPoint(x: 0.36, y: 1)) /// The panel's carousel. nonisolated static let flip: Double = 0.25 + /// A facet's flash while recording. + nonisolated static let glintLife: Double = 0.5 /// The keyboard resizing. nonisolated static let heightChange: Double = 0.25 /// A key lighting. nonisolated static let keyPress: Double = 0.08 /// The glint when the words land. nonisolated static let landing: Double = 0.6 - /// The orb's colour moving between moods. - nonisolated static let mood: Double = 0.8 /// The orb's press; the one thing that answers at once. nonisolated static let press: Double = 0.1 /// One turn of the ring, the Mac's cadence. nonisolated static let ringPeriod: Double = 1.6 + /// One pass of the light over the element at rest. + nonisolated static let sheen: Double = 4 + /// And while something is happening: the ring's cadence. + nonisolated static let sheenWorking: Double = 1.6 /// Every other change on the key: the ring, a glyph, the dimming. nonisolated static let stateFade: Double = 0.5 /// The voice bar becoming the field. @@ -409,26 +424,6 @@ enum DesignTokens { } enum Gradients { - /// The Mac orb's fill, the design's own stops (App elements/Recording.svg), swept bottom to top. - nonisolated static let orb = LinearGradient( - stops: [ - .init(color: Brand.violetLavender, location: 0), - .init(color: Brand.violetPeriwinkle, location: 0.0673), - .init(color: Brand.green400, location: 0.1442), - .init(color: Brand.green700, location: 0.3029), - .init(color: Brand.cobolt, location: 0.5962), - .init(color: Brand.violetIris, location: 0.75), - .init(color: Brand.violetLavender, location: 0.8942), - .init(color: Brand.white, location: 1), - ], - startPoint: .bottom, endPoint: .top) - /// The ring round the orb: green into white, corner to corner; spun while something is happening. - nonisolated static let orbRing = LinearGradient( - stops: [ - .init(color: Brand.green700, location: 0), - .init(color: Brand.white, location: 1), - ], - startPoint: .topLeading, endPoint: .bottomTrailing) } /// Every token as `group.name: value`, the way tokens.json renders it, so a @@ -502,9 +497,6 @@ enum DesignTokens { "keyboard.kb/legend": "#F5F3EB", "keyboard.kb/legend-secondary": "#A5A4A2", "keyboard.kb/notice-error": "#E67F36", - "keyboard.kb/notice-ok": "#67AD82", - "keyboard.kb/orb-ring-end": "#FFFFFF", - "keyboard.kb/orb-ring-start": "#01762F", "keyboard.kb/popup": "#33302A", "keyboard.kb/signal": "#67AD82", "keyboard.kb/surface": "#1D1B16", @@ -517,6 +509,17 @@ enum DesignTokens { "metrics.caret/width": "2", "metrics.gesture/swipe-min": "24", "metrics.glyph/hit": "32", + "metrics.grille/bar-height": "28", + "metrics.grille/bar-width": "64", + "metrics.grille/dot": "2", + "metrics.grille/glint-arm": "1.6", + "metrics.grille/glint-width": "1", + "metrics.grille/home-height": "108", + "metrics.grille/home-width": "240", + "metrics.grille/panel-height": "72", + "metrics.grille/panel-width": "160", + "metrics.grille/pitch": "4", + "metrics.grille/sheen-width": "0.35", "metrics.key/abc-width-402": "43.333", "metrics.key/gap": "6", "metrics.key/height": "43", @@ -535,28 +538,20 @@ enum DesignTokens { "metrics.margin/bottom-keys": "13", "metrics.margin/side": "6.5", "metrics.margin/vertical": "8", - "metrics.opacity/dim": "0.8", - "metrics.opacity/dim-saturation": "0.35", "metrics.opacity/disabled": "0.4", - "metrics.opacity/grain": "0.5", - "metrics.opacity/home-dim-saturation": "0.45", + "metrics.opacity/glint": "0.95", + "metrics.opacity/grille-rest": "0.55", + "metrics.opacity/hairline": "0.5", "metrics.opacity/legend": "1", "metrics.opacity/legend-muted": "0.5", - "metrics.opacity/orb-light": "0.3", + "metrics.opacity/off": "0.45", "metrics.opacity/placeholder": "0.4", "metrics.opacity/popup-shadow": "0.12", "metrics.opacity/press-brighten": "0.15", + "metrics.opacity/sheen": "0.22", "metrics.opacity/surface-grain": "0.14", "metrics.opacity/surface-vignette": "0", "metrics.opacity/term-cancel": "0.7", - "metrics.orb/bar": "40", - "metrics.orb/dissipate-blur": "0.16", - "metrics.orb/dissipate-scale": "1.25", - "metrics.orb/home": "112", - "metrics.orb/light-reach": "0.9", - "metrics.orb/light-x": "0.3", - "metrics.orb/light-y": "0.22", - "metrics.orb/panel": "96", "metrics.panel/spacing": "12", "metrics.picker/preview-width": "393", "metrics.picker/radius": "10", @@ -567,30 +562,41 @@ enum DesignTokens { "metrics.popup/radius": "10", "metrics.popup/shadow-radius": "8", "metrics.popup/shadow-y": "2", - "metrics.press/scale": "0.94", - "metrics.ring/active": "2", - "metrics.ring/still": "1", + "metrics.radius/button": "4", + "metrics.radius/card": "12", + "metrics.radius/hero": "16", + "metrics.radius/input": "8", + "metrics.ribs/rest-height": "16", + "metrics.ribs/rest-width": "40", "metrics.row/gap": "11", "metrics.slim/spacing": "8", + "metrics.streak/arm": "1.4", + "metrics.streak/height": "2", + "metrics.streak/line": "1", + "metrics.streak/point": "4", "metrics.surface/vignette-end": "0.75", "metrics.surface/vignette-start": "0.3", "metrics.term/gap": "8", "metrics.term/height": "36", "metrics.term/inset": "2", "metrics.term/pad": "14", + "metrics.voice/bar-height": "32", + "metrics.voice/bar-width": "240", + "metrics.voice/home-height": "112", + "metrics.voice/home-width": "280", + "metrics.voice/panel-height": "88", + "metrics.voice/panel-width": "300", + "metrics.voice/press-scale": "0.94", "metrics.voicebar/addterm-clearance": "12", "metrics.voicebar/height": "44", "metrics.voicebar/note-gap": "10", "metrics.wave/bar": "2", "metrics.wave/bar-height": "24", - "metrics.wave/bar-width": "240", "metrics.wave/gap": "2", "metrics.wave/home-height": "44", - "metrics.wave/home-width": "280", "metrics.wave/panel-height": "40", - "metrics.wave/panel-width": "300", "metrics.wordmark/height": "22", - "type.ratio/orb-glyph": "0.34", + "type.ratio/voice-glyph": "0.34", "type.size/body": "16", "type.size/caption": "14", "type.size/cta": "14", @@ -608,23 +614,21 @@ enum DesignTokens { "type.weight/label": "medium", "type.weight/legend": "medium", "type.weight/letter": "regular", - "type.weight/orb-glyph": "semibold", "type.weight/popup": "regular", "type.weight/term": "regular", + "type.weight/voice-glyph": "semibold", "motion.caret": "0.5", "motion.colour": "0.2", - "motion.drop": "2.4", - "motion.drop-hold": "0.9", - "motion.drop-rise": "0.5", - "motion.drop-spread": "1", "motion.ease/signature": "0.22,1,0.36,1", "motion.flip": "0.25", + "motion.glint-life": "0.5", "motion.height-change": "0.25", "motion.key-press": "0.08", "motion.landing": "0.6", - "motion.mood": "0.8", "motion.press": "0.1", "motion.ring-period": "1.6", + "motion.sheen": "4", + "motion.sheen-working": "1.6", "motion.state-fade": "0.5", "motion.term-swap": "0.4", "motion.wave-fade": "0.7", @@ -637,9 +641,6 @@ enum DesignTokens { "fonts.mono/light": "ModernGothicMono-Light", "fonts.mono/medium": "ModernGothicMono-Medium", "fonts.mono/regular": "ModernGothicMono-Regular", - "gradients.orb": - "#D7D3F4@0 #B0A7E9@0.0673 #67AD82@0.1442 #01762F@0.3029 #3923C7@0.5962 #887BDD@0.75 #D7D3F4@0.8942 #FFFFFF@1 bottom>top", - "gradients.orb-ring": "#01762F@0 #FFFFFF@1 topLeading>bottomTrailing", ] } // swiftlint:enable type_body_length diff --git a/scripts/design-capture.sh b/scripts/design-capture.sh index 69395017..dded7be3 100755 --- a/scripts/design-capture.sh +++ b/scripts/design-capture.sh @@ -8,6 +8,7 @@ # # scripts/design-capture.sh # panel × the golden states × both faces # scripts/design-capture.sh --layout full --states idle,recording,error --themes dark +# scripts/design-capture.sh --voice b # the ribs candidate (-BlurtGalleryVoice) # scripts/design-capture.sh --out .build/design/captures --no-build # # Writes /--@3x.png (1206 px wide on iPhone 18 Pro, @@ -22,6 +23,7 @@ LAYOUT=panel STATES=idle,recording,error,term THEMES=light,dark OUT="$REPO_ROOT/.build/design/captures" +VOICE="" BUILD=1 while [ $# -gt 0 ]; do case "$1" in @@ -41,12 +43,16 @@ while [ $# -gt 0 ]; do OUT="${2:?}" shift 2 ;; + --voice) + VOICE="${2:?}" + shift 2 + ;; --no-build) BUILD=0 shift ;; *) - echo "usage: design-capture.sh [--layout slimBar|panel|full] [--states a,b] [--themes a,b] [--out DIR] [--no-build]" >&2 + echo "usage: design-capture.sh [--layout slimBar|panel|full] [--states a,b] [--themes a,b] [--voice a|b|c] [--out DIR] [--no-build]" >&2 exit 2 ;; esac @@ -71,7 +77,7 @@ IFS=, read -ra STATE_LIST <<<"$STATES" IFS=, read -ra THEME_LIST <<<"$THEMES" for theme in "${THEME_LIST[@]}"; do for state in "${STATE_LIST[@]}"; do - name="$LAYOUT-$state-$theme" + name="$LAYOUT-$state-$theme${VOICE:+-$VOICE}" raw="$OUT/$name.raw.png" flags=(--screenshot "$raw") if [ "$first" -eq 0 ] || [ "$BUILD" -eq 0 ]; then flags=(--no-build "${flags[@]}"); fi @@ -86,7 +92,7 @@ for theme in "${THEME_LIST[@]}"; do still="" fi echo "==> $name" - BLURT_LAUNCH_ARGS="-BlurtGallery $LAYOUT $state $theme $still -BlurtGalleryBare" \ + BLURT_LAUNCH_ARGS="-BlurtGallery $LAYOUT $state $theme $still -BlurtGalleryBare${VOICE:+ -BlurtGalleryVoice $VOICE}" \ BLURT_SHOT_DELAY="$delay" scripts/ios-sim.sh "${flags[@]}" >/dev/null # The capture's scale: pixels across ÷ the device's points across. scale="$(python3 -c ' diff --git a/scripts/design-sync.sh b/scripts/design-sync.sh index e59e9e1f..e128152a 100755 --- a/scripts/design-sync.sh +++ b/scripts/design-sync.sh @@ -61,9 +61,8 @@ format_outputs() { # The design-literal lint. Scope: every file under the keyboard's sources # that draws — new views are linted by default — minus the logic (the model, # the host controller, the palette, the geometry and interaction rules, the -# voice state) and PrismOrb.swift, whose body is the orb's recipe (mesh drift, -# sparkle spots, grain density), documented as text in Figma, with only its -# parameters as tokens. Numbers 0 and 1 pass: `Spacer(minLength: 0)`, +# voice state) and Grain.swift, whose body is the grain's recipe (density, +# the two shades), with only its opacity as a token. Numbers 0 and 1 pass: `Spacer(minLength: 0)`, # `.opacity(on ? 1 : 0)` and `scaleEffect(1 + …)` are structure, not design. lint_literals() { python3 - <<'PY' @@ -71,7 +70,7 @@ import glob, os, re, sys exempt = { "KeyboardModel.swift", "KeyboardModel+Mic.swift", "KeyboardModel+Phase.swift", "KeyboardModel+Typing.swift", "KeyboardViewController.swift", "KeyboardPalette.swift", "KeyGeometry.swift", "KeyboardInteraction.swift", - "VoiceState.swift", "KeyboardMotion.swift", "MotionHeld.swift", "PrismOrb.swift", + "VoiceState.swift", "KeyboardMotion.swift", "MotionHeld.swift", "Grain.swift", } files = sorted( path for path in glob.glob("App/BlurtiOS/BlurtKeyboard/Sources/**/*.swift", recursive=True) diff --git a/scripts/ios-record.sh b/scripts/ios-record.sh index a492e11b..f216481a 100755 --- a/scripts/ios-record.sh +++ b/scripts/ios-record.sh @@ -21,6 +21,7 @@ LAYOUT=panel THEME=dark OUT="$REPO_ROOT/.build/design/loops" FRAMES="" +VOICE="" CYCLE=11.7 BUILD=() while [ $# -gt 0 ]; do @@ -41,12 +42,16 @@ while [ $# -gt 0 ]; do FRAMES="${2:?}" shift 2 ;; + --voice) + VOICE="${2:?}" + shift 2 + ;; --no-build) BUILD=(--no-build) shift ;; *) - echo "usage: ios-record.sh [--layout L] [--theme T] [--out DIR] [--frames s,s,…] [--no-build]" >&2 + echo "usage: ios-record.sh [--layout L] [--theme T] [--voice a|b|c] [--out DIR] [--frames s,s,…] [--no-build]" >&2 exit 2 ;; esac @@ -56,12 +61,12 @@ command -v ffmpeg >/dev/null || { exit 1 } mkdir -p "$OUT" -name="$LAYOUT-$THEME" +name="$LAYOUT-$THEME${VOICE:+-$VOICE}" # A still first: it builds, boots, and gives the crop rectangle. scripts/design-capture.sh --layout "$LAYOUT" --states idle --themes "$THEME" --out "$OUT/.still" \ - ${BUILD[@]+"${BUILD[@]}"} >/dev/null -raw="$OUT/.still/$LAYOUT-idle-$THEME.raw.png" + ${VOICE:+--voice "$VOICE"} ${BUILD[@]+"${BUILD[@]}"} >/dev/null +raw="$OUT/.still/$LAYOUT-idle-$THEME${VOICE:+-$VOICE}.raw.png" read -r CROP_W CROP_H CROP_X CROP_Y < <(swift scripts/design-diff.swift crop "$raw" "$OUT/.still/crop-probe.png" \ | sed -E 's/crop: ([0-9]+)×([0-9]+) at \(([0-9]+),([0-9]+)\).*/\1 \2 \3 \4/') [ -n "${CROP_W:-}" ] || { @@ -80,7 +85,8 @@ rm -f "$movie" xcrun simctl io "$UDID" recordVideo --codec h264 --force "$movie" & REC=$! sleep 1 -xcrun simctl launch "$UDID" "$BUNDLE_ID" -BlurtGallery "$LAYOUT" live "$THEME" -BlurtGalleryBare >/dev/null +xcrun simctl launch "$UDID" "$BUNDLE_ID" -BlurtGallery "$LAYOUT" live "$THEME" -BlurtGalleryBare \ + ${VOICE:+-BlurtGalleryVoice "$VOICE"} >/dev/null LAUNCH_AT=1 sleep "$(python3 -c "print(2 * $CYCLE + 3)")" kill -INT "$REC" From cb6db3a766b2b22b41ac4f0b756321f538828772 Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Tue, 29 Sep 2026 17:28:03 -0400 Subject: [PATCH 54/79] Keyboard: the chrome on the brand MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The word labels — 123, ABC, #+=, space, the return key's send / go / done — are the brand's eyebrow: Modern Gothic Mono, medium, 12 pt, uppercase, +1.2 tracking, a step quieter than a letter (the face's secondary legend). The letters stay SF Pro at the iPhone's size, the glyph keys SF Symbols, so the keyboard is native under the fingers and on-brand everywhere it uses a word. The key-term field is the brand's input — a rectangle at 8 pt with a 1 pt hairline, never a capsule. The film grain lies heavier on ink than on paper (opacity/grain-dark 0.14, grain-light 0.08, carried by the face). The Full Access note is short enough for the slim bar. `BlurtType` is the one way into the brand's faces (by PostScript name, fixed sizes); the root asserts in debug builds that the bundle knows them, and a test pins it. The gallery gains `symbols`, `send` and `saved`. Co-Authored-By: Claude Fable 5.1 --- .../BlurtKeyboard/Sources/KeyCap.swift | 23 ++++++---- .../Sources/KeyboardPalette.swift | 6 ++- .../Sources/KeyboardRootView.swift | 5 +++ .../BlurtKeyboard/Sources/SurfaceFinish.swift | 10 +++-- .../BlurtKeyboard/Sources/TermField.swift | 11 +++-- .../BlurtKeyboard/Sources/VoiceBar.swift | 2 +- .../BlurtKeyboard/Sources/VoiceGrille.swift | 5 ++- .../Sources/KeyboardGalleryView.swift | 12 +++++- .../BlurtiOSTests/BlurtTypeTests.swift | 12 ++++++ App/BlurtiOS/DESIGN.md | 5 ++- App/BlurtiOS/Design/figma/tokens.js | 5 ++- App/BlurtiOS/Design/tokens.json | 28 +++++++++---- App/BlurtiOS/Shared/BlurtType.swift | 42 +++++++++++++++++++ App/BlurtiOS/Shared/DesignTokens.swift | 15 +++++-- scripts/design-capture.sh | 2 +- 15 files changed, 147 insertions(+), 36 deletions(-) create mode 100644 App/BlurtiOS/BlurtiOSTests/BlurtTypeTests.swift create mode 100644 App/BlurtiOS/Shared/BlurtType.swift diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyCap.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyCap.swift index 1e99fe0b..c61bf69f 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyCap.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyCap.swift @@ -1,10 +1,11 @@ import SwiftUI -/// One ordinary key: a legend on a cap in the current palette; `dark` for the -/// modifier keys, a step darker as on the system keyboard; `bare` for a glyph -/// with no cap at all (the panel's cancel). `flexible` keys (the space bar) -/// take the width they're given, `width` fixes one, and the rest are the -/// iPhone's 123 key wide. +/// One ordinary key: a glyph (SF Symbols, as the system keyboard's) or a +/// word (the brand's mono eyebrow) on a cap in the current face; `dark` for +/// the modifier keys, a step darker as on the system keyboard; `bare` for a +/// glyph with no cap at all (the panel's cancel). `flexible` keys (the space +/// bar) take the width they're given, `width` fixes one, and the rest are +/// the iPhone's 123 key wide. struct KeyCap: View { var title: String? var systemImage: String? @@ -36,12 +37,18 @@ struct KeyCap: View { Group { if let systemImage { Image(systemName: systemImage) + .font(.system(size: DesignTokens.Typography.sizeLegend, weight: DesignTokens.Typography.weightLegend)) + .foregroundStyle(tint ?? palette.keyText) } else { - Text(title ?? "") + // A word on a key — 123, ABC, #+=, space, the return label — is the + // brand's eyebrow: Modern Gothic Mono, uppercase, tracked, a step + // quieter than a letter. + Text((title ?? "").uppercased()) + .font(BlurtType.mono(DesignTokens.Typography.sizeLabel, weight: .medium)) + .tracking(DesignTokens.Typography.trackingEyebrow) + .foregroundStyle(tint ?? palette.keyTextSecondary) } } - .font(.system(size: DesignTokens.Typography.sizeLegend, weight: DesignTokens.Typography.weightLegend)) - .foregroundStyle(tint ?? palette.keyText) .opacity(DesignTokens.Metrics.opacityLegend) .frame(maxWidth: flexible ? .infinity : nil) .frame(width: width) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift index 15e36361..75e557a8 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift @@ -39,6 +39,8 @@ struct KeyboardPalette: Equatable, Identifiable { let fieldBorder: Color /// The error word, the cancel ×, the Full Access note: orange on both faces. let notice: Color + /// How much film grain lies over the surface: the brand's texture, matte. + let grain: Double static let keyGap = DesignTokens.Metrics.keyGap static let rowGap = DesignTokens.Metrics.rowGap @@ -59,7 +61,7 @@ struct KeyboardPalette: Equatable, Identifiable { surface: Themes.lightSurface, key: Themes.lightKey, keyDark: Themes.lightKeyModifier, keyText: Themes.lightLegend, keyTextSecondary: Themes.lightLegendSecondary, signal: Themes.lightSignal, popupFill: Themes.lightPopup, field: Themes.lightField, fieldBorder: Themes.lightFieldBorder, - notice: Themes.lightNotice) + notice: Themes.lightNotice, grain: DesignTokens.Metrics.opacityGrainLight) /// The dark face: ink `#1D1B16`, `#33302A` keys, `#26231E` modifiers, warm /// white legends, the lifted green. @@ -68,7 +70,7 @@ struct KeyboardPalette: Equatable, Identifiable { surface: Themes.darkSurface, key: Themes.darkKey, keyDark: Themes.darkKeyModifier, keyText: Themes.darkLegend, keyTextSecondary: Themes.darkLegendSecondary, signal: Themes.darkSignal, popupFill: Themes.darkPopup, field: Themes.darkField, fieldBorder: Themes.darkFieldBorder, - notice: Themes.darkNotice) + notice: Themes.darkNotice, grain: DesignTokens.Metrics.opacityGrainDark) /// The picker's list, one entry per theme (a theme's two faces share an id). static let all: [KeyboardPalette] = [brandLight] diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardRootView.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardRootView.swift index 0c2870b6..d0d33a1e 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardRootView.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardRootView.swift @@ -39,6 +39,11 @@ struct KeyboardRootView: View { .environment(\.keyboardPalette, model.palette) .simultaneousGesture(swipe, including: model.layout == .panel ? .all : .subviews) .animation(reduceMotion ? nil : .easeInOut(duration: DesignTokens.Motion.flip), value: model.panelShowsKeys) + .onAppear { + // `Font.custom` falls back to the system font in silence; the bundle + // must know the brand's faces (UIAppFonts + Design/fonts). + assert(BlurtType.missing().isEmpty, "fonts not registered: \(BlurtType.missing())") + } } @Environment(\.accessibilityReduceMotion) private var systemReduceMotion diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/SurfaceFinish.swift b/App/BlurtiOS/BlurtKeyboard/Sources/SurfaceFinish.swift index c96338ad..d16a91f8 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/SurfaceFinish.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/SurfaceFinish.swift @@ -1,10 +1,10 @@ import SwiftUI -/// The surface's finish. Under the keys: the palette's flat colour and, when +/// The surface's finish. Under the keys: the face's flat colour and, when /// the tokens ask for one, a soft vignette toward the edges. Over everything: /// the brand's film grain, still (one seed, no shimmer — a keyboard has no -/// energy to spare), so every theme reads matte rather than painted. Neither -/// takes a touch. +/// energy to spare), heavier on ink than on paper, so both faces read matte +/// rather than painted. Neither takes a touch. enum SurfaceFinish { struct Ground: View { let surface: Color @@ -27,9 +27,11 @@ enum SurfaceFinish { } struct Grain: View { + @Environment(\.keyboardPalette) private var palette + var body: some View { BlurtiOSGrain(seed: 7) - .opacity(DesignTokens.Metrics.opacitySurfaceGrain) + .opacity(palette.grain) .blendMode(.overlay) .allowsHitTesting(false) .accessibilityHidden(true) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/TermField.swift b/App/BlurtiOS/BlurtKeyboard/Sources/TermField.swift index f99f9104..2dac9ac1 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/TermField.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/TermField.swift @@ -1,7 +1,8 @@ import SwiftUI -/// The voice bar as a field: × to leave, what has been typed with a caret, -/// ✓ to save. Return saves too. +/// The voice bar as a field — the brand's input, a rectangle with a hairline, +/// never a capsule: × to leave, what has been typed with a caret, ✓ to save. +/// Return saves too. struct TermField: View { var model: KeyboardModel @Environment(\.keyboardPalette) private var palette @@ -24,7 +25,11 @@ struct TermField: View { .padding(.horizontal, DesignTokens.Metrics.termPad) .frame(maxWidth: .infinity) .frame(height: DesignTokens.Metrics.termHeight) - .background(Capsule().fill(palette.keyDark)) + .background( + RoundedRectangle(cornerRadius: DesignTokens.Metrics.termRadius) + .fill(palette.field) + .strokeBorder(palette.fieldBorder, lineWidth: DesignTokens.Metrics.termBorder) + ) .accessibilityElement(children: .ignore) .accessibilityLabel("Key term: \(model.termDraft ?? "")") round("checkmark", tint: palette.signal) { model.saveTerm() } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift index 79264336..07b2ffab 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift @@ -27,7 +27,7 @@ struct VoiceBar: View { Button { model.openApp() } label: { - Text("Allow Full Access in Settings → Keyboards") + Text("Allow Full Access in Settings") .font(.footnote) .foregroundStyle(palette.notice) .lineLimit(1) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceGrille.swift b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceGrille.swift index ecf984db..b2571186 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceGrille.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceGrille.swift @@ -55,7 +55,8 @@ struct VoiceGrille: View { let sheenPhase = VoiceClock.sheen(time: time, working: state.isWorking && !state.isRecording) let sheenBand = size.width * Metrics.grilleSheenWidth let sheenCentre = sheenPhase * (size.width + size.height + sheenBand) - sheenBand - let runner = Self.runnerIndex(time: time, columns: columns, rows: rows) + let runner = + state.isWorking && !state.isRecording ? Self.runnerIndex(time: time, columns: columns, rows: rows) : nil let (glintTick, glintPhase) = Self.glintClock(time) let (restColour, restOpacity) = Self.rest(state: state, palette: palette) let sheen = inputs.animated && !state.isRecording ? (centre: sheenCentre, band: sheenBand) : nil @@ -127,7 +128,7 @@ struct VoiceGrille: View { } /// The perimeter dot the runner is on while something is happening. - private static func runnerIndex(time: TimeInterval, columns: Int, rows: Int) -> Int? { + private static func runnerIndex(time: TimeInterval, columns: Int, rows: Int) -> Int { let perimeter = max(1, 2 * columns + 2 * rows - 4) let phase = VoiceClock.sheen(time: time, working: true) return Int(phase * Double(perimeter)) % perimeter diff --git a/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift b/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift index bc9308a2..d9770749 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift @@ -21,7 +21,10 @@ /// `idle`, `connecting`, `recording`, `processing`, `pasted`, `copied`, /// `error`, `landed` (the drop, timed for a screenshot) or `live` (a whole /// dictation walked on a clock, over and over, for watching or recording - /// the motion). `scripts/ios-sim.sh` passes `BLURT_LAUNCH_ARGS` through, so + /// the motion), plus the keyboard's own `keys` (the panel flipped to its + /// keyboard page), `symbols`, `term` (the key-term field mid-typing), + /// `send` (a return key with a label) and `saved` (the + just after a term + /// was saved). `scripts/ios-sim.sh` passes `BLURT_LAUNCH_ARGS` through, so /// /// BLURT_LAUNCH_ARGS="-BlurtGallery panel idle,recording,processing" \ /// scripts/ios-sim.sh --screenshot panel.png @@ -131,8 +134,13 @@ model.paletteOverride = .resolve(KeyboardPalette.brandID, dark: Self.darkFaces.contains(theme)) // `keys` shows the panel's carousel flipped to its keyboard page; // `term` the voice bar as the key-term field, mid-typing. - model.panelShowsKeys = state == "keys" + model.panelShowsKeys = state == "keys" || state == "symbols" if state == "term" { model.termDraft = "Rizz" } + // `symbols`: the keys on their symbols page; `send`: a field whose + // return key says so; `saved`: the + a moment after a term was saved. + model.symbolsPage = state == "symbols" + if state == "send" { model.returnLabel = "send" } + if state == "saved" { model.termSavedAt = Date() } // `landed`: the words go in 2.75 s after launch, so a screenshot taken // 3 s in (scripts/ios-sim.sh) catches the glint mid-sweep. if state == "landed" { model.resultLandedAt = Date().addingTimeInterval(2.75) } diff --git a/App/BlurtiOS/BlurtiOSTests/BlurtTypeTests.swift b/App/BlurtiOS/BlurtiOSTests/BlurtTypeTests.swift new file mode 100644 index 00000000..ff359663 --- /dev/null +++ b/App/BlurtiOS/BlurtiOSTests/BlurtTypeTests.swift @@ -0,0 +1,12 @@ +import Testing + +@testable import BlurtiOS + +@Suite("Brand type") +struct BlurtTypeTests { + @Test("every face the tokens name is registered in this bundle") + func registered() { + #expect(BlurtType.missing().isEmpty, "unregistered: \(BlurtType.missing())") + #expect(BlurtType.names.count == 6) + } +} diff --git a/App/BlurtiOS/DESIGN.md b/App/BlurtiOS/DESIGN.md index ce2994b9..adf64f84 100644 --- a/App/BlurtiOS/DESIGN.md +++ b/App/BlurtiOS/DESIGN.md @@ -495,6 +495,8 @@ derivation. | `margin/vertical` | `8` | `Metrics.marginVertical` | the keyboard's top, and the slim bar's bottom | | `opacity/disabled` | `0.4` | `Metrics.opacityDisabled` | the + without Full Access | | `opacity/glint` | `0.95` | `Metrics.opacityGlint` | the cross glint when the words land | +| `opacity/grain-dark` | `0.14` | `Metrics.opacityGrainDark` | film grain over the dark face: matte, the brand's texture | +| `opacity/grain-light` | `0.08` | `Metrics.opacityGrainLight` | film grain over the light face: paper, lighter | | `opacity/grille-rest` | `0.55` | `Metrics.opacityGrilleRest` | the dots at rest, over the key colour | | `opacity/hairline` | `0.5` | `Metrics.opacityHairline` | — | | `opacity/legend` | `1` | `Metrics.opacityLegend` | key legends over the cap; below 1 they sit back | @@ -504,7 +506,6 @@ derivation. | `opacity/popup-shadow` | `0.12` | `Metrics.opacityPopupShadow` | — | | `opacity/press-brighten` | `0.15` | `Metrics.opacityPressBrighten` | a key lightens this much while pressed | | `opacity/sheen` | `0.22` | `Metrics.opacitySheen` | the light passing over the element at rest: chrome catching light | -| `opacity/surface-grain` | `0.14` | `Metrics.opacitySurfaceGrain` | film grain over the whole keyboard surface: matte, the brand's texture | | `opacity/surface-vignette` | `0` | `Metrics.opacitySurfaceVignette` | a soft darkening toward the surface's edges; 0 is none | | `opacity/term-cancel` | `0.7` | `Metrics.opacityTermCancel` | the field's × | | `panel/spacing` | `12` | `Metrics.panelSpacing` | between the panel's orb and its key row | @@ -531,10 +532,12 @@ derivation. | `streak/point` | `4` | `Metrics.streakPoint` | the bright point at the centre | | `surface/vignette-end` | `0.75` | `Metrics.surfaceVignetteEnd` | where it is full | | `surface/vignette-start` | `0.3` | `Metrics.surfaceVignetteStart` | where the vignette begins, as a fraction of the keyboard's width | +| `term/border` | `1` | `Metrics.termBorder` | the field's hairline | | `term/gap` | `8` | `Metrics.termGap` | × · field · ✓ | | `term/height` | `36` | `Metrics.termHeight` | the key-term field's capsule | | `term/inset` | `2` | `Metrics.termInset` | the field row's side inset | | `term/pad` | `14` | `Metrics.termPad` | the field's side padding | +| `term/radius` | `8` | `Metrics.termRadius` | the key-term field: the brand's input corners (radius/input) | | `voice/bar-height` | `32` | `Metrics.voiceBarHeight` | — | | `voice/bar-width` | `240` | `Metrics.voiceBarWidth` | the voice element's box in the voice bar: what the wave gets | | `voice/home-height` | `112` | `Metrics.voiceHomeHeight` | — | diff --git a/App/BlurtiOS/Design/figma/tokens.js b/App/BlurtiOS/Design/figma/tokens.js index 0265cbd0..317e1ea3 100644 --- a/App/BlurtiOS/Design/figma/tokens.js +++ b/App/BlurtiOS/Design/figma/tokens.js @@ -113,6 +113,8 @@ Metrics|margin/side|FLOAT|6.5||WIDTH_HEIGHT|DesignTokens.Metrics.marginSide|at t Metrics|margin/vertical|FLOAT|8||WIDTH_HEIGHT|DesignTokens.Metrics.marginVertical|the keyboard's top, and the slim bar's bottom Metrics|opacity/disabled|FLOAT|0.4||OPACITY|DesignTokens.Metrics.opacityDisabled|the + without Full Access Metrics|opacity/glint|FLOAT|0.95||OPACITY|DesignTokens.Metrics.opacityGlint|the cross glint when the words land +Metrics|opacity/grain-dark|FLOAT|0.14||OPACITY|DesignTokens.Metrics.opacityGrainDark|film grain over the dark face: matte, the brand's texture +Metrics|opacity/grain-light|FLOAT|0.08||OPACITY|DesignTokens.Metrics.opacityGrainLight|film grain over the light face: paper, lighter Metrics|opacity/grille-rest|FLOAT|0.55||OPACITY|DesignTokens.Metrics.opacityGrilleRest|the dots at rest, over the key colour Metrics|opacity/hairline|FLOAT|0.5||OPACITY|DesignTokens.Metrics.opacityHairline| Metrics|opacity/legend|FLOAT|1||OPACITY|DesignTokens.Metrics.opacityLegend|key legends over the cap; below 1 they sit back @@ -122,7 +124,6 @@ Metrics|opacity/placeholder|FLOAT|0.4||OPACITY|DesignTokens.Metrics.opacityPlace Metrics|opacity/popup-shadow|FLOAT|0.12||OPACITY|DesignTokens.Metrics.opacityPopupShadow| Metrics|opacity/press-brighten|FLOAT|0.15||OPACITY|DesignTokens.Metrics.opacityPressBrighten|a key lightens this much while pressed Metrics|opacity/sheen|FLOAT|0.22||OPACITY|DesignTokens.Metrics.opacitySheen|the light passing over the element at rest: chrome catching light -Metrics|opacity/surface-grain|FLOAT|0.14||OPACITY|DesignTokens.Metrics.opacitySurfaceGrain|film grain over the whole keyboard surface: matte, the brand's texture Metrics|opacity/surface-vignette|FLOAT|0||OPACITY|DesignTokens.Metrics.opacitySurfaceVignette|a soft darkening toward the surface's edges; 0 is none Metrics|opacity/term-cancel|FLOAT|0.7||OPACITY|DesignTokens.Metrics.opacityTermCancel|the field's × Metrics|panel/spacing|FLOAT|12||GAP|DesignTokens.Metrics.panelSpacing|between the panel's orb and its key row @@ -149,10 +150,12 @@ Metrics|streak/line|FLOAT|1||WIDTH_HEIGHT|DesignTokens.Metrics.streakLine|the ha Metrics|streak/point|FLOAT|4||WIDTH_HEIGHT|DesignTokens.Metrics.streakPoint|the bright point at the centre Metrics|surface/vignette-end|FLOAT|0.75||WIDTH_HEIGHT|DesignTokens.Metrics.surfaceVignetteEnd|where it is full Metrics|surface/vignette-start|FLOAT|0.3||WIDTH_HEIGHT|DesignTokens.Metrics.surfaceVignetteStart|where the vignette begins, as a fraction of the keyboard's width +Metrics|term/border|FLOAT|1||WIDTH_HEIGHT|DesignTokens.Metrics.termBorder|the field's hairline Metrics|term/gap|FLOAT|8||GAP|DesignTokens.Metrics.termGap|× · field · ✓ Metrics|term/height|FLOAT|36||WIDTH_HEIGHT|DesignTokens.Metrics.termHeight|the key-term field's capsule Metrics|term/inset|FLOAT|2||GAP|DesignTokens.Metrics.termInset|the field row's side inset Metrics|term/pad|FLOAT|14||GAP|DesignTokens.Metrics.termPad|the field's side padding +Metrics|term/radius|FLOAT|8||CORNER_RADIUS|DesignTokens.Metrics.termRadius|the key-term field: the brand's input corners (radius/input) Metrics|voice/bar-height|FLOAT|32||WIDTH_HEIGHT|DesignTokens.Metrics.voiceBarHeight| Metrics|voice/bar-width|FLOAT|240||WIDTH_HEIGHT|DesignTokens.Metrics.voiceBarWidth|the voice element's box in the voice bar: what the wave gets Metrics|voice/home-height|FLOAT|112||WIDTH_HEIGHT|DesignTokens.Metrics.voiceHomeHeight| diff --git a/App/BlurtiOS/Design/tokens.json b/App/BlurtiOS/Design/tokens.json index d5ff8c9d..aa2e4015 100644 --- a/App/BlurtiOS/Design/tokens.json +++ b/App/BlurtiOS/Design/tokens.json @@ -263,10 +263,6 @@ "value": 43.333, "use": "a key that isn't given a width: the iPhone's 123 key at 402 pt" }, - "key/pad": { - "value": 4, - "use": "a legend's side padding on a min-width key" - }, "key/letter-width-402": { "value": 33.5, "use": "a letter key at 402 pt: (width − 2 × margin/side − 9 × key/gap) / 10" @@ -436,10 +432,6 @@ "opacity/popup-shadow": { "value": 0.12 }, - "opacity/surface-grain": { - "value": 0.14, - "use": "film grain over the whole keyboard surface: matte, the brand's texture" - }, "opacity/surface-vignette": { "value": 0.0, "use": "a soft darkening toward the surface's edges; 0 is none" @@ -599,6 +591,26 @@ }, "opacity/hairline": { "value": 0.5 + }, + "opacity/grain-dark": { + "value": 0.14, + "use": "film grain over the dark face: matte, the brand's texture" + }, + "opacity/grain-light": { + "value": 0.08, + "use": "film grain over the light face: paper, lighter" + }, + "term/radius": { + "value": 8, + "use": "the key-term field: the brand's input corners (radius/input)" + }, + "term/border": { + "value": 1, + "use": "the field's hairline" + }, + "key/pad": { + "value": 4, + "use": "a legend's side padding on a min-width key" } }, "type": { diff --git a/App/BlurtiOS/Shared/BlurtType.swift b/App/BlurtiOS/Shared/BlurtType.swift new file mode 100644 index 00000000..13de78e8 --- /dev/null +++ b/App/BlurtiOS/Shared/BlurtType.swift @@ -0,0 +1,42 @@ +import SwiftUI +import UIKit + +/// The brand's faces, by the names the bundle registered them under +/// (`DesignTokens.Fonts`, PostScript names from the files in `Design/fonts`). +/// The keyboard uses the mono; the app's serif and body faces join when its +/// screens move onto the brand. Fixed point sizes throughout, as the system +/// keyboard's are — no Dynamic Type. `Font.custom` falls back to the system font in silence when a name +/// is wrong, so `missing()` says which names the bundle doesn't know; a test +/// pins it empty and debug builds assert it once. +enum BlurtType { + enum MonoWeight { + case light + case regular + case medium + } + + private typealias Fonts = DesignTokens.Fonts + + /// Modern Gothic Mono: eyebrows, CTAs, the keyboard's word labels. + nonisolated static func mono(_ size: CGFloat, weight: MonoWeight = .regular) -> Font { + Font.custom(monoName(weight), fixedSize: size) + } + + private nonisolated static func monoName(_ weight: MonoWeight) -> String { + switch weight { + case .light: Fonts.monoLight + case .regular: Fonts.monoRegular + case .medium: Fonts.monoMedium + } + } + + nonisolated static let names = [ + Fonts.monoLight, Fonts.monoRegular, Fonts.monoMedium, Fonts.headingRegular, Fonts.bodyRegular, Fonts.bodyBold, + ] + + /// The names this process cannot load: empty when the bundle's + /// `UIAppFonts` and `Design/fonts` agree with the tokens. + nonisolated static func missing() -> [String] { + names.filter { UIFont(name: $0, size: 12) == nil } + } +} diff --git a/App/BlurtiOS/Shared/DesignTokens.swift b/App/BlurtiOS/Shared/DesignTokens.swift index bfa1c6d7..d17dc408 100644 --- a/App/BlurtiOS/Shared/DesignTokens.swift +++ b/App/BlurtiOS/Shared/DesignTokens.swift @@ -235,6 +235,10 @@ enum DesignTokens { nonisolated static let opacityDisabled: CGFloat = 0.4 /// The cross glint when the words land. nonisolated static let opacityGlint: CGFloat = 0.95 + /// Film grain over the dark face: matte, the brand's texture. + nonisolated static let opacityGrainDark: CGFloat = 0.14 + /// Film grain over the light face: paper, lighter. + nonisolated static let opacityGrainLight: CGFloat = 0.08 /// The dots at rest, over the key colour. nonisolated static let opacityGrilleRest: CGFloat = 0.55 nonisolated static let opacityHairline: CGFloat = 0.5 @@ -251,8 +255,6 @@ enum DesignTokens { nonisolated static let opacityPressBrighten: CGFloat = 0.15 /// The light passing over the element at rest: chrome catching light. nonisolated static let opacitySheen: CGFloat = 0.22 - /// Film grain over the whole keyboard surface: matte, the brand's texture. - nonisolated static let opacitySurfaceGrain: CGFloat = 0.14 /// A soft darkening toward the surface's edges; 0 is none. nonisolated static let opacitySurfaceVignette: CGFloat = 0 /// The field's ×. @@ -301,6 +303,8 @@ enum DesignTokens { nonisolated static let surfaceVignetteEnd: CGFloat = 0.75 /// Where the vignette begins, as a fraction of the keyboard's width. nonisolated static let surfaceVignetteStart: CGFloat = 0.3 + /// The field's hairline. + nonisolated static let termBorder: CGFloat = 1 /// × · field · ✓. nonisolated static let termGap: CGFloat = 8 /// The key-term field's capsule. @@ -309,6 +313,8 @@ enum DesignTokens { nonisolated static let termInset: CGFloat = 2 /// The field's side padding. nonisolated static let termPad: CGFloat = 14 + /// The key-term field: the brand's input corners (radius/input). + nonisolated static let termRadius: CGFloat = 8 nonisolated static let voiceBarHeight: CGFloat = 32 /// The voice element's box in the voice bar: what the wave gets. nonisolated static let voiceBarWidth: CGFloat = 240 @@ -540,6 +546,8 @@ enum DesignTokens { "metrics.margin/vertical": "8", "metrics.opacity/disabled": "0.4", "metrics.opacity/glint": "0.95", + "metrics.opacity/grain-dark": "0.14", + "metrics.opacity/grain-light": "0.08", "metrics.opacity/grille-rest": "0.55", "metrics.opacity/hairline": "0.5", "metrics.opacity/legend": "1", @@ -549,7 +557,6 @@ enum DesignTokens { "metrics.opacity/popup-shadow": "0.12", "metrics.opacity/press-brighten": "0.15", "metrics.opacity/sheen": "0.22", - "metrics.opacity/surface-grain": "0.14", "metrics.opacity/surface-vignette": "0", "metrics.opacity/term-cancel": "0.7", "metrics.panel/spacing": "12", @@ -576,10 +583,12 @@ enum DesignTokens { "metrics.streak/point": "4", "metrics.surface/vignette-end": "0.75", "metrics.surface/vignette-start": "0.3", + "metrics.term/border": "1", "metrics.term/gap": "8", "metrics.term/height": "36", "metrics.term/inset": "2", "metrics.term/pad": "14", + "metrics.term/radius": "8", "metrics.voice/bar-height": "32", "metrics.voice/bar-width": "240", "metrics.voice/home-height": "112", diff --git a/scripts/design-capture.sh b/scripts/design-capture.sh index dded7be3..2d8aa5b4 100755 --- a/scripts/design-capture.sh +++ b/scripts/design-capture.sh @@ -103,7 +103,7 @@ print(3 if px > 1000 else 2) ' "$raw")" # `term` and `keys` show the full keyboard whatever layout was asked for. expect=$((HEIGHT_PT * scale)) - case "$state" in term | keys) expect=$(($(height_pt full) * scale)) ;; esac + case "$state" in term | keys | symbols) expect=$(($(height_pt full) * scale)) ;; esac swift scripts/design-diff.swift crop "$raw" "$OUT/$name@${scale}x.png" --expect-height "$expect" done done From e478ba20036c423f3ef74628c24f300c5ef69fb5 Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Tue, 29 Sep 2026 17:35:19 -0400 Subject: [PATCH 55/79] App: the screens on the brand, and DESIGN.md rewritten MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Blurt landing page on a phone, in the phone's appearance: the page under the brand's grain (warm off-white, or ink), the wordmark and the gear across the top, sections under Modern Gothic Mono eyebrows, Oceanic Text headlines, UN 11ST body, cards with 12 pt corners and a hairline (the hero 16), chips and buttons rectangular at 4 pt — the one green button per row with its label in uppercase mono, a hairline one beside it, a colour change on press and never a lift. The asset catalog gains Page, Text, Muted, CTA and CTAText, generated from the tokens like the three it had, so system chrome and our views agree in both appearances. `AppChrome` holds the card, the page, the eyebrow, the button style and the wordmark; `brandForm()` puts Settings, the styles editor, the import sheet and the key entry on the same page with the same faces. The theme picker shows a theme's two faces side by side. Every spacing is a token (`app/*`), and the design-literal lint now covers the app's views too. `-BlurtSettings` opens Settings as the root for a screenshot. DESIGN.md is rewritten for what the phone is now: the two faces, Apple's measured geometry and how it was read, the keys and their type, the voice element and its three candidates, the screens, and where Blurt diverges from the brand system on purpose. 72 tests; periphery clean. Co-Authored-By: Claude Fable 5.1 --- .../CTA.colorset/Contents.json | 38 + .../CTAText.colorset/Contents.json | 38 + .../Muted.colorset/Contents.json | 38 + .../Page.colorset/Contents.json | 38 + .../Text.colorset/Contents.json | 38 + App/BlurtiOS/BlurtiOS/Sources/AppChrome.swift | 134 ++++ .../BlurtiOS/Sources/BlurtBrand+App.swift | 45 -- .../BlurtiOS/Sources/BlurtiOSApp.swift | 3 + App/BlurtiOS/BlurtiOS/Sources/HomeHero.swift | 59 +- App/BlurtiOS/BlurtiOS/Sources/HomeView.swift | 63 +- .../BlurtiOS/Sources/ImportTermsView.swift | 3 +- .../BlurtiOS/Sources/KeyEntryView.swift | 6 +- .../BlurtiOS/Sources/RecentSection.swift | 33 +- .../BlurtiOS/Sources/SettingsView.swift | 24 +- App/BlurtiOS/BlurtiOS/Sources/SetupCard.swift | 48 +- .../BlurtiOS/Sources/StyleChips.swift | 40 +- .../BlurtiOS/Sources/StylesView.swift | 19 +- .../BlurtiOS/Sources/ThemePickerView.swift | 61 +- App/BlurtiOS/DESIGN.md | 723 +++++++++--------- App/BlurtiOS/Design/figma/tokens.js | 29 +- App/BlurtiOS/Design/tokens.json | 112 ++- App/BlurtiOS/Shared/BlurtType.swift | 8 + App/BlurtiOS/Shared/DesignTokens.swift | 87 ++- scripts/design-sync.sh | 19 +- scripts/design-tokens.swift | 5 + 25 files changed, 1124 insertions(+), 587 deletions(-) create mode 100644 App/BlurtiOS/BlurtiOS/Assets.xcassets/CTA.colorset/Contents.json create mode 100644 App/BlurtiOS/BlurtiOS/Assets.xcassets/CTAText.colorset/Contents.json create mode 100644 App/BlurtiOS/BlurtiOS/Assets.xcassets/Muted.colorset/Contents.json create mode 100644 App/BlurtiOS/BlurtiOS/Assets.xcassets/Page.colorset/Contents.json create mode 100644 App/BlurtiOS/BlurtiOS/Assets.xcassets/Text.colorset/Contents.json create mode 100644 App/BlurtiOS/BlurtiOS/Sources/AppChrome.swift delete mode 100644 App/BlurtiOS/BlurtiOS/Sources/BlurtBrand+App.swift diff --git a/App/BlurtiOS/BlurtiOS/Assets.xcassets/CTA.colorset/Contents.json b/App/BlurtiOS/BlurtiOS/Assets.xcassets/CTA.colorset/Contents.json new file mode 100644 index 00000000..ecf45080 --- /dev/null +++ b/App/BlurtiOS/BlurtiOS/Assets.xcassets/CTA.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x2F", + "green" : "0x76", + "red" : "0x01" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x82", + "green" : "0xAD", + "red" : "0x67" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/App/BlurtiOS/BlurtiOS/Assets.xcassets/CTAText.colorset/Contents.json b/App/BlurtiOS/BlurtiOS/Assets.xcassets/CTAText.colorset/Contents.json new file mode 100644 index 00000000..2017b08a --- /dev/null +++ b/App/BlurtiOS/BlurtiOS/Assets.xcassets/CTAText.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xFF", + "green" : "0xFF", + "red" : "0xFF" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x16", + "green" : "0x1B", + "red" : "0x1D" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/App/BlurtiOS/BlurtiOS/Assets.xcassets/Muted.colorset/Contents.json b/App/BlurtiOS/BlurtiOS/Assets.xcassets/Muted.colorset/Contents.json new file mode 100644 index 00000000..42a5841e --- /dev/null +++ b/App/BlurtiOS/BlurtiOS/Assets.xcassets/Muted.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x73", + "green" : "0x76", + "red" : "0x77" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xA2", + "green" : "0xA4", + "red" : "0xA5" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/App/BlurtiOS/BlurtiOS/Assets.xcassets/Page.colorset/Contents.json b/App/BlurtiOS/BlurtiOS/Assets.xcassets/Page.colorset/Contents.json new file mode 100644 index 00000000..8d857880 --- /dev/null +++ b/App/BlurtiOS/BlurtiOS/Assets.xcassets/Page.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xF8", + "green" : "0xFC", + "red" : "0xFD" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x16", + "green" : "0x1B", + "red" : "0x1D" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/App/BlurtiOS/BlurtiOS/Assets.xcassets/Text.colorset/Contents.json b/App/BlurtiOS/BlurtiOS/Assets.xcassets/Text.colorset/Contents.json new file mode 100644 index 00000000..efde6002 --- /dev/null +++ b/App/BlurtiOS/BlurtiOS/Assets.xcassets/Text.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x16", + "green" : "0x1B", + "red" : "0x1D" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xEB", + "green" : "0xF3", + "red" : "0xF5" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/App/BlurtiOS/BlurtiOS/Sources/AppChrome.swift b/App/BlurtiOS/BlurtiOS/Sources/AppChrome.swift new file mode 100644 index 00000000..33b8adcf --- /dev/null +++ b/App/BlurtiOS/BlurtiOS/Sources/AppChrome.swift @@ -0,0 +1,134 @@ +import SwiftUI +import UIKit + +/// The app's chrome, on the brand: the appearance-adaptive colours from the +/// asset catalog (generated from the tokens — page, text, muted, the card, +/// the one green button), the card, the eyebrow, the button, the wordmark. +/// The keyboard never uses these: it has its own faces. +extension BlurtBrand { + /// `green` in light, the lifted green in dark — the catalog's `AccentColor`, + /// also the app-level accent (`project.yml`). + nonisolated static let accent = Color.accentColor + /// The page: the design system's warm off-white in light, ink in dark. + nonisolated static let page = Color("Page") + nonisolated static let text = Color("Text") + /// Eyebrows, captions, secondary lines. + nonisolated static let muted = Color("Muted") + /// The card: warm tint on paper, a step up from ink in dark, with a hairline. + nonisolated static let cardFill = Color("CardFill") + nonisolated static let cardBorder = Color("CardBorder") + /// The one green button per row, and its text. + nonisolated static let cta = Color("CTA") + nonisolated static let ctaText = Color("CTAText") +} + +extension View { + /// The brand's card: the warm fill, 12 pt corners, a 1 pt hairline, no shadow. + func card(radius: CGFloat = DesignTokens.Metrics.cardRadius) -> some View { + background(BlurtBrand.cardFill, in: RoundedRectangle(cornerRadius: radius)) + .overlay( + RoundedRectangle(cornerRadius: radius).strokeBorder( + BlurtBrand.cardBorder, lineWidth: DesignTokens.Metrics.cardBorder)) + } + + /// The page under a screen: the ground colour with the brand's film grain over it. + func page() -> some View { + background { + ZStack { + BlurtBrand.page + BlurtiOSGrain(seed: 7) + .opacity(DesignTokens.Metrics.opacityGrainDark) + .blendMode(.overlay) + .allowsHitTesting(false) + } + .ignoresSafeArea() + } + } +} + +extension View { + /// A form or list on the brand: the page under it, the card as each row's + /// ground, the body face for its text, the accent for its controls. + func brandForm() -> some View { + scrollContentBackground(.hidden) + .page() + .listRowBackground(BlurtBrand.cardFill) + .font(BlurtType.body(DesignTokens.Typography.sizeBody)) + .foregroundStyle(BlurtBrand.text) + .tint(BlurtBrand.accent) + } +} + +/// An eyebrow: Modern Gothic Mono, uppercase, tracked, muted — the brand's +/// section label, above every group on a screen. +struct Eyebrow: View { + let text: String + var color = BlurtBrand.muted + + init(_ text: String, color: Color = BlurtBrand.muted) { + self.text = text + self.color = color + } + + var body: some View { + Text(text.uppercased()) + .font(BlurtType.mono(DesignTokens.Typography.sizeEyebrow, weight: .medium)) + .tracking(DesignTokens.Typography.trackingEyebrow) + .foregroundStyle(color) + } +} + +/// The brand's button: 40 pt, 4 pt corners — rectangular, never a pill — +/// its label in uppercase mono; a colour change while pressed, no lift. +/// `primary` is the one green button per row; `secondary` a hairline. +struct BrandButtonStyle: ButtonStyle { + enum Role { + case primary + case secondary + } + + var role = Role.primary + + func makeBody(configuration: Configuration) -> some View { + configuration.label + .font(BlurtType.mono(DesignTokens.Typography.sizeCta, weight: .medium)) + .tracking(DesignTokens.Typography.trackingCta) + .textCase(.uppercase) + .foregroundStyle(role == .primary ? BlurtBrand.ctaText : BlurtBrand.text) + .padding(.horizontal, DesignTokens.Metrics.appButtonPad) + .frame(maxWidth: .infinity, minHeight: DesignTokens.Metrics.appButtonHeight) + .background( + role == .primary ? BlurtBrand.cta : Color.clear, + in: RoundedRectangle(cornerRadius: DesignTokens.Metrics.radiusButton) + ) + .overlay( + RoundedRectangle(cornerRadius: DesignTokens.Metrics.radiusButton) + .strokeBorder( + role == .secondary ? BlurtBrand.cardBorder : Color.clear, lineWidth: DesignTokens.Metrics.cardBorder) + ) + .opacity(configuration.isPressed ? DesignTokens.Metrics.opacityPressed : 1) + .animation(.easeInOut(duration: DesignTokens.Motion.colour), value: configuration.isPressed) + } +} + +/// The lowercase wordmark from the Mac's ready screen, tinted with the accent +/// (`blurt-ready-logo.png`, shared from `App/Blurt/Blurt/Branding`). +struct Wordmark: View { + private static let height = DesignTokens.Metrics.wordmarkHeight + + var body: some View { + if let image = UIImage(named: "blurt-ready-logo") { + Image(uiImage: image) + .renderingMode(.template) + .resizable() + .scaledToFit() + .frame(height: Self.height) + .foregroundStyle(BlurtBrand.accent) + .accessibilityLabel("Blurt") + } else { + Text("blurt") + .font(BlurtType.heading(DesignTokens.Typography.sizeTitle)) + .foregroundStyle(BlurtBrand.accent) + } + } +} diff --git a/App/BlurtiOS/BlurtiOS/Sources/BlurtBrand+App.swift b/App/BlurtiOS/BlurtiOS/Sources/BlurtBrand+App.swift deleted file mode 100644 index c8d40536..00000000 --- a/App/BlurtiOS/BlurtiOS/Sources/BlurtBrand+App.swift +++ /dev/null @@ -1,45 +0,0 @@ -import SwiftUI - -/// The app's own additions to the brand: the appearance-adaptive pieces the -/// keyboard never needs, resolved from the asset catalog exactly as on the Mac -/// (`Assets.xcassets`, copied from `App/Blurt/Blurt/Assets.xcassets`). -extension BlurtBrand { - /// `green` in light, `greenOnDark` in dark — the catalog's `AccentColor`, - /// which is also the app-level accent (`project.yml`), so system-drawn - /// chrome and our views agree. - nonisolated static let accent = Color.accentColor - /// The warm card the design draws its containers with: `#EBE8E8` on - /// `#DEDBDB` in light, `#26231E` on `#3A362F` in dark. - nonisolated static let cardFill = Color("CardFill") - nonisolated static let cardBorder = Color("CardBorder") -} - -extension View { - /// The design's card: warm fill, 16 pt corners, a hairline border. - func card() -> some View { - background(BlurtBrand.cardFill, in: RoundedRectangle(cornerRadius: DesignTokens.Metrics.cardRadius)) - .overlay( - RoundedRectangle(cornerRadius: DesignTokens.Metrics.cardRadius) - .strokeBorder(BlurtBrand.cardBorder, lineWidth: DesignTokens.Metrics.cardBorder)) - } -} - -/// The lowercase wordmark from the Mac's ready screen, tinted with the accent -/// (`blurt-ready-logo.png`, shared from `App/Blurt/Blurt/Branding`). -struct Wordmark: View { - private static let height = DesignTokens.Metrics.wordmarkHeight - - var body: some View { - if let image = UIImage(named: "blurt-ready-logo") { - Image(uiImage: image) - .renderingMode(.template) - .resizable() - .scaledToFit() - .frame(height: Self.height) - .foregroundStyle(BlurtBrand.accent) - .accessibilityLabel("Blurt") - } else { - Text("blurt").font(.title2.weight(.bold)).foregroundStyle(BlurtBrand.accent) - } - } -} diff --git a/App/BlurtiOS/BlurtiOS/Sources/BlurtiOSApp.swift b/App/BlurtiOS/BlurtiOS/Sources/BlurtiOSApp.swift index 2727b740..36b8745d 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/BlurtiOSApp.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/BlurtiOSApp.swift @@ -43,6 +43,9 @@ struct BlurtiOSApp: App { probe } else if let voice = KeyboardGalleryView.VoiceStillView.parse(CommandLine.arguments) { voice + } else if CommandLine.arguments.contains("-BlurtSettings") { + // The settings sheet as the root, for a screenshot without a tap. + SettingsView(coordinator: coordinator) } else if rows.isEmpty { home } else { diff --git a/App/BlurtiOS/BlurtiOS/Sources/HomeHero.swift b/App/BlurtiOS/BlurtiOS/Sources/HomeHero.swift index c712f561..6ba26603 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/HomeHero.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/HomeHero.swift @@ -1,14 +1,14 @@ import SwiftUI -/// The hero: the keyboard's voice element at hero size, with the listening -/// state in words under it and the one button that opens or closes the mic. +/// The hero: the status as an eyebrow, a serif headline and a line of body +/// text, the voice element at hero size, and the one green button that opens +/// the mic (or the hairline one that closes it). struct HomeHero: View { var coordinator: DictationCoordinator let status: HomeStatus - /// When the last dictation's words landed — the hero's drop. + /// When the last dictation's words landed — the hero's glint. let landedAt: Date? @Environment(\.accessibilityReduceMotion) private var reduceMotion - @Environment(\.colorScheme) private var colorScheme private var state: VoiceState { @@ -16,55 +16,56 @@ struct HomeHero: View { } var body: some View { - VStack(spacing: 18) { + VStack(alignment: .leading, spacing: DesignTokens.Metrics.appHeroGap) { + Eyebrow("Status") + Text(status.title) + .font(BlurtType.heading(DesignTokens.Typography.sizeTitle)) + .foregroundStyle(BlurtBrand.text) + Text(status.subtitle) + .font(BlurtType.body(DesignTokens.Typography.sizeBody)) + .foregroundStyle(BlurtBrand.muted) VoiceElementView( inputs: VoiceElementInputs( state: state, landedAt: landedAt, animated: !reduceMotion, palette: colorScheme == .dark ? .brandDark : .brandLight, slot: .home) ) .frame(width: VoiceSlot.home.box.width, height: VoiceSlot.home.box.height) - .padding(.top, 6) - VStack(spacing: 4) { - Text(status.title).font(.title2.weight(.semibold)).multilineTextAlignment(.center) - Text(status.subtitle).font(.callout).foregroundStyle(.secondary).multilineTextAlignment(.center) - } + .frame(maxWidth: .infinity) if coordinator.window.isOpen { - Button(role: .destructive) { + Button("Stop listening") { Task { await coordinator.stopListening() } - } label: { - Text("Stop listening").frame(maxWidth: .infinity) } - .buttonStyle(.bordered) - .controlSize(.large) + .buttonStyle(BrandButtonStyle(role: .secondary)) } else { - Button { + Button("Start listening") { Task { await coordinator.startListening() } - } label: { - Text("Start listening").frame(maxWidth: .infinity) } - .buttonStyle(.borderedProminent) - .controlSize(.large) + .buttonStyle(BrandButtonStyle(role: .primary)) .disabled(!coordinator.apiKey.hasAPIKey) } Button(coordinator.phase.isCapturing ? "Stop and transcribe" : "Dictate here, to the clipboard") { coordinator.toggleDictation() } - .font(.callout) + .font(BlurtType.body(DesignTokens.Typography.sizeCaption)) + .foregroundStyle(BlurtBrand.muted) + .frame(maxWidth: .infinity) .disabled(!coordinator.window.isOpen) if let error = coordinator.window.lastError { - Text(error).font(.footnote).foregroundStyle(BlurtBrand.errorOrange).multilineTextAlignment(.center) + note(error) } if coordinator.microphoneDenied { - Text("Blurt needs the microphone. Allow it in Settings.") - .font(.footnote).foregroundStyle(BlurtBrand.errorOrange) + note("Blurt needs the microphone. Allow it in Settings.") } if coordinator.needsKey { - Text("Add your API key first (Settings → Account).") - .font(.footnote).foregroundStyle(BlurtBrand.errorOrange) + note("Add your API key first (Settings → Account).") } } - .padding(20) - .frame(maxWidth: .infinity) - .card() + .padding(DesignTokens.Metrics.appHeroPad) + .frame(maxWidth: .infinity, alignment: .leading) + .card(radius: DesignTokens.Metrics.radiusHero) + } + + private func note(_ text: String) -> some View { + Text(text).font(BlurtType.body(DesignTokens.Typography.sizeCaption)).foregroundStyle(BlurtBrand.errorOrange) } } diff --git a/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift b/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift index 462c0bf5..ba4d7151 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift @@ -2,10 +2,11 @@ import AVFoundation import BlurtEngine import SwiftUI -/// The app's one screen, in the shape of the Mac's ready screen: the wordmark, -/// the orb as the hero with the listening state under it, the style chips, -/// and the recent dictations as cards. Setup sits on top while anything is -/// missing; everything adjustable lives behind the gear. +/// The app's one screen: the Blurt landing page on a phone. The wordmark and +/// the gear across the top; the status as an eyebrow, a serif headline and a +/// line of body text over the voice element; the one green button; then the +/// styles and the recent dictations under their eyebrows. Setup sits on top +/// while anything is missing; everything adjustable lives behind the gear. struct HomeView: View { var coordinator: DictationCoordinator @Environment(\.scenePhase) private var scenePhase @@ -13,7 +14,7 @@ struct HomeView: View { @State private var keyboardSeen = SharedStore.keyboardEverSeen @State private var showsKeyEntry = false @State private var showsSettings = false - /// When the last dictation's words landed — the hero's drop. + /// When the last dictation's words landed — the hero's glint. @State private var landedAt: Date? private var status: HomeStatus { @@ -25,7 +26,8 @@ struct HomeView: View { var body: some View { NavigationStack { ScrollView { - VStack(spacing: 20) { + VStack(alignment: .leading, spacing: DesignTokens.Metrics.appSectionGap) { + header if !status.isSetUp { SetupCard( hasKey: coordinator.apiKey.hasAPIKey, microphoneGranted: microphoneGranted, keyboardSeen: keyboardSeen, @@ -34,25 +36,14 @@ struct HomeView: View { HomeHero(coordinator: coordinator, status: status, landedAt: landedAt) StyleChips() RecentSection(coordinator: coordinator) - poweredBy - } - .padding(.horizontal, 20) - .padding(.top, 8) - .padding(.bottom, 24) - } - .background(Color(uiColor: .systemGroupedBackground)) - .navigationBarTitleDisplayMode(.inline) - .toolbar { - ToolbarItem(placement: .principal) { Wordmark() } - ToolbarItem(placement: .topBarTrailing) { - Button { - showsSettings = true - } label: { - Image(systemName: "gearshape") - } - .accessibilityLabel("Settings") + Eyebrow("Powered by AssemblyAI") + .frame(maxWidth: .infinity) } + .padding(.horizontal, DesignTokens.Metrics.appPagePad) + .padding(.bottom, DesignTokens.Metrics.appSectionGap) } + .page() + .toolbar(.hidden, for: .navigationBar) .sheet(isPresented: $showsKeyEntry) { KeyEntryView(apiKey: coordinator.apiKey) } .sheet(isPresented: $showsSettings) { SettingsView(coordinator: coordinator) } .sheet(item: Binding(get: { coordinator.pendingTermPack }, set: { coordinator.pendingTermPack = $0 })) { @@ -76,18 +67,26 @@ struct HomeView: View { .tint(BlurtBrand.accent) } + /// The wordmark, and the gear that opens Settings. + private var header: some View { + HStack { + Wordmark() + Spacer() + Button { + showsSettings = true + } label: { + Image(systemName: "gearshape") + .font(.system(size: DesignTokens.Metrics.appIcon, weight: DesignTokens.Typography.weightGlyph)) + .foregroundStyle(BlurtBrand.muted) + } + .accessibilityLabel("Settings") + } + .frame(height: DesignTokens.Metrics.appHeaderHeight) + } + private func refreshStatus() { microphoneGranted = AVAudioApplication.shared.recordPermission == .granted keyboardSeen = SharedStore.keyboardEverSeen coordinator.apiKey.refreshStatus() } - - private var poweredBy: some View { - HStack(spacing: 3) { - Text("Powered by").foregroundStyle(.secondary) - Text("AssemblyAI").fontWeight(.medium) - } - .font(.caption) - .padding(.top, 4) - } } diff --git a/App/BlurtiOS/BlurtiOS/Sources/ImportTermsView.swift b/App/BlurtiOS/BlurtiOS/Sources/ImportTermsView.swift index 7e6d408b..6ad1e85d 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/ImportTermsView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/ImportTermsView.swift @@ -18,13 +18,14 @@ struct ImportTermsView: View { Toggle(term, isOn: binding(for: term)) } } header: { - Text(pack.from.map { "From \($0)" } ?? "Shared with you") + Eyebrow(pack.from.map { "From \($0)" } ?? "Shared with you") } footer: { Text( "They'll ride along with every dictation so Blurt spells them right. Terms you already have are skipped; " + "the first \(TermPack.termCap) terms ride each request, so keep the list to what matters.") } } + .brandForm() .navigationTitle(pack.name) .navigationBarTitleDisplayMode(.inline) .toolbar { diff --git a/App/BlurtiOS/BlurtiOS/Sources/KeyEntryView.swift b/App/BlurtiOS/BlurtiOS/Sources/KeyEntryView.swift index 9866c71e..5ff60cb9 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/KeyEntryView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/KeyEntryView.swift @@ -20,12 +20,16 @@ struct KeyEntryView: View { .autocorrectionDisabled() .textInputAutocapitalization(.never) if let inlineError { - Text(inlineError).font(.footnote).foregroundStyle(BlurtBrand.errorOrange) + Text(inlineError).font(BlurtType.body(DesignTokens.Typography.sizeCaption)).foregroundStyle( + BlurtBrand.errorOrange) } + } header: { + Eyebrow("API key") } footer: { Text("Keys live at assemblyai.com/dashboard/api-keys. Stored in the Keychain on this phone.") } } + .brandForm() .navigationTitle("API key") .toolbar { ToolbarItem(placement: .cancellationAction) { Button("Cancel") { dismiss() } } diff --git a/App/BlurtiOS/BlurtiOS/Sources/RecentSection.swift b/App/BlurtiOS/BlurtiOS/Sources/RecentSection.swift index 4c1a389d..5fe2d426 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/RecentSection.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/RecentSection.swift @@ -1,42 +1,43 @@ import SwiftUI import UIKit -/// The recent dictations as cards, with a copy button each. +/// The recent dictations as cards under their eyebrow: the words, the style +/// as a small mono tag, the time, a copy button. struct RecentSection: View { var coordinator: DictationCoordinator var body: some View { - VStack(alignment: .leading, spacing: 10) { - Text("Recent").font(.headline) + VStack(alignment: .leading, spacing: DesignTokens.Metrics.appStackGap) { + Eyebrow("Recent") if coordinator.recent.displayed.isEmpty { Text("Your recent blurts will appear here.") - .font(.callout).foregroundStyle(.secondary) + .font(BlurtType.body(DesignTokens.Typography.sizeBody)).foregroundStyle(BlurtBrand.muted) .frame(maxWidth: .infinity, alignment: .leading) - .padding(16) + .padding(DesignTokens.Metrics.appCardPad) .card() } ForEach(coordinator.recent.displayed) { entry in - VStack(alignment: .leading, spacing: 8) { - Text(entry.text).font(.body).lineLimit(3) - HStack(spacing: 8) { - if let style = entry.style { - Text(style) - .font(.caption.weight(.medium)) - .padding(.horizontal, 8).padding(.vertical, 3) - .background(Capsule().fill(BlurtBrand.accent.opacity(0.15))) - } - Text(entry.relativeLabel(now: Date())).font(.caption).foregroundStyle(.secondary) + VStack(alignment: .leading, spacing: DesignTokens.Metrics.appLineGap) { + Text(entry.text) + .font(BlurtType.body(DesignTokens.Typography.sizeBody)).foregroundStyle(BlurtBrand.text) + .lineLimit(3) // literal-ok: three lines of a dictation + HStack(spacing: DesignTokens.Metrics.appChipGap) { + if let style = entry.style { Eyebrow(style, color: BlurtBrand.accent) } + Text(entry.relativeLabel(now: Date())) + .font(BlurtType.body(DesignTokens.Typography.sizeCaption)).foregroundStyle(BlurtBrand.muted) Spacer() Button { UIPasteboard.general.string = entry.text } label: { Image(systemName: "doc.on.doc") + .font(.system(size: DesignTokens.Typography.sizeGlyph, weight: DesignTokens.Typography.weightGlyph)) + .foregroundStyle(BlurtBrand.muted) } .buttonStyle(.borderless) .accessibilityLabel("Copy") } } - .padding(16) + .padding(DesignTokens.Metrics.appCardPad) .card() } } diff --git a/App/BlurtiOS/BlurtiOS/Sources/SettingsView.swift b/App/BlurtiOS/BlurtiOS/Sources/SettingsView.swift index 123740b5..042f1d33 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/SettingsView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/SettingsView.swift @@ -2,8 +2,9 @@ import BlurtEngine import SwiftUI /// Everything adjustable, grouped the way the Mac's Settings are: the keyboard -/// (layout, hands-free), listening, transcription, the account, and -/// about. Presented from the home screen's gear. +/// (layout, theme, hands-free), listening, transcription, the account, and +/// about — a form on the brand's page, its sections under mono eyebrows. +/// Presented from the home screen's gear. struct SettingsView: View { var coordinator: DictationCoordinator @Environment(\.dismiss) private var dismiss @@ -25,6 +26,7 @@ struct SettingsView: View { accountSection aboutSection } + .brandForm() .navigationTitle("Settings") .navigationBarTitleDisplayMode(.inline) .toolbar { @@ -42,7 +44,7 @@ struct SettingsView: View { } .pickerStyle(.segmented) .onChange(of: layout) { _, value in SharedStore.layout = value } - Text(layout.summary).font(.footnote).foregroundStyle(.secondary) + Text(layout.summary).font(BlurtType.body(DesignTokens.Typography.sizeCaption)).foregroundStyle(BlurtBrand.muted) NavigationLink { ThemePickerView() } label: { @@ -51,7 +53,7 @@ struct SettingsView: View { Toggle("Hands-free", isOn: $autoDictate) .onChange(of: autoDictate) { _, value in SharedStore.autoDictate = value } } header: { - Text("Keyboard") + Eyebrow("Keyboard") } footer: { Text( "Hands-free starts dictating the moment the Blurt keyboard comes up in a text field; tap the mic to stop. " @@ -69,7 +71,7 @@ struct SettingsView: View { } .onChange(of: windowMinutes) { _, value in SharedStore.windowMinutes = value } } header: { - Text("Listening") + Eyebrow("Listening") } footer: { Text("How long the mic stays open with nobody dictating, so the keyboard can start without opening Blurt.") } @@ -91,7 +93,7 @@ struct SettingsView: View { } } } header: { - Text("Transcription") + Eyebrow("Transcription") } footer: { Text( "Enhanced transcripts clean up punctuation and wording. Key terms are names and jargon to spell right — " @@ -101,19 +103,23 @@ struct SettingsView: View { } private var accountSection: some View { - Section("Account") { + Section { LabeledContent("Sign in with AssemblyAI", value: "Coming soon") #if DEBUG Button(coordinator.apiKey.hasAPIKey ? "Replace the API key" : "Use an API key") { showsKeyEntry = true } #endif + } header: { + Eyebrow("Account") } } private var aboutSection: some View { - Section("About") { + Section { LabeledContent("Version", value: Self.version) Link("Blurt on GitHub", destination: URL(string: "https://github.com/AssemblyAI/blurt") ?? URL(filePath: "/")) - Text("Powered by AssemblyAI").foregroundStyle(.secondary) + Text("Powered by AssemblyAI").foregroundStyle(BlurtBrand.muted) + } header: { + Eyebrow("About") } } diff --git a/App/BlurtiOS/BlurtiOS/Sources/SetupCard.swift b/App/BlurtiOS/BlurtiOS/Sources/SetupCard.swift index aae67401..511f92f8 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/SetupCard.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/SetupCard.swift @@ -3,7 +3,8 @@ import SwiftUI import UIKit /// The setup checklist, on top of the home screen while anything is missing: -/// sign in (a key, in debug builds), the microphone, the keyboard. +/// three numbered steps — sign in (a key, in debug builds), the microphone, +/// the keyboard — each with its control until it is done. struct SetupCard: View { let hasKey: Bool let microphoneGranted: Bool @@ -14,21 +15,21 @@ struct SetupCard: View { let refresh: () -> Void var body: some View { - VStack(alignment: .leading, spacing: 14) { - Text("Set up Blurt").font(.headline) - SetupRow(done: hasKey, title: "Sign in with AssemblyAI") { - VStack(alignment: .leading, spacing: 6) { + VStack(alignment: .leading, spacing: DesignTokens.Metrics.appStackGap) { + Eyebrow("Set up Blurt") + SetupRow(number: "01", done: hasKey, title: "Sign in with AssemblyAI") { + VStack(alignment: .leading, spacing: DesignTokens.Metrics.appLineGap) { Text("Coming soon — sign-in needs the AssemblyAI login service.") - .font(.footnote).foregroundStyle(.secondary) + .font(BlurtType.body(DesignTokens.Typography.sizeCaption)).foregroundStyle(BlurtBrand.muted) #if DEBUG - Button("Use an API key instead") { enterKey() } + Button("Use an API key instead") { enterKey() }.buttonStyle(BrandButtonStyle(role: .secondary)) #endif } } - SetupRow(done: microphoneGranted, title: "Allow the microphone") { + SetupRow(number: "02", done: microphoneGranted, title: "Allow the microphone") { if AVAudioApplication.shared.recordPermission == .denied { // iOS asks once; after a refusal only Settings can change it. - Button("Allow in Settings") { Self.openAppSettings() } + Button("Allow in Settings") { Self.openAppSettings() }.buttonStyle(BrandButtonStyle(role: .primary)) } else { Button("Allow") { Task { @@ -36,20 +37,21 @@ struct SetupCard: View { refresh() } } + .buttonStyle(BrandButtonStyle(role: .primary)) } } - SetupRow(done: keyboardSeen, title: "Add the Blurt keyboard") { - VStack(alignment: .leading, spacing: 6) { + SetupRow(number: "03", done: keyboardSeen, title: "Add the Blurt keyboard") { + VStack(alignment: .leading, spacing: DesignTokens.Metrics.appLineGap) { Text( "Settings → Keyboards: turn on Blurt and Allow Full Access. " + "Full Access is what lets the keyboard send your words to Blurt." ) - .font(.footnote).foregroundStyle(.secondary) - Button("Open Settings") { Self.openAppSettings() } + .font(BlurtType.body(DesignTokens.Typography.sizeCaption)).foregroundStyle(BlurtBrand.muted) + Button("Open Settings") { Self.openAppSettings() }.buttonStyle(BrandButtonStyle(role: .secondary)) } } } - .padding(20) + .padding(DesignTokens.Metrics.appCardPad) .frame(maxWidth: .infinity, alignment: .leading) .card() } @@ -60,19 +62,23 @@ struct SetupCard: View { } } -/// One line of the setup checklist: a check or a circle, the step, and its -/// control while it is still to do. +/// One step: its number in mono, the step, and its control while it is still +/// to do; a check when done. private struct SetupRow: View { + let number: String let done: Bool let title: String @ViewBuilder let action: () -> Action var body: some View { - HStack(alignment: .top, spacing: 12) { - Image(systemName: done ? "checkmark.circle.fill" : "circle") - .foregroundStyle(done ? BlurtBrand.accent : Color.secondary) - VStack(alignment: .leading, spacing: 6) { - Text(title) + HStack(alignment: .top, spacing: DesignTokens.Metrics.appStackGap) { + Eyebrow(number, color: done ? BlurtBrand.accent : BlurtBrand.muted) + .frame(width: DesignTokens.Metrics.appSetupNumberWidth, alignment: .leading) + VStack(alignment: .leading, spacing: DesignTokens.Metrics.appLineGap) { + HStack { + Text(title).font(BlurtType.body(DesignTokens.Typography.sizeBody)).foregroundStyle(BlurtBrand.text) + if done { Image(systemName: "checkmark").foregroundStyle(BlurtBrand.accent) } + } if !done { action() } } } diff --git a/App/BlurtiOS/BlurtiOS/Sources/StyleChips.swift b/App/BlurtiOS/BlurtiOS/Sources/StyleChips.swift index adffada2..689a3409 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/StyleChips.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/StyleChips.swift @@ -1,8 +1,9 @@ import BlurtEngine import SwiftUI -/// The output styles as chips: Default and each profile, the active one -/// filled with the accent; Edit opens the styles editor. +/// The output styles as chips under their eyebrow: Default and each profile, +/// the active one filled with the accent, rectangular like everything on the +/// brand; Edit opens the styles editor. struct StyleChips: View { @AppStorage(StyleProfileStore.defaultsKey) private var profilesRaw = "" @AppStorage(StyleProfileStore.activeDefaultsKey) private var activeRaw = "" @@ -12,10 +13,10 @@ struct StyleChips: View { private var activeStyle: StyleProfile? { StyleProfileStore.active(in: profiles, id: activeRaw) } var body: some View { - VStack(alignment: .leading, spacing: 10) { - Text("Style").font(.headline) + VStack(alignment: .leading, spacing: DesignTokens.Metrics.appStackGap) { + Eyebrow("Style") ScrollView(.horizontal, showsIndicators: false) { - HStack(spacing: 8) { + HStack(spacing: DesignTokens.Metrics.appChipGap) { StyleChip(name: StyleProfileStore.defaultStyleName, selected: activeStyle == nil) { styles.activateDefault() } ForEach(profiles) { profile in StyleChip(name: profile.name, selected: activeStyle?.id == profile.id) { styles.activate(profile) } @@ -24,13 +25,15 @@ struct StyleChips: View { StylesView() } label: { Label("Edit", systemImage: "slider.horizontal.3") - .font(.subheadline.weight(.medium)) - .padding(.horizontal, 14) - .padding(.vertical, 8) - .background(Capsule().strokeBorder(BlurtBrand.cardBorder, lineWidth: 1)) + .font(BlurtType.body(DesignTokens.Typography.sizeCaption, bold: true)) + .foregroundStyle(BlurtBrand.muted) + .padding(.horizontal, DesignTokens.Metrics.appChipPadX) + .padding(.vertical, DesignTokens.Metrics.appChipPadY) + .overlay( + RoundedRectangle(cornerRadius: DesignTokens.Metrics.radiusButton) + .strokeBorder(BlurtBrand.cardBorder, lineWidth: DesignTokens.Metrics.cardBorder)) } } - .padding(.vertical, 2) } } } @@ -45,12 +48,17 @@ private struct StyleChip: View { var body: some View { Button(action: activate) { Text(name) - .font(.subheadline.weight(.medium)) - .padding(.horizontal, 14) - .padding(.vertical, 8) - .foregroundStyle(selected ? Color.white : Color.primary) - .background(Capsule().fill(selected ? BlurtBrand.accent : BlurtBrand.cardFill)) - .overlay(Capsule().strokeBorder(selected ? Color.clear : BlurtBrand.cardBorder, lineWidth: 1)) + .font(BlurtType.body(DesignTokens.Typography.sizeCaption, bold: true)) + .padding(.horizontal, DesignTokens.Metrics.appChipPadX) + .padding(.vertical, DesignTokens.Metrics.appChipPadY) + .foregroundStyle(selected ? BlurtBrand.ctaText : BlurtBrand.text) + .background( + selected ? BlurtBrand.cta : BlurtBrand.cardFill, + in: RoundedRectangle(cornerRadius: DesignTokens.Metrics.radiusButton) + ) + .overlay( + RoundedRectangle(cornerRadius: DesignTokens.Metrics.radiusButton) + .strokeBorder(selected ? Color.clear : BlurtBrand.cardBorder, lineWidth: DesignTokens.Metrics.cardBorder)) } .buttonStyle(.plain) .accessibilityAddTraits(selected ? .isSelected : []) diff --git a/App/BlurtiOS/BlurtiOS/Sources/StylesView.swift b/App/BlurtiOS/BlurtiOS/Sources/StylesView.swift index 7abcfb07..07a18965 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/StylesView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/StylesView.swift @@ -31,6 +31,8 @@ struct StylesView: View { Button("Edit") { editing = profile }.tint(BlurtBrand.green) } } + } header: { + Eyebrow("Styles") } footer: { Text("Tap a style to use it. Swipe a style to edit it. Up to \(StyleProfileStore.profileLimit).") } @@ -39,6 +41,7 @@ struct StylesView: View { .disabled(profiles.count >= StyleProfileStore.profileLimit) } } + .brandForm() .navigationTitle("Output styles") .sheet(isPresented: $adding) { StyleEditor(profile: nil, store: store) } .sheet(item: $editing) { StyleEditor(profile: $0, store: store) } @@ -54,9 +57,10 @@ private struct StyleRow: View { var body: some View { Button(action: activate) { HStack { - VStack(alignment: .leading, spacing: 3) { - Text(name).foregroundStyle(.primary) - Text(detail).font(.footnote).foregroundStyle(.secondary).lineLimit(2) + VStack(alignment: .leading, spacing: DesignTokens.Metrics.appLineGap) { + Text(name).foregroundStyle(BlurtBrand.text) + Text(detail).font(BlurtType.body(DesignTokens.Typography.sizeCaption)).foregroundStyle(BlurtBrand.muted) + .lineLimit(2) // literal-ok: two lines of instructions } Spacer() if isActive { Image(systemName: "checkmark").foregroundStyle(BlurtBrand.green) } @@ -90,23 +94,25 @@ private struct StyleEditor: View { var body: some View { NavigationStack { Form { - Section("Name") { + Section { TextField("e.g. Casual", text: $name) .onChange(of: name) { _, value in if value.count > StyleProfileStore.nameLimit { name = String(value.prefix(StyleProfileStore.nameLimit)) } } + } header: { + Eyebrow("Name") } Section { TextField( "e.g. add fitting emojis sparingly, or always write in lowercase", text: $instructions, axis: .vertical ) - .lineLimit(3...8) + .lineLimit(3...8) // literal-ok: the editor's rows .onChange(of: instructions) { _, value in let trimmed = value.prefix(maxUTF8Bytes: StyleProfileStore.characterLimit) if trimmed != value { instructions = trimmed } } } header: { - Text("Instructions") + Eyebrow("Instructions") } footer: { Text("\(instructions.utf8.count)/\(StyleProfileStore.characterLimit)") } @@ -119,6 +125,7 @@ private struct StyleEditor: View { } } } + .brandForm() .navigationTitle(profile == nil ? "New style" : "Edit style") .toolbar { ToolbarItem(placement: .cancellationAction) { Button("Cancel") { dismiss() } } diff --git a/App/BlurtiOS/BlurtiOS/Sources/ThemePickerView.swift b/App/BlurtiOS/BlurtiOS/Sources/ThemePickerView.swift index 54c52f50..a14e06ca 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/ThemePickerView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/ThemePickerView.swift @@ -1,32 +1,27 @@ import SwiftUI -/// Pick a keyboard theme from live previews, Partiful-style: a grid of cards, -/// each the real keyboard drawn small in that theme, the chosen one ringed -/// in the accent. The keyboard picks it up the next time it comes up. +/// Pick a keyboard theme from live previews: a card per theme, each the real +/// keyboard drawn small in both of its faces — the light one the keyboard +/// shows over a light app, the dark one over a dark app — the chosen theme +/// ringed in the accent. One theme for now; the curated ones return through +/// `KeyboardPalette.all`. The keyboard picks the choice up the next time it +/// comes up. struct ThemePickerView: View { @State private var chosen = KeyboardPalette.resolve(SharedStore.themeID, dark: false).id - @Environment(\.colorScheme) private var colorScheme - - private let columns = [GridItem(.flexible(), spacing: 14), GridItem(.flexible(), spacing: 14)] var body: some View { ScrollView { - LazyVGrid(columns: columns, spacing: 14) { + VStack(spacing: DesignTokens.Metrics.appStackGap) { ForEach(KeyboardPalette.all) { palette in - // A theme has two faces; the card shows the one this screen is in, - // which is the one the keyboard would show in an app that looks - // like it. - ThemeCard( - palette: KeyboardPalette.resolve(palette.id, dark: colorScheme == .dark), chosen: palette.id == chosen - ) { + ThemeCard(palette: palette, chosen: palette.id == chosen) { chosen = palette.id SharedStore.themeID = palette.id } } } - .padding(20) + .padding(DesignTokens.Metrics.appPagePad) } - .background(Color(uiColor: .systemGroupedBackground)) + .page() .navigationTitle("Theme") .navigationBarTitleDisplayMode(.inline) } @@ -37,37 +32,45 @@ private struct ThemeCard: View { let chosen: Bool let pick: () -> Void - /// The preview keyboard is the full layout, drawn at a phone's width and - /// scaled down to fit two cards across. + /// The preview keyboard is the full layout, drawn at the reference width + /// and scaled down to fit the card. private static let previewWidth = DesignTokens.Metrics.pickerPreviewWidth private static let scale = DesignTokens.Metrics.pickerScale var body: some View { Button(action: pick) { - VStack(alignment: .leading, spacing: 10) { - KeyboardRootView(model: Self.model(for: palette)) - .frame(width: Self.previewWidth, height: KeyboardLayout.full.height) - .scaleEffect(Self.scale, anchor: .topLeading) - .frame(width: Self.previewWidth * Self.scale, height: KeyboardLayout.full.height * Self.scale) - .clipShape(RoundedRectangle(cornerRadius: DesignTokens.Metrics.pickerRadius)) - .allowsHitTesting(false) - VStack(alignment: .leading, spacing: 2) { - Text(palette.name).font(.headline) - Text(palette.vibe).font(.caption).foregroundStyle(.secondary) + VStack(alignment: .leading, spacing: DesignTokens.Metrics.appStackGap) { + HStack(spacing: DesignTokens.Metrics.appPreviewGap) { + preview(KeyboardPalette.resolve(palette.id, dark: false)) + preview(KeyboardPalette.resolve(palette.id, dark: true)) + } + VStack(alignment: .leading, spacing: DesignTokens.Metrics.appLineGap) { + Text(palette.name).font(BlurtType.body(DesignTokens.Typography.sizeBody, bold: true)).foregroundStyle( + BlurtBrand.text) + Text(palette.vibe).font(BlurtType.body(DesignTokens.Typography.sizeCaption)).foregroundStyle(BlurtBrand.muted) } } - .padding(12) + .padding(DesignTokens.Metrics.appCardPad) .frame(maxWidth: .infinity, alignment: .leading) .card() .overlay( RoundedRectangle(cornerRadius: DesignTokens.Metrics.cardRadius) - .strokeBorder(chosen ? BlurtBrand.accent : Color.clear, lineWidth: 2)) + .strokeBorder(chosen ? BlurtBrand.accent : Color.clear, lineWidth: DesignTokens.Metrics.cardBorder)) } .buttonStyle(.plain) .accessibilityLabel(palette.name) .accessibilityAddTraits(chosen ? .isSelected : []) } + private func preview(_ face: KeyboardPalette) -> some View { + KeyboardRootView(model: Self.model(for: face)) + .frame(width: Self.previewWidth, height: KeyboardLayout.full.height) + .scaleEffect(Self.scale, anchor: .topLeading) + .frame(width: Self.previewWidth * Self.scale, height: KeyboardLayout.full.height * Self.scale) + .clipShape(RoundedRectangle(cornerRadius: DesignTokens.Metrics.pickerRadius)) + .allowsHitTesting(false) + } + private static func model(for palette: KeyboardPalette) -> KeyboardModel { let model = KeyboardModel() model.layout = .full diff --git a/App/BlurtiOS/DESIGN.md b/App/BlurtiOS/DESIGN.md index adf64f84..ca61fa7a 100644 --- a/App/BlurtiOS/DESIGN.md +++ b/App/BlurtiOS/DESIGN.md @@ -1,27 +1,23 @@ # Blurt for iPhone — design -The iPhone app and its keyboard are the Mac app's design on a phone: the same -ink, the same two greens, the same orb, the Mac pill's meter and ring. Nothing here was -invented; every number traces to a Mac source file, and where the phone needed -something the Mac has no equivalent for, this file says what was decided and -why. - -Source of truth on the Mac side: `App/Blurt/Blurt/Branding/BlurtBrand.swift` -(tokens, orb gradient), `App/Blurt/Blurt/Overlay/OverlayView.swift` and -`OverlayPillContent.swift` (the pill), `BrandOrb.swift` (the orb), -`Sources/BlurtEngine/Pipeline/MeterBarGeometry.swift` (the meter, unit-tested). -The phone reads the meter and the ring's rotation straight from the engine, so -they cannot drift from the Mac's. - -On the phone, every colour and number the views draw with lives once, in -`Design/tokens.json`, and is fanned out from there: `Shared/DesignTokens.swift` +The iPhone app and its keyboard are Blurt's brand on a phone: Cam Neri's +"warped futurism" as it appears on assemblyai.com/blurt — an ink ground +under film grain, a warm paper one in the light, serif headlines, uppercase +mono labels, green as the one signal, rectangular corners — at the iPhone +keyboard's own measured geometry, so nothing is unfamiliar under the fingers. +Nothing here is decoration: every number and colour is a token, every rule +has a test, and every state can be captured from a launch argument. + +Sources of truth: the brand design system +(`https://www.assemblyai.com/brand-design-system/assemblyai-brand-design-system.md`) +and the Blurt landing page for the look; `Design/apple-geometry.json` for the +keys; `Design/tokens.json` for every value the views draw with. From the +tokens, `scripts/design-tokens.swift` writes `Shared/DesignTokens.swift` (what the views read), the tables in this file marked `tokens:begin` / -`tokens:end`, and the app's three asset-catalog colour sets are all generated -by `scripts/design-tokens.swift`. Edit the JSON (or export it from Figma, see -below), run `scripts/design-sync.sh`, commit; `scripts/check.sh` runs -`design-sync.sh --check` and fails on drift. The views carry no design -literals — the same script lints them — so a number that changes in Figma -changes everywhere or nowhere. +`tokens:end`, the app's asset-catalog colour sets, and the Figma build's +variables. Edit the JSON, run `scripts/design-sync.sh`, commit; `check.sh` +runs `design-sync.sh --check` and fails on drift or on a design literal in a +view (`// literal-ok: ` for a genuine derivation). ## Reproducing it @@ -29,116 +25,55 @@ Every layout and state renders inside the app, from a launch argument, so a screenshot never depends on tapping through Notes: ```bash -BLURT_LAUNCH_ARGS="-BlurtGallery panel idle,recording,processing" scripts/ios-sim.sh --screenshot panel.png -BLURT_LAUNCH_ARGS="-BlurtGallery slimBar off,start,idle,connecting,recording,processing,pasted,copied,error" scripts/ios-sim.sh --screenshot slim.png -BLURT_LAUNCH_ARGS="-BlurtGallery full idle,recording,error" scripts/ios-sim.sh --screenshot full.png +BLURT_LAUNCH_ARGS="-BlurtGallery panel idle,recording,processing dark" scripts/ios-sim.sh --screenshot panel.png +BLURT_LAUNCH_ARGS="-BlurtGallery full idle,symbols,send light" scripts/ios-sim.sh --screenshot full.png +BLURT_LAUNCH_ARGS="-BlurtSettings" scripts/ios-sim.sh --screenshot settings.png ``` -Layouts: `slimBar`, `panel`, `full`. States: `off` (no Full Access), `start` -(the app isn't listening), then the pipeline's `idle`, `connecting`, -`recording` (level 0.62), `processing`, `pasted`, `copied`, `error`; `landed` -(the drop, timed for a 3 s screenshot); `live` (a whole dictation walked on -a clock, over and over — the way to watch or record the fades); and two -of the keyboard's own: `keys` (the panel flipped to its keyboard page) and -`term` (the key-term field mid-typing, e.g. `-BlurtGallery panel keys,term`). The -gallery is `BlurtiOS/Sources/KeyboardGalleryView.swift`, debug builds only; -the keyboard's sources are compiled into the app for it (`project.yml`). - -For the design loop the capture has to be the same pixels every time, and it -has to be the keyboard's pixels alone. Two switches do that: -`-BlurtGalleryStill` holds every motion at time zero (the ring, the meter's -wave, the orb's fluid and its grain — what Reduce Motion does) and -`-BlurtGalleryBare` draws the first row by itself inside a 2 pt `#FF00FF` -registration border. `-BlurtOrb ` -renders one orb fill the same way, for Figma's image fills. The scripts on -top: +Layouts: `slimBar`, `panel`, `full`. Faces: `light`, `dark` (the older theme +words still land on one). States: `off` (no Full Access), `start` (the app +isn't listening), the pipeline's `idle`, `connecting`, `recording` (level +0.62), `processing`, `pasted`, `copied`, `error`; `landed` (the glint, timed +for a 3 s screenshot); `live` (a whole dictation walked on a clock, over and +over, for watching or recording); and the keyboard's own `keys` (the panel +flipped to its keyboard page), `symbols`, `term` (the key-term field +mid-typing), `send` (a return key with a label), `saved` (the + just after a +term was saved). `-BlurtGalleryVoice a|b|c` picks the mic concept +(below). The gallery is `BlurtiOS/Sources/KeyboardGalleryView.swift`, debug +builds only; the keyboard's sources are compiled into the app for it. + +For the design loop a capture has to be the same pixels every time, and it +has to be the keyboard's pixels alone: `-BlurtGalleryStill` holds every +motion at time zero (what Reduce Motion does) and `-BlurtGalleryBare` draws +the first row by itself inside a 2 pt `#FF00FF` registration border. +`-BlurtVoice [light|dark]` renders one voice +element the same way. The scripts on top: ```bash -scripts/design-capture.sh --layout panel --states idle,recording,error,term --themes system,system-dark,ink - # builds once, captures each still, crops it → .build/design/captures/--@3x.png -scripts/ios-record.sh --layout panel --theme ink --frames 0,0.35,0.7 - # one 11.7 s loop of the `live` walk, cropped, plus stills at those seconds -swift scripts/design-diff.swift diff figma.png sim.png --out triptych.png --json metrics.json --mask x,y,w,h - # both to sRGB, then AE (pixels over the threshold) and RMSE, outside the masks and per mask -swift scripts/design-diff.swift sheet --out sheet.png --columns 4 "panel · idle · ink=a.png" … -scripts/design-sync.sh # tokens.json → DesignTokens.swift, these tables, the colour sets -scripts/design-sync.sh --check # what check.sh runs: drift and design literals +scripts/design-capture.sh --layout panel --states idle,recording,error,term --themes light,dark [--voice a] + # builds once, captures each still, crops it → .build/design/captures/--[-]@3x.png +scripts/ios-record.sh --layout panel --theme dark [--voice a] + # one 11.7 s loop of the `live` walk, cropped +swift scripts/design-diff.swift diff a.png b.png --out triptych.png --json metrics.json + # sRGB, AE and RMSE; `sheet` makes a contact sheet; `measure` reads a keyboard's caps off a screenshot +scripts/apple-geometry.sh # measures the iPhone's own keyboard → Design/apple-geometry.json +scripts/design-sync.sh [--check] # tokens.json → DesignTokens.swift, these tables, the colour sets ``` -`ios-sim.sh --no-build` reuses the last build, so a loop of forty captures -builds once. The capture device is the iPhone 18 Pro (402 pt → 1206 px at 3×, -the Figma frames' width), pinned in `scripts/ios-sim.sh`; a crop that is not -the layout's height × the scale fails rather than being resampled. - -## Figma - -The keyboard is designed in Figma and built from the export. The file is -**Blurt Keyboard** (Neil's personal Figma space until the design moves into the -AssemblyAI org; key and approved version in `Design/tokens.json` › `figma`), -three pages: `01 Foundations` (the variables below as six collections, text and -effect styles, specimens), `02 Components` (Key, LetterPopup, Orb, MicKey, -WaveformMeter, TermField, AddTermKey, CancelKey, VoiceBar), `03 Layouts` (the -three layouts at 402 pt — iPhone 18 Pro, the simulator this repo captures on — -as state rows named `//` exactly as the gallery captions -them, an Apple-keyboard reference overlay, redlines, the motion table, and the -review boards). The file is rebuilt from the scripts in `Design/figma/`, so the -scripts, not the file, are the durable record. - -The loop: design and approve in Figma (a named version) → export the variables -to `Design/tokens.json` → `scripts/design-sync.sh` → the views → captures from -the gallery compared against the Figma exports. The orb is the one exception -that goes the other way: `MeshGradient` plus grain cannot be drawn natively in -Figma, so the app renders deterministic stills that Figma uses as image fills, -and Figma holds the parameters (`orb/*`, `opacity/orb-light`, `opacity/grain`, -the drop timings). - -## Prototype on this branch: the prism orb (`PrismOrb.swift`) - -The brand artwork — a green beam into the prism, a violet, starlit one out — -as the orb's own story. The mic key and the home hero are filled by a 3 × 3 -`MeshGradient` whose edge and centre points drift on slow sines (further -with the voice level), under a soft upper-left light and animated film grain -(a seeded scatter of faint dots, new each frame at 20 Hz). The orb lives -**green**: calm at rest (`idle`, `working`, `off`), greener and brighter with -the voice (`listening(level:)`). The moment the words land in the field — -`resultLandedAt` on the keyboard, the phase reaching pasted or copied on the -home screen — a **violet drop** falls in: a bloom that grows from the centre -(the mesh soaks violet centre-first, corners least), six four-point sparkles -bursting a beat apart, up in 0.5 s, held to 0.9 s, flowing back out into the -green by 2.4 s. It lands with the success haptic. Under Reduce Motion the -fluid holds still and the drop simply fades. The ring stays the Mac orb's. - -The orb is a circle, never a pill, and while you talk it is not there at -all: it **dissipates** — swells a little, softens to a haze, is gone -(`Dissipate`) — and in its place the voice is a **thin wave** (`WaveformMeter` -at the keyboard's pitch: 2 pt bars 2 pt apart, dense, slim, flat on the -surface with no container). The wave is the key while it shows; on the stop -it fades and the orb condenses back the same way. Motion is soft and slow: -the crossing takes 0.7 s, every other change on the key 0.5 s, nothing -springs or snaps; only the press answers at once. - -The chrome is flat and contemporary: one colour per key at 8 pt corners, no -drop, no edge, no gloss; the +, the cancel ×, the term field's × and ✓ are -bare glyphs; the term field a flat capsule; the letter pop-up carries only a -whisper of shadow (12 %, radius 8), being the one thing that floats. - -Not merged: judge it on the simulator (`-BlurtGallery panel -idle,recording,landed`; `-BlurtGallery panel live` walks a whole dictation -on a clock, for watching or `xcrun simctl io booted recordVideo`; -`-BlurtStartListening` for the hero). - -## Themes, at the iPhone's spacing (`BlurtKeyboard/Sources/KeyboardPalette.swift`) - -The keys sit exactly where the iPhone keyboard's do, so nobody's fingers are -thrown off: 6 pt between keys, 11 pt between rows, 3 pt at the edges. The -keys are flat — one colour at 8 pt corners, no drop, no edge. A theme changes -how the keyboard looks and never how it types. The **default is the iPhone keyboard's own** look, -light or dark with the app being typed in (its field's `keyboardAppearance`, -else the app's style), so Blurt's keys sit on Apple's globe-and-mic bar as -one keyboard and the brand lives in the orb. Six more, curated, -Partiful-style — pick from live previews in Settings → Keyboard → Theme; the -keyboard picks it up the next time it comes up (`keyboardTheme` in the App -Group): +The capture device is the iPhone 18 Pro (402 pt → 1206 px at 3×), pinned in +`scripts/ios-sim.sh`; a crop that is not the layout's height fails rather +than being resampled. + +## The two faces + +The keyboard follows the field it is typing into, as the iPhone's does: +**dark** — ink under the brand's film grain, the website's ground — when the +host field's `keyboardAppearance` is dark, else the app's own appearance; +**light** — warm paper — otherwise. Both are the brand; neither is Apple's +grey. A face changes how the keyboard looks and never how it types. The +curated themes come back later as value sets through the same +`KeyboardPalette` shape (`all`, `resolve(_:dark:)`); a retired id resolves to +the brand's face. Ten roles each (`BlurtKeyboard/Sources/KeyboardPalette.swift`): @@ -149,23 +84,169 @@ Group): -The picker's one-liners (the vibes) live with the palettes in -`KeyboardPalette.swift`; the colours are the tokens above. The orb and the ring -are the same in every theme; the wave takes the -palette's `signal` green — the wordmark's on the light surfaces, the lifted -one on the dark. The picker (`ThemePickerView`) draws the real full keyboard at 0.42 scale on -each card, the iPhone theme in the picker's own appearance. The gallery's -last argument is a theme id (`system-dark` for the iPhone's dark face). - -The full layout follows the iPhone's geometry: ten letter keys across at one -width (`(width − 9·gap) / 10`), the middle row centred, shift and delete -taking what seven letters leave (twice the gap away from them), then 123 · -globe · space · return, return two modifiers wide. Letters pop up while -pressed (a 32 pt copy 58 pt above the key, typed on release); shift comes on -by itself at the start of a sentence — or of every word, or always — as the -field's `autocapitalizationType` asks, and goes off after one letter; a -second space within 450 ms of the first, after a word, becomes ". ". Not -yet: autocorrect and the suggestion bar. +The app's screens follow the phone's appearance through the asset catalog's +colour sets (generated from the `keyboard.app/*` tokens): `Page`, `Text`, +`Muted`, `CardFill`, `CardBorder`, `AccentColor`, `CTA`, `CTAText`. + +## Apple's geometry, measured + +The key tokens were assumed until 2026-09-29; now they are measured. +`scripts/apple-geometry.sh` runs the `BlurtiOSProbe` UI test (XCTest, the one +allowed use of it; its own scheme, never in the app's test run or the +periphery scan): the app launches on `-BlurtProbeField light|dark`, a bare +text field takes the system keyboard, the test reads every key's frame and +screenshots both faces. XCUITest reports touch cells, which tile a row with +no gaps, so `design-diff.swift measure` reads the caps themselves — widths, +gaps, height, the corner radius fitted to the top-left inset — off the +screenshot. The result is `Design/apple-geometry.json`; `AppleGeometryTests` +ties the tokens to it, `DesignTokensTests` the geometry to the tokens. + +iPhone 18 Pro, iOS 27, 402 pt: caps 33.5 wide and 43 tall, 6 between, 6.5 at +the sides, 11 between rows, corners at 8; shift and delete 45.58 with a 13.67 +gap to the letters; 123 and the globe 43.33, return two of those and a gap +(92.67); a 52 pt band above the keys (the suggestion bar's — where the voice +row goes: 8 + 44) and 13 under them; 270 in all. The dark face is identical. +The letter legend estimates at 24 pt from the l glyph. `KeyGeometry` +(`BlurtKeyboard/Sources/KeyGeometry.swift`) is the arithmetic between the +tokens: ten letters and nine gaps across the row, the side keys taking what +seven letters and the side gaps leave, the bottom row's widths scaling from +the reference width; the full keyboard draws from it and carries no +arithmetic of its own. iOS draws its own globe-and-mic bar under a custom +keyboard on a Face ID phone (58 pt), so the globe appears in ours only when +`needsInputModeSwitchKey` says so. + +## Keys + +Flat, one colour, at the iPhone's corner (8); no edge, no drop, no gloss. A +key brightens 15 % while pressed (0.08 s) rather than dimming; the letter +pop-up carries the one shadow on the keyboard, a whisper (12 %, radius 8), +being the one thing that floats. + +Type: the letters are SF Pro at the iPhone's size, and the glyph keys — shift, +delete, globe, return, the +, × and ✓ — SF Symbols, so the keyboard feels +native under the fingers. Every **word** on a key — `123`, `ABC`, `#+=`, +`space`, the return key's `send` / `go` / `done` / `search` / `next` / `join` — +is the brand's eyebrow: Modern Gothic Mono, medium, 12 pt, uppercase, +1.2 +tracking, in the face's secondary legend, a step quieter than a letter. Fixed +point sizes throughout, as the system keyboard's; no Dynamic Type. + + + +| Token | Value | Swift | Use | +| -------------------- | ---------- | ----------------------------- | --------------------------------------------------------------------------------- | +| `ratio/voice-glyph` | `0.34` | `Typography.ratioVoiceGlyph` | the clipboard and exclamation glyphs, as a fraction of the voice element's height | +| `size/body` | `16` | `Typography.sizeBody` | the app's body text | +| `size/caption` | `14` | `Typography.sizeCaption` | the app's small text | +| `size/cta` | `14` | `Typography.sizeCta` | a mono button label in the app (E2) | +| `size/eyebrow` | `12` | `Typography.sizeEyebrow` | a mono eyebrow in the app (E1) | +| `size/glyph` | `17` | `Typography.sizeGlyph` | the +, × and ✓ | +| `size/label` | `12` | `Typography.sizeLabel` | the mono word labels on keys: 123, ABC, #+=, space, the return label | +| `size/legend` | `16` | `Typography.sizeLegend` | every other key | +| `size/letter` | `24` | `Typography.sizeLetter` | letter keys: the iPhone's (estimated from the l glyph, apple-geometry.json) | +| `size/popup` | `32` | `Typography.sizePopup` | the letter pop-up | +| `size/term` | `17` | `Typography.sizeTerm` | the key-term field | +| `size/title` | `34` | `Typography.sizeTitle` | the app's serif headline | +| `tracking/cta` | `1.4` | `Typography.trackingCta` | uppercase mono at 14: the brand's E2 tracking | +| `tracking/eyebrow` | `1.2` | `Typography.trackingEyebrow` | uppercase mono at 12: the brand's E1 tracking | +| `weight/glyph` | `medium` | `Typography.weightGlyph` | — | +| `weight/label` | `medium` | `Typography.weightLabel` | — | +| `weight/legend` | `medium` | `Typography.weightLegend` | — | +| `weight/letter` | `regular` | `Typography.weightLetter` | — | +| `weight/popup` | `regular` | `Typography.weightPopup` | — | +| `weight/term` | `regular` | `Typography.weightTerm` | — | +| `weight/voice-glyph` | `semibold` | `Typography.weightVoiceGlyph` | — | + + + +The three faces are bundled in both targets (`Design/fonts/`, registered +through `UIAppFonts` in `project.yml`; an extension cannot read the app's +bundle) and reached only through `BlurtType`, by PostScript name: + + + +| Token | Value | Swift | Use | +| ----------------- | -------------------------- | ---------------------- | ----------------------------------------------- | +| `body/bold` | `UN-11ST-Bold` | `Fonts.bodyBold` | — | +| `body/family` | `UN-11 ST` | `Fonts.bodyFamily` | the app's body text | +| `body/regular` | `UN-11ST-Regular` | `Fonts.bodyRegular` | — | +| `heading/family` | `Oceanic Text` | `Fonts.headingFamily` | the app's serif headlines, sentence case, tight | +| `heading/regular` | `OceanicText-Regular` | `Fonts.headingRegular` | — | +| `mono/family` | `Modern Gothic Mono` | `Fonts.monoFamily` | eyebrows, CTAs, the keyboard's word labels | +| `mono/light` | `ModernGothicMono-Light` | `Fonts.monoLight` | — | +| `mono/medium` | `ModernGothicMono-Medium` | `Fonts.monoMedium` | — | +| `mono/regular` | `ModernGothicMono-Regular` | `Fonts.monoRegular` | — | + + + +`Font.custom` falls back to the system font in silence when a name is wrong, +so the root asserts in debug builds that the bundle knows every face, and +`BlurtTypeTests` pins it. The fonts come from the website's rebrand set; the +licence covers the web, and embedding them in an app that will one day merge +into the public MIT repo is to be settled with Brand Studio first. + +## The voice element + +The mic control is the one part of the keyboard that says what is +happening, and it says it without a word: the orb is gone. Three concepts +are built side by side behind one seam, `VoiceElementView` +(`BlurtKeyboard/Sources/VoiceElement.swift`), so they can be judged on sight +from the same states, the same level and the same landing moment; the one +that ships stays and the others go. Every candidate draws from +`VoiceElementInputs` — the `VoiceState`, the level inside it, when the words +landed, whether motion is allowed, the face, the slot (bar, panel, home) — +and nothing else. `VoiceClock` holds the clocks they share: the landing +glint (0 → 1 over `motion.landing`), the sheen (one pass per `motion.sheen` +at rest, per `sheen-working` while something is happening), and a facet hash +that makes the glints random to the eye and the same in every capture. + +| Kind | At rest | Recording | Working | Landed | Error | +| ------------------------------ | ---------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- | ------------------------------------------------------------------------- | ----------------------------------------------- | +| **a — Grille** (`VoiceGrille`) | a dot lattice (2 pt dots, 4 pt pitch) in a 4 pt-corner rectangle, a diagonal sheen crossing it | the lattice is the meter: columns light bottom-up in green with the engine's envelope, quantised to whole dots; facets on the peaks flash white | one lit dot runs the perimeter on the ring's cadence | a thin white cross glint with a faint prismatic fringe sweeps across once | the lattice orange, an exclamation mark over it | +| **b — Ribs** (`VoiceRibs`) | a short block of the wave's own bars under a cosine envelope, the sheen passing rib to rib | the ribs are the wave: they widen to the box and follow the voice | the ribs breathe with the sheen | a white glint runs the ribs | the ribs orange | +| **c — Streak** (`VoiceStreak`) | a hairline the width of the box with a bright point at its centre | the point blooms into a light streak whose reach follows the level, green along it, white at the heart, violet at the tips | a short streak sweeps the line back and forth | the cross's vertical arm flashes through the point | the line orange | + +What is common: the box (`voice/*`), dimming to `opacity/off` when Blurt +isn't ready (a tap opens the app), the two glyphs that need saying (a +clipboard when the words went there, an exclamation mark on a failure) drawn +by `MicControl` over the element, every change fading over `state-fade`, and +the press answering at once. Under Reduce Motion the sheen and the glints +hold still; the level still drives the meter. The home screen draws the same +element at home size in the app's face. + +| State | Element | Haptic | +| ----------------------- | ---------------------------------------------------------------------- | ---------------------------- | +| no Full Access | the note "Allow Full Access in Settings" is the key; a tap opens Blurt | — | +| app not listening | the element at `opacity/off`; a tap opens Blurt | — | +| idle | at rest, the sheen | — | +| connecting / processing | working | — / light impact on the stop | +| recording | the meter | medium impact | +| pasted | the landing glint, the element in green for 1.2 s | success | +| copied | the same, with the clipboard glyph, 2 s | success | +| error | orange, the exclamation mark, 2 s; the message on VoiceOver | error | + +The gesture is `MicPressSequencer` (`KeyboardInteraction.swift`), tested: a +press waits 90 ms so a swipe that starts on the key never starts a dictation +it must then cancel; a tap quicker than that is still a tap; a swipe past +24 pt cancels the timer, or undoes a press that went out. Finger down and up +drive the engine's `DictationKeyGate`, so a tap latches and a hold is +push-to-talk exactly as on the Mac. + +## Layouts and their heights (`KeyboardLayout.height`) + +Side margins 6.5; top 8; under a row of keys 13 (the iPhone's), under the +slim bar 8. + +| Layout | Rows | Height | +| --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | +| `slimBar` | globe · voice bar · delete · return | 60 | +| `panel` | the voice element, centred (the + top-left; cancel top-right while in flight) · globe · space · delete · return. A two-page carousel: a horizontal swipe flips between the panel and the full keyboard, and it is back to the element each time the keyboard appears. | 216, or 270 when flipped | +| `full` | voice row 44, then the first key row right under it as the iPhone's sits under its suggestions · three letter rows 43 · 123 / globe / space / return | 270 | + +The voice row (`VoiceBar`) is where the system keyboard puts its suggestion +bar: the element, the + beside it at the trailing edge, or the key-term +field. A swipe flips the panel past 48 pt sideways and more sideways than up +or down by 1.5×; a key acts on release and only under 12 pt of travel +(`KeyboardInteraction`, tested). ## Quick-add key term @@ -173,10 +254,11 @@ The most-asked-for thing: Blurt mishears a niche word, and the fix has to take seconds, inside the app you're typing in, never a trip to Settings. 1. Select the misheard word in your text (or select nothing). -2. Tap the small **+** beside the orb (top-right of the bar; top-left corner of - the panel). The bar becomes a field — × · what you type · ✓ — pre-filled - with the selection, and the keys type into it (the panel and slim bar flip - to the letter keys for it). Shift is on for the first letter. +2. Tap the small **+** beside the element (trailing edge of the bar; top-left + corner of the panel). The bar becomes a field — × · what you type · ✓ — the + brand's input, a rectangle at 8 pt with a hairline — pre-filled with the + selection, and the keys type into it (the panel and slim bar flip to the + letter keys for it). Shift is on for the first letter. 3. Type the right spelling; return or ✓ saves. The term goes into Blurt's key terms (`BlurtKeyTerms` in the App Group, `KeyTermList` rules: trimmed, deduplicated case-insensitively) and rides `keyterms_prompt` on the very @@ -185,60 +267,47 @@ seconds, inside the app you're typing in, never a trip to Settings. haptic, and the + shows a check for 1.2 s. × or an empty save leaves the mode, and so does the keyboard going away. A -hardware keyboard (an iPad's, a Bluetooth one, the simulator's Mac) types -past the on-screen keys into the app's field; while the term field is open a -short run that appears there right after where the cursor was — the text -before the cursor grew, the text after it didn't, nothing is selected — is -moved into the term and taken back out of the field; a cursor move changes -both sides and is left alone. A selection that carried spaces around the -word keeps them on replacement. The list itself is edited in Settings → -Transcription, which shows the count against the request's cap of 100 terms -(`KeytermsBoost`); the engine applies the caps on the request, first terms -first. +hardware keyboard types past the on-screen keys into the app's field; while +the term field is open a short run that appears there right after where the +cursor was is moved into the term and taken back out of the field. The list +itself is edited in Settings → Transcription, which shows the count against +the request's cap of 100 terms. ## Sharing key terms -A group chat has names and slang everyone's dictation should get right, so a -list travels. Settings → Transcription → **Share key terms…** puts the list -in the share sheet as a `.blurtterms` file (JSON — `name`, `from`, `terms`; a -declared document type, `dev.alex.blurt.terms`) with the words as the -message text, so a friend without Blurt still gets them. A tap on the file -in Messages opens Blurt with "Add N key terms?": every term ticked, untick -any, Add merges the rest without duplicates. A `blurt://terms?add=a,b,c&name=…&from=…` -link does the same (`TermPack`, `ImportTermsView`). A pack is refused over -64 KB, past 100 terms (the request's own cap; the rest are dropped) or with a -term, name or sender over 80 characters; a file or link that claims to be a -pack and isn't gets "Couldn't read that list". A file iOS handed over in the -app's Inbox is deleted once read. +Settings → Transcription → **Share key terms…** puts the list in the share +sheet as a `.blurtterms` file (JSON — `name`, `from`, `terms`; a declared +document type, `dev.alex.blurt.terms`) with the words as the message text. A +tap on the file in Messages opens Blurt with "Add N key terms?": every term +ticked, untick any, Add merges the rest without duplicates. A +`blurt://terms?add=a,b,c&name=…&from=…` link does the same (`TermPack`, +`ImportTermsView`). A pack is refused over 64 KB, past 100 terms or with a +term, name or sender over 80 characters. ## Adapting to the phone's own keyboard settings Nothing to configure: key clicks play only if the user has keyboard clicks -on (the input view adopts `UIInputViewAudioFeedback`; `playInputClick` on -letters, space, delete and return); the return key says what the field asks — send, search, go, done, -next, join — with the glyph otherwise; a number, decimal or phone field opens -on the symbols page; capitalisation follows the field's -`autocapitalizationType`; the letter rows follow the phone's first language -(AZERTY for French, QWERTZ for German, Czech, Slovak and Hungarian, QWERTY -otherwise). +on; the return key says what the field asks — send, search, go, done, next, +join — with the glyph otherwise; a number, decimal or phone field opens on +the symbols page; capitalisation follows the field's `autocapitalizationType`; +the letter rows follow the phone's first language (AZERTY for French, QWERTZ +for German, Czech, Slovak and Hungarian, QWERTY otherwise); the face follows +the field's `keyboardAppearance`. ## Hands-free On by default, with a toggle in Settings: a dictation starts the moment the keyboard comes up in a text field — the same synthetic tap through the -engine's gate, so it latches and the next tap of the mic stops it. Only when -the app is listening and nothing is in flight; otherwise the orb sits dimmed -and the first tap opens Blurt. It fires on the keyboard's appearance, not on -every field change while it stays up. When the keyboard leaves the screen -with a dictation it started, it releases a recording (the words still land, -on the clipboard if no keyboard is there) and cancels anything earlier, so -nothing records on without it. +engine's gate, so it latches and the next tap of the element stops it. Only +when the app is listening and nothing is in flight; otherwise the element +sits dimmed and the first tap opens Blurt. When the keyboard leaves the +screen with a dictation it started, it releases a recording (the words still +land, on the clipboard if no keyboard is there) and cancels anything earlier. ## Tokens (`Design/tokens.json` → `Shared/DesignTokens.swift`) -The brand's colours, as the Mac defines them and as the phone extends them. -`BlurtBrand` keeps its names (`green`, `greenOnDark`, `ink`, …) as aliases of -these, so the Mac's vocabulary still reads at the call sites. +The brand's colours, as the design system defines them and as the phone +uses them. `BlurtBrand` keeps a few of the Mac's names as aliases. @@ -280,9 +349,8 @@ these, so the Mac's vocabulary still reads at the call sites. -The keyboard's semantic colours — what a Figma component binds to. In Swift -the keys read the chosen theme's palette at run time; these are the design -theme's (ink) values, and the app's catalog colours. +The keyboard's semantic colours — what a Figma component binds to — and the +app's catalog colours: @@ -294,6 +362,16 @@ theme's (ink) values, and the app's catalog colours. | `app/card-border-light` | `#C7C3B2` (`brand.paper/400`) | `Keyboard.appCardBorderLight` | the catalog's CardBorder in light | | `app/card-fill-dark` | `#26231E` (`brand.ink/800`) | `Keyboard.appCardFillDark` | the catalog's CardFill in dark | | `app/card-fill-light` | `#F5F3EB` (`brand.paper/tint`) | `Keyboard.appCardFillLight` | the catalog's CardFill in light | +| `app/cta-dark` | `#67AD82` (`brand.green/400`) | `Keyboard.appCtaDark` | the catalog's CTA in dark: the site's button green | +| `app/cta-light` | `#01762F` (`brand.green/700`) | `Keyboard.appCtaLight` | the catalog's CTA in light: the one green button | +| `app/cta-text-dark` | `#1D1B16` (`brand.ink`) | `Keyboard.appCtaTextDark` | the catalog's CTAText in dark: ink on green, as the site | +| `app/cta-text-light` | `#FFFFFF` (`brand.white`) | `Keyboard.appCtaTextLight` | the catalog's CTAText in light | +| `app/muted-dark` | `#A5A4A2` (`brand.neutral/500`) | `Keyboard.appMutedDark` | the catalog's Muted in dark | +| `app/muted-light` | `#777673` (`brand.neutral/700`) | `Keyboard.appMutedLight` | the catalog's Muted in light: eyebrows, captions, secondary text | +| `app/page-dark` | `#1D1B16` (`brand.ink`) | `Keyboard.appPageDark` | the catalog's Page in dark: ink, the website's ground | +| `app/page-light` | `#FDFCF8` (`brand.paper/page`) | `Keyboard.appPageLight` | the catalog's Page in light: the design system's page | +| `app/text-dark` | `#F5F3EB` (`brand.paper/tint`) | `Keyboard.appTextDark` | the catalog's Text in dark | +| `app/text-light` | `#1D1B16` (`brand.ink`) | `Keyboard.appTextLight` | the catalog's Text in light | | `kb/cancel` | `#E67F36` (`brand.orange`) | `Keyboard.kbCancel` | the panel's cancel × | | `kb/field` | `#33302A` (`themes.dark/field`) | `Keyboard.kbField` | the key-term field | | `kb/field-border` | `#3A362F` (`themes.dark/field-border`) | `Keyboard.kbFieldBorder` | the field's hairline | @@ -309,155 +387,39 @@ theme's (ink) values, and the app's catalog colours. -Gradients: - -The default theme follows the host app's light or dark appearance, as the -iPhone keyboard does; Blurt's own themes are **fixed**, whatever the host -app's appearance, for the reason the Mac pill is: the keyboard floats over -whichever app the user is typing in and must read the same over a white Notes -page and a black Messages thread. Nothing on it uses `accent`. - -## Type - -System font throughout (SF Pro; the Figma file must have it installed, never -Inter). Sizes are fixed points, not Dynamic Type, as the system keyboard's are. - - - -| Token | Value | Swift | Use | -| -------------------- | ---------- | ----------------------------- | --------------------------------------------------------------------------------- | -| `ratio/voice-glyph` | `0.34` | `Typography.ratioVoiceGlyph` | the clipboard and exclamation glyphs, as a fraction of the voice element's height | -| `size/body` | `16` | `Typography.sizeBody` | the app's body text | -| `size/caption` | `14` | `Typography.sizeCaption` | the app's small text | -| `size/cta` | `14` | `Typography.sizeCta` | a mono button label in the app (E2) | -| `size/eyebrow` | `12` | `Typography.sizeEyebrow` | a mono eyebrow in the app (E1) | -| `size/glyph` | `17` | `Typography.sizeGlyph` | the +, × and ✓ | -| `size/label` | `12` | `Typography.sizeLabel` | the mono word labels on keys: 123, ABC, #+=, space, the return label | -| `size/legend` | `16` | `Typography.sizeLegend` | every other key | -| `size/letter` | `24` | `Typography.sizeLetter` | letter keys: the iPhone's (estimated from the l glyph, apple-geometry.json) | -| `size/popup` | `32` | `Typography.sizePopup` | the letter pop-up | -| `size/term` | `17` | `Typography.sizeTerm` | the key-term field | -| `size/title` | `34` | `Typography.sizeTitle` | the app's serif headline | -| `tracking/cta` | `1.4` | `Typography.trackingCta` | uppercase mono at 14: the brand's E2 tracking | -| `tracking/eyebrow` | `1.2` | `Typography.trackingEyebrow` | uppercase mono at 12: the brand's E1 tracking | -| `weight/glyph` | `medium` | `Typography.weightGlyph` | — | -| `weight/label` | `medium` | `Typography.weightLabel` | — | -| `weight/legend` | `medium` | `Typography.weightLegend` | — | -| `weight/letter` | `regular` | `Typography.weightLetter` | — | -| `weight/popup` | `regular` | `Typography.weightPopup` | — | -| `weight/term` | `regular` | `Typography.weightTerm` | — | -| `weight/voice-glyph` | `semibold` | `Typography.weightVoiceGlyph` | — | - - - -## Fonts (`Design/fonts/`, `DesignTokens.Fonts`) - -The brand's three faces, bundled in both targets and named by PostScript name -(what `Font.custom` takes). Letter keys stay in SF Pro; everything that is a -word label on the keyboard, and the app's eyebrows and buttons, is Modern -Gothic Mono in uppercase; the app's headlines are Oceanic Text, its body -UN 11ST. - - - -| Token | Value | Swift | Use | -| ----------------- | -------------------------- | ---------------------- | ----------------------------------------------- | -| `body/bold` | `UN-11ST-Bold` | `Fonts.bodyBold` | — | -| `body/family` | `UN-11 ST` | `Fonts.bodyFamily` | the app's body text | -| `body/regular` | `UN-11ST-Regular` | `Fonts.bodyRegular` | — | -| `heading/family` | `Oceanic Text` | `Fonts.headingFamily` | the app's serif headlines, sentence case, tight | -| `heading/regular` | `OceanicText-Regular` | `Fonts.headingRegular` | — | -| `mono/family` | `Modern Gothic Mono` | `Fonts.monoFamily` | eyebrows, CTAs, the keyboard's word labels | -| `mono/light` | `ModernGothicMono-Light` | `Fonts.monoLight` | — | -| `mono/medium` | `ModernGothicMono-Medium` | `Fonts.monoMedium` | — | -| `mono/regular` | `ModernGothicMono-Regular` | `Fonts.monoRegular` | — | - - - -## Components (`BlurtKeyboard/Sources/`) - -**Voice bar** (`VoiceBar.swift`) — the only place voice lives, and it has no -words and no glyph: the orb is the mic key, 40 pt in a 44 pt row where the -system keyboard puts its suggestion bar. The panel has it at 96 pt, centred -in the space above the keys; the slim bar has it between the globe and -delete. State is the orb's ring and colour, and the wave: - -| State | Orb | Haptic | -| ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | -| no Full Access / app not listening | dimmed (saturation 0.35, opacity 0.8); a tap opens Blurt | — | -| idle | the circle, ring still | — | -| connecting | ring 2 pt sweeping, as the app's orb does (one turn per 1.6 s) | — | -| recording | the orb dissipates (swells, blurs, fades; 0.7 s) into the thin wave, flat on the surface: 240 × 24 in the bar, 300 × 40 in the panel; the wave is the key | medium impact | -| processing | back to the circle, ring sweeping | light impact | -| pasted | green solid ring, 1.2 s | success | -| copied (no field) | green solid ring with a clipboard glyph, 2 s | success | -| error | orange solid ring with an exclamation mark, 2 s; the message on VoiceOver | error | - -Nothing snaps: the orb and the wave cross over 0.7 s, every other change on -the key (ring, glyph, dimming) over 0.5 s, and the term field swaps in over -0.4 s. Only the press answers at once. VoiceOver keeps the words: Dictate / Stop -dictation / Start Blurt on the key, and the error message. - -**Orb** (`BrandOrb.swift`) — the gradient disc with a hairline ring that sweeps -one turn per 1.6 s while something is happening, still otherwise. The disc -never moves. Under Reduce Motion the ring is drawn but holds still. - -**Meter** (`WaveformMeter` in `VoiceBar.swift`) — the Mac pill's bars, at -the pitch the caller sets: the keyboard and the home screen use `slimBar` / -`slimGap` (2 pt bars, 2 pt apart), the count from the width, heights from -`MeterBarRow(count:availableHeight:)` (the engine's envelope, gamma and idle -wave, so it cannot drift from the Mac's). The app publishes the level at -~12 Hz; the wave keeps the row alive between. The colour is the palette's -`signal` on the keyboard and `accent` on the home screen. - -**Mic key** (`MicKey` in `KeyboardViews.swift`) — the orb _is_ the key until -it dissipates into the wave, and then the wave is (`wave: CGSize?`; nil in -the Full Access row, where the orb stays). The key's frame is the wave's -width throughout so nothing shifts while the two cross; the touch shape is -the circle, then the wave's band. No glyph: the Mac's orb carries none and -neither does this. No glow, no shadow — matte. Ring 2 pt while working or -noticing, 1 pt otherwise. Pressed: scale 0.94, 0.1 s. -Finger down / up drive the engine's `DictationKeyGate`, so a tap latches and -a hold is push-to-talk exactly as on the Mac; a touch that travelled more -than 24 pt cancels instead (it was a swipe). Cancel is the orange × in the -panel's top-right corner while something is in flight. - -**Keys** (`KeyCap`, `LetterKey`) — 42 pt tall, radius 8, flat: `key` for -letters and space, `keyDark` for modifiers, `bare` for a glyph with no cap -(the panel's cancel); a key brightens 15 % while pressed rather than dimming. - -## Layouts and their heights (`KeyboardLayout.height`) - -Top and bottom margin 8 (`KeyboardRootView`); 11 between rows and 3 at the sides (`KeyboardPalette`). - -| Layout | Rows | Height | -| --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | -| `slimBar` | globe · voice bar · delete · return | 60 | -| `panel` | orb 96, centred (cancel in the top-right corner while in flight) · space row 42. A two-page carousel: a horizontal swipe in either direction, as often as you like, flips between the mic panel and the full keyboard; the page slides the way the finger went, the keyboard resizes with it, and it is back to the orb each time the keyboard appears. Keys ignore a touch that travelled more than 12 pt, the orb cancels one that travelled more than 24 pt. | 216, or 272 when flipped | -| `full` | voice bar 44 · three letter rows 42 · 123/globe/space/return 42; `8·2 + 44 + 4·11 + 4·42` | 272 | - -The globe key appears only when iOS says another keyboard is -installed (`needsInputModeSwitchKey`). - ## Metrics and motion -Every size, gap, radius, opacity and duration the keyboard's views use. The -heights in `KeyboardLayout.height` are derived from these (slim = 2 × -`margin/vertical` + `voicebar/height`; full adds 4 × `row/gap` + 4 × -`key/height`; the panel's is chosen), and `LayoutArithmeticTests` pins the -derivation. +Every size, gap, radius, opacity and duration the views use. The heights in +`KeyboardLayout.height` are derived from these, and `LayoutArithmeticTests` +pins the derivation. | Token | Points | Swift | Use | | ---------------------------- | --------- | ---------------------------------- | ---------------------------------------------------------------------------------------------- | | `addterm/inset` | `6` | `Metrics.addtermInset` | the + from the panel's corner | +| `app/button-height` | `40` | `Metrics.appButtonHeight` | the brand's button | +| `app/button-pad` | `12` | `Metrics.appButtonPad` | its side padding | +| `app/card-pad` | `16` | `Metrics.appCardPad` | inside a card | +| `app/chip-gap` | `8` | `Metrics.appChipGap` | between chips | +| `app/chip-pad-x` | `12` | `Metrics.appChipPadX` | a style chip's side padding | +| `app/chip-pad-y` | `8` | `Metrics.appChipPadY` | and its top and bottom | +| `app/header-height` | `44` | `Metrics.appHeaderHeight` | the home header: wordmark and gear | +| `app/hero-gap` | `14` | `Metrics.appHeroGap` | between the hero's pieces | +| `app/hero-pad` | `20` | `Metrics.appHeroPad` | inside the hero card | +| `app/icon` | `20` | `Metrics.appIcon` | the header's gear, the copy glyph | +| `app/line-gap` | `6` | `Metrics.appLineGap` | between lines of one thought | +| `app/page-pad` | `20` | `Metrics.appPagePad` | the screens' side padding | +| `app/preview-gap` | `8` | `Metrics.appPreviewGap` | between the theme card's two faces | +| `app/section-gap` | `24` | `Metrics.appSectionGap` | between the home screen's sections | +| `app/setup-number-width` | `24` | `Metrics.appSetupNumberWidth` | the setup steps' mono numerals | +| `app/stack-gap` | `12` | `Metrics.appStackGap` | between a section's eyebrow and its content, and between cards | | `card/border` | `1` | `Metrics.cardBorder` | the card's hairline | -| `card/radius` | `16` | `Metrics.cardRadius` | the app's cards | +| `card/radius` | `12` | `Metrics.cardRadius` | the app's cards (radius/card) | | `caret/height` | `20` | `Metrics.caretHeight` | — | | `caret/lead` | `1` | `Metrics.caretLead` | the caret's gap from the text | | `caret/radius` | `1` | `Metrics.caretRadius` | — | @@ -505,6 +467,7 @@ derivation. | `opacity/placeholder` | `0.4` | `Metrics.opacityPlaceholder` | the field's placeholder | | `opacity/popup-shadow` | `0.12` | `Metrics.opacityPopupShadow` | — | | `opacity/press-brighten` | `0.15` | `Metrics.opacityPressBrighten` | a key lightens this much while pressed | +| `opacity/pressed` | `0.85` | `Metrics.opacityPressed` | a brand button while pressed: a colour change, no lift | | `opacity/sheen` | `0.22` | `Metrics.opacitySheen` | the light passing over the element at rest: chrome catching light | | `opacity/surface-vignette` | `0` | `Metrics.opacitySurfaceVignette` | a soft darkening toward the surface's edges; 0 is none | | `opacity/term-cancel` | `0.7` | `Metrics.opacityTermCancel` | the field's × | @@ -557,7 +520,9 @@ derivation. -Motion, in seconds. Nothing springs or snaps; only the press answers at once. +Motion. Nothing springs or snaps; only the press answers at once. Colour and +fill changes ease over the brand's transition; everything else moves on the +house curve (`ease/signature`, `cubic-bezier(0.22, 1, 0.36, 1)`). @@ -581,20 +546,50 @@ Motion, in seconds. Nothing springs or snaps; only the press answers at once. -## Feedback +## The app's screens (`BlurtiOS/Sources/`) + +The Blurt landing page on a phone, in the phone's appearance: the page under +the brand's grain; the wordmark (tinted with the accent) and the gear across +the top; sections under mono eyebrows; serif headlines (Oceanic Text, 34), +body in UN 11ST (16, captions 14); cards with 12 pt corners and a 1 pt +hairline (the hero 16), no shadows; chips and buttons rectangular at 4 pt, +buttons 40 pt tall with their label in uppercase mono, one green button per +row (Cam's rule) and a hairline one beside it, a colour change on press and +never a lift. Glyphs are SF Symbols — the platform's — where the web brand +uses Material Symbols. + +**Home** (`HomeView`, `HomeHero`, `SetupCard`, `StyleChips`, `RecentSection`, +`HomeStatus` for the words): the setup card only while something is missing, +its three steps numbered `01 02 03` in mono; the hero — `STATUS`, the +headline (Not listening · Ready to dictate · Connecting… · Listening… · +Transcribing… · Pasted · Copied · the error), the line under it, the voice +element at home size, `START LISTENING` (refused without a key, with a line +saying so) or the hairline `STOP LISTENING`, and "Dictate here, to the +clipboard" as a text button; `STYLE` and the chips, the active one filled; +`RECENT` and the cards (three lines, the style as a green mono tag, the +time, a copy button); `POWERED BY ASSEMBLYAI`. + +**Settings** (`SettingsView`): a form on the page, its sections under +eyebrows — Keyboard (layout, theme, hands-free), Listening (the window), +Transcription (enhanced transcripts, output styles, key terms with the +contact-name count, sharing), Account (sign-in stub; the API key in debug +builds), About. The theme picker shows each theme's two faces side by side. +Styles, the import sheet and the key entry share the form's chrome +(`brandForm()`). + +`-BlurtSettings` opens Settings as the root for a screenshot; `xcrun simctl +ui booted appearance dark` before any capture for the dark appearance; +`-BlurtStartListening` opens the mic at launch. + +## Feedback and accessibility Haptics (`KeyboardModel.haptics`): medium impact on `recording`, light on the stop, `.success` on pasted/copied, `.error` on error — with no words on the -keyboard, they are half of the feedback. The DX7 start/stop cues -play in the app, not the keyboard (a keyboard plays audio only with Full -Access, and the app already owns the audio session). - -## Accessibility - -The mic key is a button labelled Dictate / Stop dictation / Start Blurt, and -speaks the error message; the meters are hidden from VoiceOver. Reduce -Motion stops the ring and the meter's idle wave; heights still follow the -level. +keyboard, they are half of the feedback. The DX7 start/stop cues play in the +app, not the keyboard. The mic control is a button labelled Dictate / Stop +dictation / Start Blurt and speaks the error message; the element itself is +hidden from VoiceOver. Reduce Motion stops the sheen and the glints; heights +still follow the level. ## The two processes, and every number @@ -613,50 +608,34 @@ notifications that carry nothing and just say "look" (`SharedState.swift`). | command retry | one re-signal after 600 ms with no phase change | a missed Darwin notification would leave the gate latched over nothing | | phase staleness | notices 3 s (max dwell 2 s + 1); in flight 130 s (the 120 s cap + 10) | the keyboard reads the snapshot on every appearance | | notice dwell | pasted 1.2 s; copied, error 2 s | the Mac's 0.8 / 1.6 s, a little longer with no hover | -| press delay on the orb | 90 ms | a swipe that starts on the orb never starts a dictation it must then cancel | -| tap travel | 12 pt (keys), 24 pt (orb), swipe ≥ 48 pt horizontal and 1.5× the vertical | the carousel's swipe never types or dictates | -| level publish | every 80 ms while recording | the orb's meter, off the capture path's back | +| press delay on the mic | 90 ms | a swipe that starts on the key never starts a dictation it must then cancel | +| tap travel | 12 pt (keys), 24 pt (mic), swipe ≥ 48 pt horizontal and 1.5× the vertical | the carousel's swipe never types or dictates | +| level publish | every 80 ms while recording | the element's meter, off the capture path's back | | lexicon refresh | hourly | thousands of contacts on a keyboard memory budget | | height change | 0.25 s; constraint priority 999 | iOS honours a keyboard's height at just under required | | the visual numbers | see Metrics and motion above | generated from `Design/tokens.json`; the views carry no literals | | term packs | ≤ 64 KB, ≤ 100 terms, ≤ 80 characters each | the request's cap; unbounded input from a stranger | Tests pin the rules that can be pinned (`BlurtiOSTests`: the contract, the -gate, results, the term field, the feed, the layout arithmetic); anything -that gains a number here should gain a line there. +gate, results, the term field, the feed, the layout arithmetic, Apple's +geometry, the interaction rules, the voice state, the home's words, the +fonts, the tokens); anything that gains a number here should gain a line +there. -## The app's screens (`BlurtiOS/Sources/`) +## Where Blurt diverges from the brand system, on purpose -Appearance-adaptive, unlike the keyboard: `accent` (the catalog's -`AccentColor`, `green` in light and `greenOnDark` in dark), `cardFill` / -`cardBorder` (the Mac's card, `#EBE8E8` on `#DEDBDB` light, `#26231E` on -`#3A362F` dark, 16 pt corners, 1 pt hairline), system grouped background, -system fonts. The Mac's Icon Composer icon and its ready-screen wordmark are -shared, not copied (`project.yml`). - -**Home** (`HomeView.swift`) — the Mac's ready screen, stacked for a phone: - -| Piece | What | -| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Bar | the wordmark (tinted accent, 22 pt tall) centred; the gear → Settings | -| Setup card | only while something is missing: sign in (stub; debug builds take a key), microphone, keyboard + Full Access | -| Hero card | the orb, 112 pt, ring 2 pt sweeping while the mic is open or a dictation is in flight, dissipating into the thin wave (280 × 44) while recording as the keyboard's key does; a title2 line (Not listening · Ready to dictate · Connecting… · Listening… · Transcribing… · Pasted · Copied · the error) and a callout under it; **Start listening** (prominent; refused without a key, with a line saying so) or **Stop listening** (bordered, destructive; cancels a dictation in flight before closing, so nothing is transcribed for nobody); "Dictate here, to the clipboard" as a text button | -| Style | chips: Default and each profile, the active one filled with the accent; Edit → the styles editor | -| Recent | cards: three lines of text, the style as a tinted capsule, the relative time, a copy button; an empty-state card | -| Footer | "Powered by AssemblyAI", caption | - -**Settings** (`SettingsView.swift`) — a sheet, grouped as the Mac's: Keyboard -(layout, theme, hands-free), Listening (the window), Transcription (enhanced -transcripts, output styles, key terms with the contact-name count), Account -(sign-in stub; the API key in debug builds), About (version, GitHub, Powered -by AssemblyAI). - -Screenshots: `scripts/ios-sim.sh --screenshot home.png` for the resting -screen; `BLURT_LAUNCH_ARGS=-BlurtStartListening` opens the mic at launch for -the listening state (debug builds); `xcrun simctl ui booted appearance dark` -before either for dark mode. +- Green is the UI signal (the system says cobolt-only): Cam's rule for the + collab brand — inside the Assembly palette, off primary cobolt. Cobolt and + its violets appear only as light: the glint's fringe, the streak's tips. +- SF Pro for the letter keys and SF Symbols for every glyph (the web uses + Material Symbols): a keyboard has to be native under the fingers. +- The keys' corners are the iPhone's (8), not the brand's 4: Apple's exact + geometry wins on the keyboard; the brand's radii hold everywhere else. ## Next -Onboarding as a stepped flow once sign-in exists; the keyboard's autocorrect -and suggestion bar; the app's cues and haptics on the phase edges. +The pick between a, b and c; the losers and the `-BlurtGalleryVoice` switch +go, and the winner's tokens lose their prefix. Then: the keyboard's autocorrect +and suggestion bar; onboarding as a stepped flow once sign-in exists; the +app's cues on the phase edges; the curated themes as brand value sets; the +Figma file rebuilt from the tokens. diff --git a/App/BlurtiOS/Design/figma/tokens.js b/App/BlurtiOS/Design/figma/tokens.js index 317e1ea3..320b43f8 100644 --- a/App/BlurtiOS/Design/figma/tokens.js +++ b/App/BlurtiOS/Design/figma/tokens.js @@ -61,6 +61,16 @@ Keyboard|app/card-border-dark|COLOR|#3A362F|Brand:ink/600|STROKE_COLOR|DesignTok Keyboard|app/card-border-light|COLOR|#C7C3B2|Brand:paper/400|STROKE_COLOR|DesignTokens.Keyboard.appCardBorderLight|the catalog's CardBorder in light Keyboard|app/card-fill-dark|COLOR|#26231E|Brand:ink/800|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.appCardFillDark|the catalog's CardFill in dark Keyboard|app/card-fill-light|COLOR|#F5F3EB|Brand:paper/tint|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.appCardFillLight|the catalog's CardFill in light +Keyboard|app/cta-dark|COLOR|#67AD82|Brand:green/400|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.appCtaDark|the catalog's CTA in dark: the site's button green +Keyboard|app/cta-light|COLOR|#01762F|Brand:green/700|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.appCtaLight|the catalog's CTA in light: the one green button +Keyboard|app/cta-text-dark|COLOR|#1D1B16|Brand:ink|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.appCtaTextDark|the catalog's CTAText in dark: ink on green, as the site +Keyboard|app/cta-text-light|COLOR|#FFFFFF|Brand:white|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.appCtaTextLight|the catalog's CTAText in light +Keyboard|app/muted-dark|COLOR|#A5A4A2|Brand:neutral/500|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.appMutedDark|the catalog's Muted in dark +Keyboard|app/muted-light|COLOR|#777673|Brand:neutral/700|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.appMutedLight|the catalog's Muted in light: eyebrows, captions, secondary text +Keyboard|app/page-dark|COLOR|#1D1B16|Brand:ink|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.appPageDark|the catalog's Page in dark: ink, the website's ground +Keyboard|app/page-light|COLOR|#FDFCF8|Brand:paper/page|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.appPageLight|the catalog's Page in light: the design system's page +Keyboard|app/text-dark|COLOR|#F5F3EB|Brand:paper/tint|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.appTextDark|the catalog's Text in dark +Keyboard|app/text-light|COLOR|#1D1B16|Brand:ink|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.appTextLight|the catalog's Text in light Keyboard|kb/cancel|COLOR|#E67F36|Brand:orange|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.kbCancel|the panel's cancel × Keyboard|kb/field|COLOR|#33302A|Themes:dark/field|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.kbField|the key-term field Keyboard|kb/field-border|COLOR|#3A362F|Themes:dark/field-border|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.kbFieldBorder|the field's hairline @@ -74,8 +84,24 @@ Keyboard|kb/popup|COLOR|#33302A|Themes:dark/popup|FRAME_FILL,SHAPE_FILL|DesignTo Keyboard|kb/signal|COLOR|#67AD82|Themes:dark/signal|SHAPE_FILL,TEXT_FILL|DesignTokens.Keyboard.kbSignal|the wave, the caret, the saved check Keyboard|kb/surface|COLOR|#1D1B16|Themes:dark/surface|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.kbSurface|the design face's surface (Figma binds to kb/*; Swift reads the palette) Metrics|addterm/inset|FLOAT|6||GAP|DesignTokens.Metrics.addtermInset|the + from the panel's corner +Metrics|app/button-height|FLOAT|40||WIDTH_HEIGHT|DesignTokens.Metrics.appButtonHeight|the brand's button +Metrics|app/button-pad|FLOAT|12||WIDTH_HEIGHT|DesignTokens.Metrics.appButtonPad|its side padding +Metrics|app/card-pad|FLOAT|16||WIDTH_HEIGHT|DesignTokens.Metrics.appCardPad|inside a card +Metrics|app/chip-gap|FLOAT|8||GAP|DesignTokens.Metrics.appChipGap|between chips +Metrics|app/chip-pad-x|FLOAT|12||WIDTH_HEIGHT|DesignTokens.Metrics.appChipPadX|a style chip's side padding +Metrics|app/chip-pad-y|FLOAT|8||WIDTH_HEIGHT|DesignTokens.Metrics.appChipPadY|and its top and bottom +Metrics|app/header-height|FLOAT|44||WIDTH_HEIGHT|DesignTokens.Metrics.appHeaderHeight|the home header: wordmark and gear +Metrics|app/hero-gap|FLOAT|14||GAP|DesignTokens.Metrics.appHeroGap|between the hero's pieces +Metrics|app/hero-pad|FLOAT|20||WIDTH_HEIGHT|DesignTokens.Metrics.appHeroPad|inside the hero card +Metrics|app/icon|FLOAT|20||WIDTH_HEIGHT|DesignTokens.Metrics.appIcon|the header's gear, the copy glyph +Metrics|app/line-gap|FLOAT|6||GAP|DesignTokens.Metrics.appLineGap|between lines of one thought +Metrics|app/page-pad|FLOAT|20||WIDTH_HEIGHT|DesignTokens.Metrics.appPagePad|the screens' side padding +Metrics|app/preview-gap|FLOAT|8||GAP|DesignTokens.Metrics.appPreviewGap|between the theme card's two faces +Metrics|app/section-gap|FLOAT|24||GAP|DesignTokens.Metrics.appSectionGap|between the home screen's sections +Metrics|app/setup-number-width|FLOAT|24||WIDTH_HEIGHT|DesignTokens.Metrics.appSetupNumberWidth|the setup steps' mono numerals +Metrics|app/stack-gap|FLOAT|12||GAP|DesignTokens.Metrics.appStackGap|between a section's eyebrow and its content, and between cards Metrics|card/border|FLOAT|1||STROKE_FLOAT,WIDTH_HEIGHT|DesignTokens.Metrics.cardBorder|the card's hairline -Metrics|card/radius|FLOAT|16||CORNER_RADIUS|DesignTokens.Metrics.cardRadius|the app's cards +Metrics|card/radius|FLOAT|12||CORNER_RADIUS|DesignTokens.Metrics.cardRadius|the app's cards (radius/card) Metrics|caret/height|FLOAT|20||WIDTH_HEIGHT|DesignTokens.Metrics.caretHeight| Metrics|caret/lead|FLOAT|1||GAP|DesignTokens.Metrics.caretLead|the caret's gap from the text Metrics|caret/radius|FLOAT|1||CORNER_RADIUS|DesignTokens.Metrics.caretRadius| @@ -123,6 +149,7 @@ Metrics|opacity/off|FLOAT|0.45||OPACITY|DesignTokens.Metrics.opacityOff|the elem Metrics|opacity/placeholder|FLOAT|0.4||OPACITY|DesignTokens.Metrics.opacityPlaceholder|the field's placeholder Metrics|opacity/popup-shadow|FLOAT|0.12||OPACITY|DesignTokens.Metrics.opacityPopupShadow| Metrics|opacity/press-brighten|FLOAT|0.15||OPACITY|DesignTokens.Metrics.opacityPressBrighten|a key lightens this much while pressed +Metrics|opacity/pressed|FLOAT|0.85||OPACITY|DesignTokens.Metrics.opacityPressed|a brand button while pressed: a colour change, no lift Metrics|opacity/sheen|FLOAT|0.22||OPACITY|DesignTokens.Metrics.opacitySheen|the light passing over the element at rest: chrome catching light Metrics|opacity/surface-vignette|FLOAT|0||OPACITY|DesignTokens.Metrics.opacitySurfaceVignette|a soft darkening toward the surface's edges; 0 is none Metrics|opacity/term-cancel|FLOAT|0.7||OPACITY|DesignTokens.Metrics.opacityTermCancel|the field's × diff --git a/App/BlurtiOS/Design/tokens.json b/App/BlurtiOS/Design/tokens.json index aa2e4015..06a7b2ac 100644 --- a/App/BlurtiOS/Design/tokens.json +++ b/App/BlurtiOS/Design/tokens.json @@ -231,6 +231,46 @@ "kb/field-border": { "value": "{themes.dark/field-border}", "use": "the field's hairline" + }, + "app/page-light": { + "value": "{brand.paper/page}", + "use": "the catalog's Page in light: the design system's page" + }, + "app/page-dark": { + "value": "{brand.ink}", + "use": "the catalog's Page in dark: ink, the website's ground" + }, + "app/text-light": { + "value": "{brand.ink}", + "use": "the catalog's Text in light" + }, + "app/text-dark": { + "value": "{brand.paper/tint}", + "use": "the catalog's Text in dark" + }, + "app/muted-light": { + "value": "{brand.neutral/700}", + "use": "the catalog's Muted in light: eyebrows, captions, secondary text" + }, + "app/muted-dark": { + "value": "{brand.neutral/500}", + "use": "the catalog's Muted in dark" + }, + "app/cta-light": { + "value": "{brand.green/700}", + "use": "the catalog's CTA in light: the one green button" + }, + "app/cta-dark": { + "value": "{brand.green/400}", + "use": "the catalog's CTA in dark: the site's button green" + }, + "app/cta-text-light": { + "value": "{brand.white}", + "use": "the catalog's CTAText in light" + }, + "app/cta-text-dark": { + "value": "{brand.ink}", + "use": "the catalog's CTAText in dark: ink on green, as the site" } }, "gradients": {}, @@ -371,8 +411,8 @@ "use": "the + from the panel's corner" }, "card/radius": { - "value": 16, - "use": "the app's cards" + "value": 12, + "use": "the app's cards (radius/card)" }, "card/border": { "value": 1, @@ -611,6 +651,74 @@ "key/pad": { "value": 4, "use": "a legend's side padding on a min-width key" + }, + "app/page-pad": { + "value": 20, + "use": "the screens' side padding" + }, + "app/header-height": { + "value": 44, + "use": "the home header: wordmark and gear" + }, + "app/section-gap": { + "value": 24, + "use": "between the home screen's sections" + }, + "app/stack-gap": { + "value": 12, + "use": "between a section's eyebrow and its content, and between cards" + }, + "app/line-gap": { + "value": 6, + "use": "between lines of one thought" + }, + "app/card-pad": { + "value": 16, + "use": "inside a card" + }, + "app/hero-pad": { + "value": 20, + "use": "inside the hero card" + }, + "app/hero-gap": { + "value": 14, + "use": "between the hero's pieces" + }, + "app/button-height": { + "value": 40, + "use": "the brand's button" + }, + "app/button-pad": { + "value": 12, + "use": "its side padding" + }, + "app/chip-pad-x": { + "value": 12, + "use": "a style chip's side padding" + }, + "app/chip-pad-y": { + "value": 8, + "use": "and its top and bottom" + }, + "app/chip-gap": { + "value": 8, + "use": "between chips" + }, + "app/icon": { + "value": 20, + "use": "the header's gear, the copy glyph" + }, + "app/setup-number-width": { + "value": 24, + "use": "the setup steps' mono numerals" + }, + "app/preview-gap": { + "value": 8, + "use": "between the theme card's two faces" + }, + "opacity/pressed": { + "value": 0.85, + "use": "a brand button while pressed: a colour change, no lift" } }, "type": { diff --git a/App/BlurtiOS/Shared/BlurtType.swift b/App/BlurtiOS/Shared/BlurtType.swift index 13de78e8..c61d2e25 100644 --- a/App/BlurtiOS/Shared/BlurtType.swift +++ b/App/BlurtiOS/Shared/BlurtType.swift @@ -22,6 +22,14 @@ enum BlurtType { Font.custom(monoName(weight), fixedSize: size) } + /// Oceanic Text: the app's serif headlines, sentence case, tight. + nonisolated static func heading(_ size: CGFloat) -> Font { Font.custom(Fonts.headingRegular, fixedSize: size) } + + /// UN 11ST: the app's body text. + nonisolated static func body(_ size: CGFloat, bold: Bool = false) -> Font { + Font.custom(bold ? Fonts.bodyBold : Fonts.bodyRegular, fixedSize: size) + } + private nonisolated static func monoName(_ weight: MonoWeight) -> String { switch weight { case .light: Fonts.monoLight diff --git a/App/BlurtiOS/Shared/DesignTokens.swift b/App/BlurtiOS/Shared/DesignTokens.swift index d17dc408..82c6a56c 100644 --- a/App/BlurtiOS/Shared/DesignTokens.swift +++ b/App/BlurtiOS/Shared/DesignTokens.swift @@ -134,6 +134,26 @@ enum DesignTokens { nonisolated static let appCardFillDark: Color = Brand.ink800 /// The catalog's CardFill in light. nonisolated static let appCardFillLight: Color = Brand.paperTint + /// The catalog's CTA in dark: the site's button green. + nonisolated static let appCtaDark: Color = Brand.green400 + /// The catalog's CTA in light: the one green button. + nonisolated static let appCtaLight: Color = Brand.green700 + /// The catalog's CTAText in dark: ink on green, as the site. + nonisolated static let appCtaTextDark: Color = Brand.ink + /// The catalog's CTAText in light. + nonisolated static let appCtaTextLight: Color = Brand.white + /// The catalog's Muted in dark. + nonisolated static let appMutedDark: Color = Brand.neutral500 + /// The catalog's Muted in light: eyebrows, captions, secondary text. + nonisolated static let appMutedLight: Color = Brand.neutral700 + /// The catalog's Page in dark: ink, the website's ground. + nonisolated static let appPageDark: Color = Brand.ink + /// The catalog's Page in light: the design system's page. + nonisolated static let appPageLight: Color = Brand.paperPage + /// The catalog's Text in dark. + nonisolated static let appTextDark: Color = Brand.paperTint + /// The catalog's Text in light. + nonisolated static let appTextLight: Color = Brand.ink /// The panel's cancel ×. nonisolated static let kbCancel: Color = Brand.orange /// The key-term field. @@ -163,10 +183,42 @@ enum DesignTokens { enum Metrics { /// The + from the panel's corner. nonisolated static let addtermInset: CGFloat = 6 + /// The brand's button. + nonisolated static let appButtonHeight: CGFloat = 40 + /// Its side padding. + nonisolated static let appButtonPad: CGFloat = 12 + /// Inside a card. + nonisolated static let appCardPad: CGFloat = 16 + /// Between chips. + nonisolated static let appChipGap: CGFloat = 8 + /// A style chip's side padding. + nonisolated static let appChipPadX: CGFloat = 12 + /// And its top and bottom. + nonisolated static let appChipPadY: CGFloat = 8 + /// The home header: wordmark and gear. + nonisolated static let appHeaderHeight: CGFloat = 44 + /// Between the hero's pieces. + nonisolated static let appHeroGap: CGFloat = 14 + /// Inside the hero card. + nonisolated static let appHeroPad: CGFloat = 20 + /// The header's gear, the copy glyph. + nonisolated static let appIcon: CGFloat = 20 + /// Between lines of one thought. + nonisolated static let appLineGap: CGFloat = 6 + /// The screens' side padding. + nonisolated static let appPagePad: CGFloat = 20 + /// Between the theme card's two faces. + nonisolated static let appPreviewGap: CGFloat = 8 + /// Between the home screen's sections. + nonisolated static let appSectionGap: CGFloat = 24 + /// The setup steps' mono numerals. + nonisolated static let appSetupNumberWidth: CGFloat = 24 + /// Between a section's eyebrow and its content, and between cards. + nonisolated static let appStackGap: CGFloat = 12 /// The card's hairline. nonisolated static let cardBorder: CGFloat = 1 - /// The app's cards. - nonisolated static let cardRadius: CGFloat = 16 + /// The app's cards (radius/card). + nonisolated static let cardRadius: CGFloat = 12 nonisolated static let caretHeight: CGFloat = 20 /// The caret's gap from the text. nonisolated static let caretLead: CGFloat = 1 @@ -253,6 +305,8 @@ enum DesignTokens { nonisolated static let opacityPopupShadow: CGFloat = 0.12 /// A key lightens this much while pressed. nonisolated static let opacityPressBrighten: CGFloat = 0.15 + /// A brand button while pressed: a colour change, no lift. + nonisolated static let opacityPressed: CGFloat = 0.85 /// The light passing over the element at rest: chrome catching light. nonisolated static let opacitySheen: CGFloat = 0.22 /// A soft darkening toward the surface's edges; 0 is none. @@ -494,6 +548,16 @@ enum DesignTokens { "keyboard.app/card-border-light": "#C7C3B2", "keyboard.app/card-fill-dark": "#26231E", "keyboard.app/card-fill-light": "#F5F3EB", + "keyboard.app/cta-dark": "#67AD82", + "keyboard.app/cta-light": "#01762F", + "keyboard.app/cta-text-dark": "#1D1B16", + "keyboard.app/cta-text-light": "#FFFFFF", + "keyboard.app/muted-dark": "#A5A4A2", + "keyboard.app/muted-light": "#777673", + "keyboard.app/page-dark": "#1D1B16", + "keyboard.app/page-light": "#FDFCF8", + "keyboard.app/text-dark": "#F5F3EB", + "keyboard.app/text-light": "#1D1B16", "keyboard.kb/cancel": "#E67F36", "keyboard.kb/field": "#33302A", "keyboard.kb/field-border": "#3A362F", @@ -507,8 +571,24 @@ enum DesignTokens { "keyboard.kb/signal": "#67AD82", "keyboard.kb/surface": "#1D1B16", "metrics.addterm/inset": "6", + "metrics.app/button-height": "40", + "metrics.app/button-pad": "12", + "metrics.app/card-pad": "16", + "metrics.app/chip-gap": "8", + "metrics.app/chip-pad-x": "12", + "metrics.app/chip-pad-y": "8", + "metrics.app/header-height": "44", + "metrics.app/hero-gap": "14", + "metrics.app/hero-pad": "20", + "metrics.app/icon": "20", + "metrics.app/line-gap": "6", + "metrics.app/page-pad": "20", + "metrics.app/preview-gap": "8", + "metrics.app/section-gap": "24", + "metrics.app/setup-number-width": "24", + "metrics.app/stack-gap": "12", "metrics.card/border": "1", - "metrics.card/radius": "16", + "metrics.card/radius": "12", "metrics.caret/height": "20", "metrics.caret/lead": "1", "metrics.caret/radius": "1", @@ -556,6 +636,7 @@ enum DesignTokens { "metrics.opacity/placeholder": "0.4", "metrics.opacity/popup-shadow": "0.12", "metrics.opacity/press-brighten": "0.15", + "metrics.opacity/pressed": "0.85", "metrics.opacity/sheen": "0.22", "metrics.opacity/surface-vignette": "0", "metrics.opacity/term-cancel": "0.7", diff --git a/scripts/design-sync.sh b/scripts/design-sync.sh index e128152a..fd96f5cc 100755 --- a/scripts/design-sync.sh +++ b/scripts/design-sync.sh @@ -41,6 +41,11 @@ OUTPUTS=( App/BlurtiOS/BlurtiOS/Assets.xcassets/AccentColor.colorset/Contents.json App/BlurtiOS/BlurtiOS/Assets.xcassets/CardFill.colorset/Contents.json App/BlurtiOS/BlurtiOS/Assets.xcassets/CardBorder.colorset/Contents.json + App/BlurtiOS/BlurtiOS/Assets.xcassets/Page.colorset/Contents.json + App/BlurtiOS/BlurtiOS/Assets.xcassets/Text.colorset/Contents.json + App/BlurtiOS/BlurtiOS/Assets.xcassets/Muted.colorset/Contents.json + App/BlurtiOS/BlurtiOS/Assets.xcassets/CTA.colorset/Contents.json + App/BlurtiOS/BlurtiOS/Assets.xcassets/CTAText.colorset/Contents.json App/BlurtiOS/Design/figma/tokens.js ) @@ -58,8 +63,8 @@ format_outputs() { fi } -# The design-literal lint. Scope: every file under the keyboard's sources -# that draws — new views are linted by default — minus the logic (the model, +# The design-literal lint. Scope: every file under the keyboard's and the +# app's sources that draws — new views are linted by default — minus the logic (the model, # the host controller, the palette, the geometry and interaction rules, the # voice state) and Grain.swift, whose body is the grain's recipe (density, # the two shades), with only its opacity as a token. Numbers 0 and 1 pass: `Spacer(minLength: 0)`, @@ -72,9 +77,15 @@ exempt = { "KeyboardViewController.swift", "KeyboardPalette.swift", "KeyGeometry.swift", "KeyboardInteraction.swift", "VoiceState.swift", "KeyboardMotion.swift", "MotionHeld.swift", "Grain.swift", } +app_exempt = { + "BlurtiOSApp.swift", "DictationCoordinator.swift", "ListeningWindow.swift", "ListeningSource.swift", + "AudioSource.swift", "SimulatorAudioSource.swift", "KeyboardRelayInjector.swift", "APIKeyModel.swift", + "TermPack.swift", "HomeStatus.swift", "KeyboardGalleryView.swift", "KeyboardProbeView.swift", +} files = sorted( - path for path in glob.glob("App/BlurtiOS/BlurtKeyboard/Sources/**/*.swift", recursive=True) - if os.path.basename(path) not in exempt + [path for path in glob.glob("App/BlurtiOS/BlurtKeyboard/Sources/**/*.swift", recursive=True) + if os.path.basename(path) not in exempt] + + [path for path in glob.glob("App/BlurtiOS/BlurtiOS/Sources/*.swift") if os.path.basename(path) not in app_exempt] ) modifiers = re.compile( r"\.(padding|frame|font|blur|scaleEffect|offset|shadow|opacity|cornerRadius|saturation|brightness" diff --git a/scripts/design-tokens.swift b/scripts/design-tokens.swift index 885a201d..4ac75dea 100755 --- a/scripts/design-tokens.swift +++ b/scripts/design-tokens.swift @@ -425,6 +425,11 @@ let colorSets: [(String, String, String)] = [ ("AccentColor", "keyboard.app/accent-light", "keyboard.app/accent-dark"), ("CardFill", "keyboard.app/card-fill-light", "keyboard.app/card-fill-dark"), ("CardBorder", "keyboard.app/card-border-light", "keyboard.app/card-border-dark"), + ("Page", "keyboard.app/page-light", "keyboard.app/page-dark"), + ("Text", "keyboard.app/text-light", "keyboard.app/text-dark"), + ("Muted", "keyboard.app/muted-light", "keyboard.app/muted-dark"), + ("CTA", "keyboard.app/cta-light", "keyboard.app/cta-dark"), + ("CTAText", "keyboard.app/cta-text-light", "keyboard.app/cta-text-dark"), ] // MARK: - Figma From 6c1d2cda171b34661e909b39f29f5e111866b07e Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Tue, 29 Sep 2026 19:20:47 -0400 Subject: [PATCH 56/79] Keyboard: a temporary switch between the three mic concepts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Settings → Keyboard → Mic (Grille / Ribs / Streak) writes `SharedStore.voiceElementKind` to the App Group; the keyboard reads it on every appearance, the home screen's hero follows it live, so each concept can be tried in real use — in any app, with the real phases and the real level — before one is chosen. The gallery's `-BlurtGalleryVoice` sets the same value on its rows. Marked TEMPORARY at every site: the switch, the two losers and the launch argument go together once the direction is picked. 73 tests; periphery clean. Co-Authored-By: Claude Fable 5.1 --- .../BlurtKeyboard/Sources/KeyboardModel.swift | 6 ++++++ .../Sources/KeyboardRootView.swift | 1 + App/BlurtiOS/BlurtiOS/Sources/HomeView.swift | 5 +++++ .../BlurtiOS/Sources/KeyboardGalleryView.swift | 18 ++++++++---------- .../BlurtiOS/Sources/SettingsView.swift | 11 +++++++++++ .../BlurtiOSTests/FeedAndLayoutTests.swift | 6 +++--- .../BlurtiOSTests/SharedStateTests.swift | 14 ++++++++++++++ App/BlurtiOS/DESIGN.md | 5 +++++ App/BlurtiOS/Shared/SharedState.swift | 11 +++++++++++ 9 files changed, 64 insertions(+), 13 deletions(-) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift index dac0d070..542b09cc 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift @@ -90,6 +90,11 @@ final class KeyboardModel { var palette: KeyboardPalette { paletteOverride ?? .resolve(themeID, dark: isDark) } var themeID = SharedStore.themeID var paletteOverride: KeyboardPalette? + /// TEMPORARY: which mic concept draws, from Settings — or, for a preview + /// or a gallery row, whatever it is told. Goes with the losers. + var voiceKind: VoiceElementKind { voiceKindOverride ?? storedVoiceKind } + var storedVoiceKind = SharedStore.voiceElementKind + var voiceKindOverride: VoiceElementKind? /// Whether the app being typed in wants a dark keyboard: what its field /// asks for, else the app's own light or dark appearance. var isDark = false @@ -156,6 +161,7 @@ final class KeyboardModel { guard hasFullAccess else { return } layout = SharedStore.layout themeID = SharedStore.themeID + storedVoiceKind = SharedStore.voiceElementKind SharedStore.keyboardEverSeen = true refresh(haptics: false) startHeartbeat() diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardRootView.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardRootView.swift index d0d33a1e..49dea28c 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardRootView.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardRootView.swift @@ -37,6 +37,7 @@ struct KeyboardRootView: View { .overlay { SurfaceFinish.Grain() } .clipped() .environment(\.keyboardPalette, model.palette) + .environment(\.voiceElementKind, model.voiceKind) .simultaneousGesture(swipe, including: model.layout == .panel ? .all : .subviews) .animation(reduceMotion ? nil : .easeInOut(duration: DesignTokens.Motion.flip), value: model.panelShowsKeys) .onAppear { diff --git a/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift b/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift index ba4d7151..be65377c 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift @@ -16,6 +16,10 @@ struct HomeView: View { @State private var showsSettings = false /// When the last dictation's words landed — the hero's glint. @State private var landedAt: Date? + /// TEMPORARY: the mic concept from Settings, so the hero shows the one + /// the keyboard will. Goes with the losers. + @AppStorage(BlurtShared.Key.voiceElement, store: SharedStore.defaults) private var voiceRaw = + VoiceElementKind.shipped.rawValue private var status: HomeStatus { HomeStatus( @@ -43,6 +47,7 @@ struct HomeView: View { .padding(.bottom, DesignTokens.Metrics.appSectionGap) } .page() + .environment(\.voiceElementKind, VoiceElementKind(rawValue: voiceRaw) ?? .shipped) .toolbar(.hidden, for: .navigationBar) .sheet(isPresented: $showsKeyEntry) { KeyEntryView(apiKey: coordinator.apiKey) } .sheet(isPresented: $showsSettings) { SettingsView(coordinator: coordinator) } diff --git a/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift b/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift index d9770749..8ce09933 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift @@ -46,13 +46,8 @@ var still = false /// One row, no caption, a registration border round the keyboard. var bare = false - /// Which mic concept draws. - var voice = VoiceElementKind.shipped - static func parse(_ arguments: [String]) -> Options { - Options( - still: arguments.contains("-BlurtGalleryStill"), bare: arguments.contains("-BlurtGalleryBare"), - voice: VoiceElementKind.parse(arguments) ?? .shipped) + Options(still: arguments.contains("-BlurtGalleryStill"), bare: arguments.contains("-BlurtGalleryBare")) } } @@ -100,7 +95,6 @@ .frame(height: row.model.effectiveLayout.height) .clipped() .environment(\.keyboardMotionHeld, options.still) - .environment(\.voiceElementKind, options.voice) } /// The rows named by the launch arguments; empty when they don't ask for @@ -111,10 +105,11 @@ else { return [] } // The theme is the next word unless it is a switch. let theme = arguments.count > flag + 3 && !arguments[flag + 3].hasPrefix("-") ? arguments[flag + 3] : "light" + let voice = VoiceElementKind.parse(arguments) ?? .shipped return arguments[flag + 2].split(separator: ",").map { name in Row( - caption: "\(layout.rawValue) · \(name) · \(theme)", - model: model(layout: layout, state: String(name), theme: theme)) + caption: "\(layout.rawValue) · \(name) · \(theme) · \(voice.rawValue)", + model: model(layout: layout, state: String(name), theme: theme, voice: voice)) } } @@ -128,9 +123,12 @@ "copied": .copied, "error": .error, "landed": .pasted, ] - private static func model(layout: KeyboardLayout, state: String, theme: String) -> KeyboardModel { + private static func model( + layout: KeyboardLayout, state: String, theme: String, voice: VoiceElementKind + ) -> KeyboardModel { let model = KeyboardModel() model.layout = layout + model.voiceKindOverride = voice model.paletteOverride = .resolve(KeyboardPalette.brandID, dark: Self.darkFaces.contains(theme)) // `keys` shows the panel's carousel flipped to its keyboard page; // `term` the voice bar as the key-term field, mid-typing. diff --git a/App/BlurtiOS/BlurtiOS/Sources/SettingsView.swift b/App/BlurtiOS/BlurtiOS/Sources/SettingsView.swift index 042f1d33..17bf445b 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/SettingsView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/SettingsView.swift @@ -12,6 +12,9 @@ struct SettingsView: View { @State private var autoDictate = SharedStore.autoDictate @State private var windowMinutes = SharedStore.windowMinutes @AppStorage(BlurtShared.Key.theme, store: SharedStore.defaults) private var themeID = "system" + /// TEMPORARY: which mic concept to try. Goes with the losers. + @AppStorage(BlurtShared.Key.voiceElement, store: SharedStore.defaults) private var voiceRaw = + VoiceElementKind.shipped.rawValue @State private var showsKeyEntry = false @AppStorage(SharedStore.keyTermsKey, store: SharedStore.defaults) private var keyTerms = "" @AppStorage(EnhancedTranscriptsStore.defaultsKey) private var enhancedTranscripts = @@ -52,11 +55,19 @@ struct SettingsView: View { } Toggle("Hands-free", isOn: $autoDictate) .onChange(of: autoDictate) { _, value in SharedStore.autoDictate = value } + // TEMPORARY: the three mic concepts, to try each in use. Goes with the losers. + Picker("Mic", selection: $voiceRaw) { + Text("Grille").tag(VoiceElementKind.grille.rawValue) + Text("Ribs").tag(VoiceElementKind.ribs.rawValue) + Text("Streak").tag(VoiceElementKind.streak.rawValue) + } + .pickerStyle(.segmented) } header: { Eyebrow("Keyboard") } footer: { Text( "Hands-free starts dictating the moment the Blurt keyboard comes up in a text field; tap the mic to stop. " + + "Mic is a temporary switch between the three concepts while one is chosen. " + "The keyboard picks up changes the next time it appears.") } } diff --git a/App/BlurtiOS/BlurtiOSTests/FeedAndLayoutTests.swift b/App/BlurtiOS/BlurtiOSTests/FeedAndLayoutTests.swift index 11ded56e..4c929676 100644 --- a/App/BlurtiOS/BlurtiOSTests/FeedAndLayoutTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/FeedAndLayoutTests.swift @@ -71,9 +71,9 @@ struct LayoutArithmeticTests { #expect(KeyboardGalleryView.rows(from: args)[0].model.palette.face == .light) #expect(KeyboardGalleryView.Options.parse(args) == .init(still: true, bare: true)) #expect(KeyboardGalleryView.Options.parse(["app", "-BlurtGallery", "panel", "idle", "dark"]) == .init()) - #expect(KeyboardGalleryView.Options.parse(args).voice == .shipped) - #expect(KeyboardGalleryView.Options.parse(args + ["-BlurtGalleryVoice", "b"]).voice == .ribs) - #expect(KeyboardGalleryView.Options.parse(args + ["-BlurtGalleryVoice", "z"]).voice == .shipped) + #expect(KeyboardGalleryView.rows(from: args)[0].model.voiceKind == .shipped) + #expect(KeyboardGalleryView.rows(from: args + ["-BlurtGalleryVoice", "b"])[0].model.voiceKind == .ribs) + #expect(KeyboardGalleryView.rows(from: args + ["-BlurtGalleryVoice", "z"])[0].model.voiceKind == .shipped) #expect(KeyboardGalleryView.VoiceStillView.parse(args) == nil) let voice = KeyboardGalleryView.VoiceStillView.parse(["app", "-BlurtVoice", "a", "panel", "landed", "dark"]) #expect(voice?.kind == .grille) diff --git a/App/BlurtiOS/BlurtiOSTests/SharedStateTests.swift b/App/BlurtiOS/BlurtiOSTests/SharedStateTests.swift index 4a830199..d042b034 100644 --- a/App/BlurtiOS/BlurtiOSTests/SharedStateTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/SharedStateTests.swift @@ -59,6 +59,20 @@ struct PhaseSnapshotTests { } } +@Suite("Voice element setting") +struct VoiceElementSettingTests { + @Test("the mic concept round-trips through the App Group; unset or unknown is the shipped one") + func roundTrip() { + let suite = ScratchSuite() + defer { suite.tearDown() } + #expect(SharedStore.voiceElementKind == .shipped) + SharedStore.voiceElementKind = .streak + #expect(SharedStore.voiceElementKind == .streak) + SharedStore.defaults.set("z", forKey: BlurtShared.Key.voiceElement) + #expect(SharedStore.voiceElementKind == .shipped) + } +} + @Suite("Layouts and palettes") struct LayoutTests { @Test("heights are the rows at the iPhone keyboard's spacing (DESIGN.md)") diff --git a/App/BlurtiOS/DESIGN.md b/App/BlurtiOS/DESIGN.md index ca61fa7a..82469404 100644 --- a/App/BlurtiOS/DESIGN.md +++ b/App/BlurtiOS/DESIGN.md @@ -205,6 +205,11 @@ that makes the glints random to the eye and the same in every capture. | **b — Ribs** (`VoiceRibs`) | a short block of the wave's own bars under a cosine envelope, the sheen passing rib to rib | the ribs are the wave: they widen to the box and follow the voice | the ribs breathe with the sheen | a white glint runs the ribs | the ribs orange | | **c — Streak** (`VoiceStreak`) | a hairline the width of the box with a bright point at its centre | the point blooms into a light streak whose reach follows the level, green along it, white at the heart, violet at the tips | a short streak sweeps the line back and forth | the cross's vertical arm flashes through the point | the line orange | +**Temporary, while one is chosen:** Settings → Keyboard → Mic switches the +concept in use (`SharedStore.voiceElementKind`, read by the keyboard on every +appearance and by the home screen live). The switch, the two losers and +`-BlurtGalleryVoice` go together once the direction is picked. + What is common: the box (`voice/*`), dimming to `opacity/off` when Blurt isn't ready (a tap opens the app), the two glyphs that need saying (a clipboard when the words went there, an exclamation mark on a failure) drawn diff --git a/App/BlurtiOS/Shared/SharedState.swift b/App/BlurtiOS/Shared/SharedState.swift index 0a6fd1a9..75ada6f1 100644 --- a/App/BlurtiOS/Shared/SharedState.swift +++ b/App/BlurtiOS/Shared/SharedState.swift @@ -22,6 +22,9 @@ nonisolated enum BlurtShared { static let layout = "keyboardLayout" static let autoDictate = "autoDictate" static let theme = "keyboardTheme" + /// TEMPORARY: which mic concept draws (a, b or c), while the three are + /// tried in use. Goes with the losers once one is picked. + static let voiceElement = "voiceElement" static let listeningUntil = "listeningUntil" static let windowMinutes = "listeningWindowMinutes" static let phase = "phase" @@ -235,6 +238,14 @@ nonisolated enum SharedStore { set { defaults.set(newValue, forKey: BlurtShared.Key.theme) } } + /// TEMPORARY: the mic concept to draw — `VoiceElementKind.rawValue`, the + /// shipped one until Settings says otherwise. Read by the keyboard on every + /// appearance and by the home screen live. Goes with the losers. + static var voiceElementKind: VoiceElementKind { + get { VoiceElementKind(rawValue: defaults.string(forKey: BlurtShared.Key.voiceElement) ?? "") ?? .shipped } + set { defaults.set(newValue.rawValue, forKey: BlurtShared.Key.voiceElement) } + } + /// Hands-free: the keyboard starts a dictation the moment it appears in a /// text field, so there is nothing to tap before talking. On by default. static var autoDictate: Bool { From 63de3b1e5c387d34dbd206fbc644740adc0e22f3 Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Tue, 29 Sep 2026 19:40:57 -0400 Subject: [PATCH 57/79] =?UTF-8?q?Keyboard:=20draw=20the=20candidates=20syn?= =?UTF-8?q?chronously=20=E2=80=94=20they=20never=20showed=20in=20the=20ext?= =?UTF-8?q?ension?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every candidate (and the surface grain) drew with `Canvas(rendersAsynchronously: true)`, which presents nothing inside a keyboard extension: the gallery and the home hero, in the app's process, showed all three; the real keyboard showed an empty bar. Synchronous canvases now; the drawing is a few hundred dots at 20 Hz, well within a keyboard's budget. So the difference can't hide again, `scripts/ios-keyboard-shot.sh` captures the real keyboard: the `BlurtKeyboardShot` UI test launches the app on `-BlurtProbeField [a|b|c] [layout]` (the probe field now writes the mic concept and the layout to the App Group), taps the system's globe until Blurt's + is on screen — XCUITest sees a custom keyboard only through its controls — and exports the screenshot. xcodebuild hands the test runner only TEST_RUNNER_-prefixed variables; the script uses one. Co-Authored-By: Claude Fable 5.1 --- .../BlurtKeyboard/Sources/Grain.swift | 5 +- .../BlurtKeyboard/Sources/VoiceElement.swift | 4 + .../BlurtKeyboard/Sources/VoiceGrille.swift | 2 +- .../BlurtKeyboard/Sources/VoiceRibs.swift | 2 +- .../BlurtKeyboard/Sources/VoiceStreak.swift | 2 +- .../BlurtiOS/Sources/KeyboardProbeView.swift | 8 ++ .../BlurtiOSProbe/BlurtKeyboardShot.swift | 41 ++++++++ App/BlurtiOS/DESIGN.md | 3 + scripts/ios-keyboard-shot.sh | 95 +++++++++++++++++++ 9 files changed, 157 insertions(+), 5 deletions(-) create mode 100644 App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardShot.swift create mode 100755 scripts/ios-keyboard-shot.sh diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/Grain.swift b/App/BlurtiOS/BlurtKeyboard/Sources/Grain.swift index 22d622ab..0981d8c4 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/Grain.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/Grain.swift @@ -2,12 +2,13 @@ import SwiftUI /// Film grain: a scatter of faint dots drawn from a seed, so a frame is /// reproducible — the brand's texture, on the keyboard's surface -/// (`SurfaceFinish`), still, one seed. +/// (`SurfaceFinish`), still, one seed. Drawn synchronously: a canvas that +/// renders asynchronously never presents inside a keyboard extension. struct BlurtiOSGrain: View { let seed: Int var body: some View { - Canvas(rendersAsynchronously: true) { context, size in + Canvas { context, size in var state = UInt64(truncatingIfNeeded: seed &* 6_364_136_223_846_793_005 &+ 1) func next() -> CGFloat { state = state &* 6_364_136_223_846_793_005 &+ 1_442_695_040_888_963_407 diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceElement.swift b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceElement.swift index f45961ce..4e9fb064 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceElement.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceElement.swift @@ -39,6 +39,10 @@ nonisolated enum VoiceSlot: String, CaseIterable, Sendable { } } +/// Every candidate draws with a synchronous `Canvas`: one that renders +/// asynchronously never presents inside a keyboard extension, and the +/// keyboard is where these live. +/// /// Everything a candidate draws from — nothing else reaches it: the state, /// the level inside it, the moment the words landed, whether motion is /// allowed, the face's colours, and where it sits. diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceGrille.swift b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceGrille.swift index b2571186..b0107820 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceGrille.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceGrille.swift @@ -20,7 +20,7 @@ struct VoiceGrille: View { let box = Self.box(inputs.slot) TimelineView(.animation(minimumInterval: keyboardAnimationInterval, paused: !inputs.animated)) { timeline in let now = inputs.animated ? timeline.date : Date(timeIntervalSinceReferenceDate: 0) - Canvas(rendersAsynchronously: true) { context, size in + Canvas { context, size in draw(&context, size: size, now: now) } } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceRibs.swift b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceRibs.swift index b1f63c64..f7111f9f 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceRibs.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceRibs.swift @@ -33,7 +33,7 @@ struct VoiceRibs: View { } else { TimelineView(.animation(minimumInterval: keyboardAnimationInterval, paused: !inputs.animated)) { timeline in let now = inputs.animated ? timeline.date : Date(timeIntervalSinceReferenceDate: 0) - Canvas(rendersAsynchronously: true) { context, size in + Canvas { context, size in Self.ribs(&context, size: size, inputs: inputs, now: now) } } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceStreak.swift b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceStreak.swift index 7643cf7e..95211ac1 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceStreak.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceStreak.swift @@ -17,7 +17,7 @@ struct VoiceStreak: View { let box = inputs.slot.box TimelineView(.animation(minimumInterval: keyboardAnimationInterval, paused: !inputs.animated)) { timeline in let now = inputs.animated ? timeline.date : Date(timeIntervalSinceReferenceDate: 0) - Canvas(rendersAsynchronously: true) { context, size in + Canvas { context, size in Self.draw(&context, size: size, inputs: inputs, now: now) } } diff --git a/App/BlurtiOS/BlurtiOS/Sources/KeyboardProbeView.swift b/App/BlurtiOS/BlurtiOS/Sources/KeyboardProbeView.swift index 38940e00..a3e07492 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/KeyboardProbeView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/KeyboardProbeView.swift @@ -11,10 +11,18 @@ struct KeyboardProbeView: View { let dark: Bool + /// `-BlurtProbeField light|dark [a|b|c] [slimBar|panel|full]`: the words + /// after the face set the mic concept and the layout in the App Group, + /// so the Blurt keyboard — which reads both on every appearance — comes up + /// that way for a capture of the real extension (`scripts/ios-keyboard-shot.sh`). static func parse(_ arguments: [String]) -> KeyboardProbeView? { guard let flag = arguments.firstIndex(of: "-BlurtProbeField") else { return nil } let face = arguments.count > flag + 1 ? arguments[flag + 1] : "light" guard face == "light" || face == "dark" else { return nil } + for word in arguments.dropFirst(flag + 2).prefix(while: { !$0.hasPrefix("-") }) { + if let kind = VoiceElementKind(rawValue: word) { SharedStore.voiceElementKind = kind } + if let layout = KeyboardLayout(rawValue: word) { SharedStore.layout = layout } + } return KeyboardProbeView(dark: face == "dark") } diff --git a/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardShot.swift b/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardShot.swift new file mode 100644 index 00000000..0f021de6 --- /dev/null +++ b/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardShot.swift @@ -0,0 +1,41 @@ +import XCTest + +/// A screenshot of the real Blurt keyboard — the extension, in its own +/// process, over a text field — for the states the gallery cannot vouch +/// for. Launches the app on `-BlurtProbeField` (which also sets the face, +/// the mic concept and the layout), taps the system's globe until Blurt is +/// up, and attaches the screen. `scripts/ios-keyboard-shot.sh` runs it and +/// exports the attachment. Blurt must be enabled as a keyboard on the +/// simulator (Settings → General → Keyboard → Keyboards) once by hand. +final class BlurtKeyboardShot: XCTestCase { + @MainActor + func testShot() throws { + let arguments = + ProcessInfo.processInfo.environment["BLURT_PROBE_ARGS"]?.split(separator: " ").map(String.init) ?? [] + let app = XCUIApplication() + app.launchArguments = ["-BlurtProbeField"] + (arguments.isEmpty ? ["light"] : arguments) + app.launch() + // Blurt's own control: the + that adds a key term, which no system + // keyboard has. XCUITest sees the system keyboard as a keyboard and a + // custom one only through its controls, so wait for either; then the + // globe cycles the enabled keyboards until Blurt is up. + let blurt = app.buttons["Add a key term"] + let system = app.keyboards.firstMatch + let deadline = Date().addingTimeInterval(15) + while !blurt.exists, !system.exists, Date() < deadline { Thread.sleep(forTimeInterval: 0.5) } + XCTAssertTrue(blurt.exists || system.exists, "no on-screen keyboard") + var hops = 0 + while !blurt.waitForExistence(timeout: 2), hops < 4 { + let globe = app.buttons["Next keyboard"] + XCTAssertTrue(globe.waitForExistence(timeout: 5), "no globe key: is more than one keyboard enabled?") + globe.tap() + hops += 1 + } + XCTAssertTrue(blurt.exists, "Blurt's keyboard never came up: enable it in Settings → General → Keyboard") + Thread.sleep(forTimeInterval: 2) + let shot = XCTAttachment(screenshot: app.screenshot()) + shot.name = "blurt-keyboard.png" + shot.lifetime = .keepAlways + add(shot) + } +} diff --git a/App/BlurtiOS/DESIGN.md b/App/BlurtiOS/DESIGN.md index 82469404..424d70dc 100644 --- a/App/BlurtiOS/DESIGN.md +++ b/App/BlurtiOS/DESIGN.md @@ -57,6 +57,9 @@ scripts/ios-record.sh --layout panel --theme dark [--voice a] swift scripts/design-diff.swift diff a.png b.png --out triptych.png --json metrics.json # sRGB, AE and RMSE; `sheet` makes a contact sheet; `measure` reads a keyboard's caps off a screenshot scripts/apple-geometry.sh # measures the iPhone's own keyboard → Design/apple-geometry.json +scripts/ios-keyboard-shot.sh --face dark --voice b --layout panel + # the real keyboard — the extension in its own process — over a field in the app: what the gallery + # cannot vouch for (a canvas that renders asynchronously never presents in an extension) scripts/design-sync.sh [--check] # tokens.json → DesignTokens.swift, these tables, the colour sets ``` diff --git a/scripts/ios-keyboard-shot.sh b/scripts/ios-keyboard-shot.sh new file mode 100755 index 00000000..9970ee34 --- /dev/null +++ b/scripts/ios-keyboard-shot.sh @@ -0,0 +1,95 @@ +#!/bin/bash +# A screenshot of the real Blurt keyboard — the extension in its own process, +# over a text field in the app — as the gallery cannot take one: what renders +# in the app's process (the gallery, the home hero) can differ from what the +# extension may draw. The BlurtiOSProbe UI test launches the app on +# -BlurtProbeField, which sets the face, the mic concept and the layout in the +# App Group, taps the globe until Blurt's keyboard is up, and attaches the +# screen; this exports it. +# +# scripts/ios-keyboard-shot.sh # light, the shipped mic, the saved layout +# scripts/ios-keyboard-shot.sh --face dark --voice b --layout panel --out .build/design/ext/panel-b.png +# +# Blurt must be enabled as a keyboard on the simulator once by hand +# (Settings → General → Keyboard → Keyboards → Add New Keyboard → Blurt). +set -euo pipefail + +REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" +cd "$REPO_ROOT" +# shellcheck source=scripts/ios-lib.sh +source "$REPO_ROOT/scripts/ios-lib.sh" +DERIVED="${BLURT_DERIVED_DATA:-$REPO_ROOT/.build/ios-sim}" +FACE=light +VOICE="" +LAYOUT="" +OUT="" +while [ $# -gt 0 ]; do + case "$1" in + --face) + FACE="${2:?}" + shift 2 + ;; + --voice) + VOICE="${2:?}" + shift 2 + ;; + --layout) + LAYOUT="${2:?}" + shift 2 + ;; + --out) + OUT="${2:?}" + shift 2 + ;; + *) + echo "usage: ios-keyboard-shot.sh [--face light|dark] [--voice a|b|c] [--layout slimBar|panel|full] [--out FILE.png]" >&2 + exit 2 + ;; + esac +done +[ -n "$OUT" ] || OUT="$REPO_ROOT/.build/design/ext/keyboard-$FACE${VOICE:+-$VOICE}${LAYOUT:+-$LAYOUT}.png" +mkdir -p "$(dirname "$OUT")" + +PICKED="$(ios_pick_device "${BLURT_SIM_DEVICE:-iPhone 18 Pro}")" +[ -n "$PICKED" ] || { + echo "ios-keyboard-shot: no iPhone simulator available" >&2 + exit 1 +} +UDID="${PICKED%% *}" +ios_wait_booted "$UDID" +WORK="$(mktemp -d)" +trap 'rm -rf "$WORK"' EXIT + +(cd "$REPO_ROOT/App/BlurtiOS" && xcodegen generate --quiet) +# xcodebuild hands the test runner only the environment variables prefixed +# TEST_RUNNER_; the test reads BLURT_PROBE_ARGS. +if ! TEST_RUNNER_BLURT_PROBE_ARGS="$FACE $VOICE $LAYOUT" xcodebuild test -project "$REPO_ROOT/App/BlurtiOS/BlurtiOS.xcodeproj" \ + -scheme BlurtiOSProbe -only-testing:BlurtiOSProbe/BlurtKeyboardShot \ + -destination "platform=iOS Simulator,id=$UDID" -derivedDataPath "$DERIVED" \ + -resultBundlePath "$WORK/shot.xcresult" "${IOS_SIM_SIGNING[@]}" -collect-test-diagnostics never -quiet; then + # Say why, from the result bundle, before it goes. + xcrun xcresulttool get test-results tests --path "$WORK/shot.xcresult" 2>/dev/null | python3 -c ' +import json, sys +def walk(node): + if isinstance(node, dict): + if node.get("nodeType") == "Failure Message": print("ios-keyboard-shot:", node.get("name")) + for child in node.get("children", []): walk(child) + elif isinstance(node, list): + for child in node: walk(child) +walk(json.load(sys.stdin).get("testNodes", [])) +' || true + exit 1 +fi +xcrun xcresulttool export attachments --path "$WORK/shot.xcresult" --output-path "$WORK/attachments" >/dev/null +python3 - "$WORK/attachments" "$OUT" <<'PY' +import json, os, shutil, sys +attachments, out = sys.argv[1], sys.argv[2] +manifest = json.load(open(os.path.join(attachments, "manifest.json"))) +for test in manifest: + for a in test.get("attachments", []): + if a["suggestedHumanReadableName"].startswith("blurt-keyboard"): + shutil.copy(os.path.join(attachments, a["exportedFileName"]), out) + print(f"ios-keyboard-shot: {out}") + sys.exit(0) +sys.exit("ios-keyboard-shot: no screenshot in the result bundle") +PY From 545527d094540a29f82550009d1986fe801296ef Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Wed, 30 Sep 2026 09:12:15 -0400 Subject: [PATCH 58/79] =?UTF-8?q?Keyboard:=20the=20surface=20is=20the=20ho?= =?UTF-8?q?st's=20=E2=80=94=20clear=20by=20default?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The band above the keyboard: iOS 26 wraps a third-party keyboard in the host app's own rounded material, inset about 16 pt above and below, and nothing the keyboard draws reaches the inset (Apple's forums: working as intended). Every Liquid Glass app shows it over a painted surface; it is only more visible over a dark compose bar. No height trick moves it: a late-activated constraint, a nudge after appearing, self-sizing through intrinsicContentSize (which collapsed the keyboard to 31 pt) and the plain input view style all leave the host's container where it is. So the surface is clear by default: the host's material is the surface, seamlessly, and the keys take the face's container colours, which read on the system's light and dark material (`#575757` keys on the dark one, measured). The brand lives in the keys, the labels and the voice element. `surface/paint` 1 paints the face and its grain under the keys and accepts the band. The height constraint is activated from updateViewConstraints once the view has appeared, at required − 1, which is the forum-proven way to avoid the host's first-layout fight. Verified in Messages (light and dark, fresh and after the system keyboard) and in the app: `MessagesKeyboardShot` drives Messages itself. `ios-keyboard-shot.sh` now builds and installs the app explicitly first — `xcodebuild test` does not reinstall a host app it thinks is installed, which is how a stale keyboard extension sat on the simulator for an hour. Co-Authored-By: Claude Fable 5.1 --- .../Sources/FullKeyboardView.swift | 3 +- .../BlurtKeyboard/Sources/KeyCap.swift | 3 +- .../Sources/KeyboardPalette.swift | 34 +- .../Sources/KeyboardRootView.swift | 22 +- .../Sources/KeyboardViewController.swift | 26 +- .../BlurtiOSProbe/BlurtKeyboardShot.swift | 2 +- .../BlurtiOSProbe/MessagesKeyboardShot.swift | 62 ++++ .../BlurtiOSTests/DesignTokensTests.swift | 6 +- App/BlurtiOS/DESIGN.md | 333 +++++++++--------- App/BlurtiOS/Design/figma/tokens.js | 7 + App/BlurtiOS/Design/tokens.json | 18 +- App/BlurtiOS/Shared/DesignTokens.swift | 21 ++ scripts/design-tokens.swift | 6 +- scripts/ios-keyboard-shot.sh | 5 + 14 files changed, 373 insertions(+), 175 deletions(-) create mode 100644 App/BlurtiOS/BlurtiOSProbe/MessagesKeyboardShot.swift diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift b/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift index 1f3d7c4b..fbfd50b3 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift @@ -83,13 +83,14 @@ private struct LetterKey: View { let action: () -> Void @State private var pressed = false @Environment(\.keyboardPalette) private var palette + @Environment(\.keyboardInContainer) private var inContainer var body: some View { Text(label) .font(.system(size: DesignTokens.Typography.sizeLetter, weight: DesignTokens.Typography.weightLetter)) .foregroundStyle(palette.keyText) .frame(width: width, height: KeyCap.height) - .keyCap(palette.key) + .keyCap(palette.keyFill(modifier: false, inContainer: inContainer)) .overlay(alignment: .top) { if pressed { popup } } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyCap.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyCap.swift index c61bf69f..e0aaabb5 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyCap.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyCap.swift @@ -16,6 +16,7 @@ struct KeyCap: View { var width: CGFloat? var action: () -> Void @Environment(\.keyboardPalette) private var palette + @Environment(\.keyboardInContainer) private var inContainer static let height = DesignTokens.Metrics.keyHeight @@ -54,7 +55,7 @@ struct KeyCap: View { .frame(width: width) .frame(minWidth: width == nil ? DesignTokens.Metrics.keyMinWidth : nil, minHeight: Self.height) .padding(.horizontal, flexible || width != nil ? 0 : DesignTokens.Metrics.keyPad) - .keyCap(bare ? .clear : dark ? palette.keyDark : palette.key) + .keyCap(bare ? .clear : palette.keyFill(modifier: dark, inContainer: inContainer)) .keyPress(action) .accessibilityLabel(title ?? systemImage ?? "") } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift index 75e557a8..e5d957bc 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift @@ -41,6 +41,11 @@ struct KeyboardPalette: Equatable, Identifiable { let notice: Color /// How much film grain lies over the surface: the brand's texture, matte. let grain: Double + /// The keys when the host wraps the keyboard in its own material (iOS 26's + /// Liquid Glass apps: Messages, Notes, Safari) and the surface goes clear: + /// colours that read on the system's light or dark material. + let containerKey: Color + let containerKeyModifier: Color static let keyGap = DesignTokens.Metrics.keyGap static let rowGap = DesignTokens.Metrics.rowGap @@ -61,7 +66,8 @@ struct KeyboardPalette: Equatable, Identifiable { surface: Themes.lightSurface, key: Themes.lightKey, keyDark: Themes.lightKeyModifier, keyText: Themes.lightLegend, keyTextSecondary: Themes.lightLegendSecondary, signal: Themes.lightSignal, popupFill: Themes.lightPopup, field: Themes.lightField, fieldBorder: Themes.lightFieldBorder, - notice: Themes.lightNotice, grain: DesignTokens.Metrics.opacityGrainLight) + notice: Themes.lightNotice, grain: DesignTokens.Metrics.opacityGrainLight, + containerKey: Themes.lightContainerKey, containerKeyModifier: Themes.lightContainerKeyModifier) /// The dark face: ink `#1D1B16`, `#33302A` keys, `#26231E` modifiers, warm /// white legends, the lifted green. @@ -70,7 +76,8 @@ struct KeyboardPalette: Equatable, Identifiable { surface: Themes.darkSurface, key: Themes.darkKey, keyDark: Themes.darkKeyModifier, keyText: Themes.darkLegend, keyTextSecondary: Themes.darkLegendSecondary, signal: Themes.darkSignal, popupFill: Themes.darkPopup, field: Themes.darkField, fieldBorder: Themes.darkFieldBorder, - notice: Themes.darkNotice, grain: DesignTokens.Metrics.opacityGrainDark) + notice: Themes.darkNotice, grain: DesignTokens.Metrics.opacityGrainDark, + containerKey: Themes.darkContainerKey, containerKeyModifier: Themes.darkContainerKeyModifier) /// The picker's list, one entry per theme (a theme's two faces share an id). static let all: [KeyboardPalette] = [brandLight] @@ -83,6 +90,13 @@ struct KeyboardPalette: Equatable, Identifiable { return dark ? brandDark : brandLight } + /// A key's fill: the face's, or the container's when the host's material + /// is the surface. + func keyFill(modifier: Bool, inContainer: Bool) -> Color { + if inContainer { return modifier ? containerKeyModifier : containerKey } + return modifier ? keyDark : key + } + static func == (lhs: KeyboardPalette, rhs: KeyboardPalette) -> Bool { lhs.id == rhs.id && lhs.face == rhs.face } } @@ -95,6 +109,22 @@ extension Color { } } +private struct KeyboardInContainerKey: EnvironmentKey { + static let defaultValue = false +} + +extension EnvironmentValues { + /// Whether the host wraps the keyboard in its own material (iOS 26's + /// Liquid Glass apps inset a third-party keyboard inside a rounded + /// container nothing can paint over): the surface goes clear and the keys + /// take the palette's container colours, so there is no band of a + /// different grey above the keyboard. + var keyboardInContainer: Bool { + get { self[KeyboardInContainerKey.self] } + set { self[KeyboardInContainerKey.self] = newValue } + } +} + private struct KeyboardPaletteKey: EnvironmentKey { static let defaultValue = KeyboardPalette.brandLight } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardRootView.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardRootView.swift index 49dea28c..9eeed2a2 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardRootView.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardRootView.swift @@ -14,6 +14,8 @@ struct KeyboardRootView: View { static let verticalMargin = DesignTokens.Metrics.marginVertical /// Under a bottom row of keys, the iPhone's own margin. static let bottomMarginKeys = DesignTokens.Metrics.marginBottomKeys + /// Whether the face's surface is painted under the keys (`surface/paint`). + static let paintsSurface = DesignTokens.Metrics.surfacePaint > 0 var body: some View { Group { @@ -32,11 +34,25 @@ struct KeyboardRootView: View { .padding(.horizontal, KeyboardPalette.margin) .padding(.top, Self.verticalMargin) .padding(.bottom, model.effectiveLayout == .slimBar ? Self.verticalMargin : Self.bottomMarginKeys) - .frame(maxWidth: .infinity, maxHeight: .infinity) - .background { SurfaceFinish.Ground(surface: model.palette.surface) } - .overlay { SurfaceFinish.Grain() } + // Anchored to the bottom: if the host ever gives the keyboard more + // height than its layout, the extra is surface above the keys, never + // a hole under them. + .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottom) + // iOS 26 wraps a third-party keyboard in the host's own rounded material, + // inset above and below, and nothing the keyboard draws reaches the + // inset: a painted surface shows a band of the host's grey above it. So + // by default the surface is clear — the host's material is the surface, + // seamlessly — and the keys take the colours that read on it; the face + // is painted, grain on top, only when `surface/paint` says so. + .background { + if Self.paintsSurface { SurfaceFinish.Ground(surface: model.palette.surface) } + } + .overlay { + if Self.paintsSurface { SurfaceFinish.Grain() } + } .clipped() .environment(\.keyboardPalette, model.palette) + .environment(\.keyboardInContainer, !Self.paintsSurface) .environment(\.voiceElementKind, model.voiceKind) .simultaneousGesture(swipe, including: model.layout == .panel ? .all : .subviews) .animation(reduceMotion ? nil : .easeInOut(duration: DesignTokens.Motion.flip), value: model.panelShowsKeys) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift index 3a8d3497..c49467f9 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift @@ -8,7 +8,6 @@ import UIKit /// keyboard use the microphone, so the app listens and this inserts. final class KeyboardViewController: UIInputViewController { private let model = KeyboardModel() - private var heightConstraint: NSLayoutConstraint? /// The input view says it wants clicks, so `UIDevice.playInputClick()` on /// each key press plays the system's keyboard click — and only if the @@ -17,6 +16,9 @@ final class KeyboardViewController: UIInputViewController { var enableInputClicksWhenVisible: Bool { true } } + private var heightConstraint: NSLayoutConstraint? + private var hasAppeared = false + override func loadView() { view = ClickingInputView(frame: .zero, inputViewStyle: .keyboard) } @@ -36,11 +38,14 @@ final class KeyboardViewController: UIInputViewController { host.view.bottomAnchor.constraint(equalTo: view.bottomAnchor), ]) host.didMove(toParent: self) - // The keyboard's height is ours to declare; iOS honours a constraint on the - // input view at just under required priority. + // The keyboard's height is ours to declare, at just under required + // priority, and only once the view has appeared (from + // updateViewConstraints): activated from viewDidLoad it fights the host's + // first layout and the keyboard flashes at the wrong size. What the host + // draws *around* the keyboard — iOS 26's rounded container, inset above + // and below — is the host's, and nothing here changes it. let height = view.heightAnchor.constraint(equalToConstant: model.effectiveLayout.height) - height.priority = UILayoutPriority(999) - height.isActive = true + height.priority = .required - 1 heightConstraint = height // The panel's carousel changes the keyboard's height when it flips. model.onLayoutChange = { [weak self] in self?.updateHeight(animated: true) } @@ -49,11 +54,20 @@ final class KeyboardViewController: UIInputViewController { override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) model.appeared() - updateHeight(animated: false) + hasAppeared = true + view.setNeedsUpdateConstraints() + } + + override func updateViewConstraints() { + super.updateViewConstraints() + guard hasAppeared, let heightConstraint else { return } + heightConstraint.constant = model.effectiveLayout.height + if !heightConstraint.isActive { heightConstraint.isActive = true } } private func updateHeight(animated: Bool) { heightConstraint?.constant = model.effectiveLayout.height + view.setNeedsUpdateConstraints() guard animated else { return } UIView.animate(withDuration: DesignTokens.Motion.heightChange) { self.view.superview?.layoutIfNeeded() } } diff --git a/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardShot.swift b/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardShot.swift index 0f021de6..830b0f9d 100644 --- a/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardShot.swift +++ b/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardShot.swift @@ -19,7 +19,7 @@ final class BlurtKeyboardShot: XCTestCase { // keyboard has. XCUITest sees the system keyboard as a keyboard and a // custom one only through its controls, so wait for either; then the // globe cycles the enabled keyboards until Blurt is up. - let blurt = app.buttons["Add a key term"] + let blurt = app.buttons.matching(NSPredicate(format: "label BEGINSWITH %@", "Add a key term")).firstMatch let system = app.keyboards.firstMatch let deadline = Date().addingTimeInterval(15) while !blurt.exists, !system.exists, Date() < deadline { Thread.sleep(forTimeInterval: 0.5) } diff --git a/App/BlurtiOS/BlurtiOSProbe/MessagesKeyboardShot.swift b/App/BlurtiOS/BlurtiOSProbe/MessagesKeyboardShot.swift new file mode 100644 index 00000000..a75bdfbd --- /dev/null +++ b/App/BlurtiOS/BlurtiOSProbe/MessagesKeyboardShot.swift @@ -0,0 +1,62 @@ +import XCTest + +/// The real Blurt keyboard inside Messages — another host, another layout +/// history — repeated, since the system's keyboard container sometimes keeps +/// the previous keyboard's height. Attaches a screenshot per showing and +/// prints where Blurt's + landed, so the container's extra height (the +/// system's backdrop above our surface) can be measured. +final class MessagesKeyboardShot: XCTestCase { + @MainActor + func testShots() throws { + let messages = XCUIApplication(bundleIdentifier: "com.apple.MobileSMS") + messages.launch() + // A conversation if there is one, else a new message. + let cell = messages.cells.firstMatch + if cell.waitForExistence(timeout: 5) { + cell.tap() + } else { + messages.buttons["compose"].firstMatch.tap() + } + // The message field, whatever element Messages makes it this year. + let field = messages.descendants(matching: .any).matching( + NSPredicate(format: "placeholderValue == %@ OR label == %@", "iMessage", "iMessage") + ).firstMatch + if !field.waitForExistence(timeout: 10) { + let lines = messages.debugDescription.split(separator: "\n").filter { + $0.contains("Message") || $0.contains("TextView") || $0.contains("TextField") + } + XCTFail("no message field; candidates:\n" + lines.prefix(30).joined(separator: "\n")) + return + } + print("BLURT-FIELD \(field.elementType.rawValue) \(field.frame)") + let blurt = messages.buttons.matching(NSPredicate(format: "label BEGINSWITH %@", "Add a key term")).firstMatch + for round in 0..<3 { + field.tap() + // Round 1 comes to Blurt from the emoji keyboard, round 2 from the + // system keyboard: the container keeps the previous keyboard's height + // when it is taller, which is the band above the surface. + if round > 0 { + let globe = messages.buttons["Next keyboard"] + if blurt.exists, globe.waitForExistence(timeout: 3) { globe.tap() } + if round == 1 { Thread.sleep(forTimeInterval: 1.5) } + } + var hops = 0 + while !blurt.waitForExistence(timeout: 2), hops < 4 { + let globe = messages.buttons["Next keyboard"] + XCTAssertTrue(globe.waitForExistence(timeout: 5), "no globe key") + globe.tap() + hops += 1 + } + XCTAssertTrue(blurt.exists, "Blurt never came up in Messages") + Thread.sleep(forTimeInterval: 2.5) + print("BLURT-FRAMES round \(round): plus \(blurt.frame) space \(messages.buttons["space"].firstMatch.frame)") + let shot = XCTAttachment(screenshot: messages.screenshot()) + shot.name = "messages-\(round).png" + shot.lifetime = .keepAlways + add(shot) + // Dismiss and bring it back: swipe the conversation down to hide the keyboard. + messages.swipeDown() + Thread.sleep(forTimeInterval: 1.5) + } + } +} diff --git a/App/BlurtiOS/BlurtiOSTests/DesignTokensTests.swift b/App/BlurtiOS/BlurtiOSTests/DesignTokensTests.swift index 98c8e7e9..071f92e2 100644 --- a/App/BlurtiOS/BlurtiOSTests/DesignTokensTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/DesignTokensTests.swift @@ -116,7 +116,7 @@ struct DesignTokensTests { [ Themes.lightSurface, Themes.lightKey, Themes.lightKeyModifier, Themes.lightLegend, Themes.lightLegendSecondary, Themes.lightSignal, Themes.lightPopup, Themes.lightField, - Themes.lightFieldBorder, Themes.lightNotice, + Themes.lightFieldBorder, Themes.lightNotice, Themes.lightContainerKey, Themes.lightContainerKeyModifier, ] ), ( @@ -124,6 +124,7 @@ struct DesignTokensTests { [ Themes.darkSurface, Themes.darkKey, Themes.darkKeyModifier, Themes.darkLegend, Themes.darkLegendSecondary, Themes.darkSignal, Themes.darkPopup, Themes.darkField, Themes.darkFieldBorder, Themes.darkNotice, + Themes.darkContainerKey, Themes.darkContainerKeyModifier, ] ), ] @@ -135,7 +136,8 @@ struct DesignTokensTests { for (palette, colors) in Self.paletteTokens { let roles = [ palette.surface, palette.key, palette.keyDark, palette.keyText, palette.keyTextSecondary, palette.signal, - palette.popupFill, palette.field, palette.fieldBorder, palette.notice, + palette.popupFill, palette.field, palette.fieldBorder, palette.notice, palette.containerKey, + palette.containerKeyModifier, ] #expect(roles == colors, "\(palette.id) \(palette.face)") } diff --git a/App/BlurtiOS/DESIGN.md b/App/BlurtiOS/DESIGN.md index 424d70dc..0addd572 100644 --- a/App/BlurtiOS/DESIGN.md +++ b/App/BlurtiOS/DESIGN.md @@ -80,13 +80,29 @@ the brand's face. Ten roles each (`BlurtKeyboard/Sources/KeyboardPalette.swift`) -| Face | Surface | Key | Modifier | Legend | Secondary | Signal | Pop-up | Field | Field border | Notice | -| ------- | --------- | --------- | --------- | --------- | --------- | --------- | --------- | --------- | ------------ | --------- | -| `light` | `#ECEBE5` | `#FFFFFF` | `#DAD7CB` | `#1D1B16` | `#777673` | `#01762F` | `#FFFFFF` | `#FFFFFF` | `#C7C3B2` | `#E67F36` | -| `dark` | `#1D1B16` | `#33302A` | `#26231E` | `#F5F3EB` | `#A5A4A2` | `#67AD82` | `#33302A` | `#33302A` | `#3A362F` | `#E67F36` | +| Face | Surface | Key | Modifier | Legend | Secondary | Signal | Pop-up | Field | Field border | Notice | Key in container | Modifier in container | +| ------- | --------- | --------- | --------- | --------- | --------- | --------- | --------- | --------- | ------------ | --------- | ---------------- | --------------------- | +| `light` | `#ECEBE5` | `#FFFFFF` | `#DAD7CB` | `#1D1B16` | `#777673` | `#01762F` | `#FFFFFF` | `#FFFFFF` | `#C7C3B2` | `#E67F36` | `#FFFFFF` | `#DAD7CB` | +| `dark` | `#1D1B16` | `#33302A` | `#26231E` | `#F5F3EB` | `#A5A4A2` | `#67AD82` | `#33302A` | `#33302A` | `#3A362F` | `#E67F36` | `#575757` | `#474747` | +**The surface is the host's.** iOS 26 wraps a third-party keyboard in the host +app's own rounded keyboard material, inset above and below by about 16 pt, +and nothing the keyboard draws reaches the inset (Apple: working as +intended). A painted surface therefore shows a band of the host's grey above +it, in every Liquid Glass app. So the surface is **clear** by default +(`surface/paint` 0): the host's material is the surface, seamlessly, and the +keys take the face's `container-key` / `container-key-modifier` colours, +which read on the system's light and dark material (measured from the iPhone +keyboard: `#575757` keys on the dark one). The brand lives in the keys, the +labels and the voice element. `surface/paint` 1 paints the face's surface +and grain under the keys — and accepts the band. The keyboard's height is a +constraint at required − 1, activated from `updateViewConstraints` once the +view has appeared; activated earlier it fights the host's first layout. +`scripts/ios-keyboard-shot.sh` and the `MessagesKeyboardShot` UI test +capture the real keyboard in the app and in Messages. + The app's screens follow the phone's appearance through the asset catalog's colour sets (generated from the `keyboard.app/*` tokens): `Page`, `Text`, `Muted`, `CardFill`, `CardBorder`, `AccentColor`, `CTA`, `CTAText`. @@ -319,41 +335,43 @@ uses them. `BlurtBrand` keeps a few of the Mac's names as aliases. -| Token | Value | Swift | Use | -| ---------------------- | --------- | -------------------------- | -------------------------------------------------------------------------- | -| `apple/dark-key` | `#6B6B6B` | `Brand.appleDarkKey` | the iPhone keyboard's dark key | -| `apple/dark-modifier` | `#464646` | `Brand.appleDarkModifier` | the iPhone keyboard's dark modifier key | -| `apple/dark-surface` | `#2B2B2B` | `Brand.appleDarkSurface` | the iPhone keyboard's dark surface | -| `apple/light-modifier` | `#ADB3BC` | `Brand.appleLightModifier` | the iPhone keyboard's light modifier key | -| `apple/light-surface` | `#D1D5DB` | `Brand.appleLightSurface` | the iPhone keyboard's light surface | -| `black` | `#000000` | `Brand.black` | — | -| `card` | `#EBE8E8` | `Brand.card` | the warm card fill; the paper theme's surface | -| `card-border` | `#DEDBDB` | `Brand.cardBorder` | the card's hairline; the paper theme's modifier key | -| `cobolt` | `#3923C7` | `Brand.cobolt` | AssemblyAI's primary violet: the drop, never a key or a surface | -| `green/100` | `#CCE4D5` | `Brand.green100` | the design system's UI-and-code green fill (unused on the phone yet) | -| `green/200` | `#99C8AC` | `Brand.green200` | the design system's UI-and-code green highlight (unused on the phone yet) | -| `green/400` | `#67AD82` | `Brand.green400` | the brand hue lifted for dark chrome: the meter, the ring, the wave on ink | -| `green/700` | `#01762F` | `Brand.green700` | the wordmark green, light chrome (the app's accent in light) | -| `green/mist` | `#DBF5E6` | `Brand.greenMist` | the pale green the orb lightens into | -| `ink` | `#1D1B16` | `Brand.ink` | the brand ink: the Mac pill's body, the ink theme's surface | -| `ink/600` | `#3A362F` | `Brand.ink600` | the Mac's dark card border | -| `ink/700` | `#33302A` | `Brand.ink700` | an ordinary key on ink, one step up | -| `ink/800` | `#26231E` | `Brand.ink800` | a modifier key on ink; the Mac's dark card fill | -| `neutral/300` | `#D2D1D0` | `Brand.neutral300` | black-100: the lightest warm grey | -| `neutral/500` | `#A5A4A2` | `Brand.neutral500` | black-200: mono labels on the dark face | -| `neutral/700` | `#777673` | `Brand.neutral700` | black-300: muted text and mono labels on the light face | -| `neutral/900` | `#4A4945` | `Brand.neutral900` | black-400: body text on the light face | -| `orange` | `#E67F36` | `Brand.orange` | the error word and ring, cancel, the Full Access note; never a red body | -| `paper/200` | `#ECEBE5` | `Brand.paper200` | neutral-100: the light face's surface | -| `paper/300` | `#DAD7CB` | `Brand.paper300` | neutral-200: a modifier key on the light face | -| `paper/400` | `#C7C3B2` | `Brand.paper400` | neutral-300: hairlines and field borders on the light face | -| `paper/page` | `#FDFCF8` | `Brand.paperPage` | the design system's page: the app's light ground | -| `paper/tint` | `#F5F3EB` | `Brand.paperTint` | the warm off-white one step in: light cards, dark legends | -| `violet/iris` | `#887BDD` | `Brand.violetIris` | the orb gradient's upper violet stop | -| `violet/lavender` | `#D7D3F4` | `Brand.violetLavender` | the orb's lightest violet: its top and the gradient's ends | -| `violet/periwinkle` | `#B0A7E9` | `Brand.violetPeriwinkle` | the orb's mid violet: the drop's halo | -| `warm-white` | `#F2EEE6` | `Brand.warmWhite` | key legends on ink: warm white on warm ink | -| `white` | `#FFFFFF` | `Brand.white` | — | +| Token | Value | Swift | Use | +| ------------------------ | --------- | ---------------------------- | ----------------------------------------------------------------------------------- | +| `apple/dark-key` | `#6B6B6B` | `Brand.appleDarkKey` | the iPhone keyboard's dark key | +| `apple/dark-modifier` | `#464646` | `Brand.appleDarkModifier` | the iPhone keyboard's dark modifier key | +| `apple/dark-surface` | `#2B2B2B` | `Brand.appleDarkSurface` | the iPhone keyboard's dark surface | +| `apple/light-modifier` | `#ADB3BC` | `Brand.appleLightModifier` | the iPhone keyboard's light modifier key | +| `apple/light-surface` | `#D1D5DB` | `Brand.appleLightSurface` | the iPhone keyboard's light surface | +| `black` | `#000000` | `Brand.black` | — | +| `card` | `#EBE8E8` | `Brand.card` | the warm card fill; the paper theme's surface | +| `card-border` | `#DEDBDB` | `Brand.cardBorder` | the card's hairline; the paper theme's modifier key | +| `cobolt` | `#3923C7` | `Brand.cobolt` | AssemblyAI's primary violet: the drop, never a key or a surface | +| `green/100` | `#CCE4D5` | `Brand.green100` | the design system's UI-and-code green fill (unused on the phone yet) | +| `green/200` | `#99C8AC` | `Brand.green200` | the design system's UI-and-code green highlight (unused on the phone yet) | +| `green/400` | `#67AD82` | `Brand.green400` | the brand hue lifted for dark chrome: the meter, the ring, the wave on ink | +| `green/700` | `#01762F` | `Brand.green700` | the wordmark green, light chrome (the app's accent in light) | +| `green/mist` | `#DBF5E6` | `Brand.greenMist` | the pale green the orb lightens into | +| `ink` | `#1D1B16` | `Brand.ink` | the brand ink: the Mac pill's body, the ink theme's surface | +| `ink/600` | `#3A362F` | `Brand.ink600` | the Mac's dark card border | +| `ink/700` | `#33302A` | `Brand.ink700` | an ordinary key on ink, one step up | +| `ink/800` | `#26231E` | `Brand.ink800` | a modifier key on ink; the Mac's dark card fill | +| `material/dark-key` | `#575757` | `Brand.materialDarkKey` | a key on the system's dark keyboard material (measured, iOS 27): the container case | +| `material/dark-modifier` | `#474747` | `Brand.materialDarkModifier` | a modifier key on the system's dark material | +| `neutral/300` | `#D2D1D0` | `Brand.neutral300` | black-100: the lightest warm grey | +| `neutral/500` | `#A5A4A2` | `Brand.neutral500` | black-200: mono labels on the dark face | +| `neutral/700` | `#777673` | `Brand.neutral700` | black-300: muted text and mono labels on the light face | +| `neutral/900` | `#4A4945` | `Brand.neutral900` | black-400: body text on the light face | +| `orange` | `#E67F36` | `Brand.orange` | the error word and ring, cancel, the Full Access note; never a red body | +| `paper/200` | `#ECEBE5` | `Brand.paper200` | neutral-100: the light face's surface | +| `paper/300` | `#DAD7CB` | `Brand.paper300` | neutral-200: a modifier key on the light face | +| `paper/400` | `#C7C3B2` | `Brand.paper400` | neutral-300: hairlines and field borders on the light face | +| `paper/page` | `#FDFCF8` | `Brand.paperPage` | the design system's page: the app's light ground | +| `paper/tint` | `#F5F3EB` | `Brand.paperTint` | the warm off-white one step in: light cards, dark legends | +| `violet/iris` | `#887BDD` | `Brand.violetIris` | the orb gradient's upper violet stop | +| `violet/lavender` | `#D7D3F4` | `Brand.violetLavender` | the orb's lightest violet: its top and the gradient's ends | +| `violet/periwinkle` | `#B0A7E9` | `Brand.violetPeriwinkle` | the orb's mid violet: the drop's halo | +| `warm-white` | `#F2EEE6` | `Brand.warmWhite` | key legends on ink: warm white on warm ink | +| `white` | `#FFFFFF` | `Brand.white` | — | @@ -407,124 +425,125 @@ pins the derivation. -| Token | Points | Swift | Use | -| ---------------------------- | --------- | ---------------------------------- | ---------------------------------------------------------------------------------------------- | -| `addterm/inset` | `6` | `Metrics.addtermInset` | the + from the panel's corner | -| `app/button-height` | `40` | `Metrics.appButtonHeight` | the brand's button | -| `app/button-pad` | `12` | `Metrics.appButtonPad` | its side padding | -| `app/card-pad` | `16` | `Metrics.appCardPad` | inside a card | -| `app/chip-gap` | `8` | `Metrics.appChipGap` | between chips | -| `app/chip-pad-x` | `12` | `Metrics.appChipPadX` | a style chip's side padding | -| `app/chip-pad-y` | `8` | `Metrics.appChipPadY` | and its top and bottom | -| `app/header-height` | `44` | `Metrics.appHeaderHeight` | the home header: wordmark and gear | -| `app/hero-gap` | `14` | `Metrics.appHeroGap` | between the hero's pieces | -| `app/hero-pad` | `20` | `Metrics.appHeroPad` | inside the hero card | -| `app/icon` | `20` | `Metrics.appIcon` | the header's gear, the copy glyph | -| `app/line-gap` | `6` | `Metrics.appLineGap` | between lines of one thought | -| `app/page-pad` | `20` | `Metrics.appPagePad` | the screens' side padding | -| `app/preview-gap` | `8` | `Metrics.appPreviewGap` | between the theme card's two faces | -| `app/section-gap` | `24` | `Metrics.appSectionGap` | between the home screen's sections | -| `app/setup-number-width` | `24` | `Metrics.appSetupNumberWidth` | the setup steps' mono numerals | -| `app/stack-gap` | `12` | `Metrics.appStackGap` | between a section's eyebrow and its content, and between cards | -| `card/border` | `1` | `Metrics.cardBorder` | the card's hairline | -| `card/radius` | `12` | `Metrics.cardRadius` | the app's cards (radius/card) | -| `caret/height` | `20` | `Metrics.caretHeight` | — | -| `caret/lead` | `1` | `Metrics.caretLead` | the caret's gap from the text | -| `caret/radius` | `1` | `Metrics.caretRadius` | — | -| `caret/width` | `2` | `Metrics.caretWidth` | — | -| `gesture/swipe-min` | `24` | `Metrics.gestureSwipeMin` | the carousel gesture's minimum distance | -| `glyph/hit` | `32` | `Metrics.glyphHit` | the +, × and ✓ touch targets | -| `grille/bar-height` | `28` | `Metrics.grilleBarHeight` | — | -| `grille/bar-width` | `64` | `Metrics.grilleBarWidth` | the grille in the voice bar | -| `grille/dot` | `2` | `Metrics.grilleDot` | a dot's diameter | -| `grille/glint-arm` | `1.6` | `Metrics.grilleGlintArm` | the cross glint's vertical arm, as a fraction of the grille's height | -| `grille/glint-width` | `1` | `Metrics.grilleGlintWidth` | the glint's arms | -| `grille/home-height` | `108` | `Metrics.grilleHomeHeight` | — | -| `grille/home-width` | `240` | `Metrics.grilleHomeWidth` | the grille on the home screen | -| `grille/panel-height` | `72` | `Metrics.grillePanelHeight` | — | -| `grille/panel-width` | `160` | `Metrics.grillePanelWidth` | the grille in the panel | -| `grille/pitch` | `4` | `Metrics.grillePitch` | the dot lattice: one dot every | -| `grille/sheen-width` | `0.35` | `Metrics.grilleSheenWidth` | the sheen's band, as a fraction of the width | -| `key/abc-width-402` | `43.333` | `Metrics.keyAbcWidth402` | 123 and the globe at 402 pt: the iPhone's | -| `key/gap` | `6` | `Metrics.keyGap` | between keys, the iPhone's | -| `key/height` | `43` | `Metrics.keyHeight` | every key: the iPhone's cap height (apple-geometry.json) | -| `key/letter-width-402` | `33.5` | `Metrics.keyLetterWidth402` | a letter key at 402 pt: (width − 2 × margin/side − 9 × key/gap) / 10 | -| `key/min-width` | `43.333` | `Metrics.keyMinWidth` | a key that isn't given a width: the iPhone's 123 key at 402 pt | -| `key/pad` | `4` | `Metrics.keyPad` | a legend's side padding on a min-width key | -| `key/radius` | `8` | `Metrics.keyRadius` | flat keys, one colour at this corner: the iPhone's (fitted 8.17) | -| `key/reference-width` | `402` | `Metrics.keyReferenceWidth` | the width the @402 tokens were measured at (iPhone 18 Pro); widths scale from it | -| `key/return-width-402` | `92.667` | `Metrics.keyReturnWidth402` | return at 402 pt: two 123 keys and a gap | -| `key/side-gap` | `13.667` | `Metrics.keySideGap` | shift and delete stand this far from the letters: the iPhone's | -| `key/side-width-402` | `45.583` | `Metrics.keySideWidth402` | shift and delete at 402 pt: what seven letters and the side gaps leave, halved (measured 45.5) | -| `key/space-width-402` | `191.667` | `Metrics.keySpaceWidth402` | space at 402 pt beside 123, the globe and return: what is left (measured 191.333) | -| `layout/full` | `270` | `Metrics.layoutFull` | margin/vertical + voicebar/height + 4 × key/height + 3 × row/gap + margin/bottom-keys | -| `layout/panel` | `216` | `Metrics.layoutPanel` | chosen: room for the 96 orb over one key row | -| `layout/slim` | `60` | `Metrics.layoutSlim` | 2 × margin/vertical + voicebar/height | -| `margin/bottom-keys` | `13` | `Metrics.marginBottomKeys` | under a bottom row of keys (the full keyboard, the panel): the iPhone's | -| `margin/side` | `6.5` | `Metrics.marginSide` | at the keyboard's sides: the iPhone's cap margin, (402 − 10 letters − 9 gaps) / 2 | -| `margin/vertical` | `8` | `Metrics.marginVertical` | the keyboard's top, and the slim bar's bottom | -| `opacity/disabled` | `0.4` | `Metrics.opacityDisabled` | the + without Full Access | -| `opacity/glint` | `0.95` | `Metrics.opacityGlint` | the cross glint when the words land | -| `opacity/grain-dark` | `0.14` | `Metrics.opacityGrainDark` | film grain over the dark face: matte, the brand's texture | -| `opacity/grain-light` | `0.08` | `Metrics.opacityGrainLight` | film grain over the light face: paper, lighter | -| `opacity/grille-rest` | `0.55` | `Metrics.opacityGrilleRest` | the dots at rest, over the key colour | -| `opacity/hairline` | `0.5` | `Metrics.opacityHairline` | — | -| `opacity/legend` | `1` | `Metrics.opacityLegend` | key legends over the cap; below 1 they sit back | -| `opacity/legend-muted` | `0.5` | `Metrics.opacityLegendMuted` | the + at rest | -| `opacity/off` | `0.45` | `Metrics.opacityOff` | the element when Blurt isn't ready: a tap opens the app | -| `opacity/placeholder` | `0.4` | `Metrics.opacityPlaceholder` | the field's placeholder | -| `opacity/popup-shadow` | `0.12` | `Metrics.opacityPopupShadow` | — | -| `opacity/press-brighten` | `0.15` | `Metrics.opacityPressBrighten` | a key lightens this much while pressed | -| `opacity/pressed` | `0.85` | `Metrics.opacityPressed` | a brand button while pressed: a colour change, no lift | -| `opacity/sheen` | `0.22` | `Metrics.opacitySheen` | the light passing over the element at rest: chrome catching light | -| `opacity/surface-vignette` | `0` | `Metrics.opacitySurfaceVignette` | a soft darkening toward the surface's edges; 0 is none | -| `opacity/term-cancel` | `0.7` | `Metrics.opacityTermCancel` | the field's × | -| `panel/spacing` | `12` | `Metrics.panelSpacing` | between the panel's orb and its key row | -| `picker/preview-width` | `393` | `Metrics.pickerPreviewWidth` | the theme card draws the keyboard at this width | -| `picker/radius` | `10` | `Metrics.pickerRadius` | the theme card's preview corners | -| `picker/scale` | `0.42` | `Metrics.pickerScale` | then scales it to fit two across | -| `popup/extra-width` | `18` | `Metrics.popupExtraWidth` | the letter pop-up is the key width plus this | -| `popup/height` | `56` | `Metrics.popupHeight` | — | -| `popup/offset` | `58` | `Metrics.popupOffset` | the pop-up sits this far above the key | -| `popup/radius` | `10` | `Metrics.popupRadius` | — | -| `popup/shadow-radius` | `8` | `Metrics.popupShadowRadius` | the one thing that floats | -| `popup/shadow-y` | `2` | `Metrics.popupShadowY` | — | -| `radius/button` | `4` | `Metrics.radiusButton` | the brand's buttons and the grille: rectangular, never a pill | -| `radius/card` | `12` | `Metrics.radiusCard` | the brand's cards | -| `radius/hero` | `16` | `Metrics.radiusHero` | the brand's featured cards | -| `radius/input` | `8` | `Metrics.radiusInput` | the brand's inputs: the key-term field | -| `ribs/rest-height` | `16` | `Metrics.ribsRestHeight` | — | -| `ribs/rest-width` | `40` | `Metrics.ribsRestWidth` | the ribs asleep: the wave's own bars at rest | -| `row/gap` | `11` | `Metrics.rowGap` | between rows, the iPhone's | -| `slim/spacing` | `8` | `Metrics.slimSpacing` | between the slim bar's keys | -| `streak/arm` | `1.4` | `Metrics.streakArm` | the landing flash's vertical arm, as a fraction of the box's height | -| `streak/height` | `2` | `Metrics.streakHeight` | the light streak while recording | -| `streak/line` | `1` | `Metrics.streakLine` | the hairline at rest | -| `streak/point` | `4` | `Metrics.streakPoint` | the bright point at the centre | -| `surface/vignette-end` | `0.75` | `Metrics.surfaceVignetteEnd` | where it is full | -| `surface/vignette-start` | `0.3` | `Metrics.surfaceVignetteStart` | where the vignette begins, as a fraction of the keyboard's width | -| `term/border` | `1` | `Metrics.termBorder` | the field's hairline | -| `term/gap` | `8` | `Metrics.termGap` | × · field · ✓ | -| `term/height` | `36` | `Metrics.termHeight` | the key-term field's capsule | -| `term/inset` | `2` | `Metrics.termInset` | the field row's side inset | -| `term/pad` | `14` | `Metrics.termPad` | the field's side padding | -| `term/radius` | `8` | `Metrics.termRadius` | the key-term field: the brand's input corners (radius/input) | -| `voice/bar-height` | `32` | `Metrics.voiceBarHeight` | — | -| `voice/bar-width` | `240` | `Metrics.voiceBarWidth` | the voice element's box in the voice bar: what the wave gets | -| `voice/home-height` | `112` | `Metrics.voiceHomeHeight` | — | -| `voice/home-width` | `280` | `Metrics.voiceHomeWidth` | the box on the home screen | -| `voice/panel-height` | `88` | `Metrics.voicePanelHeight` | — | -| `voice/panel-width` | `300` | `Metrics.voicePanelWidth` | the box in the panel | -| `voice/press-scale` | `0.94` | `Metrics.voicePressScale` | the element while pressed | -| `voicebar/addterm-clearance` | `12` | `Metrics.voicebarAddtermClearance` | the wave stays this clear of the + at the trailing edge | -| `voicebar/height` | `44` | `Metrics.voicebarHeight` | the voice row, where the system puts its suggestion bar | -| `voicebar/note-gap` | `10` | `Metrics.voicebarNoteGap` | between the orb and the Full Access note | -| `wave/bar` | `2` | `Metrics.waveBar` | a wave bar's width | -| `wave/bar-height` | `24` | `Metrics.waveBarHeight` | — | -| `wave/gap` | `2` | `Metrics.waveGap` | between wave bars | -| `wave/home-height` | `44` | `Metrics.waveHomeHeight` | — | -| `wave/panel-height` | `40` | `Metrics.wavePanelHeight` | — | -| `wordmark/height` | `22` | `Metrics.wordmarkHeight` | — | +| Token | Points | Swift | Use | +| ---------------------------- | --------- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `addterm/inset` | `6` | `Metrics.addtermInset` | the + from the panel's corner | +| `app/button-height` | `40` | `Metrics.appButtonHeight` | the brand's button | +| `app/button-pad` | `12` | `Metrics.appButtonPad` | its side padding | +| `app/card-pad` | `16` | `Metrics.appCardPad` | inside a card | +| `app/chip-gap` | `8` | `Metrics.appChipGap` | between chips | +| `app/chip-pad-x` | `12` | `Metrics.appChipPadX` | a style chip's side padding | +| `app/chip-pad-y` | `8` | `Metrics.appChipPadY` | and its top and bottom | +| `app/header-height` | `44` | `Metrics.appHeaderHeight` | the home header: wordmark and gear | +| `app/hero-gap` | `14` | `Metrics.appHeroGap` | between the hero's pieces | +| `app/hero-pad` | `20` | `Metrics.appHeroPad` | inside the hero card | +| `app/icon` | `20` | `Metrics.appIcon` | the header's gear, the copy glyph | +| `app/line-gap` | `6` | `Metrics.appLineGap` | between lines of one thought | +| `app/page-pad` | `20` | `Metrics.appPagePad` | the screens' side padding | +| `app/preview-gap` | `8` | `Metrics.appPreviewGap` | between the theme card's two faces | +| `app/section-gap` | `24` | `Metrics.appSectionGap` | between the home screen's sections | +| `app/setup-number-width` | `24` | `Metrics.appSetupNumberWidth` | the setup steps' mono numerals | +| `app/stack-gap` | `12` | `Metrics.appStackGap` | between a section's eyebrow and its content, and between cards | +| `card/border` | `1` | `Metrics.cardBorder` | the card's hairline | +| `card/radius` | `12` | `Metrics.cardRadius` | the app's cards (radius/card) | +| `caret/height` | `20` | `Metrics.caretHeight` | — | +| `caret/lead` | `1` | `Metrics.caretLead` | the caret's gap from the text | +| `caret/radius` | `1` | `Metrics.caretRadius` | — | +| `caret/width` | `2` | `Metrics.caretWidth` | — | +| `gesture/swipe-min` | `24` | `Metrics.gestureSwipeMin` | the carousel gesture's minimum distance | +| `glyph/hit` | `32` | `Metrics.glyphHit` | the +, × and ✓ touch targets | +| `grille/bar-height` | `28` | `Metrics.grilleBarHeight` | — | +| `grille/bar-width` | `64` | `Metrics.grilleBarWidth` | the grille in the voice bar | +| `grille/dot` | `2` | `Metrics.grilleDot` | a dot's diameter | +| `grille/glint-arm` | `1.6` | `Metrics.grilleGlintArm` | the cross glint's vertical arm, as a fraction of the grille's height | +| `grille/glint-width` | `1` | `Metrics.grilleGlintWidth` | the glint's arms | +| `grille/home-height` | `108` | `Metrics.grilleHomeHeight` | — | +| `grille/home-width` | `240` | `Metrics.grilleHomeWidth` | the grille on the home screen | +| `grille/panel-height` | `72` | `Metrics.grillePanelHeight` | — | +| `grille/panel-width` | `160` | `Metrics.grillePanelWidth` | the grille in the panel | +| `grille/pitch` | `4` | `Metrics.grillePitch` | the dot lattice: one dot every | +| `grille/sheen-width` | `0.35` | `Metrics.grilleSheenWidth` | the sheen's band, as a fraction of the width | +| `key/abc-width-402` | `43.333` | `Metrics.keyAbcWidth402` | 123 and the globe at 402 pt: the iPhone's | +| `key/gap` | `6` | `Metrics.keyGap` | between keys, the iPhone's | +| `key/height` | `43` | `Metrics.keyHeight` | every key: the iPhone's cap height (apple-geometry.json) | +| `key/letter-width-402` | `33.5` | `Metrics.keyLetterWidth402` | a letter key at 402 pt: (width − 2 × margin/side − 9 × key/gap) / 10 | +| `key/min-width` | `43.333` | `Metrics.keyMinWidth` | a key that isn't given a width: the iPhone's 123 key at 402 pt | +| `key/pad` | `4` | `Metrics.keyPad` | a legend's side padding on a min-width key | +| `key/radius` | `8` | `Metrics.keyRadius` | flat keys, one colour at this corner: the iPhone's (fitted 8.17) | +| `key/reference-width` | `402` | `Metrics.keyReferenceWidth` | the width the @402 tokens were measured at (iPhone 18 Pro); widths scale from it | +| `key/return-width-402` | `92.667` | `Metrics.keyReturnWidth402` | return at 402 pt: two 123 keys and a gap | +| `key/side-gap` | `13.667` | `Metrics.keySideGap` | shift and delete stand this far from the letters: the iPhone's | +| `key/side-width-402` | `45.583` | `Metrics.keySideWidth402` | shift and delete at 402 pt: what seven letters and the side gaps leave, halved (measured 45.5) | +| `key/space-width-402` | `191.667` | `Metrics.keySpaceWidth402` | space at 402 pt beside 123, the globe and return: what is left (measured 191.333) | +| `layout/full` | `270` | `Metrics.layoutFull` | margin/vertical + voicebar/height + 4 × key/height + 3 × row/gap + margin/bottom-keys | +| `layout/panel` | `216` | `Metrics.layoutPanel` | chosen: room for the 96 orb over one key row | +| `layout/slim` | `60` | `Metrics.layoutSlim` | 2 × margin/vertical + voicebar/height | +| `margin/bottom-keys` | `13` | `Metrics.marginBottomKeys` | under a bottom row of keys (the full keyboard, the panel): the iPhone's | +| `margin/side` | `6.5` | `Metrics.marginSide` | at the keyboard's sides: the iPhone's cap margin, (402 − 10 letters − 9 gaps) / 2 | +| `margin/vertical` | `8` | `Metrics.marginVertical` | the keyboard's top, and the slim bar's bottom | +| `opacity/disabled` | `0.4` | `Metrics.opacityDisabled` | the + without Full Access | +| `opacity/glint` | `0.95` | `Metrics.opacityGlint` | the cross glint when the words land | +| `opacity/grain-dark` | `0.14` | `Metrics.opacityGrainDark` | film grain over the dark face: matte, the brand's texture | +| `opacity/grain-light` | `0.08` | `Metrics.opacityGrainLight` | film grain over the light face: paper, lighter | +| `opacity/grille-rest` | `0.55` | `Metrics.opacityGrilleRest` | the dots at rest, over the key colour | +| `opacity/hairline` | `0.5` | `Metrics.opacityHairline` | — | +| `opacity/legend` | `1` | `Metrics.opacityLegend` | key legends over the cap; below 1 they sit back | +| `opacity/legend-muted` | `0.5` | `Metrics.opacityLegendMuted` | the + at rest | +| `opacity/off` | `0.45` | `Metrics.opacityOff` | the element when Blurt isn't ready: a tap opens the app | +| `opacity/placeholder` | `0.4` | `Metrics.opacityPlaceholder` | the field's placeholder | +| `opacity/popup-shadow` | `0.12` | `Metrics.opacityPopupShadow` | — | +| `opacity/press-brighten` | `0.15` | `Metrics.opacityPressBrighten` | a key lightens this much while pressed | +| `opacity/pressed` | `0.85` | `Metrics.opacityPressed` | a brand button while pressed: a colour change, no lift | +| `opacity/sheen` | `0.22` | `Metrics.opacitySheen` | the light passing over the element at rest: chrome catching light | +| `opacity/surface-vignette` | `0` | `Metrics.opacitySurfaceVignette` | a soft darkening toward the surface's edges; 0 is none | +| `opacity/term-cancel` | `0.7` | `Metrics.opacityTermCancel` | the field's × | +| `panel/spacing` | `12` | `Metrics.panelSpacing` | between the panel's orb and its key row | +| `picker/preview-width` | `393` | `Metrics.pickerPreviewWidth` | the theme card draws the keyboard at this width | +| `picker/radius` | `10` | `Metrics.pickerRadius` | the theme card's preview corners | +| `picker/scale` | `0.42` | `Metrics.pickerScale` | then scales it to fit two across | +| `popup/extra-width` | `18` | `Metrics.popupExtraWidth` | the letter pop-up is the key width plus this | +| `popup/height` | `56` | `Metrics.popupHeight` | — | +| `popup/offset` | `58` | `Metrics.popupOffset` | the pop-up sits this far above the key | +| `popup/radius` | `10` | `Metrics.popupRadius` | — | +| `popup/shadow-radius` | `8` | `Metrics.popupShadowRadius` | the one thing that floats | +| `popup/shadow-y` | `2` | `Metrics.popupShadowY` | — | +| `radius/button` | `4` | `Metrics.radiusButton` | the brand's buttons and the grille: rectangular, never a pill | +| `radius/card` | `12` | `Metrics.radiusCard` | the brand's cards | +| `radius/hero` | `16` | `Metrics.radiusHero` | the brand's featured cards | +| `radius/input` | `8` | `Metrics.radiusInput` | the brand's inputs: the key-term field | +| `ribs/rest-height` | `16` | `Metrics.ribsRestHeight` | — | +| `ribs/rest-width` | `40` | `Metrics.ribsRestWidth` | the ribs asleep: the wave's own bars at rest | +| `row/gap` | `11` | `Metrics.rowGap` | between rows, the iPhone's | +| `slim/spacing` | `8` | `Metrics.slimSpacing` | between the slim bar's keys | +| `streak/arm` | `1.4` | `Metrics.streakArm` | the landing flash's vertical arm, as a fraction of the box's height | +| `streak/height` | `2` | `Metrics.streakHeight` | the light streak while recording | +| `streak/line` | `1` | `Metrics.streakLine` | the hairline at rest | +| `streak/point` | `4` | `Metrics.streakPoint` | the bright point at the centre | +| `surface/paint` | `0` | `Metrics.surfacePaint` | 1 paints the face's surface under the keys; 0 leaves it clear, so the host's own keyboard material (iOS 26's rounded container, which insets a third-party keyboard and cannot be painted over) is the surface, seamlessly, and the keys take the container colours | +| `surface/vignette-end` | `0.75` | `Metrics.surfaceVignetteEnd` | where it is full | +| `surface/vignette-start` | `0.3` | `Metrics.surfaceVignetteStart` | where the vignette begins, as a fraction of the keyboard's width | +| `term/border` | `1` | `Metrics.termBorder` | the field's hairline | +| `term/gap` | `8` | `Metrics.termGap` | × · field · ✓ | +| `term/height` | `36` | `Metrics.termHeight` | the key-term field's capsule | +| `term/inset` | `2` | `Metrics.termInset` | the field row's side inset | +| `term/pad` | `14` | `Metrics.termPad` | the field's side padding | +| `term/radius` | `8` | `Metrics.termRadius` | the key-term field: the brand's input corners (radius/input) | +| `voice/bar-height` | `32` | `Metrics.voiceBarHeight` | — | +| `voice/bar-width` | `240` | `Metrics.voiceBarWidth` | the voice element's box in the voice bar: what the wave gets | +| `voice/home-height` | `112` | `Metrics.voiceHomeHeight` | — | +| `voice/home-width` | `280` | `Metrics.voiceHomeWidth` | the box on the home screen | +| `voice/panel-height` | `88` | `Metrics.voicePanelHeight` | — | +| `voice/panel-width` | `300` | `Metrics.voicePanelWidth` | the box in the panel | +| `voice/press-scale` | `0.94` | `Metrics.voicePressScale` | the element while pressed | +| `voicebar/addterm-clearance` | `12` | `Metrics.voicebarAddtermClearance` | the wave stays this clear of the + at the trailing edge | +| `voicebar/height` | `44` | `Metrics.voicebarHeight` | the voice row, where the system puts its suggestion bar | +| `voicebar/note-gap` | `10` | `Metrics.voicebarNoteGap` | between the orb and the Full Access note | +| `wave/bar` | `2` | `Metrics.waveBar` | a wave bar's width | +| `wave/bar-height` | `24` | `Metrics.waveBarHeight` | — | +| `wave/gap` | `2` | `Metrics.waveGap` | between wave bars | +| `wave/home-height` | `44` | `Metrics.waveHomeHeight` | — | +| `wave/panel-height` | `40` | `Metrics.wavePanelHeight` | — | +| `wordmark/height` | `22` | `Metrics.wordmarkHeight` | — | diff --git a/App/BlurtiOS/Design/figma/tokens.js b/App/BlurtiOS/Design/figma/tokens.js index 320b43f8..07813d1b 100644 --- a/App/BlurtiOS/Design/figma/tokens.js +++ b/App/BlurtiOS/Design/figma/tokens.js @@ -20,6 +20,8 @@ Brand|ink|COLOR|#1D1B16|||DesignTokens.Brand.ink|the brand ink: the Mac pill's b Brand|ink/600|COLOR|#3A362F|||DesignTokens.Brand.ink600|the Mac's dark card border Brand|ink/700|COLOR|#33302A|||DesignTokens.Brand.ink700|an ordinary key on ink, one step up Brand|ink/800|COLOR|#26231E|||DesignTokens.Brand.ink800|a modifier key on ink; the Mac's dark card fill +Brand|material/dark-key|COLOR|#575757|||DesignTokens.Brand.materialDarkKey|a key on the system's dark keyboard material (measured, iOS 27): the container case +Brand|material/dark-modifier|COLOR|#474747|||DesignTokens.Brand.materialDarkModifier|a modifier key on the system's dark material Brand|neutral/300|COLOR|#D2D1D0|||DesignTokens.Brand.neutral300|black-100: the lightest warm grey Brand|neutral/500|COLOR|#A5A4A2|||DesignTokens.Brand.neutral500|black-200: mono labels on the dark face Brand|neutral/700|COLOR|#777673|||DesignTokens.Brand.neutral700|black-300: muted text and mono labels on the light face @@ -35,6 +37,8 @@ Brand|violet/lavender|COLOR|#D7D3F4|||DesignTokens.Brand.violetLavender|the orb' Brand|violet/periwinkle|COLOR|#B0A7E9|||DesignTokens.Brand.violetPeriwinkle|the orb's mid violet: the drop's halo Brand|warm-white|COLOR|#F2EEE6|||DesignTokens.Brand.warmWhite|key legends on ink: warm white on warm ink Brand|white|COLOR|#FFFFFF|||DesignTokens.Brand.white| +Themes|dark/container-key|COLOR|#575757|Brand:material/dark-key||DesignTokens.Themes.darkContainerKey| +Themes|dark/container-key-modifier|COLOR|#474747|Brand:material/dark-modifier||DesignTokens.Themes.darkContainerKeyModifier| Themes|dark/field|COLOR|#33302A|Brand:ink/700||DesignTokens.Themes.darkField| Themes|dark/field-border|COLOR|#3A362F|Brand:ink/600||DesignTokens.Themes.darkFieldBorder| Themes|dark/key|COLOR|#33302A|Brand:ink/700||DesignTokens.Themes.darkKey| @@ -45,6 +49,8 @@ Themes|dark/notice|COLOR|#E67F36|Brand:orange||DesignTokens.Themes.darkNotice| Themes|dark/popup|COLOR|#33302A|Brand:ink/700||DesignTokens.Themes.darkPopup| Themes|dark/signal|COLOR|#67AD82|Brand:green/400||DesignTokens.Themes.darkSignal| Themes|dark/surface|COLOR|#1D1B16|Brand:ink||DesignTokens.Themes.darkSurface| +Themes|light/container-key|COLOR|#FFFFFF|Brand:white||DesignTokens.Themes.lightContainerKey| +Themes|light/container-key-modifier|COLOR|#DAD7CB|Brand:paper/300||DesignTokens.Themes.lightContainerKeyModifier| Themes|light/field|COLOR|#FFFFFF|Brand:white||DesignTokens.Themes.lightField| Themes|light/field-border|COLOR|#C7C3B2|Brand:paper/400||DesignTokens.Themes.lightFieldBorder| Themes|light/key|COLOR|#FFFFFF|Brand:white||DesignTokens.Themes.lightKey| @@ -175,6 +181,7 @@ Metrics|streak/arm|FLOAT|1.4||WIDTH_HEIGHT|DesignTokens.Metrics.streakArm|the la Metrics|streak/height|FLOAT|2||WIDTH_HEIGHT|DesignTokens.Metrics.streakHeight|the light streak while recording Metrics|streak/line|FLOAT|1||WIDTH_HEIGHT|DesignTokens.Metrics.streakLine|the hairline at rest Metrics|streak/point|FLOAT|4||WIDTH_HEIGHT|DesignTokens.Metrics.streakPoint|the bright point at the centre +Metrics|surface/paint|FLOAT|0||WIDTH_HEIGHT|DesignTokens.Metrics.surfacePaint|1 paints the face's surface under the keys; 0 leaves it clear, so the host's own keyboard material (iOS 26's rounded container, which insets a third-party keyboard and cannot be painted over) is the surface, seamlessly, and the keys take the container colours Metrics|surface/vignette-end|FLOAT|0.75||WIDTH_HEIGHT|DesignTokens.Metrics.surfaceVignetteEnd|where it is full Metrics|surface/vignette-start|FLOAT|0.3||WIDTH_HEIGHT|DesignTokens.Metrics.surfaceVignetteStart|where the vignette begins, as a fraction of the keyboard's width Metrics|term/border|FLOAT|1||WIDTH_HEIGHT|DesignTokens.Metrics.termBorder|the field's hairline diff --git a/App/BlurtiOS/Design/tokens.json b/App/BlurtiOS/Design/tokens.json index 06a7b2ac..9d0cb3f0 100644 --- a/App/BlurtiOS/Design/tokens.json +++ b/App/BlurtiOS/Design/tokens.json @@ -135,6 +135,14 @@ "neutral/300": { "value": "#D2D1D0", "use": "black-100: the lightest warm grey" + }, + "material/dark-key": { + "value": "#575757", + "use": "a key on the system's dark keyboard material (measured, iOS 27): the container case" + }, + "material/dark-modifier": { + "value": "#474747", + "use": "a modifier key on the system's dark material" } }, "themes": { @@ -148,6 +156,8 @@ "light/field": "{brand.white}", "light/field-border": "{brand.paper/400}", "light/notice": "{brand.orange}", + "light/container-key": "{brand.white}", + "light/container-key-modifier": "{brand.paper/300}", "dark/surface": "{brand.ink}", "dark/key": "{brand.ink/700}", "dark/key-modifier": "{brand.ink/800}", @@ -157,7 +167,9 @@ "dark/popup": "{brand.ink/700}", "dark/field": "{brand.ink/700}", "dark/field-border": "{brand.ink/600}", - "dark/notice": "{brand.orange}" + "dark/notice": "{brand.orange}", + "dark/container-key": "{brand.material/dark-key}", + "dark/container-key-modifier": "{brand.material/dark-modifier}" }, "keyboard": { "kb/surface": { @@ -719,6 +731,10 @@ "opacity/pressed": { "value": 0.85, "use": "a brand button while pressed: a colour change, no lift" + }, + "surface/paint": { + "value": 0, + "use": "1 paints the face's surface under the keys; 0 leaves it clear, so the host's own keyboard material (iOS 26's rounded container, which insets a third-party keyboard and cannot be painted over) is the surface, seamlessly, and the keys take the container colours" } }, "type": { diff --git a/App/BlurtiOS/Shared/DesignTokens.swift b/App/BlurtiOS/Shared/DesignTokens.swift index 82c6a56c..81674891 100644 --- a/App/BlurtiOS/Shared/DesignTokens.swift +++ b/App/BlurtiOS/Shared/DesignTokens.swift @@ -47,6 +47,10 @@ enum DesignTokens { nonisolated static let ink700: Color = Color(hex: 0x33302A) /// A modifier key on ink; the Mac's dark card fill. nonisolated static let ink800: Color = Color(hex: 0x26231E) + /// A key on the system's dark keyboard material (measured, iOS 27): the container case. + nonisolated static let materialDarkKey: Color = Color(hex: 0x575757) + /// A modifier key on the system's dark material. + nonisolated static let materialDarkModifier: Color = Color(hex: 0x474747) /// Black-100: the lightest warm grey. nonisolated static let neutral300: Color = Color(hex: 0xD2D1D0) /// Black-200: mono labels on the dark face. @@ -79,6 +83,10 @@ enum DesignTokens { } enum Themes { + /// `brand.material/dark-key`. + nonisolated static let darkContainerKey: Color = Brand.materialDarkKey + /// `brand.material/dark-modifier`. + nonisolated static let darkContainerKeyModifier: Color = Brand.materialDarkModifier /// `brand.ink/700`. nonisolated static let darkField: Color = Brand.ink700 /// `brand.ink/600`. @@ -100,6 +108,10 @@ enum DesignTokens { /// `brand.ink`. nonisolated static let darkSurface: Color = Brand.ink /// `brand.white`. + nonisolated static let lightContainerKey: Color = Brand.white + /// `brand.paper/300`. + nonisolated static let lightContainerKeyModifier: Color = Brand.paper300 + /// `brand.white`. nonisolated static let lightField: Color = Brand.white /// `brand.paper/400`. nonisolated static let lightFieldBorder: Color = Brand.paper400 @@ -353,6 +365,8 @@ enum DesignTokens { nonisolated static let streakLine: CGFloat = 1 /// The bright point at the centre. nonisolated static let streakPoint: CGFloat = 4 + /// 1 paints the face's surface under the keys; 0 leaves it clear, so the host's own keyboard material (iOS 26's rounded container, which insets a third-party keyboard and cannot be painted over) is the surface, seamlessly, and the keys take the container colours. + nonisolated static let surfacePaint: CGFloat = 0 /// Where it is full. nonisolated static let surfaceVignetteEnd: CGFloat = 0.75 /// Where the vignette begins, as a fraction of the keyboard's width. @@ -507,6 +521,8 @@ enum DesignTokens { "brand.ink/600": "#3A362F", "brand.ink/700": "#33302A", "brand.ink/800": "#26231E", + "brand.material/dark-key": "#575757", + "brand.material/dark-modifier": "#474747", "brand.neutral/300": "#D2D1D0", "brand.neutral/500": "#A5A4A2", "brand.neutral/700": "#777673", @@ -522,6 +538,8 @@ enum DesignTokens { "brand.violet/periwinkle": "#B0A7E9", "brand.warm-white": "#F2EEE6", "brand.white": "#FFFFFF", + "themes.dark/container-key": "#575757", + "themes.dark/container-key-modifier": "#474747", "themes.dark/field": "#33302A", "themes.dark/field-border": "#3A362F", "themes.dark/key": "#33302A", @@ -532,6 +550,8 @@ enum DesignTokens { "themes.dark/popup": "#33302A", "themes.dark/signal": "#67AD82", "themes.dark/surface": "#1D1B16", + "themes.light/container-key": "#FFFFFF", + "themes.light/container-key-modifier": "#DAD7CB", "themes.light/field": "#FFFFFF", "themes.light/field-border": "#C7C3B2", "themes.light/key": "#FFFFFF", @@ -662,6 +682,7 @@ enum DesignTokens { "metrics.streak/height": "2", "metrics.streak/line": "1", "metrics.streak/point": "4", + "metrics.surface/paint": "0", "metrics.surface/vignette-end": "0.75", "metrics.surface/vignette-start": "0.3", "metrics.term/border": "1", diff --git a/scripts/design-tokens.swift b/scripts/design-tokens.swift index 4ac75dea..44a0a842 100755 --- a/scripts/design-tokens.swift +++ b/scripts/design-tokens.swift @@ -338,9 +338,13 @@ let themeNames = tokens.filter { $0.group == "themes" }.map { String($0.name.spl let themeOrder = ["light", "dark"] + Set(themeNames).subtracting(["light", "dark"]).sorted() let roles = [ "surface", "key", "key-modifier", "legend", "legend-secondary", "signal", "popup", "field", "field-border", "notice", + "container-key", "container-key-modifier", ] blocks["themes"] = table( - ["Face", "Surface", "Key", "Modifier", "Legend", "Secondary", "Signal", "Pop-up", "Field", "Field border", "Notice"], + [ + "Face", "Surface", "Key", "Modifier", "Legend", "Secondary", "Signal", "Pop-up", "Field", "Field border", "Notice", + "Key in container", "Modifier in container", + ], themeOrder.compactMap { theme -> [String]? in let cells = roles.compactMap { role in byQualified["themes.\(theme)/\(role)"].map { code(rendered($0)) } } guard cells.count == roles.count else { return nil } diff --git a/scripts/ios-keyboard-shot.sh b/scripts/ios-keyboard-shot.sh index 9970ee34..33942620 100755 --- a/scripts/ios-keyboard-shot.sh +++ b/scripts/ios-keyboard-shot.sh @@ -61,6 +61,11 @@ WORK="$(mktemp -d)" trap 'rm -rf "$WORK"' EXIT (cd "$REPO_ROOT/App/BlurtiOS" && xcodegen generate --quiet) +# `xcodebuild test` does not reinstall a host app it thinks it has installed; +# the keyboard is inside it, so the last build is put on the simulator first. +xcodebuild build -project "$REPO_ROOT/App/BlurtiOS/BlurtiOS.xcodeproj" -scheme BlurtiOS \ + -destination "platform=iOS Simulator,id=$UDID" -derivedDataPath "$DERIVED" "${IOS_SIM_SIGNING[@]}" -quiet +xcrun simctl install "$UDID" "$DERIVED/Build/Products/Debug-iphonesimulator/BlurtiOS.app" # xcodebuild hands the test runner only the environment variables prefixed # TEST_RUNNER_; the test reads BLURT_PROBE_ARGS. if ! TEST_RUNNER_BLURT_PROBE_ARGS="$FACE $VOICE $LAYOUT" xcodebuild test -project "$REPO_ROOT/App/BlurtiOS/BlurtiOS.xcodeproj" \ From 6c9129dd18f5b4c1644f8557ec0118e2617515cd Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Wed, 30 Sep 2026 09:30:40 -0400 Subject: [PATCH 59/79] Keyboard: the return key says return; the element and the + sit centred MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The return key is a word like the other labels — `RETURN` in the mono eyebrow, or the field's own send / go / done / search / next / join — on all three layouts, no glyph. In the voice row the element and the + are one centred pair with the clearance between them, instead of the + off at the trailing edge; the bar's box narrows to 160 so the pair reads centred. The gallery, the theme picker and the voice stills stand the host's keyboard material (measured: #E2E3E8 light, #373737 dark, now `material/*` tokens and the faces' `material` role) under a clear surface, so a capture looks like the keyboard does in a host and the registration crop finds its border again. Co-Authored-By: Claude Fable 5.1 --- .../Sources/FullKeyboardView.swift | 5 +- .../Sources/KeyboardPalette.swift | 14 ++- .../BlurtKeyboard/Sources/PanelView.swift | 2 +- .../BlurtKeyboard/Sources/SlimBarView.swift | 2 +- .../BlurtKeyboard/Sources/VoiceBar.swift | 16 ++- .../Sources/KeyboardGalleryView.swift | 4 +- .../BlurtiOS/Sources/ThemePickerView.swift | 1 + .../BlurtiOSTests/DesignTokensTests.swift | 5 +- App/BlurtiOS/DESIGN.md | 98 ++++++++++--------- App/BlurtiOS/Design/figma/tokens.js | 8 +- App/BlurtiOS/Design/tokens.json | 18 +++- App/BlurtiOS/Shared/DesignTokens.swift | 20 +++- scripts/design-tokens.swift | 4 +- 13 files changed, 117 insertions(+), 80 deletions(-) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift b/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift index fbfd50b3..c8e88ef3 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift @@ -48,10 +48,7 @@ struct FullKeyboardView: View { KeyCap(systemImage: "globe", dark: true, width: geometry.abcWidth) { model.globe() } } KeyCap(title: "space", flexible: true) { model.space() } - KeyCap( - title: model.returnLabel, systemImage: model.returnLabel == nil ? "return" : nil, dark: true, - width: geometry.returnWidth - ) { model.newline() } + KeyCap(title: model.returnLabel ?? "return", dark: true, width: geometry.returnWidth) { model.newline() } } } } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift index e5d957bc..d22fb6e2 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift @@ -46,6 +46,9 @@ struct KeyboardPalette: Equatable, Identifiable { /// colours that read on the system's light or dark material. let containerKey: Color let containerKeyModifier: Color + /// The host's material under a clear surface, as the gallery and the home + /// screen stand in for it (the system's own keyboard colour, measured). + let material: Color static let keyGap = DesignTokens.Metrics.keyGap static let rowGap = DesignTokens.Metrics.rowGap @@ -67,7 +70,8 @@ struct KeyboardPalette: Equatable, Identifiable { keyText: Themes.lightLegend, keyTextSecondary: Themes.lightLegendSecondary, signal: Themes.lightSignal, popupFill: Themes.lightPopup, field: Themes.lightField, fieldBorder: Themes.lightFieldBorder, notice: Themes.lightNotice, grain: DesignTokens.Metrics.opacityGrainLight, - containerKey: Themes.lightContainerKey, containerKeyModifier: Themes.lightContainerKeyModifier) + containerKey: Themes.lightContainerKey, containerKeyModifier: Themes.lightContainerKeyModifier, + material: Themes.lightMaterial) /// The dark face: ink `#1D1B16`, `#33302A` keys, `#26231E` modifiers, warm /// white legends, the lifted green. @@ -77,7 +81,8 @@ struct KeyboardPalette: Equatable, Identifiable { keyText: Themes.darkLegend, keyTextSecondary: Themes.darkLegendSecondary, signal: Themes.darkSignal, popupFill: Themes.darkPopup, field: Themes.darkField, fieldBorder: Themes.darkFieldBorder, notice: Themes.darkNotice, grain: DesignTokens.Metrics.opacityGrainDark, - containerKey: Themes.darkContainerKey, containerKeyModifier: Themes.darkContainerKeyModifier) + containerKey: Themes.darkContainerKey, containerKeyModifier: Themes.darkContainerKeyModifier, + material: Themes.darkMaterial) /// The picker's list, one entry per theme (a theme's two faces share an id). static let all: [KeyboardPalette] = [brandLight] @@ -90,6 +95,11 @@ struct KeyboardPalette: Equatable, Identifiable { return dark ? brandDark : brandLight } + /// What stands under the keyboard where the host's material would be + /// (the gallery, a preview): the face's surface when it is painted, else + /// the material. + var standIn: Color { KeyboardRootView.paintsSurface ? surface : material } + /// A key's fill: the face's, or the container's when the host's material /// is the surface. func keyFill(modifier: Bool, inContainer: Bool) -> Color { diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/PanelView.swift b/App/BlurtiOS/BlurtKeyboard/Sources/PanelView.swift index 715ae9ae..72bc6744 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/PanelView.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/PanelView.swift @@ -15,7 +15,7 @@ struct PanelView: View { if model.needsGlobe { KeyCap(systemImage: "globe", dark: true) { model.globe() } } KeyCap(title: "space", flexible: true) { model.space() } KeyCap(systemImage: "delete.left", dark: true) { model.deleteBackward() } - KeyCap(systemImage: "return", dark: true) { model.newline() } + KeyCap(title: model.returnLabel ?? "return", dark: true) { model.newline() } } } .overlay(alignment: .topTrailing) { diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/SlimBarView.swift b/App/BlurtiOS/BlurtKeyboard/Sources/SlimBarView.swift index 30df9f88..38b639d9 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/SlimBarView.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/SlimBarView.swift @@ -9,7 +9,7 @@ struct SlimBarView: View { if model.needsGlobe { KeyCap(systemImage: "globe", dark: true) { model.globe() } } VoiceBar(model: model) KeyCap(systemImage: "delete.left", dark: true) { model.deleteBackward() } - KeyCap(systemImage: "return", dark: true) { model.newline() } + KeyCap(title: model.returnLabel ?? "return", dark: true) { model.newline() } } } } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift index 07b2ffab..e9fac69c 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift @@ -38,21 +38,19 @@ struct VoiceBar: View { .accessibilityLabel("Start Blurt") .transition(.opacity) } else { - // The element stays clear of the + at the trailing edge, on both sides so it stays centred. - let clearance = DesignTokens.Metrics.glyphHit + DesignTokens.Metrics.voicebarAddtermClearance - MicControl( - model: model, slot: .bar, - width: min(DesignTokens.Metrics.voiceBarWidth, geo.size.width - 2 * clearance) // literal-ok: both sides - ) + // The element and the + together, centred: the + rides beside the + // element, a clearance away, never off at the edge. + let plus = DesignTokens.Metrics.glyphHit + DesignTokens.Metrics.voicebarAddtermClearance + HStack(spacing: DesignTokens.Metrics.voicebarAddtermClearance) { + MicControl(model: model, slot: .bar, width: min(DesignTokens.Metrics.voiceBarWidth, geo.size.width - plus)) + AddTermKey(model: model) + } .transition(.opacity) } } .frame(maxWidth: .infinity, maxHeight: .infinity) } .frame(height: Self.height) - .overlay(alignment: .trailing) { - if model.termDraft == nil, model.hasFullAccess { AddTermKey(model: model) } - } .animation(.easeInOut(duration: DesignTokens.Motion.termSwap), value: model.termDraft == nil) } } diff --git a/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift b/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift index 8ce09933..1e160e6b 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift @@ -93,6 +93,8 @@ private func keyboard(_ row: Row) -> some View { KeyboardRootView(model: row.model) .frame(height: row.model.effectiveLayout.height) + // The host's material, under a clear surface, as the app stands in for it. + .background(row.model.palette.standIn) .clipped() .environment(\.keyboardMotionHeld, options.still) } @@ -211,7 +213,7 @@ Spacer(minLength: 0) } .frame(maxWidth: .infinity, maxHeight: .infinity) - .background(palette.surface) + .background(palette.standIn) .ignoresSafeArea() } diff --git a/App/BlurtiOS/BlurtiOS/Sources/ThemePickerView.swift b/App/BlurtiOS/BlurtiOS/Sources/ThemePickerView.swift index a14e06ca..8c60a5b6 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/ThemePickerView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/ThemePickerView.swift @@ -65,6 +65,7 @@ private struct ThemeCard: View { private func preview(_ face: KeyboardPalette) -> some View { KeyboardRootView(model: Self.model(for: face)) .frame(width: Self.previewWidth, height: KeyboardLayout.full.height) + .background(face.standIn) .scaleEffect(Self.scale, anchor: .topLeading) .frame(width: Self.previewWidth * Self.scale, height: KeyboardLayout.full.height * Self.scale) .clipShape(RoundedRectangle(cornerRadius: DesignTokens.Metrics.pickerRadius)) diff --git a/App/BlurtiOS/BlurtiOSTests/DesignTokensTests.swift b/App/BlurtiOS/BlurtiOSTests/DesignTokensTests.swift index 071f92e2..62fec0fd 100644 --- a/App/BlurtiOS/BlurtiOSTests/DesignTokensTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/DesignTokensTests.swift @@ -117,6 +117,7 @@ struct DesignTokensTests { Themes.lightSurface, Themes.lightKey, Themes.lightKeyModifier, Themes.lightLegend, Themes.lightLegendSecondary, Themes.lightSignal, Themes.lightPopup, Themes.lightField, Themes.lightFieldBorder, Themes.lightNotice, Themes.lightContainerKey, Themes.lightContainerKeyModifier, + Themes.lightMaterial, ] ), ( @@ -124,7 +125,7 @@ struct DesignTokensTests { [ Themes.darkSurface, Themes.darkKey, Themes.darkKeyModifier, Themes.darkLegend, Themes.darkLegendSecondary, Themes.darkSignal, Themes.darkPopup, Themes.darkField, Themes.darkFieldBorder, Themes.darkNotice, - Themes.darkContainerKey, Themes.darkContainerKeyModifier, + Themes.darkContainerKey, Themes.darkContainerKeyModifier, Themes.darkMaterial, ] ), ] @@ -137,7 +138,7 @@ struct DesignTokensTests { let roles = [ palette.surface, palette.key, palette.keyDark, palette.keyText, palette.keyTextSecondary, palette.signal, palette.popupFill, palette.field, palette.fieldBorder, palette.notice, palette.containerKey, - palette.containerKeyModifier, + palette.containerKeyModifier, palette.material, ] #expect(roles == colors, "\(palette.id) \(palette.face)") } diff --git a/App/BlurtiOS/DESIGN.md b/App/BlurtiOS/DESIGN.md index 0addd572..0761b692 100644 --- a/App/BlurtiOS/DESIGN.md +++ b/App/BlurtiOS/DESIGN.md @@ -80,10 +80,10 @@ the brand's face. Ten roles each (`BlurtKeyboard/Sources/KeyboardPalette.swift`) -| Face | Surface | Key | Modifier | Legend | Secondary | Signal | Pop-up | Field | Field border | Notice | Key in container | Modifier in container | -| ------- | --------- | --------- | --------- | --------- | --------- | --------- | --------- | --------- | ------------ | --------- | ---------------- | --------------------- | -| `light` | `#ECEBE5` | `#FFFFFF` | `#DAD7CB` | `#1D1B16` | `#777673` | `#01762F` | `#FFFFFF` | `#FFFFFF` | `#C7C3B2` | `#E67F36` | `#FFFFFF` | `#DAD7CB` | -| `dark` | `#1D1B16` | `#33302A` | `#26231E` | `#F5F3EB` | `#A5A4A2` | `#67AD82` | `#33302A` | `#33302A` | `#3A362F` | `#E67F36` | `#575757` | `#474747` | +| Face | Surface | Key | Modifier | Legend | Secondary | Signal | Pop-up | Field | Field border | Notice | Key in container | Modifier in container | Host material | +| ------- | --------- | --------- | --------- | --------- | --------- | --------- | --------- | --------- | ------------ | --------- | ---------------- | --------------------- | ------------- | +| `light` | `#ECEBE5` | `#FFFFFF` | `#DAD7CB` | `#1D1B16` | `#777673` | `#01762F` | `#FFFFFF` | `#FFFFFF` | `#C7C3B2` | `#E67F36` | `#FFFFFF` | `#DAD7CB` | `#E2E3E8` | +| `dark` | `#1D1B16` | `#33302A` | `#26231E` | `#F5F3EB` | `#A5A4A2` | `#67AD82` | `#33302A` | `#33302A` | `#3A362F` | `#E67F36` | `#575757` | `#474747` | `#373737` | @@ -142,9 +142,9 @@ pop-up carries the one shadow on the keyboard, a whisper (12 %, radius 8), being the one thing that floats. Type: the letters are SF Pro at the iPhone's size, and the glyph keys — shift, -delete, globe, return, the +, × and ✓ — SF Symbols, so the keyboard feels -native under the fingers. Every **word** on a key — `123`, `ABC`, `#+=`, -`space`, the return key's `send` / `go` / `done` / `search` / `next` / `join` — +delete, globe, the +, × and ✓ — SF Symbols, so the keyboard feels native +under the fingers. Every **word** on a key — `123`, `ABC`, `#+=`, `space`, +`return` and the field's own `send` / `go` / `done` / `search` / `next` / `join` — is the brand's eyebrow: Modern Gothic Mono, medium, 12 pt, uppercase, +1.2 tracking, in the face's secondary legend, a step quieter than a letter. Fixed point sizes throughout, as the system keyboard's; no Dynamic Type. @@ -267,7 +267,7 @@ slim bar 8. | `full` | voice row 44, then the first key row right under it as the iPhone's sits under its suggestions · three letter rows 43 · 123 / globe / space / return | 270 | The voice row (`VoiceBar`) is where the system keyboard puts its suggestion -bar: the element, the + beside it at the trailing edge, or the key-term +bar: the element with the + beside it, the pair centred, or the key-term field. A swipe flips the panel past 48 pt sideways and more sideways than up or down by 1.5×; a key acts on release and only under 12 pt of travel (`KeyboardInteraction`, tested). @@ -312,7 +312,7 @@ term, name or sender over 80 characters. Nothing to configure: key clicks play only if the user has keyboard clicks on; the return key says what the field asks — send, search, go, done, next, -join — with the glyph otherwise; a number, decimal or phone field opens on +join — and `return` otherwise; a number, decimal or phone field opens on the symbols page; capitalisation follows the field's `autocapitalizationType`; the letter rows follow the phone's first language (AZERTY for French, QWERTZ for German, Czech, Slovak and Hungarian, QWERTY otherwise); the face follows @@ -335,43 +335,45 @@ uses them. `BlurtBrand` keeps a few of the Mac's names as aliases. -| Token | Value | Swift | Use | -| ------------------------ | --------- | ---------------------------- | ----------------------------------------------------------------------------------- | -| `apple/dark-key` | `#6B6B6B` | `Brand.appleDarkKey` | the iPhone keyboard's dark key | -| `apple/dark-modifier` | `#464646` | `Brand.appleDarkModifier` | the iPhone keyboard's dark modifier key | -| `apple/dark-surface` | `#2B2B2B` | `Brand.appleDarkSurface` | the iPhone keyboard's dark surface | -| `apple/light-modifier` | `#ADB3BC` | `Brand.appleLightModifier` | the iPhone keyboard's light modifier key | -| `apple/light-surface` | `#D1D5DB` | `Brand.appleLightSurface` | the iPhone keyboard's light surface | -| `black` | `#000000` | `Brand.black` | — | -| `card` | `#EBE8E8` | `Brand.card` | the warm card fill; the paper theme's surface | -| `card-border` | `#DEDBDB` | `Brand.cardBorder` | the card's hairline; the paper theme's modifier key | -| `cobolt` | `#3923C7` | `Brand.cobolt` | AssemblyAI's primary violet: the drop, never a key or a surface | -| `green/100` | `#CCE4D5` | `Brand.green100` | the design system's UI-and-code green fill (unused on the phone yet) | -| `green/200` | `#99C8AC` | `Brand.green200` | the design system's UI-and-code green highlight (unused on the phone yet) | -| `green/400` | `#67AD82` | `Brand.green400` | the brand hue lifted for dark chrome: the meter, the ring, the wave on ink | -| `green/700` | `#01762F` | `Brand.green700` | the wordmark green, light chrome (the app's accent in light) | -| `green/mist` | `#DBF5E6` | `Brand.greenMist` | the pale green the orb lightens into | -| `ink` | `#1D1B16` | `Brand.ink` | the brand ink: the Mac pill's body, the ink theme's surface | -| `ink/600` | `#3A362F` | `Brand.ink600` | the Mac's dark card border | -| `ink/700` | `#33302A` | `Brand.ink700` | an ordinary key on ink, one step up | -| `ink/800` | `#26231E` | `Brand.ink800` | a modifier key on ink; the Mac's dark card fill | -| `material/dark-key` | `#575757` | `Brand.materialDarkKey` | a key on the system's dark keyboard material (measured, iOS 27): the container case | -| `material/dark-modifier` | `#474747` | `Brand.materialDarkModifier` | a modifier key on the system's dark material | -| `neutral/300` | `#D2D1D0` | `Brand.neutral300` | black-100: the lightest warm grey | -| `neutral/500` | `#A5A4A2` | `Brand.neutral500` | black-200: mono labels on the dark face | -| `neutral/700` | `#777673` | `Brand.neutral700` | black-300: muted text and mono labels on the light face | -| `neutral/900` | `#4A4945` | `Brand.neutral900` | black-400: body text on the light face | -| `orange` | `#E67F36` | `Brand.orange` | the error word and ring, cancel, the Full Access note; never a red body | -| `paper/200` | `#ECEBE5` | `Brand.paper200` | neutral-100: the light face's surface | -| `paper/300` | `#DAD7CB` | `Brand.paper300` | neutral-200: a modifier key on the light face | -| `paper/400` | `#C7C3B2` | `Brand.paper400` | neutral-300: hairlines and field borders on the light face | -| `paper/page` | `#FDFCF8` | `Brand.paperPage` | the design system's page: the app's light ground | -| `paper/tint` | `#F5F3EB` | `Brand.paperTint` | the warm off-white one step in: light cards, dark legends | -| `violet/iris` | `#887BDD` | `Brand.violetIris` | the orb gradient's upper violet stop | -| `violet/lavender` | `#D7D3F4` | `Brand.violetLavender` | the orb's lightest violet: its top and the gradient's ends | -| `violet/periwinkle` | `#B0A7E9` | `Brand.violetPeriwinkle` | the orb's mid violet: the drop's halo | -| `warm-white` | `#F2EEE6` | `Brand.warmWhite` | key legends on ink: warm white on warm ink | -| `white` | `#FFFFFF` | `Brand.white` | — | +| Token | Value | Swift | Use | +| ------------------------ | --------- | ---------------------------- | ------------------------------------------------------------------------------------------------------ | +| `apple/dark-key` | `#6B6B6B` | `Brand.appleDarkKey` | the iPhone keyboard's dark key | +| `apple/dark-modifier` | `#464646` | `Brand.appleDarkModifier` | the iPhone keyboard's dark modifier key | +| `apple/dark-surface` | `#2B2B2B` | `Brand.appleDarkSurface` | the iPhone keyboard's dark surface | +| `apple/light-modifier` | `#ADB3BC` | `Brand.appleLightModifier` | the iPhone keyboard's light modifier key | +| `apple/light-surface` | `#D1D5DB` | `Brand.appleLightSurface` | the iPhone keyboard's light surface | +| `black` | `#000000` | `Brand.black` | — | +| `card` | `#EBE8E8` | `Brand.card` | the warm card fill; the paper theme's surface | +| `card-border` | `#DEDBDB` | `Brand.cardBorder` | the card's hairline; the paper theme's modifier key | +| `cobolt` | `#3923C7` | `Brand.cobolt` | AssemblyAI's primary violet: the drop, never a key or a surface | +| `green/100` | `#CCE4D5` | `Brand.green100` | the design system's UI-and-code green fill (unused on the phone yet) | +| `green/200` | `#99C8AC` | `Brand.green200` | the design system's UI-and-code green highlight (unused on the phone yet) | +| `green/400` | `#67AD82` | `Brand.green400` | the brand hue lifted for dark chrome: the meter, the ring, the wave on ink | +| `green/700` | `#01762F` | `Brand.green700` | the wordmark green, light chrome (the app's accent in light) | +| `green/mist` | `#DBF5E6` | `Brand.greenMist` | the pale green the orb lightens into | +| `ink` | `#1D1B16` | `Brand.ink` | the brand ink: the Mac pill's body, the ink theme's surface | +| `ink/600` | `#3A362F` | `Brand.ink600` | the Mac's dark card border | +| `ink/700` | `#33302A` | `Brand.ink700` | an ordinary key on ink, one step up | +| `ink/800` | `#26231E` | `Brand.ink800` | a modifier key on ink; the Mac's dark card fill | +| `material/dark-key` | `#575757` | `Brand.materialDarkKey` | a key on the system's dark keyboard material (measured, iOS 27): the container case | +| `material/dark-modifier` | `#474747` | `Brand.materialDarkModifier` | a modifier key on the system's dark material | +| `material/dark-surface` | `#373737` | `Brand.materialDarkSurface` | the system's dark keyboard material (measured, iOS 27) | +| `material/light-surface` | `#E2E3E8` | `Brand.materialLightSurface` | the system's light keyboard material (measured, iOS 27): what the gallery stands under a clear surface | +| `neutral/300` | `#D2D1D0` | `Brand.neutral300` | black-100: the lightest warm grey | +| `neutral/500` | `#A5A4A2` | `Brand.neutral500` | black-200: mono labels on the dark face | +| `neutral/700` | `#777673` | `Brand.neutral700` | black-300: muted text and mono labels on the light face | +| `neutral/900` | `#4A4945` | `Brand.neutral900` | black-400: body text on the light face | +| `orange` | `#E67F36` | `Brand.orange` | the error word and ring, cancel, the Full Access note; never a red body | +| `paper/200` | `#ECEBE5` | `Brand.paper200` | neutral-100: the light face's surface | +| `paper/300` | `#DAD7CB` | `Brand.paper300` | neutral-200: a modifier key on the light face | +| `paper/400` | `#C7C3B2` | `Brand.paper400` | neutral-300: hairlines and field borders on the light face | +| `paper/page` | `#FDFCF8` | `Brand.paperPage` | the design system's page: the app's light ground | +| `paper/tint` | `#F5F3EB` | `Brand.paperTint` | the warm off-white one step in: light cards, dark legends | +| `violet/iris` | `#887BDD` | `Brand.violetIris` | the orb gradient's upper violet stop | +| `violet/lavender` | `#D7D3F4` | `Brand.violetLavender` | the orb's lightest violet: its top and the gradient's ends | +| `violet/periwinkle` | `#B0A7E9` | `Brand.violetPeriwinkle` | the orb's mid violet: the drop's halo | +| `warm-white` | `#F2EEE6` | `Brand.warmWhite` | key legends on ink: warm white on warm ink | +| `white` | `#FFFFFF` | `Brand.white` | — | @@ -529,13 +531,13 @@ pins the derivation. | `term/pad` | `14` | `Metrics.termPad` | the field's side padding | | `term/radius` | `8` | `Metrics.termRadius` | the key-term field: the brand's input corners (radius/input) | | `voice/bar-height` | `32` | `Metrics.voiceBarHeight` | — | -| `voice/bar-width` | `240` | `Metrics.voiceBarWidth` | the voice element's box in the voice bar: what the wave gets | +| `voice/bar-width` | `160` | `Metrics.voiceBarWidth` | the voice element's box in the voice bar; with the + beside it the pair sits centred | | `voice/home-height` | `112` | `Metrics.voiceHomeHeight` | — | | `voice/home-width` | `280` | `Metrics.voiceHomeWidth` | the box on the home screen | | `voice/panel-height` | `88` | `Metrics.voicePanelHeight` | — | | `voice/panel-width` | `300` | `Metrics.voicePanelWidth` | the box in the panel | | `voice/press-scale` | `0.94` | `Metrics.voicePressScale` | the element while pressed | -| `voicebar/addterm-clearance` | `12` | `Metrics.voicebarAddtermClearance` | the wave stays this clear of the + at the trailing edge | +| `voicebar/addterm-clearance` | `12` | `Metrics.voicebarAddtermClearance` | between the element and the + | | `voicebar/height` | `44` | `Metrics.voicebarHeight` | the voice row, where the system puts its suggestion bar | | `voicebar/note-gap` | `10` | `Metrics.voicebarNoteGap` | between the orb and the Full Access note | | `wave/bar` | `2` | `Metrics.waveBar` | a wave bar's width | diff --git a/App/BlurtiOS/Design/figma/tokens.js b/App/BlurtiOS/Design/figma/tokens.js index 07813d1b..1e0cd5dd 100644 --- a/App/BlurtiOS/Design/figma/tokens.js +++ b/App/BlurtiOS/Design/figma/tokens.js @@ -22,6 +22,8 @@ Brand|ink/700|COLOR|#33302A|||DesignTokens.Brand.ink700|an ordinary key on ink, Brand|ink/800|COLOR|#26231E|||DesignTokens.Brand.ink800|a modifier key on ink; the Mac's dark card fill Brand|material/dark-key|COLOR|#575757|||DesignTokens.Brand.materialDarkKey|a key on the system's dark keyboard material (measured, iOS 27): the container case Brand|material/dark-modifier|COLOR|#474747|||DesignTokens.Brand.materialDarkModifier|a modifier key on the system's dark material +Brand|material/dark-surface|COLOR|#373737|||DesignTokens.Brand.materialDarkSurface|the system's dark keyboard material (measured, iOS 27) +Brand|material/light-surface|COLOR|#E2E3E8|||DesignTokens.Brand.materialLightSurface|the system's light keyboard material (measured, iOS 27): what the gallery stands under a clear surface Brand|neutral/300|COLOR|#D2D1D0|||DesignTokens.Brand.neutral300|black-100: the lightest warm grey Brand|neutral/500|COLOR|#A5A4A2|||DesignTokens.Brand.neutral500|black-200: mono labels on the dark face Brand|neutral/700|COLOR|#777673|||DesignTokens.Brand.neutral700|black-300: muted text and mono labels on the light face @@ -45,6 +47,7 @@ Themes|dark/key|COLOR|#33302A|Brand:ink/700||DesignTokens.Themes.darkKey| Themes|dark/key-modifier|COLOR|#26231E|Brand:ink/800||DesignTokens.Themes.darkKeyModifier| Themes|dark/legend|COLOR|#F5F3EB|Brand:paper/tint||DesignTokens.Themes.darkLegend| Themes|dark/legend-secondary|COLOR|#A5A4A2|Brand:neutral/500||DesignTokens.Themes.darkLegendSecondary| +Themes|dark/material|COLOR|#373737|Brand:material/dark-surface||DesignTokens.Themes.darkMaterial| Themes|dark/notice|COLOR|#E67F36|Brand:orange||DesignTokens.Themes.darkNotice| Themes|dark/popup|COLOR|#33302A|Brand:ink/700||DesignTokens.Themes.darkPopup| Themes|dark/signal|COLOR|#67AD82|Brand:green/400||DesignTokens.Themes.darkSignal| @@ -57,6 +60,7 @@ Themes|light/key|COLOR|#FFFFFF|Brand:white||DesignTokens.Themes.lightKey| Themes|light/key-modifier|COLOR|#DAD7CB|Brand:paper/300||DesignTokens.Themes.lightKeyModifier| Themes|light/legend|COLOR|#1D1B16|Brand:ink||DesignTokens.Themes.lightLegend| Themes|light/legend-secondary|COLOR|#777673|Brand:neutral/700||DesignTokens.Themes.lightLegendSecondary| +Themes|light/material|COLOR|#E2E3E8|Brand:material/light-surface||DesignTokens.Themes.lightMaterial| Themes|light/notice|COLOR|#E67F36|Brand:orange||DesignTokens.Themes.lightNotice| Themes|light/popup|COLOR|#FFFFFF|Brand:white||DesignTokens.Themes.lightPopup| Themes|light/signal|COLOR|#01762F|Brand:green/700||DesignTokens.Themes.lightSignal| @@ -191,13 +195,13 @@ Metrics|term/inset|FLOAT|2||GAP|DesignTokens.Metrics.termInset|the field row's s Metrics|term/pad|FLOAT|14||GAP|DesignTokens.Metrics.termPad|the field's side padding Metrics|term/radius|FLOAT|8||CORNER_RADIUS|DesignTokens.Metrics.termRadius|the key-term field: the brand's input corners (radius/input) Metrics|voice/bar-height|FLOAT|32||WIDTH_HEIGHT|DesignTokens.Metrics.voiceBarHeight| -Metrics|voice/bar-width|FLOAT|240||WIDTH_HEIGHT|DesignTokens.Metrics.voiceBarWidth|the voice element's box in the voice bar: what the wave gets +Metrics|voice/bar-width|FLOAT|160||WIDTH_HEIGHT|DesignTokens.Metrics.voiceBarWidth|the voice element's box in the voice bar; with the + beside it the pair sits centred Metrics|voice/home-height|FLOAT|112||WIDTH_HEIGHT|DesignTokens.Metrics.voiceHomeHeight| Metrics|voice/home-width|FLOAT|280||WIDTH_HEIGHT|DesignTokens.Metrics.voiceHomeWidth|the box on the home screen Metrics|voice/panel-height|FLOAT|88||WIDTH_HEIGHT|DesignTokens.Metrics.voicePanelHeight| Metrics|voice/panel-width|FLOAT|300||WIDTH_HEIGHT|DesignTokens.Metrics.voicePanelWidth|the box in the panel Metrics|voice/press-scale|FLOAT|0.94||WIDTH_HEIGHT|DesignTokens.Metrics.voicePressScale|the element while pressed -Metrics|voicebar/addterm-clearance|FLOAT|12||GAP|DesignTokens.Metrics.voicebarAddtermClearance|the wave stays this clear of the + at the trailing edge +Metrics|voicebar/addterm-clearance|FLOAT|12||GAP|DesignTokens.Metrics.voicebarAddtermClearance|between the element and the + Metrics|voicebar/height|FLOAT|44||WIDTH_HEIGHT|DesignTokens.Metrics.voicebarHeight|the voice row, where the system puts its suggestion bar Metrics|voicebar/note-gap|FLOAT|10||GAP|DesignTokens.Metrics.voicebarNoteGap|between the orb and the Full Access note Metrics|wave/bar|FLOAT|2||STROKE_FLOAT,WIDTH_HEIGHT|DesignTokens.Metrics.waveBar|a wave bar's width diff --git a/App/BlurtiOS/Design/tokens.json b/App/BlurtiOS/Design/tokens.json index 9d0cb3f0..18743e79 100644 --- a/App/BlurtiOS/Design/tokens.json +++ b/App/BlurtiOS/Design/tokens.json @@ -143,6 +143,14 @@ "material/dark-modifier": { "value": "#474747", "use": "a modifier key on the system's dark material" + }, + "material/light-surface": { + "value": "#E2E3E8", + "use": "the system's light keyboard material (measured, iOS 27): what the gallery stands under a clear surface" + }, + "material/dark-surface": { + "value": "#373737", + "use": "the system's dark keyboard material (measured, iOS 27)" } }, "themes": { @@ -158,6 +166,7 @@ "light/notice": "{brand.orange}", "light/container-key": "{brand.white}", "light/container-key-modifier": "{brand.paper/300}", + "light/material": "{brand.material/light-surface}", "dark/surface": "{brand.ink}", "dark/key": "{brand.ink/700}", "dark/key-modifier": "{brand.ink/800}", @@ -169,7 +178,8 @@ "dark/field-border": "{brand.ink/600}", "dark/notice": "{brand.orange}", "dark/container-key": "{brand.material/dark-key}", - "dark/container-key-modifier": "{brand.material/dark-modifier}" + "dark/container-key-modifier": "{brand.material/dark-modifier}", + "dark/material": "{brand.material/dark-surface}" }, "keyboard": { "kb/surface": { @@ -337,7 +347,7 @@ }, "voicebar/addterm-clearance": { "value": 12, - "use": "the wave stays this clear of the + at the trailing edge" + "use": "between the element and the +" }, "wave/bar-height": { "value": 24 @@ -521,8 +531,8 @@ "use": "space at 402 pt beside 123, the globe and return: what is left (measured 191.333)" }, "voice/bar-width": { - "value": 240, - "use": "the voice element's box in the voice bar: what the wave gets" + "value": 160, + "use": "the voice element's box in the voice bar; with the + beside it the pair sits centred" }, "voice/bar-height": { "value": 32 diff --git a/App/BlurtiOS/Shared/DesignTokens.swift b/App/BlurtiOS/Shared/DesignTokens.swift index 81674891..b31a3798 100644 --- a/App/BlurtiOS/Shared/DesignTokens.swift +++ b/App/BlurtiOS/Shared/DesignTokens.swift @@ -51,6 +51,10 @@ enum DesignTokens { nonisolated static let materialDarkKey: Color = Color(hex: 0x575757) /// A modifier key on the system's dark material. nonisolated static let materialDarkModifier: Color = Color(hex: 0x474747) + /// The system's dark keyboard material (measured, iOS 27). + nonisolated static let materialDarkSurface: Color = Color(hex: 0x373737) + /// The system's light keyboard material (measured, iOS 27): what the gallery stands under a clear surface. + nonisolated static let materialLightSurface: Color = Color(hex: 0xE2E3E8) /// Black-100: the lightest warm grey. nonisolated static let neutral300: Color = Color(hex: 0xD2D1D0) /// Black-200: mono labels on the dark face. @@ -99,6 +103,8 @@ enum DesignTokens { nonisolated static let darkLegend: Color = Brand.paperTint /// `brand.neutral/500`. nonisolated static let darkLegendSecondary: Color = Brand.neutral500 + /// `brand.material/dark-surface`. + nonisolated static let darkMaterial: Color = Brand.materialDarkSurface /// `brand.orange`. nonisolated static let darkNotice: Color = Brand.orange /// `brand.ink/700`. @@ -123,6 +129,8 @@ enum DesignTokens { nonisolated static let lightLegend: Color = Brand.ink /// `brand.neutral/700`. nonisolated static let lightLegendSecondary: Color = Brand.neutral700 + /// `brand.material/light-surface`. + nonisolated static let lightMaterial: Color = Brand.materialLightSurface /// `brand.orange`. nonisolated static let lightNotice: Color = Brand.orange /// `brand.white`. @@ -384,8 +392,8 @@ enum DesignTokens { /// The key-term field: the brand's input corners (radius/input). nonisolated static let termRadius: CGFloat = 8 nonisolated static let voiceBarHeight: CGFloat = 32 - /// The voice element's box in the voice bar: what the wave gets. - nonisolated static let voiceBarWidth: CGFloat = 240 + /// The voice element's box in the voice bar; with the + beside it the pair sits centred. + nonisolated static let voiceBarWidth: CGFloat = 160 nonisolated static let voiceHomeHeight: CGFloat = 112 /// The box on the home screen. nonisolated static let voiceHomeWidth: CGFloat = 280 @@ -394,7 +402,7 @@ enum DesignTokens { nonisolated static let voicePanelWidth: CGFloat = 300 /// The element while pressed. nonisolated static let voicePressScale: CGFloat = 0.94 - /// The wave stays this clear of the + at the trailing edge. + /// Between the element and the +. nonisolated static let voicebarAddtermClearance: CGFloat = 12 /// The voice row, where the system puts its suggestion bar. nonisolated static let voicebarHeight: CGFloat = 44 @@ -523,6 +531,8 @@ enum DesignTokens { "brand.ink/800": "#26231E", "brand.material/dark-key": "#575757", "brand.material/dark-modifier": "#474747", + "brand.material/dark-surface": "#373737", + "brand.material/light-surface": "#E2E3E8", "brand.neutral/300": "#D2D1D0", "brand.neutral/500": "#A5A4A2", "brand.neutral/700": "#777673", @@ -546,6 +556,7 @@ enum DesignTokens { "themes.dark/key-modifier": "#26231E", "themes.dark/legend": "#F5F3EB", "themes.dark/legend-secondary": "#A5A4A2", + "themes.dark/material": "#373737", "themes.dark/notice": "#E67F36", "themes.dark/popup": "#33302A", "themes.dark/signal": "#67AD82", @@ -558,6 +569,7 @@ enum DesignTokens { "themes.light/key-modifier": "#DAD7CB", "themes.light/legend": "#1D1B16", "themes.light/legend-secondary": "#777673", + "themes.light/material": "#E2E3E8", "themes.light/notice": "#E67F36", "themes.light/popup": "#FFFFFF", "themes.light/signal": "#01762F", @@ -692,7 +704,7 @@ enum DesignTokens { "metrics.term/pad": "14", "metrics.term/radius": "8", "metrics.voice/bar-height": "32", - "metrics.voice/bar-width": "240", + "metrics.voice/bar-width": "160", "metrics.voice/home-height": "112", "metrics.voice/home-width": "280", "metrics.voice/panel-height": "88", diff --git a/scripts/design-tokens.swift b/scripts/design-tokens.swift index 44a0a842..469b76b9 100755 --- a/scripts/design-tokens.swift +++ b/scripts/design-tokens.swift @@ -338,12 +338,12 @@ let themeNames = tokens.filter { $0.group == "themes" }.map { String($0.name.spl let themeOrder = ["light", "dark"] + Set(themeNames).subtracting(["light", "dark"]).sorted() let roles = [ "surface", "key", "key-modifier", "legend", "legend-secondary", "signal", "popup", "field", "field-border", "notice", - "container-key", "container-key-modifier", + "container-key", "container-key-modifier", "material", ] blocks["themes"] = table( [ "Face", "Surface", "Key", "Modifier", "Legend", "Secondary", "Signal", "Pop-up", "Field", "Field border", "Notice", - "Key in container", "Modifier in container", + "Key in container", "Modifier in container", "Host material", ], themeOrder.compactMap { theme -> [String]? in let cells = roles.compactMap { role in byQualified["themes.\(theme)/\(role)"].map { code(rendered($0)) } } From 1c3e2e7b546fe5bbf72d0558e532086e1af64975 Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Wed, 30 Sep 2026 10:58:00 -0400 Subject: [PATCH 60/79] Keyboard: the carousel swipes from anywhere; the bar pairs the + with what shows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three bugs from real use of the panel and the bar. The panel would not flip from its empty space. The host hands a keyboard only the touches that land on pixels it drew, and with the surface clear a swipe that started between the element and the keys never reached this process at all — its hit test was not even asked. The controller now paints a floor at 1 % black under the hosted keyboard and recognises the swipe on the input view itself (a pan recogniser beside SwiftUI's gestures, cancelling none), so the gap, the mic, the space key and the letters all flip it, both ways. A swipe while a key term is open flips nothing. The + sat off to the right of the bar. The pair was centred on the element's box (160 pt) while the grille shows 64 and the ribs 40: the mic key is now as wide as the element shows (`VoiceElementKind.visibleWidth`, never narrower than a key) and the + rides a clearance beside it; the ribs push it out as they wake. The element vanished when Blurt was not listening: 0.45 over the grille's own 0.55 was nothing on either material. Not ready is 0.6 now, and still — no sheen — so it reads as the key it is, a tap that opens the app. Also: trailing `literal-ok` comments reflowed under the line length, the unused swipe-minimum token retired. Co-Authored-By: Claude Fable 5.1 --- .../Sources/FullKeyboardView.swift | 2 +- .../BlurtKeyboard/Sources/KeyboardModel.swift | 3 +- .../Sources/KeyboardRootView.swift | 17 ++----- .../Sources/KeyboardViewController.swift | 48 ++++++++++++++++++- .../BlurtKeyboard/Sources/VoiceBar.swift | 13 +++-- .../BlurtKeyboard/Sources/VoiceElement.swift | 14 ++++++ .../BlurtKeyboard/Sources/VoiceGrille.swift | 16 ++++--- .../BlurtKeyboard/Sources/VoiceRibs.swift | 15 +++--- .../BlurtKeyboard/Sources/VoiceStreak.swift | 24 ++++++---- .../BlurtiOSTests/KeyboardModelTests.swift | 16 +++++++ .../BlurtiOSTests/VoiceElementTests.swift | 18 +++++++ App/BlurtiOS/DESIGN.md | 22 ++++++--- App/BlurtiOS/Design/figma/tokens.js | 5 +- App/BlurtiOS/Design/tokens.json | 10 ++-- App/BlurtiOS/Shared/DesignTokens.swift | 11 ++--- 15 files changed, 170 insertions(+), 64 deletions(-) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift b/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift index c8e88ef3..ccee0175 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift @@ -24,7 +24,7 @@ struct FullKeyboardView: View { VoiceBar(model: model) VStack(spacing: KeyboardPalette.rowGap) { ForEach(Array(rows.enumerated()), id: \.offset) { index, row in - HStack(spacing: index == 2 ? geometry.sideGap : gap) { // literal-ok: the third row carries shift and delete + HStack(spacing: index == 2 ? geometry.sideGap : gap) { // literal-ok: the third row if index == 2 { modifierKey(width: geometry.sideWidth) } // literal-ok: the third row HStack(spacing: gap) { ForEach(Array(row), id: \.self) { character in diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift index 542b09cc..34dace01 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift @@ -112,7 +112,8 @@ final class KeyboardModel { /// A horizontal swipe on the panel: flip to the other page, sliding the way /// the finger went. func flipPanel(towardsLeading: Bool) { - guard layout == .panel else { return } + // Only the panel has two pages, and not while the keys are up for a term. + guard layout == .panel, termDraft == nil else { return } flipTowardsLeading = towardsLeading panelShowsKeys.toggle() onLayoutChange?() diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardRootView.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardRootView.swift index 9eeed2a2..298266d3 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardRootView.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardRootView.swift @@ -54,7 +54,11 @@ struct KeyboardRootView: View { .environment(\.keyboardPalette, model.palette) .environment(\.keyboardInContainer, !Self.paintsSurface) .environment(\.voiceElementKind, model.voiceKind) - .simultaneousGesture(swipe, including: model.layout == .panel ? .all : .subviews) + // The carousel's swipe is not a SwiftUI gesture here. The surface is + // clear, and the host hands the keyboard only the touches that land on + // painted pixels: `KeyboardViewController` paints a floor the eye can't + // see and recognises the swipe on the input view itself, which sees + // every touch the keyboard gets, the panel's empty space included. .animation(reduceMotion ? nil : .easeInOut(duration: DesignTokens.Motion.flip), value: model.panelShowsKeys) .onAppear { // `Font.custom` falls back to the system font in silence; the bundle @@ -74,15 +78,4 @@ struct KeyboardRootView: View { ? .asymmetric(insertion: .move(edge: .trailing), removal: .move(edge: .leading)) : .asymmetric(insertion: .move(edge: .leading), removal: .move(edge: .trailing)) } - - /// A horizontal swipe anywhere on the panel flips it; taps and holds on keys - /// never travel this far, and the keys ignore a touch that did - /// (`KeyboardInteraction`). - private var swipe: some Gesture { - DragGesture(minimumDistance: DesignTokens.Metrics.gestureSwipeMin) - .onEnded { value in - guard let direction = KeyboardInteraction.flip(value.translation) else { return } - model.flipPanel(towardsLeading: direction == .towardsLeading) - } - } } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift index c49467f9..e9a99cda 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift @@ -6,7 +6,7 @@ import UIKit /// to the layout the user chose, and forwards the lifecycle to `KeyboardModel`, /// which does the talking to the app. It never hears anything: iOS lets no /// keyboard use the microphone, so the app listens and this inserts. -final class KeyboardViewController: UIInputViewController { +final class KeyboardViewController: UIInputViewController, UIGestureRecognizerDelegate { private let model = KeyboardModel() /// The input view says it wants clicks, so `UIDevice.playInputClick()` on @@ -14,11 +14,16 @@ final class KeyboardViewController: UIInputViewController { /// user has keyboard clicks on in Settings. Their setting, not ours. private final class ClickingInputView: UIInputView, UIInputViewAudioFeedback { var enableInputClicksWhenVisible: Bool { true } + } private var heightConstraint: NSLayoutConstraint? private var hasAppeared = false + /// The least the floor can be painted and still be the keyboard's to the + /// host: 1 % black, invisible on either material, never zero. + private static let floorAlpha: CGFloat = 0.01 + override func loadView() { view = ClickingInputView(frame: .zero, inputViewStyle: .keyboard) } @@ -26,12 +31,27 @@ final class KeyboardViewController: UIInputViewController { override func viewDidLoad() { super.viewDidLoad() model.attach(to: self) + // The floor. The host hands the keyboard only the touches that land on + // pixels it drew: where the keyboard is fully transparent — and the + // surface is clear, the host's own material showing through — a touch + // never reaches this process at all (its hit test is not even asked), + // and goes to the host's keyboard chrome instead. So the panel's empty + // space, where a finger swipes the carousel, must be painted, if only + // just: a floor the eye cannot see but the compositor can. + let floor = UIView() + floor.translatesAutoresizingMaskIntoConstraints = false + floor.backgroundColor = UIColor.black.withAlphaComponent(Self.floorAlpha) + view.addSubview(floor) let host = UIHostingController(rootView: KeyboardRootView(model: model)) addChild(host) host.view.translatesAutoresizingMaskIntoConstraints = false host.view.backgroundColor = .clear view.addSubview(host.view) NSLayoutConstraint.activate([ + floor.leadingAnchor.constraint(equalTo: view.leadingAnchor), + floor.trailingAnchor.constraint(equalTo: view.trailingAnchor), + floor.topAnchor.constraint(equalTo: view.topAnchor), + floor.bottomAnchor.constraint(equalTo: view.bottomAnchor), host.view.leadingAnchor.constraint(equalTo: view.leadingAnchor), host.view.trailingAnchor.constraint(equalTo: view.trailingAnchor), host.view.topAnchor.constraint(equalTo: view.topAnchor), @@ -49,6 +69,32 @@ final class KeyboardViewController: UIInputViewController { heightConstraint = height // The panel's carousel changes the keyboard's height when it flips. model.onLayoutChange = { [weak self] in self?.updateHeight(animated: true) } + // The carousel's swipe, on the input view itself: it sees every touch the + // keyboard gets — a key, the mic, the floor — where a SwiftUI gesture on + // the hosted root only sees what SwiftUI hit-tests. It runs beside + // SwiftUI's own gestures and cancels none of them: the keys and the mic + // keep their touch and apply their travel rules (`KeyboardInteraction`), + // so a swipe across a key never types and one across the mic never + // dictates. + let swipe = UIPanGestureRecognizer(target: self, action: #selector(swiped)) + swipe.cancelsTouchesInView = false + swipe.delaysTouchesBegan = false + swipe.delaysTouchesEnded = false + swipe.delegate = self + view.addGestureRecognizer(swipe) + } + + @objc private func swiped(_ swipe: UIPanGestureRecognizer) { + guard swipe.state == .ended else { return } + let travel = swipe.translation(in: view) + guard let direction = KeyboardInteraction.flip(CGSize(width: travel.x, height: travel.y)) else { return } + model.flipPanel(towardsLeading: direction == .towardsLeading) + } + + func gestureRecognizer( + _ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith other: UIGestureRecognizer + ) -> Bool { + true } override func viewWillAppear(_ animated: Bool) { diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift index e9fac69c..504a298e 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift @@ -10,6 +10,7 @@ import SwiftUI struct VoiceBar: View { var model: KeyboardModel @Environment(\.keyboardPalette) private var palette + @Environment(\.voiceElementKind) private var kind static let height = DesignTokens.Metrics.voicebarHeight @@ -38,13 +39,19 @@ struct VoiceBar: View { .accessibilityLabel("Start Blurt") .transition(.opacity) } else { - // The element and the + together, centred: the + rides beside the - // element, a clearance away, never off at the edge. + // The element and the + together, centred on what shows: the mic + // key is as wide as the element is (never narrower than a key, so + // the ribs asleep are still a target), the + a clearance beside it. + // When the ribs wake into the wave the + slides out of its way. let plus = DesignTokens.Metrics.glyphHit + DesignTokens.Metrics.voicebarAddtermClearance + let recording = model.voiceState.isRecording + let shown = kind.visibleWidth(slot: .bar, recording: recording) + let width = min(max(shown, DesignTokens.Metrics.keyMinWidth), geo.size.width - plus) HStack(spacing: DesignTokens.Metrics.voicebarAddtermClearance) { - MicControl(model: model, slot: .bar, width: min(DesignTokens.Metrics.voiceBarWidth, geo.size.width - plus)) + MicControl(model: model, slot: .bar, width: width) AddTermKey(model: model) } + .animation(.easeInOut(duration: DesignTokens.Motion.waveFade), value: recording) .transition(.opacity) } } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceElement.swift b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceElement.swift index 4e9fb064..9270e5da 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceElement.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceElement.swift @@ -39,6 +39,20 @@ nonisolated enum VoiceSlot: String, CaseIterable, Sendable { } } +extension VoiceElementKind { + /// How wide the element shows in a slot — what the + sits beside and the + /// pair is centred on. The slot's box is the most it takes (the ribs awake, + /// the streak); at rest the grille and the ribs are narrower, and a pair + /// centred on the box would put the + off at the edge. + func visibleWidth(slot: VoiceSlot, recording: Bool) -> CGFloat { + switch self { + case .grille: VoiceGrille.box(slot).width + case .ribs: recording ? slot.box.width : DesignTokens.Metrics.ribsRestWidth + case .streak: slot.box.width + } + } +} + /// Every candidate draws with a synchronous `Canvas`: one that renders /// asynchronously never presents inside a keyboard extension, and the /// keyboard is where these live. diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceGrille.swift b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceGrille.swift index b0107820..a847f737 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceGrille.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceGrille.swift @@ -59,11 +59,13 @@ struct VoiceGrille: View { state.isWorking && !state.isRecording ? Self.runnerIndex(time: time, columns: columns, rows: rows) : nil let (glintTick, glintPhase) = Self.glintClock(time) let (restColour, restOpacity) = Self.rest(state: state, palette: palette) - let sheen = inputs.animated && !state.isRecording ? (centre: sheenCentre, band: sheenBand) : nil + // No sheen while Blurt isn't ready: the grille sits still as well as dim. + let sheen = inputs.animated && state.isReady && !state.isRecording ? (centre: sheenCentre, band: sheenBand) : nil for column in 0.. 0.35 && VoiceClock.hash(column, glintTick) < Double(level) * 0.5 // literal-ok: how often a facet catches the light + // How often a facet catches the light: the louder, the more. + let glints = Double(level) > 0.35 && VoiceClock.hash(column, glintTick) < Double(level) * 0.5 for row in 0.. Date: Wed, 30 Sep 2026 10:58:00 -0400 Subject: [PATCH 61/79] =?UTF-8?q?Probe:=20the=20keyboard's=20flows=20in=20?= =?UTF-8?q?the=20real=20extension,=20face=20=C3=97=20mic=20=C3=97=20layout?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `scripts/ios-keyboard-flows.sh` drives the Blurt keyboard as used — the extension in its own process over a field in the app, the app listening — through every layout's flows and collects a screenshot of each step: the mic key present, ready and centred; the + beside it; the panel's carousel from the gap, the mic, the space key and the letters, both ways; the term field opening, typing, saving and closing; letters typing into the field; a tap starting a dictation and a second stopping it. One run per face × mic concept × layout, or the whole matrix. The mic key carries an identifier (`blurt-mic`): the system's own bottom bar has a "Dictate" button, and a label query landed on it. The probe field now starts the coordinator like the home screen does, so `-BlurtStartListening` holds there too and the keyboard over it is live. Co-Authored-By: Claude Fable 5.1 --- .../BlurtKeyboard/Sources/MicControl.swift | 1 + .../BlurtiOS/Sources/BlurtiOSApp.swift | 24 ++- .../BlurtiOSProbe/BlurtKeyboardFlows.swift | 203 ++++++++++++++++++ scripts/ios-keyboard-flows.sh | 98 +++++++++ 4 files changed, 316 insertions(+), 10 deletions(-) create mode 100644 App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardFlows.swift create mode 100755 scripts/ios-keyboard-flows.sh diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/MicControl.swift b/App/BlurtiOS/BlurtKeyboard/Sources/MicControl.swift index 6ab0788c..6008759b 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/MicControl.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/MicControl.swift @@ -51,6 +51,7 @@ struct MicControl: View { .accessibilityLabel(state.accessibilityLabel) .accessibilityValue(state.accessibilityValue) .accessibilityAddTraits(.isButton) + .accessibilityIdentifier("blurt-mic") .simultaneousGesture( DragGesture(minimumDistance: 0) .onChanged { value in diff --git a/App/BlurtiOS/BlurtiOS/Sources/BlurtiOSApp.swift b/App/BlurtiOS/BlurtiOS/Sources/BlurtiOSApp.swift index 36b8745d..ce5d3f82 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/BlurtiOSApp.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/BlurtiOSApp.swift @@ -40,7 +40,9 @@ struct BlurtiOSApp: App { #if DEBUG let rows = KeyboardGalleryView.rows(from: CommandLine.arguments) if let probe = KeyboardProbeView.parse(CommandLine.arguments) { - probe + // The keyboard over this field is only live if the app runs as it + // does under the home screen: the coordinator up, listening on request. + probe.task { await start() } } else if let voice = KeyboardGalleryView.VoiceStillView.parse(CommandLine.arguments) { voice } else if CommandLine.arguments.contains("-BlurtSettings") { @@ -60,14 +62,16 @@ struct BlurtiOSApp: App { private var home: some View { HomeView(coordinator: coordinator) .onOpenURL { coordinator.handle($0) } - .task { - guard !Self.isTestHost else { return } - coordinator.start() - #if DEBUG - // `-BlurtStartListening` opens the mic at launch, so the listening - // state can be screenshotted without a tap (see scripts/ios-sim.sh). - if CommandLine.arguments.contains("-BlurtStartListening") { await coordinator.startListening() } - #endif - } + .task { await start() } + } + + private func start() async { + guard !Self.isTestHost else { return } + coordinator.start() + #if DEBUG + // `-BlurtStartListening` opens the mic at launch, so the listening + // state can be screenshotted without a tap (see scripts/ios-sim.sh). + if CommandLine.arguments.contains("-BlurtStartListening") { await coordinator.startListening() } + #endif } } diff --git a/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardFlows.swift b/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardFlows.swift new file mode 100644 index 00000000..75a7f1a6 --- /dev/null +++ b/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardFlows.swift @@ -0,0 +1,203 @@ +import XCTest + +/// The real keyboard, used: the extension in its own process over a field in +/// the app, driven through every layout's flows — the mic key present and +/// centred, the + beside it, the panel's carousel swiping to the keys and +/// back, the key-term field opening and closing, letters typing into the +/// field, the mic starting and stopping a dictation while the app listens. +/// One run per face × mic concept × layout (`TEST_RUNNER_BLURT_PROBE_ARGS`); +/// every step prints a FLOW line and attaches a screenshot, and +/// `scripts/ios-keyboard-flows.sh` runs the matrix and collects them. +final class BlurtKeyboardFlows: XCTestCase { + private var app = XCUIApplication() + private var shots = 0 + + override func setUp() { + continueAfterFailure = true + } + + @MainActor + func testFlows() throws { + let arguments = + ProcessInfo.processInfo.environment["BLURT_PROBE_ARGS"]?.split(separator: " ").map(String.init) ?? ["light"] + let layout = arguments.first { ["slimBar", "panel", "full"].contains($0) } ?? "panel" + app = XCUIApplication() + // The app listens from launch, so the keyboard's mic key is live. + app.launchArguments = ["-BlurtProbeField"] + arguments + ["-BlurtStartListening"] + app.launch() + try bringUpBlurt() + shot("up") + let mic = micKey() + check(mic.exists, "mic key present (\(mic.label))") + check(mic.label == "Dictate", "mic key ready: the app is listening (\(mic.label))") + let plus = app.buttons["Add a key term"] + check(plus.exists, "the + present") + if mic.exists, plus.exists { + let width = app.windows.firstMatch.frame.width + let centre = mic.frame.midX + if layout == "panel" { + check(abs(centre - width / 2) < 4, "mic centred in the panel (\(centre) of \(width))") + check(plus.frame.midX < 60, "the + in the panel's top-left corner (\(plus.frame.midX))") + } else { + // The pair is centred in the voice bar's own width: the whole row in + // the full keyboard, the room left of delete and return in the slim bar. + let pair = (mic.frame.minX + plus.frame.maxX) / 2 + let room = layout == "slimBar" ? app.buttons["delete.left"].firstMatch.frame.minX : width + check(abs(pair - room / 2) < 20, "mic and + centred as a pair (\(pair) in \(room))") + } + } + switch layout { + case "panel": try panelFlows() + case "full": try fullFlows() + default: try slimFlows() + } + try termFlow() + try dictationFlow() + } + + // MARK: Flows + + private func panelFlows() throws { + // Where a finger swipes on the panel: the empty space under the element, + // the element itself, the space key. Each attempt says where it started + // and whether the carousel flipped; the page is put back between them. + let mic = { self.micKey().coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5)) } + let gap = { self.micKey().coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 1.15)) } + let space = { self.app.buttons["space"].coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5)) } + let attempts = [ + Swipe(origin: "the gap under the mic, left", start: gap, dx: -160), + Swipe(origin: "the mic itself, left", start: mic, dx: -160), + Swipe(origin: "the space key, left", start: space, dx: -160), + Swipe(origin: "the gap under the mic, right", start: gap, dx: 160), + Swipe(origin: "the space key, right", start: space, dx: 160), + ] + for (index, swipe) in attempts.enumerated() { + let (origin, dx) = (swipe.origin, swipe.dx) + let from = swipe.start() + from.press(forDuration: 0.05, thenDragTo: from.withOffset(CGVector(dx: dx, dy: 0))) + Thread.sleep(forTimeInterval: 1.2) + let flipped = keysUp + check(flipped, "swipe from \(origin) flips the panel to the keys") + if index == 0 { shot("panel-keys") } + if flipped { + // Back to the panel from the letters, the swipe that is known to work. + let g = letterKey("g").exists ? letterKey("g") : letterKey("G") + let on = g.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5)) + on.press(forDuration: 0.05, thenDragTo: on.withOffset(CGVector(dx: dx > 0 ? -160 : 160, dy: 0))) + Thread.sleep(forTimeInterval: 1.2) + check(!keysUp, "swipe from the letters (\(dx > 0 ? "left" : "right")) flips back to the panel") + if index == 0 { shot("panel-back") } + } + } + check(!keysUp && micKey().frame.width > 200, "the panel is showing again, its mic full size") + } + + /// Where a swipe starts and how far it goes. + private struct Swipe { + let origin: String + let start: () -> XCUICoordinate + let dx: CGFloat + } + + /// Whether the letter keys are on screen (either shift state). + private var keysUp: Bool { letterKey("Q").exists || letterKey("q").exists } + + private func fullFlows() throws { + let q = letterKey("Q") + check(q.exists, "letter keys present") + q.tap() + letterKey("q").tap() + let field = app.textFields.firstMatch + check( + (field.value as? String)?.lowercased().contains("qq") == true, + "letters type into the field (\(field.value ?? "-"))") + check( + app.buttons["return"].exists || app.buttons["RETURN"].exists || app.buttons["Return"].exists, + "return key labelled") + shot("full-typed") + } + + private func slimFlows() throws { + check(app.buttons["delete.left"].exists, "delete present on the slim bar") + shot("slim") + } + + private func termFlow() throws { + let plus = app.buttons["Add a key term"] + guard plus.exists else { return } + plus.tap() + let cancel = app.buttons["Cancel"] + check(cancel.waitForExistence(timeout: 3), "the + opens the key-term field") + check(letterKey("Q").exists, "the keys come up for the term") + letterKey("R").tap() + letterKey("i").tap() + shot("term") + let save = app.buttons["Save the key term"] + check(save.exists && save.isEnabled, "save enabled after typing") + cancel.tap() + check(micKey().waitForExistence(timeout: 3), "cancel returns to the mic") + } + + private func dictationFlow() throws { + let mic = micKey() + guard mic.exists else { return } + if mic.label == "Start Blurt" { + check(false, "mic not ready: the app is not listening (\(mic.label))") + return + } + mic.tap() + let stop = micKey(labelled: "Stop dictation") + check(stop.waitForExistence(timeout: 4), "a tap starts a dictation (recording)") + Thread.sleep(forTimeInterval: 1.5) + shot("recording") + if stop.exists { stop.tap() } + let back = micKey(labelled: "Dictate") + check(back.waitForExistence(timeout: 12), "a second tap stops it and the key settles") + shot("settled") + } + + // MARK: Helpers + + private func bringUpBlurt() throws { + let blurt = app.buttons["Add a key term"] + let system = app.keyboards.firstMatch + let deadline = Date().addingTimeInterval(15) + while !blurt.exists, !system.exists, Date() < deadline { Thread.sleep(forTimeInterval: 0.5) } + var hops = 0 + while !blurt.waitForExistence(timeout: 2), hops < 4 { + let globe = app.buttons["Next keyboard"] + XCTAssertTrue(globe.waitForExistence(timeout: 5), "no globe key") + globe.tap() + hops += 1 + } + XCTAssertTrue(blurt.exists, "Blurt never came up") + Thread.sleep(forTimeInterval: 1.5) + } + + /// Blurt's mic key, by its identifier: the system's own bottom bar has a + /// "Dictate" button too, and a label query lands on it. + private func micKey() -> XCUIElement { + app.buttons.matching(NSPredicate(format: "identifier == %@", "blurt-mic")).firstMatch + } + + private func micKey(labelled label: String) -> XCUIElement { + app.buttons.matching(NSPredicate(format: "identifier == %@ AND label == %@", "blurt-mic", label)).firstMatch + } + + private func letterKey(_ letter: String) -> XCUIElement { + app.buttons.matching(NSPredicate(format: "label == %@", letter)).firstMatch + } + + private func check(_ condition: Bool, _ what: String) { + print("FLOW-\(condition ? "OK" : "FAIL"): \(what)") + XCTAssertTrue(condition, what) + } + + private func shot(_ name: String) { + shots += 1 + let attachment = XCTAttachment(screenshot: app.screenshot()) + attachment.name = "flow-\(String(format: "%02d", shots))-\(name).png" + attachment.lifetime = .keepAlways + add(attachment) + } +} diff --git a/scripts/ios-keyboard-flows.sh b/scripts/ios-keyboard-flows.sh new file mode 100755 index 00000000..89194c59 --- /dev/null +++ b/scripts/ios-keyboard-flows.sh @@ -0,0 +1,98 @@ +#!/bin/bash +# Drive the real Blurt keyboard through its flows in the simulator — the +# extension in its own process over a field in the app, with the app +# listening — for each face × mic concept × layout, and collect a screenshot +# of every step. The truth about the keyboard as used, which the gallery +# (the app's process, no host, no touches) cannot give. +# +# scripts/ios-keyboard-flows.sh # the whole matrix +# scripts/ios-keyboard-flows.sh --face dark --voice a --layout panel +# +# Prints one FLOW-OK / FLOW-FAIL line per step; screenshots land in +# .build/design/flows/--/. Blurt must be enabled as a +# keyboard on the simulator once by hand. +set -uo pipefail + +REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" +cd "$REPO_ROOT" || exit 1 +# shellcheck source=scripts/ios-lib.sh +source "$REPO_ROOT/scripts/ios-lib.sh" +DERIVED="${BLURT_DERIVED_DATA:-$REPO_ROOT/.build/ios-sim}" +FACES="light dark" +VOICES="a b c" +LAYOUTS="panel full slimBar" +OUT="$REPO_ROOT/.build/design/flows" +while [ $# -gt 0 ]; do + case "$1" in + --face) + FACES="${2:?}" + shift 2 + ;; + --voice) + VOICES="${2:?}" + shift 2 + ;; + --layout) + LAYOUTS="${2:?}" + shift 2 + ;; + --out) + OUT="${2:?}" + shift 2 + ;; + *) + echo "usage: ios-keyboard-flows.sh [--face light|dark] [--voice a|b|c] [--layout slimBar|panel|full] [--out DIR]" >&2 + exit 2 + ;; + esac +done + +PICKED="$(ios_pick_device "${BLURT_SIM_DEVICE:-iPhone 18 Pro}")" +[ -n "$PICKED" ] || { + echo "ios-keyboard-flows: no iPhone simulator available" >&2 + exit 1 +} +UDID="${PICKED%% *}" +ios_wait_booted "$UDID" + +(cd "$REPO_ROOT/App/BlurtiOS" && xcodegen generate --quiet) +xcodebuild build -project "$REPO_ROOT/App/BlurtiOS/BlurtiOS.xcodeproj" -scheme BlurtiOS \ + -destination "platform=iOS Simulator,id=$UDID" -derivedDataPath "$DERIVED" "${IOS_SIM_SIGNING[@]}" -quiet +xcrun simctl install "$UDID" "$DERIVED/Build/Products/Debug-iphonesimulator/BlurtiOS.app" +xcrun simctl privacy "$UDID" grant microphone dev.alex.blurt.ios + +for face in $FACES; do + xcrun simctl ui "$UDID" appearance "$face" + for voice in $VOICES; do + for layout in $LAYOUTS; do + name="$face-$voice-$layout" + dir="$OUT/$name" + rm -rf "$dir" + mkdir -p "$dir" + echo "==> $name" + TEST_RUNNER_BLURT_PROBE_ARGS="$face $voice $layout" xcodebuild test \ + -project "$REPO_ROOT/App/BlurtiOS/BlurtiOS.xcodeproj" -scheme BlurtiOSProbe \ + -only-testing:BlurtiOSProbe/BlurtKeyboardFlows \ + -destination "platform=iOS Simulator,id=$UDID" -derivedDataPath "$DERIVED" \ + -resultBundlePath "$dir/flows.xcresult" "${IOS_SIM_SIGNING[@]}" -collect-test-diagnostics never \ + 2>&1 | grep -E "^FLOW-|XCTAssertTrue failed|Blurt never came up|error:|TEST BUILD FAILED" | grep -v "XCTAssertTrue failed" | sed "s/^/ /" + if grep -q "FLOW-FAIL\|failed" "$dir/flows.xcresult/Info.plist" 2>/dev/null; then :; fi + xcrun xcresulttool export attachments --path "$dir/flows.xcresult" --output-path "$dir/attachments" >/dev/null 2>&1 + python3 - "$dir" <<'PY' +import json, os, shutil, sys +d = sys.argv[1] +try: + manifest = json.load(open(os.path.join(d, "attachments", "manifest.json"))) +except FileNotFoundError: + sys.exit(0) +for test in manifest: + for a in test.get("attachments", []): + name = a["suggestedHumanReadableName"] + if name.startswith("flow-"): + shutil.copy(os.path.join(d, "attachments", a["exportedFileName"]), os.path.join(d, name.split("_")[0] + ".png")) +PY + done + done +done +xcrun simctl ui "$UDID" appearance light +echo "ios-keyboard-flows: screenshots in $OUT" From 734c4bb0e06d6a30e560acb4059121e7cd17855a Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Wed, 30 Sep 2026 11:11:04 -0400 Subject: [PATCH 62/79] Probe: the flows test on the main actor; a sheet per run MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The test class is main-actor isolated so its app object can be a plain stored property (the target's default isolation made a lazy default an error). Each run now ends with a sheet.png — the keyboard from every step's screenshot, side by side and captioned — so a face × mic × layout can be judged at a glance without opening the screenshots one by one. Co-Authored-By: Claude Fable 5.1 --- .../BlurtiOSProbe/BlurtKeyboardFlows.swift | 7 ++---- scripts/ios-keyboard-flows.sh | 24 +++++++++++++++++-- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardFlows.swift b/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardFlows.swift index 75a7f1a6..5f95378f 100644 --- a/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardFlows.swift +++ b/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardFlows.swift @@ -8,16 +8,13 @@ import XCTest /// One run per face × mic concept × layout (`TEST_RUNNER_BLURT_PROBE_ARGS`); /// every step prints a FLOW line and attaches a screenshot, and /// `scripts/ios-keyboard-flows.sh` runs the matrix and collects them. +@MainActor final class BlurtKeyboardFlows: XCTestCase { private var app = XCUIApplication() private var shots = 0 - override func setUp() { - continueAfterFailure = true - } - - @MainActor func testFlows() throws { + continueAfterFailure = true let arguments = ProcessInfo.processInfo.environment["BLURT_PROBE_ARGS"]?.split(separator: " ").map(String.init) ?? ["light"] let layout = arguments.first { ["slimBar", "panel", "full"].contains($0) } ?? "panel" diff --git a/scripts/ios-keyboard-flows.sh b/scripts/ios-keyboard-flows.sh index 89194c59..739c9221 100755 --- a/scripts/ios-keyboard-flows.sh +++ b/scripts/ios-keyboard-flows.sh @@ -9,8 +9,9 @@ # scripts/ios-keyboard-flows.sh --face dark --voice a --layout panel # # Prints one FLOW-OK / FLOW-FAIL line per step; screenshots land in -# .build/design/flows/--/. Blurt must be enabled as a -# keyboard on the simulator once by hand. +# .build/design/flows/--/, with a sheet.png of every +# step's keyboard side by side. Blurt must be enabled as a keyboard on the +# simulator once by hand. set -uo pipefail REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" @@ -91,6 +92,25 @@ for test in manifest: if name.startswith("flow-"): shutil.copy(os.path.join(d, "attachments", a["exportedFileName"]), os.path.join(d, name.split("_")[0] + ".png")) PY + # The sheet: the bottom of every step's screenshot — the field is at + # the top, the keyboard at the bottom — captioned with the step. + captions=() + for shot in "$dir"/flow-*.png; do + [ -e "$shot" ] || continue + case "$shot" in *-crop.png) continue ;; esac + crop="${shot%.png}-crop.png" + h=$(sips -g pixelHeight "$shot" | awk '/pixelHeight/ {print $2}') + w=$(sips -g pixelWidth "$shot" | awk '/pixelWidth/ {print $2}') + ch=$((h * 45 / 100)) + # sips wants the offset plus the height strictly inside the image. + sips -c "$ch" "$w" --cropOffset $((h - ch - 1)) 0 "$shot" --out "$crop" >/dev/null + step=$(basename "$shot" .png) + captions+=("${step#flow-??-}=$crop") + done + if [ ${#captions[@]} -gt 0 ]; then + swift "$REPO_ROOT/scripts/design-diff.swift" sheet --out "$dir/sheet.png" --columns 3 --scale 0.5 \ + "${captions[@]}" >/dev/null + fi done done done From 6aca9d3885bc9a722b1ac6f427879e8208add070 Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Wed, 30 Sep 2026 11:58:49 -0400 Subject: [PATCH 63/79] Keyboard: the floor in the material's own colour, not black MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit One percent black over the host's light material read as a keyboard a shade darker than the border around it (230 against 231, measured). The floor is painted in the face's material colour at the same one percent — nothing to see, and the touches still reach the keyboard — and repainted when the field, and so the face, changes. Co-Authored-By: Claude Fable 5.1 --- .../Sources/KeyboardViewController.swift | 19 +++++++++++++++---- App/BlurtiOS/DESIGN.md | 4 +++- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift index e9a99cda..53aa56cb 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift @@ -19,9 +19,12 @@ final class KeyboardViewController: UIInputViewController, UIGestureRecognizerDe private var heightConstraint: NSLayoutConstraint? private var hasAppeared = false + private let floor = UIView() /// The least the floor can be painted and still be the keyboard's to the - /// host: 1 % black, invisible on either material, never zero. + /// host — never zero. In the host material's own colour, so the 1 % adds + /// nothing the eye can see: 1 % black over the light material was a + /// keyboard a shade darker than the border around it. private static let floorAlpha: CGFloat = 0.01 override func loadView() { @@ -37,10 +40,8 @@ final class KeyboardViewController: UIInputViewController, UIGestureRecognizerDe // never reaches this process at all (its hit test is not even asked), // and goes to the host's keyboard chrome instead. So the panel's empty // space, where a finger swipes the carousel, must be painted, if only - // just: a floor the eye cannot see but the compositor can. - let floor = UIView() + // just: a floor the eye cannot see but the compositor can (`paintFloor`). floor.translatesAutoresizingMaskIntoConstraints = false - floor.backgroundColor = UIColor.black.withAlphaComponent(Self.floorAlpha) view.addSubview(floor) let host = UIHostingController(rootView: KeyboardRootView(model: model)) addChild(host) @@ -100,10 +101,18 @@ final class KeyboardViewController: UIInputViewController, UIGestureRecognizerDe override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) model.appeared() + paintFloor() hasAppeared = true view.setNeedsUpdateConstraints() } + /// The floor in the face's material at `floorAlpha`: the host's own + /// keyboard colour, measured, so nothing shows through the paint but the + /// touches reach the keyboard. + private func paintFloor() { + floor.backgroundColor = UIColor(model.palette.material).withAlphaComponent(Self.floorAlpha) + } + override func updateViewConstraints() { super.updateViewConstraints() guard hasAppeared, let heightConstraint else { return } @@ -126,5 +135,7 @@ final class KeyboardViewController: UIInputViewController, UIGestureRecognizerDe override func textDidChange(_ textInput: (any UITextInput)?) { super.textDidChange(textInput) model.contextChanged() + // The field's appearance can change with the field. + paintFloor() } } diff --git a/App/BlurtiOS/DESIGN.md b/App/BlurtiOS/DESIGN.md index e1bc9972..63a409d6 100644 --- a/App/BlurtiOS/DESIGN.md +++ b/App/BlurtiOS/DESIGN.md @@ -275,7 +275,9 @@ narrower than a key), or the key-term field. A swipe flips the panel past 48 pt sideways and more sideways than up or down by 1.5×; a key acts on release and only under 12 pt of travel (`KeyboardInteraction`, tested). The swipe is recognised on the input view itself (`KeyboardViewController`), not -in SwiftUI, and the keyboard paints a floor at 1 % black under everything: +in SwiftUI, and the keyboard paints a floor under everything at 1 % of the +host material's own colour (`material/*`, so nothing shows; 1 % black read as +a shade darker than the border around it): the host hands a keyboard only the touches that land on pixels it drew, so with the surface clear a swipe that started on the panel's empty space never reached the keyboard at all (`scripts/ios-keyboard-flows.sh` swipes from the From 7ca5edc9d476561c560da08fccac7c92a7a5583d Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Wed, 30 Sep 2026 12:33:32 -0400 Subject: [PATCH 64/79] Keyboard: the carousel is a strip the finger slides; the pages never cross MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Alternating or quick swipes jumbled the panel's flip: each page's slide was a SwiftUI insertion/removal transition whose direction was read from state, and on a reversed or interrupted swipe the outgoing page kept the direction of the flip before, so both cards travelled the same way and crossed. `PanelCarousel` lays the two pages out as a strip one page wide: the page that is up sits in the middle, the other is set down a whole page away on the side the finger moved towards, and the strip slides one page — the first leaves one way as the second arrives the other. Side by side, a page apart, they cannot cross whichever way the flips come. A flip back before the slide has settled retreats instead of starting over; a retreat cut short keeps its side; a slide that was overtaken cannot settle the strip late (`PanelCarouselState`, tested). Each page keeps its own height while the keyboard resizes under the slide. The flows test adds four pairs from one fixed screen point — left then right and left twice, each with no wait and again once settled — and checks each lands back on the panel. (An element mid-slide is no anchor for a coordinate: the second swipe of a pair once resolved against the mic as it slid out, and went the wrong way.) Co-Authored-By: Claude Fable 5.1 --- .../Sources/KeyboardRootView.swift | 26 +--- .../BlurtKeyboard/Sources/PanelCarousel.swift | 141 ++++++++++++++++++ .../BlurtiOSProbe/BlurtKeyboardFlows.swift | 28 ++++ .../BlurtiOSTests/PanelCarouselTests.swift | 73 +++++++++ App/BlurtiOS/DESIGN.md | 10 +- 5 files changed, 254 insertions(+), 24 deletions(-) create mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/PanelCarousel.swift create mode 100644 App/BlurtiOS/BlurtiOSTests/PanelCarouselTests.swift diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardRootView.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardRootView.swift index 298266d3..cb618a3b 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardRootView.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardRootView.swift @@ -19,16 +19,12 @@ struct KeyboardRootView: View { var body: some View { Group { - switch model.effectiveLayout { - case .slimBar: SlimBarView(model: model) - case .panel: - PanelView(model: model) - .id("panel") - .transition(flip) - case .full: - FullKeyboardView(model: model) - .id(model.layout == .panel ? "panel-keys" : "full") - .transition(flip) + switch model.layout { + case .panel: PanelCarousel(model: model, reduceMotion: reduceMotion) + case .full: FullKeyboardView(model: model) + case .slimBar: + // The keys come up for a key term; the bar is back when it closes. + if model.termDraft == nil { SlimBarView(model: model) } else { FullKeyboardView(model: model) } } } .padding(.horizontal, KeyboardPalette.margin) @@ -59,7 +55,7 @@ struct KeyboardRootView: View { // painted pixels: `KeyboardViewController` paints a floor the eye can't // see and recognises the swipe on the input view itself, which sees // every touch the keyboard gets, the panel's empty space included. - .animation(reduceMotion ? nil : .easeInOut(duration: DesignTokens.Motion.flip), value: model.panelShowsKeys) + // The slide itself is `PanelCarousel`'s. .onAppear { // `Font.custom` falls back to the system font in silence; the bundle // must know the brand's faces (UIAppFonts + Design/fonts). @@ -70,12 +66,4 @@ struct KeyboardRootView: View { @Environment(\.accessibilityReduceMotion) private var systemReduceMotion @Environment(\.keyboardMotionHeld) private var motionHeld private var reduceMotion: Bool { systemReduceMotion || motionHeld } - - /// The carousel's slide: the incoming page arrives from the side the finger - /// moved towards, the outgoing one leaves the other way. - private var flip: AnyTransition { - model.flipTowardsLeading - ? .asymmetric(insertion: .move(edge: .trailing), removal: .move(edge: .leading)) - : .asymmetric(insertion: .move(edge: .leading), removal: .move(edge: .trailing)) - } } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/PanelCarousel.swift b/App/BlurtiOS/BlurtKeyboard/Sources/PanelCarousel.swift new file mode 100644 index 00000000..14e4bdaa --- /dev/null +++ b/App/BlurtiOS/BlurtKeyboard/Sources/PanelCarousel.swift @@ -0,0 +1,141 @@ +import SwiftUI + +/// The panel's two pages — the mic panel and the full keyboard — as a strip +/// the finger slides, one page wide. The page that is up sits in the middle; +/// when a flip comes, the other page is set down a whole page away on the +/// side the finger moved towards, and the strip slides one page: the first +/// leaves one way as the second arrives the other. Side by side, a page +/// apart, the two can never cross, whichever way the flips come — left then +/// right, or left twice. A flip back before the slide has settled retreats +/// rather than starting a second slide over the first. `PanelCarouselState` +/// holds the rules (tested); this view only animates what it says. +struct PanelCarousel: View { + var model: KeyboardModel + let reduceMotion: Bool + @State private var carousel: PanelCarouselState + /// How far the strip has slid, in pages: 0 at rest, −1 or 1 at the end of + /// a slide. The only animated value. + @State private var slide: CGFloat = 0 + @State private var onScreen = false + + init(model: KeyboardModel, reduceMotion: Bool) { + self.model = model + self.reduceMotion = reduceMotion + _carousel = State(initialValue: PanelCarouselState(keysUp: model.panelShowsKeys)) + } + + var body: some View { + GeometryReader { geo in + let width = geo.size.width + ZStack(alignment: .bottom) { + // The keys come up for a key term whichever page is up, in place. + page(keys: carousel.keysUp || model.termDraft != nil, width: width) + .offset(x: slide * width) + if let edge = carousel.incomingEdge, model.termDraft == nil { + page(keys: !carousel.keysUp, width: width) + .offset(x: (slide + (edge == .trailing ? 1 : -1)) * width) + } + } + .frame(width: width, height: geo.size.height, alignment: .bottom) + } + .onAppear { onScreen = true } + .onDisappear { onScreen = false } + .onChange(of: model.panelShowsKeys) { _, keysUp in flip(to: keysUp) } + } + + /// One page at its own height, so neither is stretched while the keyboard + /// is resizing under the slide. + @ViewBuilder private func page(keys: Bool, width: CGFloat) -> some View { + let height = + (keys ? KeyboardLayout.full : .panel).height - KeyboardRootView.verticalMargin + - KeyboardRootView.bottomMarginKeys + if keys { + FullKeyboardView(model: model).id("keys").frame(width: width, height: height, alignment: .bottom) + } else { + PanelView(model: model).id("panel").frame(width: width, height: height, alignment: .bottom) + } + } + + private func flip(to keysUp: Bool) { + let motion = carousel.flip( + to: keysUp, towardsLeading: model.flipTowardsLeading, animated: !reduceMotion && onScreen) + guard let motion else { + slide = 0 + return + } + withAnimation(.easeInOut(duration: DesignTokens.Motion.flip)) { + slide = motion.slide + } completion: { + // Only the slide that was last asked for settles the strip; an older + // one was overtaken and its ending means nothing. + guard carousel.settle(motion.generation) else { return } + var settled = Transaction() + settled.disablesAnimations = true + withTransaction(settled) { slide = 0 } + } + } +} + +/// The carousel's rules, out of the view: which page is at rest in the +/// middle, which the model wants, where the other page waits, and which slide +/// is the current one — so a flip back mid-slide retreats, a retreat cut +/// short keeps its side, and a slide that was overtaken cannot settle the +/// strip late. +nonisolated struct PanelCarouselState: Equatable { + enum Edge: Equatable { + case leading + case trailing + } + + /// What the view animates: the strip's slide in pages, and the generation + /// that may settle it when the slide ends. + struct Motion: Equatable { + let slide: CGFloat + let generation: Int + } + + /// The page in the middle at rest (true: the keys). + private(set) var keysUp: Bool + /// The page the model wants — the same as `keysUp` unless a slide is in flight. + private(set) var target: Bool + /// The side the other page waits on while a slide is in flight. + private(set) var incomingEdge: Edge? + private(set) var generation = 0 + + var inFlight: Bool { incomingEdge != nil } + + init(keysUp: Bool) { + self.keysUp = keysUp + target = keysUp + } + + /// The model flipped to `page`. Nil: settled at once, nothing to animate. + /// Otherwise what `slide` animates to: a page away towards the finger, or + /// back to 0 when this flip undoes one still in flight. + mutating func flip(to page: Bool, towardsLeading: Bool, animated: Bool) -> Motion? { + target = page + generation += 1 + guard animated else { + keysUp = page + incomingEdge = nil + return nil + } + guard page != keysUp else { + // Flipped back before the slide settled: the incoming page retreats. + return inFlight ? Motion(slide: 0, generation: generation) : nil + } + // A retreat cut short keeps its side; otherwise the finger's. + let edge = incomingEdge ?? (towardsLeading ? Edge.trailing : .leading) + incomingEdge = edge + return Motion(slide: edge == .trailing ? -1 : 1, generation: generation) + } + + /// A slide ended. True, and the strip is settled on the target page, only + /// for the generation last asked for. + mutating func settle(_ generation: Int) -> Bool { + guard generation == self.generation else { return false } + keysUp = target + incomingEdge = nil + return true + } +} diff --git a/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardFlows.swift b/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardFlows.swift index 5f95378f..f46545e7 100644 --- a/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardFlows.swift +++ b/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardFlows.swift @@ -87,6 +87,34 @@ final class BlurtKeyboardFlows: XCTestCase { } } check(!keysUp && micKey().frame.width > 200, "the panel is showing again, its mic full size") + // Pairs from one fixed screen point (an element mid-slide is no anchor): + // a flip and a flip back, and two the same way — with no wait between, + // so the second lands mid-slide, and again after the slide has settled. + // Each pair lands on the panel, the cards never having crossed. + let anchor = gap().screenPoint + let fixed = app.coordinate(withNormalizedOffset: .zero).withOffset(CGVector(dx: anchor.x, dy: anchor.y)) + let pairs = [ + Pair(name: "left then right, mid-slide", first: -160, second: 160, pause: 0), + Pair(name: "left twice, mid-slide", first: -160, second: -160, pause: 0), + Pair(name: "left then right, settled", first: -160, second: 160, pause: 0.5), + Pair(name: "left twice, settled", first: -160, second: -160, pause: 0.5), + ] + for pair in pairs { + fixed.press(forDuration: 0.05, thenDragTo: fixed.withOffset(CGVector(dx: pair.first, dy: 0))) + if pair.pause > 0 { Thread.sleep(forTimeInterval: pair.pause) } + fixed.press(forDuration: 0.05, thenDragTo: fixed.withOffset(CGVector(dx: pair.second, dy: 0))) + Thread.sleep(forTimeInterval: 1.5) + check(!keysUp && micKey().frame.width > 200, "two quick swipes, \(pair.name), land back on the panel") + shot("panel-pair-\(pair.name.replacingOccurrences(of: ", ", with: "-").replacingOccurrences(of: " ", with: "-"))") + } + } + + /// Two swipes from one point: how far each goes, and the wait between. + private struct Pair { + let name: String + let first: CGFloat + let second: CGFloat + let pause: TimeInterval } /// Where a swipe starts and how far it goes. diff --git a/App/BlurtiOS/BlurtiOSTests/PanelCarouselTests.swift b/App/BlurtiOS/BlurtiOSTests/PanelCarouselTests.swift new file mode 100644 index 00000000..73bf0f30 --- /dev/null +++ b/App/BlurtiOS/BlurtiOSTests/PanelCarouselTests.swift @@ -0,0 +1,73 @@ +import Testing + +@testable import BlurtiOS + +@Suite("Panel carousel") +struct PanelCarouselTests { + @Test("a flip slides a page towards the finger, and settling puts the other page in the middle") + func flipAndSettle() { + var strip = PanelCarouselState(keysUp: false) + let left = strip.flip(to: true, towardsLeading: true, animated: true) + #expect(left == PanelCarouselState.Motion(slide: -1, generation: 1)) + #expect(strip.incomingEdge == .trailing) + #expect(!strip.keysUp && strip.target && strip.inFlight) + let settled = strip.settle(1) + #expect(settled && strip.keysUp && !strip.inFlight) + // From the keys, a swipe right brings the panel in from the leading side. + let right = strip.flip(to: false, towardsLeading: false, animated: true) + #expect(right == PanelCarouselState.Motion(slide: 1, generation: 2)) + #expect(strip.incomingEdge == .leading) + let back = strip.settle(2) + #expect(back && !strip.keysUp) + } + + @Test("two swipes the same way wrap: the incoming page is set down on the same side each time") + func wrap() { + var strip = PanelCarouselState(keysUp: false) + let first = strip.flip(to: true, towardsLeading: true, animated: true) + #expect(first?.slide == -1) + let firstSettled = strip.settle(1) + #expect(firstSettled) + let second = strip.flip(to: false, towardsLeading: true, animated: true) + #expect(second?.slide == -1) + #expect(strip.incomingEdge == .trailing) + let secondSettled = strip.settle(2) + #expect(secondSettled && !strip.keysUp) + } + + @Test("a flip back mid-slide retreats, and the overtaken slide cannot settle the strip") + func retreat() { + var strip = PanelCarouselState(keysUp: false) + let out = strip.flip(to: true, towardsLeading: true, animated: true) + #expect(out?.generation == 1) + let back = strip.flip(to: false, towardsLeading: false, animated: true) + #expect(back == PanelCarouselState.Motion(slide: 0, generation: 2)) + #expect(strip.incomingEdge == .trailing, "the page on its way in retreats where it came from") + let late = strip.settle(1) + #expect(!late, "the first slide's ending is too late") + #expect(strip.inFlight && !strip.keysUp) + let settled = strip.settle(2) + #expect(settled && !strip.keysUp && !strip.inFlight) + } + + @Test("a retreat cut short by another flip keeps the incoming page's side") + func retreatCutShort() { + var strip = PanelCarouselState(keysUp: false) + _ = strip.flip(to: true, towardsLeading: true, animated: true) + _ = strip.flip(to: false, towardsLeading: false, animated: true) + let again = strip.flip(to: true, towardsLeading: false, animated: true) + #expect(again == PanelCarouselState.Motion(slide: -1, generation: 3)) + #expect(strip.incomingEdge == .trailing) + let settled = strip.settle(3) + #expect(settled && strip.keysUp) + } + + @Test("without motion a flip settles at once, with nothing to animate") + func still() { + var strip = PanelCarouselState(keysUp: false) + let still = strip.flip(to: true, towardsLeading: true, animated: false) + #expect(still == nil && strip.keysUp && !strip.inFlight) + let same = strip.flip(to: true, towardsLeading: true, animated: true) + #expect(same == nil, "already there: nothing moves") + } +} diff --git a/App/BlurtiOS/DESIGN.md b/App/BlurtiOS/DESIGN.md index 63a409d6..4705942e 100644 --- a/App/BlurtiOS/DESIGN.md +++ b/App/BlurtiOS/DESIGN.md @@ -260,11 +260,11 @@ push-to-talk exactly as on the Mac. Side margins 6.5; top 8; under a row of keys 13 (the iPhone's), under the slim bar 8. -| Layout | Rows | Height | -| --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | -| `slimBar` | globe · voice bar · delete · return | 60 | -| `panel` | the voice element, centred (the + top-left; cancel top-right while in flight) · globe · space · delete · return. A two-page carousel: a horizontal swipe flips between the panel and the full keyboard, and it is back to the element each time the keyboard appears. | 216, or 270 when flipped | -| `full` | voice row 44, then the first key row right under it as the iPhone's sits under its suggestions · three letter rows 43 · 123 / globe / space / return | 270 | +| Layout | Rows | Height | +| --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | +| `slimBar` | globe · voice bar · delete · return | 60 | +| `panel` | the voice element, centred (the + top-left; cancel top-right while in flight) · globe · space · delete · return. A two-page carousel: a horizontal swipe flips between the panel and the full keyboard, and it is back to the element each time the keyboard appears. The pages are a strip one page wide (`PanelCarousel`): the other page is set down a page away on the side the finger moved towards and the strip slides, so the two never cross whichever way the flips come; a flip back mid-slide retreats (`PanelCarouselState`, tested). | 216, or 270 when flipped | +| `full` | voice row 44, then the first key row right under it as the iPhone's sits under its suggestions · three letter rows 43 · 123 / globe / space / return | 270 | The voice row (`VoiceBar`) is where the system keyboard puts its suggestion bar: the element with the + a clearance beside it, the pair centred on what From 2c9f3e9053da809fc5cc46078fee558986a33eed Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Wed, 30 Sep 2026 13:14:03 -0400 Subject: [PATCH 65/79] Keyboard: highlight a word and the + is a chip that adds it Select a word in the host field and the + beside the mic becomes a chip in the field's shape holding the word; one tap adds it to the key terms as it stands, no typing, the text untouched. A check for a moment, then a quiet check: Blurt knows it. A word already in the list shows the check from the start. Hold the chip to open the field pre-filled instead (fix the spelling, replace it in the text). The selection is read on selectionDidChange and textDidChange, with Full Access only; the chip hugs the word and the pair stays centred, the element giving way to a 96 pt minimum; in the panel it grows from the corner up to 240 pt. Tokens addterm/chip-*, motion chip-hold; gallery states selected and known; the flows probe highlights the typed word and taps the chip. 85 iOS tests, 15/15 flows in the real extension. Co-Authored-By: Claude Fable 5.1 --- .../BlurtKeyboard/Sources/AddTermKey.swift | 117 ++++++++++++++++-- .../Sources/KeyboardModel+Typing.swift | 39 +++++- .../BlurtKeyboard/Sources/KeyboardModel.swift | 23 ++++ .../Sources/KeyboardViewController.swift | 7 ++ .../BlurtKeyboard/Sources/PanelView.swift | 7 +- .../BlurtKeyboard/Sources/VoiceBar.swift | 18 ++- .../Sources/KeyboardGalleryView.swift | 10 +- .../BlurtiOSProbe/BlurtKeyboardFlows.swift | 19 +++ .../BlurtiOSTests/KeyboardModelTests.swift | 77 ++++++++++++ App/BlurtiOS/DESIGN.md | 53 +++++--- App/BlurtiOS/Design/figma/tokens.js | 5 + App/BlurtiOS/Design/tokens.json | 20 +++ App/BlurtiOS/Shared/DesignTokens.swift | 15 +++ 13 files changed, 372 insertions(+), 38 deletions(-) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/AddTermKey.swift b/App/BlurtiOS/BlurtKeyboard/Sources/AddTermKey.swift index 83f34fad..8467847a 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/AddTermKey.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/AddTermKey.swift @@ -1,28 +1,123 @@ import SwiftUI -/// The small + beside the orb (and in the panel's corner): a new key term. -/// A bare glyph, quiet until it is needed; a check for a moment after one -/// was saved. +/// The small + beside the element (and in the panel's corner): a new key +/// term. A bare glyph, quiet until it is needed; a check for a moment after +/// one was saved. +/// +/// Highlight a word in the text and the + is a chip instead — the field's +/// shape, holding the word — and one tap adds the word as it stands: + for a +/// word Blurt doesn't know yet, ✓ once it does. Holding the chip opens the +/// field pre-filled instead, to fix the spelling first (`KeyboardModel`: +/// `selectedTerm`, `addSelectedTerm`, `beginAddingTerm`). struct AddTermKey: View { var model: KeyboardModel + /// The most the chip may take, where nothing else bounds it (the panel's + /// corner); nil where the row's own room does (the bar). + var maxWidth: CGFloat? @Environment(\.keyboardPalette) private var palette + @State private var pressed = false + @State private var hold: Task? + @State private var held = false var body: some View { + ZStack { + if let term = model.selectedTerm { + chip(term).transition(.opacity) + } else { + plain.transition(.opacity) + } + } + .animation(.easeInOut(duration: DesignTokens.Motion.stateFade), value: model.selectedTerm == nil) + .disabled(!model.hasFullAccess) + .opacity(model.hasFullAccess ? 1 : DesignTokens.Metrics.opacityDisabled) + } + + private var saved: Bool { model.termSavedAt != nil } + + /// The bare +: a new term typed from nothing (or from the selection, seeded). + private var plain: some View { Button { model.beginAddingTerm() } label: { - Image(systemName: model.termSavedAt == nil ? "plus" : "checkmark") - .font(.system(size: DesignTokens.Typography.sizeGlyph, weight: DesignTokens.Typography.weightGlyph)) - .foregroundStyle( - model.termSavedAt == nil ? palette.keyText.opacity(DesignTokens.Metrics.opacityLegendMuted) : palette.signal - ) + glyph(saved ? "checkmark" : "plus", tint: saved ? palette.signal : mutedTint) .frame(width: DesignTokens.Metrics.glyphHit, height: DesignTokens.Metrics.glyphHit) .contentShape(Circle()) - .contentTransition(.symbolEffect(.replace)) } .buttonStyle(KeyPressStyle()) .accessibilityLabel("Add a key term") - .disabled(!model.hasFullAccess) - .opacity(model.hasFullAccess ? 1 : DesignTokens.Metrics.opacityDisabled) + } + + /// The chip: the highlighted word, ready to add with one tap. + private func chip(_ term: String) -> some View { + let known = model.selectedTermIsKnown + return HStack(spacing: DesignTokens.Metrics.addtermChipGap) { + // Green while there is something to do, and for the moment after it + // was done; quiet once the word is simply known. + glyph(known ? "checkmark" : "plus", tint: known && !saved ? mutedTint : palette.signal) + Text(term) + .font(.system(size: DesignTokens.Typography.sizeTerm, weight: DesignTokens.Typography.weightTerm)) + .foregroundStyle(palette.keyText) + .lineLimit(1) + .truncationMode(.tail) + } + .padding(.horizontal, DesignTokens.Metrics.addtermChipPad) + .frame(height: DesignTokens.Metrics.termHeight) + .background( + RoundedRectangle(cornerRadius: DesignTokens.Metrics.termRadius) + .fill(palette.field) + .strokeBorder(palette.fieldBorder, lineWidth: DesignTokens.Metrics.termBorder) + ) + .brightness(pressed ? DesignTokens.Metrics.opacityPressBrighten : 0) + .animation(.easeOut(duration: DesignTokens.Motion.keyPress), value: pressed) + .contentShape(Rectangle()) + .accessibilityElement(children: .ignore) + .accessibilityLabel(known ? "“\(term)” is a key term" : "Add “\(term)” as a key term") + .accessibilityHint(known ? "" : "Hold to edit it first") + .accessibilityAddTraits(.isButton) + .accessibilityIdentifier("blurt-add-selected") + .simultaneousGesture(tapOrHold) + // The chip hugs the word — a shorter word, a shorter chip — and only + // shrinks, truncating the word, when the room it is offered is less: + // the bar's remainder beside the element, or this cap in the panel. The + // cap is an outer, invisible frame, so the chip never stretches to it. + .frame(maxWidth: maxWidth, alignment: .leading) + } + + /// A tap adds; a hold opens the field with the word in it; a touch that + /// travelled (the panel's carousel) does neither. + private var tapOrHold: some Gesture { + DragGesture(minimumDistance: 0) + .onChanged { value in + if !pressed { + pressed = true + held = false + hold = Task { [model] in + try? await Task.sleep(for: .seconds(DesignTokens.Motion.chipHold)) + guard !Task.isCancelled else { return } + held = true + model.beginAddingTerm() + } + } + if !KeyboardInteraction.isTap(value.translation) { + hold?.cancel() + hold = nil + } + } + .onEnded { value in + pressed = false + hold?.cancel() + hold = nil + guard !held, KeyboardInteraction.isTap(value.translation) else { return } + model.addSelectedTerm() + } + } + + private var mutedTint: Color { palette.keyText.opacity(DesignTokens.Metrics.opacityLegendMuted) } + + private func glyph(_ symbol: String, tint: Color) -> some View { + Image(systemName: symbol) + .font(.system(size: DesignTokens.Typography.sizeGlyph, weight: DesignTokens.Typography.weightGlyph)) + .foregroundStyle(tint) + .contentTransition(.symbolEffect(.replace)) } } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Typing.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Typing.swift index 54fbfb1b..a0231346 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Typing.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Typing.swift @@ -37,12 +37,34 @@ extension KeyboardModel { // MARK: Quick-add key term + /// The most characters a highlighted word may have and still be offered as + /// a key term: a name or a phrase, not a sentence. + static let termLengthCap = 48 + + /// A selection as a key term: trimmed, on one line, short enough to be a + /// name or a phrase. Nil when it is none of those, or nothing is selected. + static func termCandidate(from selected: String?) -> String? { + guard let trimmed = selected?.trimmingCharacters(in: .whitespacesAndNewlines), !trimmed.isEmpty, + trimmed.count <= termLengthCap, !trimmed.contains(where: \.isNewline) + else { return nil } + return trimmed + } + + /// The chip: the highlighted word goes into Blurt's key terms as it stands + /// — one tap, no typing, the text untouched. Nothing to do for a word Blurt + /// already has. + func addSelectedTerm() { + guard let term = selectedTerm, !selectedTermIsKnown else { return } + SharedStore.addKeyTerm(term) + selectedTermIsKnown = true + noteTermSaved() + } + /// The voice bar becomes a field and the keys type into it. If the user /// had selected a word — the one Blurt got wrong — it is the starting /// point, and saving also replaces it in the text with what they typed. func beginAddingTerm() { - let selected = proxy?.selectedText?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - let seed = selected.count <= 48 && !selected.contains("\n") ? selected : "" + let seed = Self.termCandidate(from: proxy?.selectedText) ?? "" termDraftFromSelection = seed.isEmpty ? nil : seed termHostBaseline = proxy?.documentContextBeforeInput ?? "" termHostBaselineAfter = proxy?.documentContextAfterInput ?? "" @@ -56,6 +78,8 @@ extension KeyboardModel { termDraftFromSelection = nil termHostBaseline = nil termHostBaselineAfter = nil + // The highlight may still stand: the chip comes back as it is now. + readSelection() updateShift() onLayoutChange?() } @@ -84,6 +108,15 @@ extension KeyboardModel { let trail = selected.reversed().prefix { $0.isWhitespace }.reversed() proxy?.insertText(String(lead) + draft + String(trail)) } + // Saved as selected, the word is still highlighted: the chip knows it now. + readSelection() + noteTermSaved() + updateShift() + onLayoutChange?() + } + + /// A success haptic, and the + (or the chip) shows a check for a moment. + private func noteTermSaved() { if hasFullAccess { UINotificationFeedbackGenerator().notificationOccurred(.success) } termSavedAt = Date() termNotice?.cancel() @@ -92,8 +125,6 @@ extension KeyboardModel { guard !Task.isCancelled else { return } self?.termSavedAt = nil } - updateShift() - onLayoutChange?() } /// A space — or, tapped twice quickly after a word, the system keyboard's diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift index 34dace01..95b1a20c 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift @@ -39,6 +39,14 @@ final class KeyboardModel { var termDraft: String? /// When the last term was saved, so the bar can show a check for a moment. var termSavedAt: Date? + /// The word highlighted in the host's text, when it could be a key term + /// (`termCandidate`) and the key terms are in reach (Full Access): the + + /// grows into a chip holding it, and one tap adds it. Read off the proxy + /// on every context change (`readSelection`); the gallery sets it. + var selectedTerm: String? + /// Whether `selectedTerm` is already one of Blurt's key terms: the chip + /// shows a check and adds nothing. + var selectedTermIsKnown = false /// The field's own return key, as iOS labels it: "send", "search", "go"… var returnLabel: String? /// The letter rows for the user's first keyboard language (AZERTY for @@ -156,6 +164,7 @@ final class KeyboardModel { symbolsPage = Self.wantsSymbols(proxy?.keyboardType) readAppearance() readField() + readSelection() updateShift() // Without Full Access the App Group is out of reach: the keyboard still // types, and says what it needs (see `VoiceBar`), but nothing below can run. @@ -213,6 +222,7 @@ final class KeyboardModel { func contextChanged() { readAppearance() readField() + readSelection() claimHostTypingForTerm() updateShift() } @@ -243,6 +253,19 @@ final class KeyboardModel { returnLabel = proxy?.returnKeyType.flatMap(Self.returnLabel) } + /// What is highlighted in the host's text, as a key-term candidate, and + /// whether Blurt has it already. The list lives in the App Group, so only + /// with Full Access — without it there is nothing the chip could do. + func readSelection() { + guard hasFullAccess, let term = Self.termCandidate(from: proxy?.selectedText) else { + selectedTerm = nil + selectedTermIsKnown = false + return + } + selectedTerm = term + selectedTermIsKnown = SharedStore.keyTerms.contains { $0.caseInsensitiveCompare(term) == .orderedSame } + } + private func readAppearance() { switch proxy?.keyboardAppearance { case .dark: isDark = true diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift index 53aa56cb..7891d4eb 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift @@ -138,4 +138,11 @@ final class KeyboardViewController: UIInputViewController, UIGestureRecognizerDe // The field's appearance can change with the field. paintFloor() } + + /// The highlight moved without the text changing — a word selected, or the + /// selection cleared: the + follows it (`KeyboardModel.selectedTerm`). + override func selectionDidChange(_ textInput: (any UITextInput)?) { + super.selectionDidChange(textInput) + model.contextChanged() + } } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/PanelView.swift b/App/BlurtiOS/BlurtKeyboard/Sources/PanelView.swift index 72bc6744..86f13b4a 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/PanelView.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/PanelView.swift @@ -25,6 +25,11 @@ struct PanelView: View { .transition(.opacity) } } - .overlay(alignment: .topLeading) { AddTermKey(model: model).padding(DesignTokens.Metrics.addtermInset) } + .overlay(alignment: .topLeading) { + // The +, or the chip for a highlighted word, growing from the corner + // and never as far as the cancel × in the other one. + AddTermKey(model: model, maxWidth: DesignTokens.Metrics.addtermChipMaxWidth) + .padding(DesignTokens.Metrics.addtermInset) + } } } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift index 504a298e..1213f1d4 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift @@ -6,7 +6,9 @@ import SwiftUI /// wave, say what is happening, and the haptics confirm it (see `MicControl`). /// Beside it, a small /// + for the one thing people want the instant Blurt mishears a word: add it -/// as a key term. The bar then becomes the field the keys type into. +/// as a key term. The bar then becomes the field the keys type into — or, +/// when a word is highlighted in the text, the + is already a chip holding +/// that word, and one tap adds it (`AddTermKey`). struct VoiceBar: View { var model: KeyboardModel @Environment(\.keyboardPalette) private var palette @@ -42,16 +44,22 @@ struct VoiceBar: View { // The element and the + together, centred on what shows: the mic // key is as wide as the element is (never narrower than a key, so // the ribs asleep are still a target), the + a clearance beside it. - // When the ribs wake into the wave the + slides out of its way. - let plus = DesignTokens.Metrics.glyphHit + DesignTokens.Metrics.voicebarAddtermClearance + // When the ribs wake into the wave the + slides out of its way. A + // highlighted word makes the + a chip: the bar keeps it a minimum, + // the element gives way, and the chip hugs its word inside what is + // left, so the pair stays centred. + let clearance = DesignTokens.Metrics.voicebarAddtermClearance + let chip = model.selectedTerm != nil + let beside = chip ? DesignTokens.Metrics.addtermChipMinWidth : DesignTokens.Metrics.glyphHit let recording = model.voiceState.isRecording let shown = kind.visibleWidth(slot: .bar, recording: recording) - let width = min(max(shown, DesignTokens.Metrics.keyMinWidth), geo.size.width - plus) - HStack(spacing: DesignTokens.Metrics.voicebarAddtermClearance) { + let width = min(max(shown, DesignTokens.Metrics.keyMinWidth), geo.size.width - beside - clearance) + HStack(spacing: clearance) { MicControl(model: model, slot: .bar, width: width) AddTermKey(model: model) } .animation(.easeInOut(duration: DesignTokens.Motion.waveFade), value: recording) + .animation(.easeInOut(duration: DesignTokens.Motion.stateFade), value: chip) .transition(.opacity) } } diff --git a/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift b/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift index 1e160e6b..68e54174 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift @@ -23,8 +23,10 @@ /// dictation walked on a clock, over and over, for watching or recording /// the motion), plus the keyboard's own `keys` (the panel flipped to its /// keyboard page), `symbols`, `term` (the key-term field mid-typing), - /// `send` (a return key with a label) and `saved` (the + just after a term - /// was saved). `scripts/ios-sim.sh` passes `BLURT_LAUNCH_ARGS` through, so + /// `send` (a return key with a label), `saved` (the + just after a term + /// was saved), `selected` (a word highlighted in the text: the + is the + /// chip holding it) and `known` (the same, for a word already in the key + /// terms). `scripts/ios-sim.sh` passes `BLURT_LAUNCH_ARGS` through, so /// /// BLURT_LAUNCH_ARGS="-BlurtGallery panel idle,recording,processing" \ /// scripts/ios-sim.sh --screenshot panel.png @@ -141,6 +143,10 @@ model.symbolsPage = state == "symbols" if state == "send" { model.returnLabel = "send" } if state == "saved" { model.termSavedAt = Date() } + // `selected`: a word is highlighted in the text, so the + is the chip + // holding it; `known`: the same word, already one of the key terms. + if state == "selected" || state == "known" { model.selectedTerm = "Rizz" } + model.selectedTermIsKnown = state == "known" // `landed`: the words go in 2.75 s after launch, so a screenshot taken // 3 s in (scripts/ios-sim.sh) catches the glint mid-sweep. if state == "landed" { model.resultLandedAt = Date().addingTimeInterval(2.75) } diff --git a/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardFlows.swift b/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardFlows.swift index f46545e7..52c2b7a2 100644 --- a/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardFlows.swift +++ b/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardFlows.swift @@ -140,6 +140,25 @@ final class BlurtKeyboardFlows: XCTestCase { app.buttons["return"].exists || app.buttons["RETURN"].exists || app.buttons["Return"].exists, "return key labelled") shot("full-typed") + try selectionFlow(field) + } + + /// Highlight the word in the field: the + becomes a chip holding it, one + /// tap adds it, and the chip then says Blurt has it. + private func selectionFlow(_ field: XCUIElement) throws { + field.doubleTap() + let chip = app.buttons.matching(NSPredicate(format: "label BEGINSWITH %@", "Add “")).firstMatch + check(chip.waitForExistence(timeout: 3), "highlighting a word shows the add chip (\(chip.label))") + shot("full-selected") + guard chip.exists else { return } + let word = chip.label.dropFirst("Add “".count).prefix { $0 != "”" } + chip.tap() + let known = app.descendants(matching: .any).matching(NSPredicate(format: "label == %@", "“\(word)” is a key term")) + .firstMatch + check(known.waitForExistence(timeout: 3), "one tap adds “\(word)”; the chip shows the check") + shot("full-added") + // Put the cursor back at the end so the flows after this type, not replace. + field.tap() } private func slimFlows() throws { diff --git a/App/BlurtiOS/BlurtiOSTests/KeyboardModelTests.swift b/App/BlurtiOS/BlurtiOSTests/KeyboardModelTests.swift index 53edb946..fea85cf3 100644 --- a/App/BlurtiOS/BlurtiOSTests/KeyboardModelTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/KeyboardModelTests.swift @@ -144,4 +144,81 @@ struct KeyboardModelTypingTests { model.contextChanged() #expect(model.returnLabel == nil) } + + // MARK: The chip for a highlighted word + + @Test("a selection is a key-term candidate when trimmed, on one line and short") + func termCandidate() { + #expect(KeyboardModel.termCandidate(from: " Rizz ") == "Rizz") + #expect(KeyboardModel.termCandidate(from: "Neil Bisht") == "Neil Bisht") + #expect(KeyboardModel.termCandidate(from: nil) == nil) + #expect(KeyboardModel.termCandidate(from: " ") == nil) + #expect(KeyboardModel.termCandidate(from: "two\nlines") == nil) + #expect(KeyboardModel.termCandidate(from: String(repeating: "a", count: KeyboardModel.termLengthCap)) != nil) + #expect(KeyboardModel.termCandidate(from: String(repeating: "a", count: KeyboardModel.termLengthCap + 1)) == nil) + } + + @Test("a highlighted word is the chip; one tap adds it as it stands and leaves the text alone") + func addSelectedTerm() { + let suite = ScratchSuite() + defer { suite.tearDown() } + let (model, proxy) = model(before: "he said ", selected: "Rizz") + model.hasFullAccess = true + model.contextChanged() + #expect(model.selectedTerm == "Rizz") + #expect(!model.selectedTermIsKnown) + model.addSelectedTerm() + #expect(SharedStore.keyTerms == ["Rizz"]) + #expect(model.selectedTermIsKnown) + #expect(model.termSavedAt != nil) + #expect(model.termDraft == nil) + #expect(proxy.before == "he said ") + #expect(proxy.selected == "Rizz") + // A second tap adds nothing twice. + model.addSelectedTerm() + #expect(SharedStore.keyTerms == ["Rizz"]) + } + + @Test("a word already in the key terms is known on selection; clearing the highlight takes the chip away") + func knownSelection() { + let suite = ScratchSuite() + defer { suite.tearDown() } + SharedStore.addKeyTerm("rizz") + let (model, proxy) = model(before: "he said ", selected: "Rizz") + model.hasFullAccess = true + model.contextChanged() + #expect(model.selectedTerm == "Rizz") + #expect(model.selectedTermIsKnown) + proxy.selected = nil + model.contextChanged() + #expect(model.selectedTerm == nil) + #expect(!model.selectedTermIsKnown) + } + + @Test("no chip without Full Access, or for a selection that is no term") + func noChip() { + let (model, proxy) = model(before: "", selected: "Rizz") + model.contextChanged() + #expect(model.selectedTerm == nil) + model.hasFullAccess = true + proxy.selected = "a whole\nparagraph" + model.contextChanged() + #expect(model.selectedTerm == nil) + } + + @Test("holding the chip opens the field with the word; saving it as it is leaves the chip knowing it") + func chipToField() { + let suite = ScratchSuite() + defer { suite.tearDown() } + let (model, proxy) = model(before: "he said ", selected: "riz") + model.hasFullAccess = true + model.contextChanged() + model.beginAddingTerm() + #expect(model.termDraft == "riz") + model.saveTerm() + #expect(SharedStore.keyTerms == ["riz"]) + #expect(proxy.before == "he said ") + #expect(model.selectedTerm == "riz") + #expect(model.selectedTermIsKnown) + } } diff --git a/App/BlurtiOS/DESIGN.md b/App/BlurtiOS/DESIGN.md index 4705942e..ab4a9f25 100644 --- a/App/BlurtiOS/DESIGN.md +++ b/App/BlurtiOS/DESIGN.md @@ -38,7 +38,9 @@ for a 3 s screenshot); `live` (a whole dictation walked on a clock, over and over, for watching or recording); and the keyboard's own `keys` (the panel flipped to its keyboard page), `symbols`, `term` (the key-term field mid-typing), `send` (a return key with a label), `saved` (the + just after a -term was saved). `-BlurtGalleryVoice a|b|c` picks the mic concept +term was saved), `selected` (a word highlighted in the text: the + is the chip +holding it) and `known` (the same, for a word already in the key terms). +`-BlurtGalleryVoice a|b|c` picks the mic concept (below). The gallery is `BlurtiOS/Sources/KeyboardGalleryView.swift`, debug builds only; the keyboard's sources are compiled into the app for it. @@ -286,20 +288,36 @@ gap, the mic, the space key and the letters, both ways). ## Quick-add key term The most-asked-for thing: Blurt mishears a niche word, and the fix has to take -seconds, inside the app you're typing in, never a trip to Settings. - -1. Select the misheard word in your text (or select nothing). -2. Tap the small **+** beside the element (trailing edge of the bar; top-left - corner of the panel). The bar becomes a field — × · what you type · ✓ — the - brand's input, a rectangle at 8 pt with a hairline — pre-filled with the - selection, and the keys type into it (the panel and slim bar flip to the - letter keys for it). Shift is on for the first letter. -3. Type the right spelling; return or ✓ saves. The term goes into Blurt's key - terms (`BlurtKeyTerms` in the App Group, `KeyTermList` rules: trimmed, - deduplicated case-insensitively) and rides `keyterms_prompt` on the very - next dictation. If it began as a selection and you changed it, the - misheard word in your text is replaced with what you typed. A success - haptic, and the + shows a check for 1.2 s. +seconds, inside the app you're typing in, never a trip to Settings. Two ways +in, both from the small **+** beside the element (trailing edge of the bar; +top-left corner of the panel). + +**Highlight a word, tap once.** Select a word (or a short phrase) in your text +and the + grows into a chip — the field's shape, a rectangle at 8 pt with a +hairline — holding the word, with a green **+** before it (`AddTermKey`, +`KeyboardModel.selectedTerm`). One tap adds the word as it stands to Blurt's +key terms; the text is not touched, a success haptic, and the + becomes a ✓ +for 1.2 s. The word stays highlighted and the chip now shows a quiet ✓: Blurt +knows it. A word already in the list shows that ✓ from the start, so +selecting anything tells you whether Blurt has it. The selection is read off +the host field on every change (`selectionDidChange`, `textDidChange`); what +counts as a word is trimmed, one line, at most 48 characters +(`termCandidate`, tested), and only with Full Access, since the list lives in +the App Group. In the bar the chip keeps a 96 pt minimum and the element +gives way to it; in the panel it grows from the corner up to 240 pt, clear of +the cancel ×. **Hold the chip** (0.4 s) to open the field with the word in it +instead — for the case below. + +**Type it.** Tap the + with nothing selected (or hold the chip) and the bar +becomes a field — × · what you type · ✓ — pre-filled with the selection if +there was one, and the keys type into it (the panel and slim bar flip to the +letter keys for it). Shift is on for the first letter. Type the right +spelling; return or ✓ saves. The term goes into Blurt's key terms +(`BlurtKeyTerms` in the App Group, `KeyTermList` rules: trimmed, deduplicated +case-insensitively) and rides `keyterms_prompt` on the very next dictation. If +it began as a selection and you changed it, the misheard word in your text is +replaced with what you typed. A success haptic, and the + shows a check for +1.2 s. × or an empty save leaves the mode, and so does the keyboard going away. A hardware keyboard types past the on-screen keys into the app's field; while @@ -440,6 +458,10 @@ pins the derivation. | Token | Points | Swift | Use | | ---------------------------- | --------- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `addterm/chip-gap` | `6` | `Metrics.addtermChipGap` | between the chip's glyph and the word | +| `addterm/chip-max-width` | `240` | `Metrics.addtermChipMaxWidth` | the most the chip may take in the panel's corner, clear of the cancel × | +| `addterm/chip-min-width` | `96` | `Metrics.addtermChipMinWidth` | the room the voice bar keeps for the chip; the element gives way beyond it | +| `addterm/chip-pad` | `10` | `Metrics.addtermChipPad` | the selected-word chip's side padding | | `addterm/inset` | `6` | `Metrics.addtermInset` | the + from the panel's corner | | `app/button-height` | `40` | `Metrics.appButtonHeight` | the brand's button | | `app/button-pad` | `12` | `Metrics.appButtonPad` | its side padding | @@ -568,6 +590,7 @@ house curve (`ease/signature`, `cubic-bezier(0.22, 1, 0.36, 1)`). | Token | Value | Swift | Use | | ---------------- | --------------- | ---------------------- | ------------------------------------------------------------- | | `caret` | `0.5` | `Motion.caret` | the caret's blink | +| `chip-hold` | `0.4` | `Motion.chipHold` | holding the chip opens the field instead of adding | | `colour` | `0.2` | `Motion.colour` | a colour or fill changing state: the brand's transition | | `ease/signature` | `0.22,1,0.36,1` | `Motion.easeSignature` | the house curve for everything that moves; nothing springs | | `flip` | `0.25` | `Motion.flip` | the panel's carousel | diff --git a/App/BlurtiOS/Design/figma/tokens.js b/App/BlurtiOS/Design/figma/tokens.js index f4d417e1..dba47c57 100644 --- a/App/BlurtiOS/Design/figma/tokens.js +++ b/App/BlurtiOS/Design/figma/tokens.js @@ -93,6 +93,10 @@ Keyboard|kb/notice-error|COLOR|#E67F36|Brand:orange|STROKE_COLOR|DesignTokens.Ke Keyboard|kb/popup|COLOR|#33302A|Themes:dark/popup|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.kbPopup|the letter pop-up Keyboard|kb/signal|COLOR|#67AD82|Themes:dark/signal|SHAPE_FILL,TEXT_FILL|DesignTokens.Keyboard.kbSignal|the wave, the caret, the saved check Keyboard|kb/surface|COLOR|#1D1B16|Themes:dark/surface|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.kbSurface|the design face's surface (Figma binds to kb/*; Swift reads the palette) +Metrics|addterm/chip-gap|FLOAT|6||GAP|DesignTokens.Metrics.addtermChipGap|between the chip's glyph and the word +Metrics|addterm/chip-max-width|FLOAT|240||WIDTH_HEIGHT|DesignTokens.Metrics.addtermChipMaxWidth|the most the chip may take in the panel's corner, clear of the cancel × +Metrics|addterm/chip-min-width|FLOAT|96||WIDTH_HEIGHT|DesignTokens.Metrics.addtermChipMinWidth|the room the voice bar keeps for the chip; the element gives way beyond it +Metrics|addterm/chip-pad|FLOAT|10||WIDTH_HEIGHT|DesignTokens.Metrics.addtermChipPad|the selected-word chip's side padding Metrics|addterm/inset|FLOAT|6||GAP|DesignTokens.Metrics.addtermInset|the + from the panel's corner Metrics|app/button-height|FLOAT|40||WIDTH_HEIGHT|DesignTokens.Metrics.appButtonHeight|the brand's button Metrics|app/button-pad|FLOAT|12||WIDTH_HEIGHT|DesignTokens.Metrics.appButtonPad|its side padding @@ -231,6 +235,7 @@ Typography|weight/popup|STRING|regular||FONT_STYLE|DesignTokens.Typography.weigh Typography|weight/term|STRING|regular||FONT_STYLE|DesignTokens.Typography.weightTerm| Typography|weight/voice-glyph|STRING|semibold||FONT_STYLE|DesignTokens.Typography.weightVoiceGlyph| Motion|caret|FLOAT|0.5|||DesignTokens.Motion.caret|the caret's blink +Motion|chip-hold|FLOAT|0.4|||DesignTokens.Motion.chipHold|holding the chip opens the field instead of adding Motion|colour|FLOAT|0.2|||DesignTokens.Motion.colour|a colour or fill changing state: the brand's transition Motion|ease/signature|STRING|0.22,1,0.36,1|||DesignTokens.Motion.easeSignature|the house curve for everything that moves; nothing springs Motion|flip|FLOAT|0.25|||DesignTokens.Motion.flip|the panel's carousel diff --git a/App/BlurtiOS/Design/tokens.json b/App/BlurtiOS/Design/tokens.json index 69465e4e..37f833f1 100644 --- a/App/BlurtiOS/Design/tokens.json +++ b/App/BlurtiOS/Design/tokens.json @@ -432,6 +432,22 @@ "value": 6, "use": "the + from the panel's corner" }, + "addterm/chip-pad": { + "value": 10, + "use": "the selected-word chip's side padding" + }, + "addterm/chip-gap": { + "value": 6, + "use": "between the chip's glyph and the word" + }, + "addterm/chip-min-width": { + "value": 96, + "use": "the room the voice bar keeps for the chip; the element gives way beyond it" + }, + "addterm/chip-max-width": { + "value": 240, + "use": "the most the chip may take in the panel's corner, clear of the cancel ×" + }, "card/radius": { "value": 12, "use": "the app's cards (radius/card)" @@ -835,6 +851,10 @@ "value": 0.4, "use": "the voice bar becoming the field" }, + "chip-hold": { + "value": 0.4, + "use": "holding the chip opens the field instead of adding" + }, "press": { "value": 0.1, "use": "the orb's press; the one thing that answers at once" diff --git a/App/BlurtiOS/Shared/DesignTokens.swift b/App/BlurtiOS/Shared/DesignTokens.swift index b7897af2..bbdf556c 100644 --- a/App/BlurtiOS/Shared/DesignTokens.swift +++ b/App/BlurtiOS/Shared/DesignTokens.swift @@ -201,6 +201,14 @@ enum DesignTokens { } enum Metrics { + /// Between the chip's glyph and the word. + nonisolated static let addtermChipGap: CGFloat = 6 + /// The most the chip may take in the panel's corner, clear of the cancel ×. + nonisolated static let addtermChipMaxWidth: CGFloat = 240 + /// The room the voice bar keeps for the chip; the element gives way beyond it. + nonisolated static let addtermChipMinWidth: CGFloat = 96 + /// The selected-word chip's side padding. + nonisolated static let addtermChipPad: CGFloat = 10 /// The + from the panel's corner. nonisolated static let addtermInset: CGFloat = 6 /// The brand's button. @@ -457,6 +465,8 @@ enum DesignTokens { enum Motion { /// The caret's blink. nonisolated static let caret: Double = 0.5 + /// Holding the chip opens the field instead of adding. + nonisolated static let chipHold: Double = 0.4 /// A colour or fill changing state: the brand's transition. nonisolated static let colour: Double = 0.2 /// The house curve for everything that moves; nothing springs. @@ -600,6 +610,10 @@ enum DesignTokens { "keyboard.kb/popup": "#33302A", "keyboard.kb/signal": "#67AD82", "keyboard.kb/surface": "#1D1B16", + "metrics.addterm/chip-gap": "6", + "metrics.addterm/chip-max-width": "240", + "metrics.addterm/chip-min-width": "96", + "metrics.addterm/chip-pad": "10", "metrics.addterm/inset": "6", "metrics.app/button-height": "40", "metrics.app/button-pad": "12", @@ -738,6 +752,7 @@ enum DesignTokens { "type.weight/term": "regular", "type.weight/voice-glyph": "semibold", "motion.caret": "0.5", + "motion.chip-hold": "0.4", "motion.colour": "0.2", "motion.ease/signature": "0.22,1,0.36,1", "motion.flip": "0.25", From 8b4848cbd89446c4f3c720bce3162c53d2d15588 Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Wed, 30 Sep 2026 14:31:43 -0400 Subject: [PATCH 66/79] Keyboard: the mic at the left or right edge, for one hand MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Settings → Keyboard, under the layout and in its shape — Left alignment · Default · Right alignment with a line beneath. MicAlignment lives in the App Group and the keyboard reads it on appearance, as it does the layout. At an edge the mic key is the thing at the edge: in the bar and the slim bar the pair slides there and the + moves to the mic's inner side; the panel becomes a big voice bar — the element at the edge as wide as it shows, the + beside it, cancel in the far corner. Left and right are the phone's sides, so a right-to-left language flips the leading/trailing mapping and the mic stays under the thumb chosen. Gallery -BlurtGalleryAlign, probe word left|right, ios-keyboard-flows.sh --align; the probe resets the key terms at launch so the add-chip flow finds its word new every run, and knows an edge-aligned panel's mic is element-wide. 88 iOS tests; flows green in the real extension: full right 16/16, panel right 26/26, slim bar left 12/12. Co-Authored-By: Claude Fable 5.1 --- .../BlurtKeyboard/Sources/KeyboardModel.swift | 6 ++ .../BlurtKeyboard/Sources/PanelView.swift | 28 ++++++-- .../BlurtKeyboard/Sources/VoiceBar.swift | 10 ++- .../Sources/KeyboardGalleryView.swift | 14 ++-- .../BlurtiOS/Sources/KeyboardProbeView.swift | 13 ++-- .../BlurtiOS/Sources/SettingsView.swift | 10 +++ .../BlurtiOSProbe/BlurtKeyboardFlows.swift | 72 ++++++++++++++----- .../BlurtiOSTests/SharedStateTests.swift | 35 +++++++++ App/BlurtiOS/DESIGN.md | 31 ++++++-- App/BlurtiOS/Shared/MicAlignment.swift | 55 ++++++++++++++ App/BlurtiOS/Shared/SharedState.swift | 8 +++ scripts/ios-keyboard-flows.sh | 12 +++- 12 files changed, 254 insertions(+), 40 deletions(-) create mode 100644 App/BlurtiOS/Shared/MicAlignment.swift diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift index 95b1a20c..e5f600bb 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift @@ -103,6 +103,11 @@ final class KeyboardModel { var voiceKind: VoiceElementKind { voiceKindOverride ?? storedVoiceKind } var storedVoiceKind = SharedStore.voiceElementKind var voiceKindOverride: VoiceElementKind? + /// Where the mic key sits across the row, from Settings (one hand: at the + /// thumb's edge) — or, for a preview or a gallery row, whatever it is told. + var micAlignment: MicAlignment { micAlignmentOverride ?? storedMicAlignment } + var storedMicAlignment = SharedStore.micAlignment + var micAlignmentOverride: MicAlignment? /// Whether the app being typed in wants a dark keyboard: what its field /// asks for, else the app's own light or dark appearance. var isDark = false @@ -172,6 +177,7 @@ final class KeyboardModel { layout = SharedStore.layout themeID = SharedStore.themeID storedVoiceKind = SharedStore.voiceElementKind + storedMicAlignment = SharedStore.micAlignment SharedStore.keyboardEverSeen = true refresh(haptics: false) startHeartbeat() diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/PanelView.swift b/App/BlurtiOS/BlurtKeyboard/Sources/PanelView.swift index 86f13b4a..775d8f7e 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/PanelView.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/PanelView.swift @@ -5,11 +5,29 @@ import SwiftUI struct PanelView: View { var model: KeyboardModel @Environment(\.keyboardPalette) private var palette + @Environment(\.voiceElementKind) private var kind + @Environment(\.layoutDirection) private var direction var body: some View { + let alignment = model.micAlignment.alignment(in: direction) + let atEdge = alignment != .center + let plusLeads = model.micAlignment.plusLeads(in: direction) + let recording = model.voiceState.isRecording + // In the middle the element has its whole slot and the + its corner. At + // an edge (one hand) the panel is a big voice bar: the key is as wide as + // the element shows, so the element itself — not an empty half of its + // box — is what sits under the thumb, the + beside it on its inner side, + // and cancel in the far corner, clear of them both. + let width = atEdge ? max(kind.visibleWidth(slot: .panel, recording: recording), DesignTokens.Metrics.keyMinWidth) : nil VStack(spacing: DesignTokens.Metrics.panelSpacing) { Spacer(minLength: 0) - MicControl(model: model, slot: .panel) + HStack(spacing: DesignTokens.Metrics.voicebarAddtermClearance) { + if atEdge, plusLeads { AddTermKey(model: model) } + MicControl(model: model, slot: .panel, width: width) + if atEdge, !plusLeads { AddTermKey(model: model) } + } + .frame(maxWidth: .infinity, alignment: alignment) + .animation(.easeInOut(duration: DesignTokens.Motion.waveFade), value: recording) Spacer(minLength: 0) HStack(spacing: KeyboardPalette.keyGap) { if model.needsGlobe { KeyCap(systemImage: "globe", dark: true) { model.globe() } } @@ -18,7 +36,7 @@ struct PanelView: View { KeyCap(title: model.returnLabel ?? "return", dark: true) { model.newline() } } } - .overlay(alignment: .topTrailing) { + .overlay(alignment: alignment == .trailing ? .topLeading : .topTrailing) { if model.voiceState.canCancel { KeyCap(systemImage: "xmark", tint: palette.notice, bare: true) { model.cancel() } .accessibilityLabel("Cancel dictation") @@ -28,8 +46,10 @@ struct PanelView: View { .overlay(alignment: .topLeading) { // The +, or the chip for a highlighted word, growing from the corner // and never as far as the cancel × in the other one. - AddTermKey(model: model, maxWidth: DesignTokens.Metrics.addtermChipMaxWidth) - .padding(DesignTokens.Metrics.addtermInset) + if !atEdge { + AddTermKey(model: model, maxWidth: DesignTokens.Metrics.addtermChipMaxWidth) + .padding(DesignTokens.Metrics.addtermInset) + } } } } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift index 1213f1d4..b9eb2b55 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift @@ -13,6 +13,7 @@ struct VoiceBar: View { var model: KeyboardModel @Environment(\.keyboardPalette) private var palette @Environment(\.voiceElementKind) private var kind + @Environment(\.layoutDirection) private var direction static let height = DesignTokens.Metrics.voicebarHeight @@ -54,16 +55,21 @@ struct VoiceBar: View { let recording = model.voiceState.isRecording let shown = kind.visibleWidth(slot: .bar, recording: recording) let width = min(max(shown, DesignTokens.Metrics.keyMinWidth), geo.size.width - beside - clearance) + // At the right edge the + comes first, so the mic is the thing + // at the edge and the + sits on its inner side. HStack(spacing: clearance) { + if model.micAlignment.plusLeads(in: direction) { AddTermKey(model: model) } MicControl(model: model, slot: .bar, width: width) - AddTermKey(model: model) + if !model.micAlignment.plusLeads(in: direction) { AddTermKey(model: model) } } .animation(.easeInOut(duration: DesignTokens.Motion.waveFade), value: recording) .animation(.easeInOut(duration: DesignTokens.Motion.stateFade), value: chip) .transition(.opacity) } } - .frame(maxWidth: .infinity, maxHeight: .infinity) + // The pair sits where Settings put the mic — the middle, or the edge + // under the thumb (`MicAlignment`); the field and the note fill the row. + .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: model.micAlignment.alignment(in: direction)) } .frame(height: Self.height) .animation(.easeInOut(duration: DesignTokens.Motion.termSwap), value: model.termDraft == nil) diff --git a/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift b/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift index 68e54174..c6a6c7ed 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift @@ -5,7 +5,7 @@ /// reference, and the way a screenshot of the keyboard is taken without /// tapping through Notes. Debug builds only, reached by launch argument: /// - /// -BlurtGallery [,…] [face] [-BlurtGalleryStill] [-BlurtGalleryBare] [-BlurtGalleryVoice a|b|c] + /// -BlurtGallery [,…] [face] [-BlurtGalleryStill] [-BlurtGalleryBare] [-BlurtGalleryVoice a|b|c] [-BlurtGalleryAlign left|center|right] /// /// The last word is a face, `light` or `dark` (the older theme words still /// land: `system` and `paper` are light, `system-dark` and `ink` dark); the @@ -15,7 +15,9 @@ /// captures of one state are the same pixels; `-BlurtGalleryBare` draws the /// first row alone, no caption, inside a 2 pt `#FF00FF` registration border /// that `scripts/design-diff.swift crop` cuts to. `-BlurtGalleryVoice a|b|c` - /// picks which mic concept draws (`VoiceElementKind`); `-BlurtVoice + /// picks which mic concept draws (`VoiceElementKind`); `-BlurtGalleryAlign + /// left|center|right` puts the mic at a side (`MicAlignment`, as Settings → + /// Mic side does); `-BlurtVoice /// [light|dark]` renders that element by itself. /// where a state is `off` (no Full Access), `start` (app not listening), /// `idle`, `connecting`, `recording`, `processing`, `pasted`, `copied`, @@ -110,10 +112,11 @@ // The theme is the next word unless it is a switch. let theme = arguments.count > flag + 3 && !arguments[flag + 3].hasPrefix("-") ? arguments[flag + 3] : "light" let voice = VoiceElementKind.parse(arguments) ?? .shipped + let align = MicAlignment.parse(arguments) ?? .center return arguments[flag + 2].split(separator: ",").map { name in Row( - caption: "\(layout.rawValue) · \(name) · \(theme) · \(voice.rawValue)", - model: model(layout: layout, state: String(name), theme: theme, voice: voice)) + caption: "\(layout.rawValue) · \(name) · \(theme) · \(voice.rawValue) · \(align.rawValue)", + model: model(layout: layout, state: String(name), theme: theme, voice: voice, align: align)) } } @@ -128,11 +131,12 @@ ] private static func model( - layout: KeyboardLayout, state: String, theme: String, voice: VoiceElementKind + layout: KeyboardLayout, state: String, theme: String, voice: VoiceElementKind, align: MicAlignment ) -> KeyboardModel { let model = KeyboardModel() model.layout = layout model.voiceKindOverride = voice + model.micAlignmentOverride = align model.paletteOverride = .resolve(KeyboardPalette.brandID, dark: Self.darkFaces.contains(theme)) // `keys` shows the panel's carousel flipped to its keyboard page; // `term` the voice bar as the key-term field, mid-typing. diff --git a/App/BlurtiOS/BlurtiOS/Sources/KeyboardProbeView.swift b/App/BlurtiOS/BlurtiOS/Sources/KeyboardProbeView.swift index a3e07492..7b27734e 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/KeyboardProbeView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/KeyboardProbeView.swift @@ -11,10 +11,11 @@ struct KeyboardProbeView: View { let dark: Bool - /// `-BlurtProbeField light|dark [a|b|c] [slimBar|panel|full]`: the words - /// after the face set the mic concept and the layout in the App Group, - /// so the Blurt keyboard — which reads both on every appearance — comes up - /// that way for a capture of the real extension (`scripts/ios-keyboard-shot.sh`). + /// `-BlurtProbeField light|dark [a|b|c] [slimBar|panel|full] [left|center|right]`: + /// the words after the face set the mic concept, the layout and the mic's + /// side in the App Group, so the Blurt keyboard — which reads them on every + /// appearance — comes up that way for a capture of the real extension + /// (`scripts/ios-keyboard-shot.sh`, `scripts/ios-keyboard-flows.sh`). static func parse(_ arguments: [String]) -> KeyboardProbeView? { guard let flag = arguments.firstIndex(of: "-BlurtProbeField") else { return nil } let face = arguments.count > flag + 1 ? arguments[flag + 1] : "light" @@ -22,7 +23,11 @@ for word in arguments.dropFirst(flag + 2).prefix(while: { !$0.hasPrefix("-") }) { if let kind = VoiceElementKind(rawValue: word) { SharedStore.voiceElementKind = kind } if let layout = KeyboardLayout(rawValue: word) { SharedStore.layout = layout } + if let side = MicAlignment(rawValue: word) { SharedStore.micAlignment = side } } + // `-BlurtProbeResetTerms`: an empty key-term list, so a flow that adds a + // word finds it new on every run (the App Group outlives the test). + if arguments.contains("-BlurtProbeResetTerms") { SharedStore.keyTerms = [] } return KeyboardProbeView(dark: face == "dark") } diff --git a/App/BlurtiOS/BlurtiOS/Sources/SettingsView.swift b/App/BlurtiOS/BlurtiOS/Sources/SettingsView.swift index 17bf445b..ddb02948 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/SettingsView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/SettingsView.swift @@ -9,6 +9,7 @@ struct SettingsView: View { var coordinator: DictationCoordinator @Environment(\.dismiss) private var dismiss @State private var layout = SharedStore.layout + @State private var micAlignment = SharedStore.micAlignment @State private var autoDictate = SharedStore.autoDictate @State private var windowMinutes = SharedStore.windowMinutes @AppStorage(BlurtShared.Key.theme, store: SharedStore.defaults) private var themeID = "system" @@ -48,6 +49,15 @@ struct SettingsView: View { .pickerStyle(.segmented) .onChange(of: layout) { _, value in SharedStore.layout = value } Text(layout.summary).font(BlurtType.body(DesignTokens.Typography.sizeCaption)).foregroundStyle(BlurtBrand.muted) + // The mic's side, for one hand — the same shape as the layout above: three + // segments and a line saying what the choice does. + Picker("Mic alignment", selection: $micAlignment) { + ForEach(MicAlignment.allCases) { Text($0.title).tag($0) } + } + .pickerStyle(.segmented) + .onChange(of: micAlignment) { _, value in SharedStore.micAlignment = value } + Text(micAlignment.summary).font(BlurtType.body(DesignTokens.Typography.sizeCaption)) + .foregroundStyle(BlurtBrand.muted) NavigationLink { ThemePickerView() } label: { diff --git a/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardFlows.swift b/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardFlows.swift index 52c2b7a2..d115a70f 100644 --- a/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardFlows.swift +++ b/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardFlows.swift @@ -12,15 +12,19 @@ import XCTest final class BlurtKeyboardFlows: XCTestCase { private var app = XCUIApplication() private var shots = 0 + /// `left` or `right` when the run puts the mic at an edge (Settings › + /// alignment); nil for the middle. + private var side: String? func testFlows() throws { continueAfterFailure = true let arguments = ProcessInfo.processInfo.environment["BLURT_PROBE_ARGS"]?.split(separator: " ").map(String.init) ?? ["light"] let layout = arguments.first { ["slimBar", "panel", "full"].contains($0) } ?? "panel" + side = arguments.first { ["left", "right"].contains($0) } app = XCUIApplication() // The app listens from launch, so the keyboard's mic key is live. - app.launchArguments = ["-BlurtProbeField"] + arguments + ["-BlurtStartListening"] + app.launchArguments = ["-BlurtProbeField"] + arguments + ["-BlurtStartListening", "-BlurtProbeResetTerms"] app.launch() try bringUpBlurt() shot("up") @@ -32,7 +36,22 @@ final class BlurtKeyboardFlows: XCTestCase { if mic.exists, plus.exists { let width = app.windows.firstMatch.frame.width let centre = mic.frame.midX - if layout == "panel" { + if let side { + // One hand: the mic at the chosen edge, the + on its inner side. The + // slim bar's row is bounded by the globe (when Blurt draws one; on a + // Face ID phone the system puts it under the keyboard) and delete + // keys, so there the mic is next to that key rather than the edge. + let left = side == "left" + let globe = app.buttons["globe"].firstMatch + let bound = + layout == "slimBar" + ? (left ? (globe.exists ? globe.frame.maxX : 0) : app.buttons["delete.left"].firstMatch.frame.minX) + : (left ? 0 : width) + let edge = left ? mic.frame.minX - bound : bound - mic.frame.maxX + let inner = left ? plus.frame.minX > mic.frame.maxX : plus.frame.maxX < mic.frame.minX + check(edge < 12, "mic at the \(side) edge (\(edge) pt in)") + check(inner, "the + on the mic's inner side") + } else if layout == "panel" { check(abs(centre - width / 2) < 4, "mic centred in the panel (\(centre) of \(width))") check(plus.frame.midX < 60, "the + in the panel's top-left corner (\(plus.frame.midX))") } else { @@ -86,7 +105,7 @@ final class BlurtKeyboardFlows: XCTestCase { if index == 0 { shot("panel-back") } } } - check(!keysUp && micKey().frame.width > 200, "the panel is showing again, its mic full size") + check(!keysUp && micKey().frame.width > panelMicWidth, "the panel is showing again, its mic full size") // Pairs from one fixed screen point (an element mid-slide is no anchor): // a flip and a flip back, and two the same way — with no wait between, // so the second lands mid-slide, and again after the slide has settled. @@ -104,7 +123,7 @@ final class BlurtKeyboardFlows: XCTestCase { if pair.pause > 0 { Thread.sleep(forTimeInterval: pair.pause) } fixed.press(forDuration: 0.05, thenDragTo: fixed.withOffset(CGVector(dx: pair.second, dy: 0))) Thread.sleep(forTimeInterval: 1.5) - check(!keysUp && micKey().frame.width > 200, "two quick swipes, \(pair.name), land back on the panel") + check(!keysUp && micKey().frame.width > panelMicWidth, "two quick swipes, \(pair.name), land back on the panel") shot("panel-pair-\(pair.name.replacingOccurrences(of: ", ", with: "-").replacingOccurrences(of: " ", with: "-"))") } } @@ -127,6 +146,10 @@ final class BlurtKeyboardFlows: XCTestCase { /// Whether the letter keys are on screen (either shift state). private var keysUp: Bool { letterKey("Q").exists || letterKey("q").exists } + /// The least the panel's mic key is wide when the panel is up: its whole + /// 300 pt slot in the middle, the element's own width at an edge. + private var panelMicWidth: CGFloat { side == nil ? 200 : 60 } + private func fullFlows() throws { let q = letterKey("Q") check(q.exists, "letter keys present") @@ -146,19 +169,36 @@ final class BlurtKeyboardFlows: XCTestCase { /// Highlight the word in the field: the + becomes a chip holding it, one /// tap adds it, and the chip then says Blurt has it. private func selectionFlow(_ field: XCUIElement) throws { - field.doubleTap() - let chip = app.buttons.matching(NSPredicate(format: "label BEGINSWITH %@", "Add “")).firstMatch - check(chip.waitForExistence(timeout: 3), "highlighting a word shows the add chip (\(chip.label))") + // Double-tap the word itself — it sits at the field's leading edge — not + // the field's empty middle, and once more after a beat if the highlight + // didn't take the first time (a shot of the miss says why). + // Either face of the chip: the word to add, or — were the list not reset — + // the word Blurt already knows. + let chip = app.buttons.matching( + NSPredicate(format: "label BEGINSWITH %@ OR label ENDSWITH %@", "Add “", "” is a key term") + ).firstMatch + for attempt in 1...2 where !chip.exists { + field.coordinate(withNormalizedOffset: CGVector(dx: 0.08, dy: 0.5)).doubleTap() + if chip.waitForExistence(timeout: 3) { break } + shot("full-select-miss-\(attempt)") + } + let label = chip.exists ? chip.label : "-" + check(chip.exists, "highlighting a word shows the chip (\(label))") shot("full-selected") - guard chip.exists else { return } - let word = chip.label.dropFirst("Add “".count).prefix { $0 != "”" } - chip.tap() - let known = app.descendants(matching: .any).matching(NSPredicate(format: "label == %@", "“\(word)” is a key term")) - .firstMatch - check(known.waitForExistence(timeout: 3), "one tap adds “\(word)”; the chip shows the check") - shot("full-added") - // Put the cursor back at the end so the flows after this type, not replace. - field.tap() + if label.hasPrefix("Add “") { + let word = label.dropFirst("Add “".count).prefix { $0 != "”" } + chip.tap() + let known = app.descendants(matching: .any) + .matching(NSPredicate(format: "label == %@", "“\(word)” is a key term")).firstMatch + check(known.waitForExistence(timeout: 3), "one tap adds “\(word)”; the chip shows the check") + shot("full-added") + } else if chip.exists { + check(false, "the word was already a key term before this run (\(label)) — the list was not reset") + } + // Clear the highlight, cursor at the end, so the + is back for the flows + // after this and typing appends rather than replaces. + field.coordinate(withNormalizedOffset: CGVector(dx: 0.95, dy: 0.5)).tap() + Thread.sleep(forTimeInterval: 0.5) } private func slimFlows() throws { diff --git a/App/BlurtiOS/BlurtiOSTests/SharedStateTests.swift b/App/BlurtiOS/BlurtiOSTests/SharedStateTests.swift index d042b034..20d25292 100644 --- a/App/BlurtiOS/BlurtiOSTests/SharedStateTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/SharedStateTests.swift @@ -1,8 +1,43 @@ import Foundation +import SwiftUI import Testing @testable import BlurtiOS +@Suite("Mic alignment setting") +struct MicAlignmentSettingTests { + @Test("the mic's side round-trips through the App Group; unset or unknown is the middle") + func roundTrip() { + let suite = ScratchSuite() + defer { suite.tearDown() } + #expect(SharedStore.micAlignment == .center) + SharedStore.micAlignment = .right + #expect(SharedStore.micAlignment == .right) + SharedStore.defaults.set("sideways", forKey: BlurtShared.Key.micAlignment) + #expect(SharedStore.micAlignment == .center) + } + + @Test("left and right are the phone's sides whatever the language reads in; the + leads only at the trailing edge") + func sides() { + #expect(MicAlignment.left.alignment(in: .leftToRight) == .leading) + #expect(MicAlignment.left.alignment(in: .rightToLeft) == .trailing) + #expect(MicAlignment.right.alignment(in: .leftToRight) == .trailing) + #expect(MicAlignment.right.alignment(in: .rightToLeft) == .leading) + #expect(MicAlignment.center.alignment(in: .rightToLeft) == .center) + #expect(MicAlignment.right.plusLeads(in: .leftToRight)) + #expect(MicAlignment.left.plusLeads(in: .rightToLeft)) + #expect(!MicAlignment.left.plusLeads(in: .leftToRight)) + #expect(!MicAlignment.center.plusLeads(in: .leftToRight)) + } + + @Test("the gallery and probe words name a side") + func parse() { + #expect(MicAlignment.parse(["-BlurtGallery", "panel", "idle", "-BlurtGalleryAlign", "right"]) == .right) + #expect(MicAlignment.parse(["-BlurtGallery", "panel", "idle"]) == nil) + #expect(MicAlignment(rawValue: "left") == .left) + } +} + @Suite("Key term list") struct KeyTermListTests { @Test("parse trims, drops blanks, and deduplicates case-insensitively in first-seen order") diff --git a/App/BlurtiOS/DESIGN.md b/App/BlurtiOS/DESIGN.md index ab4a9f25..4a76f5a0 100644 --- a/App/BlurtiOS/DESIGN.md +++ b/App/BlurtiOS/DESIGN.md @@ -40,7 +40,8 @@ flipped to its keyboard page), `symbols`, `term` (the key-term field mid-typing), `send` (a return key with a label), `saved` (the + just after a term was saved), `selected` (a word highlighted in the text: the + is the chip holding it) and `known` (the same, for a word already in the key terms). -`-BlurtGalleryVoice a|b|c` picks the mic concept +`-BlurtGalleryVoice a|b|c` picks the mic concept and `-BlurtGalleryAlign +left|center|right` the mic's side (One hand, below) (below). The gallery is `BlurtiOS/Sources/KeyboardGalleryView.swift`, debug builds only; the keyboard's sources are compiled into the app for it. @@ -262,11 +263,11 @@ push-to-talk exactly as on the Mac. Side margins 6.5; top 8; under a row of keys 13 (the iPhone's), under the slim bar 8. -| Layout | Rows | Height | -| --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | -| `slimBar` | globe · voice bar · delete · return | 60 | -| `panel` | the voice element, centred (the + top-left; cancel top-right while in flight) · globe · space · delete · return. A two-page carousel: a horizontal swipe flips between the panel and the full keyboard, and it is back to the element each time the keyboard appears. The pages are a strip one page wide (`PanelCarousel`): the other page is set down a page away on the side the finger moved towards and the strip slides, so the two never cross whichever way the flips come; a flip back mid-slide retreats (`PanelCarouselState`, tested). | 216, or 270 when flipped | -| `full` | voice row 44, then the first key row right under it as the iPhone's sits under its suggestions · three letter rows 43 · 123 / globe / space / return | 270 | +| Layout | Rows | Height | +| --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | +| `slimBar` | globe · voice bar · delete · return | 60 | +| `panel` | the voice element, centred — or at an edge for one hand (Settings, below) — (the + top-left; cancel top-right while in flight) · globe · space · delete · return. A two-page carousel: a horizontal swipe flips between the panel and the full keyboard, and it is back to the element each time the keyboard appears. The pages are a strip one page wide (`PanelCarousel`): the other page is set down a page away on the side the finger moved towards and the strip slides, so the two never cross whichever way the flips come; a flip back mid-slide retreats (`PanelCarouselState`, tested). | 216, or 270 when flipped | +| `full` | voice row 44, then the first key row right under it as the iPhone's sits under its suggestions · three letter rows 43 · 123 / globe / space / return | 270 | The voice row (`VoiceBar`) is where the system keyboard puts its suggestion bar: the element with the + a clearance beside it, the pair centred on what @@ -357,6 +358,24 @@ sits dimmed and the first tap opens Blurt. When the keyboard leaves the screen with a dictation it started, it releases a recording (the words still land, on the clipboard if no keyboard is there) and cancels anything earlier. +## One hand: the mic at an edge + +Settings → Keyboard, under the layout, the same three-segment shape with a +line beneath: **Left alignment · Default · Right alignment** (`MicAlignment`, +`micAlignment` in the App Group, read on every appearance like the layout). +Default is the middle, as everywhere above. At an edge the mic key is the +thing at the edge. In the bar and the slim bar the pair slides there and the +add key (+) moves to the mic's inner side, so at the right edge it comes +first. The panel becomes a big voice bar: the element sits at the edge as +wide as it _shows_ (`visibleWidth`, so the grille is under the thumb, not an +empty half of its 300 pt box), the add key beside it on its inner side rather +than in the corner, and cancel in the far top corner, clear of them both. +Left and right are the phone's sides: in a right-to-left language the +leading/trailing mapping flips so the mic stays under the thumb chosen +(`Shared/MicAlignment.swift`, tested). Gallery: `-BlurtGalleryAlign +left|center|right`; the real extension: `scripts/ios-keyboard-flows.sh +--align left|right` checks the mic is at that edge with the add key inside it. + ## Tokens (`Design/tokens.json` → `Shared/DesignTokens.swift`) The brand's colours, as the design system defines them and as the phone diff --git a/App/BlurtiOS/Shared/MicAlignment.swift b/App/BlurtiOS/Shared/MicAlignment.swift new file mode 100644 index 00000000..0ca8a067 --- /dev/null +++ b/App/BlurtiOS/Shared/MicAlignment.swift @@ -0,0 +1,55 @@ +import SwiftUI + +/// Where the mic key sits across the keyboard, for one hand: at the left +/// edge, in the middle (the default), or at the right edge. Left and right +/// are the phone's own sides — the side the thumb is on — whatever the +/// language reads in (Settings → Keyboard, under the layout; the keyboard +/// reads it on appearance). +nonisolated enum MicAlignment: String, CaseIterable, Codable, Sendable, Identifiable { + case left + case center + case right + + var id: String { rawValue } + + var title: String { + switch self { + case .left: "Left alignment" + case .center: "Default" + case .right: "Right alignment" + } + } + + var summary: String { + switch self { + case .left: "The mic key at the left edge of the keyboard, under your thumb." + case .center: "The mic key in the middle of the keyboard." + case .right: "The mic key at the right edge of the keyboard, under your thumb." + } + } +} + +extension MicAlignment { + /// The side of the row, as SwiftUI counts sides: left is the leading edge + /// in a left-to-right language and the trailing one in a right-to-left + /// one, so the mic stays under the thumb the user chose either way. + func alignment(in direction: LayoutDirection) -> Alignment { + switch self { + case .center: .center + case .left: direction == .leftToRight ? .leading : .trailing + case .right: direction == .leftToRight ? .trailing : .leading + } + } + + /// Whether the + goes before the mic in the row: at the trailing edge, so + /// the mic is the thing at the edge and the + sits on its inner side. + func plusLeads(in direction: LayoutDirection) -> Bool { + alignment(in: direction) == .trailing + } + + /// `-BlurtGalleryAlign left|center|right`, or nil when the arguments don't say. + static func parse(_ arguments: [String]) -> MicAlignment? { + guard let flag = arguments.firstIndex(of: "-BlurtGalleryAlign"), arguments.count > flag + 1 else { return nil } + return MicAlignment(rawValue: arguments[flag + 1]) + } +} diff --git a/App/BlurtiOS/Shared/SharedState.swift b/App/BlurtiOS/Shared/SharedState.swift index 75ada6f1..1c25e54d 100644 --- a/App/BlurtiOS/Shared/SharedState.swift +++ b/App/BlurtiOS/Shared/SharedState.swift @@ -25,6 +25,8 @@ nonisolated enum BlurtShared { /// TEMPORARY: which mic concept draws (a, b or c), while the three are /// tried in use. Goes with the losers once one is picked. static let voiceElement = "voiceElement" + /// Where the mic key sits across the keyboard (`MicAlignment`). + static let micAlignment = "micAlignment" static let listeningUntil = "listeningUntil" static let windowMinutes = "listeningWindowMinutes" static let phase = "phase" @@ -246,6 +248,12 @@ nonisolated enum SharedStore { set { defaults.set(newValue.rawValue, forKey: BlurtShared.Key.voiceElement) } } + /// Where the mic key sits across the keyboard; the middle until chosen. + static var micAlignment: MicAlignment { + get { MicAlignment(rawValue: defaults.string(forKey: BlurtShared.Key.micAlignment) ?? "") ?? .center } + set { defaults.set(newValue.rawValue, forKey: BlurtShared.Key.micAlignment) } + } + /// Hands-free: the keyboard starts a dictation the moment it appears in a /// text field, so there is nothing to tap before talking. On by default. static var autoDictate: Bool { diff --git a/scripts/ios-keyboard-flows.sh b/scripts/ios-keyboard-flows.sh index 739c9221..fa320ed5 100755 --- a/scripts/ios-keyboard-flows.sh +++ b/scripts/ios-keyboard-flows.sh @@ -7,6 +7,7 @@ # # scripts/ios-keyboard-flows.sh # the whole matrix # scripts/ios-keyboard-flows.sh --face dark --voice a --layout panel +# scripts/ios-keyboard-flows.sh --layout full --align right # the mic at an edge (Settings › alignment) # # Prints one FLOW-OK / FLOW-FAIL line per step; screenshots land in # .build/design/flows/--/, with a sheet.png of every @@ -22,6 +23,7 @@ DERIVED="${BLURT_DERIVED_DATA:-$REPO_ROOT/.build/ios-sim}" FACES="light dark" VOICES="a b c" LAYOUTS="panel full slimBar" +ALIGN="" OUT="$REPO_ROOT/.build/design/flows" while [ $# -gt 0 ]; do case "$1" in @@ -41,8 +43,12 @@ while [ $# -gt 0 ]; do OUT="${2:?}" shift 2 ;; + --align) + ALIGN="${2:?}" + shift 2 + ;; *) - echo "usage: ios-keyboard-flows.sh [--face light|dark] [--voice a|b|c] [--layout slimBar|panel|full] [--out DIR]" >&2 + echo "usage: ios-keyboard-flows.sh [--face light|dark] [--voice a|b|c] [--layout slimBar|panel|full] [--align left|right] [--out DIR]" >&2 exit 2 ;; esac @@ -66,12 +72,12 @@ for face in $FACES; do xcrun simctl ui "$UDID" appearance "$face" for voice in $VOICES; do for layout in $LAYOUTS; do - name="$face-$voice-$layout" + name="$face-$voice-$layout${ALIGN:+-$ALIGN}" dir="$OUT/$name" rm -rf "$dir" mkdir -p "$dir" echo "==> $name" - TEST_RUNNER_BLURT_PROBE_ARGS="$face $voice $layout" xcodebuild test \ + TEST_RUNNER_BLURT_PROBE_ARGS="$face $voice $layout${ALIGN:+ $ALIGN}" xcodebuild test \ -project "$REPO_ROOT/App/BlurtiOS/BlurtiOS.xcodeproj" -scheme BlurtiOSProbe \ -only-testing:BlurtiOSProbe/BlurtKeyboardFlows \ -destination "platform=iOS Simulator,id=$UDID" -derivedDataPath "$DERIVED" \ From 3e37780bd715eb4bb35a681f7765bfa7ab2f767c Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Wed, 30 Sep 2026 15:28:57 -0400 Subject: [PATCH 67/79] Keyboard: the mic itself is centred; the + hangs beside it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A pair centred as a whole put the grille left of centre and read as off. Now the element is dead centre and an unseen twin of the + balances the other side, so the + hangs off the element rather than shifting it. Edge alignment unchanged. Probe: the centring check measures the mic, not the pair; selection flow double-taps the word itself and accepts either face of the chip; the run resets the key terms and the mic's side at launch (the App Group outlives a run); switchAwayAndBack drives the system globe away and back from the mic page and the keys page — the mic comes back both ways, at the panel's own height; dismissAndReturn puts the keyboard away (a new probe-dismiss button in the probe field) and brings it back — written, not yet run green. Neil's "mic gone after switching keyboards" in Messages is the carousel case the other session is reproducing there; nothing here touches PanelCarousel. Full flow 18/18 and panel flow 28/28 with the switch steps, in the probe app. Co-Authored-By: Claude Fable 5.1 --- .../BlurtKeyboard/Sources/VoiceBar.swift | 36 ++-- .../BlurtiOS/Sources/KeyboardProbeView.swift | 11 + .../BlurtiOSProbe/BlurtKeyboardFlows.swift | 190 +++++++++++++----- App/BlurtiOS/DESIGN.md | 13 +- 4 files changed, 183 insertions(+), 67 deletions(-) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift index b9eb2b55..72a9e8c7 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift @@ -42,25 +42,37 @@ struct VoiceBar: View { .accessibilityLabel("Start Blurt") .transition(.opacity) } else { - // The element and the + together, centred on what shows: the mic - // key is as wide as the element is (never narrower than a key, so - // the ribs asleep are still a target), the + a clearance beside it. - // When the ribs wake into the wave the + slides out of its way. A - // highlighted word makes the + a chip: the bar keeps it a minimum, - // the element gives way, and the chip hugs its word inside what is - // left, so the pair stays centred. + // The element where Settings put it, the + a clearance beside it. + // In the middle the element itself is dead centre — an unseen twin + // of the + balances the row on the other side, so the + hangs off + // the element rather than shifting it. The mic key is as wide as + // the element is (never narrower than a key, so the ribs asleep are + // still a target); when the ribs wake into the wave the + slides + // out of its way. A highlighted word makes the + a chip: the bar + // keeps it a minimum, the element gives way, and the chip hugs its + // word inside what is left. At the right edge the + comes first, so + // the mic is the thing at the edge and the + sits on its inner side. let clearance = DesignTokens.Metrics.voicebarAddtermClearance let chip = model.selectedTerm != nil + let centred = model.micAlignment == .center + let plusLeads = model.micAlignment.plusLeads(in: direction) let beside = chip ? DesignTokens.Metrics.addtermChipMinWidth : DesignTokens.Metrics.glyphHit let recording = model.voiceState.isRecording let shown = kind.visibleWidth(slot: .bar, recording: recording) - let width = min(max(shown, DesignTokens.Metrics.keyMinWidth), geo.size.width - beside - clearance) - // At the right edge the + comes first, so the mic is the thing - // at the edge and the + sits on its inner side. + let room = geo.size.width - (beside + clearance) * (centred ? 2 : 1) // literal-ok: a twin on each side + let width = min(max(shown, DesignTokens.Metrics.keyMinWidth), room) HStack(spacing: clearance) { - if model.micAlignment.plusLeads(in: direction) { AddTermKey(model: model) } + if plusLeads { + AddTermKey(model: model) + } else if centred { + AddTermKey(model: model).hidden() + } MicControl(model: model, slot: .bar, width: width) - if !model.micAlignment.plusLeads(in: direction) { AddTermKey(model: model) } + if !plusLeads { + AddTermKey(model: model) + } else if centred { + AddTermKey(model: model).hidden() + } } .animation(.easeInOut(duration: DesignTokens.Motion.waveFade), value: recording) .animation(.easeInOut(duration: DesignTokens.Motion.stateFade), value: chip) diff --git a/App/BlurtiOS/BlurtiOS/Sources/KeyboardProbeView.swift b/App/BlurtiOS/BlurtiOS/Sources/KeyboardProbeView.swift index 7b27734e..80d04200 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/KeyboardProbeView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/KeyboardProbeView.swift @@ -20,6 +20,9 @@ guard let flag = arguments.firstIndex(of: "-BlurtProbeField") else { return nil } let face = arguments.count > flag + 1 ? arguments[flag + 1] : "light" guard face == "light" || face == "dark" else { return nil } + // The mic's side is the middle unless a word says otherwise: the App + // Group outlives a run, and an earlier `left` must not leak into this one. + SharedStore.micAlignment = .center for word in arguments.dropFirst(flag + 2).prefix(while: { !$0.hasPrefix("-") }) { if let kind = VoiceElementKind(rawValue: word) { SharedStore.voiceElementKind = kind } if let layout = KeyboardLayout(rawValue: word) { SharedStore.layout = layout } @@ -36,6 +39,14 @@ ProbeField(dark: dark) .frame(height: DesignTokens.Metrics.keyMinWidth) .padding() + // Puts the keyboard away without leaving the field, so a flow can + // bring it back into the same host and see what a re-appearance + // in a living extension keeps or loses. + Button("Dismiss keyboard") { + UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil) + } + .accessibilityIdentifier("probe-dismiss") + .foregroundStyle(dark ? Color.white : Color.black) Spacer(minLength: 0) } .frame(maxWidth: .infinity, maxHeight: .infinity) diff --git a/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardFlows.swift b/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardFlows.swift index d115a70f..c5f270dd 100644 --- a/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardFlows.swift +++ b/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardFlows.swift @@ -55,11 +55,14 @@ final class BlurtKeyboardFlows: XCTestCase { check(abs(centre - width / 2) < 4, "mic centred in the panel (\(centre) of \(width))") check(plus.frame.midX < 60, "the + in the panel's top-left corner (\(plus.frame.midX))") } else { - // The pair is centred in the voice bar's own width: the whole row in - // the full keyboard, the room left of delete and return in the slim bar. - let pair = (mic.frame.minX + plus.frame.maxX) / 2 - let room = layout == "slimBar" ? app.buttons["delete.left"].firstMatch.frame.minX : width - check(abs(pair - room / 2) < 20, "mic and + centred as a pair (\(pair) in \(room))") + // The element itself is centred in the voice bar's own width — the + // whole row in the full keyboard, the room between the globe (if any) + // and delete in the slim bar — with the + hanging beside it. + let globe = app.buttons["globe"].firstMatch + let from = layout == "slimBar" && globe.exists ? globe.frame.maxX : 0 + let to = layout == "slimBar" ? app.buttons["delete.left"].firstMatch.frame.minX : width + check(abs(centre - (from + to) / 2) < 8, "mic centred in its row (\(centre) in \(from)…\(to))") + check(plus.frame.minX > mic.frame.maxX, "the + beside the mic, to its right") } } switch layout { @@ -69,6 +72,138 @@ final class BlurtKeyboardFlows: XCTestCase { } try termFlow() try dictationFlow() + try switchAwayAndBack() + } + + // MARK: Helpers + + private func bringUpBlurt() throws { + let blurt = app.buttons["Add a key term"] + let system = app.keyboards.firstMatch + let deadline = Date().addingTimeInterval(15) + while !blurt.exists, !system.exists, Date() < deadline { Thread.sleep(forTimeInterval: 0.5) } + var hops = 0 + while !blurt.waitForExistence(timeout: 2), hops < 4 { + let globe = app.buttons["Next keyboard"] + XCTAssertTrue(globe.waitForExistence(timeout: 5), "no globe key") + globe.tap() + hops += 1 + } + XCTAssertTrue(blurt.exists, "Blurt never came up") + Thread.sleep(forTimeInterval: 1.5) + } + + /// Blurt's mic key, by its identifier: the system's own bottom bar has a + /// "Dictate" button too, and a label query lands on it. + private func micKey() -> XCUIElement { + app.buttons.matching(NSPredicate(format: "identifier == %@", "blurt-mic")).firstMatch + } + + private func micKey(labelled label: String) -> XCUIElement { + app.buttons.matching(NSPredicate(format: "identifier == %@ AND label == %@", "blurt-mic", label)).firstMatch + } + + private func letterKey(_ letter: String) -> XCUIElement { + app.buttons.matching(NSPredicate(format: "label == %@", letter)).firstMatch + } + + private func check(_ condition: Bool, _ what: String) { + print("FLOW-\(condition ? "OK" : "FAIL"): \(what)") + XCTAssertTrue(condition, what) + } + + private func shot(_ name: String) { + shots += 1 + let attachment = XCTAttachment(screenshot: app.screenshot()) + attachment.name = "flow-\(String(format: "%02d", shots))-\(name).png" + attachment.lifetime = .keepAlways + add(attachment) + } +} + +// MARK: - Switching keyboards + +extension BlurtKeyboardFlows { + /// The globe under the keyboard: away to the system keyboard and back to + /// Blurt. The mic key must be there again, drawn and full size — the one + /// thing a fresh appearance in a living extension process can lose. + private func switchAwayAndBack() throws { + let globe = app.buttons["Next keyboard"].firstMatch + guard globe.exists else { + check(false, "no globe under the keyboard to switch with") + return + } + // Once from the page that is up, and — on the panel — once more from its + // keys page, the way a swipe leaves it: the panel must come back on its + // mic page, at its own height, with the mic drawn. + try switchAwayAndBack(globe: globe, from: "the mic page") + if micKey().exists, app.buttons["space"].exists, !keysUp { + flipToKeys() + if keysUp { try switchAwayAndBack(globe: globe, from: "the keys page") } + } + // And the other way a keyboard comes back: put away and brought up again + // in the same field, from the mic page and from the keys page. + try dismissAndReturn(from: "the mic page") + if micKey().exists, app.buttons["space"].exists, !keysUp { + flipToKeys() + if keysUp { try dismissAndReturn(from: "the keys page") } + } + } + + /// A swipe on the panel's gap, to its keys page. + private func flipToKeys() { + let gap = micKey().coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 1.15)) + gap.press(forDuration: 0.05, thenDragTo: gap.withOffset(CGVector(dx: -160, dy: 0))) + Thread.sleep(forTimeInterval: 1.2) + } + + private func dismissAndReturn(from page: String) throws { + let dismiss = app.buttons["probe-dismiss"] + guard dismiss.exists else { return } + let plus = app.buttons["Add a key term"] + dismiss.tap() + Thread.sleep(forTimeInterval: 1.5) + check(!plus.exists && !micKey().exists, "the keyboard goes away (from \(page))") + app.textFields.firstMatch.tap() + let back = plus.waitForExistence(timeout: 5) || micKey().waitForExistence(timeout: 2) + Thread.sleep(forTimeInterval: 1.5) + let mic = micKey() + let frame = mic.exists ? mic.frame : .zero + check(back && frame.width > 40 && frame.height > 20, "brought back from \(page) the mic key is there, full size (\(frame))") + if frame == .zero { print("FLOW-TREE (mic missing after the return):\n\(app.debugDescription)") } + if page == "the keys page" { check(!keysUp, "the panel is back on its mic page after being put away") } + shot("returned-\(page == "the mic page" ? "mic" : "keys")") + } + + private func switchAwayAndBack(globe: XCUIElement, from page: String) throws { + // XCUITest has no Keyboard element for a custom keyboard: the + at the + // panel's top corner stands in for where the keyboard begins. + let plus = app.buttons["Add a key term"] + let topBefore = plus.exists ? plus.frame.minY : 0 + globe.tap() + Thread.sleep(forTimeInterval: 2) + check(!plus.exists, "the globe switches away from Blurt (from \(page))") + shot("switched-away") + var hops = 0 + while !plus.waitForExistence(timeout: 2), hops < 4 { + app.buttons["Next keyboard"].firstMatch.tap() + hops += 1 + } + Thread.sleep(forTimeInterval: 1.5) + let mic = micKey() + let top = plus.exists ? plus.frame.minY : 0 + // One snapshot: an element that flickers would throw between two. + let frame = mic.exists ? mic.frame : .zero + check( + frame.width > 40 && frame.height > 20, + "back on Blurt from \(page) the mic key is there, full size (\(frame); top \(topBefore) → \(top))") + if frame == .zero { print("FLOW-TREE (mic missing after the switch):\n\(app.debugDescription)") } + if page == "the keys page" { + check(!keysUp, "the panel is back on its mic page after the switch") + // The keys page was up before, so the keyboard was 54 pt taller then. + check(abs(top - topBefore - 54) < 4, "the panel is back at its own height (top \(topBefore) → \(top))") + } + shot("switched-back") } // MARK: Flows @@ -239,49 +374,4 @@ final class BlurtKeyboardFlows: XCTestCase { check(back.waitForExistence(timeout: 12), "a second tap stops it and the key settles") shot("settled") } - - // MARK: Helpers - - private func bringUpBlurt() throws { - let blurt = app.buttons["Add a key term"] - let system = app.keyboards.firstMatch - let deadline = Date().addingTimeInterval(15) - while !blurt.exists, !system.exists, Date() < deadline { Thread.sleep(forTimeInterval: 0.5) } - var hops = 0 - while !blurt.waitForExistence(timeout: 2), hops < 4 { - let globe = app.buttons["Next keyboard"] - XCTAssertTrue(globe.waitForExistence(timeout: 5), "no globe key") - globe.tap() - hops += 1 - } - XCTAssertTrue(blurt.exists, "Blurt never came up") - Thread.sleep(forTimeInterval: 1.5) - } - - /// Blurt's mic key, by its identifier: the system's own bottom bar has a - /// "Dictate" button too, and a label query lands on it. - private func micKey() -> XCUIElement { - app.buttons.matching(NSPredicate(format: "identifier == %@", "blurt-mic")).firstMatch - } - - private func micKey(labelled label: String) -> XCUIElement { - app.buttons.matching(NSPredicate(format: "identifier == %@ AND label == %@", "blurt-mic", label)).firstMatch - } - - private func letterKey(_ letter: String) -> XCUIElement { - app.buttons.matching(NSPredicate(format: "label == %@", letter)).firstMatch - } - - private func check(_ condition: Bool, _ what: String) { - print("FLOW-\(condition ? "OK" : "FAIL"): \(what)") - XCTAssertTrue(condition, what) - } - - private func shot(_ name: String) { - shots += 1 - let attachment = XCTAttachment(screenshot: app.screenshot()) - attachment.name = "flow-\(String(format: "%02d", shots))-\(name).png" - attachment.lifetime = .keepAlways - add(attachment) - } } diff --git a/App/BlurtiOS/DESIGN.md b/App/BlurtiOS/DESIGN.md index 4a76f5a0..ea4f7e4f 100644 --- a/App/BlurtiOS/DESIGN.md +++ b/App/BlurtiOS/DESIGN.md @@ -270,11 +270,14 @@ slim bar 8. | `full` | voice row 44, then the first key row right under it as the iPhone's sits under its suggestions · three letter rows 43 · 123 / globe / space / return | 270 | The voice row (`VoiceBar`) is where the system keyboard puts its suggestion -bar: the element with the + a clearance beside it, the pair centred on what -the element _shows_ (`VoiceElementKind.visibleWidth`, tested: the grille's -own width, the ribs asleep or the wave awake, the streak's line — never the -slot's box, which would put the + off at the edge; the mic key is never -narrower than a key), or the key-term field. A swipe flips the panel past +bar: the element dead centre with the + a clearance beside it — an unseen +twin of the + balances the other side, so the + hangs off the element rather +than shifting it (a pair centred as a whole read as off) — or, for one hand, +the element at an edge with the + inside it (One hand, below). The mic key +is as wide as the element _shows_ (`VoiceElementKind.visibleWidth`, tested: +the grille's own width, the ribs asleep or the wave awake, the streak's line +— never the slot's box, which would put the + off at the edge; never +narrower than a key). Or the row is the key-term field. A swipe flips the panel past 48 pt sideways and more sideways than up or down by 1.5×; a key acts on release and only under 12 pt of travel (`KeyboardInteraction`, tested). The swipe is recognised on the input view itself (`KeyboardViewController`), not From c3b632a27f8fc761ea76ad14eaf5ff074aadc3b7 Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Wed, 30 Sep 2026 15:30:14 -0400 Subject: [PATCH 68/79] Probe: the panel's carousel inside Messages, every way, on video MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `MessagesCarouselProbe` brings Blurt up in Messages — the globe's menu, else hopping — and swipes the panel from one fixed point twelve times: left, right, left twice, right twice, and pairs with no wait between, with a screenshot and a FLOW line after each saying which page is up. Run under `xcrun simctl io recordVideo` to see the motion. Verified the strip carousel in Neil's host: every swipe lands on the page it should, the mic element drawn on each return. Co-Authored-By: Claude Fable 5.1 --- .../BlurtiOSProbe/MessagesCarouselProbe.swift | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 App/BlurtiOS/BlurtiOSProbe/MessagesCarouselProbe.swift diff --git a/App/BlurtiOS/BlurtiOSProbe/MessagesCarouselProbe.swift b/App/BlurtiOS/BlurtiOSProbe/MessagesCarouselProbe.swift new file mode 100644 index 00000000..8e019e85 --- /dev/null +++ b/App/BlurtiOS/BlurtiOSProbe/MessagesCarouselProbe.swift @@ -0,0 +1,98 @@ +import XCTest + +/// The panel's carousel inside Messages — Neil's host — swiped every which +/// way from one fixed point, with a screenshot after each swipe and a +/// FLOW line saying which page is up. Run under `simctl io recordVideo` to +/// see the motion itself. Blurt must be enabled as a keyboard on the +/// simulator, and the App Group set to the panel (`-BlurtProbeField light a +/// panel` once). +@MainActor +final class MessagesCarouselProbe: XCTestCase { + private var shots = 0 + + func testSwipes() throws { + continueAfterFailure = true + let messages = XCUIApplication(bundleIdentifier: "com.apple.MobileSMS") + messages.launch() + let plus = try bringUpBlurt(in: messages) + Thread.sleep(forTimeInterval: 2) + let mic = messages.buttons.matching(NSPredicate(format: "identifier == %@", "blurt-mic")).firstMatch + XCTAssertTrue(mic.exists, "no mic key") + print("FLOW-INFO mic \(mic.frame) plus \(plus.frame)") + shot(messages, "up") + // One fixed point: the gap under the panel's mic. + let anchor = mic.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 1.15)).screenPoint + let fixed = messages.coordinate(withNormalizedOffset: .zero).withOffset(CGVector(dx: anchor.x, dy: anchor.y)) + let sequence = [ + Swipe("left", -160, 1.2), Swipe("right", 160, 1.2), Swipe("left", -160, 1.2), Swipe("left", -160, 1.2), + Swipe("right", 160, 1.2), Swipe("right", 160, 1.2), Swipe("left", -160, 0), Swipe("right", 160, 1.2), + Swipe("left", -160, 0), Swipe("left", -160, 1.2), Swipe("right", 160, 0), Swipe("left", -160, 1.2), + ] + for (index, swipe) in sequence.enumerated() { + fixed.press(forDuration: 0.05, thenDragTo: fixed.withOffset(CGVector(dx: swipe.dx, dy: 0))) + guard swipe.pause > 0 else { continue } + Thread.sleep(forTimeInterval: swipe.pause) + let keys = messages.buttons.matching(NSPredicate(format: "label == %@ OR label == %@", "Q", "q")).firstMatch + // The panel's mic is element-wide when aligned to an edge, so its + // presence, not its width, says the panel is up. + let up = keys.exists ? "keys" : (mic.exists ? "panel" : "NEITHER") + print("FLOW-INFO after \(index + 1) (\(swipe.name)): \(up)") + shot(messages, "\(index + 1)-\(swipe.name)") + } + } + + /// One swipe: how far, and how long to wait after it (0: the next comes at once). + private struct Swipe { + let name: String + let dx: CGFloat + let pause: TimeInterval + init(_ name: String, _ dx: CGFloat, _ pause: TimeInterval) { + self.name = name + self.dx = dx + self.pause = pause + } + } + + /// A conversation, its field, and Blurt on it: the globe's menu goes + /// straight there; hopping does when there is no menu. Returns the +. + private func bringUpBlurt(in messages: XCUIApplication) throws -> XCUIElement { + let cell = messages.cells.firstMatch + if cell.waitForExistence(timeout: 5) { + cell.tap() + } else { + messages.buttons["compose"].firstMatch.tap() + } + let field = messages.descendants(matching: .any).matching( + NSPredicate(format: "placeholderValue == %@ OR label == %@", "iMessage", "iMessage") + ).firstMatch + XCTAssertTrue(field.waitForExistence(timeout: 10), "no message field") + field.tap() + let plus = messages.buttons.matching(NSPredicate(format: "label BEGINSWITH %@", "Add a key term")).firstMatch + var hops = 0 + while !plus.waitForExistence(timeout: 2), hops < 12 { + let globe = messages.buttons["Next keyboard"] + XCTAssertTrue(globe.waitForExistence(timeout: 5), "no globe key") + if hops == 0 { + globe.press(forDuration: 1) + let item = messages.descendants(matching: .any).matching(NSPredicate(format: "label == %@", "Blurt")).firstMatch + if item.waitForExistence(timeout: 2) { + item.tap() + hops += 1 + continue + } + } + globe.tap() + hops += 1 + } + XCTAssertTrue(plus.exists, "Blurt never came up in Messages") + return plus + } + + private func shot(_ app: XCUIApplication, _ name: String) { + shots += 1 + let attachment = XCTAttachment(screenshot: app.screenshot()) + attachment.name = "flow-\(String(format: "%02d", shots))-\(name).png" + attachment.lifetime = .keepAlways + add(attachment) + } +} From cf2f9cc31289e401f45dc040f647588086e7e651 Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Wed, 30 Sep 2026 15:43:01 -0400 Subject: [PATCH 69/79] Probe: every way a keyboard comes back, ending with the mic drawn Chasing "switching keyboards makes the dictation button disappear" (the panel page up, no grille). The probe field gains a dismiss button and one button per layout (what Settings does while a keyboard is up elsewhere), and the flows end with the re-appearances: the system globe away and back from the mic page and the keys page; put away and brought back from both pages; the layout changed to each other layout and back, re-shown each time; a slow swipe that rests on the mic long enough to press it before travelling; a swipe while recording. In the probe app every one brings the mic key back, full size, at the panel's own height, drawn (screenshots). The reappearance probes live in their own file; the shared helpers are no longer private. Not reproduced here, nor in the other session's Messages carousel probe. Panel flow 40/40, full flow 26/26. Co-Authored-By: Claude Fable 5.1 --- .../BlurtiOS/Sources/KeyboardProbeView.swift | 10 ++ .../BlurtKeyboardFlows+Reappearance.swift | 140 ++++++++++++++++++ .../BlurtiOSProbe/BlurtKeyboardFlows.swift | 105 ++----------- 3 files changed, 163 insertions(+), 92 deletions(-) create mode 100644 App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardFlows+Reappearance.swift diff --git a/App/BlurtiOS/BlurtiOS/Sources/KeyboardProbeView.swift b/App/BlurtiOS/BlurtiOS/Sources/KeyboardProbeView.swift index 80d04200..8b364159 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/KeyboardProbeView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/KeyboardProbeView.swift @@ -47,6 +47,16 @@ } .accessibilityIdentifier("probe-dismiss") .foregroundStyle(dark ? Color.white : Color.black) + // What Settings does while a keyboard is up elsewhere: the layout + // changes in the App Group, and the keyboard reads it when it next + // appears. One button per layout, so a flow can switch and re-show. + HStack { + ForEach(KeyboardLayout.allCases) { layout in + Button(layout.rawValue) { SharedStore.layout = layout } + .accessibilityIdentifier("probe-layout-\(layout.rawValue)") + } + } + .foregroundStyle(dark ? Color.white : Color.black) Spacer(minLength: 0) } .frame(maxWidth: .infinity, maxHeight: .infinity) diff --git a/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardFlows+Reappearance.swift b/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardFlows+Reappearance.swift new file mode 100644 index 00000000..a0683600 --- /dev/null +++ b/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardFlows+Reappearance.swift @@ -0,0 +1,140 @@ +import XCTest + +// The ways a keyboard comes back — the system globe away and back, put +// away and brought up in the same field, a layout changed in Settings +// meanwhile, a rough swipe on the panel — each ending with the mic key +// there and drawn. `BlurtKeyboardFlows.testFlows` runs these last. + +// MARK: - Switching keyboards + +extension BlurtKeyboardFlows { + /// The globe under the keyboard: away to the system keyboard and back to + /// Blurt. The mic key must be there again, drawn and full size — the one + /// thing a fresh appearance in a living extension process can lose. + func switchAwayAndBack() throws { + let globe = app.buttons["Next keyboard"].firstMatch + guard globe.exists else { + check(false, "no globe under the keyboard to switch with") + return + } + // Once from the page that is up, and — on the panel — once more from its + // keys page, the way a swipe leaves it: the panel must come back on its + // mic page, at its own height, with the mic drawn. + try switchAwayAndBack(globe: globe, from: "the mic page") + if micKey().exists, app.buttons["space"].exists, !keysUp { + flipToKeys() + if keysUp { try switchAwayAndBack(globe: globe, from: "the keys page") } + } + // And the other way a keyboard comes back: put away and brought up again + // in the same field, from the mic page and from the keys page. + try dismissAndReturn(from: "the mic page") + if micKey().exists, app.buttons["space"].exists, !keysUp { + flipToKeys() + if keysUp { try dismissAndReturn(from: "the keys page") } + } + // And with the layout changed in Settings meanwhile: to each of the + // other two, then back to this run's own, the keyboard re-shown after + // each change. + let others = ["slimBar", "panel", "full"].filter { $0 != layoutName } + [layoutName] + for other in others where app.buttons["probe-layout-\(other)"].exists { + app.buttons["probe-layout-\(other)"].tap() + try dismissAndReturn(from: "a layout change to \(other)") + } + if layoutName == "panel", micKey().exists, !keysUp { try roughSwipes() } + } + + /// The swipes a finger makes and a clean drag does not: one that rests on + /// the mic long enough to press it before it travels (a press goes out and + /// is cancelled), and one taken while a dictation is recording. After each + /// pair the panel must be back with its mic drawn. + private func roughSwipes() throws { + let mic = micKey() + let held = mic.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5)) + held.press(forDuration: 0.35, thenDragTo: held.withOffset(CGVector(dx: -160, dy: 0))) + Thread.sleep(forTimeInterval: 1.2) + check(keysUp, "a slow swipe from the mic flips to the keys (\(micKey().label))") + swipeBackFromLetters() + var frame = micKey().exists ? micKey().frame : .zero + check( + frame.width > 200, "after a slow swipe from the mic and back, the mic is there (\(frame), \(micKey().label))") + shot("rough-slow") + guard micKey().exists, micKey().label == "Dictate" else { return } + micKey().tap() + check(micKey(labelled: "Stop dictation").waitForExistence(timeout: 4), "a tap starts a dictation") + let gap = micKey().coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 1.15)) + gap.press(forDuration: 0.05, thenDragTo: gap.withOffset(CGVector(dx: -160, dy: 0))) + Thread.sleep(forTimeInterval: 1.2) + check(keysUp, "a swipe while recording flips to the keys") + swipeBackFromLetters() + frame = micKey().exists ? micKey().frame : .zero + check(frame.width > 200, "back on the panel while recording, the mic is there (\(frame), \(micKey().label))") + shot("rough-recording") + if micKey(labelled: "Stop dictation").exists { micKey().tap() } + _ = micKey(labelled: "Dictate").waitForExistence(timeout: 12) + } + + private func swipeBackFromLetters() { + let g = letterKey("g").exists ? letterKey("g") : letterKey("G") + let on = g.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5)) + on.press(forDuration: 0.05, thenDragTo: on.withOffset(CGVector(dx: 160, dy: 0))) + Thread.sleep(forTimeInterval: 1.2) + } + + /// A swipe on the panel's gap, to its keys page. + private func flipToKeys() { + let gap = micKey().coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 1.15)) + gap.press(forDuration: 0.05, thenDragTo: gap.withOffset(CGVector(dx: -160, dy: 0))) + Thread.sleep(forTimeInterval: 1.2) + } + + private func dismissAndReturn(from page: String) throws { + let dismiss = app.buttons["probe-dismiss"] + guard dismiss.exists else { return } + let plus = app.buttons["Add a key term"] + dismiss.tap() + Thread.sleep(forTimeInterval: 1.5) + check(!plus.exists && !micKey().exists, "the keyboard goes away (from \(page))") + app.textFields.firstMatch.tap() + let back = plus.waitForExistence(timeout: 5) || micKey().waitForExistence(timeout: 2) + Thread.sleep(forTimeInterval: 1.5) + let mic = micKey() + let frame = mic.exists ? mic.frame : .zero + check( + back && frame.width > 40 && frame.height > 20, + "brought back from \(page) the mic key is there, full size (\(frame))") + if frame == .zero { print("FLOW-TREE (mic missing after the return):\n\(app.debugDescription)") } + if page == "the keys page" { check(!keysUp, "the panel is back on its mic page after being put away") } + shot("returned-\(page.replacingOccurrences(of: " ", with: "-"))") + } + + private func switchAwayAndBack(globe: XCUIElement, from page: String) throws { + // XCUITest has no Keyboard element for a custom keyboard: the + at the + // panel's top corner stands in for where the keyboard begins. + let plus = app.buttons["Add a key term"] + let topBefore = plus.exists ? plus.frame.minY : 0 + globe.tap() + Thread.sleep(forTimeInterval: 2) + check(!plus.exists, "the globe switches away from Blurt (from \(page))") + shot("switched-away") + var hops = 0 + while !plus.waitForExistence(timeout: 2), hops < 4 { + app.buttons["Next keyboard"].firstMatch.tap() + hops += 1 + } + Thread.sleep(forTimeInterval: 1.5) + let mic = micKey() + let top = plus.exists ? plus.frame.minY : 0 + // One snapshot: an element that flickers would throw between two. + let frame = mic.exists ? mic.frame : .zero + check( + frame.width > 40 && frame.height > 20, + "back on Blurt from \(page) the mic key is there, full size (\(frame); top \(topBefore) → \(top))") + if frame == .zero { print("FLOW-TREE (mic missing after the switch):\n\(app.debugDescription)") } + if page == "the keys page" { + check(!keysUp, "the panel is back on its mic page after the switch") + // The keys page was up before, so the keyboard was 54 pt taller then. + check(abs(top - topBefore - 54) < 4, "the panel is back at its own height (top \(topBefore) → \(top))") + } + shot("switched-back") + } +} diff --git a/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardFlows.swift b/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardFlows.swift index c5f270dd..db804b42 100644 --- a/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardFlows.swift +++ b/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardFlows.swift @@ -10,17 +10,20 @@ import XCTest /// `scripts/ios-keyboard-flows.sh` runs the matrix and collects them. @MainActor final class BlurtKeyboardFlows: XCTestCase { - private var app = XCUIApplication() - private var shots = 0 + var app = XCUIApplication() + var shots = 0 /// `left` or `right` when the run puts the mic at an edge (Settings › /// alignment); nil for the middle. - private var side: String? + var side: String? + /// The layout this run is of: `slimBar`, `panel` or `full`. + var layoutName = "panel" func testFlows() throws { continueAfterFailure = true let arguments = ProcessInfo.processInfo.environment["BLURT_PROBE_ARGS"]?.split(separator: " ").map(String.init) ?? ["light"] let layout = arguments.first { ["slimBar", "panel", "full"].contains($0) } ?? "panel" + layoutName = layout side = arguments.first { ["left", "right"].contains($0) } app = XCUIApplication() // The app listens from launch, so the keyboard's mic key is live. @@ -95,24 +98,24 @@ final class BlurtKeyboardFlows: XCTestCase { /// Blurt's mic key, by its identifier: the system's own bottom bar has a /// "Dictate" button too, and a label query lands on it. - private func micKey() -> XCUIElement { + func micKey() -> XCUIElement { app.buttons.matching(NSPredicate(format: "identifier == %@", "blurt-mic")).firstMatch } - private func micKey(labelled label: String) -> XCUIElement { + func micKey(labelled label: String) -> XCUIElement { app.buttons.matching(NSPredicate(format: "identifier == %@ AND label == %@", "blurt-mic", label)).firstMatch } - private func letterKey(_ letter: String) -> XCUIElement { + func letterKey(_ letter: String) -> XCUIElement { app.buttons.matching(NSPredicate(format: "label == %@", letter)).firstMatch } - private func check(_ condition: Bool, _ what: String) { + func check(_ condition: Bool, _ what: String) { print("FLOW-\(condition ? "OK" : "FAIL"): \(what)") XCTAssertTrue(condition, what) } - private func shot(_ name: String) { + func shot(_ name: String) { shots += 1 let attachment = XCTAttachment(screenshot: app.screenshot()) attachment.name = "flow-\(String(format: "%02d", shots))-\(name).png" @@ -121,91 +124,9 @@ final class BlurtKeyboardFlows: XCTestCase { } } -// MARK: - Switching keyboards +// MARK: - Flows extension BlurtKeyboardFlows { - /// The globe under the keyboard: away to the system keyboard and back to - /// Blurt. The mic key must be there again, drawn and full size — the one - /// thing a fresh appearance in a living extension process can lose. - private func switchAwayAndBack() throws { - let globe = app.buttons["Next keyboard"].firstMatch - guard globe.exists else { - check(false, "no globe under the keyboard to switch with") - return - } - // Once from the page that is up, and — on the panel — once more from its - // keys page, the way a swipe leaves it: the panel must come back on its - // mic page, at its own height, with the mic drawn. - try switchAwayAndBack(globe: globe, from: "the mic page") - if micKey().exists, app.buttons["space"].exists, !keysUp { - flipToKeys() - if keysUp { try switchAwayAndBack(globe: globe, from: "the keys page") } - } - // And the other way a keyboard comes back: put away and brought up again - // in the same field, from the mic page and from the keys page. - try dismissAndReturn(from: "the mic page") - if micKey().exists, app.buttons["space"].exists, !keysUp { - flipToKeys() - if keysUp { try dismissAndReturn(from: "the keys page") } - } - } - - /// A swipe on the panel's gap, to its keys page. - private func flipToKeys() { - let gap = micKey().coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 1.15)) - gap.press(forDuration: 0.05, thenDragTo: gap.withOffset(CGVector(dx: -160, dy: 0))) - Thread.sleep(forTimeInterval: 1.2) - } - - private func dismissAndReturn(from page: String) throws { - let dismiss = app.buttons["probe-dismiss"] - guard dismiss.exists else { return } - let plus = app.buttons["Add a key term"] - dismiss.tap() - Thread.sleep(forTimeInterval: 1.5) - check(!plus.exists && !micKey().exists, "the keyboard goes away (from \(page))") - app.textFields.firstMatch.tap() - let back = plus.waitForExistence(timeout: 5) || micKey().waitForExistence(timeout: 2) - Thread.sleep(forTimeInterval: 1.5) - let mic = micKey() - let frame = mic.exists ? mic.frame : .zero - check(back && frame.width > 40 && frame.height > 20, "brought back from \(page) the mic key is there, full size (\(frame))") - if frame == .zero { print("FLOW-TREE (mic missing after the return):\n\(app.debugDescription)") } - if page == "the keys page" { check(!keysUp, "the panel is back on its mic page after being put away") } - shot("returned-\(page == "the mic page" ? "mic" : "keys")") - } - - private func switchAwayAndBack(globe: XCUIElement, from page: String) throws { - // XCUITest has no Keyboard element for a custom keyboard: the + at the - // panel's top corner stands in for where the keyboard begins. - let plus = app.buttons["Add a key term"] - let topBefore = plus.exists ? plus.frame.minY : 0 - globe.tap() - Thread.sleep(forTimeInterval: 2) - check(!plus.exists, "the globe switches away from Blurt (from \(page))") - shot("switched-away") - var hops = 0 - while !plus.waitForExistence(timeout: 2), hops < 4 { - app.buttons["Next keyboard"].firstMatch.tap() - hops += 1 - } - Thread.sleep(forTimeInterval: 1.5) - let mic = micKey() - let top = plus.exists ? plus.frame.minY : 0 - // One snapshot: an element that flickers would throw between two. - let frame = mic.exists ? mic.frame : .zero - check( - frame.width > 40 && frame.height > 20, - "back on Blurt from \(page) the mic key is there, full size (\(frame); top \(topBefore) → \(top))") - if frame == .zero { print("FLOW-TREE (mic missing after the switch):\n\(app.debugDescription)") } - if page == "the keys page" { - check(!keysUp, "the panel is back on its mic page after the switch") - // The keys page was up before, so the keyboard was 54 pt taller then. - check(abs(top - topBefore - 54) < 4, "the panel is back at its own height (top \(topBefore) → \(top))") - } - shot("switched-back") - } - // MARK: Flows private func panelFlows() throws { @@ -279,7 +200,7 @@ extension BlurtKeyboardFlows { } /// Whether the letter keys are on screen (either shift state). - private var keysUp: Bool { letterKey("Q").exists || letterKey("q").exists } + var keysUp: Bool { letterKey("Q").exists || letterKey("q").exists } /// The least the panel's mic key is wide when the panel is up: its whole /// 300 pt slot in the middle, the element's own width at an edge. From eb5ed06e90192139d182534ef9d2e1c5dd72fc50 Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Thu, 1 Oct 2026 13:37:45 -0400 Subject: [PATCH 70/79] Keyboard: one placement rule, a path-drawn grille, a gate that settles by command MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The review and transition passes of 2026-09-30, verified on the real extension. Layout: the mic and the + are placed by one tested rule in every layout (VoiceRowLayout): the mic dead centre or at the chosen edge, the + hanging off it on its centre line, a chip growing to the row's edge, the pair centred when the row is too narrow (the slim bar, where the chip used to draw over the grille). The panel's + leaves its corner; the cancel × mirrors it (× · mic · +). One GlyphKey (44 pt) for + / × / ✓. Panel and slim-bar keys at the full keyboard's KeyGeometry widths; the panel's mic centred between the keyboard's top and the keys; the symbols' #+= page; the top-row pop-up inside the keyboard; a tap is "ended on the key ± 8 pt". Drawing: the grille is plain SwiftUI paths, never a Canvas — a Canvas's render surface failed to present in the extension three separate ways (asynchronous; a model mutation inside Messages' layout pass; background and resume), the key there and the dots not. The trait-change registration is gone; the face is re-read in viewIsAppearing. Behaviour: after a one-tap add the chip shows ✓ for 1.2 s then gives way to the + (only that word's chip); a tap on a known-word ✓ dismisses it; opening the term field closes a live dictation (release from the +, cancel over a highlight or an unanswered press); collapsing the highlight the field opened over no longer deletes the word; host typing is claimed one character at a time; save replaces only while the highlight stands; a release during connecting is held for the first recording phase; a touch cancelled inside the mic delay presses nothing; the × only while the app is there; an in-flight phase with the app gone reads idle; notices never replay; lost Full Access resets the phase and gate; pressed states are gesture state. Protocol: every phase the app publishes names the command it last took (PhaseSnapshot.command) and the keyboard settles its gate only for the press it answers — the previous dictation's "pasted" landing after a new press used to turn the next tap into a second press. Every command names its keyboard (KeyboardCommand.keyboard) and a result goes back to the keyboard that pressed, else the clipboard. The press retry re-reads the phase, then re-puts the command. Tests: 110 iOS tests (was 88): VoiceRowLayout, the gate's answers, KeyboardModelFuzzTests (five seeds × 2000 random events with invariants after each, 200 disappear/appear recovery rounds). Probes check the mic's pixels (MicPixels), not only its frame; the Messages carousel probe checks frames and pixels after every return; the flows restore the App Group side they set. Co-Authored-By: Claude Fable 5.1 --- .../BlurtKeyboard/Sources/AddTermKey.swift | 84 ++--- .../Sources/FullKeyboardView.swift | 43 ++- .../BlurtKeyboard/Sources/KeyCap.swift | 47 ++- .../BlurtKeyboard/Sources/KeyGeometry.swift | 3 + .../Sources/KeyboardInteraction.swift | 13 + .../Sources/KeyboardModel+Field.swift | 37 +++ .../Sources/KeyboardModel+Mic.swift | 37 ++- .../Sources/KeyboardModel+Phase.swift | 59 +++- .../Sources/KeyboardModel+Typing.swift | 120 ++++++- .../BlurtKeyboard/Sources/KeyboardModel.swift | 114 ++++--- .../Sources/KeyboardViewController.swift | 12 + .../BlurtKeyboard/Sources/MicControl.swift | 29 +- .../BlurtKeyboard/Sources/PanelView.swift | 74 ++--- .../BlurtKeyboard/Sources/SlimBarView.swift | 25 +- .../BlurtKeyboard/Sources/TermField.swift | 23 +- .../BlurtKeyboard/Sources/VoiceBar.swift | 101 ++---- .../BlurtKeyboard/Sources/VoiceGrille.swift | 128 +++++--- .../BlurtKeyboard/Sources/VoiceRow.swift | 209 ++++++++++++ .../BlurtKeyboard/Sources/VoiceState.swift | 4 +- .../Sources/DictationCoordinator.swift | 9 +- .../BlurtiOS/Sources/KeyboardProbeView.swift | 13 +- .../Sources/KeyboardRelayInjector.swift | 14 +- .../BlurtKeyboardFlows+Reappearance.swift | 23 +- .../BlurtiOSProbe/BlurtKeyboardFlows.swift | 138 +++++--- .../BlurtiOSProbe/MessagesCarouselProbe.swift | 22 +- App/BlurtiOS/BlurtiOSProbe/MicPixels.swift | 64 ++++ .../KeyboardInteractionTests.swift | 19 ++ .../KeyboardModelFuzzTests.swift | 303 ++++++++++++++++++ .../KeyboardModelGateTests.swift | 135 ++++++++ .../BlurtiOSTests/KeyboardModelTests.swift | 141 +++++++- .../BlurtiOSTests/ProtocolTests.swift | 36 ++- .../BlurtiOSTests/VoiceRowLayoutTests.swift | 132 ++++++++ App/BlurtiOS/DESIGN.md | 200 +++++++----- App/BlurtiOS/Design/figma/tokens.js | 16 +- App/BlurtiOS/Design/tokens.json | 39 +-- App/BlurtiOS/Shared/DesignTokens.swift | 40 +-- App/BlurtiOS/Shared/KeyTermList.swift | 21 ++ App/BlurtiOS/Shared/SharedState.swift | 39 +-- scripts/ios-keyboard-flows.sh | 15 + 39 files changed, 1989 insertions(+), 592 deletions(-) create mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Field.swift create mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/VoiceRow.swift create mode 100644 App/BlurtiOS/BlurtiOSProbe/MicPixels.swift create mode 100644 App/BlurtiOS/BlurtiOSTests/KeyboardModelFuzzTests.swift create mode 100644 App/BlurtiOS/BlurtiOSTests/KeyboardModelGateTests.swift create mode 100644 App/BlurtiOS/BlurtiOSTests/VoiceRowLayoutTests.swift create mode 100644 App/BlurtiOS/Shared/KeyTermList.swift diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/AddTermKey.swift b/App/BlurtiOS/BlurtKeyboard/Sources/AddTermKey.swift index 8467847a..12881bc7 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/AddTermKey.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/AddTermKey.swift @@ -1,22 +1,22 @@ import SwiftUI -/// The small + beside the element (and in the panel's corner): a new key -/// term. A bare glyph, quiet until it is needed; a check for a moment after -/// one was saved. +/// The small + beside the mic: a new key term. A bare glyph, quiet until it +/// is needed; a check for a moment after one was saved. /// /// Highlight a word in the text and the + is a chip instead — the field's /// shape, holding the word — and one tap adds the word as it stands: + for a -/// word Blurt doesn't know yet, ✓ once it does. Holding the chip opens the -/// field pre-filled instead, to fix the spelling first (`KeyboardModel`: -/// `selectedTerm`, `addSelectedTerm`, `beginAddingTerm`). +/// word Blurt doesn't know yet, ✓ once it does. After the check the + comes +/// back, highlight or not; a tap on a ✓ chip puts it back at once. Holding +/// the chip opens the field pre-filled instead, to fix the spelling first +/// (`KeyboardModel`: `selectedTerm`, `addSelectedTerm`, `beginAddingTerm`). +/// The row it hangs in (`VoiceRow`) decides how wide the chip may grow. struct AddTermKey: View { var model: KeyboardModel - /// The most the chip may take, where nothing else bounds it (the panel's - /// corner); nil where the row's own room does (the bar). - var maxWidth: CGFloat? @Environment(\.keyboardPalette) private var palette - @State private var pressed = false - @State private var hold: Task? + /// Lit while a finger is on the chip. A gesture state, so a touch the + /// system takes away (a call, the keyboard dismissed mid-press) unlights it + /// too; a plain state would stay lit. + @GestureState private var pressed = false @State private var held = false var body: some View { @@ -36,15 +36,9 @@ struct AddTermKey: View { /// The bare +: a new term typed from nothing (or from the selection, seeded). private var plain: some View { - Button { + GlyphKey(symbol: saved ? "checkmark" : "plus", tint: saved ? palette.signal : mutedTint, label: "Add a key term") { model.beginAddingTerm() - } label: { - glyph(saved ? "checkmark" : "plus", tint: saved ? palette.signal : mutedTint) - .frame(width: DesignTokens.Metrics.glyphHit, height: DesignTokens.Metrics.glyphHit) - .contentShape(Circle()) } - .buttonStyle(KeyPressStyle()) - .accessibilityLabel("Add a key term") } /// The chip: the highlighted word, ready to add with one tap. @@ -72,44 +66,30 @@ struct AddTermKey: View { .contentShape(Rectangle()) .accessibilityElement(children: .ignore) .accessibilityLabel(known ? "“\(term)” is a key term" : "Add “\(term)” as a key term") - .accessibilityHint(known ? "" : "Hold to edit it first") + .accessibilityHint(known ? "Tap to put the + back" : "Hold to edit it first") .accessibilityAddTraits(.isButton) .accessibilityIdentifier("blurt-add-selected") - .simultaneousGesture(tapOrHold) - // The chip hugs the word — a shorter word, a shorter chip — and only - // shrinks, truncating the word, when the room it is offered is less: - // the bar's remainder beside the element, or this cap in the panel. The - // cap is an outer, invisible frame, so the chip never stretches to it. - .frame(maxWidth: maxWidth, alignment: .leading) - } - - /// A tap adds; a hold opens the field with the word in it; a touch that - /// travelled (the panel's carousel) does neither. - private var tapOrHold: some Gesture { - DragGesture(minimumDistance: 0) - .onChanged { value in - if !pressed { - pressed = true - held = false - hold = Task { [model] in - try? await Task.sleep(for: .seconds(DesignTokens.Motion.chipHold)) - guard !Task.isCancelled else { return } - held = true - model.beginAddingTerm() - } + // A hold opens the field with the word in it. The system's long press: + // it fails on its own when the finger travels or the touch is taken + // away, so no timer of ours can open the field after the finger is gone. + .simultaneousGesture( + LongPressGesture(minimumDuration: DesignTokens.Motion.chipHold, maximumDistance: KeyboardInteraction.tapTravel) + .onEnded { _ in + held = true + model.beginAddingTerm() } - if !KeyboardInteraction.isTap(value.translation) { - hold?.cancel() - hold = nil + ) + // A tap adds; a touch that travelled (the panel's carousel), or one the + // hold already answered, does nothing. + .simultaneousGesture( + DragGesture(minimumDistance: 0) + .updating($pressed) { _, state, _ in state = true } + .onEnded { value in + defer { held = false } + guard !held, KeyboardInteraction.isTap(value.translation) else { return } + model.addSelectedTerm() } - } - .onEnded { value in - pressed = false - hold?.cancel() - hold = nil - guard !held, KeyboardInteraction.isTap(value.translation) else { return } - model.addSelectedTerm() - } + ) } private var mutedTint: Color { palette.keyText.opacity(DesignTokens.Metrics.opacityLegendMuted) } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift b/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift index ccee0175..8e37c87a 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift @@ -5,13 +5,15 @@ import SwiftUI /// letters, then 123 · globe · space · return, at the system keyboard's /// measured spacing (`KeyGeometry`) — with the voice bar where the suggestion /// bar would be. Letters pop up while pressed, sentences capitalise -/// themselves, a double space ends one. +/// themselves, a double space ends one. 123 opens the numbers and symbols, +/// #+= the rest of them, as the system keyboard's pages go. /// No autocorrect or suggestions yet. iOS swaps in its own keyboard for /// password fields, so those never reach here. struct FullKeyboardView: View { var model: KeyboardModel private static let symbols = ["1234567890", "-/:;()$&@\"", ".,?!'"] + private static let more = ["[]{}#%^*+=", "_\\|~<>€£¥•", ".,?!'"] var body: some View { GeometryReader { geo in @@ -24,16 +26,21 @@ struct FullKeyboardView: View { VoiceBar(model: model) VStack(spacing: KeyboardPalette.rowGap) { ForEach(Array(rows.enumerated()), id: \.offset) { index, row in - HStack(spacing: index == 2 ? geometry.sideGap : gap) { // literal-ok: the third row - if index == 2 { modifierKey(width: geometry.sideWidth) } // literal-ok: the third row + let third = index == 2 // literal-ok: the third row + // The third row's keys fill what shift and delete leave: seven + // letters at the letter width, or the five punctuation keys, wider, + // as the system keyboard has them on its symbol pages. + let keyWidth = third && model.symbolsPage ? geometry.punctuationWidth : geometry.letterWidth + HStack(spacing: third ? geometry.sideGap : gap) { + if third { modifierKey(width: geometry.sideWidth) } HStack(spacing: gap) { ForEach(Array(row), id: \.self) { character in - LetterKey(label: label(for: character), width: geometry.letterWidth) { + LetterKey(label: label(for: character), width: keyWidth) { model.type(label(for: character)) } } } - if index == 2 { + if third { KeyCap(systemImage: "delete.left", dark: true, width: geometry.sideWidth) { model.deleteBackward() } } } @@ -55,30 +62,37 @@ struct FullKeyboardView: View { } } - private var rows: [String] { model.symbolsPage ? Self.symbols : model.letterRows } + private var rows: [String] { + guard model.symbolsPage else { return model.letterRows } + return model.morePage ? Self.more : Self.symbols + } private func label(for character: Character) -> String { let text = String(character) return model.shifted && !model.symbolsPage ? text.uppercased() : text } + /// Shift on the letters; on the symbol pages the key that swaps between + /// the two of them, labelled with where it goes, as the iPhone's is. @ViewBuilder private func modifierKey(width: CGFloat) -> some View { if model.symbolsPage { - KeyCap(title: "#+=", dark: true, width: width) { model.toggleSymbols() } + KeyCap(title: model.morePage ? "123" : "#+=", dark: true, width: width) { model.toggleMore() } } else { KeyCap(systemImage: model.shifted ? "shift.fill" : "shift", dark: true, width: width) { model.toggleShift() } } } } -/// A letter key with the system keyboard's 22 pt legend and its pop-up: a +/// A letter key with the system keyboard's 24 pt legend and its pop-up: a /// larger copy of the letter above the key while the finger is down, so the /// finger doesn't hide what it's pressing. Typed on release, as iOS does. private struct LetterKey: View { let label: String let width: CGFloat let action: () -> Void - @State private var pressed = false + /// A gesture state, so a touch the system takes away unlights the key and + /// drops its pop-up; a plain state would leave both up. + @GestureState private var pressed = false @Environment(\.keyboardPalette) private var palette @Environment(\.keyboardInContainer) private var inContainer @@ -97,11 +111,14 @@ private struct LetterKey: View { .accessibilityAddTraits(.isButton) .simultaneousGesture( DragGesture(minimumDistance: 0) - .onChanged { _ in pressed = true } + .updating($pressed) { _, state, _ in state = true } .onEnded { value in - pressed = false - // A touch that travelled was a swipe (the panel's carousel), not a tap. - guard KeyboardInteraction.isTap(value.translation) else { return } + // A touch that swiped away (the panel's carousel) was not a tap; + // one that ended on the key was, wherever the thumb rolled. + guard + KeyboardInteraction.isTap( + value.translation, endedAt: value.location, in: CGSize(width: width, height: KeyCap.height)) + else { return } action() } ) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyCap.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyCap.swift index e0aaabb5..d6802f7c 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyCap.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyCap.swift @@ -3,9 +3,11 @@ import SwiftUI /// One ordinary key: a glyph (SF Symbols, as the system keyboard's) or a /// word (the brand's mono eyebrow) on a cap in the current face; `dark` for /// the modifier keys, a step darker as on the system keyboard; `bare` for a -/// glyph with no cap at all (the panel's cancel). `flexible` keys (the space -/// bar) take the width they're given, `width` fixes one, and the rest are -/// the iPhone's 123 key wide. +/// glyph with no cap at all. `flexible` keys (the space bar) take the width +/// they're given, `width` fixes one — the layouts pass `KeyGeometry`'s, so +/// a key is the same size on every page — and a key with neither is at least +/// the iPhone's 123 key wide, its legend padded inside that. `height` fixes +/// the cap's height where a row is not the standard 43 (the slim bar). struct KeyCap: View { var title: String? var systemImage: String? @@ -14,6 +16,7 @@ struct KeyCap: View { var dark = false var bare = false var width: CGFloat? + var height: CGFloat? var action: () -> Void @Environment(\.keyboardPalette) private var palette @Environment(\.keyboardInContainer) private var inContainer @@ -22,7 +25,8 @@ struct KeyCap: View { init( title: String? = nil, systemImage: String? = nil, tint: Color? = nil, flexible: Bool = false, - dark: Bool = false, bare: Bool = false, width: CGFloat? = nil, action: @escaping () -> Void + dark: Bool = false, bare: Bool = false, width: CGFloat? = nil, height: CGFloat? = nil, + action: @escaping () -> Void ) { self.title = title self.systemImage = systemImage @@ -31,6 +35,7 @@ struct KeyCap: View { self.dark = dark self.bare = bare self.width = width + self.height = height self.action = action } @@ -43,18 +48,22 @@ struct KeyCap: View { } else { // A word on a key — 123, ABC, #+=, space, the return label — is the // brand's eyebrow: Modern Gothic Mono, uppercase, tracked, a step - // quieter than a letter. + // quieter than a letter. Tracking adds its space after the last + // letter too; the same again before the first keeps the word centred. Text((title ?? "").uppercased()) .font(BlurtType.mono(DesignTokens.Typography.sizeLabel, weight: .medium)) .tracking(DesignTokens.Typography.trackingEyebrow) + .padding(.leading, DesignTokens.Typography.trackingEyebrow) .foregroundStyle(tint ?? palette.keyTextSecondary) } } .opacity(DesignTokens.Metrics.opacityLegend) - .frame(maxWidth: flexible ? .infinity : nil) - .frame(width: width) - .frame(minWidth: width == nil ? DesignTokens.Metrics.keyMinWidth : nil, minHeight: Self.height) + // The padding sits inside the minimum width, so a glyph key is exactly + // the minimum and only a long word widens a key past it. .padding(.horizontal, flexible || width != nil ? 0 : DesignTokens.Metrics.keyPad) + .frame(maxWidth: flexible ? .infinity : nil) + .frame(width: width, height: height) + .frame(minWidth: width == nil ? DesignTokens.Metrics.keyMinWidth : nil, minHeight: height ?? Self.height) .keyCap(bare ? .clear : palette.keyFill(modifier: dark, inContainer: inContainer)) .keyPress(action) .accessibilityLabel(title ?? systemImage ?? "") @@ -69,9 +78,9 @@ extension View { } /// A key's touch: lights while the finger is down, acts on release — and - /// only if the finger didn't travel, so a swipe across a key (the panel's - /// carousel) never types. The system keyboard's own rule - /// (`KeyboardInteraction.isTap`). + /// only if the finger ended on the key, so a swipe across a key (the + /// panel's carousel) never types while a thumb that rolls still does. The + /// system keyboard's own rule (`KeyboardInteraction.isTap`). func keyPress(_ action: @escaping () -> Void) -> some View { modifier(KeyPress(action: action)) } @@ -79,20 +88,28 @@ extension View { struct KeyPress: ViewModifier { let action: () -> Void - @State private var pressed = false + /// A gesture state: a touch the system takes away (a swipe from the screen's + /// bottom edge, a call, the keyboard dismissed) unlights the key too, where + /// a plain state would leave it lit. + @GestureState private var pressed = false + @State private var size = CGSize.zero func body(content: Content) -> some View { content .brightness(pressed ? DesignTokens.Metrics.opacityPressBrighten : 0) .animation(.easeOut(duration: DesignTokens.Motion.keyPress), value: pressed) .contentShape(Rectangle()) + .onGeometryChange(for: CGSize.self) { + $0.size + } action: { + size = $0 + } .accessibilityAddTraits(.isButton) .simultaneousGesture( DragGesture(minimumDistance: 0) - .onChanged { _ in pressed = true } + .updating($pressed) { _, state, _ in state = true } .onEnded { value in - pressed = false - guard KeyboardInteraction.isTap(value.translation) else { return } + guard KeyboardInteraction.isTap(value.translation, endedAt: value.location, in: size) else { return } action() } ) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyGeometry.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyGeometry.swift index 547f9e0f..10bce306 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyGeometry.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyGeometry.swift @@ -25,6 +25,9 @@ nonisolated struct KeyGeometry: Equatable { /// stand from each other. var sideGap: CGFloat { Metrics.keySideGap } var sideWidth: CGFloat { (rowWidth - 7 * letterWidth - 6 * gap - 2 * sideGap) / 2 } + /// On the symbol pages the third row holds five punctuation keys between + /// shift's and delete's places, filling the same span seven letters do. + var punctuationWidth: CGFloat { (rowWidth - 2 * sideWidth - 2 * sideGap - 4 * gap) / 5 } /// The widths measured at the reference width scale with the keyboard. private var scale: CGFloat { (rowWidth + 2 * Metrics.marginSide) / Metrics.keyReferenceWidth } /// 123 (or ABC), and the globe when there is one. diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardInteraction.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardInteraction.swift index 5a7a332a..bf778bc8 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardInteraction.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardInteraction.swift @@ -37,6 +37,19 @@ nonisolated enum KeyboardInteraction { abs(translation.width) < tapTravel && abs(translation.height) < tapTravel } + /// How far past a key's edge a finger may end and still have tapped it. + static let tapSlop: CGFloat = 8 + + /// A key's tap: the finger barely moved, or it ended on the key (within + /// `tapSlop` of its edges) wherever it went in between — a thumb that rolls + /// still types, as on the system keyboard, while a swipe that left the key + /// (the panel's carousel) does not. `location` is in the key's own space. + static func isTap(_ translation: CGSize, endedAt location: CGPoint, in size: CGSize) -> Bool { + if isTap(translation) { return true } + guard size.width > 0, size.height > 0 else { return false } + return CGRect(origin: .zero, size: size).insetBy(dx: -tapSlop, dy: -tapSlop).contains(location) + } + static func micTravelled(_ translation: CGSize) -> Bool { abs(translation.width) > micTravel || abs(translation.height) > micTravel } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Field.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Field.swift new file mode 100644 index 00000000..6e154ebe --- /dev/null +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Field.swift @@ -0,0 +1,37 @@ +import Foundation +import UIKit + +// MARK: - What the host field says: the return key, the symbols page, the face + +extension KeyboardModel { + /// What the field asked for, the way the system keyboard honours it: the + /// return key's own word, and the symbols page first for a number field. + func readField() { + returnLabel = proxy?.returnKeyType.flatMap(Self.returnLabel) + } + + func readAppearance() { + switch proxy?.keyboardAppearance { + case .dark: isDark = true + case .light: isDark = false + default: isDark = controller?.traitCollection.userInterfaceStyle == .dark + } + } + + /// Number, decimal and phone fields open on the symbols page, as the system + /// keyboard would show a number pad. + static func wantsSymbols(_ type: UIKeyboardType?) -> Bool { + switch type { + case .numberPad, .decimalPad, .phonePad, .numbersAndPunctuation, .asciiCapableNumberPad: true + default: false + } + } + + /// iOS's own words for the return key, by the type the field asked for. + static let returnLabels: [UIReturnKeyType: String] = [ + .go: "go", .google: "search", .yahoo: "search", .search: "search", .join: "join", .next: "next", + .route: "route", .send: "send", .done: "done", .emergencyCall: "call", .continue: "continue", + ] + + static func returnLabel(_ type: UIReturnKeyType) -> String? { returnLabels[type] } +} diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Mic.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Mic.swift index 2603945c..962b88e0 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Mic.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Mic.swift @@ -28,12 +28,11 @@ extension KeyboardModel { /// Finger up. When Blurt isn't ready — no Full Access, or the app isn't /// listening — this is the tap that opens the app, whose checklist says what /// is missing (opening the app needs no Full Access; everything else does). + /// The gate comes up either way, so a press the finger made while the app + /// was still there is never left armed. func micUp() { - guard isReady else { - openApp() - return - } perform(gate.modifierUp(at: elapsed)) + if !isReady { openApp() } } func cancel() { @@ -46,8 +45,17 @@ extension KeyboardModel { func perform(_ action: DictationKeyGate.Action) { switch action { case .start: send(.press) - case .stop: send(.release) - case .cancel: send(.cancel) + case .stop: + // The engine drops a release before it is recording (the mic still + // coming up): hold it for the first recording phase instead. + if snapshot.state == .connecting { + releasePending = true + } else { + send(.release) + } + case .cancel: + releasePending = false + send(.cancel) case .none: break } } @@ -55,17 +63,24 @@ extension KeyboardModel { func send(_ kind: KeyboardCommand.Kind) { let command = KeyboardCommand( id: UUID(), kind: kind, priorText: proxy?.documentContextBeforeInput, - selectedText: proxy?.selectedText, sentAt: Date()) + selectedText: proxy?.selectedText, sentAt: Date(), keyboard: instanceID) transport(command) - // A press the app never answers (the notification was missed) would - // leave the gate latched over nothing; one re-signal covers it. + unansweredPress = kind == .press ? command.id : nil + // A press the app never answers would leave the gate latched over + // nothing. Either notification can be missed: first catch up with a phase + // the app may have published unheard; if the picture is still as it was, + // the press itself was missed — put it back (the app takes a command out + // of the store as it reads it) and signal again. The same id, so an app + // that did read it ignores the copy. commandRetry?.cancel() guard kind == .press else { return } let stateAtSend = snapshot.state commandRetry = Task { [weak self] in try? await Task.sleep(for: Self.commandRetryDelay) - guard !Task.isCancelled, let self, snapshot.state == stateAtSend else { return } - SharedStore.post(BlurtShared.Signal.command) + guard !Task.isCancelled, let self else { return } + phaseChanged() + guard snapshot.state == stateAtSend else { return } + transport(command) } } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Phase.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Phase.swift index 9145cb74..e0a2513f 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Phase.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Phase.swift @@ -11,35 +11,65 @@ extension KeyboardModel { } func apply(_ current: PhaseSnapshot, haptics wantsHaptics: Bool = true) { + // A notice the keyboard already let go of (its dwell ran out) is not + // replayed by a second read of the same snapshot. + if let dismissedNoticeAt, current.at == dismissedNoticeAt { return } let previous = snapshot.state - snapshot = current + // A dictation in flight belongs to an app that is there to run it: with + // the app gone (killed, the mic taken), the picture is idle, not a mic + // nobody can stop. + var current = current isListening = SharedStore.isListening + if !isListening, current.noticeDwellSeconds == nil, current.state != .idle { current = .idle } + snapshot = current if wantsHaptics, current.state != previous { haptics(from: previous, to: current.state) } + // A release the finger made while the mic was still coming up goes out + // now that it is recording; anything else in the meantime clears it. + if releasePending { + releasePending = false + if current.state == .recording { + send(.release) + gate.reset() + return + } + } + syncGate(with: current) + // A notice is over after its dwell: the Mac pill fades out, this orb goes + // back to its resting circle. Only the picture settles — a gate latched by + // a tap the app hasn't answered yet is left alone. + noticeDwell?.cancel() + dismissedNoticeAt = nil + if let seconds = current.noticeDwellSeconds { + let at = current.at + noticeDwell = Task { [weak self] in + try? await Task.sleep(for: .seconds(seconds)) + guard !Task.isCancelled, let self else { return } + dismissedNoticeAt = at + snapshot = .idle + } + } + } + + /// The gate follows the app, both ways — see the comments inside. + private func syncGate(with current: PhaseSnapshot) { // The gate follows the app, both ways. A dictation that ended without a // finger event (auto-release, an error) would leave it latched and swallow // the next tap — the same sync the Mac shell does on every terminal phase. + // But only a phase that answers our press may settle it: the previous + // dictation's notice can land a moment after a new press, and resetting + // then would make the next tap a second press instead of the stop. // And a dictation in flight that this keyboard didn't start (hands-free // in another app, or a previous keyboard process) must latch it, so the // next tap is the stop rather than a press the engine drops. + if !isSettled || current.command == unansweredPress { unansweredPress = nil } if isSettled, !gate.isIdle { - gate.reset() + if unansweredPress == nil { gate.reset() } } else if !isSettled, gate.isIdle, current.state != .processing { // Only a recording (or one coming up) can be stopped by a tap; while // the words are being transcribed there is nothing for the gate to hold. _ = gate.modifierDown(at: elapsed) _ = gate.modifierUp(at: elapsed) } - // A notice is over after its dwell: the Mac pill fades out, this orb goes - // back to its resting circle. Only the picture settles — a gate latched by - // a tap the app hasn't answered yet is left alone. - noticeDwell?.cancel() - if let seconds = current.noticeDwellSeconds { - noticeDwell = Task { [weak self] in - try? await Task.sleep(for: .seconds(seconds)) - guard !Task.isCancelled else { return } - self?.snapshot = .idle - } - } } func resultArrived() { @@ -59,6 +89,9 @@ extension KeyboardModel { resultLandedAt = Date() // Not typing, so not the term field's to claim. if termDraft != nil { termHostBaseline = proxy.documentContextBeforeInput ?? "" } + // The words replaced whatever was highlighted: the chip for that word + // goes now, not on the host's next notification. + readSelection() } func haptics(from previous: PhaseSnapshot.State, to state: PhaseSnapshot.State) { diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Typing.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Typing.swift index a0231346..71477678 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Typing.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Typing.swift @@ -14,6 +14,14 @@ extension KeyboardModel { } proxy?.insertText(text) if shifted, !symbolsPage { shifted = false } + typedIntoHost() + } + + /// The keyboard's own edit to the host's text replaces whatever was + /// highlighted: the picture follows at once, not on the host's next + /// notification. + private func typedIntoHost() { + readSelection() } func deleteBackward() { @@ -24,6 +32,7 @@ extension KeyboardModel { return } proxy?.deleteBackward() + typedIntoHost() } func newline() { @@ -33,6 +42,7 @@ extension KeyboardModel { return } proxy?.insertText("\n") + typedIntoHost() } // MARK: Quick-add key term @@ -50,21 +60,74 @@ extension KeyboardModel { return trimmed } + /// What is highlighted in the host's text, as a key-term candidate, and + /// whether Blurt has it already. The list lives in the App Group, so only + /// with Full Access — without it there is nothing the chip could do. A word + /// the chip is done with (`dismissedSelection`) shows no chip while the + /// same highlight stands. + func readSelection() { + guard hasFullAccess, let term = Self.termCandidate(from: proxy?.selectedText) else { + selectedTerm = nil + selectedTermIsKnown = false + dismissedSelection = nil + return + } + if let dismissed = dismissedSelection { + guard dismissed.caseInsensitiveCompare(term) != .orderedSame else { + selectedTerm = nil + selectedTermIsKnown = false + return + } + dismissedSelection = nil + } + selectedTerm = term + selectedTermIsKnown = SharedStore.keyTerms.contains { $0.caseInsensitiveCompare(term) == .orderedSame } + } + /// The chip: the highlighted word goes into Blurt's key terms as it stands - /// — one tap, no typing, the text untouched. Nothing to do for a word Blurt - /// already has. + /// — one tap, no typing, the text untouched. The chip shows its check for + /// the notice's moment and then gives way to the + (`dismissSelection`), + /// highlight or not: the host may keep the word highlighted for as long as + /// the user leaves it, and a chip that stayed with it read as stuck. A tap + /// on a chip for a word Blurt already has puts the + back at once. func addSelectedTerm() { - guard let term = selectedTerm, !selectedTermIsKnown else { return } + guard let term = selectedTerm else { return } + guard !selectedTermIsKnown else { + dismissSelection() + return + } SharedStore.addKeyTerm(term) selectedTermIsKnown = true - noteTermSaved() + noteTermSaved(thenDismissChip: true) + } + + /// The chip is done with the highlighted word: the + comes back and stays + /// back while that highlight stands (`KeyboardModel.dismissedSelection`). + func dismissSelection() { + dismissedSelection = selectedTerm + selectedTerm = nil + selectedTermIsKnown = false } /// The voice bar becomes a field and the keys type into it. If the user /// had selected a word — the one Blurt got wrong — it is the starting /// point, and saving also replaces it in the text with what they typed. + /// The field takes the mic key's row, so a dictation in flight is closed + /// first — nothing runs on with no key to stop it. From the plain + a + /// recording is released and the words still land; from a highlighted + /// word it is cancelled: the words would land *over* the word being fixed + /// (a result replaces the selection), and the user's intent is the word. func beginAddingTerm() { let seed = Self.termCandidate(from: proxy?.selectedText) ?? "" + switch snapshot.state { + case .recording: perform(seed.isEmpty ? .stop : .cancel) + case .connecting: perform(.cancel) + case .idle, .processing, .pasted, .copied, .error: + // A press the app hasn't answered yet would start a dictation under + // the field: it is taken back. + if unansweredPress != nil || !gate.isIdle { perform(.cancel) } + } + gate.reset() termDraftFromSelection = seed.isEmpty ? nil : seed termHostBaseline = proxy?.documentContextBeforeInput ?? "" termHostBaselineAfter = proxy?.documentContextAfterInput ?? "" @@ -96,43 +159,63 @@ extension KeyboardModel { // Out of the mode before touching the text, so the field's own change // notification can't read the replacement as typing to claim. let original = termDraftFromSelection + let baseline = termHostBaseline termDraft = nil termDraftFromSelection = nil termHostBaseline = nil termHostBaselineAfter = nil + // Only while the highlight the field opened over still stands where it + // was: the host may report a selection a moment after the user moved on, + // and inserting then would put the word in twice. if let original, original != draft, let selected = proxy?.selectedText, - selected.trimmingCharacters(in: .whitespacesAndNewlines) == original + selected.trimmingCharacters(in: .whitespacesAndNewlines) == original, + (proxy?.documentContextBeforeInput ?? "") == (baseline ?? "") { // The selection may have carried the spaces around the word; keep them. let lead = selected.prefix { $0.isWhitespace } let trail = selected.reversed().prefix { $0.isWhitespace }.reversed() proxy?.insertText(String(lead) + draft + String(trail)) } - // Saved as selected, the word is still highlighted: the chip knows it now. + // The word is saved; whatever is still highlighted, the + is back with + // its check, not a chip for the word just dealt with. readSelection() - noteTermSaved() + dismissSelection() + noteTermSaved(thenDismissChip: false) updateShift() onLayoutChange?() } - /// A success haptic, and the + (or the chip) shows a check for a moment. - private func noteTermSaved() { + /// A success haptic, and the + (or the chip) shows a check for a moment; + /// after it, the chip gives way to the + when asked — only if it is still + /// the chip for the word that was saved: a word highlighted meanwhile + /// keeps its own chip. + private func noteTermSaved(thenDismissChip: Bool) { if hasFullAccess { UINotificationFeedbackGenerator().notificationOccurred(.success) } termSavedAt = Date() termNotice?.cancel() + let saved = selectedTerm termNotice = Task { [weak self] in - try? await Task.sleep(for: .seconds(1.2)) - guard !Task.isCancelled else { return } - self?.termSavedAt = nil + try? await Task.sleep(for: .seconds(Self.termNoticeDwell)) + guard !Task.isCancelled, let self else { return } + termSavedAt = nil + if thenDismissChip, let saved, let current = selectedTerm, + current.caseInsensitiveCompare(saved) == .orderedSame + { + dismissSelection() + } } } + /// How long the + (or the chip) shows its check after a term was saved. + static let termNoticeDwell: TimeInterval = 1.2 + /// A space — or, tapped twice quickly after a word, the system keyboard's /// "." shortcut: the first space becomes a full stop and a space. func space() { UIDevice.current.playInputClick() if termDraft != nil { if termDraft?.isEmpty == false, termDraft?.hasSuffix(" ") == false { termDraft?.append(" ") } + updateShift() return } let now = ContinuousClock.now @@ -147,12 +230,23 @@ extension KeyboardModel { proxy?.insertText(" ") lastSpaceAt = now } + typedIntoHost() updateShift() } func toggleShift() { shifted.toggle() } - func toggleSymbols() { symbolsPage.toggle() } + /// 123 / ABC: the symbols come up on their first page, or the letters return. + func toggleSymbols() { + symbolsPage.toggle() + morePage = false + } + + /// #+= / 123: between the two symbol pages; nothing on the letters. + func toggleMore() { + guard symbolsPage else { return } + morePage.toggle() + } func globe() { controller?.advanceToNextInputMode() } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift index e5f600bb..7596ffbb 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift @@ -57,6 +57,8 @@ final class KeyboardModel { var needsGlobe = true var shifted = true var symbolsPage = false + /// The symbols' second page (#+=), only while `symbolsPage`. + var morePage = false // Internal, not private: the model's typing, mic and phase halves live in // KeyboardModel+Typing/+Mic/+Phase.swift. @@ -80,6 +82,10 @@ final class KeyboardModel { static let commandRetryDelay: Duration = .milliseconds(600) @ObservationIgnored var commandRetry: Task? @ObservationIgnored var termDraftFromSelection: String? + /// A highlighted word the chip is done with — added, or its ✓ tapped — + /// while the host still shows it highlighted: the + is back, and stays + /// back until the highlight moves to another word or goes. + @ObservationIgnored var dismissedSelection: String? /// The text before and after the cursor when the term field opened, so /// typing that reaches the host field anyway (a hardware keyboard: an /// iPad's, a Bluetooth one, the simulator's Mac) can be pulled into the @@ -88,6 +94,16 @@ final class KeyboardModel { @ObservationIgnored var termHostBaseline: String? @ObservationIgnored var termHostBaselineAfter: String? @ObservationIgnored var termNotice: Task? + /// A release made while the mic was still coming up (the engine drops + /// one before it records): held, and sent on the first recording phase. + @ObservationIgnored var releasePending = false + /// The press the app has not answered yet. A settled phase that does not + /// answer it (the previous dictation's notice landing late) leaves the + /// gate alone; anything in flight, or a phase carrying its id, answers it. + @ObservationIgnored var unansweredPress: UUID? + /// The `at` of a notice the keyboard already let go of: a re-read of the + /// same snapshot cannot replay it. + @ObservationIgnored var dismissedNoticeAt: Date? /// The host's text field. Tests hand in a fake in place of a controller. var proxy: (any UITextDocumentProxy)? { proxyOverride ?? controller?.textDocumentProxy } @@ -156,7 +172,8 @@ final class KeyboardModel { } func appeared() { - hasFullAccess = controller?.hasFullAccess ?? false + // Without a controller (a test's model) the access stays as it was set. + hasFullAccess = controller?.hasFullAccess ?? hasFullAccess needsGlobe = controller?.needsInputModeSwitchKey ?? true letterRows = LetterLayout.forPreferredLanguages() // Every appearance starts on the mic page with no term half-typed, and on @@ -166,14 +183,29 @@ final class KeyboardModel { termDraftFromSelection = nil termHostBaseline = nil termHostBaselineAfter = nil + dismissedSelection = nil + termNotice?.cancel() + termSavedAt = nil + releasePending = false + // `unansweredPress` is not reset here: an appearance can follow another + // with no disappearance between (iOS does that), and a press still out + // must keep the gate latched so hands-free does not press again over it. symbolsPage = Self.wantsSymbols(proxy?.keyboardType) + morePage = false readAppearance() readField() readSelection() updateShift() // Without Full Access the App Group is out of reach: the keyboard still - // types, and says what it needs (see `VoiceBar`), but nothing below can run. - guard hasFullAccess else { return } + // types, and says what it needs (see `VoiceBar`), but nothing below can + // run — and nothing from a previous appearance (a phase, a latched gate) + // may linger over a keyboard that can't hear the app. + guard hasFullAccess else { + snapshot = .idle + gate.reset() + noticeDwell?.cancel() + return + } layout = SharedStore.layout themeID = SharedStore.themeID storedVoiceKind = SharedStore.voiceElementKind @@ -237,73 +269,38 @@ final class KeyboardModel { /// (a hardware keyboard types past the on-screen keys) belong to the term: /// move them over and take them back out of the field. Only a short, /// appended run right after where the cursor was; anything else is left. + /// Never when the field opened over a highlighted word: a tap that + /// collapses that highlight to its end grows the text before the cursor + /// by exactly the word, which is not typing, and taking it would delete + /// the user's word. private func claimHostTypingForTerm() { - guard termDraft != nil, let baseline = termHostBaseline, let proxy else { return } + guard termDraft != nil, termDraftFromSelection == nil, let baseline = termHostBaseline, let proxy else { + return + } let now = proxy.documentContextBeforeInput ?? "" let delta = now.count - baseline.count - // Typing lengthens the text before the cursor and leaves the text after - // it alone; a cursor move changes both; a selection is neither. - guard delta > 0, delta <= 8, proxy.selectedText == nil, + // Typing lengthens the text before the cursor by one character at a time + // and leaves the text after it alone; a cursor move changes both; a + // selection is neither; a block (a paste, the system's own dictation + // under the keyboard) is never typing and stays in the field. + guard delta == 1, proxy.selectedText == nil, (proxy.documentContextAfterInput ?? "") == (termHostBaselineAfter ?? ""), now.dropLast(delta).hasSuffix(baseline.suffix(24)) else { return } let typed = String(now.suffix(delta)) - for _ in 0.. Bool { - switch type { - case .numberPad, .decimalPad, .phonePad, .numbersAndPunctuation, .asciiCapableNumberPad: true - default: false - } - } - - /// iOS's own words for the return key, by the type the field asked for. - private static let returnLabels: [UIReturnKeyType: String] = [ - .go: "go", .google: "search", .yahoo: "search", .search: "search", .join: "join", .next: "next", - .route: "route", .send: "send", .done: "done", .emergencyCall: "call", .continue: "continue", - ] - - private static func returnLabel(_ type: UIReturnKeyType) -> String? { returnLabels[type] } - /// Auto-capitalisation, as the system keyboard does it: shift comes on at /// the start of a sentence (or of every word, or always) according to what /// the field asks for, and goes off after one letter. func updateShift() { if let termDraft { - // A key term is usually a name: capitalised to start, then as typed. - shifted = termDraft.isEmpty + // A key term is usually a name, or two: capitalised to start and after + // a space, then as typed. + shifted = termDraft.isEmpty || termDraft.last == " " return } guard let proxy else { return } @@ -324,12 +321,13 @@ final class KeyboardModel { } /// Catches up with whatever the app last published. No haptics: nothing - /// just happened, the keyboard merely came up. + /// just happened, the keyboard merely came up. A notice (pasted, copied, + /// error) was for the keyboard that was up when it happened, not this + /// appearance; a dictation in flight with the app gone is over. private func refresh(haptics: Bool) { isListening = SharedStore.isListening - if let current = SharedStore.read(PhaseSnapshot.self, forKey: BlurtShared.Key.phase) { - apply(current.isStale ? .idle : current, haptics: haptics) - } + guard let current = SharedStore.read(PhaseSnapshot.self, forKey: BlurtShared.Key.phase) else { return } + apply(current.isStale || current.noticeDwellSeconds != nil ? .idle : current, haptics: haptics) } /// Tells the app the keyboard is on screen, so a finished dictation is diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift index 7891d4eb..1dc5cb8c 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift @@ -106,6 +106,18 @@ final class KeyboardViewController: UIInputViewController, UIGestureRecognizerDe view.setNeedsUpdateConstraints() } + /// The host's traits are resolved by now where they may not have been in + /// `viewWillAppear`: the face is read again here, so a dark host is dark + /// from the first frame. Never from a trait-change registration — that + /// callback runs inside the host's layout pass, and a model change made + /// there left the mic element's drawing uncommitted in Messages (nothing + /// drew, every time). + override func viewIsAppearing(_ animated: Bool) { + super.viewIsAppearing(animated) + model.contextChanged() + paintFloor() + } + /// The floor in the face's material at `floorAlpha`: the host's own /// keyboard colour, measured, so nothing shows through the paint but the /// touches reach the keyboard. diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/MicControl.swift b/App/BlurtiOS/BlurtKeyboard/Sources/MicControl.swift index 6008759b..36e2586c 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/MicControl.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/MicControl.swift @@ -15,9 +15,14 @@ import SwiftUI struct MicControl: View { var model: KeyboardModel let slot: VoiceSlot - /// A narrower box than the slot's, when the bar hasn't the room. + /// The key's width: as wide as the element shows (`VoiceRowLayout`). var width: CGFloat? - @State private var pressed = false + /// The key's touch target is at least this tall — the row's height — so + /// the whole row under the element is the key, not just the element's box. + var hitHeight: CGFloat? + /// Down while the finger is on the key. A gesture state, so a touch the + /// system takes away lets the key back up; a plain state would hold it down. + @GestureState private var pressed = false @State private var press = MicPressSequencer() @State private var pressTask: Task? @Environment(\.accessibilityReduceMotion) private var systemReduceMotion @@ -27,7 +32,8 @@ struct MicControl: View { var body: some View { let state = model.voiceState - let box = CGSize(width: width ?? slot.box.width, height: slot.box.height) + let box = slot.box + let hit = CGSize(width: width ?? box.width, height: max(box.height, hitHeight ?? 0)) ZStack { VoiceElementView( inputs: VoiceElementInputs( @@ -43,7 +49,7 @@ struct MicControl: View { .transition(.opacity) } } - .frame(width: box.width, height: box.height) + .frame(width: hit.width, height: hit.height) .animation(.easeInOut(duration: DesignTokens.Motion.stateFade), value: state.phase) .scaleEffect(pressed ? DesignTokens.Metrics.voicePressScale : 1) .animation(.easeOut(duration: DesignTokens.Motion.press), value: pressed) @@ -52,16 +58,26 @@ struct MicControl: View { .accessibilityValue(state.accessibilityValue) .accessibilityAddTraits(.isButton) .accessibilityIdentifier("blurt-mic") + .onDisappear { + pressTask?.cancel() + pressTask = nil + press = MicPressSequencer() + } .simultaneousGesture( DragGesture(minimumDistance: 0) + .updating($pressed) { _, state, _ in state = true } .onChanged { value in - pressed = true if press.began() { // The press waits a beat, so a swipe that starts on the key (the // panel's carousel) never starts a dictation it must then cancel. pressTask = Task { [model] in try? await Task.sleep(for: KeyboardInteraction.micPressDelay) - guard !Task.isCancelled else { return } + // A touch the system took away in the meantime (the gesture + // state is down again) presses nothing. + guard !Task.isCancelled, pressed else { + press = MicPressSequencer() + return + } if press.delayFired() { model.micDown() } } } @@ -71,7 +87,6 @@ struct MicControl: View { } } .onEnded { value in - pressed = false pressTask?.cancel() pressTask = nil switch press.ended(travelled: KeyboardInteraction.micTravelled(value.translation)) { diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/PanelView.swift b/App/BlurtiOS/BlurtKeyboard/Sources/PanelView.swift index 775d8f7e..0e614d67 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/PanelView.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/PanelView.swift @@ -1,55 +1,45 @@ import SwiftUI -/// The voice element, centred, big; cancel in the corner while something is -/// in flight; one row of keys. 216 pt. +/// The voice element, big, dead centre — or at the edge Settings chose — with +/// the + beside it and cancel × on its other side while something is in +/// flight; one row of keys at the iPhone's widths. 216 pt. struct PanelView: View { var model: KeyboardModel @Environment(\.keyboardPalette) private var palette - @Environment(\.voiceElementKind) private var kind @Environment(\.layoutDirection) private var direction var body: some View { - let alignment = model.micAlignment.alignment(in: direction) - let atEdge = alignment != .center - let plusLeads = model.micAlignment.plusLeads(in: direction) - let recording = model.voiceState.isRecording - // In the middle the element has its whole slot and the + its corner. At - // an edge (one hand) the panel is a big voice bar: the key is as wide as - // the element shows, so the element itself — not an empty half of its - // box — is what sits under the thumb, the + beside it on its inner side, - // and cancel in the far corner, clear of them both. - let width = atEdge ? max(kind.visibleWidth(slot: .panel, recording: recording), DesignTokens.Metrics.keyMinWidth) : nil - VStack(spacing: DesignTokens.Metrics.panelSpacing) { - Spacer(minLength: 0) - HStack(spacing: DesignTokens.Metrics.voicebarAddtermClearance) { - if atEdge, plusLeads { AddTermKey(model: model) } - MicControl(model: model, slot: .panel, width: width) - if atEdge, !plusLeads { AddTermKey(model: model) } + GeometryReader { geo in + let geometry = KeyGeometry(rowWidth: geo.size.width) + let alignment = model.micAlignment.alignment(in: direction) + let atEdge = alignment != .center + VStack(spacing: DesignTokens.Metrics.panelSpacing) { + // The row takes all the height above the keys. The spacing under it + // is the margin above the page, so the mic is centred between the + // keyboard's top edge and the keys. + VoiceRow(model: model, slot: .panel, height: VoiceSlot.panel.box.height, cancels: !atEdge) + .frame(maxHeight: .infinity) + // The stock bottom row at the full keyboard's widths, so nothing + // changes size when the carousel flips to the keys and back. + HStack(spacing: geometry.gap) { + if model.needsGlobe { + KeyCap(systemImage: "globe", dark: true, width: geometry.abcWidth) { model.globe() } + } + KeyCap(title: "space", flexible: true) { model.space() } + KeyCap(systemImage: "delete.left", dark: true, width: geometry.abcWidth) { model.deleteBackward() } + KeyCap(title: model.returnLabel ?? "return", dark: true, width: geometry.returnWidth) { model.newline() } + } } - .frame(maxWidth: .infinity, alignment: alignment) - .animation(.easeInOut(duration: DesignTokens.Motion.waveFade), value: recording) - Spacer(minLength: 0) - HStack(spacing: KeyboardPalette.keyGap) { - if model.needsGlobe { KeyCap(systemImage: "globe", dark: true) { model.globe() } } - KeyCap(title: "space", flexible: true) { model.space() } - KeyCap(systemImage: "delete.left", dark: true) { model.deleteBackward() } - KeyCap(title: model.returnLabel ?? "return", dark: true) { model.newline() } - } - } - .overlay(alignment: alignment == .trailing ? .topLeading : .topTrailing) { - if model.voiceState.canCancel { - KeyCap(systemImage: "xmark", tint: palette.notice, bare: true) { model.cancel() } - .accessibilityLabel("Cancel dictation") - .transition(.opacity) - } - } - .overlay(alignment: .topLeading) { - // The +, or the chip for a highlighted word, growing from the corner - // and never as far as the cancel × in the other one. - if !atEdge { - AddTermKey(model: model, maxWidth: DesignTokens.Metrics.addtermChipMaxWidth) - .padding(DesignTokens.Metrics.addtermInset) + .overlay(alignment: alignment == .trailing ? .topLeading : .topTrailing) { + // With the mic at an edge, cancel goes to the far corner, clear of + // the mic and the + on its inner side. + if atEdge, model.voiceState.canCancel { + GlyphKey(symbol: "xmark", tint: palette.notice, label: "Cancel dictation") { model.cancel() } + .padding(DesignTokens.Metrics.addtermInset) + .transition(.opacity) + } } + .animation(.easeInOut(duration: DesignTokens.Motion.stateFade), value: model.voiceState.canCancel) } } } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/SlimBarView.swift b/App/BlurtiOS/BlurtKeyboard/Sources/SlimBarView.swift index 38b639d9..9311a2a1 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/SlimBarView.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/SlimBarView.swift @@ -1,15 +1,28 @@ import SwiftUI -/// One row: the globe, the voice bar, delete and return. 60 pt. +/// One row: the globe (when the phone doesn't draw its own), the voice bar, +/// delete and return, at the full keyboard's key widths and gap. 60 pt. struct SlimBarView: View { var model: KeyboardModel var body: some View { - HStack(spacing: DesignTokens.Metrics.slimSpacing) { - if model.needsGlobe { KeyCap(systemImage: "globe", dark: true) { model.globe() } } - VoiceBar(model: model) - KeyCap(systemImage: "delete.left", dark: true) { model.deleteBackward() } - KeyCap(title: model.returnLabel ?? "return", dark: true) { model.newline() } + GeometryReader { geo in + let geometry = KeyGeometry(rowWidth: geo.size.width) + // The keys are as tall as the row, so nothing sits half a point off. + let height = VoiceBar.height + HStack(spacing: geometry.gap) { + if model.needsGlobe { + KeyCap(systemImage: "globe", dark: true, width: geometry.abcWidth, height: height) { model.globe() } + } + VoiceBar(model: model) + KeyCap(systemImage: "delete.left", dark: true, width: geometry.abcWidth, height: height) { + model.deleteBackward() + } + KeyCap(title: model.returnLabel ?? "return", dark: true, width: geometry.returnWidth, height: height) { + model.newline() + } + } } + .frame(height: VoiceBar.height) } } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/TermField.swift b/App/BlurtiOS/BlurtKeyboard/Sources/TermField.swift index 2dac9ac1..e1471a65 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/TermField.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/TermField.swift @@ -2,15 +2,17 @@ import SwiftUI /// The voice bar as a field — the brand's input, a rectangle with a hairline, /// never a capsule: × to leave, what has been typed with a caret, ✓ to save. -/// Return saves too. +/// Return saves too. × and ✓ are the same glyph keys as the +. struct TermField: View { var model: KeyboardModel @Environment(\.keyboardPalette) private var palette var body: some View { HStack(spacing: DesignTokens.Metrics.termGap) { - round("xmark", tint: palette.keyText.opacity(DesignTokens.Metrics.opacityTermCancel)) { model.cancelAddingTerm() } - .accessibilityLabel("Cancel") + GlyphKey(symbol: "xmark", tint: palette.keyText.opacity(DesignTokens.Metrics.opacityTermCancel), label: "Cancel") + { + model.cancelAddingTerm() + } HStack(spacing: 0) { if let draft = model.termDraft, !draft.isEmpty { Text(draft).foregroundStyle(palette.keyText) @@ -32,24 +34,11 @@ struct TermField: View { ) .accessibilityElement(children: .ignore) .accessibilityLabel("Key term: \(model.termDraft ?? "")") - round("checkmark", tint: palette.signal) { model.saveTerm() } - .accessibilityLabel("Save the key term") + GlyphKey(symbol: "checkmark", tint: palette.signal, label: "Save the key term") { model.saveTerm() } .disabled(model.termDraft?.trimmingCharacters(in: .whitespaces).isEmpty ?? true) } .padding(.horizontal, DesignTokens.Metrics.termInset) } - - /// × and ✓: bare glyphs, as the + is. - private func round(_ symbol: String, tint: Color, action: @escaping () -> Void) -> some View { - Button(action: action) { - Image(systemName: symbol) - .font(.system(size: DesignTokens.Typography.sizeGlyph, weight: DesignTokens.Typography.weightGlyph)) - .foregroundStyle(tint) - .frame(width: DesignTokens.Metrics.glyphHit, height: DesignTokens.Metrics.glyphHit) - .contentShape(Circle()) - } - .buttonStyle(KeyPressStyle()) - } } /// A blinking caret, as a text field's; held on while motion is held. diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift index 72a9e8c7..c72128d7 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift @@ -1,88 +1,45 @@ import SwiftUI -/// The keyboard's voice row, and the only place voice lives: the orb, which -/// is the mic key — tap to start and stop, hold to talk — dissipating into -/// the wave while recording. No words: the orb's ring and colour, or the -/// wave, say what is happening, and the haptics confirm it (see `MicControl`). -/// Beside it, a small -/// + for the one thing people want the instant Blurt mishears a word: add it -/// as a key term. The bar then becomes the field the keys type into — or, -/// when a word is highlighted in the text, the + is already a chip holding -/// that word, and one tap adds it (`AddTermKey`). +/// The keyboard's voice row, and the only place voice lives in the bar and +/// the full keyboard: the mic key — tap to start and stop, hold to talk — +/// with the small + beside it for the one thing people want the instant +/// Blurt mishears a word: add it as a key term. The row is `VoiceRow`; this +/// swaps it for the key-term field the keys type into, or for the one note +/// the element can't carry (no Full Access). struct VoiceBar: View { var model: KeyboardModel @Environment(\.keyboardPalette) private var palette - @Environment(\.voiceElementKind) private var kind - @Environment(\.layoutDirection) private var direction static let height = DesignTokens.Metrics.voicebarHeight var body: some View { - GeometryReader { geo in - ZStack { - if model.termDraft != nil { - TermField(model: model) - .transition(.opacity) - } else if !model.hasFullAccess { - // The one state the element can't show on its own: without Full - // Access nothing here can work, and the user has to be told where - // to go. The line is the key: a tap opens Blurt, whose checklist - // says the rest. - Button { - model.openApp() - } label: { - Text("Allow Full Access in Settings") - .font(.footnote) - .foregroundStyle(palette.notice) - .lineLimit(1) - .minimumScaleFactor(0.8) // literal-ok: the note may shrink a little on a narrow phone - .frame(maxWidth: .infinity, maxHeight: .infinity) - } - .buttonStyle(KeyPressStyle()) - .accessibilityLabel("Start Blurt") - .transition(.opacity) - } else { - // The element where Settings put it, the + a clearance beside it. - // In the middle the element itself is dead centre — an unseen twin - // of the + balances the row on the other side, so the + hangs off - // the element rather than shifting it. The mic key is as wide as - // the element is (never narrower than a key, so the ribs asleep are - // still a target); when the ribs wake into the wave the + slides - // out of its way. A highlighted word makes the + a chip: the bar - // keeps it a minimum, the element gives way, and the chip hugs its - // word inside what is left. At the right edge the + comes first, so - // the mic is the thing at the edge and the + sits on its inner side. - let clearance = DesignTokens.Metrics.voicebarAddtermClearance - let chip = model.selectedTerm != nil - let centred = model.micAlignment == .center - let plusLeads = model.micAlignment.plusLeads(in: direction) - let beside = chip ? DesignTokens.Metrics.addtermChipMinWidth : DesignTokens.Metrics.glyphHit - let recording = model.voiceState.isRecording - let shown = kind.visibleWidth(slot: .bar, recording: recording) - let room = geo.size.width - (beside + clearance) * (centred ? 2 : 1) // literal-ok: a twin on each side - let width = min(max(shown, DesignTokens.Metrics.keyMinWidth), room) - HStack(spacing: clearance) { - if plusLeads { - AddTermKey(model: model) - } else if centred { - AddTermKey(model: model).hidden() - } - MicControl(model: model, slot: .bar, width: width) - if !plusLeads { - AddTermKey(model: model) - } else if centred { - AddTermKey(model: model).hidden() - } - } - .animation(.easeInOut(duration: DesignTokens.Motion.waveFade), value: recording) - .animation(.easeInOut(duration: DesignTokens.Motion.stateFade), value: chip) + ZStack { + if model.termDraft != nil { + TermField(model: model) .transition(.opacity) + } else if !model.hasFullAccess { + // Without Full Access nothing here can work, and the user has to be + // told where to go. The line is the key: a tap opens Blurt, whose + // checklist says the rest. + Button { + model.openApp() + } label: { + Text("Allow Full Access in Settings") + .font(.footnote) + .foregroundStyle(palette.notice) + .lineLimit(1) + .minimumScaleFactor(0.8) // literal-ok: the note may shrink a little on a narrow phone + .frame(maxWidth: .infinity, maxHeight: .infinity) } + .buttonStyle(KeyPressStyle()) + .accessibilityLabel("Start Blurt") + .transition(.opacity) + } else { + VoiceRow(model: model, slot: .bar, height: Self.height) + .transition(.opacity) } - // The pair sits where Settings put the mic — the middle, or the edge - // under the thumb (`MicAlignment`); the field and the note fill the row. - .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: model.micAlignment.alignment(in: direction)) } + .frame(maxWidth: .infinity) .frame(height: Self.height) .animation(.easeInOut(duration: DesignTokens.Motion.termSwap), value: model.termDraft == nil) } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceGrille.swift b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceGrille.swift index a847f737..10bd9418 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceGrille.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceGrille.swift @@ -11,6 +11,14 @@ import SwiftUI /// glistening. While the mic comes up or the words are made, one lit dot /// runs the perimeter on the ring's cadence. When the words land a thin /// white cross glint sweeps across it once; a failure turns it orange. +/// +/// Drawn as plain SwiftUI paths — never a `Canvas`. A Canvas has its own +/// render surface, and inside a keyboard extension that surface has failed +/// to present three separate times (asynchronous first; then in Messages, +/// whose host swaps scenes as the keyboard appears): the key was there, the +/// dots were not. Paths go through the ordinary view renderer with nothing +/// to lose. The frame is a handful of layers, one per colour, a few hundred +/// dots each. struct VoiceGrille: View { let inputs: VoiceElementInputs @@ -20,9 +28,17 @@ struct VoiceGrille: View { let box = Self.box(inputs.slot) TimelineView(.animation(minimumInterval: keyboardAnimationInterval, paused: !inputs.animated)) { timeline in let now = inputs.animated ? timeline.date : Date(timeIntervalSinceReferenceDate: 0) - Canvas { context, size in - draw(&context, size: size, now: now) + let layers = Self.layers(size: box, inputs: inputs, now: now) + ZStack { + ForEach(layers) { layer in + if layer.stroke > 0 { + layer.path.stroke(layer.colour.opacity(layer.opacity), lineWidth: layer.stroke) + } else { + layer.path.fill(layer.colour.opacity(layer.opacity)) + } + } } + .frame(width: box.width, height: box.height) } .frame(width: box.width, height: box.height) .opacity(inputs.state.isReady ? 1 : Metrics.opacityOff) @@ -38,7 +54,23 @@ struct VoiceGrille: View { } } - private func draw(_ context: inout GraphicsContext, size: CGSize, now: Date) { + /// One colour's worth of the frame: the dots (or the glint's lines) in it. + struct Layer: Identifiable { + let id: Int + var path = Path() + let colour: Color + let opacity: Double + /// A stroke width for the glint's lines; 0 fills. + var stroke: CGFloat = 0 + } + + /// The sheen's lift on a dot is quantised to this many steps, so the frame + /// is a few layers rather than one per dot; the lift is faint (0.22 at + /// most), and the steps are not seen. + private static let sheenSteps = 4 + + // swiftlint:disable:next function_body_length + static func layers(size: CGSize, inputs: VoiceElementInputs, now: Date) -> [Layer] { let state = inputs.state let palette = inputs.palette let time = now.timeIntervalSinceReferenceDate @@ -61,41 +93,50 @@ struct VoiceGrille: View { let (restColour, restOpacity) = Self.rest(state: state, palette: palette) // No sheen while Blurt isn't ready: the grille sits still as well as dim. let sheen = inputs.animated && state.isReady && !state.isRecording ? (centre: sheenCentre, band: sheenBand) : nil + // The layers: rest, the sheen's steps over rest, lit (and the runner), the facets' flashes. + var rest = Layer(id: 0, colour: restColour, opacity: restOpacity) + var sheened = (1...sheenSteps).map { step in + Layer( + id: step, colour: restColour, + opacity: min(1, restOpacity + Metrics.opacitySheen * Double(step) / Double(sheenSteps))) + } + var lit = Layer(id: sheenSteps + 1, colour: palette.signal, opacity: 1) + var flash = Layer(id: sheenSteps + 2, colour: DesignTokens.Brand.white, opacity: 1 - glintPhase) for column in 0.. 0.35 && VoiceClock.hash(column, glintTick) < Double(level) * 0.5 for row in 0.. 0, fromBottom <= lit { - colour = palette.signal - opacity = 1 + if litCount > 0, fromBottom <= litCount { // The top of a loud column glistens: a facet catches the light. - if fromBottom == lit, glints { - colour = DesignTokens.Brand.white - opacity = 1 - glintPhase + if fromBottom == litCount, glints { + flash.path.addEllipse(in: rect) + } else { + lit.path.addEllipse(in: rect) } } else if let runner, runner == Self.perimeterIndex(column: column, row: row, columns: columns, rows: rows) { - colour = palette.signal - opacity = 1 - } else if let sheen { + lit.path.addEllipse(in: rect) + } else if let sheen, abs(x + y - sheen.centre) < sheen.band / 2 { // The sheen: a diagonal band of light passing over the lattice, - // half the band each side of its centre. - let distance = abs(x + y - sheen.centre) - if distance < sheen.band / 2 { opacity += Metrics.opacitySheen * (1 - distance / (sheen.band / 2)) } + // half the band each side of its centre, in steps. + let lift = 1 - abs(x + y - sheen.centre) / (sheen.band / 2) + let step = max(1, min(sheenSteps, Int((lift * Double(sheenSteps)).rounded(.up)))) + sheened[step - 1].path.addEllipse(in: rect) + } else { + rest.path.addEllipse(in: rect) } - let rect = CGRect(x: x - dot / 2, y: y - dot / 2, width: dot, height: dot) // literal-ok: centred dots - context.fill(Path(ellipseIn: rect), with: .color(colour.opacity(min(1, opacity)))) } } + var layers = [rest] + sheened + [lit, flash] if let progress = VoiceClock.landing(landedAt: inputs.landedAt, now: now) { - Self.glint(&context, size: size, progress: progress) + layers += Self.glint(size: size, progress: progress, firstID: layers.count) } + return layers.filter { !$0.path.isEmpty } } /// How many dots fit, and where the first one sits so the lattice is centred. @@ -149,34 +190,37 @@ struct VoiceGrille: View { /// The cross glint: a thin white four-point flare that sweeps left to right /// as the words land, its vertical arm taller than the grille, with a /// faint prismatic fringe — the photograph's lens flare, once. - private static func glint(_ context: inout GraphicsContext, size: CGSize, progress: Double) { + private static func glint(size: CGSize, progress: Double, firstID: Int) -> [Layer] { let alpha = Metrics.opacityGlint * (1 - progress) let x = size.width * progress let arm = size.height * Metrics.grilleGlintArm let width = Metrics.grilleGlintWidth let midY = size.height / 2 - func line(_ from: CGPoint, _ to: CGPoint, colour: Color, opacity: Double) { - var path = Path() - path.move(to: from) - path.addLine(to: to) - context.stroke(path, with: .color(colour.opacity(opacity)), lineWidth: width) + func line(_ id: Int, _ from: CGPoint, _ to: CGPoint, colour: Color, opacity: Double) -> Layer { + var layer = Layer(id: id, colour: colour, opacity: opacity, stroke: width) + layer.path.move(to: from) + layer.path.addLine(to: to) + return layer } let fringe = alpha * 0.4 // literal-ok: the fringe is a fraction of the flare - line( - CGPoint(x: x + width, y: midY - arm / 2), CGPoint(x: x + width, y: midY + arm / 2), - colour: DesignTokens.Brand.violetIris, opacity: fringe) - line( - CGPoint(x: x - width, y: midY - arm / 2), CGPoint(x: x - width, y: midY + arm / 2), - colour: DesignTokens.Brand.green400, opacity: fringe) - line( - CGPoint(x: x, y: midY - arm / 2), CGPoint(x: x, y: midY + arm / 2), colour: DesignTokens.Brand.white, - opacity: alpha) - // The horizontal arm sits back. - line( - CGPoint(x: 0, y: midY), CGPoint(x: size.width, y: midY), colour: DesignTokens.Brand.white, opacity: alpha * 0.7) let core = Metrics.grilleDot * 2 // literal-ok: the flare's centre is a double dot - context.fill( - Path(ellipseIn: CGRect(x: x - core / 2, y: midY - core / 2, width: core, height: core)), // literal-ok: centred - with: .color(DesignTokens.Brand.white.opacity(alpha))) + var centre = Layer(id: firstID + 4, colour: DesignTokens.Brand.white, opacity: alpha) + centre.path.addEllipse(in: CGRect(x: x - core / 2, y: midY - core / 2, width: core, height: core)) // literal-ok: centred + return [ + line( + firstID, CGPoint(x: x + width, y: midY - arm / 2), CGPoint(x: x + width, y: midY + arm / 2), + colour: DesignTokens.Brand.violetIris, opacity: fringe), + line( + firstID + 1, CGPoint(x: x - width, y: midY - arm / 2), CGPoint(x: x - width, y: midY + arm / 2), + colour: DesignTokens.Brand.green400, opacity: fringe), + line( + firstID + 2, CGPoint(x: x, y: midY - arm / 2), CGPoint(x: x, y: midY + arm / 2), + colour: DesignTokens.Brand.white, opacity: alpha), + // The horizontal arm sits back. + line( + firstID + 3, CGPoint(x: 0, y: midY), CGPoint(x: size.width, y: midY), colour: DesignTokens.Brand.white, + opacity: alpha * 0.7), + centre, + ] } } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceRow.swift b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceRow.swift new file mode 100644 index 00000000..280deec8 --- /dev/null +++ b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceRow.swift @@ -0,0 +1,209 @@ +import SwiftUI + +/// The voice row's arithmetic, out of the views, so the bar, the panel and +/// the slim bar place the mic key and the add key one way and the numbers +/// can be tested (DESIGN.md › Layouts). +/// +/// The mic key is what is placed: dead centre of the row, or at the edge +/// Settings chose (`MicAlignment`). The add key — the +, or the chip for a +/// highlighted word — hangs off the mic a clearance away, at the mic's own +/// vertical centre: on its trailing side in the middle, on its inner side at +/// an edge, so the mic is always the thing at the edge. A chip grows away +/// from the mic as far as the row allows. When a chip has less than its +/// minimum beside a centred mic (the slim bar), the mic and the chip centre +/// as a pair instead: the mic moves over rather than the chip collapsing +/// onto it. In the panel the cancel × mirrors the add key on the mic's other +/// side, so the row reads × · mic · + while something is in flight. +nonisolated struct VoiceRowLayout: Equatable { + enum Side: Equatable { + case center + case leading + case trailing + } + + /// Where things go, in points from the row's leading edge. + struct Placement: Equatable { + /// The mic key's leading edge and width. + let micX: CGFloat + let micWidth: CGFloat + /// The add key's box: the + sits at the box's mic-side edge; a chip hugs + /// that edge and may grow to the box's far one. + let addX: CGFloat + let addWidth: CGFloat + /// Whether the box's mic-side edge is its leading one — the box grows + /// towards the trailing edge. + let addGrowsTrailing: Bool + /// The cancel key's leading edge, mirroring the + on the mic's other + /// side; nil at an edge, where cancel goes to the far corner instead. + let cancelX: CGFloat? + /// The mic and the chip centred together as a pair, the mic moved over: + /// `micX` and `addX` are then unused and `addWidth` is the chip's most. + let paired: Bool + } + + let rowWidth: CGFloat + let side: Side + /// Between the mic key's edge and the add key's box. + let clearance: CGFloat + /// The +'s box, a square. + let glyphHit: CGFloat + /// The least a chip needs beside a centred mic before the pair centres instead. + let chipMinWidth: CGFloat + + init( + rowWidth: CGFloat, side: Side, clearance: CGFloat = DesignTokens.Metrics.voicebarAddtermClearance, + glyphHit: CGFloat = DesignTokens.Metrics.glyphHit, chipMinWidth: CGFloat = DesignTokens.Metrics.addtermChipMinWidth + ) { + self.rowWidth = rowWidth + self.side = side + self.clearance = clearance + self.glyphHit = glyphHit + self.chipMinWidth = chipMinWidth + } + + /// Places a mic key that shows `shown` wide — never narrower than + /// `minMicWidth` (a key), never wider than the row — with the + beside it, + /// or a chip when `chip`. + func place(micWidth shown: CGFloat, minMicWidth: CGFloat, chip: Bool) -> Placement { + let mic = min(rowWidth, max(minMicWidth, shown)) + switch side { + case .leading: + let addX = mic + clearance + let room = max(0, rowWidth - addX) + return Placement( + micX: 0, micWidth: mic, addX: addX, addWidth: chip ? room : min(glyphHit, room), addGrowsTrailing: true, + cancelX: nil, paired: false) + case .trailing: + let micX = rowWidth - mic + let room = max(0, micX - clearance) + let width = chip ? room : min(glyphHit, room) + return Placement( + micX: micX, micWidth: mic, addX: room - width, addWidth: width, addGrowsTrailing: false, cancelX: nil, + paired: false) + case .center: + let micX = (rowWidth - mic) / 2 // literal-ok: centred + let addX = micX + mic + clearance + let room = max(0, rowWidth - addX) + if chip, room < chipMinWidth { + // Not enough beside a centred mic: the pair centres, the chip taking + // what the mic leaves. + return Placement( + micX: 0, micWidth: mic, addX: 0, addWidth: max(0, rowWidth - mic - clearance), addGrowsTrailing: true, + cancelX: nil, paired: true) + } + // The + never leaves the row: beside a mic wider than the row allows + // it moves in over the mic's edge, and so does its mirror. + let plusX = max(0, min(addX, rowWidth - glyphHit)) + let cancelX = max(0, min(micX - clearance - glyphHit, rowWidth - glyphHit)) + return Placement( + micX: micX, micWidth: mic, addX: chip ? addX : plusX, addWidth: chip ? room : glyphHit, addGrowsTrailing: true, + cancelX: cancelX, paired: false) + } + } +} + +/// The row itself: the mic key where `VoiceRowLayout` puts it, the add key +/// hanging off it and — where `cancels` — the cancel × mirroring the add key +/// while a dictation is in flight. Fills the width it is given; `height` is +/// the row's, and the mic key's touch target is that tall. +struct VoiceRow: View { + var model: KeyboardModel + let slot: VoiceSlot + let height: CGFloat + var cancels = false + @Environment(\.keyboardPalette) private var palette + @Environment(\.voiceElementKind) private var kind + @Environment(\.layoutDirection) private var direction + + var body: some View { + GeometryReader { geo in + let recording = model.voiceState.isRecording + let chip = model.selectedTerm != nil + let layout = VoiceRowLayout(rowWidth: geo.size.width, side: Self.side(model.micAlignment, in: direction)) + let placed = layout.place( + micWidth: kind.visibleWidth(slot: slot, recording: recording), minMicWidth: DesignTokens.Metrics.keyMinWidth, + chip: chip) + let cancel = cancels && model.voiceState.canCancel + ZStack(alignment: .leading) { + if placed.paired { + // The chip at its own width, capped — a frame would stretch to the + // cap and the pair would sit off centre. + HStack(spacing: layout.clearance) { + if cancel { cancelKey.transition(.opacity) } + MicControl(model: model, slot: slot, width: placed.micWidth, hitHeight: height) + CappedWidth(cap: placed.addWidth) { AddTermKey(model: model) } + } + .frame(maxWidth: .infinity) + } else { + MicControl(model: model, slot: slot, width: placed.micWidth, hitHeight: height) + .padding(.leading, placed.micX) + AddTermKey(model: model) + .frame(width: placed.addWidth, alignment: placed.addGrowsTrailing ? .leading : .trailing) + .padding(.leading, placed.addX) + if cancel, let cancelX = placed.cancelX { + cancelKey.padding(.leading, cancelX).transition(.opacity) + } + } + } + .frame(width: geo.size.width, height: geo.size.height, alignment: .leading) + .animation(.easeInOut(duration: DesignTokens.Motion.waveFade), value: recording) + .animation(.easeInOut(duration: DesignTokens.Motion.stateFade), value: chip) + .animation(.easeInOut(duration: DesignTokens.Motion.stateFade), value: cancel) + } + .frame(height: height) + } + + private var cancelKey: some View { + GlyphKey(symbol: "xmark", tint: palette.notice, label: "Cancel dictation") { model.cancel() } + } + + /// The row's side for the alignment Settings chose, as SwiftUI counts sides. + static func side(_ alignment: MicAlignment, in direction: LayoutDirection) -> VoiceRowLayout.Side { + switch alignment.alignment(in: direction) { + case .leading: .leading + case .trailing: .trailing + default: .center + } + } +} + +/// A bare glyph as a key — the +, × and ✓: an SF Symbol at `size/glyph` in a +/// `glyph/hit` square (the HIG's 44 pt), no cap, lighting while pressed. One +/// shape wherever a glyph is a key, so the row's furniture matches. +struct GlyphKey: View { + let symbol: String + let tint: Color + let label: String + let action: () -> Void + + var body: some View { + Button(action: action) { + Image(systemName: symbol) + .font(.system(size: DesignTokens.Typography.sizeGlyph, weight: DesignTokens.Typography.weightGlyph)) + .foregroundStyle(tint) + .contentTransition(.symbolEffect(.replace)) + .frame(width: DesignTokens.Metrics.glyphHit, height: DesignTokens.Metrics.glyphHit) + .contentShape(Rectangle()) + } + .buttonStyle(KeyPressStyle()) + .accessibilityLabel(label) + } +} + +/// One view at its own width, but never wider than `cap`: what a chip needs +/// when it is centred with the mic as a pair. (`frame(maxWidth:)` is greedy — +/// it takes the cap whatever the content wants.) +struct CappedWidth: Layout { + let cap: CGFloat + + func sizeThatFits(proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) -> CGSize { + guard let subview = subviews.first else { return .zero } + let ideal = subview.sizeThatFits(.unspecified) + let width = min(ideal.width, cap, proposal.width ?? .infinity) + return subview.sizeThatFits(ProposedViewSize(width: width, height: proposal.height)) + } + + func placeSubviews(in bounds: CGRect, proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) { + subviews.first?.place(at: bounds.origin, anchor: .topLeading, proposal: ProposedViewSize(bounds.size)) + } +} diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceState.swift b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceState.swift index 158c82cf..8faaafc2 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceState.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceState.swift @@ -109,7 +109,9 @@ nonisolated struct VoiceState: Equatable { } } - var canCancel: Bool { !isSettled } + /// Something is in flight and Blurt is there to stop it: no × beside a + /// dimmed mic whose app is gone. + var canCancel: Bool { !isSettled && isReady } var ring: Ring { switch phase { diff --git a/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift b/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift index 54020cfd..44797df4 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift @@ -44,6 +44,8 @@ final class DictationCoordinator { /// dictation in flight, read by the engine's context seam — and cleared once /// used, so nothing from another app's field primes a later request. nonisolated private static let pressContext = Mutex(.empty) + /// The keyboard process that pressed, for the words to go back to it. + nonisolated private static let pressKeyboard = Mutex(nil) /// Contact names, parsed once per lexicon refresh rather than on the press. nonisolated private static let lexiconNames = Mutex<[String]>([]) /// A press command older than this was held while the app was suspended. @@ -59,7 +61,7 @@ final class DictationCoordinator { session = DictationSession( mic: window.source, transcriber: AssemblyAITranscriber(), - injector: KeyboardRelayInjector(), + injector: KeyboardRelayInjector(presser: { Self.pressKeyboard.withLock { $0 } }), keyTermsProvider: { Self.keyTerms() }, readinessCheck: apiKey.readinessCheck(), onTranscriptDelivered: { _, ring in continuation.yield(ring) }, @@ -133,6 +135,7 @@ final class DictationCoordinator { /// prior text primes it. func toggleDictation() { Self.pressContext.withLock { $0 = .empty } + Self.pressKeyboard.withLock { $0 = nil } session.submit(phase.isCapturing ? .release : .press) } @@ -155,6 +158,7 @@ final class DictationCoordinator { $0 = FocusedFieldContext( priorText: command.priorText, selectedText: command.selectedText, windowTitle: nil, fieldLabel: nil) } + Self.pressKeyboard.withLock { $0 = command.keyboard } session.submit(.press) case .release: session.submit(.release) case .cancel: session.submit(.cancel) @@ -249,7 +253,8 @@ final class DictationCoordinator { private func publish(_ state: OverlayUIState) { let snapshot = PhaseSnapshot( - state: Self.snapshotState(state), message: Self.message(state), level: Double(level), at: Date()) + state: Self.snapshotState(state), message: Self.message(state), level: Double(level), at: Date(), + command: lastCommandID) SharedStore.write(snapshot, forKey: BlurtShared.Key.phase) SharedStore.post(BlurtShared.Signal.phase) } diff --git a/App/BlurtiOS/BlurtiOS/Sources/KeyboardProbeView.swift b/App/BlurtiOS/BlurtiOS/Sources/KeyboardProbeView.swift index 8b364159..053c25e1 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/KeyboardProbeView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/KeyboardProbeView.swift @@ -10,6 +10,9 @@ /// builds only; the keyboard itself never runs here. struct KeyboardProbeView: View { let dark: Bool + /// `-BlurtProbeText `: the field starts with this in it, so a flow + /// can highlight a word in any layout, letter keys or not. + var text = "" /// `-BlurtProbeField light|dark [a|b|c] [slimBar|panel|full] [left|center|right]`: /// the words after the face set the mic concept, the layout and the mic's @@ -31,12 +34,16 @@ // `-BlurtProbeResetTerms`: an empty key-term list, so a flow that adds a // word finds it new on every run (the App Group outlives the test). if arguments.contains("-BlurtProbeResetTerms") { SharedStore.keyTerms = [] } - return KeyboardProbeView(dark: face == "dark") + var text = "" + if let flag = arguments.firstIndex(of: "-BlurtProbeText"), arguments.count > flag + 1 { + text = arguments[flag + 1] + } + return KeyboardProbeView(dark: face == "dark", text: text) } var body: some View { VStack { - ProbeField(dark: dark) + ProbeField(dark: dark, text: text) .frame(height: DesignTokens.Metrics.keyMinWidth) .padding() // Puts the keyboard away without leaving the field, so a flow can @@ -70,10 +77,12 @@ /// keyboard's voice row stands in for. private struct ProbeField: UIViewRepresentable { let dark: Bool + let text: String func makeUIView(context: Context) -> UITextField { let field = UITextField() field.accessibilityIdentifier = "probe-field" + field.text = text field.keyboardAppearance = dark ? .dark : .light field.autocorrectionType = .yes field.autocapitalizationType = .none diff --git a/App/BlurtiOS/BlurtiOS/Sources/KeyboardRelayInjector.swift b/App/BlurtiOS/BlurtiOS/Sources/KeyboardRelayInjector.swift index 2c005e2d..7023aa3d 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/KeyboardRelayInjector.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/KeyboardRelayInjector.swift @@ -19,12 +19,20 @@ nonisolated struct KeyboardRelayInjector: InjectorProtocol { static let deliveryTimeout: TimeInterval = 3 static let deliveryPoll: Duration = .milliseconds(250) + /// The keyboard the dictation in flight was pressed in + /// (`KeyboardCommand.keyboard`), or nil for whichever keyboard is up. + var presser: @Sendable () -> String? = { nil } + func setTarget(_ focus: CapturedFocus?) async {} func insert(_ text: String, after priorText: String?, windowTitle: String?) async throws { - guard SharedStore.isKeyboardPresent else { try await copyOut(text) } - let result = DictationResult( - id: UUID(), text: text, deliveredAt: Date(), recipient: SharedStore.keyboardInstance) + // The words go to the keyboard that asked for them. If the user has + // moved on — another app's keyboard is the one on screen now — they go + // to the clipboard rather than into a field nobody dictated into. + let onScreen = SharedStore.keyboardInstance + let recipient = presser() ?? onScreen + guard SharedStore.isKeyboardPresent, recipient == onScreen else { try await copyOut(text) } + let result = DictationResult(id: UUID(), text: text, deliveredAt: Date(), recipient: recipient) SharedStore.write(result, forKey: BlurtShared.Key.result) SharedStore.post(BlurtShared.Signal.result) let deadline = Date().addingTimeInterval(Self.deliveryTimeout) diff --git a/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardFlows+Reappearance.swift b/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardFlows+Reappearance.swift index a0683600..52efef6a 100644 --- a/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardFlows+Reappearance.swift +++ b/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardFlows+Reappearance.swift @@ -55,11 +55,11 @@ extension BlurtKeyboardFlows { check(keysUp, "a slow swipe from the mic flips to the keys (\(micKey().label))") swipeBackFromLetters() var frame = micKey().exists ? micKey().frame : .zero - check( - frame.width > 200, "after a slow swipe from the mic and back, the mic is there (\(frame), \(micKey().label))") + check(panelMicUp, "after a slow swipe from the mic and back, the mic is there (\(frame), \(micKey().label))") shot("rough-slow") - guard micKey().exists, micKey().label == "Dictate" else { return } - micKey().tap() + guard micKey().exists, micKey().label != "Start Blurt" else { return } + // Hands-free may have it recording already; otherwise a tap starts one. + if micKey().label == "Dictate" { micKey().tap() } check(micKey(labelled: "Stop dictation").waitForExistence(timeout: 4), "a tap starts a dictation") let gap = micKey().coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 1.15)) gap.press(forDuration: 0.05, thenDragTo: gap.withOffset(CGVector(dx: -160, dy: 0))) @@ -67,7 +67,7 @@ extension BlurtKeyboardFlows { check(keysUp, "a swipe while recording flips to the keys") swipeBackFromLetters() frame = micKey().exists ? micKey().frame : .zero - check(frame.width > 200, "back on the panel while recording, the mic is there (\(frame), \(micKey().label))") + check(panelMicUp, "back on the panel while recording, the mic is there (\(frame), \(micKey().label))") shot("rough-recording") if micKey(labelled: "Stop dictation").exists { micKey().tap() } _ = micKey(labelled: "Dictate").waitForExistence(timeout: 12) @@ -102,14 +102,17 @@ extension BlurtKeyboardFlows { check( back && frame.width > 40 && frame.height > 20, "brought back from \(page) the mic key is there, full size (\(frame))") + checkDrawn(micKey(), "brought back from \(page)") if frame == .zero { print("FLOW-TREE (mic missing after the return):\n\(app.debugDescription)") } if page == "the keys page" { check(!keysUp, "the panel is back on its mic page after being put away") } shot("returned-\(page.replacingOccurrences(of: " ", with: "-"))") } private func switchAwayAndBack(globe: XCUIElement, from page: String) throws { - // XCUITest has no Keyboard element for a custom keyboard: the + at the - // panel's top corner stands in for where the keyboard begins. + // XCUITest has no Keyboard element for a custom keyboard: the + stands in + // for where the keyboard begins — 8 pt under its top on the keys page + // (the voice bar), 58 on the panel (the mic's centre line, 80, less half + // its 44 pt hit). let plus = app.buttons["Add a key term"] let topBefore = plus.exists ? plus.frame.minY : 0 globe.tap() @@ -129,11 +132,13 @@ extension BlurtKeyboardFlows { check( frame.width > 40 && frame.height > 20, "back on Blurt from \(page) the mic key is there, full size (\(frame); top \(topBefore) → \(top))") + checkDrawn(mic, "back on Blurt from \(page)") if frame == .zero { print("FLOW-TREE (mic missing after the switch):\n\(app.debugDescription)") } if page == "the keys page" { check(!keysUp, "the panel is back on its mic page after the switch") - // The keys page was up before, so the keyboard was 54 pt taller then. - check(abs(top - topBefore - 54) < 4, "the panel is back at its own height (top \(topBefore) → \(top))") + // The keys page was up before, so the keyboard was 54 pt taller then + // (270 − 216), and the + sat 50 pt nearer its top (8 against 58). + check(abs(top - topBefore - 104) < 4, "the panel is back at its own height (top \(topBefore) → \(top))") } shot("switched-back") } diff --git a/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardFlows.swift b/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardFlows.swift index db804b42..15d5365b 100644 --- a/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardFlows.swift +++ b/App/BlurtiOS/BlurtiOSProbe/BlurtKeyboardFlows.swift @@ -27,52 +27,25 @@ final class BlurtKeyboardFlows: XCTestCase { side = arguments.first { ["left", "right"].contains($0) } app = XCUIApplication() // The app listens from launch, so the keyboard's mic key is live. - app.launchArguments = ["-BlurtProbeField"] + arguments + ["-BlurtStartListening", "-BlurtProbeResetTerms"] + app.launchArguments = + ["-BlurtProbeField"] + arguments + ["-BlurtStartListening", "-BlurtProbeResetTerms", "-BlurtProbeText", "Rizz"] app.launch() try bringUpBlurt() shot("up") let mic = micKey() check(mic.exists, "mic key present (\(mic.label))") - check(mic.label == "Dictate", "mic key ready: the app is listening (\(mic.label))") + // "Stop dictation" is hands-free already recording: ready too. + check(mic.label != "Start Blurt", "mic key ready: the app is listening (\(mic.label))") let plus = app.buttons["Add a key term"] check(plus.exists, "the + present") - if mic.exists, plus.exists { - let width = app.windows.firstMatch.frame.width - let centre = mic.frame.midX - if let side { - // One hand: the mic at the chosen edge, the + on its inner side. The - // slim bar's row is bounded by the globe (when Blurt draws one; on a - // Face ID phone the system puts it under the keyboard) and delete - // keys, so there the mic is next to that key rather than the edge. - let left = side == "left" - let globe = app.buttons["globe"].firstMatch - let bound = - layout == "slimBar" - ? (left ? (globe.exists ? globe.frame.maxX : 0) : app.buttons["delete.left"].firstMatch.frame.minX) - : (left ? 0 : width) - let edge = left ? mic.frame.minX - bound : bound - mic.frame.maxX - let inner = left ? plus.frame.minX > mic.frame.maxX : plus.frame.maxX < mic.frame.minX - check(edge < 12, "mic at the \(side) edge (\(edge) pt in)") - check(inner, "the + on the mic's inner side") - } else if layout == "panel" { - check(abs(centre - width / 2) < 4, "mic centred in the panel (\(centre) of \(width))") - check(plus.frame.midX < 60, "the + in the panel's top-left corner (\(plus.frame.midX))") - } else { - // The element itself is centred in the voice bar's own width — the - // whole row in the full keyboard, the room between the globe (if any) - // and delete in the slim bar — with the + hanging beside it. - let globe = app.buttons["globe"].firstMatch - let from = layout == "slimBar" && globe.exists ? globe.frame.maxX : 0 - let to = layout == "slimBar" ? app.buttons["delete.left"].firstMatch.frame.minX : width - check(abs(centre - (from + to) / 2) < 8, "mic centred in its row (\(centre) in \(from)…\(to))") - check(plus.frame.minX > mic.frame.maxX, "the + beside the mic, to its right") - } - } + checkDrawn(mic, "on appearance") + if mic.exists, plus.exists { checkPlacement(layout: layout, mic: mic, plus: plus) } switch layout { case "panel": try panelFlows() case "full": try fullFlows() default: try slimFlows() } + try selectionFlow(app.textFields.firstMatch) try termFlow() try dictationFlow() try switchAwayAndBack() @@ -80,6 +53,44 @@ final class BlurtKeyboardFlows: XCTestCase { // MARK: Helpers + /// Where the mic and the + sit, for this run's layout and side. + private func checkPlacement(layout: String, mic: XCUIElement, plus: XCUIElement) { + let width = app.windows.firstMatch.frame.width + let centre = mic.frame.midX + // Wherever the mic is, the + sits on its centre line. + check( + abs(plus.frame.midY - mic.frame.midY) < 4, + "the + at the mic's centre line (\(plus.frame.midY) vs \(mic.frame.midY))") + if let side { + // One hand: the mic at the chosen edge, the + on its inner side. The + // slim bar's row is bounded by the globe (when Blurt draws one; on a + // Face ID phone the system puts it under the keyboard) and delete + // keys, so there the mic is next to that key rather than the edge. + let left = side == "left" + let globe = app.buttons["globe"].firstMatch + let bound = + layout == "slimBar" + ? (left ? (globe.exists ? globe.frame.maxX : 0) : app.buttons["delete.left"].firstMatch.frame.minX) + : (left ? 0 : width) + let edge = left ? mic.frame.minX - bound : bound - mic.frame.maxX + let inner = left ? plus.frame.minX > mic.frame.maxX : plus.frame.maxX < mic.frame.minX + check(edge < 12, "mic at the \(side) edge (\(edge) pt in)") + check(inner, "the + on the mic's inner side") + } else if layout == "panel" { + check(abs(centre - width / 2) < 4, "mic centred in the panel (\(centre) of \(width))") + check(plus.frame.minX > mic.frame.maxX, "the + beside the mic, to its right") + } else { + // The element itself is centred in the voice bar's own width — the + // whole row in the full keyboard, the room between the globe (if any) + // and delete in the slim bar — with the + hanging beside it. + let globe = app.buttons["globe"].firstMatch + let from = layout == "slimBar" && globe.exists ? globe.frame.maxX : 0 + let to = layout == "slimBar" ? app.buttons["delete.left"].firstMatch.frame.minX : width + check(abs(centre - (from + to) / 2) < 8, "mic centred in its row (\(centre) in \(from)…\(to))") + check(plus.frame.minX > mic.frame.maxX, "the + beside the mic, to its right") + } + } + private func bringUpBlurt() throws { let blurt = app.buttons["Add a key term"] let system = app.keyboards.firstMatch @@ -115,6 +126,13 @@ final class BlurtKeyboardFlows: XCTestCase { XCTAssertTrue(condition, what) } + /// The mic element's pixels are there — a key with nothing drawn in it is + /// the failure the frame checks cannot see. + func checkDrawn(_ mic: XCUIElement, _ when: String) { + let ink = MicPixels.ink(app, mic: mic) ?? 0 + check(ink > MicPixels.drawnThreshold, "the mic is drawn \(when) (ink \(ink))") + } + func shot(_ name: String) { shots += 1 let attachment = XCTAttachment(screenshot: app.screenshot()) @@ -161,7 +179,8 @@ extension BlurtKeyboardFlows { if index == 0 { shot("panel-back") } } } - check(!keysUp && micKey().frame.width > panelMicWidth, "the panel is showing again, its mic full size") + check(!keysUp && panelMicUp, "the panel is showing again, its mic full size") + checkDrawn(micKey(), "after the swipes back") // Pairs from one fixed screen point (an element mid-slide is no anchor): // a flip and a flip back, and two the same way — with no wait between, // so the second lands mid-slide, and again after the slide has settled. @@ -179,7 +198,7 @@ extension BlurtKeyboardFlows { if pair.pause > 0 { Thread.sleep(forTimeInterval: pair.pause) } fixed.press(forDuration: 0.05, thenDragTo: fixed.withOffset(CGVector(dx: pair.second, dy: 0))) Thread.sleep(forTimeInterval: 1.5) - check(!keysUp && micKey().frame.width > panelMicWidth, "two quick swipes, \(pair.name), land back on the panel") + check(!keysUp && panelMicUp, "two quick swipes, \(pair.name), land back on the panel") shot("panel-pair-\(pair.name.replacingOccurrences(of: ", ", with: "-").replacingOccurrences(of: " ", with: "-"))") } } @@ -202,9 +221,10 @@ extension BlurtKeyboardFlows { /// Whether the letter keys are on screen (either shift state). var keysUp: Bool { letterKey("Q").exists || letterKey("q").exists } - /// The least the panel's mic key is wide when the panel is up: its whole - /// 300 pt slot in the middle, the element's own width at an edge. - private var panelMicWidth: CGFloat { side == nil ? 200 : 60 } + /// Whether the mic key on screen is the panel's: as tall as the panel's + /// element box (88), where the bar's is the row (44). The width says + /// nothing — the key is as wide as the element shows, whichever concept. + var panelMicUp: Bool { micKey().exists && micKey().frame.height > 60 } private func fullFlows() throws { let q = letterKey("Q") @@ -219,7 +239,6 @@ extension BlurtKeyboardFlows { app.buttons["return"].exists || app.buttons["RETURN"].exists || app.buttons["Return"].exists, "return key labelled") shot("full-typed") - try selectionFlow(field) } /// Highlight the word in the field: the + becomes a chip holding it, one @@ -233,27 +252,54 @@ extension BlurtKeyboardFlows { let chip = app.buttons.matching( NSPredicate(format: "label BEGINSWITH %@ OR label ENDSWITH %@", "Add “", "” is a key term") ).firstMatch + let mic = micKey() for attempt in 1...2 where !chip.exists { field.coordinate(withNormalizedOffset: CGVector(dx: 0.08, dy: 0.5)).doubleTap() if chip.waitForExistence(timeout: 3) { break } - shot("full-select-miss-\(attempt)") + shot("\(layoutName)-select-miss-\(attempt)") } let label = chip.exists ? chip.label : "-" check(chip.exists, "highlighting a word shows the chip (\(label))") - shot("full-selected") + if chip.exists, mic.exists { + check(abs(chip.frame.midY - mic.frame.midY) < 4, "the chip at the mic's centre line") + check( + chip.frame.minX >= mic.frame.maxX - 1 || chip.frame.maxX <= mic.frame.minX + 1, + "the chip clear of the mic (\(chip.frame) vs \(mic.frame))") + } + shot("\(layoutName)-selected") + let plus = app.buttons["Add a key term"] if label.hasPrefix("Add “") { let word = label.dropFirst("Add “".count).prefix { $0 != "”" } chip.tap() let known = app.descendants(matching: .any) .matching(NSPredicate(format: "label == %@", "“\(word)” is a key term")).firstMatch - check(known.waitForExistence(timeout: 3), "one tap adds “\(word)”; the chip shows the check") - shot("full-added") + // The check shows for 1.2 s; XCUITest's snapshot of another process + // can miss it, so the proof of the add is below: the word re-selected + // is a word Blurt knows. + if known.waitForExistence(timeout: 2) { shot("\(layoutName)-added") } + // The highlight still stands in the field; the chip gives way to the + + // on its own after the check, so the row is never stuck on the word. + check(plus.waitForExistence(timeout: 4), "after the check the + is back while the word stays highlighted") + check(mic.exists && mic.label != "Start Blurt", "the mic is still the mic after adding (\(mic.label))") + shot("\(layoutName)-after-add") + // Cleared and highlighted again: Blurt knows the word now, and a tap on + // that chip puts the + back at once. + field.coordinate(withNormalizedOffset: CGVector(dx: 0.95, dy: 0.5)).tap() + Thread.sleep(forTimeInterval: 0.5) + field.coordinate(withNormalizedOffset: CGVector(dx: 0.08, dy: 0.5)).doubleTap() + check(known.waitForExistence(timeout: 4), "one tap added “\(word)”: highlighted again, the chip knows it") + shot("\(layoutName)-known") + if known.exists { + known.tap() + check(plus.waitForExistence(timeout: 3), "a tap on the known chip puts the + back") + } } else if chip.exists { check(false, "the word was already a key term before this run (\(label)) — the list was not reset") } - // Clear the highlight, cursor at the end, so the + is back for the flows - // after this and typing appends rather than replaces. + // Clear the highlight, cursor at the end, so typing appends rather than + // replaces; the + is there either way. field.coordinate(withNormalizedOffset: CGVector(dx: 0.95, dy: 0.5)).tap() + check(plus.waitForExistence(timeout: 3), "the + present once the highlight is cleared") Thread.sleep(forTimeInterval: 0.5) } diff --git a/App/BlurtiOS/BlurtiOSProbe/MessagesCarouselProbe.swift b/App/BlurtiOS/BlurtiOSProbe/MessagesCarouselProbe.swift index 8e019e85..8c3a5728 100644 --- a/App/BlurtiOS/BlurtiOSProbe/MessagesCarouselProbe.swift +++ b/App/BlurtiOS/BlurtiOSProbe/MessagesCarouselProbe.swift @@ -19,6 +19,8 @@ final class MessagesCarouselProbe: XCTestCase { let mic = messages.buttons.matching(NSPredicate(format: "identifier == %@", "blurt-mic")).firstMatch XCTAssertTrue(mic.exists, "no mic key") print("FLOW-INFO mic \(mic.frame) plus \(plus.frame)") + let inkUp = MicPixels.ink(messages, mic: mic) ?? 0 + print("FLOW-\(inkUp > MicPixels.drawnThreshold ? "OK" : "FAIL"): the mic is drawn on appearance (ink \(inkUp))") shot(messages, "up") // One fixed point: the gap under the panel's mic. let anchor = mic.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 1.15)).screenPoint @@ -36,7 +38,25 @@ final class MessagesCarouselProbe: XCTestCase { // The panel's mic is element-wide when aligned to an edge, so its // presence, not its width, says the panel is up. let up = keys.exists ? "keys" : (mic.exists ? "panel" : "NEITHER") - print("FLOW-INFO after \(index + 1) (\(swipe.name)): \(up)") + let micFrame = mic.exists ? mic.frame : .zero + let plusFrame = plus.exists ? plus.frame : .zero + print("FLOW-INFO after \(index + 1) (\(swipe.name)): \(up) mic \(micFrame) plus \(plusFrame)") + if up == "panel" { + // The panel's mic key is the grille's box, the + beside it: anything + // else is the vanished-mic state Neil sees in Messages. + let beside = plusFrame.minX >= micFrame.maxX - 1 || plusFrame.maxX <= micFrame.minX + 1 + let sound = micFrame.width > 100 && micFrame.height > 60 && beside && abs(plusFrame.midY - micFrame.midY) < 4 + print("FLOW-\(sound ? "OK" : "FAIL"): panel back with the mic full size and the + beside it (\(index + 1))") + let ink = MicPixels.ink(messages, mic: mic) ?? 0 + print( + "FLOW-\(ink > MicPixels.drawnThreshold ? "OK" : "FAIL"): the mic is drawn after the return (\(index + 1), ink \(ink))" + ) + if !sound { + print( + "FLOW-TREE\n\(messages.debugDescription.split(separator: "\n").filter { $0.contains("Button") || $0.contains("Other") }.prefix(60).joined(separator: "\n"))" + ) + } + } shot(messages, "\(index + 1)-\(swipe.name)") } } diff --git a/App/BlurtiOS/BlurtiOSProbe/MicPixels.swift b/App/BlurtiOS/BlurtiOSProbe/MicPixels.swift new file mode 100644 index 00000000..fcdc778a --- /dev/null +++ b/App/BlurtiOS/BlurtiOSProbe/MicPixels.swift @@ -0,0 +1,64 @@ +import CoreGraphics +import UIKit +import XCTest + +/// Whether the mic element is actually *drawn* — not merely present in the +/// accessibility tree with a frame. The keyboard's key has been there with +/// nothing in it more than once (a drawing surface that never presented in +/// the extension), and only the pixels can say. Samples the screenshot inside +/// the mic key's frame and counts pixels that differ from the frame's own +/// corner, which is the host's material: the grille's dots, lit or at rest, +/// cover well over a tenth of the box; an empty key covers none. +enum MicPixels { + /// The least share of differing pixels that counts as the element drawn. + static let drawnThreshold = 0.02 + + /// The share of pixels inside `frame` (points, screen coordinates) that are + /// not the material's colour. + static func inkFraction(in shot: XCUIScreenshot, frame: CGRect) -> Double { + guard let image = shot.image.cgImage, frame.width > 4, frame.height > 4 else { return 0 } + let scale = CGFloat(image.width) / UIScreen.main.bounds.width + let rect = CGRect( + x: frame.minX * scale, y: frame.minY * scale, width: frame.width * scale, height: frame.height * scale + ).integral.intersection(CGRect(x: 0, y: 0, width: image.width, height: image.height)) + guard let data = image.dataProvider?.data, let bytes = CFDataGetBytePtr(data), rect.width > 4, rect.height > 4 + else { return 0 } + let bytesPerPixel = image.bitsPerPixel / 8 + let bytesPerRow = image.bytesPerRow + struct RGB { + let r: Int + let g: Int + let b: Int + func distance(to other: RGB) -> Int { abs(r - other.r) + abs(g - other.g) + abs(b - other.b) } + } + func pixel(_ x: Int, _ y: Int) -> RGB { + let offset = y * bytesPerRow + x * bytesPerPixel + return RGB(r: Int(bytes[offset]), g: Int(bytes[offset + 1]), b: Int(bytes[offset + 2])) + } + // The material, read just inside the corner (the frame's edge may be antialiased). + let reference = pixel(Int(rect.minX) + 2, Int(rect.minY) + 2) + var differing = 0 + var total = 0 + var y = Int(rect.minY) + while y < Int(rect.maxY) { + var x = Int(rect.minX) + while x < Int(rect.maxX) { + if pixel(x, y).distance(to: reference) > 40 { differing += 1 } + total += 1 + x += 2 + } + y += 2 + } + return total == 0 ? 0 : Double(differing) / Double(total) + } + + /// The mic element's share of ink, or nil when the key is not there. + static func ink(_ app: XCUIApplication, mic: XCUIElement) -> Double? { + guard mic.exists else { return nil } + return inkFraction(in: app.screenshot(), frame: mic.frame) + } + + static func isDrawn(_ app: XCUIApplication, mic: XCUIElement) -> Bool { + (ink(app, mic: mic) ?? 0) > drawnThreshold + } +} diff --git a/App/BlurtiOS/BlurtiOSTests/KeyboardInteractionTests.swift b/App/BlurtiOS/BlurtiOSTests/KeyboardInteractionTests.swift index 447da843..f1d180cc 100644 --- a/App/BlurtiOS/BlurtiOSTests/KeyboardInteractionTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/KeyboardInteractionTests.swift @@ -24,6 +24,25 @@ struct KeyboardInteractionTests { #expect(KeyboardInteraction.micTravelled(CGSize(width: 0, height: -24.1))) } + @Test("a touch that ends on the key is a tap wherever the thumb rolled; one that left it is not") + func endsOnKey() { + let key = CGSize(width: 33.5, height: 43) + // Barely moved: a tap wherever it ended. + #expect(KeyboardInteraction.isTap(CGSize(width: 5, height: 5), endedAt: CGPoint(x: -100, y: -100), in: key)) + // Rolled 20 pt but ended inside the key. + #expect(KeyboardInteraction.isTap(CGSize(width: 0, height: 20), endedAt: CGPoint(x: 16, y: 30), in: key)) + // Ended just past the edge, within the slop. + #expect( + KeyboardInteraction.isTap( + CGSize(width: 15, height: 0), endedAt: CGPoint(x: key.width + KeyboardInteraction.tapSlop - 0.1, y: 20), + in: key)) + // Left the key: a swipe. + #expect(!KeyboardInteraction.isTap(CGSize(width: 60, height: 0), endedAt: CGPoint(x: 80, y: 20), in: key)) + #expect(!KeyboardInteraction.isTap(CGSize(width: 0, height: -60), endedAt: CGPoint(x: 16, y: -40), in: key)) + // With no size known yet, only the travel rule applies. + #expect(!KeyboardInteraction.isTap(CGSize(width: 15, height: 0), endedAt: CGPoint(x: 16, y: 20), in: .zero)) + } + // `#expect` captures its expression immutably, so each mutating step lands // in a local first. @Test("a quick tap presses and releases together") diff --git a/App/BlurtiOS/BlurtiOSTests/KeyboardModelFuzzTests.swift b/App/BlurtiOS/BlurtiOSTests/KeyboardModelFuzzTests.swift new file mode 100644 index 00000000..17c7682a --- /dev/null +++ b/App/BlurtiOS/BlurtiOSTests/KeyboardModelFuzzTests.swift @@ -0,0 +1,303 @@ +import Foundation +import Testing + +@testable import BlurtiOS + +/// The keyboard model driven through thousands of random event sequences — +/// every finger, phase, host and lifecycle event the real keyboard sees, in +/// any order — with the invariants that must hold after every one of them +/// checked each time. Seeded, so a failure names the sequence that made it. +/// This is the "nothing is ever left stale" check: a state the model can be +/// driven into and not out of shows up here as a broken invariant. +@Suite("Keyboard model: random transition sequences", .serialized) +@MainActor +struct KeyboardModelFuzzTests { + /// One event the fuzz can send. `apply` phases come as the app would + /// publish them; the rest are the keyboard's own entry points. + enum Event: CaseIterable { + case micDown, micUp, cancel + case phaseIdle, phaseConnecting, phaseRecording, phaseProcessing, phasePasted, phaseCopied, phaseError + case answerConnecting, answerError + case appNotListening, appListening + case beginTerm, cancelTerm, saveTerm, typeLetter, space, deleteBack, newline + case selectWord, selectOther, clearSelection, addSelected, dismissSelected + case flipPanel, toggleSymbols, toggleMore, toggleShift + case appeared, disappeared, appearedNoAccess, contextChanged + case resultFresh, resultStale, resultForOther + case hostTyped, hostMovedCursor + } + + /// A tiny deterministic generator (SplitMix64), so a run is repeatable. + struct Random { + var state: UInt64 + mutating func next() -> UInt64 { + state &+= 0x9E37_79B9_7F4A_7C15 + var z = state + z = (z ^ (z >> 30)) &* 0xBF58_476D_1CE4_E5B9 + z = (z ^ (z >> 27)) &* 0x94D0_49BB_1331_11EB + return z ^ (z >> 31) + } + mutating func pick(_ items: [T]) -> T { items[Int(next() % UInt64(items.count))] } + } + + final class Commands { + var sent: [KeyboardCommand] = [] + } + + /// Set by an event after which the command ledger starts over. + private final class Flag { + var value = false + } + private let epochFlag = Flag() + private var epoch: Bool { + get { epochFlag.value } + nonmutating set { epochFlag.value = newValue } + } + + private func snapshot(_ state: PhaseSnapshot.State) -> PhaseSnapshot { + PhaseSnapshot(state: state, message: nil, level: 0, at: Date()) + } + + private func listening(_ on: Bool) { + let now = Date() + SharedStore.listeningUntil = on ? now.addingTimeInterval(600) : nil + SharedStore.appSeenAt = on ? now : nil + } + + @Test( + "ten thousand random events never leave the model in a stale or contradictory state", arguments: [1, 2, 3, 4, 5]) + func fuzz(seed: UInt64) { + let suite = ScratchSuite() + defer { suite.tearDown() } + var random = Random(state: seed &* 7919) + let proxy = FakeProxy() + let model = KeyboardModel() + model.proxyOverride = proxy + model.hasFullAccess = true + let commands = Commands() + model.transport = { commands.sent.append($0) } + listening(true) + model.appeared() + var trace: [Event] = [] + // The press the app has not taken yet: closed by our release or cancel, + // by any in-flight phase (the app is on it), or by a settled phase that + // names it. A second press while one is open is the protocol broken. + var pressOpen: UUID? + for step in 0..<2000 { + let event = random.pick(Event.allCases) + trace.append(event) + let before = commands.sent.count + drive(model, proxy, event, &random) + if epoch { + commands.sent.removeAll() + pressOpen = nil + } + for command in commands.sent.dropFirst(min(before, commands.sent.count)) { + switch command.kind { + case .press: + #expect( + pressOpen == nil || pressOpen == command.id, + "two presses in flight — seed \(seed) step \(step) after \(event); last 12: \(trace.suffix(12))") + pressOpen = command.id + case .release, .cancel: pressOpen = nil + } + } + if Self.phaseEvents.contains(event), !model.isSettled || model.snapshot.command == pressOpen { + pressOpen = nil + } + check( + model, proxy, commands, after: event, + "seed \(seed) step \(step) after \(event); last 12: \(trace.suffix(12))") + } + } + + // swiftlint:disable:next cyclomatic_complexity function_body_length + private func drive(_ model: KeyboardModel, _ proxy: FakeProxy, _ event: Event, _ random: inout Random) { + epoch = false + switch event { + case .micDown: model.micDown() + case .micUp: model.micUp() + case .cancel: model.cancel() + case .phaseIdle: model.apply(snapshot(.idle)) + case .phaseConnecting: model.apply(snapshot(.connecting)) + case .phaseRecording: model.apply(snapshot(.recording)) + case .phaseProcessing: model.apply(snapshot(.processing)) + case .phasePasted: model.apply(snapshot(.pasted)) + case .phaseCopied: model.apply(snapshot(.copied)) + case .phaseError: model.apply(snapshot(.error)) + case .answerConnecting: + model.apply(PhaseSnapshot(state: .connecting, message: nil, level: 0, at: Date(), command: model.unansweredPress)) + case .answerError: + model.apply(PhaseSnapshot(state: .error, message: nil, level: 0, at: Date(), command: model.unansweredPress)) + case .appNotListening: + listening(false) + model.apply(model.snapshot) + case .appListening: + listening(true) + model.apply(model.snapshot) + case .beginTerm: model.beginAddingTerm() + case .cancelTerm: model.cancelAddingTerm() + case .saveTerm: model.saveTerm() + case .typeLetter: model.type(random.pick(["a", "B", "z"])) + case .space: model.space() + case .deleteBack: model.deleteBackward() + case .newline: model.newline() + case .selectWord: + proxy.selected = "Rizz" + model.contextChanged() + case .selectOther: + proxy.selected = random.pick(["Gyatt", "neil bisht", " Rizz "]) + model.contextChanged() + case .clearSelection: + proxy.selected = nil + model.contextChanged() + case .addSelected: model.addSelectedTerm() + case .dismissSelected: model.dismissSelection() + case .flipPanel: model.flipPanel(towardsLeading: random.next() % 2 == 0) + case .toggleSymbols: model.toggleSymbols() + case .toggleMore: model.toggleMore() + case .toggleShift: model.toggleShift() + case .appeared: + model.hasFullAccess = true + model.appeared() + case .appearedNoAccess: + // Without Full Access the keyboard can't reach the app: whatever was + // in flight is the app's to end; the command ledger starts over. + model.hasFullAccess = false + model.appeared() + model.hasFullAccess = true + epoch = true + case .disappeared: model.disappeared() + case .contextChanged: model.contextChanged() + case .resultFresh: + SharedStore.write( + DictationResult(id: UUID(), text: "words", deliveredAt: Date(), recipient: nil), forKey: BlurtShared.Key.result) + model.resultArrived() + case .resultStale: + SharedStore.write( + DictationResult(id: UUID(), text: "old", deliveredAt: Date().addingTimeInterval(-60), recipient: nil), + forKey: BlurtShared.Key.result) + model.resultArrived() + case .resultForOther: + SharedStore.write( + DictationResult(id: UUID(), text: "theirs", deliveredAt: Date(), recipient: "someone-else"), + forKey: BlurtShared.Key.result) + model.resultArrived() + case .hostTyped: + proxy.before += "x" + model.contextChanged() + case .hostMovedCursor: + proxy.before += "ab" + proxy.after = String(proxy.after.dropFirst(2)) + model.contextChanged() + } + } + + /// The events that apply a phase from the app. + static let phaseEvents: Set = [ + .phaseIdle, .phaseConnecting, .phaseRecording, .phaseProcessing, .phasePasted, .phaseCopied, .phaseError, + .answerConnecting, .answerError, .appNotListening, .appListening, + ] + + /// The events after which the term field's shift has just been re-read. + static let reevaluatesShift: Set = [ + .beginTerm, .cancelTerm, .saveTerm, .typeLetter, .space, .deleteBack, .newline, .contextChanged, .selectWord, + .selectOther, .clearSelection, .hostTyped, .hostMovedCursor, .appeared, .appearedNoAccess, + ] + + /// What must be true after every event, whatever came before. + private func check( + _ model: KeyboardModel, _ proxy: FakeProxy, _ commands: Commands, after event: Event, _ context: String + ) { + // The term field's bookkeeping lives and dies with the field. + let fieldOpen = model.termDraft != nil + #expect((model.termHostBaseline != nil) == fieldOpen, "term baseline vs field — \(context)") + #expect((model.termHostBaselineAfter != nil) == fieldOpen, "term baseline-after vs field — \(context)") + #expect(model.termDraftFromSelection == nil || fieldOpen, "seed outlives the field — \(context)") + #expect(!fieldOpen || model.effectiveLayout == .full, "keys must be up for the field — \(context)") + // Shift follows the term as typed; a tap on shift itself overrides it, + // as on the system keyboard, until the next thing that re-reads it. + if let draft = model.termDraft, Self.reevaluatesShift.contains(event) { + #expect(model.shifted == (draft.isEmpty || draft.last == " "), "term shift rule — \(context)") + } + // The chip and its dismissal never both stand. + #expect(model.dismissedSelection == nil || model.selectedTerm == nil, "chip and dismissal both up — \(context)") + if let term = model.selectedTerm { + let candidate = KeyboardModel.termCandidate(from: proxy.selectedText) + #expect(model.hasFullAccess, "chip without Full Access — \(context)") + #expect(candidate?.caseInsensitiveCompare(term) == .orderedSame, "chip for a word not highlighted — \(context)") + if model.selectedTermIsKnown { + #expect( + SharedStore.keyTerms.contains { $0.caseInsensitiveCompare(term) == .orderedSame }, + "known chip for an unknown word — \(context)") + } + } else { + #expect(!model.selectedTermIsKnown, "known without a chip — \(context)") + } + // Pages. + #expect(!model.morePage || model.symbolsPage, "#+= page without the symbols — \(context)") + // The voice picture never shows what the app can't be doing. + let state = model.voiceState + if !state.isReady { + #expect( + !state.isRecording && state.glyph == nil && !state.canCancel, "in-flight picture with no app — \(context)") + } + // A latched gate is either a press of ours the app hasn't settled, or a + // dictation in flight that the app published (started elsewhere, or a + // phase that arrived after our cancel): never a latch over nothing. + if !model.gate.isIdle { + let inFlight = !model.isSettled + #expect(commands.sent.last?.kind == .press || inFlight, "gate latched with no press out — \(context)") + } + #expect(!model.panelShowsKeys || model.layout == .panel, "keys page off the panel — \(context)") + #expect(commands.sent.allSatisfy { $0.keyboard == model.instanceID }, "command from another keyboard — \(context)") + // A result is never left in the store once it was inserted here. + if let pending = SharedStore.read(DictationResult.self, forKey: BlurtShared.Key.result) { + #expect(pending.id != model.lastResultID, "inserted result still in the store — \(context)") + } + } + + @Test("from any state, an appearance is a clean keyboard that can dictate") + func recovers() { + let suite = ScratchSuite() + defer { suite.tearDown() } + var random = Random(state: 42) + let proxy = FakeProxy() + let model = KeyboardModel() + model.proxyOverride = proxy + model.hasFullAccess = true + let commands = Commands() + model.transport = { commands.sent.append($0) } + listening(true) + // Hands-free off: a tap must be the press here, not the stop of one the + // appearance started. + SharedStore.autoDictate = false + model.appeared() + for round in 0..<200 { + for _ in 0..<25 { drive(model, proxy, random.pick(Event.allCases), &random) } + // The keyboard goes away and comes back, the app idle and listening. + model.disappeared() + SharedStore.write(snapshot(.idle), forKey: BlurtShared.Key.phase) + listening(true) + model.hasFullAccess = true + model.appeared() + #expect(model.termDraft == nil, "field open after an appearance (round \(round))") + #expect(!model.panelShowsKeys, "keys page after an appearance (round \(round))") + #expect(model.gate.isIdle, "gate latched after an appearance (round \(round))") + #expect(model.isSettled, "in flight after an appearance (round \(round))") + #expect(model.termSavedAt == nil, "saved check after an appearance (round \(round))") + // And a tap is a press. + let before = commands.sent.count + model.micDown() + model.micUp() + #expect( + commands.sent.count == before + 1 && commands.sent.last?.kind == .press, "tap is not a press (round \(round))") + model.apply(snapshot(.recording)) + model.micDown() + model.micUp() + #expect(commands.sent.last?.kind == .release, "second tap is not a release (round \(round))") + model.apply(snapshot(.pasted)) + model.apply(snapshot(.idle)) + } + } +} diff --git a/App/BlurtiOS/BlurtiOSTests/KeyboardModelGateTests.swift b/App/BlurtiOS/BlurtiOSTests/KeyboardModelGateTests.swift new file mode 100644 index 00000000..3fd30abe --- /dev/null +++ b/App/BlurtiOS/BlurtiOSTests/KeyboardModelGateTests.swift @@ -0,0 +1,135 @@ +import Foundation +import Testing +import UIKit + +@testable import BlurtiOS + +/// The mic key's gate against the app's phases: which phase settles which +/// press, the retry, the sender on every command, and the term field closing +/// a live dictation. +@Suite("Keyboard model: the gate and the app's answers", .serialized) +@MainActor +struct KeyboardModelGateTests { + struct Rig { + let model: KeyboardModel + let proxy: FakeProxy + let commands: Commands + } + + final class Commands { + var sent: [KeyboardCommand] = [] + } + + private func ready() -> Rig { + let proxy = FakeProxy() + let model = KeyboardModel() + model.proxyOverride = proxy + model.hasFullAccess = true + let now = Date() + SharedStore.listeningUntil = now.addingTimeInterval(600) + SharedStore.appSeenAt = now + model.isListening = true + let commands = Commands() + model.transport = { commands.sent.append($0) } + return Rig(model: model, proxy: proxy, commands: commands) + } + + private func snapshot(_ state: PhaseSnapshot.State, level: Double = 0) -> PhaseSnapshot { + PhaseSnapshot(state: state, message: nil, level: level, at: Date()) + } + + @Test("a settled phase resets a latched gate — once it answers the press; an older notice does not") + func resetOnSettled() { + let suite = ScratchSuite() + defer { suite.tearDown() } + let rig = ready() + let model = rig.model + let commands = rig.commands + model.micDown() + model.micUp() + #expect(!model.gate.isIdle) + // The previous dictation's words land a moment after the press: not ours. + model.apply(snapshot(.pasted)) + #expect(!model.gate.isIdle) + // The next tap is still the stop, not a second press. + model.micDown() + model.micUp() + #expect(commands.sent.map(\.kind) == [.press, .release]) + #expect(model.gate.isIdle) + // A phase that answers the press settles it. + model.micDown() + model.micUp() + let press = commands.sent.last?.id + model.apply(PhaseSnapshot(state: .error, message: "no mic", level: 0, at: Date(), command: press)) + #expect(model.gate.isIdle) + // And an in-flight phase answers it too, whatever id it carries. + model.micDown() + model.micUp() + model.apply(snapshot(.connecting)) + #expect(model.unansweredPress == nil) + model.apply(snapshot(.pasted)) + #expect(model.gate.isIdle) + } + + @Test("a command names the keyboard that sent it") + func commandCarriesSender() { + let suite = ScratchSuite() + defer { suite.tearDown() } + let rig = ready() + rig.model.micDown() + rig.model.micUp() + #expect(rig.commands.sent.map(\.keyboard) == [rig.model.instanceID]) + } + + @Test("a press the app never answers is sent again after the retry delay; one it answered is not") + func pressRetried() async throws { + let suite = ScratchSuite() + defer { suite.tearDown() } + let rig = ready() + let model = rig.model + let commands = rig.commands + model.micDown() + model.micUp() + try await Task.sleep(for: KeyboardModel.commandRetryDelay + .milliseconds(300)) + #expect(commands.sent.map(\.kind) == [.press, .press]) + #expect(commands.sent[0].id == commands.sent[1].id) + // Answered: the app published a phase the keyboard reads on the retry. + model.apply(PhaseSnapshot(state: .pasted, message: nil, level: 0, at: Date(), command: model.unansweredPress)) + model.micDown() + model.micUp() + SharedStore.write(snapshot(.recording), forKey: BlurtShared.Key.phase) + try await Task.sleep(for: KeyboardModel.commandRetryDelay + .milliseconds(300)) + #expect(commands.sent.map(\.kind) == [.press, .press, .press]) + #expect(model.snapshot.state == .recording) + } + + @Test( + "opening the key-term field over a live dictation closes it: a recording is released, a mic coming up cancelled") + func termFieldClosesDictation() { + let suite = ScratchSuite() + defer { suite.tearDown() } + let rig = ready() + let model = rig.model + let commands = rig.commands + model.micDown() + model.micUp() + model.apply(snapshot(.recording)) + model.beginAddingTerm() + #expect(commands.sent.map(\.kind) == [.press, .release]) + #expect(model.gate.isIdle) + #expect(model.termDraft == "") + model.cancelAddingTerm() + model.apply(snapshot(.idle)) + model.micDown() + model.micUp() + model.apply(snapshot(.connecting)) + model.beginAddingTerm() + #expect(commands.sent.map(\.kind) == [.press, .release, .press, .cancel]) + #expect(model.gate.isIdle) + // Nothing in flight: the field opens and nothing is sent. + model.cancelAddingTerm() + model.apply(snapshot(.idle)) + model.beginAddingTerm() + #expect(commands.sent.count == 4) + } +} diff --git a/App/BlurtiOS/BlurtiOSTests/KeyboardModelTests.swift b/App/BlurtiOS/BlurtiOSTests/KeyboardModelTests.swift index fea85cf3..99f38369 100644 --- a/App/BlurtiOS/BlurtiOSTests/KeyboardModelTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/KeyboardModelTests.swift @@ -128,10 +128,18 @@ struct KeyboardModelTypingTests { func hardwareTypingClaimed() { let (model, proxy) = model(before: "yo ") model.beginAddingTerm() - proxy.before = "yo Ri" + // A hardware key is one character per change. + proxy.before = "yo R" + model.contextChanged() + proxy.before = "yo i" model.contextChanged() #expect(model.termDraft == "Ri") #expect(proxy.before == "yo ") + // A block landing at once (a paste, the system's dictation) is not typing. + proxy.before = "yo hello" + model.contextChanged() + #expect(model.termDraft == "Ri") + #expect(proxy.before == "yo hello") } @Test("the return key wears the field's word") @@ -206,7 +214,7 @@ struct KeyboardModelTypingTests { #expect(model.selectedTerm == nil) } - @Test("holding the chip opens the field with the word; saving it as it is leaves the chip knowing it") + @Test("holding the chip opens the field with the word; saving puts the + back though the word stays highlighted") func chipToField() { let suite = ScratchSuite() defer { suite.tearDown() } @@ -218,7 +226,134 @@ struct KeyboardModelTypingTests { model.saveTerm() #expect(SharedStore.keyTerms == ["riz"]) #expect(proxy.before == "he said ") - #expect(model.selectedTerm == "riz") + #expect(proxy.selected == "riz") + #expect(model.selectedTerm == nil) + #expect(model.termSavedAt != nil) + // The host still reports the highlight on the next change: no chip. + model.contextChanged() + #expect(model.selectedTerm == nil) + } +} + +@Suite("Keyboard model: the chip and the term field") +struct KeyboardModelChipTests { + private func model(before: String = "", selected: String? = nil) -> (KeyboardModel, FakeProxy) { + let proxy = FakeProxy() + proxy.before = before + proxy.selected = selected + let model = KeyboardModel() + model.proxyOverride = proxy + return (model, proxy) + } + + @Test( + "a tap on a chip for a word Blurt has puts the + back; the chip returns for another word, or the same one again") + func dismissKnownChip() { + let suite = ScratchSuite() + defer { suite.tearDown() } + SharedStore.addKeyTerm("Rizz") + let (model, proxy) = model(before: "he said ", selected: "Rizz") + model.hasFullAccess = true + model.contextChanged() + #expect(model.selectedTerm == "Rizz") + #expect(model.selectedTermIsKnown) + model.addSelectedTerm() + #expect(model.selectedTerm == nil) + #expect(SharedStore.keyTerms == ["Rizz"]) + model.contextChanged() + #expect(model.selectedTerm == nil) + // Another word highlighted: its chip. + proxy.selected = "Gyatt" + model.contextChanged() + #expect(model.selectedTerm == "Gyatt") + #expect(!model.selectedTermIsKnown) + // The highlight cleared and the first word highlighted again: known again. + proxy.selected = nil + model.contextChanged() + proxy.selected = "Rizz" + model.contextChanged() + #expect(model.selectedTerm == "Rizz") + #expect(model.selectedTermIsKnown) + } + + @Test("the + coming back after a term was added from the chip keeps the highlight's word out of the chip") + func dismissAfterAdd() { + let suite = ScratchSuite() + defer { suite.tearDown() } + let (model, _) = model(before: "he said ", selected: "Rizz") + model.hasFullAccess = true + model.contextChanged() + model.addSelectedTerm() + // While the check shows, the chip is still up with it. + #expect(model.selectedTerm == "Rizz") #expect(model.selectedTermIsKnown) + model.dismissSelection() + #expect(model.selectedTerm == nil) + model.contextChanged() + #expect(model.selectedTerm == nil) + } + + @Test("collapsing the highlight the field opened over is not typing: the word stays in the text") + func collapseIsNotTyping() { + let suite = ScratchSuite() + defer { suite.tearDown() } + let (model, proxy) = model(before: "he said ", selected: "Rizz") + proxy.after = " today" + model.hasFullAccess = true + model.contextChanged() + model.beginAddingTerm() + #expect(model.termDraft == "Rizz") + // The user taps at the end of the word: the highlight collapses there. + proxy.selected = nil + proxy.before = "he said Rizz" + model.contextChanged() + #expect(proxy.before == "he said Rizz") + #expect(model.termDraft == "Rizz") + } + + @Test("saving does not replace the word once the cursor has moved off the highlight") + func noReplaceAfterCursorMove() { + let suite = ScratchSuite() + defer { suite.tearDown() } + let (model, proxy) = model(before: "he said ", selected: "riz") + model.hasFullAccess = true + model.contextChanged() + model.beginAddingTerm() + model.type("z") + // The host moved the cursor but still reports the old selection for a moment. + proxy.before = "he said riz and" + model.saveTerm() + #expect(SharedStore.keyTerms == ["rizz"]) + #expect(proxy.before == "he said riz and") + } + + @Test("a key term capitalises after a space too") + func termShift() { + let (model, _) = model() + model.hasFullAccess = true + model.beginAddingTerm() + #expect(model.shifted) + model.type("N") + #expect(!model.shifted) + model.space() + #expect(model.shifted) + model.type("B") + #expect(!model.shifted) + #expect(model.termDraft == "N B") + } + + @Test("123 opens the symbols, #+= the second page, 123 there the first, ABC the letters") + func symbolPages() { + let (model, _) = model() + #expect(!model.symbolsPage && !model.morePage) + model.toggleSymbols() + #expect(model.symbolsPage && !model.morePage) + model.toggleMore() + #expect(model.symbolsPage && model.morePage) + model.toggleMore() + #expect(model.symbolsPage && !model.morePage) + model.toggleMore() + model.toggleSymbols() + #expect(!model.symbolsPage && !model.morePage) } } diff --git a/App/BlurtiOS/BlurtiOSTests/ProtocolTests.swift b/App/BlurtiOS/BlurtiOSTests/ProtocolTests.swift index 8c451d96..e001c542 100644 --- a/App/BlurtiOS/BlurtiOSTests/ProtocolTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/ProtocolTests.swift @@ -75,6 +75,30 @@ struct ProtocolTests { #expect(SharedStore.read(DictationResult.self, forKey: BlurtShared.Key.result) == nil) } + @Test("the words go back to the keyboard that pressed; another keyboard up in its place means the clipboard") + func relayToPresser() async throws { + let suite = ScratchSuite() + defer { suite.tearDown() } + SharedStore.keyboardSeenAt = Date() + SharedStore.keyboardInstance = "kb-2" + UIPasteboard.general.string = "" + let elsewhere = KeyboardRelayInjector(presser: { "kb-1" }) + await #expect(throws: BlurtError.noEditableTarget) { + try await elsewhere.insert("wrong app", after: nil, windowTitle: nil) + } + #expect(UIPasteboard.general.string == "wrong app") + #expect(SharedStore.read(DictationResult.self, forKey: BlurtShared.Key.result) == nil) + let same = KeyboardRelayInjector(presser: { "kb-2" }) + let taker = Task { + try? await Task.sleep(for: .milliseconds(300)) + let pending = SharedStore.read(DictationResult.self, forKey: BlurtShared.Key.result) + SharedStore.remove(forKey: BlurtShared.Key.result) + return pending + } + try await same.insert("right app", after: nil, windowTitle: nil) + #expect(await taker.value?.recipient == "kb-2") + } + @Test("a result taken by the keyboard counts as delivered") func relayDelivered() async throws { let suite = ScratchSuite() @@ -172,18 +196,6 @@ struct KeyboardModelProtocolTests { #expect(model.gate.isIdle) } - @Test("a settled phase resets a latched gate") - func resetOnSettled() { - let suite = ScratchSuite() - defer { suite.tearDown() } - let model = ready().model - model.micDown() - model.micUp() - #expect(!model.gate.isIdle) - model.apply(snapshot(.pasted)) - #expect(model.gate.isIdle) - } - @Test("leaving the screen releases a latched recording and cancels anything earlier") func disappearEndsDictation() { let suite = ScratchSuite() diff --git a/App/BlurtiOS/BlurtiOSTests/VoiceRowLayoutTests.swift b/App/BlurtiOS/BlurtiOSTests/VoiceRowLayoutTests.swift new file mode 100644 index 00000000..e02ba9d7 --- /dev/null +++ b/App/BlurtiOS/BlurtiOSTests/VoiceRowLayoutTests.swift @@ -0,0 +1,132 @@ +import CoreGraphics +import Testing + +@testable import BlurtiOS + +/// The voice row's placement rules (`VoiceRowLayout`), at the iPhone 18 Pro's +/// row of 389 pt unless a case needs another: the mic dead centre or at an +/// edge, the + hanging off it, the chip growing away from it, the pair +/// centring when a chip has no room, and nothing ever negative. +@Suite("Voice row layout") +struct VoiceRowLayoutTests { + private let row: CGFloat = 389 + private let mic: CGFloat = 64 + private let key: CGFloat = 43.333 + private let hit = DesignTokens.Metrics.glyphHit + private let clearance = DesignTokens.Metrics.voicebarAddtermClearance + + private func layout(_ side: VoiceRowLayout.Side, row: CGFloat? = nil) -> VoiceRowLayout { + VoiceRowLayout(rowWidth: row ?? self.row, side: side) + } + + @Test("centred: the mic's centre is the row's; the + hangs a clearance off its trailing edge, the × mirrors it") + func centred() { + let placed = layout(.center).place(micWidth: mic, minMicWidth: key, chip: false) + #expect(!placed.paired) + #expect(placed.micWidth == mic) + #expect(abs(placed.micX + mic / 2 - row / 2) < 0.001) + #expect(placed.addX == placed.micX + mic + clearance) + #expect(placed.addWidth == hit) + #expect(placed.addGrowsTrailing) + #expect(placed.cancelX == placed.micX - clearance - hit) + // The + and the × sit the same distance from the mic on either side. + let plusGap = placed.addX - (placed.micX + mic) + let cancelGap = placed.micX - ((placed.cancelX ?? 0) + hit) + #expect(abs(plusGap - cancelGap) < 0.001) + } + + @Test("centred with a chip: the chip takes everything from the mic to the row's edge, the mic stays put") + func centredChip() { + let plain = layout(.center).place(micWidth: mic, minMicWidth: key, chip: false) + let chip = layout(.center).place(micWidth: mic, minMicWidth: key, chip: true) + #expect(!chip.paired) + #expect(chip.micX == plain.micX) + #expect(chip.addX == plain.addX) + #expect(abs(chip.addX + chip.addWidth - row) < 0.001) + #expect(chip.addWidth >= DesignTokens.Metrics.addtermChipMinWidth) + } + + @Test("the panel's 160 pt grille still leaves a chip its minimum on the iPhone 18 Pro") + func panelChip() { + let placed = layout(.center).place(micWidth: 160, minMicWidth: key, chip: true) + #expect(!placed.paired) + #expect(placed.addWidth >= DesignTokens.Metrics.addtermChipMinWidth) + } + + @Test( + "the slim bar's row cannot hold a chip beside a centred mic: the pair centres, the chip takes what the mic leaves") + func slimBarPairs() { + // The row between the globe, delete and return at the full keyboard's + // widths (191.67), and without the globe (247.5). + for width in [191.667, 247.5] as [CGFloat] { + let placed = layout(.center, row: width).place(micWidth: mic, minMicWidth: key, chip: true) + #expect(placed.paired, "\(width)") + #expect(placed.micWidth == mic) + #expect(abs(placed.addWidth - (width - mic - clearance)) < 0.001) + #expect(placed.addWidth > 0) + } + // The + alone always fits beside the centred mic there. + let plus = layout(.center, row: 191.667).place(micWidth: mic, minMicWidth: key, chip: false) + #expect(!plus.paired) + #expect(plus.addX + plus.addWidth <= 191.667) + } + + @Test("the mic key is never narrower than a key nor wider than the row, and the + never leaves the row") + func clamps() { + let narrow = layout(.center).place(micWidth: 10, minMicWidth: key, chip: false) + #expect(narrow.micWidth == key) + let wide = layout(.center).place(micWidth: 1000, minMicWidth: key, chip: false) + #expect(wide.micWidth == row) + #expect(wide.micX == 0) + #expect(wide.addX + wide.addWidth <= row) + #expect(wide.cancelX == 0) + // A tiny row with a chip: still nothing negative. + let tiny = layout(.center, row: 60).place(micWidth: mic, minMicWidth: key, chip: true) + #expect(tiny.micWidth == 60) + #expect(tiny.addWidth == 0) + #expect(tiny.paired) + } + + @Test("at the leading edge the mic is at the edge and the + on its inner side; a chip grows to the far edge") + func leading() { + let plus = layout(.leading).place(micWidth: mic, minMicWidth: key, chip: false) + #expect(plus.micX == 0) + #expect(plus.addX == mic + clearance) + #expect(plus.addWidth == hit) + #expect(plus.addGrowsTrailing) + #expect(plus.cancelX == nil) + let chip = layout(.leading).place(micWidth: mic, minMicWidth: key, chip: true) + #expect(abs(chip.addX + chip.addWidth - row) < 0.001) + } + + @Test("at the trailing edge the mic is at the edge and the + on its inner side, growing towards the leading edge") + func trailing() { + let plus = layout(.trailing).place(micWidth: mic, minMicWidth: key, chip: false) + #expect(abs(plus.micX + mic - row) < 0.001) + #expect(plus.addWidth == hit) + #expect(abs(plus.addX + hit + clearance - plus.micX) < 0.001) + #expect(!plus.addGrowsTrailing) + #expect(plus.cancelX == nil) + let chip = layout(.trailing).place(micWidth: mic, minMicWidth: key, chip: true) + #expect(chip.addX == 0) + #expect(abs(chip.addWidth + clearance - chip.micX) < 0.001) + } + + @Test("the row's side follows the alignment Settings chose, flipped for a right-to-left language") + func sides() { + #expect(VoiceRow.side(.center, in: .leftToRight) == .center) + #expect(VoiceRow.side(.left, in: .leftToRight) == .leading) + #expect(VoiceRow.side(.right, in: .leftToRight) == .trailing) + #expect(VoiceRow.side(.left, in: .rightToLeft) == .trailing) + #expect(VoiceRow.side(.right, in: .rightToLeft) == .leading) + } + + @Test("the full keyboard's symbol pages: five punctuation keys fill what seven letters do") + func punctuation() { + let geometry = KeyGeometry(rowWidth: row) + let letters = 7 * geometry.letterWidth + 6 * geometry.gap + let punctuation = 5 * geometry.punctuationWidth + 4 * geometry.gap + #expect(abs(letters - punctuation) < 0.001) + #expect(geometry.punctuationWidth > geometry.letterWidth) + } +} diff --git a/App/BlurtiOS/DESIGN.md b/App/BlurtiOS/DESIGN.md index ea4f7e4f..62c6e10f 100644 --- a/App/BlurtiOS/DESIGN.md +++ b/App/BlurtiOS/DESIGN.md @@ -92,6 +92,11 @@ the brand's face. Ten roles each (`BlurtKeyboard/Sources/KeyboardPalette.swift`) **The surface is the host's.** iOS 26 wraps a third-party keyboard in the host app's own rounded keyboard material, inset above and below by about 16 pt, +and the host's traits arrive on their own schedule: the face is read in +`viewWillAppear` and again in `viewIsAppearing`, never from a trait-change +registration — that callback runs inside the host's layout pass, and a model +change made there left the mic element's drawing uncommitted in Messages +(the grille never drew, every time; the probe app never fires it), and nothing the keyboard draws reaches the inset (Apple: working as intended). A painted surface therefore shows a band of the host's grey above it, in every Liquid Glass app. So the surface is **clear** by default @@ -140,9 +145,19 @@ keyboard on a Face ID phone (58 pt), so the globe appears in ours only when ## Keys Flat, one colour, at the iPhone's corner (8); no edge, no drop, no gloss. A -key brightens 15 % while pressed (0.08 s) rather than dimming; the letter -pop-up carries the one shadow on the keyboard, a whisper (12 %, radius 8), -being the one thing that floats. +key brightens 15 % while pressed (0.08 s) rather than dimming — a gesture +state, so a touch the system takes away (a call, the keyboard dismissed +mid-press) unlights it too; the letter pop-up carries the one shadow on the +keyboard, a whisper (12 %, radius 8), being the one thing that floats, and +rises `popup/offset` from the key's top so it overlaps the key and never +leaves the keyboard on the top row. A key acts on release when the finger +barely moved or ended on the key within `tapSlop` (8) of its edges — a thumb +that rolls still types, a swipe that left the key does not +(`KeyboardInteraction.isTap`, tested). Every layout's keys are `KeyGeometry` +widths: 123, globe and delete 43.33, return 92.67, so a key is the same size +on every page. 123 opens the numbers and symbols, #+= the second symbol page +(brackets, currency), 123 there the first, ABC the letters; on the symbol +pages the third row's five punctuation keys fill what seven letters do. Type: the letters are SF Pro at the iPhone's size, and the glyph keys — shift, delete, globe, the +, × and ✓ — SF Symbols, so the keyboard feels native @@ -236,7 +251,16 @@ What is common: the box (`voice/*`), dimming to `opacity/off` when Blurt isn't ready (a tap opens the app), the two glyphs that need saying (a clipboard when the words went there, an exclamation mark on a failure) drawn by `MicControl` over the element, every change fading over `state-fade`, and -the press answering at once. Under Reduce Motion the sheen and the glints +the press answering at once. **The grille is drawn as plain SwiftUI paths, +never a `Canvas`**: a Canvas has its own render surface, and in a keyboard +extension that surface has failed to present three times (asynchronous +first; then in Messages, whose host swaps scenes as the keyboard appears) — +the key was there, the dots were not. The frame is a handful of `Path` +layers, one per colour, with the sheen's lift quantised to four steps. The +two candidates still draw with a Canvas and inherit the risk; they go, or get +the same treatment, when one is picked. The probes check the element's +_pixels_ (`MicPixels`, the share of the key's box that is not the material), +not only its accessibility frame, on appearance and after every return. Under Reduce Motion the sheen and the glints hold still; the level still drives the meter. The home screen draws the same element at home size in the app's face. @@ -245,7 +269,7 @@ element at home size in the app's face. | no Full Access | the note "Allow Full Access in Settings" is the key; a tap opens Blurt | — | | app not listening | the element at `opacity/off`; a tap opens Blurt | — | | idle | at rest, the sheen | — | -| connecting / processing | working | — / light impact on the stop | +| connecting / processing | working; the cancel × only while the app is there to stop it | — / light impact on the stop | | recording | the meter | medium impact | | pasted | the landing glint, the element in green for 1.2 s | success | | copied | the same, with the clipboard glyph, 2 s | success | @@ -254,30 +278,51 @@ element at home size in the app's face. The gesture is `MicPressSequencer` (`KeyboardInteraction.swift`), tested: a press waits 90 ms so a swipe that starts on the key never starts a dictation it must then cancel; a tap quicker than that is still a tap; a swipe past -24 pt cancels the timer, or undoes a press that went out. Finger down and up -drive the engine's `DictationKeyGate`, so a tap latches and a hold is -push-to-talk exactly as on the Mac. +24 pt cancels the timer, or undoes a press that went out; a touch the system +takes away before the timer fires presses nothing. Finger down and up drive +the engine's `DictationKeyGate`, so a tap latches and a hold is push-to-talk +exactly as on the Mac. A release made while the mic is still coming up (the +engine drops one before it records) is held and sent on the first recording +phase, so a short hold over a slow mic still stops. Every phase the app +publishes carries the id of the keyboard command it last took +(`PhaseSnapshot.command`), and the keyboard settles its gate only for a phase +that answers the press it is waiting on — the previous dictation's notice +landing a moment after a new press used to reset the gate and turn the next +tap into a second press instead of the stop. An in-flight phase with +the app gone (killed, the mic taken) reads as idle, a notice is never +replayed once its dwell ran out, and a keyboard that comes up without Full +Access starts from idle with the gate reset. `KeyboardModelFuzzTests` drives +the model through ten thousand random event sequences and checks these +invariants after every one. ## Layouts and their heights (`KeyboardLayout.height`) Side margins 6.5; top 8; under a row of keys 13 (the iPhone's), under the slim bar 8. -| Layout | Rows | Height | -| --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | -| `slimBar` | globe · voice bar · delete · return | 60 | -| `panel` | the voice element, centred — or at an edge for one hand (Settings, below) — (the + top-left; cancel top-right while in flight) · globe · space · delete · return. A two-page carousel: a horizontal swipe flips between the panel and the full keyboard, and it is back to the element each time the keyboard appears. The pages are a strip one page wide (`PanelCarousel`): the other page is set down a page away on the side the finger moved towards and the strip slides, so the two never cross whichever way the flips come; a flip back mid-slide retreats (`PanelCarouselState`, tested). | 216, or 270 when flipped | -| `full` | voice row 44, then the first key row right under it as the iPhone's sits under its suggestions · three letter rows 43 · 123 / globe / space / return | 270 | +| Layout | Rows | Height | +| --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | +| `slimBar` | globe (when the phone draws none) · voice bar · delete · return, at the full keyboard's widths and gap, the keys as tall as the row | 60 | +| `panel` | the voice element, dead centre between the keyboard's top edge and the keys — or at an edge for one hand (Settings, below) — with the + beside it on its centre line and the cancel × mirroring the + on the other side while something is in flight (× · mic · +) · globe · space · delete · return at the full keyboard's widths (43.33 / 92.67), so nothing changes size when the carousel flips. A two-page carousel: a horizontal swipe flips between the panel and the full keyboard, and it is back to the element each time the keyboard appears. The pages are a strip one page wide (`PanelCarousel`): the other page is set down a page away on the side the finger moved towards and the strip slides, so the two never cross whichever way the flips come; a flip back mid-slide retreats (`PanelCarouselState`, tested). | 216, or 270 when flipped | +| `full` | voice row 44, then the first key row right under it as the iPhone's sits under its suggestions · three letter rows 43 · 123 / globe / space / return | 270 | The voice row (`VoiceBar`) is where the system keyboard puts its suggestion -bar: the element dead centre with the + a clearance beside it — an unseen -twin of the + balances the other side, so the + hangs off the element rather -than shifting it (a pair centred as a whole read as off) — or, for one hand, -the element at an edge with the + inside it (One hand, below). The mic key -is as wide as the element _shows_ (`VoiceElementKind.visibleWidth`, tested: -the grille's own width, the ribs asleep or the wave awake, the streak's line -— never the slot's box, which would put the + off at the edge; never -narrower than a key). Or the row is the key-term field. A swipe flips the panel past +bar. One rule places it everywhere (`VoiceRowLayout`, tested; `VoiceRow` +draws it in the bar and the panel): the mic key is what is placed — dead +centre of the row, or at the edge Settings chose — and the add key (the +, +or the chip for a highlighted word) hangs off it a clearance away on its +centre line: on its trailing side in the middle, on its inner side at an +edge, so the mic is always the thing at the edge. A chip grows away from the +mic as far as the row allows; when that is less than `addterm/chip-min-width` +beside a centred mic (the slim bar's row), the mic and the chip centre as a +pair instead, the mic moving over rather than the chip collapsing onto it. +The mic key is as wide as the element _shows_ (`VoiceElementKind.visibleWidth`, +tested: the grille's own width, the ribs asleep or the wave awake, the +streak's line — never the slot's box, which would put the + off at the edge; +never narrower than a key, never wider than the row) and as tall as the row, +so the whole row under the element is the key. The +, × and ✓ are one glyph +key (`GlyphKey`): a `size/glyph` symbol in a `glyph/hit` square, the HIG's +44 pt. Or the row is the key-term field. A swipe flips the panel past 48 pt sideways and more sideways than up or down by 1.5×; a key acts on release and only under 12 pt of travel (`KeyboardInteraction`, tested). The swipe is recognised on the input view itself (`KeyboardViewController`), not @@ -293,42 +338,56 @@ gap, the mic, the space key and the letters, both ways). The most-asked-for thing: Blurt mishears a niche word, and the fix has to take seconds, inside the app you're typing in, never a trip to Settings. Two ways -in, both from the small **+** beside the element (trailing edge of the bar; -top-left corner of the panel). +in, both from the small **+** beside the element, on its centre line, in +every layout. **Highlight a word, tap once.** Select a word (or a short phrase) in your text and the + grows into a chip — the field's shape, a rectangle at 8 pt with a hairline — holding the word, with a green **+** before it (`AddTermKey`, `KeyboardModel.selectedTerm`). One tap adds the word as it stands to Blurt's -key terms; the text is not touched, a success haptic, and the + becomes a ✓ -for 1.2 s. The word stays highlighted and the chip now shows a quiet ✓: Blurt -knows it. A word already in the list shows that ✓ from the start, so -selecting anything tells you whether Blurt has it. The selection is read off -the host field on every change (`selectionDidChange`, `textDidChange`); what -counts as a word is trimmed, one line, at most 48 characters -(`termCandidate`, tested), and only with Full Access, since the list lives in -the App Group. In the bar the chip keeps a 96 pt minimum and the element -gives way to it; in the panel it grows from the corner up to 240 pt, clear of -the cancel ×. **Hold the chip** (0.4 s) to open the field with the word in it -instead — for the case below. +key terms; the text is not touched, a success haptic, and the chip shows ✓ +for 1.2 s — then gives way to the + even though the host may keep the word +highlighted for as long as you leave it (a chip that stayed with the +highlight read as stuck; `dismissedSelection`, tested). Only that word's +chip: another word highlighted within the 1.2 s keeps its own. A word already in the +list shows a quiet ✓ from the start, so selecting anything tells you whether +Blurt has it; a tap on that ✓ puts the + back. Highlight another word and +the chip is back for it. The selection is read off the host field on every +change (`selectionDidChange`, `textDidChange`); what counts as a word is +trimmed, one line, at most 48 characters (`termCandidate`, tested), and only +with Full Access, since the list lives in the App Group. The chip grows away +from the mic to the row's edge (`VoiceRowLayout`, above). **Hold the chip** +(0.6 s, the system's long press, so a touch the system takes away never +opens it) to open the field with the word in it instead — for the case +below. **Type it.** Tap the + with nothing selected (or hold the chip) and the bar becomes a field — × · what you type · ✓ — pre-filled with the selection if there was one, and the keys type into it (the panel and slim bar flip to the -letter keys for it). Shift is on for the first letter. Type the right +letter keys for it). The field takes the mic key's row, so a dictation in +flight is closed first rather than running on with no key to stop it: from +the plain + a recording is released and the words still land; from a +highlighted word it is cancelled, since a result replaces the selection and +would land over the very word being fixed (tested). Shift is on for the first letter and after a space. Type the right spelling; return or ✓ saves. The term goes into Blurt's key terms (`BlurtKeyTerms` in the App Group, `KeyTermList` rules: trimmed, deduplicated case-insensitively) and rides `keyterms_prompt` on the very next dictation. If it began as a selection and you changed it, the misheard word in your text is -replaced with what you typed. A success haptic, and the + shows a check for -1.2 s. +replaced with what you typed — only while that highlight still stands where +it was (a host can report a selection a moment after the cursor moved, and +inserting then would put the word in twice). A success haptic, and the + +shows a check for 1.2 s. × or an empty save leaves the mode, and so does the keyboard going away. A hardware keyboard types past the on-screen keys into the app's field; while the term field is open a short run that appears there right after where the -cursor was is moved into the term and taken back out of the field. The list -itself is edited in Settings → Transcription, which shows the count against -the request's cap of 100 terms. +cursor was is moved into the term and taken back out of the field — one +character at a time, as a key types; a block (a paste, the system's own +dictation under the keyboard) is never typing and stays — and never when the +field opened over a highlighted word, since collapsing that highlight grows +the text before the cursor by exactly the word (tested). The +list itself is edited in Settings → Transcription, which shows the count +against the request's cap of 100 terms. ## Sharing key terms @@ -367,12 +426,11 @@ Settings → Keyboard, under the layout, the same three-segment shape with a line beneath: **Left alignment · Default · Right alignment** (`MicAlignment`, `micAlignment` in the App Group, read on every appearance like the layout). Default is the middle, as everywhere above. At an edge the mic key is the -thing at the edge. In the bar and the slim bar the pair slides there and the -add key (+) moves to the mic's inner side, so at the right edge it comes -first. The panel becomes a big voice bar: the element sits at the edge as -wide as it _shows_ (`visibleWidth`, so the grille is under the thumb, not an -empty half of its 300 pt box), the add key beside it on its inner side rather -than in the corner, and cancel in the far top corner, clear of them both. +thing at the edge, in every layout (`VoiceRowLayout`): the element sits at +the edge as wide as it _shows_ (`visibleWidth`, so the grille is under the +thumb, not an empty half of its box), the add key beside it on its inner +side, and — in the panel — cancel in the far top corner, clear of them both, +where in the middle it mirrors the + on the mic's other side. Left and right are the phone's sides: in a right-to-left language the leading/trailing mapping flips so the mic stays under the thumb chosen (`Shared/MicAlignment.swift`, tested). Gallery: `-BlurtGalleryAlign @@ -481,10 +539,9 @@ pins the derivation. | Token | Points | Swift | Use | | ---------------------------- | --------- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `addterm/chip-gap` | `6` | `Metrics.addtermChipGap` | between the chip's glyph and the word | -| `addterm/chip-max-width` | `240` | `Metrics.addtermChipMaxWidth` | the most the chip may take in the panel's corner, clear of the cancel × | -| `addterm/chip-min-width` | `96` | `Metrics.addtermChipMinWidth` | the room the voice bar keeps for the chip; the element gives way beyond it | +| `addterm/chip-min-width` | `96` | `Metrics.addtermChipMinWidth` | the least room a chip needs beside a centred mic; with less, the mic and the chip centre as a pair | | `addterm/chip-pad` | `10` | `Metrics.addtermChipPad` | the selected-word chip's side padding | -| `addterm/inset` | `6` | `Metrics.addtermInset` | the + from the panel's corner | +| `addterm/inset` | `6` | `Metrics.addtermInset` | the cancel × from the panel's far corner when the mic is at an edge | | `app/button-height` | `40` | `Metrics.appButtonHeight` | the brand's button | | `app/button-pad` | `12` | `Metrics.appButtonPad` | its side padding | | `app/card-pad` | `16` | `Metrics.appCardPad` | inside a card | @@ -507,7 +564,7 @@ pins the derivation. | `caret/lead` | `1` | `Metrics.caretLead` | the caret's gap from the text | | `caret/radius` | `1` | `Metrics.caretRadius` | — | | `caret/width` | `2` | `Metrics.caretWidth` | — | -| `glyph/hit` | `32` | `Metrics.glyphHit` | the +, × and ✓ touch targets | +| `glyph/hit` | `44` | `Metrics.glyphHit` | the +, × and ✓ touch targets: the HIG's 44 pt square around a size/glyph symbol | | `grille/bar-height` | `28` | `Metrics.grilleBarHeight` | — | | `grille/bar-width` | `64` | `Metrics.grilleBarWidth` | the grille in the voice bar | | `grille/dot` | `2` | `Metrics.grilleDot` | a dot's diameter | @@ -553,13 +610,13 @@ pins the derivation. | `opacity/sheen` | `0.22` | `Metrics.opacitySheen` | the light passing over the element at rest: chrome catching light | | `opacity/surface-vignette` | `0` | `Metrics.opacitySurfaceVignette` | a soft darkening toward the surface's edges; 0 is none | | `opacity/term-cancel` | `0.7` | `Metrics.opacityTermCancel` | the field's × | -| `panel/spacing` | `12` | `Metrics.panelSpacing` | between the panel's orb and its key row | +| `panel/spacing` | `8` | `Metrics.panelSpacing` | under the panel's voice row, above its keys: the top margin again, so the mic is centred between the keyboard's top edge and the keys | | `picker/preview-width` | `393` | `Metrics.pickerPreviewWidth` | the theme card draws the keyboard at this width | | `picker/radius` | `10` | `Metrics.pickerRadius` | the theme card's preview corners | | `picker/scale` | `0.42` | `Metrics.pickerScale` | then scales it to fit two across | | `popup/extra-width` | `18` | `Metrics.popupExtraWidth` | the letter pop-up is the key width plus this | | `popup/height` | `56` | `Metrics.popupHeight` | — | -| `popup/offset` | `58` | `Metrics.popupOffset` | the pop-up sits this far above the key | +| `popup/offset` | `50` | `Metrics.popupOffset` | the pop-up rises this far from the key's top: it overlaps the key by popup/height minus this and stays inside the keyboard on the top row | | `popup/radius` | `10` | `Metrics.popupRadius` | — | | `popup/shadow-radius` | `8` | `Metrics.popupShadowRadius` | the one thing that floats | | `popup/shadow-y` | `2` | `Metrics.popupShadowY` | — | @@ -570,7 +627,6 @@ pins the derivation. | `ribs/rest-height` | `16` | `Metrics.ribsRestHeight` | — | | `ribs/rest-width` | `40` | `Metrics.ribsRestWidth` | the ribs asleep: the wave's own bars at rest | | `row/gap` | `11` | `Metrics.rowGap` | between rows, the iPhone's | -| `slim/spacing` | `8` | `Metrics.slimSpacing` | between the slim bar's keys | | `streak/arm` | `1.4` | `Metrics.streakArm` | the landing flash's vertical arm, as a fraction of the box's height | | `streak/height` | `2` | `Metrics.streakHeight` | the light streak while recording | | `streak/line` | `1` | `Metrics.streakLine` | the hairline at rest | @@ -591,7 +647,7 @@ pins the derivation. | `voice/panel-height` | `88` | `Metrics.voicePanelHeight` | — | | `voice/panel-width` | `300` | `Metrics.voicePanelWidth` | the box in the panel | | `voice/press-scale` | `0.94` | `Metrics.voicePressScale` | the element while pressed | -| `voicebar/addterm-clearance` | `12` | `Metrics.voicebarAddtermClearance` | between the element and the + | +| `voicebar/addterm-clearance` | `6` | `Metrics.voicebarAddtermClearance` | between the mic key's edge and the add key's box (the + or the chip), the key gap | | `voicebar/height` | `44` | `Metrics.voicebarHeight` | the voice row, where the system puts its suggestion bar | | `voicebar/note-gap` | `10` | `Metrics.voicebarNoteGap` | between the orb and the Full Access note | | `wave/bar` | `2` | `Metrics.waveBar` | a wave bar's width | @@ -609,24 +665,24 @@ house curve (`ease/signature`, `cubic-bezier(0.22, 1, 0.36, 1)`). -| Token | Value | Swift | Use | -| ---------------- | --------------- | ---------------------- | ------------------------------------------------------------- | -| `caret` | `0.5` | `Motion.caret` | the caret's blink | -| `chip-hold` | `0.4` | `Motion.chipHold` | holding the chip opens the field instead of adding | -| `colour` | `0.2` | `Motion.colour` | a colour or fill changing state: the brand's transition | -| `ease/signature` | `0.22,1,0.36,1` | `Motion.easeSignature` | the house curve for everything that moves; nothing springs | -| `flip` | `0.25` | `Motion.flip` | the panel's carousel | -| `glint-life` | `0.5` | `Motion.glintLife` | a facet's flash while recording | -| `height-change` | `0.25` | `Motion.heightChange` | the keyboard resizing | -| `key-press` | `0.08` | `Motion.keyPress` | a key lighting | -| `landing` | `0.6` | `Motion.landing` | the glint when the words land | -| `press` | `0.1` | `Motion.press` | the orb's press; the one thing that answers at once | -| `ring-period` | `1.6` | `Motion.ringPeriod` | one turn of the ring, the Mac's cadence | -| `sheen` | `4` | `Motion.sheen` | one pass of the light over the element at rest | -| `sheen-working` | `1.6` | `Motion.sheenWorking` | and while something is happening: the ring's cadence | -| `state-fade` | `0.5` | `Motion.stateFade` | every other change on the key: the ring, a glyph, the dimming | -| `term-swap` | `0.4` | `Motion.termSwap` | the voice bar becoming the field | -| `wave-fade` | `0.7` | `Motion.waveFade` | the orb and the wave crossing, either way | +| Token | Value | Swift | Use | +| ---------------- | --------------- | ---------------------- | -------------------------------------------------------------------------- | +| `caret` | `0.5` | `Motion.caret` | the caret's blink | +| `chip-hold` | `0.6` | `Motion.chipHold` | holding the chip opens the field instead of adding; longer than a firm tap | +| `colour` | `0.2` | `Motion.colour` | a colour or fill changing state: the brand's transition | +| `ease/signature` | `0.22,1,0.36,1` | `Motion.easeSignature` | the house curve for everything that moves; nothing springs | +| `flip` | `0.25` | `Motion.flip` | the panel's carousel | +| `glint-life` | `0.5` | `Motion.glintLife` | a facet's flash while recording | +| `height-change` | `0.25` | `Motion.heightChange` | the keyboard resizing | +| `key-press` | `0.08` | `Motion.keyPress` | a key lighting | +| `landing` | `0.6` | `Motion.landing` | the glint when the words land | +| `press` | `0.1` | `Motion.press` | the orb's press; the one thing that answers at once | +| `ring-period` | `1.6` | `Motion.ringPeriod` | one turn of the ring, the Mac's cadence | +| `sheen` | `4` | `Motion.sheen` | one pass of the light over the element at rest | +| `sheen-working` | `1.6` | `Motion.sheenWorking` | and while something is happening: the ring's cadence | +| `state-fade` | `0.5` | `Motion.stateFade` | every other change on the key: the ring, a glyph, the dimming | +| `term-swap` | `0.4` | `Motion.termSwap` | the voice bar becoming the field | +| `wave-fade` | `0.7` | `Motion.waveFade` | the orb and the wave crossing, either way | diff --git a/App/BlurtiOS/Design/figma/tokens.js b/App/BlurtiOS/Design/figma/tokens.js index dba47c57..eeb9ff25 100644 --- a/App/BlurtiOS/Design/figma/tokens.js +++ b/App/BlurtiOS/Design/figma/tokens.js @@ -94,10 +94,9 @@ Keyboard|kb/popup|COLOR|#33302A|Themes:dark/popup|FRAME_FILL,SHAPE_FILL|DesignTo Keyboard|kb/signal|COLOR|#67AD82|Themes:dark/signal|SHAPE_FILL,TEXT_FILL|DesignTokens.Keyboard.kbSignal|the wave, the caret, the saved check Keyboard|kb/surface|COLOR|#1D1B16|Themes:dark/surface|FRAME_FILL,SHAPE_FILL|DesignTokens.Keyboard.kbSurface|the design face's surface (Figma binds to kb/*; Swift reads the palette) Metrics|addterm/chip-gap|FLOAT|6||GAP|DesignTokens.Metrics.addtermChipGap|between the chip's glyph and the word -Metrics|addterm/chip-max-width|FLOAT|240||WIDTH_HEIGHT|DesignTokens.Metrics.addtermChipMaxWidth|the most the chip may take in the panel's corner, clear of the cancel × -Metrics|addterm/chip-min-width|FLOAT|96||WIDTH_HEIGHT|DesignTokens.Metrics.addtermChipMinWidth|the room the voice bar keeps for the chip; the element gives way beyond it +Metrics|addterm/chip-min-width|FLOAT|96||WIDTH_HEIGHT|DesignTokens.Metrics.addtermChipMinWidth|the least room a chip needs beside a centred mic; with less, the mic and the chip centre as a pair Metrics|addterm/chip-pad|FLOAT|10||WIDTH_HEIGHT|DesignTokens.Metrics.addtermChipPad|the selected-word chip's side padding -Metrics|addterm/inset|FLOAT|6||GAP|DesignTokens.Metrics.addtermInset|the + from the panel's corner +Metrics|addterm/inset|FLOAT|6||GAP|DesignTokens.Metrics.addtermInset|the cancel × from the panel's far corner when the mic is at an edge Metrics|app/button-height|FLOAT|40||WIDTH_HEIGHT|DesignTokens.Metrics.appButtonHeight|the brand's button Metrics|app/button-pad|FLOAT|12||WIDTH_HEIGHT|DesignTokens.Metrics.appButtonPad|its side padding Metrics|app/card-pad|FLOAT|16||WIDTH_HEIGHT|DesignTokens.Metrics.appCardPad|inside a card @@ -120,7 +119,7 @@ Metrics|caret/height|FLOAT|20||WIDTH_HEIGHT|DesignTokens.Metrics.caretHeight| Metrics|caret/lead|FLOAT|1||GAP|DesignTokens.Metrics.caretLead|the caret's gap from the text Metrics|caret/radius|FLOAT|1||CORNER_RADIUS|DesignTokens.Metrics.caretRadius| Metrics|caret/width|FLOAT|2||STROKE_FLOAT,WIDTH_HEIGHT|DesignTokens.Metrics.caretWidth| -Metrics|glyph/hit|FLOAT|32||WIDTH_HEIGHT|DesignTokens.Metrics.glyphHit|the +, × and ✓ touch targets +Metrics|glyph/hit|FLOAT|44||WIDTH_HEIGHT|DesignTokens.Metrics.glyphHit|the +, × and ✓ touch targets: the HIG's 44 pt square around a size/glyph symbol Metrics|grille/bar-height|FLOAT|28||WIDTH_HEIGHT|DesignTokens.Metrics.grilleBarHeight| Metrics|grille/bar-width|FLOAT|64||WIDTH_HEIGHT|DesignTokens.Metrics.grilleBarWidth|the grille in the voice bar Metrics|grille/dot|FLOAT|2||WIDTH_HEIGHT|DesignTokens.Metrics.grilleDot|a dot's diameter @@ -166,13 +165,13 @@ Metrics|opacity/pressed|FLOAT|0.85||OPACITY|DesignTokens.Metrics.opacityPressed| Metrics|opacity/sheen|FLOAT|0.22||OPACITY|DesignTokens.Metrics.opacitySheen|the light passing over the element at rest: chrome catching light Metrics|opacity/surface-vignette|FLOAT|0||OPACITY|DesignTokens.Metrics.opacitySurfaceVignette|a soft darkening toward the surface's edges; 0 is none Metrics|opacity/term-cancel|FLOAT|0.7||OPACITY|DesignTokens.Metrics.opacityTermCancel|the field's × -Metrics|panel/spacing|FLOAT|12||GAP|DesignTokens.Metrics.panelSpacing|between the panel's orb and its key row +Metrics|panel/spacing|FLOAT|8||GAP|DesignTokens.Metrics.panelSpacing|under the panel's voice row, above its keys: the top margin again, so the mic is centred between the keyboard's top edge and the keys Metrics|picker/preview-width|FLOAT|393||WIDTH_HEIGHT|DesignTokens.Metrics.pickerPreviewWidth|the theme card draws the keyboard at this width Metrics|picker/radius|FLOAT|10||CORNER_RADIUS|DesignTokens.Metrics.pickerRadius|the theme card's preview corners Metrics|picker/scale|FLOAT|0.42|||DesignTokens.Metrics.pickerScale|then scales it to fit two across Metrics|popup/extra-width|FLOAT|18||WIDTH_HEIGHT|DesignTokens.Metrics.popupExtraWidth|the letter pop-up is the key width plus this Metrics|popup/height|FLOAT|56||WIDTH_HEIGHT|DesignTokens.Metrics.popupHeight| -Metrics|popup/offset|FLOAT|58||WIDTH_HEIGHT|DesignTokens.Metrics.popupOffset|the pop-up sits this far above the key +Metrics|popup/offset|FLOAT|50||WIDTH_HEIGHT|DesignTokens.Metrics.popupOffset|the pop-up rises this far from the key's top: it overlaps the key by popup/height minus this and stays inside the keyboard on the top row Metrics|popup/radius|FLOAT|10||CORNER_RADIUS|DesignTokens.Metrics.popupRadius| Metrics|popup/shadow-radius|FLOAT|8||WIDTH_HEIGHT|DesignTokens.Metrics.popupShadowRadius|the one thing that floats Metrics|popup/shadow-y|FLOAT|2||WIDTH_HEIGHT|DesignTokens.Metrics.popupShadowY| @@ -183,7 +182,6 @@ Metrics|radius/input|FLOAT|8||WIDTH_HEIGHT|DesignTokens.Metrics.radiusInput|the Metrics|ribs/rest-height|FLOAT|16||WIDTH_HEIGHT|DesignTokens.Metrics.ribsRestHeight| Metrics|ribs/rest-width|FLOAT|40||WIDTH_HEIGHT|DesignTokens.Metrics.ribsRestWidth|the ribs asleep: the wave's own bars at rest Metrics|row/gap|FLOAT|11||GAP|DesignTokens.Metrics.rowGap|between rows, the iPhone's -Metrics|slim/spacing|FLOAT|8||GAP|DesignTokens.Metrics.slimSpacing|between the slim bar's keys Metrics|streak/arm|FLOAT|1.4||WIDTH_HEIGHT|DesignTokens.Metrics.streakArm|the landing flash's vertical arm, as a fraction of the box's height Metrics|streak/height|FLOAT|2||WIDTH_HEIGHT|DesignTokens.Metrics.streakHeight|the light streak while recording Metrics|streak/line|FLOAT|1||WIDTH_HEIGHT|DesignTokens.Metrics.streakLine|the hairline at rest @@ -204,7 +202,7 @@ Metrics|voice/home-width|FLOAT|280||WIDTH_HEIGHT|DesignTokens.Metrics.voiceHomeW Metrics|voice/panel-height|FLOAT|88||WIDTH_HEIGHT|DesignTokens.Metrics.voicePanelHeight| Metrics|voice/panel-width|FLOAT|300||WIDTH_HEIGHT|DesignTokens.Metrics.voicePanelWidth|the box in the panel Metrics|voice/press-scale|FLOAT|0.94||WIDTH_HEIGHT|DesignTokens.Metrics.voicePressScale|the element while pressed -Metrics|voicebar/addterm-clearance|FLOAT|12||GAP|DesignTokens.Metrics.voicebarAddtermClearance|between the element and the + +Metrics|voicebar/addterm-clearance|FLOAT|6||GAP|DesignTokens.Metrics.voicebarAddtermClearance|between the mic key's edge and the add key's box (the + or the chip), the key gap Metrics|voicebar/height|FLOAT|44||WIDTH_HEIGHT|DesignTokens.Metrics.voicebarHeight|the voice row, where the system puts its suggestion bar Metrics|voicebar/note-gap|FLOAT|10||GAP|DesignTokens.Metrics.voicebarNoteGap|between the orb and the Full Access note Metrics|wave/bar|FLOAT|2||STROKE_FLOAT,WIDTH_HEIGHT|DesignTokens.Metrics.waveBar|a wave bar's width @@ -235,7 +233,7 @@ Typography|weight/popup|STRING|regular||FONT_STYLE|DesignTokens.Typography.weigh Typography|weight/term|STRING|regular||FONT_STYLE|DesignTokens.Typography.weightTerm| Typography|weight/voice-glyph|STRING|semibold||FONT_STYLE|DesignTokens.Typography.weightVoiceGlyph| Motion|caret|FLOAT|0.5|||DesignTokens.Motion.caret|the caret's blink -Motion|chip-hold|FLOAT|0.4|||DesignTokens.Motion.chipHold|holding the chip opens the field instead of adding +Motion|chip-hold|FLOAT|0.6|||DesignTokens.Motion.chipHold|holding the chip opens the field instead of adding; longer than a firm tap Motion|colour|FLOAT|0.2|||DesignTokens.Motion.colour|a colour or fill changing state: the brand's transition Motion|ease/signature|STRING|0.22,1,0.36,1|||DesignTokens.Motion.easeSignature|the house curve for everything that moves; nothing springs Motion|flip|FLOAT|0.25|||DesignTokens.Motion.flip|the panel's carousel diff --git a/App/BlurtiOS/Design/tokens.json b/App/BlurtiOS/Design/tokens.json index 37f833f1..3a396b78 100644 --- a/App/BlurtiOS/Design/tokens.json +++ b/App/BlurtiOS/Design/tokens.json @@ -346,8 +346,8 @@ "use": "between the orb and the Full Access note" }, "voicebar/addterm-clearance": { - "value": 12, - "use": "between the element and the +" + "value": 6, + "use": "between the mic key's edge and the add key's box (the + or the chip), the key gap" }, "wave/bar-height": { "value": 24 @@ -377,8 +377,8 @@ "value": 10 }, "popup/offset": { - "value": 58, - "use": "the pop-up sits this far above the key" + "value": 50, + "use": "the pop-up rises this far from the key's top: it overlaps the key by popup/height minus this and stays inside the keyboard on the top row" }, "popup/shadow-radius": { "value": 8, @@ -417,20 +417,16 @@ "use": "the caret's gap from the text" }, "glyph/hit": { - "value": 32, - "use": "the +, × and ✓ touch targets" - }, - "slim/spacing": { - "value": 8, - "use": "between the slim bar's keys" + "value": 44, + "use": "the +, × and ✓ touch targets: the HIG's 44 pt square around a size/glyph symbol" }, "panel/spacing": { - "value": 12, - "use": "between the panel's orb and its key row" + "value": 8, + "use": "under the panel's voice row, above its keys: the top margin again, so the mic is centred between the keyboard's top edge and the keys" }, "addterm/inset": { "value": 6, - "use": "the + from the panel's corner" + "use": "the cancel × from the panel's far corner when the mic is at an edge" }, "addterm/chip-pad": { "value": 10, @@ -442,11 +438,7 @@ }, "addterm/chip-min-width": { "value": 96, - "use": "the room the voice bar keeps for the chip; the element gives way beyond it" - }, - "addterm/chip-max-width": { - "value": 240, - "use": "the most the chip may take in the panel's corner, clear of the cancel ×" + "use": "the least room a chip needs beside a centred mic; with less, the mic and the chip centre as a pair" }, "card/radius": { "value": 12, @@ -852,8 +844,8 @@ "use": "the voice bar becoming the field" }, "chip-hold": { - "value": 0.4, - "use": "holding the chip opens the field instead of adding" + "value": 0.6, + "use": "holding the chip opens the field instead of adding; longer than a firm tap" }, "press": { "value": 0.1, @@ -888,12 +880,7 @@ "use": "the glint when the words land" }, "ease/signature": { - "value": [ - 0.22, - 1, - 0.36, - 1 - ], + "value": [0.22, 1, 0.36, 1], "use": "the house curve for everything that moves; nothing springs" }, "sheen": { diff --git a/App/BlurtiOS/Shared/DesignTokens.swift b/App/BlurtiOS/Shared/DesignTokens.swift index bbdf556c..0c8b9a75 100644 --- a/App/BlurtiOS/Shared/DesignTokens.swift +++ b/App/BlurtiOS/Shared/DesignTokens.swift @@ -203,13 +203,11 @@ enum DesignTokens { enum Metrics { /// Between the chip's glyph and the word. nonisolated static let addtermChipGap: CGFloat = 6 - /// The most the chip may take in the panel's corner, clear of the cancel ×. - nonisolated static let addtermChipMaxWidth: CGFloat = 240 - /// The room the voice bar keeps for the chip; the element gives way beyond it. + /// The least room a chip needs beside a centred mic; with less, the mic and the chip centre as a pair. nonisolated static let addtermChipMinWidth: CGFloat = 96 /// The selected-word chip's side padding. nonisolated static let addtermChipPad: CGFloat = 10 - /// The + from the panel's corner. + /// The cancel × from the panel's far corner when the mic is at an edge. nonisolated static let addtermInset: CGFloat = 6 /// The brand's button. nonisolated static let appButtonHeight: CGFloat = 40 @@ -252,8 +250,8 @@ enum DesignTokens { nonisolated static let caretLead: CGFloat = 1 nonisolated static let caretRadius: CGFloat = 1 nonisolated static let caretWidth: CGFloat = 2 - /// The +, × and ✓ touch targets. - nonisolated static let glyphHit: CGFloat = 32 + /// The +, × and ✓ touch targets: the HIG's 44 pt square around a size/glyph symbol. + nonisolated static let glyphHit: CGFloat = 44 nonisolated static let grilleBarHeight: CGFloat = 28 /// The grille in the voice bar. nonisolated static let grilleBarWidth: CGFloat = 64 @@ -339,8 +337,8 @@ enum DesignTokens { nonisolated static let opacitySurfaceVignette: CGFloat = 0 /// The field's ×. nonisolated static let opacityTermCancel: CGFloat = 0.7 - /// Between the panel's orb and its key row. - nonisolated static let panelSpacing: CGFloat = 12 + /// Under the panel's voice row, above its keys: the top margin again, so the mic is centred between the keyboard's top edge and the keys. + nonisolated static let panelSpacing: CGFloat = 8 /// The theme card draws the keyboard at this width. nonisolated static let pickerPreviewWidth: CGFloat = 393 /// The theme card's preview corners. @@ -350,8 +348,8 @@ enum DesignTokens { /// The letter pop-up is the key width plus this. nonisolated static let popupExtraWidth: CGFloat = 18 nonisolated static let popupHeight: CGFloat = 56 - /// The pop-up sits this far above the key. - nonisolated static let popupOffset: CGFloat = 58 + /// The pop-up rises this far from the key's top: it overlaps the key by popup/height minus this and stays inside the keyboard on the top row. + nonisolated static let popupOffset: CGFloat = 50 nonisolated static let popupRadius: CGFloat = 10 /// The one thing that floats. nonisolated static let popupShadowRadius: CGFloat = 8 @@ -369,8 +367,6 @@ enum DesignTokens { nonisolated static let ribsRestWidth: CGFloat = 40 /// Between rows, the iPhone's. nonisolated static let rowGap: CGFloat = 11 - /// Between the slim bar's keys. - nonisolated static let slimSpacing: CGFloat = 8 /// The landing flash's vertical arm, as a fraction of the box's height. nonisolated static let streakArm: CGFloat = 1.4 /// The light streak while recording. @@ -408,8 +404,8 @@ enum DesignTokens { nonisolated static let voicePanelWidth: CGFloat = 300 /// The element while pressed. nonisolated static let voicePressScale: CGFloat = 0.94 - /// Between the element and the +. - nonisolated static let voicebarAddtermClearance: CGFloat = 12 + /// Between the mic key's edge and the add key's box (the + or the chip), the key gap. + nonisolated static let voicebarAddtermClearance: CGFloat = 6 /// The voice row, where the system puts its suggestion bar. nonisolated static let voicebarHeight: CGFloat = 44 /// Between the orb and the Full Access note. @@ -465,8 +461,8 @@ enum DesignTokens { enum Motion { /// The caret's blink. nonisolated static let caret: Double = 0.5 - /// Holding the chip opens the field instead of adding. - nonisolated static let chipHold: Double = 0.4 + /// Holding the chip opens the field instead of adding; longer than a firm tap. + nonisolated static let chipHold: Double = 0.6 /// A colour or fill changing state: the brand's transition. nonisolated static let colour: Double = 0.2 /// The house curve for everything that moves; nothing springs. @@ -611,7 +607,6 @@ enum DesignTokens { "keyboard.kb/signal": "#67AD82", "keyboard.kb/surface": "#1D1B16", "metrics.addterm/chip-gap": "6", - "metrics.addterm/chip-max-width": "240", "metrics.addterm/chip-min-width": "96", "metrics.addterm/chip-pad": "10", "metrics.addterm/inset": "6", @@ -637,7 +632,7 @@ enum DesignTokens { "metrics.caret/lead": "1", "metrics.caret/radius": "1", "metrics.caret/width": "2", - "metrics.glyph/hit": "32", + "metrics.glyph/hit": "44", "metrics.grille/bar-height": "28", "metrics.grille/bar-width": "64", "metrics.grille/dot": "2", @@ -683,13 +678,13 @@ enum DesignTokens { "metrics.opacity/sheen": "0.22", "metrics.opacity/surface-vignette": "0", "metrics.opacity/term-cancel": "0.7", - "metrics.panel/spacing": "12", + "metrics.panel/spacing": "8", "metrics.picker/preview-width": "393", "metrics.picker/radius": "10", "metrics.picker/scale": "0.42", "metrics.popup/extra-width": "18", "metrics.popup/height": "56", - "metrics.popup/offset": "58", + "metrics.popup/offset": "50", "metrics.popup/radius": "10", "metrics.popup/shadow-radius": "8", "metrics.popup/shadow-y": "2", @@ -700,7 +695,6 @@ enum DesignTokens { "metrics.ribs/rest-height": "16", "metrics.ribs/rest-width": "40", "metrics.row/gap": "11", - "metrics.slim/spacing": "8", "metrics.streak/arm": "1.4", "metrics.streak/height": "2", "metrics.streak/line": "1", @@ -721,7 +715,7 @@ enum DesignTokens { "metrics.voice/panel-height": "88", "metrics.voice/panel-width": "300", "metrics.voice/press-scale": "0.94", - "metrics.voicebar/addterm-clearance": "12", + "metrics.voicebar/addterm-clearance": "6", "metrics.voicebar/height": "44", "metrics.voicebar/note-gap": "10", "metrics.wave/bar": "2", @@ -752,7 +746,7 @@ enum DesignTokens { "type.weight/term": "regular", "type.weight/voice-glyph": "semibold", "motion.caret": "0.5", - "motion.chip-hold": "0.4", + "motion.chip-hold": "0.6", "motion.colour": "0.2", "motion.ease/signature": "0.22,1,0.36,1", "motion.flip": "0.25", diff --git a/App/BlurtiOS/Shared/KeyTermList.swift b/App/BlurtiOS/Shared/KeyTermList.swift new file mode 100644 index 00000000..47c3c860 --- /dev/null +++ b/App/BlurtiOS/Shared/KeyTermList.swift @@ -0,0 +1,21 @@ +import Foundation + +/// The comma-separated key-term list, as the engine's `KeyTermsStore` reads +/// it: split, trimmed, emptied of blanks, deduplicated case-insensitively in +/// first-seen order. +nonisolated enum KeyTermList { + static func parse(_ raw: String) -> [String] { + var seen = Set() + var terms: [String] = [] + for piece in raw.split(separator: ",") { + let term = piece.trimmingCharacters(in: .whitespacesAndNewlines) + guard !term.isEmpty, seen.insert(term.lowercased()).inserted else { continue } + terms.append(term) + } + return terms + } + + static func join(_ terms: [String]) -> String { + terms.joined(separator: ", ") + } +} diff --git a/App/BlurtiOS/Shared/SharedState.swift b/App/BlurtiOS/Shared/SharedState.swift index 1c25e54d..cafe6a82 100644 --- a/App/BlurtiOS/Shared/SharedState.swift +++ b/App/BlurtiOS/Shared/SharedState.swift @@ -116,6 +116,9 @@ nonisolated struct KeyboardCommand: Codable, Sendable { let priorText: String? let selectedText: String? let sentAt: Date + /// The keyboard process that sent it (`KeyboardModel.instanceID`): the + /// words come back to the field the press was made in, not whichever is up. + let keyboard: String? } /// The words the app got back, for the keyboard to insert. The keyboard joins @@ -148,6 +151,20 @@ nonisolated struct PhaseSnapshot: Codable, Sendable, Equatable { let message: String? let level: Double let at: Date + /// The keyboard command the app last took when it published this — the + /// press this phase answers, or the release or cancel that ended it. The + /// keyboard settles its gate only for the press it is waiting on: a notice + /// from the *previous* dictation landing a moment after a new press must + /// not read as that press being over. + let command: UUID? + + init(state: State, message: String?, level: Double, at: Date, command: UUID? = nil) { + self.state = state + self.message = message + self.level = level + self.at = at + self.command = command + } static let idle = PhaseSnapshot(state: .idle, message: nil, level: 0, at: .distantPast) @@ -373,25 +390,3 @@ nonisolated enum SharedStore { CFNotificationCenterGetDarwinNotifyCenter(), CFNotificationName(signal as CFString), nil, nil, true) } } - -// MARK: - Brand - -/// The comma-separated key-term list, as the engine's `KeyTermsStore` reads -/// it: split, trimmed, emptied of blanks, deduplicated case-insensitively in -/// first-seen order. -nonisolated enum KeyTermList { - static func parse(_ raw: String) -> [String] { - var seen = Set() - var terms: [String] = [] - for piece in raw.split(separator: ",") { - let term = piece.trimmingCharacters(in: .whitespacesAndNewlines) - guard !term.isEmpty, seen.insert(term.lowercased()).inserted else { continue } - terms.append(term) - } - return terms - } - - static func join(_ terms: [String]) -> String { - terms.joined(separator: ", ") - } -} diff --git a/scripts/ios-keyboard-flows.sh b/scripts/ios-keyboard-flows.sh index fa320ed5..6e72db38 100755 --- a/scripts/ios-keyboard-flows.sh +++ b/scripts/ios-keyboard-flows.sh @@ -9,6 +9,10 @@ # scripts/ios-keyboard-flows.sh --face dark --voice a --layout panel # scripts/ios-keyboard-flows.sh --layout full --align right # the mic at an edge (Settings › alignment) # +# The probe app sets the layout, mic concept and side in the App Group for +# each run; a run with --align puts the side back to the middle at the end, +# so Neil's own keyboard on this simulator never inherits a probe's setting. +# # Prints one FLOW-OK / FLOW-FAIL line per step; screenshots land in # .build/design/flows/--/, with a sheet.png of every # step's keyboard side by side. Blurt must be enabled as a keyboard on the @@ -122,3 +126,14 @@ PY done xcrun simctl ui "$UDID" appearance light echo "ios-keyboard-flows: screenshots in $OUT" + +# An --align run leaves the App Group's side where the probe set it: put it +# back through the simulator's own defaults daemon (a plist edit alone is +# not seen until cfprefsd reloads). +if [ -n "$ALIGN" ]; then + GROUP="$(xcrun simctl get_app_container "$UDID" dev.alex.blurt.ios groups 2>/dev/null | awk -F'\t' '/group.dev.alex.blurt/ {print $2}')" + if [ -n "$GROUP" ]; then + xcrun simctl spawn "$UDID" defaults write "$GROUP/Library/Preferences/group.dev.alex.blurt" micAlignment center + echo "ios-keyboard-flows: mic alignment back to the middle" + fi +fi From cbbb503396ae4021fd8405876d3f441935a1a6db Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Thu, 1 Oct 2026 14:44:43 -0400 Subject: [PATCH 71/79] Engine: fence the read-aloud files for iOS; HostIdentity without releaseURL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow-ups to merging main (Sparkle, read-aloud TTS) into the iPhone work: SelectionCopy and SelectionSpeaker use the Mac's pasteboard and ⌘C, so they sit behind `#if os(macOS)` like the rest of the AppKit half; the iPhone app builds a HostIdentity without the releaseURL Sparkle removed; TextShortcutTests names FocusedFieldContext by its cross-platform top-level name; the session file back under the lint length; a grille line reflowed for swift-format. Co-Authored-By: Claude Fable 5.1 --- .../BlurtKeyboard/Sources/VoiceGrille.swift | 3 +- .../BlurtiOS/Sources/BlurtiOSApp.swift | 3 +- .../Pipeline/DictationSession.swift | 15 +-- Sources/BlurtEngine/TTS/SelectionCopy.swift | 116 +++++++++--------- .../BlurtEngine/TTS/SelectionSpeaker.swift | 116 +++++++++--------- .../BlurtEngineTests/TextShortcutTests.swift | 2 +- 6 files changed, 127 insertions(+), 128 deletions(-) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceGrille.swift b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceGrille.swift index 10bd9418..b88546fd 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceGrille.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceGrille.swift @@ -205,7 +205,8 @@ struct VoiceGrille: View { let fringe = alpha * 0.4 // literal-ok: the fringe is a fraction of the flare let core = Metrics.grilleDot * 2 // literal-ok: the flare's centre is a double dot var centre = Layer(id: firstID + 4, colour: DesignTokens.Brand.white, opacity: alpha) - centre.path.addEllipse(in: CGRect(x: x - core / 2, y: midY - core / 2, width: core, height: core)) // literal-ok: centred + let centreRect = CGRect(x: x - core / 2, y: midY - core / 2, width: core, height: core) // literal-ok: centred + centre.path.addEllipse(in: centreRect) return [ line( firstID, CGPoint(x: x + width, y: midY - arm / 2), CGPoint(x: x + width, y: midY + arm / 2), diff --git a/App/BlurtiOS/BlurtiOS/Sources/BlurtiOSApp.swift b/App/BlurtiOS/BlurtiOS/Sources/BlurtiOSApp.swift index ce5d3f82..6d81ffa0 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/BlurtiOSApp.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/BlurtiOSApp.swift @@ -20,8 +20,7 @@ struct BlurtiOSApp: App { subsystem: "dev.alex.blurt.ios", keychainService: "blurt-ios", defaultsPrefix: "Blurt", - logDirectoryName: "Blurt", - releaseURL: HostIdentity.blurt.releaseURL)) + logDirectoryName: "Blurt")) // The unit tests are hosted by this app: they get a coordinator that // touches neither the Keychain nor the App Group (the Mac's UITestSupport // does the same for its harness), and `start()` below never runs. diff --git a/Sources/BlurtEngine/Pipeline/DictationSession.swift b/Sources/BlurtEngine/Pipeline/DictationSession.swift index 0c07bc8b..11cadcb2 100644 --- a/Sources/BlurtEngine/Pipeline/DictationSession.swift +++ b/Sources/BlurtEngine/Pipeline/DictationSession.swift @@ -162,18 +162,13 @@ public actor DictationSession { /// `pipelineTask` alone would abandon only the *wait* — the request itself /// would keep streaming and complete against a dictation the user dismissed. /// - /// A bare task, because that is now all a live request is. It was an - /// `InFlightUpload` pairing the task with the context channel its `config` - /// part parked on, so abandoning it meant closing that too; the streaming - /// route settles the context up front, so `cancel()` is now the whole of it. + /// A bare task: the streaming route settles the context up front, so `cancel()` is the whole of it. var upload: Task? - /// The production entry point: the real developer-mode log, and the real - /// focus capture unless the host supplies its own — `hostFocusCapture` is how - /// a host on a platform without Accessibility reads (the iOS app, whose - /// keyboard knows the text before the cursor) hands that context in. - /// Delegates to the seam-carrying initializer below, which can't be public - /// because it names the internal log seams. + /// The production entry point: the real log, and the real focus capture + /// unless the host supplies its own (`hostFocusCapture`: the iOS app, whose + /// keyboard knows the text before the cursor). Delegates to the seam-carrying + /// initializer below, which can't be public (it names internal seams). public init( mic: MicCaptureProtocol, transcriber: TranscriberProtocol, diff --git a/Sources/BlurtEngine/TTS/SelectionCopy.swift b/Sources/BlurtEngine/TTS/SelectionCopy.swift index 9c358316..e761847d 100644 --- a/Sources/BlurtEngine/TTS/SelectionCopy.swift +++ b/Sources/BlurtEngine/TTS/SelectionCopy.swift @@ -1,62 +1,64 @@ -/// The read-aloud press's fallback for apps whose selection Accessibility can't -/// see. It sends ⌘C, reads what landed on the clipboard, and puts the user's -/// clipboard back. -/// -/// Measured against Claude.app (Electron) on 2026-09-30: the system-wide focus -/// query fails with `cannotComplete`, the app-level one has no value, and the web -/// area exposes no selected text, even with `AXManualAccessibility` or -/// `AXEnhancedUserInterface` set. ⌘C copied the highlighted reply text on the -/// first try. -/// -/// Runs only when the AX read was `.unreadable`, never when AX saw a bare caret. -/// Some editors copy the whole current line on a ⌘C with no selection, and a -/// fallback on every empty selection would turn an ordinary dictation press into -/// reading that line aloud. An app that is unreadable to AX *and* copies lines -/// (VS Code with accessibility off) still has that problem. It's accepted while -/// the feature is experimental. -struct SelectionCopy: Sendable { - private let pasteboard: any CopyPasteboard - private let postCopy: @Sendable () -> Bool - /// How long to wait for the app to answer the ⌘C. Measured copies land in - /// tens of milliseconds, and nothing landing means nothing was selected. - private let timeout: Duration +#if os(macOS) + /// The read-aloud press's fallback for apps whose selection Accessibility can't + /// see. It sends ⌘C, reads what landed on the clipboard, and puts the user's + /// clipboard back. + /// + /// Measured against Claude.app (Electron) on 2026-09-30: the system-wide focus + /// query fails with `cannotComplete`, the app-level one has no value, and the web + /// area exposes no selected text, even with `AXManualAccessibility` or + /// `AXEnhancedUserInterface` set. ⌘C copied the highlighted reply text on the + /// first try. + /// + /// Runs only when the AX read was `.unreadable`, never when AX saw a bare caret. + /// Some editors copy the whole current line on a ⌘C with no selection, and a + /// fallback on every empty selection would turn an ordinary dictation press into + /// reading that line aloud. An app that is unreadable to AX *and* copies lines + /// (VS Code with accessibility off) still has that problem. It's accepted while + /// the feature is experimental. + struct SelectionCopy: Sendable { + private let pasteboard: any CopyPasteboard + private let postCopy: @Sendable () -> Bool + /// How long to wait for the app to answer the ⌘C. Measured copies land in + /// tens of milliseconds, and nothing landing means nothing was selected. + private let timeout: Duration - init( - pasteboard: any CopyPasteboard = SystemClipboard(), - postCopy: @escaping @Sendable () -> Bool = { KeyInjector.postCmdC() }, - timeout: Duration = .milliseconds(250) - ) { - self.pasteboard = pasteboard - self.postCopy = postCopy - self.timeout = timeout - } + init( + pasteboard: any CopyPasteboard = SystemClipboard(), + postCopy: @escaping @Sendable () -> Bool = { KeyInjector.postCmdC() }, + timeout: Duration = .milliseconds(250) + ) { + self.pasteboard = pasteboard + self.postCopy = postCopy + self.timeout = timeout + } - /// The copied text, up to `maxCharacters`, or nil when the copy produced - /// nothing readable. The clipboard is restored whenever the copy changed it. - func copySelection(maxCharacters: Int) async -> String? { - // An unreadable pasteboard can't be restored, so don't disturb it. - guard let saved = pasteboard.snapshot() else { return nil } - let before = pasteboard.changeCount - guard postCopy() else { return nil } - let deadline = ContinuousClock.now + timeout - while pasteboard.changeCount == before, ContinuousClock.now < deadline { - try? await Task.sleep(for: .milliseconds(10)) + /// The copied text, up to `maxCharacters`, or nil when the copy produced + /// nothing readable. The clipboard is restored whenever the copy changed it. + func copySelection(maxCharacters: Int) async -> String? { + // An unreadable pasteboard can't be restored, so don't disturb it. + guard let saved = pasteboard.snapshot() else { return nil } + let before = pasteboard.changeCount + guard postCopy() else { return nil } + let deadline = ContinuousClock.now + timeout + while pasteboard.changeCount == before, ContinuousClock.now < deadline { + try? await Task.sleep(for: .milliseconds(10)) + } + let copiedCount = pasteboard.changeCount + guard copiedCount != before else { return nil } + let copied = pasteboard.currentString() + // Put the user's clipboard back, unless something wrote to it after the copy + // did. The same rule the paste path's restore follows. + if pasteboard.changeCount == copiedCount { pasteboard.restore(saved) } + return copied?.trimmedNonEmpty().map { String($0.prefix(maxCharacters)) } } - let copiedCount = pasteboard.changeCount - guard copiedCount != before else { return nil } - let copied = pasteboard.currentString() - // Put the user's clipboard back, unless something wrote to it after the copy - // did. The same rule the paste path's restore follows. - if pasteboard.changeCount == copiedCount { pasteboard.restore(saved) } - return copied?.trimmedNonEmpty().map { String($0.prefix(maxCharacters)) } } -} -/// The pasteboard operations `SelectionCopy` needs, so tests never touch the real -/// clipboard. `SystemClipboard` is the production conformance. -protocol CopyPasteboard: Sendable { - var changeCount: Int { get } - func snapshot() -> PasteboardSnapshot? - func currentString() -> String? - func restore(_ saved: PasteboardSnapshot) -} + /// The pasteboard operations `SelectionCopy` needs, so tests never touch the real + /// clipboard. `SystemClipboard` is the production conformance. + protocol CopyPasteboard: Sendable { + var changeCount: Int { get } + func snapshot() -> PasteboardSnapshot? + func currentString() -> String? + func restore(_ saved: PasteboardSnapshot) + } +#endif diff --git a/Sources/BlurtEngine/TTS/SelectionSpeaker.swift b/Sources/BlurtEngine/TTS/SelectionSpeaker.swift index 7add7165..e41c2a9c 100644 --- a/Sources/BlurtEngine/TTS/SelectionSpeaker.swift +++ b/Sources/BlurtEngine/TTS/SelectionSpeaker.swift @@ -1,72 +1,74 @@ -/// Reads text aloud with AssemblyAI's streaming TTS. This is the engine half of -/// the experimental read-selection-aloud press (`SelectionSpeechStore`); the app -/// decides when to call it. -/// -/// `speak` runs until the last sample has played. To stop early, cancel the task -/// that is awaiting it: cancellation silences playback at once and closes the -/// socket. -public struct SelectionSpeaker: Sendable { - /// The most text one press will read. Enough for several paragraphs, while - /// keeping a whole-document select-all from queueing minutes of audio (and - /// the TTS usage that comes with it) behind a single tap. - public static let maxCharacters = 4_000 +#if os(macOS) + /// Reads text aloud with AssemblyAI's streaming TTS. This is the engine half of + /// the experimental read-selection-aloud press (`SelectionSpeechStore`); the app + /// decides when to call it. + /// + /// `speak` runs until the last sample has played. To stop early, cancel the task + /// that is awaiting it: cancellation silences playback at once and closes the + /// socket. + public struct SelectionSpeaker: Sendable { + /// The most text one press will read. Enough for several paragraphs, while + /// keeping a whole-document select-all from queueing minutes of audio (and + /// the TTS usage that comes with it) behind a single tap. + public static let maxCharacters = 4_000 - private let synthesizer: AssemblyAISpeechSynthesizer - private let makeSink: @Sendable () -> any PCMSink + private let synthesizer: AssemblyAISpeechSynthesizer + private let makeSink: @Sendable () -> any PCMSink - public init() { - self.init(synthesizer: AssemblyAISpeechSynthesizer()) { - StreamingPCMPlayer(sampleRate: AssemblyAISpeechSynthesizer.sampleRate) + public init() { + self.init(synthesizer: AssemblyAISpeechSynthesizer()) { + StreamingPCMPlayer(sampleRate: AssemblyAISpeechSynthesizer.sampleRate) + } } - } - /// `makeSink` is the playback seam. There is one sink per `speak`, so a - /// cancelled read can't bleed into the next one. - init(synthesizer: AssemblyAISpeechSynthesizer, makeSink: @escaping @Sendable () -> any PCMSink) { - self.synthesizer = synthesizer - self.makeSink = makeSink - } + /// `makeSink` is the playback seam. There is one sink per `speak`, so a + /// cancelled read can't bleed into the next one. + init(synthesizer: AssemblyAISpeechSynthesizer, makeSink: @escaping @Sendable () -> any PCMSink) { + self.synthesizer = synthesizer + self.makeSink = makeSink + } - /// The selected text in the frontmost app, or nil when there is none, when - /// the field is secure, or when it can't be read. - /// - /// Accessibility first. The read is synchronous cross-process IPC that can - /// block a thread for the AX timeout against a hung app, so it runs on - /// `DictationSession.contextQueue`, the press-time capture's queue, and never - /// on the cooperative pool. When AX can't reach a focused element at all, it - /// falls back to copying the selection (`SelectionCopy`). - public static func focusedSelection() async -> String? { - let read = await withCheckedContinuation { continuation in - DictationSession.contextQueue.async { - continuation.resume(returning: FocusCapture.captureSelectedText(maxChars: maxCharacters)) + /// The selected text in the frontmost app, or nil when there is none, when + /// the field is secure, or when it can't be read. + /// + /// Accessibility first. The read is synchronous cross-process IPC that can + /// block a thread for the AX timeout against a hung app, so it runs on + /// `DictationSession.contextQueue`, the press-time capture's queue, and never + /// on the cooperative pool. When AX can't reach a focused element at all, it + /// falls back to copying the selection (`SelectionCopy`). + public static func focusedSelection() async -> String? { + let read = await withCheckedContinuation { continuation in + DictationSession.contextQueue.async { + continuation.resume(returning: FocusCapture.captureSelectedText(maxChars: maxCharacters)) + } } + return await resolve(read, copy: SelectionCopy()) } - return await resolve(read, copy: SelectionCopy()) - } - /// Split from `focusedSelection` so the fallback rule is testable without AX. - static func resolve(_ read: FocusCapture.SelectionRead, copy: SelectionCopy) async -> String? { - switch read { - case .text(let text): text - case .none: nil - case .unreadable: await copy.copySelection(maxCharacters: maxCharacters) + /// Split from `focusedSelection` so the fallback rule is testable without AX. + static func resolve(_ read: FocusCapture.SelectionRead, copy: SelectionCopy) async -> String? { + switch read { + case .text(let text): text + case .none: nil + case .unreadable: await copy.copySelection(maxCharacters: maxCharacters) + } } - } - public func speak(_ text: String) async throws { - let player = makeSink() - try await withTaskCancellationHandler { - do { - for try await chunk in synthesizer.synthesize(text) { - player.enqueue(chunk) + public func speak(_ text: String) async throws { + let player = makeSink() + try await withTaskCancellationHandler { + do { + for try await chunk in synthesizer.synthesize(text) { + player.enqueue(chunk) + } + } catch { + player.stop() + throw error } - } catch { + await player.drain() + } onCancel: { player.stop() - throw error } - await player.drain() - } onCancel: { - player.stop() } } -} +#endif diff --git a/Tests/BlurtEngineTests/TextShortcutTests.swift b/Tests/BlurtEngineTests/TextShortcutTests.swift index 6d3c09f9..53787c53 100644 --- a/Tests/BlurtEngineTests/TextShortcutTests.swift +++ b/Tests/BlurtEngineTests/TextShortcutTests.swift @@ -203,7 +203,7 @@ struct DictationSessionTextShortcutTests { @Test("the text before the caret goes out with expansions put back to triggers") func priorTextRedacted() async { let fixture = makeSession( - field: FocusCapture.FocusedFieldContext( + field: FocusedFieldContext( priorText: "Mail me@example.com.", selectedText: nil, windowTitle: nil, fieldLabel: nil), textShortcuts: [TextShortcut(trigger: "personal email", expansion: "me@example.com")]) From 4584e64d454e6ed0e8c4acb9cbe98d97110a96dc Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Thu, 1 Oct 2026 15:03:52 -0400 Subject: [PATCH 72/79] Keyboard: drop two declarations the iOS periphery scan found unused MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `KeyboardPalette.keyGap` — the layouts read `KeyGeometry.gap` now — and the test rig's unused proxy in the gate suite split out earlier today. Co-Authored-By: Claude Fable 5.1 --- App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift | 1 - App/BlurtiOS/BlurtiOSTests/KeyboardModelGateTests.swift | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift index d22fb6e2..a55e4f66 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardPalette.swift @@ -50,7 +50,6 @@ struct KeyboardPalette: Equatable, Identifiable { /// screen stand in for it (the system's own keyboard colour, measured). let material: Color - static let keyGap = DesignTokens.Metrics.keyGap static let rowGap = DesignTokens.Metrics.rowGap static let margin = DesignTokens.Metrics.marginSide static let keyRadius = DesignTokens.Metrics.keyRadius diff --git a/App/BlurtiOS/BlurtiOSTests/KeyboardModelGateTests.swift b/App/BlurtiOS/BlurtiOSTests/KeyboardModelGateTests.swift index 3fd30abe..21028341 100644 --- a/App/BlurtiOS/BlurtiOSTests/KeyboardModelGateTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/KeyboardModelGateTests.swift @@ -12,7 +12,6 @@ import UIKit struct KeyboardModelGateTests { struct Rig { let model: KeyboardModel - let proxy: FakeProxy let commands: Commands } @@ -31,7 +30,7 @@ struct KeyboardModelGateTests { model.isListening = true let commands = Commands() model.transport = { commands.sent.append($0) } - return Rig(model: model, proxy: proxy, commands: commands) + return Rig(model: model, commands: commands) } private func snapshot(_ state: PhaseSnapshot.State, level: Double = 0) -> PhaseSnapshot { From 87a109da87d4c144f9a57c1b41e9e204eb6a743c Mon Sep 17 00:00:00 2001 From: Neil Bisht Date: Thu, 1 Oct 2026 15:28:32 -0400 Subject: [PATCH 73/79] CI: the mutation target list follows InsertionSeparator; ios-build gets 30 minutes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `mutate.sh --list` (main's new check) named `KeyInjector+Separator.swift`, which the multiplatform work renamed to `InsertionSeparator.swift`. The ios-build job hit its 15-minute cap inside the periphery scan — the simulator build and the unit tests alone take ~12 minutes on macos-26 — so it gets the same 30 the check job has. Co-Authored-By: Claude Fable 5.1 --- .github/workflows/check.yml | 4 +++- scripts/mutate.sh | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 78c1389c..9f6e5adf 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -229,7 +229,9 @@ jobs: needs: changes if: needs.changes.outputs.code == 'true' runs-on: macos-26 - timeout-minutes: 15 + # The simulator build plus the unit tests take ~12 minutes on macos-26 and + # the periphery scan rebuilds after them; 15 cut the scan off mid-run. + timeout-minutes: 30 steps: - name: Checkout blurt diff --git a/scripts/mutate.sh b/scripts/mutate.sh index 7aaa5c47..aa203eba 100755 --- a/scripts/mutate.sh +++ b/scripts/mutate.sh @@ -51,7 +51,7 @@ DEFAULT_TARGETS=( "Sources/BlurtEngine/Hotkey/DictationKeyGate.swift" "Sources/BlurtEngine/Hotkey/DictationKeyRouter.swift" "Sources/BlurtEngine/Hotkey/TriggerKey.swift" - "Sources/BlurtEngine/Injection/KeyInjector+Separator.swift" + "Sources/BlurtEngine/Injection/InsertionSeparator.swift" "Sources/BlurtEngine/Pipeline/MeterBarGeometry.swift" "Sources/BlurtEngine/Pipeline/OverlayPlacement.swift" "Sources/BlurtEngine/Pipeline/PipelinePhase.swift" From 8363e505199ee257cb0703e010dd8343c33c172c Mon Sep 17 00:00:00 2001 From: Alex Kroman Date: Fri, 2 Oct 2026 10:42:31 -0700 Subject: [PATCH 74/79] Keyboard: fix five review findings in the mic and app hand-off - openApp: open the app with UIApplication.open(_:options:) up the responder chain. iOS 18 turned openURL: into a logged no-op, so the orb and "open Blurt" silently did nothing. - disappeared: words already being transcribed are left to finish (and land on the clipboard) instead of being cancelled. - A swipe off the orb undoes only its own press (gate.otherKeyDown): flipping the carousel mid-recording no longer cancels a latched dictation. - An unanswered press expires after BlurtShared.commandFreshnessWindow (moved from the app so both sides share it), so a killed app or a dropped stale press can't leave the gate latched and skip hands-free. - beginAddingTerm during .processing cancels only from a highlighted word; the plain + lets the words land. Each has a regression test in KeyboardModelGateTests. Co-Authored-By: Claude Opus 5.5 --- .../Sources/KeyboardModel+Mic.swift | 22 ++++ .../Sources/KeyboardModel+Phase.swift | 2 + .../Sources/KeyboardModel+Typing.swift | 23 ++-- .../BlurtKeyboard/Sources/KeyboardModel.swift | 21 +++- .../BlurtKeyboard/Sources/MicControl.swift | 2 +- .../Sources/DictationCoordinator.swift | 4 +- .../KeyboardModelGateTests.swift | 104 ++++++++++++++++++ App/BlurtiOS/Shared/SharedState.swift | 3 + 8 files changed, 167 insertions(+), 14 deletions(-) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Mic.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Mic.swift index 962b88e0..b791c2c9 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Mic.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Mic.swift @@ -66,6 +66,7 @@ extension KeyboardModel { selectedText: proxy?.selectedText, sentAt: Date(), keyboard: instanceID) transport(command) unansweredPress = kind == .press ? command.id : nil + unansweredPressSentAt = kind == .press ? command.sentAt : nil // A press the app never answers would leave the gate latched over // nothing. Either notification can be missed: first catch up with a phase // the app may have published unheard; if the picture is still as it was, @@ -84,4 +85,25 @@ extension KeyboardModel { } } + /// Lets go of a press the app can no longer answer — it drops one older + /// than `BlurtShared.commandFreshnessWindow` unread, and an app that was + /// killed answers nothing — so its latch can't outlive it. True when it did. + @discardableResult + func expireUnansweredPress(now: Date = Date()) -> Bool { + guard unansweredPress != nil, let sentAt = unansweredPressSentAt, + now.timeIntervalSince(sentAt) >= BlurtShared.commandFreshnessWindow + else { return false } + unansweredPress = nil + unansweredPressSentAt = nil + return true + } + + /// A swipe that began on the orb (the panel's carousel) after its press + /// went out: undo exactly what that press did. A fresh press is cancelled; + /// a press over a recording a tap had latched only re-latches it, so + /// flipping to the keys mid-dictation doesn't throw the words away; a press + /// the orb ignored (busy, or Blurt not ready) undoes nothing. + func undoPress() { + perform(gate.otherKeyDown()) + } } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Phase.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Phase.swift index e0a2513f..70c8e4eb 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Phase.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Phase.swift @@ -61,6 +61,8 @@ extension KeyboardModel { // And a dictation in flight that this keyboard didn't start (hands-free // in another app, or a previous keyboard process) must latch it, so the // next tap is the stop rather than a press the engine drops. + // A press too old for the app to take will never be answered at all. + expireUnansweredPress() if !isSettled || current.command == unansweredPress { unansweredPress = nil } if isSettled, !gate.isIdle { if unansweredPress == nil { gate.reset() } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Typing.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Typing.swift index 71477678..643fe4ea 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Typing.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Typing.swift @@ -117,12 +117,20 @@ extension KeyboardModel { /// recording is released and the words still land; from a highlighted /// word it is cancelled: the words would land *over* the word being fixed /// (a result replaces the selection), and the user's intent is the word. + /// Words already being transcribed follow the same rule: from the plain + + /// they still land (the mic is off; there is nothing to stop), from a + /// highlighted word they are cancelled. func beginAddingTerm() { let seed = Self.termCandidate(from: proxy?.selectedText) ?? "" switch snapshot.state { case .recording: perform(seed.isEmpty ? .stop : .cancel) case .connecting: perform(.cancel) - case .idle, .processing, .pasted, .copied, .error: + case .processing: + // The gate may still be latched from the tap that started it (an + // auto-release has no finger event to close it): that is no reason to + // cancel. + if !seed.isEmpty { perform(.cancel) } + case .idle, .pasted, .copied, .error: // A press the app hasn't answered yet would start a dictation under // the field: it is taken back. if unansweredPress != nil || !gate.isIdle { perform(.cancel) } @@ -251,18 +259,19 @@ extension KeyboardModel { func globe() { controller?.advanceToNextInputMode() } /// Brings the app forward to open the microphone — the one thing a keyboard - /// cannot do for itself. iOS gives extensions no `open(_:)`, so this walks the - /// responder chain to the application object and asks it, the way every - /// keyboard that opens its app does. + /// cannot do for itself. iOS gives extensions no `UIApplication.shared`, so + /// this walks the responder chain to the application object and asks it, the + /// way every keyboard that opens its app does. With `open(_:options:)`: since + /// iOS 18 the old `openURL:` only logs "BUG IN CLIENT OF UIKIT" and opens + /// nothing. func openApp() { guard let controller, let url = URL(string: "\(BlurtShared.urlScheme)://\(BlurtShared.startHost)") else { return } - let selector = sel_registerName("openURL:") var responder: UIResponder? = controller while let current = responder { - if current.responds(to: selector) { - _ = current.perform(selector, with: url) + if let application = current as? UIApplication { + application.open(url, options: [:], completionHandler: nil) return } responder = current.next diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift index 7596ffbb..1bd39bac 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift @@ -101,6 +101,10 @@ final class KeyboardModel { /// answer it (the previous dictation's notice landing late) leaves the /// gate alone; anything in flight, or a phase carrying its id, answers it. @ObservationIgnored var unansweredPress: UUID? + /// When `unansweredPress` went out. Past `BlurtShared.commandFreshnessWindow` + /// the app drops it unread (or was never there to read it), so no answer + /// is coming: see `expireUnansweredPress`. + @ObservationIgnored var unansweredPressSentAt: Date? /// The `at` of a notice the keyboard already let go of: a re-read of the /// same snapshot cannot replay it. @ObservationIgnored var dismissedNoticeAt: Date? @@ -190,6 +194,7 @@ final class KeyboardModel { // `unansweredPress` is not reset here: an appearance can follow another // with no disappearance between (iOS does that), and a press still out // must keep the gate latched so hands-free does not press again over it. + // One too old for the app to take is over, though (`expireUnansweredPress`). symbolsPage = Self.wantsSymbols(proxy?.keyboardType) morePage = false readAppearance() @@ -212,6 +217,10 @@ final class KeyboardModel { storedMicAlignment = SharedStore.micAlignment SharedStore.keyboardEverSeen = true refresh(haptics: false) + // `refresh` may apply no phase at all (none stored, or a notice already + // let go of), so a press the app will never answer is let go of here too: + // otherwise its latch would skip hands-free on every appearance after. + if expireUnansweredPress(), isSettled { gate.reset() } startHeartbeat() requestLexicon() // Words that landed while this keyboard was away, still fresh and meant @@ -235,14 +244,20 @@ final class KeyboardModel { /// The keyboard is leaving the screen. A dictation it started must not run /// on without it: a latched recording is released (the words still land, on /// the clipboard if no keyboard is there to take them), anything earlier is - /// cancelled. Presence ends, so a result that finishes after this goes to - /// the clipboard rather than to a keyboard nobody can see. + /// cancelled. Words already being transcribed are left to finish — the mic + /// is off, and a cancel would throw them away. Presence ends, so a result + /// that finishes after this goes to the clipboard rather than to a keyboard + /// nobody can see. func disappeared() { heartbeat?.cancel() heartbeat = nil commandRetry?.cancel() if !gate.isIdle || !isSettled { - send(snapshot.state == .recording ? .release : .cancel) + switch snapshot.state { + case .recording: send(.release) + case .processing: break + case .idle, .connecting, .pasted, .copied, .error: send(.cancel) + } gate.reset() } SharedStore.keyboardSeenAt = nil diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/MicControl.swift b/App/BlurtiOS/BlurtKeyboard/Sources/MicControl.swift index 36e2586c..61dad790 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/MicControl.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/MicControl.swift @@ -95,7 +95,7 @@ struct MicControl: View { if needsDown { model.micDown() } model.micUp() case .cancelSentPress: - model.cancel() + model.undoPress() case .nothing: break } diff --git a/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift b/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift index 44797df4..000326a9 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift @@ -48,8 +48,6 @@ final class DictationCoordinator { nonisolated private static let pressKeyboard = Mutex(nil) /// Contact names, parsed once per lexicon refresh rather than on the press. nonisolated private static let lexiconNames = Mutex<[String]>([]) - /// A press command older than this was held while the app was suspended. - static let commandFreshnessWindow: TimeInterval = 10 init(apiKey: APIKeyModel = APIKeyModel()) { let window = ListeningWindow() @@ -151,7 +149,7 @@ final class DictationCoordinator { SharedStore.remove(forKey: BlurtShared.Key.command) // A notification held while the app was suspended delivers a press from // minutes ago; the user has long since moved on. - guard Date().timeIntervalSince(command.sentAt) < Self.commandFreshnessWindow else { return } + guard Date().timeIntervalSince(command.sentAt) < BlurtShared.commandFreshnessWindow else { return } switch command.kind { case .press: Self.pressContext.withLock { diff --git a/App/BlurtiOS/BlurtiOSTests/KeyboardModelGateTests.swift b/App/BlurtiOS/BlurtiOSTests/KeyboardModelGateTests.swift index 21028341..1aaf2312 100644 --- a/App/BlurtiOS/BlurtiOSTests/KeyboardModelGateTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/KeyboardModelGateTests.swift @@ -131,4 +131,108 @@ struct KeyboardModelGateTests { model.beginAddingTerm() #expect(commands.sent.count == 4) } + + @Test("the + while words are being transcribed lets them land; from a highlighted word it cancels them") + func termFieldDuringProcessing() { + let suite = ScratchSuite() + defer { suite.tearDown() } + let rig = ready() + let model = rig.model + let commands = rig.commands + // A tap latched the gate; the app auto-released, with no finger event. + model.micDown() + model.micUp() + model.apply(snapshot(.recording)) + model.apply(snapshot(.processing)) + #expect(!model.gate.isIdle) + model.beginAddingTerm() + #expect(commands.sent.map(\.kind) == [.press]) + #expect(model.gate.isIdle) + model.cancelAddingTerm() + (model.proxyOverride as? FakeProxy)?.selected = "Rizz" + model.beginAddingTerm() + #expect(commands.sent.map(\.kind) == [.press, .cancel]) + } + + @Test("leaving the screen while the words are being transcribed lets them finish") + func disappearDuringProcessing() { + let suite = ScratchSuite() + defer { suite.tearDown() } + let rig = ready() + let model = rig.model + let commands = rig.commands + model.micDown() + model.micUp() + model.apply(snapshot(.recording)) + model.micDown() + model.micUp() + model.apply(snapshot(.processing)) + model.disappeared() + #expect(commands.sent.map(\.kind) == [.press, .release]) + #expect(model.gate.isIdle) + } + + @Test("a swipe off the orb undoes only its own press: a fresh one is cancelled, a latched recording kept") + func undoPress() { + let suite = ScratchSuite() + defer { suite.tearDown() } + let rig = ready() + let model = rig.model + let commands = rig.commands + // A swipe whose press went out from idle: taken back. + model.micDown() + model.undoPress() + #expect(commands.sent.map(\.kind) == [.press, .cancel]) + #expect(model.gate.isIdle) + // A tap latches a recording; a swipe across the orb leaves it running, + // and the next tap is still the stop. + model.apply(snapshot(.idle)) + model.micDown() + model.micUp() + model.apply(snapshot(.recording)) + model.micDown() + model.undoPress() + #expect(commands.sent.map(\.kind) == [.press, .cancel, .press]) + #expect(!model.gate.isIdle) + model.micDown() + model.micUp() + #expect(commands.sent.map(\.kind) == [.press, .cancel, .press, .release]) + } + + @Test("a press the app never answers stops holding the gate once it is too old for the app to take") + func unansweredPressExpires() { + let suite = ScratchSuite() + defer { suite.tearDown() } + let rig = ready() + let model = rig.model + model.micDown() + model.micUp() + #expect(!model.expireUnansweredPress()) + #expect(model.unansweredPress != nil) + // A settled phase that doesn't answer it leaves the latch while it is fresh… + model.apply(snapshot(.pasted)) + #expect(!model.gate.isIdle) + // …and lets it go once the app would drop it unread. + model.unansweredPressSentAt = Date().addingTimeInterval(-BlurtShared.commandFreshnessWindow - 1) + model.apply(snapshot(.idle)) + #expect(model.unansweredPress == nil) + #expect(model.gate.isIdle) + } + + @Test("an appearance lets go of a press too old to be answered, so hands-free can start") + func appearanceExpiresPress() { + let suite = ScratchSuite() + defer { suite.tearDown() } + let rig = ready() + let model = rig.model + let commands = rig.commands + SharedStore.autoDictate = true + model.micDown() + model.micUp() + model.unansweredPressSentAt = Date().addingTimeInterval(-BlurtShared.commandFreshnessWindow - 1) + model.appeared() + // Hands-free pressed afresh rather than skipping over a dead latch. + #expect(commands.sent.map(\.kind) == [.press, .press]) + #expect(model.unansweredPress == commands.sent.last?.id) + } } diff --git a/App/BlurtiOS/Shared/SharedState.swift b/App/BlurtiOS/Shared/SharedState.swift index cafe6a82..7e8bf218 100644 --- a/App/BlurtiOS/Shared/SharedState.swift +++ b/App/BlurtiOS/Shared/SharedState.swift @@ -17,6 +17,9 @@ nonisolated enum BlurtShared { /// the one moment iOS insists on before the microphone may open. static let urlScheme = "blurt" static let startHost = "start" + /// A press command older than this was held while the app was suspended: + /// the app drops it unanswered, and the keyboard stops waiting for an answer. + static let commandFreshnessWindow: TimeInterval = 10 nonisolated enum Key { static let layout = "keyboardLayout" From 938c28add4b0a4632819a23f0674ebef99f656f4 Mon Sep 17 00:00:00 2001 From: Alex Kroman Date: Fri, 2 Oct 2026 11:12:56 -0700 Subject: [PATCH 75/79] iPhone: split the logic into BlurtiOSCore and gate it like the engine The iPhone code's logic now lives apart from its UI, the way BlurtEngine sits apart from the Mac shell. BlurtiOSCore is a static framework both the app and the keyboard link: the App Group contract, KeyboardModel, VoiceState, KeyboardInteraction, TermPack, KeyboardRelayInjector and friends. No SwiftUI, no views, no audio; its API is `package` (one SWIFT_PACKAGE_NAME), so periphery still sees what nothing uses. The three UI hooks the model had (palette, KeyboardLayout.height, MicAlignment's SwiftUI alignment) became shell-side extensions; a preview now hands the model a ThemeFace instead of a palette. The iPhone suite now holds the engine's gates: - ios-test.sh fails when BlurtiOSCore line coverage drops below 88% (check.sh's MIN_COVERAGE). It is 96.81%, up from 84%, with new tests for the presence heartbeat, the app's Darwin signals, notice and saved-term dwells, the release held while the mic comes up, the word list hand-off, openApp's responder walk (via a urlOpener seam), SharedStore defaults, TermPack's share file and APIKeyModel. - A new ios-sanitizers job runs the suite under TSan and ASan; `gate` requires it. - Tests are pinned serial (scheme + -parallel-testing-enabled NO): they swap a global App Group override, and an async test suspended mid-await must not see another suite's. check-invariants' no-audio-in-the-keyboard rule now covers BlurtiOSCore, which the keyboard links. ios-typecheck.sh emits the core module first. Co-Authored-By: Claude Opus 5.5 --- .claude/skills/check/SKILL.md | 4 +- .claude/skills/project-guardrails/SKILL.md | 3 +- .github/workflows/check.yml | 38 +++- AGENTS.md | 33 ++- .../BlurtKeyboard/Sources/AddTermKey.swift | 1 + .../Sources/FullKeyboardView.swift | 1 + .../BlurtKeyboard/Sources/KeyCap.swift | 1 + .../Sources/KeyboardModel+Palette.swift | 16 ++ .../Sources/KeyboardRootView.swift | 1 + .../Sources/KeyboardViewController.swift | 1 + .../BlurtKeyboard/Sources/MicControl.swift | 1 + .../BlurtKeyboard/Sources/PanelCarousel.swift | 1 + .../BlurtKeyboard/Sources/PanelView.swift | 1 + .../BlurtKeyboard/Sources/SlimBarView.swift | 1 + .../BlurtKeyboard/Sources/TermField.swift | 1 + .../BlurtKeyboard/Sources/VoiceBar.swift | 1 + .../BlurtKeyboard/Sources/VoiceElement.swift | 23 +-- .../BlurtKeyboard/Sources/VoiceGrille.swift | 1 + .../BlurtKeyboard/Sources/VoiceRibs.swift | 1 + .../BlurtKeyboard/Sources/VoiceRow.swift | 1 + .../BlurtKeyboard/Sources/VoiceStreak.swift | 1 + .../BlurtKeyboard/Sources/WaveformMeter.swift | 1 + .../BlurtiOS/Sources/BlurtiOSApp.swift | 1 + .../Sources/DictationCoordinator.swift | 1 + App/BlurtiOS/BlurtiOS/Sources/HomeHero.swift | 1 + App/BlurtiOS/BlurtiOS/Sources/HomeView.swift | 1 + .../BlurtiOS/Sources/ImportTermsView.swift | 1 + .../BlurtiOS/Sources/KeyEntryView.swift | 1 + .../Sources/KeyboardGalleryView.swift | 4 +- .../BlurtiOS/Sources/KeyboardProbeView.swift | 2 + .../BlurtiOS/Sources/ListeningWindow.swift | 1 + .../BlurtiOS/Sources/SettingsView.swift | 1 + .../BlurtiOS/Sources/ThemePickerView.swift | 3 +- .../APIKeyModel.swift | 12 +- .../DarwinObserver.swift | 4 +- .../Sources => BlurtiOSCore}/HomeStatus.swift | 12 +- .../KeyTermList.swift | 6 +- .../KeyboardInteraction.swift | 44 ++-- .../KeyboardModel+Field.swift | 10 +- .../KeyboardModel+Mic.swift | 20 +- .../KeyboardModel+Phase.swift | 8 +- .../KeyboardModel+Typing.swift | 48 ++--- .../KeyboardModel.swift | 144 +++++++------ .../KeyboardMotion.swift | 2 +- .../KeyboardRelayInjector.swift | 16 +- .../MicAlignment.swift | 29 +-- .../SharedState.swift | 191 ++++++++--------- .../Sources => BlurtiOSCore}/TermPack.swift | 36 ++-- App/BlurtiOS/BlurtiOSCore/ThemeFace.swift | 14 ++ .../BlurtiOSCore/VoiceElementKind.swift | 23 +++ .../Sources => BlurtiOSCore}/VoiceState.swift | 44 ++-- .../BlurtiOSTests/APIKeyModelTests.swift | 37 ++++ .../BlurtiOSTests/DesignTokensTests.swift | 1 + .../BlurtiOSTests/FeedAndLayoutTests.swift | 1 + .../BlurtiOSTests/HomeStatusTests.swift | 2 +- .../KeyboardInteractionTests.swift | 2 +- .../KeyboardLifecycleTests.swift | 195 ++++++++++++++++++ .../KeyboardModelFuzzTests.swift | 1 + .../KeyboardModelGateTests.swift | 1 + .../BlurtiOSTests/KeyboardModelTests.swift | 1 + .../BlurtiOSTests/ProtocolTests.swift | 1 + .../BlurtiOSTests/SharedStateTests.swift | 60 ++++++ .../BlurtiOSTests/TermPackTests.swift | 23 ++- App/BlurtiOS/BlurtiOSTests/TestSuite.swift | 2 +- .../BlurtiOSTests/VoiceElementTests.swift | 1 + .../BlurtiOSTests/VoiceStateTests.swift | 2 +- App/BlurtiOS/DESIGN.md | 4 +- App/BlurtiOS/README.md | 33 ++- .../Shared/KeyboardLayout+Height.swift | 17 ++ App/BlurtiOS/Shared/MicAlignment+Layout.swift | 21 ++ App/BlurtiOS/project.yml | 53 ++++- scripts/check-invariants.sh | 9 +- scripts/design-sync.sh | 15 +- scripts/ios-test.sh | 79 ++++++- scripts/ios-typecheck.sh | 12 +- 75 files changed, 992 insertions(+), 394 deletions(-) create mode 100644 App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Palette.swift rename App/BlurtiOS/{BlurtiOS/Sources => BlurtiOSCore}/APIKeyModel.swift (93%) rename App/BlurtiOS/{Shared => BlurtiOSCore}/DarwinObserver.swift (89%) rename App/BlurtiOS/{BlurtiOS/Sources => BlurtiOSCore}/HomeStatus.swift (89%) rename App/BlurtiOS/{Shared => BlurtiOSCore}/KeyTermList.swift (78%) rename App/BlurtiOS/{BlurtKeyboard/Sources => BlurtiOSCore}/KeyboardInteraction.swift (74%) rename App/BlurtiOS/{BlurtKeyboard/Sources => BlurtiOSCore}/KeyboardModel+Field.swift (79%) rename App/BlurtiOS/{BlurtKeyboard/Sources => BlurtiOSCore}/KeyboardModel+Mic.swift (87%) rename App/BlurtiOS/{BlurtKeyboard/Sources => BlurtiOSCore}/KeyboardModel+Phase.swift (95%) rename App/BlurtiOS/{BlurtKeyboard/Sources => BlurtiOSCore}/KeyboardModel+Typing.swift (90%) rename App/BlurtiOS/{BlurtKeyboard/Sources => BlurtiOSCore}/KeyboardModel.swift (78%) rename App/BlurtiOS/{BlurtKeyboard/Sources => BlurtiOSCore}/KeyboardMotion.swift (81%) rename App/BlurtiOS/{BlurtiOS/Sources => BlurtiOSCore}/KeyboardRelayInjector.swift (81%) rename App/BlurtiOS/{Shared => BlurtiOSCore}/MicAlignment.swift (51%) rename App/BlurtiOS/{Shared => BlurtiOSCore}/SharedState.swift (74%) rename App/BlurtiOS/{BlurtiOS/Sources => BlurtiOSCore}/TermPack.swift (77%) create mode 100644 App/BlurtiOS/BlurtiOSCore/ThemeFace.swift create mode 100644 App/BlurtiOS/BlurtiOSCore/VoiceElementKind.swift rename App/BlurtiOS/{BlurtKeyboard/Sources => BlurtiOSCore}/VoiceState.swift (80%) create mode 100644 App/BlurtiOS/BlurtiOSTests/APIKeyModelTests.swift create mode 100644 App/BlurtiOS/BlurtiOSTests/KeyboardLifecycleTests.swift create mode 100644 App/BlurtiOS/Shared/KeyboardLayout+Height.swift create mode 100644 App/BlurtiOS/Shared/MicAlignment+Layout.swift diff --git a/.claude/skills/check/SKILL.md b/.claude/skills/check/SKILL.md index 11415a39..85fb52f5 100644 --- a/.claude/skills/check/SKILL.md +++ b/.claude/skills/check/SKILL.md @@ -130,4 +130,6 @@ hides every lint finding behind it — expect to fix a batch, not a queue. Its build and tests run in CI's `ios-build` job (the authority). Locally: `scripts/ios-typecheck.sh` typechecks both iPhone targets on a Mac with only the Command Line Tools (run by `check.sh` when the SDK carries the Mac Catalyst frameworks), `scripts/ios-test.sh` runs `BlurtiOSTests` on a -simulator when Xcode is installed, and `scripts/ios-sim.sh` builds and launches the app there. +simulator when Xcode is installed and enforces `BlurtiOSCore`'s line-coverage floor (`MIN_IOS_COVERAGE`, 88%; +`BLURT_IOS_SANITIZER=thread` or `address` runs the TSan / ASan pass CI's `ios-sanitizers` job +runs), and `scripts/ios-sim.sh` builds and launches the app there. diff --git a/.claude/skills/project-guardrails/SKILL.md b/.claude/skills/project-guardrails/SKILL.md index 42d4b438..fc2b7062 100644 --- a/.claude/skills/project-guardrails/SKILL.md +++ b/.claude/skills/project-guardrails/SKILL.md @@ -184,7 +184,8 @@ only one of stt_prompt or prompt; they are the same field`, before the audio is - **The keyboard never hears anything.** iOS lets no keyboard use the microphone; the app listens and transcribes, the keyboard is a remote control over the App Group that inserts - the words. No `AVFoundation` in `BlurtKeyboard/` or `Shared/` (mechanized). + the words. No `AVFoundation` in `BlurtKeyboard/`, `Shared/` or `BlurtiOSCore/` (the keyboard + links it) (mechanized). - The app's microphone is a _listening window_, opened once while the app is in front and kept open, not a per-press capture — the two rows marked "(macOS shell)" above do not apply. - Insertion is the keyboard's `textDocumentProxy`; the clipboard is only the fallback when no diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 9f6e5adf..beb9fb1b 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -282,6 +282,36 @@ jobs: --retain-public --retain-unused-protocol-func-params \ --report-exclude 'Sources/**' --strict --quiet + # The iPhone suite under each sanitizer, as check.sh runs the engine's. A job + # of its own, one runner per sanitizer, rather than more steps in ios-build: + # each is a full instrumented rebuild, and ios-build is already near its + # timeout. The coverage gate runs in ios-build's plain pass only. + ios-sanitizers: + needs: changes + if: needs.changes.outputs.code == 'true' + runs-on: macos-26 + timeout-minutes: 30 + strategy: + fail-fast: false + matrix: + sanitizer: [thread, address] + + steps: + - name: Checkout blurt + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + path: blurt + persist-credentials: false + + - name: Install XcodeGen + run: brew install xcodegen + + - name: Run the iPhone unit tests under the ${{ matrix.sanitizer }} sanitizer + working-directory: blurt + env: + BLURT_IOS_SANITIZER: ${{ matrix.sanitizer }} + run: BLURT_DERIVED_DATA="$RUNNER_TEMP/BlurtiOS" scripts/ios-test.sh + # Always-runs summary job, so a *skipped* `check` can't be mistaken for a pass. # GitHub reports a skipped required check to branch protection as successful, so # anything that makes `check` skip — the `changes` filter erroring, a `needs` @@ -292,18 +322,19 @@ jobs: # NOTE: this only protects the repo once branch protection requires `gate` # instead of (or as well as) `check` — that's a repo settings change. gate: - needs: [changes, check, ios-build] + needs: [changes, check, ios-build, ios-sanitizers] if: always() runs-on: ubuntu-latest steps: - - name: Assert the macOS and iOS gates ran or were intentionally skipped + - name: Assert the macOS, iOS and iOS-sanitizer gates ran or were intentionally skipped env: CHECK_RESULT: ${{ needs.check.result }} IOS_RESULT: ${{ needs.ios-build.result }} + IOS_SANITIZERS_RESULT: ${{ needs.ios-sanitizers.result }} CHANGES_RESULT: ${{ needs.changes.result }} CODE_CHANGED: ${{ needs.changes.outputs.code }} run: | - echo "changes=$CHANGES_RESULT code=$CODE_CHANGED check=$CHECK_RESULT ios-build=$IOS_RESULT" + echo "changes=$CHANGES_RESULT code=$CODE_CHANGED check=$CHECK_RESULT ios-build=$IOS_RESULT ios-sanitizers=$IOS_SANITIZERS_RESULT" if [ "$CHANGES_RESULT" != "success" ]; then echo "error: the changes filter did not succeed, so the gate cannot be trusted" >&2 exit 1 @@ -327,3 +358,4 @@ jobs: } assert_gate macOS "$CHECK_RESULT" assert_gate iOS "$IOS_RESULT" + assert_gate "iOS sanitizers" "$IOS_SANITIZERS_RESULT" diff --git a/AGENTS.md b/AGENTS.md index a09b2563..0ccb4b06 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -37,7 +37,7 @@ Four reflexes before you touch anything: | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `Sources/BlurtEngine/` | Swift package (`swift-tools-version:6.2`, `platforms: [.macOS(.v15), .iOS(.v18)]`) owning the pipeline. Pure logic behind protocol seams, no AppKit-shell deps, **no external SPM deps** — Foundation/Security/AVFoundation/CoreAudio plus toolchain modules like Synchronization, with AppKit types only at the seams. The macOS-only files (Accessibility reads, clipboard paste, CoreAudio route reads, TCC and code-signing helpers) are fenced behind `#if os(macOS)`; `check.yml`'s `ios-build` job builds the library for the iOS simulator so a symbol that escapes its fence fails the PR. | | `App/Blurt/` | AppKit/SwiftUI shell (Xcode project generated by XcodeGen) that wires the engine to an overlay window, the main window, a Settings scene, a menu bar item, and the trigger key. Its only package is the local `BlurtEngine` (declared in `App/Blurt/project.yml`). | -| `App/BlurtiOS/` | The iPhone app (SwiftUI) and the keyboard it embeds, generated by XcodeGen from its own `project.yml` and built by `check.yml`'s `ios-build` job. The app owns the engine's pipeline over an always-on capture; the keyboard is a remote control that inserts the words. `App/BlurtiOS/README.md` is its guide. | +| `App/BlurtiOS/` | The iPhone app (SwiftUI) and the keyboard it embeds, generated by XcodeGen from its own `project.yml` and built by `check.yml`'s `ios-build` job. The app owns the engine's pipeline over an always-on capture; the keyboard is a remote control that inserts the words. Their logic is `BlurtiOSCore`, a framework apart from the UI the way the engine is apart from the Mac shell. `App/BlurtiOS/README.md` is its guide. | The engine's dependency-free rule is a **rule**. The app carries one remote package — Sparkle, the in-place updater (see [Updates](#updates)) — allowlisted by URL in `check.sh`'s dependency guard, and @@ -88,18 +88,26 @@ App/Blurt/ BlurtUITests/ XCUITest bundle (see Tests) App/BlurtiOS/ the iPhone app and its keyboard (README.md there is the guide): project.yml XcodeGen source of truth — the project is generated, NOT committed + BlurtiOSCore/ the iPhone code's logic apart from its UI, as BlurtEngine is apart + from the Mac shell: SharedState (the App Group contract), + KeyboardModel, VoiceState, KeyboardInteraction, TermPack, + KeyboardRelayInjector. A static framework both targets link; no + SwiftUI, no audio; `package` access; coverage-gated (ios-test.sh) BlurtiOS/Sources/ the app: DictationCoordinator (composition root), ListeningWindow + WindowedAudioSource (the always-on capture, since iOS can't open - the mic from the background), KeyboardRelayInjector, HomeView - BlurtKeyboard/Sources/ the keyboard: a remote control that inserts the words; three - layouts (slim bar / panel / full keyboard) over one model - Shared/ SharedState.swift — the App Group contract, compiled into BOTH + the mic from the background), HomeView and the other screens + BlurtKeyboard/Sources/ the keyboard's views: a remote control that inserts the words; three + layouts (slim bar / panel / full keyboard) over BlurtiOSCore's model + Shared/ the UI both targets draw with (DesignTokens, type, brand), compiled + into BOTH Tests/BlurtEngineTests/ Swift Testing suites; Stubs/ holds the seam doubles scripts/ check.sh, check-portability.sh, check-invariants.sh, bootstrap.sh, dev-build.sh, uitest.sh, leaks.sh, release*.sh, ios-typecheck.sh (the iPhone targets without an iOS SDK), ios-sim.sh (build + run the iPhone app in the simulator), - ios-test.sh (the iPhone unit tests, BlurtiOSTests, on a simulator) + ios-test.sh (the iPhone unit tests, BlurtiOSTests, on a simulator, + with BlurtiOSCore's line-coverage gate; BLURT_IOS_SANITIZER=thread|address + runs them under a sanitizer instead) hand-run maintainer tools — no automated caller, invoked by a human, so "nothing references it" here does NOT mean dead code: screenshot.swift + beautify.swift (window imagery, capture @@ -113,7 +121,8 @@ evals/ offline decision support — the repo's only Python ruff.toml ruff config for the above — the repo's only Python config .github/workflows/ check.yml (the gate, macos-26; its ios-build job builds the engine for the iOS simulator, then the iPhone app with its keyboard, and runs - BlurtiOSTests on a simulator) + BlurtiOSTests on a simulator with its coverage gate; ios-sanitizers + runs them again under TSan and ASan) release-bump.yml (version bump) + release.yml (sign + publish), codeql.yml .claude/ Claude Code hooks, skills, subagents (see CLAUDE.md) @@ -204,8 +213,12 @@ script, so a clean local `check.sh` matches CI by construction. One more job **i `check.sh` cannot cover it: **`ios-build`** compiles the engine for the iOS simulator (`xcodebuild -scheme BlurtEngine -destination 'generic/platform=iOS Simulator'`), which is the only place a macOS-only symbol that escaped its `#if os(macOS)` fence gets caught — `swift test` builds -for the host, and every other job runs on a Mac. `gate` fails unless both platform builds are green -(or skipped for a docs-only change). Two sibling jobs exist purely to shorten the loop for whoever is +for the host, and every other job runs on a Mac. It then runs `BlurtiOSTests` under the same bar +the engine's suite meets in `check.sh`: warnings as errors, a **line-coverage gate** on +`BlurtiOSCore`, the iPhone code's logic (≥ `MIN_IOS_COVERAGE` in `scripts/ios-test.sh`, the +engine's 88%; raise it as coverage grows), and — in the sibling +**`ios-sanitizers`** job, one runner per sanitizer — **ThreadSanitizer** and **AddressSanitizer** +passes. `gate` fails unless all of them are green (or skipped for a docs-only change). Two sibling jobs exist purely to shorten the loop for whoever is editing Swift without a toolchain, and **neither is a required check** — both can only go red where `check` would too: @@ -391,7 +404,7 @@ rule along with the row. | Redirect the post-build install away from `/Applications` | TCC won't register apps in DerivedData/`/tmp`, so permission toggles never appear. | | Touch the real Keychain in tests | `APIKeyStore` is the production item — a test that writes it triggers Keychain prompts and corrupts the real item's ACL. Use an isolated service (see `KeychainStoreTests`) or `InMemoryAPIKeyStore`. | | Add backwards-compat shims for removed types | Deleted types stay deleted — no deprecated re-exports. | -| Give the keyboard extension a microphone or any audio type | iOS lets no keyboard use the microphone, and the design keeps every audio type out of it: the app listens and transcribes over its always-on capture, the keyboard is a remote control that inserts the words (`KeyboardRelayInjector`). An `AVFoundation` import in `App/BlurtiOS/BlurtKeyboard` or `Shared` is that decision being reversed by accident. | +| Give the keyboard extension a microphone or any audio type | iOS lets no keyboard use the microphone, and the design keeps every audio type out of it: the app listens and transcribes over its always-on capture, the keyboard is a remote control that inserts the words (`KeyboardRelayInjector`). An `AVFoundation` import in `App/BlurtiOS/BlurtKeyboard`, `Shared` or `BlurtiOSCore` (which the keyboard links) is that decision being reversed by accident. | **Platform scope.** Two rows above are the Mac shell's, not the iPhone's, and the iPhone app diverges from them on purpose: "no warm recorder" — on iOS the app keeps the microphone open for a listening window (`App/BlurtiOS/BlurtiOS/Sources/AudioSource.swift`), because iOS refuses to open it from the background and the keyboard, which is where a dictation starts, is in the background of whatever app the user is typing in; and "injection is always a clipboard paste" — on iOS the keyboard inserts through its `textDocumentProxy`, and the clipboard is only the degradation when no keyboard is there to take the words. Neither changes the engine: `MicCapture` and `KeyInjector` stay as they are and are macOS-only; the iOS app supplies its own `MicCaptureProtocol` and `InjectorProtocol` conformances. `App/BlurtiOS/DESIGN.md` is the iPhone's own list. diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/AddTermKey.swift b/App/BlurtiOS/BlurtKeyboard/Sources/AddTermKey.swift index 12881bc7..2db8dc35 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/AddTermKey.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/AddTermKey.swift @@ -1,3 +1,4 @@ +import BlurtiOSCore import SwiftUI /// The small + beside the mic: a new key term. A bare glyph, quiet until it diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift b/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift index 8e37c87a..66b7b935 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/FullKeyboardView.swift @@ -1,3 +1,4 @@ +import BlurtiOSCore import SwiftUI /// A complete keyboard laid out as the iPhone's own — ten letter keys across diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyCap.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyCap.swift index d6802f7c..c1f911fe 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyCap.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyCap.swift @@ -1,3 +1,4 @@ +import BlurtiOSCore import SwiftUI /// One ordinary key: a glyph (SF Symbols, as the system keyboard's) or a diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Palette.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Palette.swift new file mode 100644 index 00000000..8e49ed8d --- /dev/null +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Palette.swift @@ -0,0 +1,16 @@ +import BlurtiOSCore + +extension KeyboardModel { + /// The chosen theme's palette in the host's appearance — or, for a + /// preview, the face it is told (`faceOverride`). + var palette: KeyboardPalette { + .resolve(faceOverride?.themeID ?? themeID, dark: faceOverride?.dark ?? isDark) + } +} + +extension ThemeFace { + /// The face a palette is: what a preview hands the model to draw it. + init(_ palette: KeyboardPalette) { + self.init(themeID: palette.id, dark: palette.face == .dark) + } +} diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardRootView.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardRootView.swift index cb618a3b..62699b27 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardRootView.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardRootView.swift @@ -1,3 +1,4 @@ +import BlurtiOSCore import SwiftUI /// Picks the layout the user chose. All three share the voice bar and the diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift index 1dc5cb8c..f3b2345c 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardViewController.swift @@ -1,3 +1,4 @@ +import BlurtiOSCore import SwiftUI import UIKit diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/MicControl.swift b/App/BlurtiOS/BlurtKeyboard/Sources/MicControl.swift index 61dad790..d57bd875 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/MicControl.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/MicControl.swift @@ -1,3 +1,4 @@ +import BlurtiOSCore import SwiftUI /// The mic key. Finger down starts, finger up decides tap (latched) or hold diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/PanelCarousel.swift b/App/BlurtiOS/BlurtKeyboard/Sources/PanelCarousel.swift index 14e4bdaa..a3c18d51 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/PanelCarousel.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/PanelCarousel.swift @@ -1,3 +1,4 @@ +import BlurtiOSCore import SwiftUI /// The panel's two pages — the mic panel and the full keyboard — as a strip diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/PanelView.swift b/App/BlurtiOS/BlurtKeyboard/Sources/PanelView.swift index 0e614d67..da574873 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/PanelView.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/PanelView.swift @@ -1,3 +1,4 @@ +import BlurtiOSCore import SwiftUI /// The voice element, big, dead centre — or at the edge Settings chose — with diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/SlimBarView.swift b/App/BlurtiOS/BlurtKeyboard/Sources/SlimBarView.swift index 9311a2a1..10197fcb 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/SlimBarView.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/SlimBarView.swift @@ -1,3 +1,4 @@ +import BlurtiOSCore import SwiftUI /// One row: the globe (when the phone doesn't draw its own), the voice bar, diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/TermField.swift b/App/BlurtiOS/BlurtKeyboard/Sources/TermField.swift index e1471a65..9e02ec4d 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/TermField.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/TermField.swift @@ -1,3 +1,4 @@ +import BlurtiOSCore import SwiftUI /// The voice bar as a field — the brand's input, a rectangle with a hairline, diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift index c72128d7..215ebc44 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceBar.swift @@ -1,3 +1,4 @@ +import BlurtiOSCore import SwiftUI /// The keyboard's voice row, and the only place voice lives in the bar and diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceElement.swift b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceElement.swift index 9270e5da..9512cb81 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceElement.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceElement.swift @@ -1,27 +1,6 @@ +import BlurtiOSCore import SwiftUI -/// The mic control's face — the one part of the keyboard that says what is -/// happening, without a word. Three concepts are built side by side behind -/// this seam so they can be judged on sight from the same states, the same -/// level and the same landing moment; the one that ships stays, the others -/// go. Pick with `-BlurtGalleryVoice a|b|c` (DESIGN.md › The voice element). -nonisolated enum VoiceElementKind: String, CaseIterable, Sendable { - /// A: the grille — a dot-matrix mic head that lights as a stepped meter. - case grille = "a" - /// B: the ribs — the thin wave asleep as a ribbed grille, awake as the wave. - case ribs = "b" - /// C: the streak — a hairline with a bright point that blooms into a light streak. - case streak = "c" - - static let shipped = VoiceElementKind.grille - - /// `-BlurtGalleryVoice a|b|c`, or nil when the arguments don't say. - static func parse(_ arguments: [String]) -> VoiceElementKind? { - guard let flag = arguments.firstIndex(of: "-BlurtGalleryVoice"), arguments.count > flag + 1 else { return nil } - return VoiceElementKind(rawValue: arguments[flag + 1]) - } -} - /// Where the element sits, for the sizes that differ. nonisolated enum VoiceSlot: String, CaseIterable, Sendable { case bar diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceGrille.swift b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceGrille.swift index b88546fd..27e00751 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceGrille.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceGrille.swift @@ -1,4 +1,5 @@ import BlurtEngine +import BlurtiOSCore import SwiftUI /// Candidate A — the grille. A dot-matrix mic head: a lattice of small dots diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceRibs.swift b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceRibs.swift index c091542c..43192bd5 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceRibs.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceRibs.swift @@ -1,3 +1,4 @@ +import BlurtiOSCore import SwiftUI /// Candidate B — the ribs. The mic at rest is a short block of vertical ribs: diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceRow.swift b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceRow.swift index 280deec8..2dfa27ec 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceRow.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceRow.swift @@ -1,3 +1,4 @@ +import BlurtiOSCore import SwiftUI /// The voice row's arithmetic, out of the views, so the bar, the panel and diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceStreak.swift b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceStreak.swift index dad09113..cd755bed 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceStreak.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/VoiceStreak.swift @@ -1,3 +1,4 @@ +import BlurtiOSCore import SwiftUI /// Candidate C — the streak. The flare as the meter: at rest a hairline the diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/WaveformMeter.swift b/App/BlurtiOS/BlurtKeyboard/Sources/WaveformMeter.swift index 2af18f4f..0d5fa14b 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/WaveformMeter.swift +++ b/App/BlurtiOS/BlurtKeyboard/Sources/WaveformMeter.swift @@ -1,4 +1,5 @@ import BlurtEngine +import BlurtiOSCore import SwiftUI /// The Mac pill's live meter: a row of bars that fills the width it is given diff --git a/App/BlurtiOS/BlurtiOS/Sources/BlurtiOSApp.swift b/App/BlurtiOS/BlurtiOS/Sources/BlurtiOSApp.swift index 6d81ffa0..e8dd7066 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/BlurtiOSApp.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/BlurtiOSApp.swift @@ -1,4 +1,5 @@ import BlurtEngine +import BlurtiOSCore import SwiftUI @main diff --git a/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift b/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift index 000326a9..6d3305a9 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/DictationCoordinator.swift @@ -1,5 +1,6 @@ import AVFoundation import BlurtEngine +import BlurtiOSCore import Foundation import Observation import Synchronization diff --git a/App/BlurtiOS/BlurtiOS/Sources/HomeHero.swift b/App/BlurtiOS/BlurtiOS/Sources/HomeHero.swift index 6ba26603..2d01121f 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/HomeHero.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/HomeHero.swift @@ -1,3 +1,4 @@ +import BlurtiOSCore import SwiftUI /// The hero: the status as an eyebrow, a serif headline and a line of body diff --git a/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift b/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift index be65377c..19b3a438 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/HomeView.swift @@ -1,5 +1,6 @@ import AVFoundation import BlurtEngine +import BlurtiOSCore import SwiftUI /// The app's one screen: the Blurt landing page on a phone. The wordmark and diff --git a/App/BlurtiOS/BlurtiOS/Sources/ImportTermsView.swift b/App/BlurtiOS/BlurtiOS/Sources/ImportTermsView.swift index 6ad1e85d..d88de63d 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/ImportTermsView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/ImportTermsView.swift @@ -1,3 +1,4 @@ +import BlurtiOSCore import SwiftUI /// "Add these key terms?" — what a shared list opens into. Every term is diff --git a/App/BlurtiOS/BlurtiOS/Sources/KeyEntryView.swift b/App/BlurtiOS/BlurtiOS/Sources/KeyEntryView.swift index 5ff60cb9..823c6afd 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/KeyEntryView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/KeyEntryView.swift @@ -1,4 +1,5 @@ import BlurtEngine +import BlurtiOSCore import SwiftUI /// Paste an AssemblyAI API key, verified against the API before it is saved diff --git a/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift b/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift index c6a6c7ed..eb61569a 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/KeyboardGalleryView.swift @@ -1,3 +1,5 @@ +import BlurtiOSCore + #if DEBUG import SwiftUI @@ -137,7 +139,7 @@ model.layout = layout model.voiceKindOverride = voice model.micAlignmentOverride = align - model.paletteOverride = .resolve(KeyboardPalette.brandID, dark: Self.darkFaces.contains(theme)) + model.faceOverride = ThemeFace(themeID: KeyboardPalette.brandID, dark: Self.darkFaces.contains(theme)) // `keys` shows the panel's carousel flipped to its keyboard page; // `term` the voice bar as the key-term field, mid-typing. model.panelShowsKeys = state == "keys" || state == "symbols" diff --git a/App/BlurtiOS/BlurtiOS/Sources/KeyboardProbeView.swift b/App/BlurtiOS/BlurtiOS/Sources/KeyboardProbeView.swift index 053c25e1..280ba2b3 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/KeyboardProbeView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/KeyboardProbeView.swift @@ -1,3 +1,5 @@ +import BlurtiOSCore + #if DEBUG import SwiftUI import UIKit diff --git a/App/BlurtiOS/BlurtiOS/Sources/ListeningWindow.swift b/App/BlurtiOS/BlurtiOS/Sources/ListeningWindow.swift index 74ecf235..27358b55 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/ListeningWindow.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/ListeningWindow.swift @@ -1,4 +1,5 @@ import AVFoundation +import BlurtiOSCore import Foundation import Observation diff --git a/App/BlurtiOS/BlurtiOS/Sources/SettingsView.swift b/App/BlurtiOS/BlurtiOS/Sources/SettingsView.swift index ddb02948..d37bc0d7 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/SettingsView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/SettingsView.swift @@ -1,4 +1,5 @@ import BlurtEngine +import BlurtiOSCore import SwiftUI /// Everything adjustable, grouped the way the Mac's Settings are: the keyboard diff --git a/App/BlurtiOS/BlurtiOS/Sources/ThemePickerView.swift b/App/BlurtiOS/BlurtiOS/Sources/ThemePickerView.swift index 8c60a5b6..de227131 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/ThemePickerView.swift +++ b/App/BlurtiOS/BlurtiOS/Sources/ThemePickerView.swift @@ -1,3 +1,4 @@ +import BlurtiOSCore import SwiftUI /// Pick a keyboard theme from live previews: a card per theme, each the real @@ -78,7 +79,7 @@ private struct ThemeCard: View { model.hasFullAccess = true model.isListening = true model.needsGlobe = true - model.paletteOverride = palette + model.faceOverride = ThemeFace(palette) return model } } diff --git a/App/BlurtiOS/BlurtiOS/Sources/APIKeyModel.swift b/App/BlurtiOS/BlurtiOSCore/APIKeyModel.swift similarity index 93% rename from App/BlurtiOS/BlurtiOS/Sources/APIKeyModel.swift rename to App/BlurtiOS/BlurtiOSCore/APIKeyModel.swift index 0755ad4e..0cb42974 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/APIKeyModel.swift +++ b/App/BlurtiOS/BlurtiOSCore/APIKeyModel.swift @@ -16,7 +16,7 @@ import Observation /// themselves live in the engine's `APIKeySubmission`, where `swift test` covers /// them; this type just forwards and mirrors the result into `hasAPIKey`. @Observable -final class APIKeyModel { +package final class APIKeyModel { /// Storage for the API key. Production hits the Keychain via `APIKeyStore`; /// UI tests inject an in-memory store so the real key is never touched. @ObservationIgnored private let keyStore: any APIKeyGateway @@ -28,7 +28,7 @@ final class APIKeyModel { /// Whether an AssemblyAI API key is currently saved. Drives the wizard (which /// gates dictation on having a key) and the Settings UI. - private(set) var hasAPIKey: Bool + package private(set) var hasAPIKey: Bool /// `validateKey` defaults to the engine's real AssemblyAI check; UI tests /// inject an offline validator so the settings flow needs no network. @@ -36,7 +36,7 @@ final class APIKeyModel { /// The `hasKey` read below also loads the Keychain memo (`APIKeyStore.current`), /// so every later readiness check on the press→recording latency path is /// served from memory instead of paying a cold `SecItemCopyMatching`. - init( + package init( keyStore: any APIKeyGateway = ProductionAPIKeyStore(), validateKey: @escaping @Sendable (String) async -> APIKeyValidator.Result = { await APIKeyValidator().validate($0) @@ -51,7 +51,7 @@ final class APIKeyModel { /// with no key saved fails fast as `.failed(.apiKeyMissing)` before any capture. /// Captures the (Sendable) store, not this main-actor model, so it can cross /// into the session's `@Sendable` closure. - func readinessCheck() -> @Sendable () -> BlurtError? { + package func readinessCheck() -> @Sendable () -> BlurtError? { let keyStore = keyStore return { keyStore.hasKey ? nil : .apiKeyMissing } } @@ -64,7 +64,7 @@ final class APIKeyModel { /// already present flips `hasAPIKey` true, so the wizard advances to the ready /// screen instead of stranding the user on a setup step whose only control (a /// *changed*-key "Update") is disabled. - func refreshStatus() { + package func refreshStatus() { let hasKey = keyStore.hasKey if hasKey != hasAPIKey { hasAPIKey = hasKey } } @@ -73,7 +73,7 @@ final class APIKeyModel { /// actively accepts it (`.valid`) — the engine's `APIKeySubmission` owns /// (and unit-tests) that never-persist-an-unverified-key rule. Mirrors the /// outcome into `hasAPIKey` so the wizard/Settings UI reacts. - func submit(_ key: String) async -> APIKeySubmission.Outcome { + package func submit(_ key: String) async -> APIKeySubmission.Outcome { let outcome = await submission.submit(key) refreshStatus() return outcome diff --git a/App/BlurtiOS/Shared/DarwinObserver.swift b/App/BlurtiOS/BlurtiOSCore/DarwinObserver.swift similarity index 89% rename from App/BlurtiOS/Shared/DarwinObserver.swift rename to App/BlurtiOS/BlurtiOSCore/DarwinObserver.swift index 97aaa495..9e350cad 100644 --- a/App/BlurtiOS/Shared/DarwinObserver.swift +++ b/App/BlurtiOS/BlurtiOSCore/DarwinObserver.swift @@ -6,11 +6,11 @@ import Foundation /// `@Sendable` for that reason; hop to the main actor inside it when the work /// is UI. A class rather than a token so `deinit` can deregister — a listener /// left behind outlives its owner, since the system holds the callback. -nonisolated final class DarwinObserver: Sendable { +package nonisolated final class DarwinObserver: Sendable { private let name: String private let handler: @Sendable () -> Void - init(name: String, handler: @escaping @Sendable () -> Void) { + package init(name: String, handler: @escaping @Sendable () -> Void) { self.name = name self.handler = handler let observer = Unmanaged.passUnretained(self).toOpaque() diff --git a/App/BlurtiOS/BlurtiOS/Sources/HomeStatus.swift b/App/BlurtiOS/BlurtiOSCore/HomeStatus.swift similarity index 89% rename from App/BlurtiOS/BlurtiOS/Sources/HomeStatus.swift rename to App/BlurtiOS/BlurtiOSCore/HomeStatus.swift index b36275b6..8205a17c 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/HomeStatus.swift +++ b/App/BlurtiOS/BlurtiOSCore/HomeStatus.swift @@ -4,15 +4,15 @@ import Foundation /// What the home screen says about the app's state, in words: the headline, /// the line under it, whether setup is complete, whether the last dictation /// just landed. Pure, so the wording is tested and the view only lays it out. -nonisolated struct HomeStatus: Equatable { - let title: String - let subtitle: String +package nonisolated struct HomeStatus: Equatable { + package let title: String + package let subtitle: String /// A key, the microphone and the keyboard, all in place. - let isSetUp: Bool + package let isSetUp: Bool /// The words just went in (or to the clipboard): the hero's moment. - let landed: Bool + package let landed: Bool - init( + package init( overlay: OverlayUIState, windowOpen: Bool, until: Date?, hasKey: Bool, micGranted: Bool, keyboardSeen: Bool ) { title = Self.title(overlay, windowOpen: windowOpen) diff --git a/App/BlurtiOS/Shared/KeyTermList.swift b/App/BlurtiOS/BlurtiOSCore/KeyTermList.swift similarity index 78% rename from App/BlurtiOS/Shared/KeyTermList.swift rename to App/BlurtiOS/BlurtiOSCore/KeyTermList.swift index 47c3c860..cc212d1a 100644 --- a/App/BlurtiOS/Shared/KeyTermList.swift +++ b/App/BlurtiOS/BlurtiOSCore/KeyTermList.swift @@ -3,8 +3,8 @@ import Foundation /// The comma-separated key-term list, as the engine's `KeyTermsStore` reads /// it: split, trimmed, emptied of blanks, deduplicated case-insensitively in /// first-seen order. -nonisolated enum KeyTermList { - static func parse(_ raw: String) -> [String] { +package nonisolated enum KeyTermList { + package static func parse(_ raw: String) -> [String] { var seen = Set() var terms: [String] = [] for piece in raw.split(separator: ",") { @@ -15,7 +15,7 @@ nonisolated enum KeyTermList { return terms } - static func join(_ terms: [String]) -> String { + package static func join(_ terms: [String]) -> String { terms.joined(separator: ", ") } } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardInteraction.swift b/App/BlurtiOS/BlurtiOSCore/KeyboardInteraction.swift similarity index 74% rename from App/BlurtiOS/BlurtKeyboard/Sources/KeyboardInteraction.swift rename to App/BlurtiOS/BlurtiOSCore/KeyboardInteraction.swift index bf778bc8..05531b18 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardInteraction.swift +++ b/App/BlurtiOS/BlurtiOSCore/KeyboardInteraction.swift @@ -7,50 +7,50 @@ import Foundation /// mic key waits a beat before it presses, so a swipe that starts on it never /// starts a dictation it must then cancel; a horizontal swipe flips the /// panel's carousel. -nonisolated enum KeyboardInteraction { +package nonisolated enum KeyboardInteraction { /// The most a touch may travel and still be a tap on a key. - static let tapTravel: CGFloat = 12 + package static let tapTravel: CGFloat = 12 /// A touch on the mic that travelled this far was a swipe, not a press. - static let micTravel: CGFloat = 24 + package static let micTravel: CGFloat = 24 /// A swipe flips the panel once it has gone this far sideways… - static let swipeDistance: CGFloat = 48 + package static let swipeDistance: CGFloat = 48 /// …and more sideways than up or down, by this factor. - static let swipeRatio: CGFloat = 1.5 + package static let swipeRatio: CGFloat = 1.5 /// How long a touch must stay before it counts as a press rather than the /// start of a swipe — well under a tap's own duration for a hold. - static let micPressDelay: Duration = .milliseconds(90) + package static let micPressDelay: Duration = .milliseconds(90) - enum FlipDirection: Equatable { + package enum FlipDirection: Equatable { /// The finger moved left: the incoming page arrives from the trailing edge. case towardsLeading case towardsTrailing } /// Which way the panel flips for this drag, or nil if the drag was not a swipe. - static func flip(_ translation: CGSize) -> FlipDirection? { + package static func flip(_ translation: CGSize) -> FlipDirection? { let dx = translation.width guard abs(dx) > swipeDistance, abs(dx) > abs(translation.height) * swipeRatio else { return nil } return dx < 0 ? .towardsLeading : .towardsTrailing } - static func isTap(_ translation: CGSize) -> Bool { + package static func isTap(_ translation: CGSize) -> Bool { abs(translation.width) < tapTravel && abs(translation.height) < tapTravel } /// How far past a key's edge a finger may end and still have tapped it. - static let tapSlop: CGFloat = 8 + package static let tapSlop: CGFloat = 8 /// A key's tap: the finger barely moved, or it ended on the key (within /// `tapSlop` of its edges) wherever it went in between — a thumb that rolls /// still types, as on the system keyboard, while a swipe that left the key /// (the panel's carousel) does not. `location` is in the key's own space. - static func isTap(_ translation: CGSize, endedAt location: CGPoint, in size: CGSize) -> Bool { + package static func isTap(_ translation: CGSize, endedAt location: CGPoint, in size: CGSize) -> Bool { if isTap(translation) { return true } guard size.width > 0, size.height > 0 else { return false } return CGRect(origin: .zero, size: size).insetBy(dx: -tapSlop, dy: -tapSlop).contains(location) } - static func micTravelled(_ translation: CGSize) -> Bool { + package static func micTravelled(_ translation: CGSize) -> Bool { abs(translation.width) > micTravel || abs(translation.height) > micTravel } } @@ -60,8 +60,8 @@ nonisolated enum KeyboardInteraction { /// still a tap (press and release together); a swipe cancels the timer, or /// undoes a press that already went out; nothing else happens. The view owns /// the timer and the model calls; this owns the decisions. -nonisolated struct MicPressSequencer: Equatable { - enum Outcome: Equatable { +package nonisolated struct MicPressSequencer: Equatable { + package enum Outcome: Equatable { /// Release the key: send the press first if the timer never fired. case tap(needsDown: Bool) /// A swipe after the press went out: undo it. @@ -70,12 +70,14 @@ nonisolated struct MicPressSequencer: Equatable { case nothing } - private(set) var pressed = false - private(set) var timerArmed = false - private(set) var pressSent = false + package private(set) var pressed = false + package private(set) var timerArmed = false + package private(set) var pressSent = false + + package init() {} /// The finger touched (or moved, again). True the first time: arm the timer. - mutating func began() -> Bool { + package mutating func began() -> Bool { guard !pressed else { return false } pressed = true timerArmed = true @@ -84,14 +86,14 @@ nonisolated struct MicPressSequencer: Equatable { /// The finger moved. True when the timer must be cancelled: it travelled /// before the press went out. - mutating func moved(travelled: Bool) -> Bool { + package mutating func moved(travelled: Bool) -> Bool { guard travelled, timerArmed, !pressSent else { return false } timerArmed = false return true } /// The timer fired. True when the press goes out now. - mutating func delayFired() -> Bool { + package mutating func delayFired() -> Bool { guard pressed, timerArmed else { return false } timerArmed = false pressSent = true @@ -99,7 +101,7 @@ nonisolated struct MicPressSequencer: Equatable { } /// The finger lifted. - mutating func ended(travelled: Bool) -> Outcome { + package mutating func ended(travelled: Bool) -> Outcome { defer { self = MicPressSequencer() } if travelled { return pressSent ? .cancelSentPress : .nothing } return .tap(needsDown: !pressSent) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Field.swift b/App/BlurtiOS/BlurtiOSCore/KeyboardModel+Field.swift similarity index 79% rename from App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Field.swift rename to App/BlurtiOS/BlurtiOSCore/KeyboardModel+Field.swift index 6e154ebe..a8bafe77 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Field.swift +++ b/App/BlurtiOS/BlurtiOSCore/KeyboardModel+Field.swift @@ -6,11 +6,11 @@ import UIKit extension KeyboardModel { /// What the field asked for, the way the system keyboard honours it: the /// return key's own word, and the symbols page first for a number field. - func readField() { + package func readField() { returnLabel = proxy?.returnKeyType.flatMap(Self.returnLabel) } - func readAppearance() { + package func readAppearance() { switch proxy?.keyboardAppearance { case .dark: isDark = true case .light: isDark = false @@ -20,7 +20,7 @@ extension KeyboardModel { /// Number, decimal and phone fields open on the symbols page, as the system /// keyboard would show a number pad. - static func wantsSymbols(_ type: UIKeyboardType?) -> Bool { + package static func wantsSymbols(_ type: UIKeyboardType?) -> Bool { switch type { case .numberPad, .decimalPad, .phonePad, .numbersAndPunctuation, .asciiCapableNumberPad: true default: false @@ -28,10 +28,10 @@ extension KeyboardModel { } /// iOS's own words for the return key, by the type the field asked for. - static let returnLabels: [UIReturnKeyType: String] = [ + package static let returnLabels: [UIReturnKeyType: String] = [ .go: "go", .google: "search", .yahoo: "search", .search: "search", .join: "join", .next: "next", .route: "route", .send: "send", .done: "done", .emergencyCall: "call", .continue: "continue", ] - static func returnLabel(_ type: UIReturnKeyType) -> String? { returnLabels[type] } + package static func returnLabel(_ type: UIReturnKeyType) -> String? { returnLabels[type] } } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Mic.swift b/App/BlurtiOS/BlurtiOSCore/KeyboardModel+Mic.swift similarity index 87% rename from App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Mic.swift rename to App/BlurtiOS/BlurtiOSCore/KeyboardModel+Mic.swift index b791c2c9..b6c1a4cb 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Mic.swift +++ b/App/BlurtiOS/BlurtiOSCore/KeyboardModel+Mic.swift @@ -6,15 +6,15 @@ import UIKit extension KeyboardModel { /// Whether a tap on the orb can do anything but open the app. - var isReady: Bool { hasFullAccess && isListening } + package var isReady: Bool { hasFullAccess && isListening } /// What the voice control shows, from the phase the app published. - var voiceState: VoiceState { VoiceState(snapshot: snapshot, isReady: isReady) } + package var voiceState: VoiceState { VoiceState(snapshot: snapshot, isReady: isReady) } /// Finger down on the orb. Ignored, with a buzz, while the last dictation /// is still being transcribed: a press then would be dropped by the engine /// and the user would talk into nothing. - func micDown() { + package func micDown() { guard isReady else { return } switch snapshot.state { case .connecting, .processing: @@ -30,19 +30,19 @@ extension KeyboardModel { /// is missing (opening the app needs no Full Access; everything else does). /// The gate comes up either way, so a press the finger made while the app /// was still there is never left armed. - func micUp() { + package func micUp() { perform(gate.modifierUp(at: elapsed)) if !isReady { openApp() } } - func cancel() { + package func cancel() { gate.reset() send(.cancel) } - var elapsed: Duration { clockStart.duration(to: ContinuousClock.now) } + package var elapsed: Duration { clockStart.duration(to: ContinuousClock.now) } - func perform(_ action: DictationKeyGate.Action) { + package func perform(_ action: DictationKeyGate.Action) { switch action { case .start: send(.press) case .stop: @@ -60,7 +60,7 @@ extension KeyboardModel { } } - func send(_ kind: KeyboardCommand.Kind) { + package func send(_ kind: KeyboardCommand.Kind) { let command = KeyboardCommand( id: UUID(), kind: kind, priorText: proxy?.documentContextBeforeInput, selectedText: proxy?.selectedText, sentAt: Date(), keyboard: instanceID) @@ -89,7 +89,7 @@ extension KeyboardModel { /// than `BlurtShared.commandFreshnessWindow` unread, and an app that was /// killed answers nothing — so its latch can't outlive it. True when it did. @discardableResult - func expireUnansweredPress(now: Date = Date()) -> Bool { + package func expireUnansweredPress(now: Date = Date()) -> Bool { guard unansweredPress != nil, let sentAt = unansweredPressSentAt, now.timeIntervalSince(sentAt) >= BlurtShared.commandFreshnessWindow else { return false } @@ -103,7 +103,7 @@ extension KeyboardModel { /// a press over a recording a tap had latched only re-latches it, so /// flipping to the keys mid-dictation doesn't throw the words away; a press /// the orb ignored (busy, or Blurt not ready) undoes nothing. - func undoPress() { + package func undoPress() { perform(gate.otherKeyDown()) } } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Phase.swift b/App/BlurtiOS/BlurtiOSCore/KeyboardModel+Phase.swift similarity index 95% rename from App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Phase.swift rename to App/BlurtiOS/BlurtiOSCore/KeyboardModel+Phase.swift index 70c8e4eb..1f42e71b 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Phase.swift +++ b/App/BlurtiOS/BlurtiOSCore/KeyboardModel+Phase.swift @@ -5,12 +5,12 @@ import UIKit // MARK: - What comes back from the app: phase, results, haptics extension KeyboardModel { - func phaseChanged() { + package func phaseChanged() { guard let current = SharedStore.read(PhaseSnapshot.self, forKey: BlurtShared.Key.phase) else { return } apply(current.isStale ? .idle : current) } - func apply(_ current: PhaseSnapshot, haptics wantsHaptics: Bool = true) { + package func apply(_ current: PhaseSnapshot, haptics wantsHaptics: Bool = true) { // A notice the keyboard already let go of (its dwell ran out) is not // replayed by a second read of the same snapshot. if let dismissedNoticeAt, current.at == dismissedNoticeAt { return } @@ -74,7 +74,7 @@ extension KeyboardModel { } } - func resultArrived() { + package func resultArrived() { guard let result = SharedStore.read(DictationResult.self, forKey: BlurtShared.Key.result), result.id != lastResultID, let proxy, Date().timeIntervalSince(result.deliveredAt) < Self.resultFreshnessWindow, @@ -96,7 +96,7 @@ extension KeyboardModel { readSelection() } - func haptics(from previous: PhaseSnapshot.State, to state: PhaseSnapshot.State) { + package func haptics(from previous: PhaseSnapshot.State, to state: PhaseSnapshot.State) { guard hasFullAccess else { return } switch state { case .recording: diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Typing.swift b/App/BlurtiOS/BlurtiOSCore/KeyboardModel+Typing.swift similarity index 90% rename from App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Typing.swift rename to App/BlurtiOS/BlurtiOSCore/KeyboardModel+Typing.swift index 643fe4ea..9050773a 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel+Typing.swift +++ b/App/BlurtiOS/BlurtiOSCore/KeyboardModel+Typing.swift @@ -5,7 +5,7 @@ import UIKit // MARK: - Typing and the app extension KeyboardModel { - func type(_ text: String) { + package func type(_ text: String) { UIDevice.current.playInputClick() if termDraft != nil { termDraft?.append(text) @@ -24,7 +24,7 @@ extension KeyboardModel { readSelection() } - func deleteBackward() { + package func deleteBackward() { UIDevice.current.playInputClick() if termDraft != nil { _ = termDraft?.popLast() @@ -35,7 +35,7 @@ extension KeyboardModel { typedIntoHost() } - func newline() { + package func newline() { UIDevice.current.playInputClick() if termDraft != nil { saveTerm() @@ -49,11 +49,11 @@ extension KeyboardModel { /// The most characters a highlighted word may have and still be offered as /// a key term: a name or a phrase, not a sentence. - static let termLengthCap = 48 + package static let termLengthCap = 48 /// A selection as a key term: trimmed, on one line, short enough to be a /// name or a phrase. Nil when it is none of those, or nothing is selected. - static func termCandidate(from selected: String?) -> String? { + package static func termCandidate(from selected: String?) -> String? { guard let trimmed = selected?.trimmingCharacters(in: .whitespacesAndNewlines), !trimmed.isEmpty, trimmed.count <= termLengthCap, !trimmed.contains(where: \.isNewline) else { return nil } @@ -65,7 +65,7 @@ extension KeyboardModel { /// with Full Access — without it there is nothing the chip could do. A word /// the chip is done with (`dismissedSelection`) shows no chip while the /// same highlight stands. - func readSelection() { + package func readSelection() { guard hasFullAccess, let term = Self.termCandidate(from: proxy?.selectedText) else { selectedTerm = nil selectedTermIsKnown = false @@ -90,7 +90,7 @@ extension KeyboardModel { /// highlight or not: the host may keep the word highlighted for as long as /// the user leaves it, and a chip that stayed with it read as stuck. A tap /// on a chip for a word Blurt already has puts the + back at once. - func addSelectedTerm() { + package func addSelectedTerm() { guard let term = selectedTerm else { return } guard !selectedTermIsKnown else { dismissSelection() @@ -103,7 +103,7 @@ extension KeyboardModel { /// The chip is done with the highlighted word: the + comes back and stays /// back while that highlight stands (`KeyboardModel.dismissedSelection`). - func dismissSelection() { + package func dismissSelection() { dismissedSelection = selectedTerm selectedTerm = nil selectedTermIsKnown = false @@ -120,7 +120,7 @@ extension KeyboardModel { /// Words already being transcribed follow the same rule: from the plain + /// they still land (the mic is off; there is nothing to stop), from a /// highlighted word they are cancelled. - func beginAddingTerm() { + package func beginAddingTerm() { let seed = Self.termCandidate(from: proxy?.selectedText) ?? "" switch snapshot.state { case .recording: perform(seed.isEmpty ? .stop : .cancel) @@ -144,7 +144,7 @@ extension KeyboardModel { onLayoutChange?() } - func cancelAddingTerm() { + package func cancelAddingTerm() { termDraft = nil termDraftFromSelection = nil termHostBaseline = nil @@ -158,7 +158,7 @@ extension KeyboardModel { /// Saves the term to Blurt's key terms — read on the very next dictation — /// and, when it began as a selection, puts it into the text in place of the /// misheard word. - func saveTerm() { + package func saveTerm() { guard let draft = termDraft?.trimmingCharacters(in: .whitespacesAndNewlines), !draft.isEmpty else { cancelAddingTerm() return @@ -215,11 +215,11 @@ extension KeyboardModel { } /// How long the + (or the chip) shows its check after a term was saved. - static let termNoticeDwell: TimeInterval = 1.2 + package static let termNoticeDwell: TimeInterval = 1.2 /// A space — or, tapped twice quickly after a word, the system keyboard's /// "." shortcut: the first space becomes a full stop and a space. - func space() { + package func space() { UIDevice.current.playInputClick() if termDraft != nil { if termDraft?.isEmpty == false, termDraft?.hasSuffix(" ") == false { termDraft?.append(" ") } @@ -242,21 +242,21 @@ extension KeyboardModel { updateShift() } - func toggleShift() { shifted.toggle() } + package func toggleShift() { shifted.toggle() } /// 123 / ABC: the symbols come up on their first page, or the letters return. - func toggleSymbols() { + package func toggleSymbols() { symbolsPage.toggle() morePage = false } /// #+= / 123: between the two symbol pages; nothing on the letters. - func toggleMore() { + package func toggleMore() { guard symbolsPage else { return } morePage.toggle() } - func globe() { controller?.advanceToNextInputMode() } + package func globe() { controller?.advanceToNextInputMode() } /// Brings the app forward to open the microphone — the one thing a keyboard /// cannot do for itself. iOS gives extensions no `UIApplication.shared`, so @@ -264,14 +264,14 @@ extension KeyboardModel { /// way every keyboard that opens its app does. With `open(_:options:)`: since /// iOS 18 the old `openURL:` only logs "BUG IN CLIENT OF UIKIT" and opens /// nothing. - func openApp() { + package func openApp() { guard let controller, let url = URL(string: "\(BlurtShared.urlScheme)://\(BlurtShared.startHost)") else { return } var responder: UIResponder? = controller while let current = responder { if let application = current as? UIApplication { - application.open(url, options: [:], completionHandler: nil) + urlOpener(application, url) return } responder = current.next @@ -280,13 +280,13 @@ extension KeyboardModel { } /// The three letter rows, by the language the user types in most. -nonisolated enum LetterLayout { - static let qwerty = ["qwertyuiop", "asdfghjkl", "zxcvbnm"] - static let azerty = ["azertyuiop", "qsdfghjklm", "wxcvbn"] - static let qwertz = ["qwertzuiop", "asdfghjkl", "yxcvbnm"] +package nonisolated enum LetterLayout { + package static let qwerty = ["qwertyuiop", "asdfghjkl", "zxcvbnm"] + package static let azerty = ["azertyuiop", "qsdfghjklm", "wxcvbn"] + package static let qwertz = ["qwertzuiop", "asdfghjkl", "yxcvbnm"] /// From the phone's own language order — no setting to make. - static func forPreferredLanguages(_ languages: [String] = Locale.preferredLanguages) -> [String] { + package static func forPreferredLanguages(_ languages: [String] = Locale.preferredLanguages) -> [String] { guard let first = languages.first?.lowercased() else { return qwerty } if first.hasPrefix("fr") { return azerty } if ["de", "cs", "sk", "hu"].contains(where: { first.hasPrefix($0) }) { return qwertz } diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift b/App/BlurtiOS/BlurtiOSCore/KeyboardModel.swift similarity index 78% rename from App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift rename to App/BlurtiOS/BlurtiOSCore/KeyboardModel.swift index 1bd39bac..97208f93 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardModel.swift +++ b/App/BlurtiOS/BlurtiOSCore/KeyboardModel.swift @@ -13,138 +13,143 @@ import UIKit /// push-to-talk exactly as on the Mac. @MainActor @Observable -final class KeyboardModel { +package final class KeyboardModel { /// How old a result may be and still be inserted. Darwin notifications are /// held for a suspended process and delivered when it resumes, so the /// keyboard inside the app the user *left* hears about a dictation done /// elsewhere minutes later; anything older than this is not its to insert. - static let resultFreshnessWindow: TimeInterval = 10 + package static let resultFreshnessWindow: TimeInterval = 10 /// The phone's word list is re-read at most this often. Contacts change by /// the day, and reading thousands of them on every appearance is what the /// keyboard's memory budget cannot afford. - static let lexiconRefreshInterval: TimeInterval = 60 * 60 + package static let lexiconRefreshInterval: TimeInterval = 60 * 60 - var layout: KeyboardLayout = .panel + package var layout: KeyboardLayout = .panel /// The panel is a two-page carousel — the mic panel and the full keyboard — /// flipped by a swipe in either direction, as often as you like. Which page /// is up; back to the mic each time the keyboard appears. - var panelShowsKeys = false + package var panelShowsKeys = false /// The direction of the last flip, so the pages slide the way the finger went. - var flipTowardsLeading = false - var snapshot = PhaseSnapshot.idle + package var flipTowardsLeading = false + package var snapshot = PhaseSnapshot.idle /// When this keyboard last put the words into the field — the orb's drop. - var resultLandedAt: Date? + package var resultLandedAt: Date? /// The key term being typed on the keys, while the voice bar is a field; /// nil otherwise. See `beginAddingTerm`. - var termDraft: String? + package var termDraft: String? /// When the last term was saved, so the bar can show a check for a moment. - var termSavedAt: Date? + package var termSavedAt: Date? /// The word highlighted in the host's text, when it could be a key term /// (`termCandidate`) and the key terms are in reach (Full Access): the + /// grows into a chip holding it, and one tap adds it. Read off the proxy /// on every context change (`readSelection`); the gallery sets it. - var selectedTerm: String? + package var selectedTerm: String? /// Whether `selectedTerm` is already one of Blurt's key terms: the chip /// shows a check and adds nothing. - var selectedTermIsKnown = false + package var selectedTermIsKnown = false /// The field's own return key, as iOS labels it: "send", "search", "go"… - var returnLabel: String? + package var returnLabel: String? /// The letter rows for the user's first keyboard language (AZERTY for /// French, QWERTZ for German and its neighbours, QWERTY otherwise). - var letterRows = LetterLayout.qwerty - var isListening = false - var hasFullAccess = false - var needsGlobe = true - var shifted = true - var symbolsPage = false + package var letterRows = LetterLayout.qwerty + package var isListening = false + package var hasFullAccess = false + package var needsGlobe = true + package var shifted = true + package var symbolsPage = false /// The symbols' second page (#+=), only while `symbolsPage`. - var morePage = false + package var morePage = false // Internal, not private: the model's typing, mic and phase halves live in // KeyboardModel+Typing/+Mic/+Phase.swift. - @ObservationIgnored weak var controller: UIInputViewController? + @ObservationIgnored package weak var controller: UIInputViewController? @ObservationIgnored private var observers: [DarwinObserver] = [] - @ObservationIgnored var gate = DictationKeyGate() - @ObservationIgnored let clockStart = ContinuousClock.now - @ObservationIgnored var lastResultID: UUID? + @ObservationIgnored package var gate = DictationKeyGate() + @ObservationIgnored package let clockStart = ContinuousClock.now + @ObservationIgnored package var lastResultID: UUID? @ObservationIgnored private var heartbeat: Task? - @ObservationIgnored var lastSpaceAt: ContinuousClock.Instant? - @ObservationIgnored var noticeDwell: Task? + @ObservationIgnored package var lastSpaceAt: ContinuousClock.Instant? + @ObservationIgnored package var noticeDwell: Task? /// This keyboard process, for results addressed to it (`DictationResult.recipient`). - @ObservationIgnored let instanceID = UUID().uuidString + @ObservationIgnored package let instanceID = UUID().uuidString + /// How `openApp` asks the application object, once the responder chain + /// reaches it: a test's capture in place of really opening the app. + @ObservationIgnored var urlOpener: (UIApplication, URL) -> Void = { application, url in + application.open(url, options: [:], completionHandler: nil) + } /// Where commands go: the App Group, or a test's capture. - @ObservationIgnored var transport: (KeyboardCommand) -> Void = { command in + @ObservationIgnored package var transport: (KeyboardCommand) -> Void = { command in SharedStore.write(command, forKey: BlurtShared.Key.command) SharedStore.post(BlurtShared.Signal.command) } /// A press that got no phase back is re-signalled once (a Darwin /// notification can be missed), after this long. - static let commandRetryDelay: Duration = .milliseconds(600) - @ObservationIgnored var commandRetry: Task? - @ObservationIgnored var termDraftFromSelection: String? + package static let commandRetryDelay: Duration = .milliseconds(600) + @ObservationIgnored package var commandRetry: Task? + @ObservationIgnored package var termDraftFromSelection: String? /// A highlighted word the chip is done with — added, or its ✓ tapped — /// while the host still shows it highlighted: the + is back, and stays /// back until the highlight moves to another word or goes. - @ObservationIgnored var dismissedSelection: String? + @ObservationIgnored package var dismissedSelection: String? /// The text before and after the cursor when the term field opened, so /// typing that reaches the host field anyway (a hardware keyboard: an /// iPad's, a Bluetooth one, the simulator's Mac) can be pulled into the /// term instead — and a cursor move, which changes both sides, cannot be /// mistaken for it. - @ObservationIgnored var termHostBaseline: String? - @ObservationIgnored var termHostBaselineAfter: String? - @ObservationIgnored var termNotice: Task? + @ObservationIgnored package var termHostBaseline: String? + @ObservationIgnored package var termHostBaselineAfter: String? + @ObservationIgnored package var termNotice: Task? /// A release made while the mic was still coming up (the engine drops /// one before it records): held, and sent on the first recording phase. - @ObservationIgnored var releasePending = false + @ObservationIgnored package var releasePending = false /// The press the app has not answered yet. A settled phase that does not /// answer it (the previous dictation's notice landing late) leaves the /// gate alone; anything in flight, or a phase carrying its id, answers it. - @ObservationIgnored var unansweredPress: UUID? + @ObservationIgnored package var unansweredPress: UUID? /// When `unansweredPress` went out. Past `BlurtShared.commandFreshnessWindow` /// the app drops it unread (or was never there to read it), so no answer /// is coming: see `expireUnansweredPress`. - @ObservationIgnored var unansweredPressSentAt: Date? + @ObservationIgnored package var unansweredPressSentAt: Date? /// The `at` of a notice the keyboard already let go of: a re-read of the /// same snapshot cannot replay it. - @ObservationIgnored var dismissedNoticeAt: Date? + @ObservationIgnored package var dismissedNoticeAt: Date? /// The host's text field. Tests hand in a fake in place of a controller. - var proxy: (any UITextDocumentProxy)? { proxyOverride ?? controller?.textDocumentProxy } - @ObservationIgnored var proxyOverride: (any UITextDocumentProxy)? + package var proxy: (any UITextDocumentProxy)? { proxyOverride ?? controller?.textDocumentProxy } + @ObservationIgnored package var proxyOverride: (any UITextDocumentProxy)? - /// The chosen theme's palette in the host's appearance — or, for a - /// preview, whatever it is told. - var palette: KeyboardPalette { paletteOverride ?? .resolve(themeID, dark: isDark) } - var themeID = SharedStore.themeID - var paletteOverride: KeyboardPalette? + /// The chosen theme, by id. Its colours are the shell's: `palette` + /// (KeyboardModel+Palette.swift) resolves this, in the host's appearance. + package var themeID = SharedStore.themeID + /// For a preview: this theme face, whatever Settings and the host say. + package var faceOverride: ThemeFace? /// TEMPORARY: which mic concept draws, from Settings — or, for a preview /// or a gallery row, whatever it is told. Goes with the losers. - var voiceKind: VoiceElementKind { voiceKindOverride ?? storedVoiceKind } - var storedVoiceKind = SharedStore.voiceElementKind - var voiceKindOverride: VoiceElementKind? + package var voiceKind: VoiceElementKind { voiceKindOverride ?? storedVoiceKind } + package var storedVoiceKind = SharedStore.voiceElementKind + package var voiceKindOverride: VoiceElementKind? /// Where the mic key sits across the row, from Settings (one hand: at the /// thumb's edge) — or, for a preview or a gallery row, whatever it is told. - var micAlignment: MicAlignment { micAlignmentOverride ?? storedMicAlignment } - var storedMicAlignment = SharedStore.micAlignment - var micAlignmentOverride: MicAlignment? + package var micAlignment: MicAlignment { micAlignmentOverride ?? storedMicAlignment } + package var storedMicAlignment = SharedStore.micAlignment + package var micAlignmentOverride: MicAlignment? /// Whether the app being typed in wants a dark keyboard: what its field /// asks for, else the app's own light or dark appearance. - var isDark = false + package var isDark = false /// What is actually on screen: the panel's carousel may be showing its /// keys, and typing a key term needs them whatever the layout. - var effectiveLayout: KeyboardLayout { + package var effectiveLayout: KeyboardLayout { if termDraft != nil { return .full } return layout == .panel && panelShowsKeys ? .full : layout } /// Told when `effectiveLayout` changes, so the host can resize the keyboard. - @ObservationIgnored var onLayoutChange: (() -> Void)? + @ObservationIgnored package var onLayoutChange: (() -> Void)? /// A horizontal swipe on the panel: flip to the other page, sliding the way /// the finger went. - func flipPanel(towardsLeading: Bool) { + package func flipPanel(towardsLeading: Bool) { // Only the panel has two pages, and not while the keys are up for a term. guard layout == .panel, termDraft == nil else { return } flipTowardsLeading = towardsLeading @@ -154,16 +159,18 @@ final class KeyboardModel { /// Whether the phase leaves nothing in flight — the moments the gate has to /// be reset, since a dictation can end with no finger event to close it. - var isSettled: Bool { + package var isSettled: Bool { switch snapshot.state { case .idle, .pasted, .copied, .error: true case .connecting, .recording, .processing: false } } + package init() {} + // MARK: - Lifecycle - func attach(to controller: UIInputViewController) { + package func attach(to controller: UIInputViewController) { self.controller = controller observers = [ DarwinObserver(name: BlurtShared.Signal.phase) { [weak self] in @@ -175,7 +182,7 @@ final class KeyboardModel { ] } - func appeared() { + package func appeared() { // Without a controller (a test's model) the access stays as it was set. hasFullAccess = controller?.hasFullAccess ?? hasFullAccess needsGlobe = controller?.needsInputModeSwitchKey ?? true @@ -248,7 +255,7 @@ final class KeyboardModel { /// is off, and a cancel would throw them away. Presence ends, so a result /// that finishes after this goes to the clipboard rather than to a keyboard /// nobody can see. - func disappeared() { + package func disappeared() { heartbeat?.cancel() heartbeat = nil commandRetry?.cancel() @@ -272,7 +279,7 @@ final class KeyboardModel { /// The cursor moved or the text around it changed, including by our own /// typing: re-read where the sentence stands and what the field wants. - func contextChanged() { + package func contextChanged() { readAppearance() readField() readSelection() @@ -311,7 +318,7 @@ final class KeyboardModel { /// Auto-capitalisation, as the system keyboard does it: shift comes on at /// the start of a sentence (or of every word, or always) according to what /// the field asks for, and goes off after one letter. - func updateShift() { + package func updateShift() { if let termDraft { // A key term is usually a name, or two: capitalised to start and after // a space, then as typed. @@ -329,7 +336,7 @@ final class KeyboardModel { } } - static func isSentenceStart(_ before: String) -> Bool { + package static func isSentenceStart(_ before: String) -> Bool { let trimmed = before.reversed().drop { $0 == " " } guard let last = trimmed.first else { return true } return last == "\n" || ".?!".contains(last) @@ -372,7 +379,9 @@ final class KeyboardModel { // over, and read it on the main actor. controller?.requestSupplementaryLexicon { @Sendable lexicon in let handoff = LexiconHandoff(lexicon) - Task { @MainActor in Self.store(handoff.lexicon) } + Task { @MainActor in + Self.store(handoff.lexicon.entries.map { LexiconEntry(userInput: $0.userInput, documentText: $0.documentText) }) + } } } @@ -381,10 +390,9 @@ final class KeyboardModel { init(_ lexicon: UILexicon) { self.lexicon = lexicon } } - private static func store(_ lexicon: UILexicon) { - let entries = lexicon.entries.map { - LexiconEntry(userInput: $0.userInput, documentText: $0.documentText) - } + /// Hands the word list to the app: written to the App Group, stamped, and + /// signalled, so the next dictation spells the names right. + static func store(_ entries: [LexiconEntry]) { SharedStore.write(entries, forKey: BlurtShared.Key.lexicon) SharedStore.lexiconRefreshedAt = Date() SharedStore.post(BlurtShared.Signal.lexicon) diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardMotion.swift b/App/BlurtiOS/BlurtiOSCore/KeyboardMotion.swift similarity index 81% rename from App/BlurtiOS/BlurtKeyboard/Sources/KeyboardMotion.swift rename to App/BlurtiOS/BlurtiOSCore/KeyboardMotion.swift index 833b7734..9c1e1390 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/KeyboardMotion.swift +++ b/App/BlurtiOS/BlurtiOSCore/KeyboardMotion.swift @@ -5,4 +5,4 @@ import Foundation /// meter's idle wave, the glints. The Mac pill reads the same number from /// the engine: the level feed moves at this cadence, so drawing faster only /// burns the keyboard's tight energy and memory budget. -let keyboardAnimationInterval = MicCapture.meterIntervalSeconds +package let keyboardAnimationInterval = MicCapture.meterIntervalSeconds diff --git a/App/BlurtiOS/BlurtiOS/Sources/KeyboardRelayInjector.swift b/App/BlurtiOS/BlurtiOSCore/KeyboardRelayInjector.swift similarity index 81% rename from App/BlurtiOS/BlurtiOS/Sources/KeyboardRelayInjector.swift rename to App/BlurtiOS/BlurtiOSCore/KeyboardRelayInjector.swift index 7023aa3d..6e10b65a 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/KeyboardRelayInjector.swift +++ b/App/BlurtiOS/BlurtiOSCore/KeyboardRelayInjector.swift @@ -14,18 +14,22 @@ import UIKit /// The text goes over as returned: the keyboard applies /// `InsertionSeparator.withLeadingSeparator` against the *live* text before the /// cursor, which may have moved since the press. -nonisolated struct KeyboardRelayInjector: InjectorProtocol { +package nonisolated struct KeyboardRelayInjector: InjectorProtocol { /// How long the keyboard gets to insert before the clipboard takes over. - static let deliveryTimeout: TimeInterval = 3 - static let deliveryPoll: Duration = .milliseconds(250) + package static let deliveryTimeout: TimeInterval = 3 + package static let deliveryPoll: Duration = .milliseconds(250) /// The keyboard the dictation in flight was pressed in /// (`KeyboardCommand.keyboard`), or nil for whichever keyboard is up. - var presser: @Sendable () -> String? = { nil } + package var presser: @Sendable () -> String? = { nil } - func setTarget(_ focus: CapturedFocus?) async {} + package init(presser: @escaping @Sendable () -> String? = { nil }) { + self.presser = presser + } + + package func setTarget(_ focus: CapturedFocus?) async {} - func insert(_ text: String, after priorText: String?, windowTitle: String?) async throws { + package func insert(_ text: String, after priorText: String?, windowTitle: String?) async throws { // The words go to the keyboard that asked for them. If the user has // moved on — another app's keyboard is the one on screen now — they go // to the clipboard rather than into a field nobody dictated into. diff --git a/App/BlurtiOS/Shared/MicAlignment.swift b/App/BlurtiOS/BlurtiOSCore/MicAlignment.swift similarity index 51% rename from App/BlurtiOS/Shared/MicAlignment.swift rename to App/BlurtiOS/BlurtiOSCore/MicAlignment.swift index 0ca8a067..fde1ab02 100644 --- a/App/BlurtiOS/Shared/MicAlignment.swift +++ b/App/BlurtiOS/BlurtiOSCore/MicAlignment.swift @@ -1,18 +1,18 @@ -import SwiftUI +import Foundation /// Where the mic key sits across the keyboard, for one hand: at the left /// edge, in the middle (the default), or at the right edge. Left and right /// are the phone's own sides — the side the thumb is on — whatever the /// language reads in (Settings → Keyboard, under the layout; the keyboard /// reads it on appearance). -nonisolated enum MicAlignment: String, CaseIterable, Codable, Sendable, Identifiable { +package nonisolated enum MicAlignment: String, CaseIterable, Codable, Sendable, Identifiable { case left case center case right - var id: String { rawValue } + package var id: String { rawValue } - var title: String { + package var title: String { switch self { case .left: "Left alignment" case .center: "Default" @@ -20,7 +20,7 @@ nonisolated enum MicAlignment: String, CaseIterable, Codable, Sendable, Identifi } } - var summary: String { + package var summary: String { switch self { case .left: "The mic key at the left edge of the keyboard, under your thumb." case .center: "The mic key in the middle of the keyboard." @@ -30,25 +30,8 @@ nonisolated enum MicAlignment: String, CaseIterable, Codable, Sendable, Identifi } extension MicAlignment { - /// The side of the row, as SwiftUI counts sides: left is the leading edge - /// in a left-to-right language and the trailing one in a right-to-left - /// one, so the mic stays under the thumb the user chose either way. - func alignment(in direction: LayoutDirection) -> Alignment { - switch self { - case .center: .center - case .left: direction == .leftToRight ? .leading : .trailing - case .right: direction == .leftToRight ? .trailing : .leading - } - } - - /// Whether the + goes before the mic in the row: at the trailing edge, so - /// the mic is the thing at the edge and the + sits on its inner side. - func plusLeads(in direction: LayoutDirection) -> Bool { - alignment(in: direction) == .trailing - } - /// `-BlurtGalleryAlign left|center|right`, or nil when the arguments don't say. - static func parse(_ arguments: [String]) -> MicAlignment? { + package static func parse(_ arguments: [String]) -> MicAlignment? { guard let flag = arguments.firstIndex(of: "-BlurtGalleryAlign"), arguments.count > flag + 1 else { return nil } return MicAlignment(rawValue: arguments[flag + 1]) } diff --git a/App/BlurtiOS/Shared/SharedState.swift b/App/BlurtiOS/BlurtiOSCore/SharedState.swift similarity index 74% rename from App/BlurtiOS/Shared/SharedState.swift rename to App/BlurtiOS/BlurtiOSCore/SharedState.swift index 7e8bf218..1ccb65db 100644 --- a/App/BlurtiOS/Shared/SharedState.swift +++ b/App/BlurtiOS/BlurtiOSCore/SharedState.swift @@ -8,54 +8,54 @@ import Foundation /// through the App Group's shared defaults and wake each other with Darwin /// notifications — a system-wide "something changed" ping that carries no data, /// so every payload lives in the defaults under one of the keys below. -nonisolated enum BlurtShared { +package nonisolated enum BlurtShared { /// The App Group both targets declare. A placeholder namespace inherited from /// the Mac app; an org-owned id replaces it before the App Store, and the app /// and the keyboard must change together. - static let appGroup = "group.dev.alex.blurt" + package static let appGroup = "group.dev.alex.blurt" /// The URL the keyboard opens to bring the app forward (`blurt://start`) — /// the one moment iOS insists on before the microphone may open. - static let urlScheme = "blurt" - static let startHost = "start" + package static let urlScheme = "blurt" + package static let startHost = "start" /// A press command older than this was held while the app was suspended: /// the app drops it unanswered, and the keyboard stops waiting for an answer. - static let commandFreshnessWindow: TimeInterval = 10 + package static let commandFreshnessWindow: TimeInterval = 10 - nonisolated enum Key { - static let layout = "keyboardLayout" - static let autoDictate = "autoDictate" - static let theme = "keyboardTheme" + package nonisolated enum Key { + package static let layout = "keyboardLayout" + package static let autoDictate = "autoDictate" + package static let theme = "keyboardTheme" /// TEMPORARY: which mic concept draws (a, b or c), while the three are /// tried in use. Goes with the losers once one is picked. - static let voiceElement = "voiceElement" + package static let voiceElement = "voiceElement" /// Where the mic key sits across the keyboard (`MicAlignment`). - static let micAlignment = "micAlignment" - static let listeningUntil = "listeningUntil" - static let windowMinutes = "listeningWindowMinutes" - static let phase = "phase" - static let command = "command" - static let result = "result" - static let keyboardSeenAt = "keyboardSeenAt" - static let keyboardInstance = "keyboardInstance" - static let appSeenAt = "appSeenAt" - static let keyboardEverSeen = "keyboardEverSeen" - static let lexicon = "lexicon" - static let lexiconRefreshedAt = "lexiconRefreshedAt" + package static let micAlignment = "micAlignment" + package static let listeningUntil = "listeningUntil" + package static let windowMinutes = "listeningWindowMinutes" + package static let phase = "phase" + package static let command = "command" + package static let result = "result" + package static let keyboardSeenAt = "keyboardSeenAt" + package static let keyboardInstance = "keyboardInstance" + package static let appSeenAt = "appSeenAt" + package static let keyboardEverSeen = "keyboardEverSeen" + package static let lexicon = "lexicon" + package static let lexiconRefreshedAt = "lexiconRefreshedAt" } /// Darwin notification names. Reverse-DNS so they can't collide with another /// app's on the same device. - nonisolated enum Signal { - static let command = "dev.alex.blurt.ios.command" - static let phase = "dev.alex.blurt.ios.phase" - static let result = "dev.alex.blurt.ios.result" - static let lexicon = "dev.alex.blurt.ios.lexicon" + package nonisolated enum Signal { + package static let command = "dev.alex.blurt.ios.command" + package static let phase = "dev.alex.blurt.ios.phase" + package static let result = "dev.alex.blurt.ios.result" + package static let lexicon = "dev.alex.blurt.ios.lexicon" } } /// Which keyboard the user chose. All three share the same plumbing underneath; /// they differ only in how much keyboard sits around the mic. -nonisolated enum KeyboardLayout: String, CaseIterable, Codable, Sendable, Identifiable { +package nonisolated enum KeyboardLayout: String, CaseIterable, Codable, Sendable, Identifiable { /// A slim strip: the mic, delete, return and the globe. Typing letters means /// switching back to the system keyboard. case slimBar @@ -66,9 +66,9 @@ nonisolated enum KeyboardLayout: String, CaseIterable, Codable, Sendable, Identi /// keyboards to fix a typo. case full - var id: String { rawValue } + package var id: String { rawValue } - var title: String { + package var title: String { switch self { case .slimBar: "Mic bar" case .panel: "Mic panel" @@ -76,26 +76,13 @@ nonisolated enum KeyboardLayout: String, CaseIterable, Codable, Sendable, Identi } } - var summary: String { + package var summary: String { switch self { case .slimBar: "Just the mic and a few keys. Switch keyboards to type." case .panel: "A big mic with status and cancel. Swipe sideways for the full keyboard, and back." case .full: "Every letter key, with the orb above them." } } - - /// The keyboard's height on screen, from the layout's rows at the iPhone - /// keyboard's own spacing: see `App/BlurtiOS/DESIGN.md` for the arithmetic. - var height: CGFloat { - let metrics = DesignTokens.Metrics.self - return switch self { - case .slimBar: 2 * metrics.marginVertical + metrics.voicebarHeight - case .panel: metrics.layoutPanel - case .full: - metrics.marginVertical + metrics.voicebarHeight + 4 * metrics.keyHeight + 3 * metrics.rowGap - + metrics.marginBottomKeys - } - } } // MARK: - Payloads @@ -107,40 +94,40 @@ nonisolated enum KeyboardLayout: String, CaseIterable, Codable, Sendable, Identi /// What the keyboard asks the app to do, with the context only the keyboard can /// see: the text before the cursor primes the transcript exactly as the Mac's /// Accessibility read does. -nonisolated struct KeyboardCommand: Codable, Sendable { - nonisolated enum Kind: String, Codable, Sendable { +package nonisolated struct KeyboardCommand: Codable, Sendable { + package nonisolated enum Kind: String, Codable, Sendable { case press case release case cancel } - let id: UUID - let kind: Kind - let priorText: String? - let selectedText: String? - let sentAt: Date + package let id: UUID + package let kind: Kind + package let priorText: String? + package let selectedText: String? + package let sentAt: Date /// The keyboard process that sent it (`KeyboardModel.instanceID`): the /// words come back to the field the press was made in, not whichever is up. - let keyboard: String? + package let keyboard: String? } /// The words the app got back, for the keyboard to insert. The keyboard joins /// them onto the live text before the cursor itself (`InsertionSeparator`), /// since the user may have typed since the press. -nonisolated struct DictationResult: Codable, Sendable { - let id: UUID - let text: String - let deliveredAt: Date +package nonisolated struct DictationResult: Codable, Sendable { + package let id: UUID + package let text: String + package let deliveredAt: Date /// The keyboard instance the words are for — the one whose heartbeat the /// app last saw — so a second live keyboard in another app doesn't also /// insert them. Nil means whoever is up. - let recipient: String? + package let recipient: String? } /// What the keyboard shows while the app works: the pipeline's phase, flattened /// to what the orb can show, plus the live microphone level. -nonisolated struct PhaseSnapshot: Codable, Sendable, Equatable { - nonisolated enum State: String, Codable, Sendable { +package nonisolated struct PhaseSnapshot: Codable, Sendable, Equatable { + package nonisolated enum State: String, Codable, Sendable { case idle case connecting case recording @@ -150,18 +137,18 @@ nonisolated struct PhaseSnapshot: Codable, Sendable, Equatable { case error } - let state: State - let message: String? - let level: Double - let at: Date + package let state: State + package let message: String? + package let level: Double + package let at: Date /// The keyboard command the app last took when it published this — the /// press this phase answers, or the release or cancel that ended it. The /// keyboard settles its gate only for the press it is waiting on: a notice /// from the *previous* dictation landing a moment after a new press must /// not read as that press being over. - let command: UUID? + package let command: UUID? - init(state: State, message: String?, level: Double, at: Date, command: UUID? = nil) { + package init(state: State, message: String?, level: Double, at: Date, command: UUID? = nil) { self.state = state self.message = message self.level = level @@ -169,12 +156,12 @@ nonisolated struct PhaseSnapshot: Codable, Sendable, Equatable { self.command = command } - static let idle = PhaseSnapshot(state: .idle, message: nil, level: 0, at: .distantPast) + package static let idle = PhaseSnapshot(state: .idle, message: nil, level: 0, at: .distantPast) /// How long a notice stays on the orb before it settles back to idle — the /// Mac's 0.8 s / 1.6 s dwell, a little longer since a phone has no hover to /// reveal more. Nil for the states that end on their own. - var noticeDwellSeconds: Double? { + package var noticeDwellSeconds: Double? { switch state { case .pasted: 1.2 case .copied, .error: 2.0 @@ -188,9 +175,9 @@ nonisolated struct PhaseSnapshot: Codable, Sendable, Equatable { /// keyboard reads the snapshot back on every appearance and on every signal, /// including signals held while it was suspended, so it must decide for /// itself. - var isStale: Bool { isStale(now: Date()) } + package var isStale: Bool { isStale(now: Date()) } - func isStale(now: Date) -> Bool { + package func isStale(now: Date) -> Bool { let age = now.timeIntervalSince(at) switch state { case .idle: return false @@ -200,22 +187,22 @@ nonisolated struct PhaseSnapshot: Codable, Sendable, Equatable { } /// The longest notice dwell (2 s) plus a second of slack. - static let noticeStaleAfter: TimeInterval = 3 + package static let noticeStaleAfter: TimeInterval = 3 /// The engine's 120 s cap on one dictation, plus ten seconds for the /// transcript to come back. - static let inFlightStaleAfter: TimeInterval = 130 + package static let inFlightStaleAfter: TimeInterval = 130 } /// One entry of the phone's own word list (`UILexicon`): contact names and the /// user's text replacements. Names go to the request as key terms so they come /// back spelled right; replacements are the phone's own text shortcuts. -nonisolated struct LexiconEntry: Codable, Sendable { - let userInput: String - let documentText: String +package nonisolated struct LexiconEntry: Codable, Sendable { + package let userInput: String + package let documentText: String /// Contact names come through with both fields equal; a text replacement /// has a shortcut on one side and its expansion on the other. - var isName: Bool { userInput == documentText } + package var isName: Bool { userInput == documentText } } // MARK: - Shared defaults @@ -223,39 +210,39 @@ nonisolated struct LexiconEntry: Codable, Sendable { /// Typed access to the App Group's defaults, usable from any thread — the /// keyboard writes from the main actor, the app's capture path reads from /// wherever the engine calls it. -nonisolated enum SharedStore { +package nonisolated enum SharedStore { /// The App Group's defaults — what both processes read and write. Falls /// back to the process's own only where the group is out of reach (a /// keyboard without Full Access), so nothing crashes; nothing is shared then. /// Tests point this at a throwaway suite (`override`) so they never touch /// the real one. - static var defaults: UserDefaults { override ?? shared } + package static var defaults: UserDefaults { override ?? shared } nonisolated(unsafe) static var override: UserDefaults? // `UserDefaults` is thread-safe by contract; the type just isn't marked Sendable. nonisolated(unsafe) private static let shared = UserDefaults(suiteName: BlurtShared.appGroup) ?? .standard - static func write(_ value: Value, forKey key: String) { + package static func write(_ value: Value, forKey key: String) { guard let data = try? JSONEncoder().encode(value) else { return } defaults.set(data, forKey: key) } - static func read(_ type: Value.Type, forKey key: String) -> Value? { + package static func read(_ type: Value.Type, forKey key: String) -> Value? { guard let data = defaults.data(forKey: key) else { return nil } return try? JSONDecoder().decode(type, from: data) } - static func remove(forKey key: String) { + package static func remove(forKey key: String) { defaults.removeObject(forKey: key) } - static var layout: KeyboardLayout { + package static var layout: KeyboardLayout { get { KeyboardLayout(rawValue: defaults.string(forKey: BlurtShared.Key.layout) ?? "") ?? .panel } set { defaults.set(newValue.rawValue, forKey: BlurtShared.Key.layout) } } /// Which keyboard theme (`KeyboardPalette.id`); the iPhone's own until one /// is picked. - static var themeID: String { + package static var themeID: String { get { defaults.string(forKey: BlurtShared.Key.theme) ?? "system" } set { defaults.set(newValue, forKey: BlurtShared.Key.theme) } } @@ -263,20 +250,20 @@ nonisolated enum SharedStore { /// TEMPORARY: the mic concept to draw — `VoiceElementKind.rawValue`, the /// shipped one until Settings says otherwise. Read by the keyboard on every /// appearance and by the home screen live. Goes with the losers. - static var voiceElementKind: VoiceElementKind { + package static var voiceElementKind: VoiceElementKind { get { VoiceElementKind(rawValue: defaults.string(forKey: BlurtShared.Key.voiceElement) ?? "") ?? .shipped } set { defaults.set(newValue.rawValue, forKey: BlurtShared.Key.voiceElement) } } /// Where the mic key sits across the keyboard; the middle until chosen. - static var micAlignment: MicAlignment { + package static var micAlignment: MicAlignment { get { MicAlignment(rawValue: defaults.string(forKey: BlurtShared.Key.micAlignment) ?? "") ?? .center } set { defaults.set(newValue.rawValue, forKey: BlurtShared.Key.micAlignment) } } /// Hands-free: the keyboard starts a dictation the moment it appears in a /// text field, so there is nothing to tap before talking. On by default. - static var autoDictate: Bool { + package static var autoDictate: Bool { get { guard defaults.object(forKey: BlurtShared.Key.autoDictate) != nil else { return true } return defaults.bool(forKey: BlurtShared.Key.autoDictate) @@ -286,7 +273,7 @@ nonisolated enum SharedStore { /// How long a listening window stays open with nobody dictating, in minutes. /// 0 means until the user closes it. - static var windowMinutes: Int { + package static var windowMinutes: Int { get { guard defaults.object(forKey: BlurtShared.Key.windowMinutes) != nil else { return 15 } return defaults.integer(forKey: BlurtShared.Key.windowMinutes) @@ -294,7 +281,7 @@ nonisolated enum SharedStore { set { defaults.set(newValue, forKey: BlurtShared.Key.windowMinutes) } } - static var listeningUntil: Date? { + package static var listeningUntil: Date? { get { defaults.object(forKey: BlurtShared.Key.listeningUntil) as? Date } set { defaults.set(newValue, forKey: BlurtShared.Key.listeningUntil) } } @@ -307,30 +294,30 @@ nonisolated enum SharedStore { /// the window. The window is more than twice the heartbeat, so one missed /// beat — a busy main thread, a suspended process resuming — doesn't read /// as absence, while a killed process reads as absent within seconds. - static let appHeartbeatInterval: TimeInterval = 5 - static let keyboardHeartbeatInterval: TimeInterval = 4 - static let presenceWindow: TimeInterval = 15 + package static let appHeartbeatInterval: TimeInterval = 5 + package static let keyboardHeartbeatInterval: TimeInterval = 4 + package static let presenceWindow: TimeInterval = 15 /// Whether the app currently has the microphone open for the keyboard: the /// window has not lapsed, and the app is still there to hear — iOS may have /// killed it, or a phone call taken the microphone, with the window's end /// still in the future. The keyboard then opens the app rather than sending /// a press nobody would answer. - static var isListening: Bool { isListening(now: Date()) } + package static var isListening: Bool { isListening(now: Date()) } - static func isListening(now: Date) -> Bool { + package static func isListening(now: Date) -> Bool { guard (listeningUntil ?? .distantPast) > now else { return false } return now.timeIntervalSince(appSeenAt ?? .distantPast) < presenceWindow } /// Whether a keyboard is on screen to take the words (see `presenceWindow`). - static var isKeyboardPresent: Bool { + package static var isKeyboardPresent: Bool { Date().timeIntervalSince(keyboardSeenAt ?? .distantPast) < presenceWindow } /// Which keyboard process is on screen — a fresh id per process, written /// with its heartbeat — so a result can be addressed to it. - static var keyboardInstance: String? { + package static var keyboardInstance: String? { get { defaults.string(forKey: BlurtShared.Key.keyboardInstance) } set { defaults.set(newValue, forKey: BlurtShared.Key.keyboardInstance) } } @@ -341,19 +328,19 @@ nonisolated enum SharedStore { /// right — under the engine's own key (`KeyTermsStore.defaultsKey`, /// `BlurtKeyTerms`, comma-separated) but in the App Group, so the keyboard /// can add one on the spot and the app reads it on the very next press. - static var keyTerms: [String] { + package static var keyTerms: [String] { get { KeyTermList.parse(defaults.string(forKey: keyTermsKey) ?? "") } set { defaults.set(KeyTermList.join(newValue), forKey: keyTermsKey) } } /// `BlurtKeyTerms` — spelled out here rather than imported from the engine so /// the keyboard, which links it too, and the app can't disagree. - static let keyTermsKey = "BlurtKeyTerms" + package static let keyTermsKey = "BlurtKeyTerms" /// Adds a term unless it is already there (case-insensitively). Returns /// whether the list changed. @discardableResult - static func addKeyTerm(_ term: String) -> Bool { + package static func addKeyTerm(_ term: String) -> Bool { let trimmed = term.trimmingCharacters(in: .whitespacesAndNewlines) guard !trimmed.isEmpty else { return false } var terms = keyTerms @@ -363,32 +350,32 @@ nonisolated enum SharedStore { return true } - static var appSeenAt: Date? { + package static var appSeenAt: Date? { get { defaults.object(forKey: BlurtShared.Key.appSeenAt) as? Date } set { defaults.set(newValue, forKey: BlurtShared.Key.appSeenAt) } } - static var keyboardSeenAt: Date? { + package static var keyboardSeenAt: Date? { get { defaults.object(forKey: BlurtShared.Key.keyboardSeenAt) as? Date } set { defaults.set(newValue, forKey: BlurtShared.Key.keyboardSeenAt) } } /// When the keyboard last copied the phone's word list into the App Group. - static var lexiconRefreshedAt: Date? { + package static var lexiconRefreshedAt: Date? { get { defaults.object(forKey: BlurtShared.Key.lexiconRefreshedAt) as? Date } set { defaults.set(newValue, forKey: BlurtShared.Key.lexiconRefreshedAt) } } /// Set by the keyboard the first time it runs with Full Access — the only /// public-API way the app can tell that the keyboard was added and allowed. - static var keyboardEverSeen: Bool { + package static var keyboardEverSeen: Bool { get { defaults.bool(forKey: BlurtShared.Key.keyboardEverSeen) } set { defaults.set(newValue, forKey: BlurtShared.Key.keyboardEverSeen) } } /// Fires a Darwin notification. Carries nothing: the receiver reads the /// payload back out of these defaults. - static func post(_ signal: String) { + package static func post(_ signal: String) { CFNotificationCenterPostNotification( CFNotificationCenterGetDarwinNotifyCenter(), CFNotificationName(signal as CFString), nil, nil, true) } diff --git a/App/BlurtiOS/BlurtiOS/Sources/TermPack.swift b/App/BlurtiOS/BlurtiOSCore/TermPack.swift similarity index 77% rename from App/BlurtiOS/BlurtiOS/Sources/TermPack.swift rename to App/BlurtiOS/BlurtiOSCore/TermPack.swift index be28fd8d..aa82b731 100644 --- a/App/BlurtiOS/BlurtiOS/Sources/TermPack.swift +++ b/App/BlurtiOS/BlurtiOSCore/TermPack.swift @@ -5,28 +5,34 @@ import UniformTypeIdentifiers extension UTType { /// A shared list of Blurt key terms: JSON, `.blurtterms`, declared in /// `project.yml` so a tap on one in Messages opens Blurt. - nonisolated static let blurtTerms = UTType(exportedAs: "dev.alex.blurt.terms", conformingTo: .json) + package nonisolated static let blurtTerms = UTType(exportedAs: "dev.alex.blurt.terms", conformingTo: .json) } /// A list of key terms on its way to a friend — a group chat's names and /// slang, so everyone's dictation gets them right. Shared as a `.blurtterms` /// file (the share sheet writes it), opened by a tap; also readable from a /// `blurt://terms?add=a,b,c&name=…&from=…` link. -nonisolated struct TermPack: Codable, Identifiable, Transferable { - var name: String - var from: String? - var terms: [String] +package nonisolated struct TermPack: Codable, Identifiable, Transferable { + package var name: String + package var from: String? + package var terms: [String] - var id: String { "\(name)|\(from ?? "")|\(terms.joined(separator: ","))" } + package init(name: String, from: String?, terms: [String]) { + self.name = name + self.from = from + self.terms = terms + } + + package var id: String { "\(name)|\(from ?? "")|\(terms.joined(separator: ","))" } /// The request's own cap on key terms (`keyterms_prompt`, 100), which is /// also as many as a list is worth; a file over this size, or a term, name /// or sender longer than a line, is refused. - static let termCap = 100 - static let fileCap = 64 * 1024 - static let lengthCap = 80 + package static let termCap = 100 + package static let fileCap = 64 * 1024 + package static let lengthCap = 80 - static var transferRepresentation: some TransferRepresentation { + package static var transferRepresentation: some TransferRepresentation { FileRepresentation(exportedContentType: .blurtTerms) { pack in let url = FileManager.default.temporaryDirectory .appendingPathComponent(pack.fileStem, isDirectory: false) @@ -38,7 +44,9 @@ nonisolated struct TermPack: Codable, Identifiable, Transferable { } } - private var fileStem: String { + /// The shared file's name: the list's name with anything a file name can't + /// carry taken out, or a plain one when nothing is left. + var fileStem: String { let stem = name.components(separatedBy: CharacterSet.alphanumerics.union(.whitespaces).inverted).joined() .trimmingCharacters(in: .whitespaces) return stem.isEmpty ? "Blurt key terms" : stem @@ -46,7 +54,7 @@ nonisolated struct TermPack: Codable, Identifiable, Transferable { /// The list as plain text, for the message beside the file — a friend /// without Blurt still gets the words. - var plainText: String { + package var plainText: String { let lead = from.map { "\($0)'s Blurt key terms" } ?? "Blurt key terms" return "\(lead) (\(name)): \(KeyTermList.join(terms))" } @@ -54,7 +62,7 @@ nonisolated struct TermPack: Codable, Identifiable, Transferable { /// Whether a URL is meant to be a pack at all — a `.blurtterms` file or a /// `blurt://terms` link — so a broken one can be reported rather than /// ignored. - static func looksLikePack(_ url: URL) -> Bool { + package static func looksLikePack(_ url: URL) -> Bool { if url.isFileURL { return url.pathExtension.lowercased() == "blurtterms" } return url.scheme == BlurtShared.urlScheme && url.host() == "terms" } @@ -62,7 +70,7 @@ nonisolated struct TermPack: Codable, Identifiable, Transferable { /// A pack from a file tapped in Messages or a `blurt://terms` link; nil for /// anything else the app is asked to open, or a pack over the caps. A file /// iOS handed over in the app's Inbox is deleted once read. - static func from(_ url: URL) -> TermPack? { + package static func from(_ url: URL) -> TermPack? { guard looksLikePack(url) else { return nil } if url.isFileURL { defer { if url.path.contains("/Inbox/") { try? FileManager.default.removeItem(at: url) } } diff --git a/App/BlurtiOS/BlurtiOSCore/ThemeFace.swift b/App/BlurtiOS/BlurtiOSCore/ThemeFace.swift new file mode 100644 index 00000000..7e35ecfc --- /dev/null +++ b/App/BlurtiOS/BlurtiOSCore/ThemeFace.swift @@ -0,0 +1,14 @@ +import Foundation + +/// One face of a keyboard theme — its id and whether it is the dark one — +/// with no colours attached: the keyboard model holds a choice, and the shell +/// turns it into a palette (`KeyboardPalette.resolve`). +package nonisolated struct ThemeFace: Equatable, Sendable { + package var themeID: String + package var dark: Bool + + package init(themeID: String, dark: Bool) { + self.themeID = themeID + self.dark = dark + } +} diff --git a/App/BlurtiOS/BlurtiOSCore/VoiceElementKind.swift b/App/BlurtiOS/BlurtiOSCore/VoiceElementKind.swift new file mode 100644 index 00000000..e3b129cd --- /dev/null +++ b/App/BlurtiOS/BlurtiOSCore/VoiceElementKind.swift @@ -0,0 +1,23 @@ +import Foundation + +/// The mic control's face — the one part of the keyboard that says what is +/// happening, without a word. Three concepts are built side by side behind +/// this seam so they can be judged on sight from the same states, the same +/// level and the same landing moment; the one that ships stays, the others +/// go. Pick with `-BlurtGalleryVoice a|b|c` (DESIGN.md › The voice element). +package nonisolated enum VoiceElementKind: String, CaseIterable, Sendable { + /// A: the grille — a dot-matrix mic head that lights as a stepped meter. + case grille = "a" + /// B: the ribs — the thin wave asleep as a ribbed grille, awake as the wave. + case ribs = "b" + /// C: the streak — a hairline with a bright point that blooms into a light streak. + case streak = "c" + + package static let shipped = VoiceElementKind.grille + + /// `-BlurtGalleryVoice a|b|c`, or nil when the arguments don't say. + package static func parse(_ arguments: [String]) -> VoiceElementKind? { + guard let flag = arguments.firstIndex(of: "-BlurtGalleryVoice"), arguments.count > flag + 1 else { return nil } + return VoiceElementKind(rawValue: arguments[flag + 1]) + } +} diff --git a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceState.swift b/App/BlurtiOS/BlurtiOSCore/VoiceState.swift similarity index 80% rename from App/BlurtiOS/BlurtKeyboard/Sources/VoiceState.swift rename to App/BlurtiOS/BlurtiOSCore/VoiceState.swift index 8faaafc2..d832ec4e 100644 --- a/App/BlurtiOS/BlurtKeyboard/Sources/VoiceState.swift +++ b/App/BlurtiOS/BlurtiOSCore/VoiceState.swift @@ -7,8 +7,8 @@ import Foundation /// snapshot, the app from the engine's overlay state; every visual decision /// — the ring, a glyph, dimming, whether the meter is up — is a property here /// and tested, not a branch in a view. -nonisolated struct VoiceState: Equatable { - enum Phase: Equatable { +package nonisolated struct VoiceState: Equatable { + package enum Phase: Equatable { case idle case connecting case recording @@ -18,7 +18,7 @@ nonisolated struct VoiceState: Equatable { case error } - enum Ring: Equatable { + package enum Ring: Equatable { /// At rest, or while recording (the meter says it all). case still /// The mic coming up, the words being made. @@ -27,26 +27,26 @@ nonisolated struct VoiceState: Equatable { case solid(Tone) } - enum Tone: Equatable { + package enum Tone: Equatable { case ok case error } - enum Glyph: Equatable { + package enum Glyph: Equatable { case clipboard case exclamation } - let phase: Phase + package let phase: Phase /// Whether a press can do anything but open the app: Full Access and the /// app listening (the keyboard), the mic window open (the app). - let isReady: Bool + package let isReady: Bool /// The voice level while recording, 0…1. - let level: Float + package let level: Float /// The error's own words, for VoiceOver. - let message: String? + package let message: String? - init(phase: Phase, isReady: Bool, level: Float = 0, message: String? = nil) { + package init(phase: Phase, isReady: Bool, level: Float = 0, message: String? = nil) { self.phase = phase self.isReady = isReady self.level = level @@ -54,7 +54,7 @@ nonisolated struct VoiceState: Equatable { } /// The keyboard's: from the phase the app published. - init(snapshot: PhaseSnapshot, isReady: Bool) { + package init(snapshot: PhaseSnapshot, isReady: Bool) { let phase: Phase = switch snapshot.state { case .idle: .idle @@ -70,7 +70,7 @@ nonisolated struct VoiceState: Equatable { /// The app's: from the engine's overlay state. "No target" is the words /// going to the clipboard — the keyboard's "copied". - init(overlay: OverlayUIState, windowOpen: Bool, level: Float) { + package init(overlay: OverlayUIState, windowOpen: Bool, level: Float) { switch overlay { case .idle: self.init(phase: .idle, isReady: windowOpen) case .connecting: self.init(phase: .connecting, isReady: windowOpen) @@ -83,10 +83,10 @@ nonisolated struct VoiceState: Equatable { } /// The meter is up and is the key. - var isRecording: Bool { isReady && phase == .recording } + package var isRecording: Bool { isReady && phase == .recording } /// Something is in flight: the mic coming up, the voice, the words being made. - var isWorking: Bool { + package var isWorking: Bool { guard isReady else { return false } switch phase { case .connecting, .recording, .processing: return true @@ -94,7 +94,7 @@ nonisolated struct VoiceState: Equatable { } } - var isNotice: Bool { + package var isNotice: Bool { switch phase { case .pasted, .copied, .error: true case .idle, .connecting, .recording, .processing: false @@ -102,7 +102,7 @@ nonisolated struct VoiceState: Equatable { } /// Nothing in flight — the moments the cancel control has nothing to cancel. - var isSettled: Bool { + package var isSettled: Bool { switch phase { case .idle, .pasted, .copied, .error: true case .connecting, .recording, .processing: false @@ -111,9 +111,9 @@ nonisolated struct VoiceState: Equatable { /// Something is in flight and Blurt is there to stop it: no × beside a /// dimmed mic whose app is gone. - var canCancel: Bool { !isSettled && isReady } + package var canCancel: Bool { !isSettled && isReady } - var ring: Ring { + package var ring: Ring { switch phase { case .error: return .solid(.error) case .pasted, .copied: return .solid(.ok) @@ -123,7 +123,7 @@ nonisolated struct VoiceState: Equatable { } /// Only the two notices that need saying carry a glyph. - var glyph: Glyph? { + package var glyph: Glyph? { guard isReady else { return nil } switch phase { case .copied: return .clipboard @@ -133,14 +133,14 @@ nonisolated struct VoiceState: Equatable { } /// Blurt isn't ready: the control sits back, and a tap opens the app. - var dimmed: Bool { !isReady } + package var dimmed: Bool { !isReady } - var accessibilityLabel: String { + package var accessibilityLabel: String { guard isReady else { return "Start Blurt" } return isRecording ? "Stop dictation" : "Dictate" } - var accessibilityValue: String { + package var accessibilityValue: String { phase == .error ? message ?? "Dictation failed." : "" } } diff --git a/App/BlurtiOS/BlurtiOSTests/APIKeyModelTests.swift b/App/BlurtiOS/BlurtiOSTests/APIKeyModelTests.swift new file mode 100644 index 00000000..9a14e408 --- /dev/null +++ b/App/BlurtiOS/BlurtiOSTests/APIKeyModelTests.swift @@ -0,0 +1,37 @@ +import BlurtEngine +import Foundation +import Testing + +@testable import BlurtiOSCore + +/// The iPhone's API-key model over an in-memory store — never the real +/// Keychain — and a validator that answers without the network. +@Suite("API key model") +@MainActor +struct APIKeyModelTests { + @Test("a key AssemblyAI accepts is saved and flips the flag; a rejected one is not saved") + func submit() async { + let store = InMemoryAPIKeyStore() + let model = APIKeyModel(keyStore: store) { key in key == "good" ? .valid : .invalid } + #expect(!model.hasAPIKey) + #expect(await model.submit("bad") == .invalid) + #expect(!model.hasAPIKey) + #expect(store.current == nil) + #expect(await model.submit("good") == .valid) + #expect(model.hasAPIKey) + #expect(store.current == "good") + } + + @Test("the readiness gate reads the store as it is now; a refresh catches the flag up") + func readiness() { + let store = InMemoryAPIKeyStore() + let model = APIKeyModel(keyStore: store) { _ in .valid } + let check = model.readinessCheck() + #expect(check() == .apiKeyMissing) + store.save("key") + #expect(check() == nil) + #expect(!model.hasAPIKey) + model.refreshStatus() + #expect(model.hasAPIKey) + } +} diff --git a/App/BlurtiOS/BlurtiOSTests/DesignTokensTests.swift b/App/BlurtiOS/BlurtiOSTests/DesignTokensTests.swift index 62fec0fd..d9a970a7 100644 --- a/App/BlurtiOS/BlurtiOSTests/DesignTokensTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/DesignTokensTests.swift @@ -4,6 +4,7 @@ import Testing import UIKit @testable import BlurtiOS +@testable import BlurtiOSCore /// The compiled tokens against the file they were generated from. check.sh's /// `design-sync.sh --check` catches drift in the tree; this catches it in the diff --git a/App/BlurtiOS/BlurtiOSTests/FeedAndLayoutTests.swift b/App/BlurtiOS/BlurtiOSTests/FeedAndLayoutTests.swift index 4c929676..3d377dc7 100644 --- a/App/BlurtiOS/BlurtiOSTests/FeedAndLayoutTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/FeedAndLayoutTests.swift @@ -2,6 +2,7 @@ import Foundation import Testing @testable import BlurtiOS +@testable import BlurtiOSCore @Suite("Utterance feed") struct UtteranceFeedTests { diff --git a/App/BlurtiOS/BlurtiOSTests/HomeStatusTests.swift b/App/BlurtiOS/BlurtiOSTests/HomeStatusTests.swift index b7a25665..8792e23f 100644 --- a/App/BlurtiOS/BlurtiOSTests/HomeStatusTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/HomeStatusTests.swift @@ -2,7 +2,7 @@ import BlurtEngine import Foundation import Testing -@testable import BlurtiOS +@testable import BlurtiOSCore @Suite("Home status") struct HomeStatusTests { diff --git a/App/BlurtiOS/BlurtiOSTests/KeyboardInteractionTests.swift b/App/BlurtiOS/BlurtiOSTests/KeyboardInteractionTests.swift index f1d180cc..cd3400bd 100644 --- a/App/BlurtiOS/BlurtiOSTests/KeyboardInteractionTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/KeyboardInteractionTests.swift @@ -1,7 +1,7 @@ import CoreGraphics import Testing -@testable import BlurtiOS +@testable import BlurtiOSCore @Suite("Keyboard interaction rules") struct KeyboardInteractionTests { diff --git a/App/BlurtiOS/BlurtiOSTests/KeyboardLifecycleTests.swift b/App/BlurtiOS/BlurtiOSTests/KeyboardLifecycleTests.swift new file mode 100644 index 00000000..f75afddb --- /dev/null +++ b/App/BlurtiOS/BlurtiOSTests/KeyboardLifecycleTests.swift @@ -0,0 +1,195 @@ +import BlurtEngine +import Foundation +import Testing +import UIKit + +@testable import BlurtiOSCore + +/// The keyboard's side of being on screen, over time: the presence heartbeat, +/// the app's Darwin signals, the dwell that lets a notice go, the release held +/// while the mic comes up, the word list handed to the app, and the responder +/// walk that brings the app forward. +@Suite("Keyboard model: lifecycle and the app's signals", .serialized) +@MainActor +struct KeyboardLifecycleTests { + final class Commands { + var sent: [KeyboardCommand] = [] + } + + private func ready(_ proxy: FakeProxy = FakeProxy()) -> (KeyboardModel, Commands) { + let model = KeyboardModel() + model.proxyOverride = proxy + model.hasFullAccess = true + let now = Date() + SharedStore.listeningUntil = now.addingTimeInterval(600) + SharedStore.appSeenAt = now + model.isListening = true + let commands = Commands() + model.transport = { commands.sent.append($0) } + return (model, commands) + } + + private func snapshot(_ state: PhaseSnapshot.State) -> PhaseSnapshot { + PhaseSnapshot(state: state, message: nil, level: 0, at: Date()) + } + + /// Polls until `condition` holds or `timeout` passes; true when it held. + private func eventually(_ timeout: Duration = .seconds(3), _ condition: () -> Bool) async -> Bool { + let deadline = ContinuousClock.now + timeout + while ContinuousClock.now < deadline { + if condition() { return true } + try? await Task.sleep(for: .milliseconds(20)) + } + return condition() + } + + @Test("on screen, the keyboard tells the app it is there and which one it is; gone, it stops") + func heartbeat() async { + let suite = ScratchSuite() + defer { suite.tearDown() } + SharedStore.autoDictate = false + let (model, _) = ready() + model.appeared() + #expect(await eventually { SharedStore.keyboardSeenAt != nil }) + #expect(SharedStore.keyboardInstance == model.instanceID) + model.disappeared() + #expect(SharedStore.keyboardSeenAt == nil) + // The heartbeat is over: nothing marks the keyboard present again. + try? await Task.sleep(for: .milliseconds(200)) + #expect(SharedStore.keyboardSeenAt == nil) + } + + @Test("attached to its controller, the keyboard follows the app's phase and result signals") + func darwinSignals() async { + let suite = ScratchSuite() + defer { suite.tearDown() } + let proxy = FakeProxy() + proxy.before = "Hi" + let (model, _) = ready(proxy) + let controller = UIInputViewController(nibName: nil, bundle: nil) + model.attach(to: controller) + SharedStore.write(snapshot(.recording), forKey: BlurtShared.Key.phase) + SharedStore.post(BlurtShared.Signal.phase) + #expect(await eventually { model.snapshot.state == .recording }) + SharedStore.write( + DictationResult(id: UUID(), text: "there", deliveredAt: Date(), recipient: nil), forKey: BlurtShared.Key.result) + SharedStore.post(BlurtShared.Signal.result) + #expect(await eventually { proxy.before == "Hi there" }) + } + + @Test("a notice lets go after its dwell, and a second read of the same snapshot does not bring it back") + func noticeDwell() async throws { + let suite = ScratchSuite() + defer { suite.tearDown() } + let (model, _) = ready() + let pasted = snapshot(.pasted) + let dwell = try #require(pasted.noticeDwellSeconds) + model.apply(pasted) + #expect(model.snapshot.state == .pasted) + #expect(await eventually(.seconds(dwell + 2)) { model.snapshot.state == .idle }) + model.apply(pasted) + #expect(model.snapshot.state == .idle) + // A new notice is not the one let go of. + model.apply(snapshot(.copied)) + #expect(model.snapshot.state == .copied) + } + + @Test("a release made while the mic is coming up is held for the first recording phase") + func releaseWhileConnecting() { + let suite = ScratchSuite() + defer { suite.tearDown() } + let (model, commands) = ready() + model.micDown() + model.apply(snapshot(.connecting)) + // Push-to-talk let go before the mic was up: the engine would drop a + // release now, so it waits. + model.perform(.stop) + #expect(commands.sent.map(\.kind) == [.press]) + model.apply(snapshot(.recording)) + #expect(commands.sent.map(\.kind) == [.press, .release]) + #expect(model.gate.isIdle) + } + + @Test("a held release is dropped when the mic never comes up") + func heldReleaseDroppedOnFailure() { + let suite = ScratchSuite() + defer { suite.tearDown() } + let (model, commands) = ready() + model.micDown() + model.apply(snapshot(.connecting)) + model.perform(.stop) + model.apply(snapshot(.error)) + model.apply(snapshot(.recording)) + #expect(commands.sent.map(\.kind) == [.press]) + } + + @Test("the saved check clears after its dwell and takes the chip for that word with it") + func termSavedDwell() async { + let suite = ScratchSuite() + defer { suite.tearDown() } + let proxy = FakeProxy() + proxy.selected = "Rizz" + let (model, _) = ready(proxy) + model.contextChanged() + #expect(model.selectedTerm == "Rizz") + model.addSelectedTerm() + #expect(model.termSavedAt != nil) + #expect(SharedStore.keyTerms == ["Rizz"]) + #expect(await eventually(.seconds(KeyboardModel.termNoticeDwell + 2)) { model.termSavedAt == nil }) + #expect(model.selectedTerm == nil) + #expect(model.dismissedSelection == "Rizz") + } + + @Test("the phone's word list reaches the app: written, stamped, and only re-read once it is old") + func lexicon() throws { + let suite = ScratchSuite() + defer { suite.tearDown() } + let entries = [ + LexiconEntry(userInput: "Neil Bisht", documentText: "Neil Bisht"), + LexiconEntry(userInput: "omw", documentText: "On my way!"), + ] + KeyboardModel.store(entries) + let stored = SharedStore.read([LexiconEntry].self, forKey: BlurtShared.Key.lexicon) + #expect(stored?.map(\.documentText) == ["Neil Bisht", "On my way!"]) + #expect(stored?.map(\.isName) == [true, false]) + let refreshed = try #require(SharedStore.lexiconRefreshedAt) + #expect(Date().timeIntervalSince(refreshed) < 5) + } + + @Test("opening the app walks the responder chain to the application and asks it for blurt://start") + func openApp() { + let suite = ScratchSuite() + defer { suite.tearDown() } + let model = KeyboardModel() + // No controller: nothing to walk. + var opened: [(UIApplication, URL)] = [] + model.urlOpener = { opened.append(($0, $1)) } + model.openApp() + #expect(opened.isEmpty) + // A controller on screen: its chain ends at the application. + let controller = UIInputViewController(nibName: nil, bundle: nil) + let window = UIWindow(frame: CGRect(x: 0, y: 0, width: 10, height: 10)) + window.rootViewController = controller + window.isHidden = false + defer { window.isHidden = true } + model.controller = controller + // Not ready (no Full Access): the tap that would have dictated opens Blurt. + model.micDown() + model.micUp() + #expect(opened.count == 1) + #expect(opened.first?.0 === UIApplication.shared) + #expect(opened.first?.1.absoluteString == "\(BlurtShared.urlScheme)://\(BlurtShared.startHost)") + } + + @Test("the mic's side comes from Settings unless a preview says otherwise") + func micAlignment() { + let suite = ScratchSuite() + defer { suite.tearDown() } + let model = KeyboardModel() + #expect(model.micAlignment == .center) + model.storedMicAlignment = .left + #expect(model.micAlignment == .left) + model.micAlignmentOverride = .right + #expect(model.micAlignment == .right) + } +} diff --git a/App/BlurtiOS/BlurtiOSTests/KeyboardModelFuzzTests.swift b/App/BlurtiOS/BlurtiOSTests/KeyboardModelFuzzTests.swift index 17c7682a..da4faa5a 100644 --- a/App/BlurtiOS/BlurtiOSTests/KeyboardModelFuzzTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/KeyboardModelFuzzTests.swift @@ -2,6 +2,7 @@ import Foundation import Testing @testable import BlurtiOS +@testable import BlurtiOSCore /// The keyboard model driven through thousands of random event sequences — /// every finger, phase, host and lifecycle event the real keyboard sees, in diff --git a/App/BlurtiOS/BlurtiOSTests/KeyboardModelGateTests.swift b/App/BlurtiOS/BlurtiOSTests/KeyboardModelGateTests.swift index 1aaf2312..ccc756e5 100644 --- a/App/BlurtiOS/BlurtiOSTests/KeyboardModelGateTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/KeyboardModelGateTests.swift @@ -3,6 +3,7 @@ import Testing import UIKit @testable import BlurtiOS +@testable import BlurtiOSCore /// The mic key's gate against the app's phases: which phase settles which /// press, the retry, the sender on every command, and the term field closing diff --git a/App/BlurtiOS/BlurtiOSTests/KeyboardModelTests.swift b/App/BlurtiOS/BlurtiOSTests/KeyboardModelTests.swift index 99f38369..6a5ee0cd 100644 --- a/App/BlurtiOS/BlurtiOSTests/KeyboardModelTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/KeyboardModelTests.swift @@ -3,6 +3,7 @@ import Testing import UIKit @testable import BlurtiOS +@testable import BlurtiOSCore /// A host text field the model can type into, remembering what it did. final class FakeProxy: NSObject, UITextDocumentProxy { diff --git a/App/BlurtiOS/BlurtiOSTests/ProtocolTests.swift b/App/BlurtiOS/BlurtiOSTests/ProtocolTests.swift index e001c542..2b3598d2 100644 --- a/App/BlurtiOS/BlurtiOSTests/ProtocolTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/ProtocolTests.swift @@ -4,6 +4,7 @@ import Testing import UIKit @testable import BlurtiOS +@testable import BlurtiOSCore @Suite("The two-process contract", .serialized) @MainActor diff --git a/App/BlurtiOS/BlurtiOSTests/SharedStateTests.swift b/App/BlurtiOS/BlurtiOSTests/SharedStateTests.swift index 20d25292..134d6ad8 100644 --- a/App/BlurtiOS/BlurtiOSTests/SharedStateTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/SharedStateTests.swift @@ -3,6 +3,7 @@ import SwiftUI import Testing @testable import BlurtiOS +@testable import BlurtiOSCore @Suite("Mic alignment setting") struct MicAlignmentSettingTests { @@ -108,8 +109,67 @@ struct VoiceElementSettingTests { } } +@Suite("Shared defaults") +@MainActor +struct SharedDefaultsTests { + @Test("a payload round-trips through the App Group; unreadable or removed is nothing") + func payloads() { + let suite = ScratchSuite() + defer { suite.tearDown() } + let result = DictationResult(id: UUID(), text: "hi", deliveredAt: Date(), recipient: "kb") + SharedStore.write(result, forKey: BlurtShared.Key.result) + #expect(SharedStore.read(DictationResult.self, forKey: BlurtShared.Key.result)?.id == result.id) + SharedStore.defaults.set(Data("not json".utf8), forKey: BlurtShared.Key.result) + #expect(SharedStore.read(DictationResult.self, forKey: BlurtShared.Key.result) == nil) + SharedStore.write(result, forKey: BlurtShared.Key.result) + SharedStore.remove(forKey: BlurtShared.Key.result) + #expect(SharedStore.read(DictationResult.self, forKey: BlurtShared.Key.result) == nil) + } + + @Test("each setting has its default until chosen, and keeps what was chosen") + func settings() { + let suite = ScratchSuite() + defer { suite.tearDown() } + #expect(SharedStore.layout == .panel) + SharedStore.layout = .full + #expect(SharedStore.layout == .full) + #expect(SharedStore.themeID == "system") + SharedStore.themeID = "blurt" + #expect(SharedStore.themeID == "blurt") + #expect(SharedStore.autoDictate) + SharedStore.autoDictate = false + #expect(!SharedStore.autoDictate) + #expect(SharedStore.windowMinutes == 15) + // 0 is a real choice (until closed), not the unset default. + SharedStore.windowMinutes = 0 + #expect(SharedStore.windowMinutes == 0) + #expect(SharedStore.lexiconRefreshedAt == nil) + } + + @Test("a contact name has both sides equal; a text replacement does not") + func lexiconEntries() { + #expect(LexiconEntry(userInput: "Neil Bisht", documentText: "Neil Bisht").isName) + #expect(!LexiconEntry(userInput: "omw", documentText: "On my way!").isName) + } +} + @Suite("Layouts and palettes") struct LayoutTests { + @Test("every layout and mic side has its own name and description for Settings") + func settingsCopy() { + for cases in [ + KeyboardLayout.allCases.map { ($0.id, $0.title, $0.summary) }, + MicAlignment.allCases.map { ($0.id, $0.title, $0.summary) }, + ] { + #expect(Set(cases.map(\.0)).count == cases.count) + #expect(Set(cases.map(\.1)).count == cases.count) + #expect(Set(cases.map(\.2)).count == cases.count) + #expect(cases.allSatisfy { !$0.1.isEmpty && !$0.2.isEmpty }) + } + #expect(KeyboardLayout.full.id == "full") + #expect(MicAlignment.left.id == "left") + } + @Test("heights are the rows at the iPhone keyboard's spacing (DESIGN.md)") func heights() { #expect(KeyboardLayout.slimBar.height == 60) diff --git a/App/BlurtiOS/BlurtiOSTests/TermPackTests.swift b/App/BlurtiOS/BlurtiOSTests/TermPackTests.swift index 63ebddd2..ff564f6e 100644 --- a/App/BlurtiOS/BlurtiOSTests/TermPackTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/TermPackTests.swift @@ -1,7 +1,7 @@ import Foundation import Testing -@testable import BlurtiOS +@testable import BlurtiOSCore @Suite("Term packs") struct TermPackTests { @@ -32,6 +32,27 @@ struct TermPackTests { #expect(read.name == "Chat") } + @Test("the shared file is named for the list, with what a file name can't carry taken out") + func fileName() { + #expect(TermPack(name: "Gym / crew!", from: nil, terms: ["a"]).fileStem == "Gym crew") + #expect(TermPack(name: " ", from: nil, terms: ["a"]).fileStem == "Blurt key terms") + #expect(TermPack(name: "../../", from: nil, terms: ["a"]).fileStem == "Blurt key terms") + } + + @Test("the share sheet's file is the pack, as JSON a friend's Blurt reads back") + func shared() async throws { + // `exported(as:)` is iOS 18.2; the suite runs on the current simulator. + guard #available(iOS 18.2, *) else { + Issue.record("needs iOS 18.2 to export a Transferable") + return + } + let pack = TermPack(name: "Chat", from: "Neil", terms: ["Rizz", "Blurt"]) + let data = try await pack.exported(as: .blurtTerms) + let read = try JSONDecoder().decode(TermPack.self, from: data) + #expect(read.id == pack.id) + #expect(TermPack(name: "Chat", from: "Neil", terms: ["Blurt", "Rizz"]).id != pack.id) + } + @Test("the plain text names the sender and lists the words") func plainText() { let pack = TermPack(name: "Chat", from: "Neil", terms: ["Rizz", "Blurt"]) diff --git a/App/BlurtiOS/BlurtiOSTests/TestSuite.swift b/App/BlurtiOS/BlurtiOSTests/TestSuite.swift index 77370e88..76a2bbc1 100644 --- a/App/BlurtiOS/BlurtiOSTests/TestSuite.swift +++ b/App/BlurtiOS/BlurtiOSTests/TestSuite.swift @@ -1,6 +1,6 @@ import Foundation -@testable import BlurtiOS +@testable import BlurtiOSCore /// A throwaway App Group for one test: nothing a test writes reaches the real /// suite the installed app and keyboard share (the engine's own rule about diff --git a/App/BlurtiOS/BlurtiOSTests/VoiceElementTests.swift b/App/BlurtiOS/BlurtiOSTests/VoiceElementTests.swift index 2675626d..e84b8500 100644 --- a/App/BlurtiOS/BlurtiOSTests/VoiceElementTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/VoiceElementTests.swift @@ -2,6 +2,7 @@ import Foundation import Testing @testable import BlurtiOS +@testable import BlurtiOSCore @Suite("Voice element") struct VoiceElementTests { diff --git a/App/BlurtiOS/BlurtiOSTests/VoiceStateTests.swift b/App/BlurtiOS/BlurtiOSTests/VoiceStateTests.swift index 0693d68e..df1eab48 100644 --- a/App/BlurtiOS/BlurtiOSTests/VoiceStateTests.swift +++ b/App/BlurtiOS/BlurtiOSTests/VoiceStateTests.swift @@ -2,7 +2,7 @@ import BlurtEngine import Foundation import Testing -@testable import BlurtiOS +@testable import BlurtiOSCore @Suite("Voice state") struct VoiceStateTests { diff --git a/App/BlurtiOS/DESIGN.md b/App/BlurtiOS/DESIGN.md index 62c6e10f..d0444acb 100644 --- a/App/BlurtiOS/DESIGN.md +++ b/App/BlurtiOS/DESIGN.md @@ -433,7 +433,7 @@ side, and — in the panel — cancel in the far top corner, clear of them both, where in the middle it mirrors the + on the mic's other side. Left and right are the phone's sides: in a right-to-left language the leading/trailing mapping flips so the mic stays under the thumb chosen -(`Shared/MicAlignment.swift`, tested). Gallery: `-BlurtGalleryAlign +(`BlurtiOSCore/MicAlignment.swift` and `Shared/MicAlignment+Layout.swift`, tested). Gallery: `-BlurtGalleryAlign left|center|right`; the real extension: `scripts/ios-keyboard-flows.sh --align left|right` checks the mic is at that edge with the add key inside it. @@ -735,7 +735,7 @@ still follow the level. The app listens and transcribes; the keyboard is a remote control. They talk over the App Group's `UserDefaults` (payloads as JSON) plus Darwin -notifications that carry nothing and just say "look" (`SharedState.swift`). +notifications that carry nothing and just say "look" (`BlurtiOSCore/SharedState.swift`). | Rule | Value | Why | | ---------------------- | ---------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | diff --git a/App/BlurtiOS/README.md b/App/BlurtiOS/README.md index 7770339e..9b91b33f 100644 --- a/App/BlurtiOS/README.md +++ b/App/BlurtiOS/README.md @@ -14,7 +14,7 @@ The iPhone app and the keyboard it ships. Same engine as the Mac app shows the phase the app publishes, inserts the words that come back through `textDocumentProxy`, and reads the phone's word list (`UILexicon`: contact names and text replacements) so names come back spelled right with no setup. -- **They talk through an App Group** (`Shared/SharedState.swift`): payloads in the +- **They talk through an App Group** (`BlurtiOSCore/SharedState.swift`): payloads in the shared defaults, Darwin notifications to wake each other. Full Access is what lets the keyboard reach the group — without it the keyboard still types, and says what it needs. @@ -56,13 +56,36 @@ the Apple Developer Agreement at developer.apple.com/account; a company-managed download. The archive lands in `~/Library/Application Support/com.robotsandpencils.xcodes/`; an 83 KB "xip" there is a saved error page, delete it and retry. +## Logic and UI + +The iPhone code splits the way the Mac's does. **`BlurtiOSCore/`** is the logic — the App Group +contract, the keyboard's model and rules, the voice state, term packs, the relay injector — and +plays the part `BlurtEngine` plays for the Mac shell: no SwiftUI, no views, no audio (the keyboard +links it, and the keyboard never hears anything; `check-invariants.sh` enforces the last). The +app (`BlurtiOS/Sources`) and the keyboard (`BlurtKeyboard/Sources`) are the UI on top of it, with +`Shared/` holding what both draw with (design tokens, type, brand colours). + +It is a static framework, so the app and the keyboard each link their own copy beside the +engine's, and its API is `package` (one `SWIFT_PACKAGE_NAME` across the project), not `public`: +nothing outside this project can see it, and periphery still reports what nothing uses. A +preview hands the model a `ThemeFace`, not a palette — the colours are the UI's +(`KeyboardModel+Palette.swift`). + ## Unit tests `scripts/ios-test.sh` runs `BlurtiOSTests` on a simulator (CI's `ios-build` job runs it after -the build): the iPhone code's pure logic — the App Group contract (`KeyTermList`, stale -snapshots, layouts), the keyboard's rules (sentence start, the double space, the term field, -return labels, letter rows) against a fake text field, term packs, palettes. The engine's own -tests stay `swift test`. Anything with a rule in `DESIGN.md` should have a test here. +the build): the core's logic — the App Group contract (`KeyTermList`, stale snapshots, layouts), +the keyboard's rules (sentence start, the double space, the term field, return labels, letter +rows) against a fake text field, the gate against the app's phases, the Darwin signals, term +packs — and what the UI builds on it (palettes, the voice element, the gallery). The engine's +own tests stay `swift test`. Anything with a rule in `DESIGN.md` should have a test here. + +The suite holds the same gates as the engine's: warnings are errors, a plain run fails when +`BlurtiOSCore` drops below the engine's own line-coverage floor (`MIN_IOS_COVERAGE`, 88%, in the +script — raise it as coverage grows, never lower it to land a change), and CI's `ios-sanitizers` +job runs it again under ThreadSanitizer and AddressSanitizer (`BLURT_IOS_SANITIZER=thread` or +`address` locally). The views are not in that figure, as the Mac shell's aren't in the engine's: +they are checked on sight, through the gallery and the probe's screenshot flows. ## Testing in the simulator diff --git a/App/BlurtiOS/Shared/KeyboardLayout+Height.swift b/App/BlurtiOS/Shared/KeyboardLayout+Height.swift new file mode 100644 index 00000000..5fe25539 --- /dev/null +++ b/App/BlurtiOS/Shared/KeyboardLayout+Height.swift @@ -0,0 +1,17 @@ +import BlurtiOSCore +import CoreGraphics + +extension KeyboardLayout { + /// The keyboard's height on screen, from the layout's rows at the iPhone + /// keyboard's own spacing: see `App/BlurtiOS/DESIGN.md` for the arithmetic. + var height: CGFloat { + let metrics = DesignTokens.Metrics.self + return switch self { + case .slimBar: 2 * metrics.marginVertical + metrics.voicebarHeight + case .panel: metrics.layoutPanel + case .full: + metrics.marginVertical + metrics.voicebarHeight + 4 * metrics.keyHeight + 3 * metrics.rowGap + + metrics.marginBottomKeys + } + } +} diff --git a/App/BlurtiOS/Shared/MicAlignment+Layout.swift b/App/BlurtiOS/Shared/MicAlignment+Layout.swift new file mode 100644 index 00000000..716bf598 --- /dev/null +++ b/App/BlurtiOS/Shared/MicAlignment+Layout.swift @@ -0,0 +1,21 @@ +import BlurtiOSCore +import SwiftUI + +extension MicAlignment { + /// The side of the row, as SwiftUI counts sides: left is the leading edge + /// in a left-to-right language and the trailing one in a right-to-left + /// one, so the mic stays under the thumb the user chose either way. + func alignment(in direction: LayoutDirection) -> Alignment { + switch self { + case .center: .center + case .left: direction == .leftToRight ? .leading : .trailing + case .right: direction == .leftToRight ? .trailing : .leading + } + } + + /// Whether the + goes before the mic in the row: at the trailing edge, so + /// the mic is the thing at the edge and the + sits on its inner side. + func plusLeads(in direction: LayoutDirection) -> Bool { + alignment(in: direction) == .trailing + } +} diff --git a/App/BlurtiOS/project.yml b/App/BlurtiOS/project.yml index 9aa77f1f..cd50a608 100644 --- a/App/BlurtiOS/project.yml +++ b/App/BlurtiOS/project.yml @@ -33,12 +33,39 @@ settings: # what CI wants — it builds with signing off. App Groups need a paid team. DEVELOPMENT_TEAM: ${BLURT_TEAM} CODE_SIGN_STYLE: Automatic + # One package access identifier for every target, so BlurtiOSCore's + # `package` declarations reach the app, the keyboard and the tests (and + # nothing outside them) without becoming `public` API. + SWIFT_PACKAGE_NAME: BlurtiOS packages: # The same local package the Mac app carries, reached from App/BlurtiOS. No # remote packages: check.sh's dependency guard reads every App/*/project.yml. BlurtEngine: path: ../.. targets: + # The iPhone code's logic, apart from its UI, the way BlurtEngine sits apart + # from the Mac shell: the App Group contract, the keyboard's model and rules, + # the voice state, term packs. No SwiftUI and no views (those stay in the app + # and the keyboard), and no audio: the keyboard links this, and it never + # hears anything. Static, so the app and the keyboard each carry their own + # copy alongside the engine's, with no framework to embed and no second copy + # of the engine inside one process. ios-test.sh gates its line coverage. + BlurtiOSCore: + type: framework.static + platform: iOS + sources: + - path: BlurtiOSCore + settings: + base: + PRODUCT_BUNDLE_IDENTIFIER: dev.alex.blurt.ios.core + GENERATE_INFOPLIST_FILE: YES + SWIFT_TREAT_WARNINGS_AS_ERRORS: YES + SWIFT_DEFAULT_ACTOR_ISOLATION: MainActor + # The keyboard links it, so only extension-safe API. + APPLICATION_EXTENSION_API_ONLY: YES + dependencies: + - package: BlurtEngine + product: BlurtEngine BlurtiOS: type: application platform: iOS @@ -57,9 +84,9 @@ targets: # The keyboard carries its own copy: an extension can't read the app's. - path: Design/fonts buildPhase: resources - # The App Group contract, compiled into BOTH the app and the keyboard (an - # extension can't import the app's module) — one source, no duplication, - # the same shape as App/Blurt/Shared. + # The UI both the app and the keyboard draw with (design tokens, type, + # brand colours), compiled into each — an extension can't import the + # app's module. The App Group contract itself is BlurtiOSCore. - path: Shared # The keyboard's views and model: the theme picker draws the real keyboard # on its cards, the home screen draws the orb and the meter, and debug @@ -132,6 +159,8 @@ targets: dependencies: - package: BlurtEngine product: BlurtEngine + - target: BlurtiOSCore + embed: false - target: BlurtKeyboard # The keyboard. It types, it starts and stops a dictation, it inserts the # words; it never hears anything. `RequestsOpenAccess` asks the user for Full @@ -178,10 +207,13 @@ targets: dependencies: - package: BlurtEngine product: BlurtEngine - # Unit tests for the iPhone code's pure logic — the App Group contract, the - # keyboard's rules, term packs — hosted by the app so `@testable import - # BlurtiOS` reaches everything (the keyboard's sources are compiled into the - # app too). Swift Testing; `scripts/ios-test.sh` runs them on a simulator. + - target: BlurtiOSCore + embed: false + # Unit tests for the iPhone code — BlurtiOSCore's logic, and what the app and + # keyboard build on it — hosted by the app so `@testable import BlurtiOS` + # reaches the shell too (the keyboard's sources are compiled into the app). + # Core is linked into the host already, so the bundle only imports it. + # Swift Testing; `scripts/ios-test.sh` runs them on a simulator. BlurtiOSTests: type: bundle.unit-test platform: iOS @@ -235,7 +267,12 @@ schemes: test: config: Debug targets: - - BlurtiOSTests + # Serial, on purpose: tests swap `SharedStore.override` (a global) for a + # scratch App Group, and an async test suspended mid-await would read + # another suite's — or the real one — if a second ran in the gap. + # `.serialized` only orders tests inside one suite. + - name: BlurtiOSTests + parallelizable: false BlurtiOSProbe: build: targets: diff --git a/scripts/check-invariants.sh b/scripts/check-invariants.sh index eee93e58..907aa423 100755 --- a/scripts/check-invariants.sh +++ b/scripts/check-invariants.sh @@ -80,10 +80,11 @@ ENGINE="Sources/*.swift" # next one. APP="App/*.swift App/*.yml App/*.plist :!App/Blurt/Blurt.xcodeproj :!App/BlurtiOS/BlurtiOSTests" TESTS="Tests/*.swift App/Blurt/BlurtUITests/*.swift App/BlurtiOS/BlurtiOSTests/*.swift" -# The keyboard extension and what it compiles: iOS lets no keyboard use the -# microphone, and the design keeps every audio type out of it, so an import -# there is a decision being reversed by accident. -KEYBOARD="App/BlurtiOS/BlurtKeyboard/*.swift App/BlurtiOS/Shared/*.swift" +# The keyboard extension and what it compiles or links — its own sources, the +# Shared UI, and BlurtiOSCore: iOS lets no keyboard use the microphone, and the +# design keeps every audio type out of it, so an import there is a decision +# being reversed by accident. +KEYBOARD="App/BlurtiOS/BlurtKeyboard/*.swift App/BlurtiOS/Shared/*.swift App/BlurtiOS/BlurtiOSCore/*.swift" # The streaming-STT rule's one carve-out: the experimental read-selection-aloud # feature speaks through AssemblyAI's streaming TTS, which is WebSocket-only. # The rule is about *dictation* staying one request/one response, so the TTS diff --git a/scripts/design-sync.sh b/scripts/design-sync.sh index fd96f5cc..04ce8178 100755 --- a/scripts/design-sync.sh +++ b/scripts/design-sync.sh @@ -64,23 +64,22 @@ format_outputs() { } # The design-literal lint. Scope: every file under the keyboard's and the -# app's sources that draws — new views are linted by default — minus the logic (the model, -# the host controller, the palette, the geometry and interaction rules, the -# voice state) and Grain.swift, whose body is the grain's recipe (density, +# app's sources that draws — new views are linted by default — minus the few +# that compute rather than draw (the host controller, the palette, the +# geometry) and Grain.swift, whose body is the grain's recipe (density, # the two shades), with only its opacity as a token. Numbers 0 and 1 pass: `Spacer(minLength: 0)`, # `.opacity(on ? 1 : 0)` and `scaleEffect(1 + …)` are structure, not design. lint_literals() { python3 - <<'PY' import glob, os, re, sys +# BlurtiOSCore (the model, the voice state, the interaction rules) is not +# globbed at all: it draws nothing, so it has no design literals to carry. exempt = { - "KeyboardModel.swift", "KeyboardModel+Mic.swift", "KeyboardModel+Phase.swift", "KeyboardModel+Typing.swift", - "KeyboardViewController.swift", "KeyboardPalette.swift", "KeyGeometry.swift", "KeyboardInteraction.swift", - "VoiceState.swift", "KeyboardMotion.swift", "MotionHeld.swift", "Grain.swift", + "KeyboardViewController.swift", "KeyboardPalette.swift", "KeyGeometry.swift", "MotionHeld.swift", "Grain.swift", } app_exempt = { "BlurtiOSApp.swift", "DictationCoordinator.swift", "ListeningWindow.swift", "ListeningSource.swift", - "AudioSource.swift", "SimulatorAudioSource.swift", "KeyboardRelayInjector.swift", "APIKeyModel.swift", - "TermPack.swift", "HomeStatus.swift", "KeyboardGalleryView.swift", "KeyboardProbeView.swift", + "AudioSource.swift", "SimulatorAudioSource.swift", "KeyboardGalleryView.swift", "KeyboardProbeView.swift", } files = sorted( [path for path in glob.glob("App/BlurtiOS/BlurtKeyboard/Sources/**/*.swift", recursive=True) diff --git a/scripts/ios-test.sh b/scripts/ios-test.sh index e235c057..f8fbcbbe 100755 --- a/scripts/ios-test.sh +++ b/scripts/ios-test.sh @@ -1,7 +1,9 @@ #!/bin/bash # Run the iPhone app's unit tests (BlurtiOSTests) on a simulator. # -# scripts/ios-test.sh +# scripts/ios-test.sh # tests + the line-coverage gate +# BLURT_IOS_SANITIZER=thread scripts/ios-test.sh # tests under ThreadSanitizer +# BLURT_IOS_SANITIZER=address scripts/ios-test.sh # tests under AddressSanitizer # BLURT_SIM_DEVICE="iPhone 17" scripts/ios-test.sh # # Hosted by the app, signed ad hoc, on the named simulator or whichever iPhone @@ -11,12 +13,44 @@ # result bundle the last line names. A failure never triggers xcodebuild's # sysdiagnose collection (`-collect-test-diagnostics never`): that step takes # ten minutes on this simulator and the result bundle already says what failed. +# +# The same gates the engine's suite runs under in check.sh: warnings are errors +# (project.yml), a plain run must hold BlurtiOSCore's line coverage at or +# above MIN_IOS_COVERAGE, and CI runs the suite again under each sanitizer. A +# sanitizer run skips the coverage gate — the instrumented build is a second +# pass over the same tests, not a second measurement — and builds into its own +# derived-data directory, so it never reuses (or poisons) the plain build. set -euo pipefail REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" # shellcheck source=scripts/ios-lib.sh source "$REPO_ROOT/scripts/ios-lib.sh" -DERIVED="${BLURT_DERIVED_DATA:-$REPO_ROOT/.build/ios-sim}" + +# BlurtiOSCore's line-coverage floor (percent) — the engine's own bar +# (check.sh's MIN_COVERAGE). The core is the iPhone code's logic, apart from +# its UI the way BlurtEngine is apart from the Mac shell; the views in the app +# and the keyboard are measured by eye and by the probe's screenshot flows, as +# the Mac shell is by its XCUITest suite, not by this number. Raise it as +# coverage grows; never lower it to land a change. +MIN_IOS_COVERAGE=88 +IOS_CORE="App/BlurtiOS/BlurtiOSCore/" + +# Core files the figure leaves out. None today; keep it that way unless a file +# genuinely cannot run without a device, as check.sh's engine list does. +IOS_COVERAGE_EXCLUDE='^$' + +SANITIZER="${BLURT_IOS_SANITIZER:-}" +SANITIZE_FLAGS=() +case "$SANITIZER" in + "") ;; + thread) SANITIZE_FLAGS=(-enableThreadSanitizer YES) ;; + address) SANITIZE_FLAGS=(-enableAddressSanitizer YES) ;; + *) + echo "ios-test: BLURT_IOS_SANITIZER must be thread or address, not '$SANITIZER'" >&2 + exit 1 + ;; +esac +DERIVED="${BLURT_DERIVED_DATA:-$REPO_ROOT/.build/ios-sim}${SANITIZER:+-$SANITIZER}" PICKED="$(ios_pick_device "${BLURT_SIM_DEVICE:-iPhone 18 Pro}")" if [ -z "$PICKED" ]; then @@ -24,17 +58,54 @@ if [ -z "$PICKED" ]; then exit 1 fi UDID="${PICKED%% *}" -echo "testing on ${PICKED#* }" +echo "testing on ${PICKED#* }${SANITIZER:+ under the $SANITIZER sanitizer}" ios_wait_booted "$UDID" (cd "$REPO_ROOT/App/BlurtiOS" && xcodegen generate --quiet) RESULTS="$DERIVED/BlurtiOSTests-$(date +%Y%m%d-%H%M%S).xcresult" +COVERAGE_FLAGS=() +[ -z "$SANITIZER" ] && COVERAGE_FLAGS=(-enableCodeCoverage YES) +# The `${a[@]+...}` form: macOS bash 3.2 calls an empty array unbound under `set -u`. +# Serial for the reason project.yml's scheme gives (the tests share one global +# App Group override); said here too so no test plan or default can undo it. xcodebuild test -project "$REPO_ROOT/App/BlurtiOS/BlurtiOS.xcodeproj" -scheme BlurtiOS \ -destination "platform=iOS Simulator,id=$UDID" -derivedDataPath "$DERIVED" \ - -resultBundlePath "$RESULTS" "${IOS_SIM_SIGNING[@]}" -collect-test-diagnostics never -quiet + -resultBundlePath "$RESULTS" "${IOS_SIM_SIGNING[@]}" ${COVERAGE_FLAGS[@]+"${COVERAGE_FLAGS[@]}"} ${SANITIZE_FLAGS[@]+"${SANITIZE_FLAGS[@]}"} \ + -parallel-testing-enabled NO -collect-test-diagnostics never -quiet xcrun xcresulttool get test-results summary --path "$RESULTS" 2>/dev/null | python3 -c ' import json, sys d = json.load(sys.stdin) print("ios-test:", d.get("passedTests", "?"), "passed,", d.get("failedTests", "?"), "failed,", d.get("skippedTests", 0), "skipped") ' || true echo "results: $RESULTS" + +[ -n "$SANITIZER" ] && exit 0 + +echo "==> coverage gate (>= ${MIN_IOS_COVERAGE}% BlurtiOSCore lines)" +# The core is static, linked into the app and the keyboard both, so its files +# can appear under either binary: each is counted once, at the better figure +# (the tests run in the app's process; the keyboard's copy is never reached). +COVERAGE="$(xcrun xccov view --report --json "$RESULTS" | python3 -c ' +import json, re, sys +root, core, exclude = sys.argv[1], sys.argv[2], re.compile(sys.argv[3]) +files = {} +for target in json.load(sys.stdin)["targets"]: + for f in target["files"]: + path = f["path"] + rel = path[len(root) + 1:] if path.startswith(root + "/") else path + if not rel.startswith(core) or exclude.search(rel): + continue + best = files.get(rel, (0, 0)) + if f["coveredLines"] >= best[0]: + files[rel] = (f["coveredLines"], f["executableLines"]) +if not files: + sys.exit("no BlurtiOSCore sources in the coverage report") +covered = sum(c for c, _ in files.values()) +total = sum(t for _, t in files.values()) +print(round(100 * covered / total, 2)) +' "$REPO_ROOT" "$IOS_CORE" "$IOS_COVERAGE_EXCLUDE")" +echo "BlurtiOSCore line coverage: ${COVERAGE}%" +if ! awk -v c="$COVERAGE" -v min="$MIN_IOS_COVERAGE" 'BEGIN{ exit (c+0 < min+0) }'; then + echo "error: coverage ${COVERAGE}% is below the ${MIN_IOS_COVERAGE}% floor" >&2 + exit 1 +fi diff --git a/scripts/ios-typecheck.sh b/scripts/ios-typecheck.sh index 1ba77d4c..f610c254 100755 --- a/scripts/ios-typecheck.sh +++ b/scripts/ios-typecheck.sh @@ -40,10 +40,18 @@ find "$REPO_ROOT/Sources/BlurtEngine" -name '*.swift' -print0 \ -emit-module -emit-module-path "$WORK/BlurtEngine.swiftmodule" IOS="$REPO_ROOT/App/BlurtiOS" -TARGET_FLAGS=( - "${COMMON[@]}" -typecheck -I "$WORK" -warnings-as-errors +# project.yml's SWIFT_PACKAGE_NAME, so BlurtiOSCore's `package` API resolves. +IOS_FLAGS=( + "${COMMON[@]}" -I "$WORK" -warnings-as-errors -package-name BlurtiOS -Xfrontend -default-isolation -Xfrontend MainActor ) +TARGET_FLAGS=("${IOS_FLAGS[@]}" -typecheck) + +# The logic both targets link: emitted, not just checked, so they import it. +# Extension-safe, since the keyboard links it (APPLICATION_EXTENSION_API_ONLY). +echo "BlurtiOSCore" +xcrun swiftc "${IOS_FLAGS[@]}" -application-extension -D DEBUG -module-name BlurtiOSCore \ + -emit-module -emit-module-path "$WORK/BlurtiOSCore.swiftmodule" "$IOS"/BlurtiOSCore/*.swift # The app also compiles the keyboard's sources, all but its entry point # (project.yml: the theme picker and the home screen draw the real keyboard From c41ec3a0bb0e5508a313aad3ddc250d67e6d985b Mon Sep 17 00:00:00 2001 From: Alex Kroman Date: Fri, 2 Oct 2026 12:32:19 -0700 Subject: [PATCH 76/79] iPhone: hold it to the Mac's lint gates; drop Figma and the bundled fonts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The iPhone code now meets every quality gate the engine and the Mac shell do. scripts/ios-check.sh is its check.sh: BlurtiOSTests with BlurtiOSCore's coverage gate, then `swiftlint analyze` (unused imports, never run on App/BlurtiOS before) over that build's log, then periphery. CI's ios-build runs it; a local check.sh runs it too when an iPhone simulator on this Xcode's runtime exists. codeql.yml now builds the iPhone app as well, so it is in the Swift database. The first analyze pass found 17 unused imports, now gone (CGFloat and CFNotificationCenter users import CoreFoundation, which is what actually declares them). Removed the Figma plugin (Design/figma, design-figma-call.sh, the generator's tokens.js output) and the bundled brand fonts, whose licence covered only the web. BlurtType keeps its roles (mono, heading, body) on the system's monospaced, serif and default faces; the fonts token group, UIAppFonts and the registration checks go with them. Copilot review fixes: - An automatic window close (expiry, a call, Siri) now ends the dictation first: a recording is released so its words land, a mic coming up is cancelled. It used to sit in .recording over a dead feed until the 120 s auto-release, with the keyboard showing idle. - WindowedAudioSource throws when the session refuses its input or output instead of opening a window that hears nothing. - ios-keyboard-flows.sh exits non-zero when a run's XCUITest fails. - PrivacyInfo.xcprivacy for the app and the keyboard (App Group and own UserDefaults, the only required-reason API either uses). Also: - The app icon's art is full-bleed: its own transparent rounded corners were filled white by iOS, a halo that read as a broken icon mid-launch. Shared with the Mac app, which gets the same fix. - The launch screen is the app's Page colour, not blank system white. - LSSupportsOpeningDocumentsInPlace: false, matching TermPack's copy-then-delete import (and silencing Xcode's warning). - The setup card says to tap Keyboards on Blurt's Settings page — the only Settings link Apple allows. - check-invariants.sh no longer pipes the ~30 KB settled-decisions table into `grep -q`: an early match left printf writing to a closed pipe, EPIPE under pipefail, and a "missing" row on CI at random. Co-Authored-By: Claude Opus 5.5 --- .claude/settings.json | 1 + .claude/skills/check/SKILL.md | 7 +- .github/workflows/check.yml | 31 +- .github/workflows/codeql.yml | 27 + AGENTS.md | 23 +- .../AppIcon.icon/Assets/blurt-wordmark.png | Bin 2307387 -> 2063088 bytes .../BlurtKeyboard/PrivacyInfo.xcprivacy | 24 + .../BlurtKeyboard/Sources/KeyCap.swift | 2 +- .../BlurtKeyboard/Sources/KeyGeometry.swift | 2 +- .../Sources/KeyboardRootView.swift | 5 - .../BlurtKeyboard/Sources/MotionHeld.swift | 2 +- App/BlurtiOS/BlurtiOS/PrivacyInfo.xcprivacy | 24 + App/BlurtiOS/BlurtiOS/Sources/AppChrome.swift | 2 +- .../BlurtiOS/Sources/AudioSource.swift | 12 +- .../Sources/DictationCoordinator.swift | 17 + .../Sources/KeyboardGalleryView.swift | 4 +- .../BlurtiOS/Sources/ListeningWindow.swift | 15 +- App/BlurtiOS/BlurtiOS/Sources/SetupCard.swift | 6 +- .../BlurtiOSCore/DarwinObserver.swift | 2 +- .../BlurtiOSCore/KeyboardInteraction.swift | 1 - .../BlurtiOSCore/KeyboardModel+Field.swift | 1 - .../BlurtiOSCore/KeyboardMotion.swift | 1 - App/BlurtiOS/BlurtiOSCore/MicAlignment.swift | 2 - App/BlurtiOS/BlurtiOSCore/ThemeFace.swift | 2 - .../BlurtiOSCore/VoiceElementKind.swift | 2 - App/BlurtiOS/BlurtiOSCore/VoiceState.swift | 1 - .../BlurtiOSTests/APIKeyModelTests.swift | 1 - .../BlurtiOSTests/BlurtTypeTests.swift | 12 - .../BlurtiOSTests/DesignTokensTests.swift | 15 +- .../KeyboardModelFuzzTests.swift | 1 - .../KeyboardModelGateTests.swift | 2 - .../BlurtiOSTests/KeyboardModelTests.swift | 1 - .../BlurtiOSTests/ProtocolTests.swift | 1 - .../BlurtiOSTests/VoiceRowLayoutTests.swift | 2 +- App/BlurtiOS/DESIGN.md | 107 ++-- App/BlurtiOS/Design/figma/README.md | 84 --- App/BlurtiOS/Design/figma/components.js | 510 ------------------ App/BlurtiOS/Design/figma/core.js | 244 --------- App/BlurtiOS/Design/figma/exports.js | 55 -- App/BlurtiOS/Design/figma/foundations.js | 189 ------- App/BlurtiOS/Design/figma/layouts.js | 222 -------- App/BlurtiOS/Design/figma/manifest.json | 18 - App/BlurtiOS/Design/figma/plugin.js | 31 -- App/BlurtiOS/Design/figma/themes.js | 73 --- App/BlurtiOS/Design/figma/tokens.js | 260 --------- .../Design/fonts/ModernGothicMono-Light.ttf | Bin 56160 -> 0 bytes .../Design/fonts/ModernGothicMono-Medium.ttf | Bin 59148 -> 0 bytes .../Design/fonts/ModernGothicMono-Regular.ttf | Bin 58776 -> 0 bytes .../Design/fonts/OceanicText-Regular.otf | Bin 91688 -> 0 bytes App/BlurtiOS/Design/fonts/UN_11ST_Bold.ttf | Bin 95152 -> 0 bytes App/BlurtiOS/Design/fonts/UN_11ST_Regular.ttf | Bin 92392 -> 0 bytes App/BlurtiOS/Design/tokens.json | 39 +- App/BlurtiOS/README.md | 4 +- App/BlurtiOS/Shared/BlurtBrand.swift | 2 - App/BlurtiOS/Shared/BlurtType.swift | 46 +- App/BlurtiOS/Shared/DesignTokens.swift | 31 +- .../Shared/KeyboardLayout+Height.swift | 2 +- App/BlurtiOS/project.yml | 35 +- scripts/check-invariants.sh | 6 +- scripts/check.sh | 20 +- scripts/design-capture.sh | 4 +- scripts/design-diff.swift | 2 +- scripts/design-figma-call.sh | 49 -- scripts/design-sync.sh | 18 +- scripts/design-tokens.swift | 120 +---- scripts/ios-check.sh | 77 +++ scripts/ios-keyboard-flows.sh | 12 +- scripts/ios-record.sh | 2 +- scripts/ios-test.sh | 12 +- 69 files changed, 380 insertions(+), 2145 deletions(-) create mode 100644 App/BlurtiOS/BlurtKeyboard/PrivacyInfo.xcprivacy create mode 100644 App/BlurtiOS/BlurtiOS/PrivacyInfo.xcprivacy delete mode 100644 App/BlurtiOS/BlurtiOSTests/BlurtTypeTests.swift delete mode 100644 App/BlurtiOS/Design/figma/README.md delete mode 100644 App/BlurtiOS/Design/figma/components.js delete mode 100644 App/BlurtiOS/Design/figma/core.js delete mode 100644 App/BlurtiOS/Design/figma/exports.js delete mode 100644 App/BlurtiOS/Design/figma/foundations.js delete mode 100644 App/BlurtiOS/Design/figma/layouts.js delete mode 100644 App/BlurtiOS/Design/figma/manifest.json delete mode 100644 App/BlurtiOS/Design/figma/plugin.js delete mode 100644 App/BlurtiOS/Design/figma/themes.js delete mode 100644 App/BlurtiOS/Design/figma/tokens.js delete mode 100644 App/BlurtiOS/Design/fonts/ModernGothicMono-Light.ttf delete mode 100644 App/BlurtiOS/Design/fonts/ModernGothicMono-Medium.ttf delete mode 100644 App/BlurtiOS/Design/fonts/ModernGothicMono-Regular.ttf delete mode 100644 App/BlurtiOS/Design/fonts/OceanicText-Regular.otf delete mode 100644 App/BlurtiOS/Design/fonts/UN_11ST_Bold.ttf delete mode 100644 App/BlurtiOS/Design/fonts/UN_11ST_Regular.ttf delete mode 100755 scripts/design-figma-call.sh create mode 100755 scripts/ios-check.sh diff --git a/.claude/settings.json b/.claude/settings.json index 4f1d1d5d..ac54a6ac 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -24,6 +24,7 @@ "Bash(scripts/dev-build.sh)", "Bash(scripts/ios-sim.sh*)", "Bash(scripts/ios-test.sh*)", + "Bash(scripts/ios-check.sh*)", "Bash(scripts/ios-typecheck.sh*)", "Bash(prettier *)", "Bash(actionlint)", diff --git a/.claude/skills/check/SKILL.md b/.claude/skills/check/SKILL.md index 85fb52f5..1eb3bc19 100644 --- a/.claude/skills/check/SKILL.md +++ b/.claude/skills/check/SKILL.md @@ -126,8 +126,11 @@ hides every lint finding behind it — expect to fix a batch, not a queue. ## The iPhone app -`check.sh` covers `App/BlurtiOS` only by the dependency guard, the invariants and the linters. -Its build and tests run in CI's `ios-build` job (the authority). Locally: `scripts/ios-typecheck.sh` +`check.sh` covers `App/BlurtiOS` with the dependency guard, the invariants, the linters and +`ios-typecheck.sh`, and — off CI, when an iPhone simulator on this Xcode's iOS runtime exists — +`scripts/ios-check.sh`: the tests with `BlurtiOSCore`'s coverage gate, `swiftlint analyze` and +periphery over the iPhone project. Without that runtime it is skipped with a note (the closing `ok` +line says so) and CI's `ios-build` job, which runs the same script, is the authority. Locally: `scripts/ios-typecheck.sh` typechecks both iPhone targets on a Mac with only the Command Line Tools (run by `check.sh` when the SDK carries the Mac Catalyst frameworks), `scripts/ios-test.sh` runs `BlurtiOSTests` on a simulator when Xcode is installed and enforces `BlurtiOSCore`'s line-coverage floor (`MIN_IOS_COVERAGE`, 88%; diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index beb9fb1b..f11b6b30 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -262,25 +262,20 @@ jobs: # a second before every build, so it can never go stale against its yml. run: xcodegen generate --quiet - - name: Build the iPhone app and its keyboard, and run its unit tests - working-directory: blurt - # One scheme builds the app with the keyboard it embeds and runs - # BlurtiOSTests against it, on whichever iPhone simulator the runner has - # (scripts/ios-lib.sh picks). Ad hoc signing: the simulator accepts it - # and, unlike no signing, it embeds the App Group entitlement. - run: BLURT_DERIVED_DATA="$RUNNER_TEMP/BlurtiOS" scripts/ios-test.sh - - name: Scan the iPhone app for unused code + - name: Install the iPhone gates' linters + # swiftlint for `swiftlint analyze`, periphery for the unused-code scan; + # both are in the Brewfile too, so these are the versions check.sh uses. + run: brew install swiftlint periphery + + - name: Build the iPhone app and its keyboard, and run its quality gates working-directory: blurt - # periphery over the iOS project only — the Mac scan in check.sh can't - # see it. `--retain-public`: the engine's public API is used by the Mac - # app this scan can't see either, and the engine's own findings are - # excluded from the report, so only the iPhone code's dead declarations - # are reported. - run: | - brew install periphery - periphery scan --project App/BlurtiOS/BlurtiOS.xcodeproj --schemes BlurtiOS \ - --retain-public --retain-unused-protocol-func-params \ - --report-exclude 'Sources/**' --strict --quiet + # scripts/ios-check.sh — the iPhone's check.sh: BlurtiOSTests (warnings + # as errors, BlurtiOSCore's coverage gate) on whichever iPhone simulator + # the runner has (scripts/ios-lib.sh picks), then `swiftlint analyze` + # over that from-scratch build's log, then periphery. Ad hoc signing: the + # simulator accepts it and, unlike no signing, it embeds the App Group + # entitlement. + run: BLURT_DERIVED_DATA="$RUNNER_TEMP/BlurtiOS" scripts/ios-check.sh # The iPhone suite under each sanitizer, as check.sh runs the engine's. A job # of its own, one runner per sanitizer, rather than more steps in ios-build: diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 0d5e9c43..f4183f1b 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -95,6 +95,15 @@ jobs: -derivedDataPath "$DERIVED" \ -resolvePackageDependencies + # The iPhone app's project is generated, not committed (see check.yml's + # ios-build), so generate it before tracing starts. It has no remote + # packages to resolve — only the local engine. + - name: Generate the iPhone app's project (untraced) + working-directory: App/BlurtiOS + run: | + brew install xcodegen + xcodegen generate --quiet + - name: Initialize CodeQL uses: github/codeql-action/init@1c5b675653bb5c22dbe9b12b556ec555138e09fd # v4 with: @@ -122,6 +131,24 @@ jobs: CODE_SIGNING_ALLOWED=NO \ build + # The iPhone app, its keyboard and BlurtiOSCore, traced in the same + # database: CodeQL analyses whatever the job compiles between init and + # analyze, so the Mac build alone would leave App/BlurtiOS unscanned. + # Simulator, signing off — nothing here needs a device or a team. + - name: Build Swift (iPhone) + working-directory: App/BlurtiOS + run: | + xcodebuild \ + -project BlurtiOS.xcodeproj \ + -scheme BlurtiOS \ + -configuration Debug \ + -destination 'generic/platform=iOS Simulator' \ + -derivedDataPath "$DERIVED-ios" \ + CODE_SIGN_IDENTITY="-" \ + CODE_SIGNING_REQUIRED=NO \ + CODE_SIGNING_ALLOWED=NO \ + build + - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@1c5b675653bb5c22dbe9b12b556ec555138e09fd # v4 with: diff --git a/AGENTS.md b/AGENTS.md index 0ccb4b06..9ff81469 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -107,7 +107,9 @@ scripts/ check.sh, check-portability.sh, check-invariants.sh ios-sim.sh (build + run the iPhone app in the simulator), ios-test.sh (the iPhone unit tests, BlurtiOSTests, on a simulator, with BlurtiOSCore's line-coverage gate; BLURT_IOS_SANITIZER=thread|address - runs them under a sanitizer instead) + runs them under a sanitizer instead), + ios-check.sh (the iPhone's check.sh: ios-test, then swiftlint analyze + and periphery over App/BlurtiOS — CI's ios-build and a local check.sh) hand-run maintainer tools — no automated caller, invoked by a human, so "nothing references it" here does NOT mean dead code: screenshot.swift + beautify.swift (window imagery, capture @@ -207,18 +209,27 @@ the two checks that genuinely need the build products stay behind them (step 12) 12. **`swiftlint analyze`** (unused imports — reads the compiler log the app build captured) and **`periphery scan --strict`** (unused declarations — runs its own xcodebuild + index). The only two checks that can't move earlier. +13. **`scripts/ios-check.sh`** — the same gates for `App/BlurtiOS`: `BlurtiOSTests` with + `BlurtiOSCore`'s coverage gate, then `swiftlint analyze` over that build's log and periphery + over the iPhone project. Locally only, and only when an iPhone simulator on this Xcode's iOS + runtime exists (`xcodebuild -downloadPlatform iOS`); otherwise skipped with a note in the + closing `ok` line. On CI the `ios-build` job runs it instead. CI (`.github/workflows/check.yml`) installs all of these via Homebrew on `macos-26` and runs the same script, so a clean local `check.sh` matches CI by construction. One more job **is** required, because `check.sh` cannot cover it: **`ios-build`** compiles the engine for the iOS simulator (`xcodebuild -scheme BlurtEngine -destination 'generic/platform=iOS Simulator'`), which is the only place a macOS-only symbol that escaped its `#if os(macOS)` fence gets caught — `swift test` builds -for the host, and every other job runs on a Mac. It then runs `BlurtiOSTests` under the same bar -the engine's suite meets in `check.sh`: warnings as errors, a **line-coverage gate** on -`BlurtiOSCore`, the iPhone code's logic (≥ `MIN_IOS_COVERAGE` in `scripts/ios-test.sh`, the -engine's 88%; raise it as coverage grows), and — in the sibling +for the host, and every other job runs on a Mac. It then runs **`scripts/ios-check.sh`**, which holds +the iPhone code to the bar the engine and the Mac shell meet in `check.sh`: `BlurtiOSTests` with +warnings as errors and a **line-coverage gate** on `BlurtiOSCore`, the iPhone code's logic +(≥ `MIN_IOS_COVERAGE` in `scripts/ios-test.sh`, the engine's 88%; raise it as coverage grows), then +**`swiftlint analyze`** over that from-scratch build's log and **periphery** over the iPhone +project; `check.sh`'s swift-format, `swiftlint lint`, invariants and `ios-typecheck.sh` already read +every Swift file there. In the sibling **`ios-sanitizers`** job, one runner per sanitizer — **ThreadSanitizer** and **AddressSanitizer** -passes. `gate` fails unless all of them are green (or skipped for a docs-only change). Two sibling jobs exist purely to shorten the loop for whoever is +passes run the same tests. `codeql.yml`'s Swift analysis builds the iPhone app as well as the Mac +one, so both are in its database. `gate` fails unless all of them are green (or skipped for a docs-only change). Two sibling jobs exist purely to shorten the loop for whoever is editing Swift without a toolchain, and **neither is a required check** — both can only go red where `check` would too: diff --git a/App/Blurt/Blurt/AppIcon.icon/Assets/blurt-wordmark.png b/App/Blurt/Blurt/AppIcon.icon/Assets/blurt-wordmark.png index e287922976f0e8244efb0c00e05acd099487ab88..8bf85a458402a3a2c0525b9f2344eb2b917427cd 100644 GIT binary patch literal 2063088 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