Skip to content

feat!: collapse the two-level enable model into one master switch#50

Merged
BlackHole1 merged 2 commits into
mainfrom
feat/single-enable-switch
Jul 2, 2026
Merged

feat!: collapse the two-level enable model into one master switch#50
BlackHole1 merged 2 commits into
mainfrom
feat/single-enable-switch

Conversation

@BlackHole1

Copy link
Copy Markdown
Member

The "Enable locking" sub-toggle (#39, for issue #37) gave the app two states for one concept: a global default of None already expresses "switch on entry, pin nothing", so keeping a separate locking switch on top of Enable LockIME was redundant. This collapses the model back to the single switch — it gates everything, the General pane loses the sub-toggle, and the tray/menu header now reads Enabled/Disabled instead of Locked/Unlocked (new catalog keys, translated for every supported language).

LockConfiguration.lockingEnabled is removed. A config that explicitly persisted lockingEnabled: false (a v1.5.x pure-switch user) migrates on first decode by clearing defaultSourceID, so the upgrade cannot silently re-pin their input source everywhere. Rule-level locks (.locked app rules, .lock URL/address-bar rules) deliberately re-engage instead of being demoted — rules now mean what they say, and rewriting the user's rule modes on a heuristic would be the more destructive migration. The decode shim is marked TODO(legacy-locking-migration) and can be deleted a few releases from now, once nobody is upgrading straight from v1.5.x.

The README and the URL Scheme API reference are updated across all nine languages.

Breaking API change: the set-locking URL command (alias locking) now fails with unknown_command, and the status payload no longer carries lockingEnabled/locked — read enabled instead.

Refs #37

The subordinate "Enable locking" toggle (added by #39 for issue #37)
made the app carry two states for one concept: a global default of
None already expresses "switch on entry, pin nothing", so the
sub-toggle was redundant. One `Enable LockIME` switch now gates
everything, and the tray header reads Enabled/Disabled instead of
Locked/Unlocked.

`LockConfiguration.lockingEnabled` is gone. A legacy config that
explicitly persisted `lockingEnabled: false` (a v1.5.x pure-switch
user) migrates by clearing `defaultSourceID`, so the upgrade cannot
silently re-pin their input source everywhere. Rule-level locks
(`.locked` app rules, `.lock` URL/address-bar rules) deliberately
re-engage instead of being demoted: rules now mean what they say, and
rewriting the user's rule modes on a heuristic would be the more
destructive migration. The decode shim is marked
`TODO(legacy-locking-migration)` for removal a few releases from now.

The README and the URL Scheme API reference are updated across all
nine languages, and the catalog swaps the Locked/Unlocked keys for
Enabled/Disabled with translations for every supported language.

BREAKING CHANGE: the `set-locking` URL command (alias `locking`) now
fails with `unknown_command`, and the `status` payload no longer
carries `lockingEnabled`/`locked` — read `enabled` instead.

Signed-off-by: Kevin Cui <bh@bugs.cc>
@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 54dc0fc2-af9e-4276-9c4b-f24f33736c22

📥 Commits

Reviewing files that changed from the base of the PR and between 36813ee and d3086cf.

📒 Files selected for processing (2)
  • Sources/LockIMEKit/LockEngine/LockEngine.swift
  • Tests/LockIMEKitTests/LockEngineAddressBarTests.swift

Summary by CodeRabbit

  • New Features
    • Simplified LockIME to a single Enable/Disable control; a global default of “None” makes it a pure per-app/per-site switcher.
    • Updated UI, icons, and status text to Enabled/Disabled.
    • Updated URL scheme behavior: removed the continuous-locking sub-toggle and aligned commands/status to the new model.
  • Bug Fixes
    • When LockIME is disabled, URL and address-bar observation no longer attaches.
    • Improved migration of legacy settings to preserve sensible behavior.
  • Documentation
    • Updated README, URL scheme API docs, design notes, and translations to match the new controls/status.
  • Tests
    • Added/updated tests for migration, URL parsing, and disable/enable observation behavior.

Walkthrough

This PR removes the lockingEnabled sub-toggle and reworks the app around a single isEnabled master switch. It updates LockConfiguration, LockEngine, AppState, URL command parsing/handling, menu bar and settings UI, localized strings, tests, and the README/design/API docs to describe enable/disable semantics and global default input-source behavior.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Title check ⚠️ Warning The title matches the change, but it does not follow the required <type>(<scope>): <subject> format. Rewrite it in conventional format, for example feat(lockime): collapse the two-level enable model into one master switch.},{
✅ Passed checks (2 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch feat/single-enable-switch

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
docs/README/README.es.md (1)

136-136: 📐 Maintainability & Code Quality | 🔵 Trivial

Point this cross-link at the canonical English reference.

This translated README should link to the English URL Scheme API doc to stay aligned with the docs guideline and avoid per-locale drift.

♻️ Proposed fix
- Referencia completa: **[URL Scheme API](../URL-Scheme-API/README.es.md)**.
+ Referencia completa: **[URL Scheme API](../URL-Scheme-API/README.md)**.

As per coding guidelines, "Intra-doc links in translated READMEs should point at English docs using relative paths (../DESIGN.md, ../RELEASING.md, ../../README.md, ../../LICENSE)."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/README/README.es.md` at line 136, The cross-link in the translated
README still points to the Spanish URL Scheme API doc instead of the canonical
English reference. Update the Markdown link in README.es.md for the URL Scheme
API entry to use the English target, following the same relative-path pattern
used by other translated docs, and keep the link text unchanged.

Source: Coding guidelines

docs/README/README.de.md (1)

132-132: 📐 Maintainability & Code Quality | 🔵 Trivial

Point this cross-link at the canonical English reference.

This translated README should link to the English URL Scheme API doc to stay aligned with the docs guideline and avoid per-locale drift.

♻️ Proposed fix
- **[URL Scheme API](../URL-Scheme-API/README.de.md)**
+ **[URL Scheme API](../URL-Scheme-API/README.md)**

As per coding guidelines, "Intra-doc links in translated READMEs should point at English docs using relative paths (../DESIGN.md, ../RELEASING.md, ../../README.md, ../../LICENSE)."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/README/README.de.md` at line 132, The cross-link in the translated
README points to the localized URL Scheme API doc instead of the canonical
English reference. Update the Markdown link in README.de.md so it targets the
English URL-Scheme-API README using the appropriate relative path, consistent
with the docs guideline for translated READMEs and the existing link style in
this section.

Source: Coding guidelines

docs/README/README.fr.md (1)

132-132: 📐 Maintainability & Code Quality | 🔵 Trivial

Point this cross-link at the canonical English reference.

This translated README should link to the English URL Scheme API doc to stay aligned with the docs guideline and avoid per-locale drift.

♻️ Proposed fix
- Référence complète : **[URL Scheme API](../URL-Scheme-API/README.fr.md)**.
+ Référence complète : **[URL Scheme API](../URL-Scheme-API/README.md)**.

As per coding guidelines, "Intra-doc links in translated READMEs should point at English docs using relative paths (../DESIGN.md, ../RELEASING.md, ../../README.md, ../../LICENSE)."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/README/README.fr.md` at line 132, The cross-link in README.fr.md points
to the French URL Scheme API page instead of the canonical English doc. Update
the reference so the translated README links to the English URL-Scheme-API
README using the relative path convention used elsewhere in translated docs,
keeping the link target aligned with the docs guideline.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Sources/LockIMEKit/LockEngine/LockEngine.swift`:
- Around line 134-151: apply(false) is still leaving URL polling and address-bar
monitoring active because LockEngine.apply(_:reason:) always calls
updateURLPolling() and updateAddressBarMonitoring(). Update those helpers, or
gate their calls from apply(_:reason:), so they no-op or tear down observers
when config.isEnabled is false and only start monitoring when the master switch
is on.

---

Nitpick comments:
In `@docs/README/README.de.md`:
- Line 132: The cross-link in the translated README points to the localized URL
Scheme API doc instead of the canonical English reference. Update the Markdown
link in README.de.md so it targets the English URL-Scheme-API README using the
appropriate relative path, consistent with the docs guideline for translated
READMEs and the existing link style in this section.

In `@docs/README/README.es.md`:
- Line 136: The cross-link in the translated README still points to the Spanish
URL Scheme API doc instead of the canonical English reference. Update the
Markdown link in README.es.md for the URL Scheme API entry to use the English
target, following the same relative-path pattern used by other translated docs,
and keep the link text unchanged.

In `@docs/README/README.fr.md`:
- Line 132: The cross-link in README.fr.md points to the French URL Scheme API
page instead of the canonical English doc. Update the reference so the
translated README links to the English URL-Scheme-API README using the relative
path convention used elsewhere in translated docs, keeping the link target
aligned with the docs guideline.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4bed137c-1197-43d7-b890-a101cd7cd981

📥 Commits

Reviewing files that changed from the base of the PR and between 1cd8c39 and 36813ee.

📒 Files selected for processing (34)
  • README.md
  • Sources/LockIME/API/URLCommandHandler.swift
  • Sources/LockIME/AppState.swift
  • Sources/LockIME/Localizable.xcstrings
  • Sources/LockIME/LockIMEApp.swift
  • Sources/LockIME/Shortcuts/ShortcutNames.swift
  • Sources/LockIME/UI/AboutView.swift
  • Sources/LockIME/UI/MenuBarView.swift
  • Sources/LockIME/UI/Settings/GeneralSettingsPane.swift
  • Sources/LockIMEKit/API/URLCommand.swift
  • Sources/LockIMEKit/Backup/ImportPlan.swift
  • Sources/LockIMEKit/LockEngine/LockEngine.swift
  • Sources/LockIMEKit/Rules/LockConfiguration.swift
  • Tests/LockIMEKitTests/LockConfigurationTests.swift
  • Tests/LockIMEKitTests/LockEngineTests.swift
  • Tests/LockIMEKitTests/URLCommandParserTests.swift
  • docs/DESIGN.md
  • docs/README/README.de.md
  • docs/README/README.es.md
  • docs/README/README.fr.md
  • docs/README/README.ja.md
  • docs/README/README.pt.md
  • docs/README/README.ru.md
  • docs/README/README.zh-CN.md
  • docs/README/README.zh-TW.md
  • docs/URL-Scheme-API/README.de.md
  • docs/URL-Scheme-API/README.es.md
  • docs/URL-Scheme-API/README.fr.md
  • docs/URL-Scheme-API/README.ja.md
  • docs/URL-Scheme-API/README.md
  • docs/URL-Scheme-API/README.pt.md
  • docs/URL-Scheme-API/README.ru.md
  • docs/URL-Scheme-API/README.zh-CN.md
  • docs/URL-Scheme-API/README.zh-TW.md

Comment thread Sources/LockIMEKit/LockEngine/LockEngine.swift
`apply()` re-ran `updateURLPolling()`/`updateAddressBarMonitoring()` on
every config change, but neither helper guarded on `config.isEnabled`,
so a disabled LockIME kept polling browser URLs and kept its AX
address-bar observer attached — observing when it could never act.
Pre-existing behavior, but the single-switch model makes "off ⇒ fully
idle" the documented contract, so gate both helpers on the master.

Signed-off-by: Kevin Cui <bh@bugs.cc>
@BlackHole1 BlackHole1 merged commit 84ffc96 into main Jul 2, 2026
3 checks passed
@BlackHole1 BlackHole1 deleted the feat/single-enable-switch branch July 2, 2026 05:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant