Add "On Layout Switch" correction mode, permissions menu, and broader layout detection#4
Conversation
… be granted later
…xt is transcripted automatically. Also added a helper textContainsScript() method to check if the text is latin, cirylic, etc.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 64352cc862
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| let fromVariant = inputSourceManager.currentUkrainianVariant() ?? inputSourceManager.preferredUkrainianVariant() | ||
| let toVariant = inputSourceManager.preferredUkrainianVariant() |
There was a problem hiding this comment.
Track actual Ukrainian variants during layout switches
When layout-switch correction involves Ukrainian and the user has both standard and legacy Ukrainian sources installed, these values can use the wrong keymap: the notification is handled after the system has already switched, so currentUkrainianVariant() describes the new layout when switching into Ukrainian and is nil when switching out, while toVariant is always the preferred/first discovered source. For example, switching English → Ukrainian Legacy will still convert with the preferred standard mapping, so letters on the s/b positions are transcribed incorrectly for both selection and buffer correction.
Useful? React with 👍 / 👎.
| "com.apple.keylayout.USInternational-PC", | ||
| "com.apple.keylayout.Colemak", | ||
| "com.apple.keylayout.Dvorak", | ||
| "keylayout.US", |
There was a problem hiding this comment.
Keep switch fallbacks as selectable source IDs
These entries are now suffix fragments, but InputSourceManager.switchTo still builds its fallback targetIDs from Layout.inputSourceIDs and compares them to TIS source IDs with exact equality. If a supported Apple layout is added after startup, or installedSourceIDs is otherwise not populated for the target, the fallback now tries values like keylayout.US instead of com.apple.keylayout.US, so corrections cannot switch to that layout until the app rediscovers it or restarts.
Useful? React with 👍 / 👎.
1. New correction mode: "On Layout Switch"
Introduces CorrectionMode.layoutSwitch as a third option next to automatic and hotkey. When enabled, SwitchFix observes NSTextInputContext.keyboardSelectionDidChangeNotification and, on a real layout change, transcribes either:
the currently selected text (via Permissions.getSelectedText()), or
the current in-progress word buffer from LayoutDetector,
from the previous layout into the new one — without triggering an additional layout switch (new shouldSwitchLayout flag on TextCorrector.performSelectionCorrection and DetectionResult).
A new helper AppDelegate.textContainsScript(of:text:) skips conversion when the selected text doesn't actually contain letters of the source layout's script (Latin for English, Cyrillic for Ukrainian/Russian), preventing spurious transcriptions of already-foreign text.
UI:
SettingsView exposes the new mode with a descriptive caption.
StatusBarController adds an "On Layout Switch" item to the Correction Mode submenu.
2. Permissions visible in the menu bar
StatusBarController now surfaces missing Accessibility and Input Monitoring permissions directly in the status bar menu, with click-through items that open the relevant System Settings panes (openAccessibilitySettings / openInputMonitoringSettings). The menu bar tooltip reflects a "missing permissions" state, and the indicators refresh every time the menu opens — so users can grant permissions after first launch without restarting the app.
3. Wider input-layout coverage
LayoutMapper matches input source IDs by suffix (e.g. keylayout.US) instead of exact full bundle IDs, and adds USExtended to the English set. This accommodates third-party and non-com.apple.keylayout.* sources. InputSourceManager now logs any unmatched input sources to aid diagnostics and avoids repeated matching work per source.
Files changed
Sources/Core/InputSourceManager.swift — single-pass matching + unmatched-source logging
Sources/Core/LayoutMapper.swift — suffix-based matches(sourceID:), added USExtended
Sources/Core/LayoutDetector.swift — public memberwise initializer for DetectionResult
Sources/Core/TextCorrector.swift — optional shouldSwitchLayout parameter
Sources/SwitchFixApp/AppDelegate.swift — layout-change observer, triggerLayoutSwitchCorrection, textContainsScript helper, correction-in-progress guard
Sources/UI/PreferencesManager.swift — new CorrectionMode.layoutSwitch case
Sources/UI/SettingsView.swift — picker option + per-mode description
Sources/UI/StatusBarController.swift — permission menu items, tooltip, new mode entry