fix(settings): banner quyền Trợ năng tự cập nhật ngay khi user cấp quyền - #41
Merged
Merged
Conversation
Banner chỉ re-evaluate ở onAppear + didBecomeKey. Nhưng System Settings GIỮ focus sau khi user tick checkbox, nên cửa sổ Cài đặt không bao giờ thành key lại → chữ đỏ "chưa có quyền" đứng nguyên cạnh một quyền đã sống. Field report: "cấp quyền rồi nhưng vẫn báo" — user phải click lại vào cửa sổ, hoặc logout. Hai nguyên nhân độc lập, sửa cả hai: 1. Thiếu trigger. Nay subscribe com.apple.accessibility.api qua DistributedNotificationCenter — CÙNG signal main.swift đã observe để dựng lại tap. App vốn đã event-driven cho tap; chỉ banner bị bỏ sót. 2. Đọc ra giá trị cũ. refreshAccessibilityStatus() gọi Accessibility.isTrusted, mà reader đó khi hết TTL trả .serveCachedAndRefresh: hand back giá trị CŨ rồi mới refresh ở background. Đúng cho keystroke path (cache tồn tại chính vì thế, và các path không được sai thì đọc TCC trực tiếp), sai cho UI — lần refresh đầu sau khi cấp quyền vẫn đọc false, và không có gì đọc lại nữa. Nên kể cả khi cửa sổ thành key lại, banner vẫn có thể đỏ. Thêm Accessibility.readTrustNow(): đồng bộ, bỏ qua cache, CHỈ dành cho UI path. Vẫn honor testTrustOverride trong #if DEBUG — không có nó thì SettingsModelTests/GonhanhHardeningTests sẽ đọc trạng thái TCC thật của máy build và fail tuỳ máy. Đọc 2 lần cách 1.5s: ngay sau toggle tccd còn trả giá trị CŨ (cùng race và cùng con số delay mà TerminalTapController.trustMayHaveChanged đã phòng). Một lần đọc duy nhất có thể latch banner sai theo chiều ngược lại — báo "quyền OK" ngay sau khi user THU HỒI quyền. Không timer, không polling. Xoá luôn nhu cầu "You may need to restart your Mac" trong chính text cảnh báo. 164 AppTests pass, 0 fail.
ptrinh
added a commit
that referenced
this pull request
Aug 12, 2026
… + test readTrustNow Hai điểm review của PR #41 (banner Trợ năng tự cập nhật): 1. DistributedNotificationCenter.publisher không đảm bảo deliver trên main (main.swift phải chỉ định queue: .main tường minh cùng lý do), mà handler mutate @published — thêm .receive(on: DispatchQueue.main). 2. readTrustNow() có test: honor testTrustOverride cả hai chiều, và không override thì khớp TCC thật + đồng bộ cache dùng chung. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ptrinh
added a commit
that referenced
this pull request
Aug 12, 2026
… cảm ơn @J2TEAM) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Owner
|
Merged + ship trong v1.5.7 🙏 Có thêm follow-up nhỏ (2ccc59a): |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Banner chỉ re-evaluate ở onAppear + didBecomeKey. Nhưng System Settings GIỮ focus sau khi user tick checkbox, nên cửa sổ Cài đặt không bao giờ thành key lại → chữ đỏ "chưa có quyền" đứng nguyên cạnh một quyền đã sống. Field report: "cấp quyền rồi nhưng vẫn báo" — user phải click lại vào cửa sổ, hoặc logout.
Hai nguyên nhân độc lập, sửa cả hai:
Thiếu trigger. Nay subscribe com.apple.accessibility.api qua DistributedNotificationCenter — CÙNG signal main.swift đã observe để dựng lại tap. App vốn đã event-driven cho tap; chỉ banner bị bỏ sót.
Đọc ra giá trị cũ. refreshAccessibilityStatus() gọi Accessibility.isTrusted, mà reader đó khi hết TTL trả .serveCachedAndRefresh: hand back giá trị CŨ rồi mới refresh ở background. Đúng cho keystroke path (cache tồn tại chính vì thế, và các path không được sai thì đọc TCC trực tiếp), sai cho UI — lần refresh đầu sau khi cấp quyền vẫn đọc false, và không có gì đọc lại nữa. Nên kể cả khi cửa sổ thành key lại, banner vẫn có thể đỏ. Thêm Accessibility.readTrustNow(): đồng bộ, bỏ qua cache, CHỈ dành cho UI path. Vẫn honor testTrustOverride trong #if DEBUG — không có nó thì SettingsModelTests/GonhanhHardeningTests sẽ đọc trạng thái TCC thật của máy build và fail tuỳ máy.
Đọc 2 lần cách 1.5s: ngay sau toggle tccd còn trả giá trị CŨ (cùng race và cùng con số delay mà TerminalTapController.trustMayHaveChanged đã phòng). Một lần đọc duy nhất có thể latch banner sai theo chiều ngược lại — báo "quyền OK" ngay sau khi user THU HỒI quyền. Không timer, không polling.
Xoá luôn nhu cầu "You may need to restart your Mac" trong chính text cảnh báo.