Skip to content

feat: separate the app master switch from locking#39

Merged
BlackHole1 merged 2 commits into
mainfrom
feat/decouple-lock-switch
Jun 27, 2026
Merged

feat: separate the app master switch from locking#39
BlackHole1 merged 2 commits into
mainfrom
feat/decouple-lock-switch

Conversation

@BlackHole1

Copy link
Copy Markdown
Member

The single "Enable input-source locking" toggle gated everything — both the continuous lock and the one-shot switch rules — so turning it off to avoid a global lock silently disabled per-app and per-URL switch rules too. That left no way to run LockIME as a pure switcher (the Input Source Pro model the issue asks for): you either locked everything or got nothing.

This splits the model into two levels. A master isEnabled ("Enable LockIME") gates the whole app, and a new subordinate lockingEnabled ("Enable locking", on by default) gates only the continuous lock — the global default, per-app .locked rules, URL .lock rules, and the address-bar lock. One-shot switching is now gated by the master alone, so master on + locking off pins nothing while per-app/per-site switch rules keep firing. In the General pane the second toggle sits under the master and dims when it's off (the HIG subordinate-control pattern).

Backward compatible: LockConfiguration decodes an absent lockingEnabled as true, so existing configs — and the lock-on default — behave exactly as before. The only users whose behavior changes are the ones the issue is about: those who had the master off with switch rules configured, whose switching now starts working.

Also updated to match: the menu bar (clicking the checked source clears just the global lock target instead of disabling the app), the toggle-lock shortcut (flips the master), the lockime:// API (new set-locking command; status now reports enabled and lockingEnabled alongside locked), and the README + URL-Scheme-API docs across all nine languages.

The decoupling truth table is covered by new engine tests, plus migration-default and set-locking parser tests.

Closes #37

The single "Enable input-source locking" toggle gated everything —
both the continuous lock and the one-shot switch rules. Turning it
off to avoid a global lock silently disabled per-app and per-URL
switch rules too, so LockIME could not be used as a pure switcher
(the Input Source Pro model the issue asks for).

Split the model in two: the master `isEnabled` ("Enable LockIME")
gates the whole app, and a new subordinate `lockingEnabled`
("Enable locking", on by default) gates only continuous locking.
One-shot switching is now gated by the master alone, so master on
plus locking off pins nothing while per-app/per-site switch rules
keep firing. `LockConfiguration` decodes an absent `lockingEnabled`
as `true`, so existing configs and the lock-on default are
unchanged.

The menu bar, the toggle-lock shortcut, the `lockime://` API (new
`set-locking` command; `status` now reports `enabled` and
`lockingEnabled`), and the README / URL-Scheme-API docs in all nine
languages are updated to match.

Closes #37

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

coderabbitai Bot commented Jun 27, 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: 0291bc98-baa0-478d-8550-b204a3629a39

📥 Commits

Reviewing files that changed from the base of the PR and between c1ed574 and 453c950.

📒 Files selected for processing (9)
  • 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
✅ Files skipped from review due to trivial changes (5)
  • docs/URL-Scheme-API/README.zh-CN.md
  • docs/URL-Scheme-API/README.es.md
  • docs/URL-Scheme-API/README.md
  • docs/URL-Scheme-API/README.zh-TW.md
  • docs/URL-Scheme-API/README.ja.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • docs/URL-Scheme-API/README.de.md
  • docs/URL-Scheme-API/README.ru.md

Summary by CodeRabbit

  • New Features
    • Added separate controls for enabling LockIME (master) and enabling continuous locking (sub-toggle).
    • Added URL-scheme support for setting continuous locking independently (set-locking / locking).
    • Expanded status reporting to include both LockIME enabled state and whether continuous locking is active.
  • Bug Fixes
    • Clicking the selected menu-bar source now clears only the global lock target, keeping switching rules active.
    • Lock-related shortcut behavior now aligns with the master “Enable LockIME” toggle.
  • Documentation
    • Updated README and URL API docs to reflect the two-toggle model.
  • Tests
    • Added test coverage for continuous locking, master/lock decoupling, and URL command parsing.

Walkthrough

The PR separates LockIME master enablement from continuous locking. LockConfiguration, AppState, and LockEngine now treat lockingEnabled as a separate control. The URL scheme adds set-locking and returns enabled plus lockingEnabled in status responses. The Settings pane and menu bar actions reflect the new behavior, and the README, design docs, and localized strings are updated.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant SettingsPane
  participant AppState
  participant LockEngine
  participant URLCommandHandler

  User->>SettingsPane: toggle Enable LockIME / Enable locking
  SettingsPane->>AppState: setMasterEnabled / setLockingEnabled
  AppState->>LockEngine: apply(reason:)
  LockEngine->>LockEngine: reevaluate / enable or disable enforcement

  User->>URLCommandHandler: lockime://set-locking?enabled=...
  URLCommandHandler->>AppState: update lockingEnabled
  AppState->>LockEngine: apply(reason:)
Loading

Possibly related PRs

  • oomol-lab/LockIME#6: Touches the same menu-bar source selection and lock-target flow in MenuBarView and AppState.
  • oomol-lab/LockIME#22: Changes the same LockEngine flow that this PR now gates with lockingEnabled.
  • oomol-lab/LockIME#25: Extends the same lockime:// command handling path that this PR adds set-locking to.
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is English and clearly describes the main change, separating the master switch from locking.
Description check ✅ Passed The description matches the PR and explains the master-vs-locking split and related behavior changes.
Linked Issues check ✅ Passed The changes address #37 by allowing app and URL switch rules to work when global locking is off.
Out of Scope Changes check ✅ Passed The edits are consistent with the stated objective and the docs/tests support the same locking split.
✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch feat/decouple-lock-switch

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 markdownlint-cli2 (0.22.1)
docs/URL-Scheme-API/README.de.md

markdownlint-cli2 wrapper config was not available before execution

docs/URL-Scheme-API/README.es.md

markdownlint-cli2 wrapper config was not available before execution

docs/URL-Scheme-API/README.fr.md

markdownlint-cli2 wrapper config was not available before execution

  • 6 others

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: 3

🤖 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 `@docs/URL-Scheme-API/README.md`:
- Around line 81-94: Clarify the runtime behavior of the master/sub-toggle in
the Enable & locking section: the current wording in the `set-locking`
description implies no effect while the master is off, but `lockingEnabled` is
still persisted and reported by `status`. Update the copy around `lock`,
`unlock`, `toggle-lock`, and `set-locking` to explicitly distinguish immediate
runtime effect from persisted observable state, so readers understand that
`set-locking` can still change state even when `LockIME` is off.

In `@docs/URL-Scheme-API/README.pt.md`:
- Around line 97-98: In the Portuguese README translation, update the wording
for the alias labels in the table so it uses “aliás” instead of “alias”; adjust
the entries for the `toggle-lock` and `set-locking` rows in `README.pt.md` to
keep the translation natural and consistent with the rest of the document.

In `@Sources/LockIME/UI/MenuBarView.swift`:
- Around line 55-61: The checked-row clear path in MenuBarView should key off
the configured default target, not state.isLocked, so the current saved source
remains selectable even when locking is disabled. Update the isLockedTo
condition in MenuBarView’s Button action to use state.config.defaultSourceID ==
source.id as the source of truth, and keep the clear action on
state.setDefaultSource(nil) tied to that target. This ensures the “click checked
source” path still clears the stored defaultSourceID regardless of
lockingEnabled.
🪄 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: c89bae3c-8b13-447e-90de-6e4a6ff09794

📥 Commits

Reviewing files that changed from the base of the PR and between 6678f00 and c1ed574.

📒 Files selected for processing (31)
  • README.md
  • Sources/LockIME/API/URLCommandHandler.swift
  • Sources/LockIME/AppState.swift
  • Sources/LockIME/Localizable.xcstrings
  • 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 docs/URL-Scheme-API/README.md Outdated
Comment thread docs/URL-Scheme-API/README.pt.md Outdated
Comment thread Sources/LockIME/UI/MenuBarView.swift
set-locking persists lockingEnabled (and status reports it), so it still
changes observable state while the master is off — it simply has no
immediate runtime effect until the master is on. Sync the wording across
all nine URL-Scheme-API docs.

Signed-off-by: Kevin Cui <bh@bugs.cc>
@BlackHole1 BlackHole1 merged commit 1bb5723 into main Jun 27, 2026
3 checks passed
@BlackHole1 BlackHole1 deleted the feat/decouple-lock-switch branch June 27, 2026 14:38
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