feat(desktop): mode de déclenchement « Basculer » en plus du push-to-talk (T-128) #119

Merged
ahitosly merged 5 commits from feat/T-128-desktop-toggle-hotkey into main 2026-09-09 18:16:05 +02:00
Owner

Tâche

T-xxx — (titre dans docs/STATUS.md)

Changements

Contrat modifié ?

  • Non
  • Oui : packages/contract / supabase/migrations — docs/API.md / docs/DATA.md mis à jour, label contract, approbation humaine requise

Tests

  • scripts/check.sh vert
  • Test manuel (OS, scénario) :

Impacts cross-domaine

Fichiers hors périmètre de l'agent (et pourquoi) :

Suivi

  • docs/STATUS.md mis à jour (ligne de la tâche)
  • docs/CHANGELOG.md : entrée ajoutée sous Unreleased
  • docs/DECISIONS.md / docs/ECARTS.md mis à jour si décision ou écart
## Tâche T-xxx — (titre dans docs/STATUS.md) ## Changements - ## Contrat modifié ? - [ ] Non - [ ] Oui : `packages/contract` / `supabase/migrations` — `docs/API.md` / `docs/DATA.md` mis à jour, label `contract`, approbation humaine requise ## Tests - [ ] `scripts/check.sh` vert - [ ] Test manuel (OS, scénario) : ## Impacts cross-domaine Fichiers hors périmètre de l'agent (et pourquoi) : ## Suivi - [ ] `docs/STATUS.md` mis à jour (ligne de la tâche) - [ ] `docs/CHANGELOG.md` : entrée ajoutée sous Unreleased - [ ] `docs/DECISIONS.md` / `docs/ECARTS.md` mis à jour si décision ou écart
Demande directe de l'humain : démarrer un enregistrement en appuyant
plusieurs fois rapidement sur une touche dédiée (nombre d'appuis
configurable), un seul appui pour arrêter — en plus du push-to-talk
existant, choix explicite entre les deux modes dans Settings (ADR-016).

- config::HotkeyMode (PushToTalk/Toggle) + toggle_hotkey/toggle_tap_count,
  rétrocompatibles avec un store existant (serde default par champ).
- hotkey.rs : ToggleTapTracker pur (partagé macOS/autres OS), watcher
  macOS dédié (CGEventTap déjà actif) et 2e Shortcut tauri-plugin-
  global-shortcut sur les autres OS (jamais testé en conditions réelles
  sur Windows/Linux, même prudence que le reste du fichier).
- Settings > Général : sélecteur de mode, capture de la touche de
  bascule (modificateur seul ou chord), nombre d'appuis (2 à 4).
- docs/SPEC.md §12 : « mode toggle » retiré du hors-scope v1.

20 nouveaux tests Rust exécutés (macOS), 155/155 verts ; cargo clippy
-D warnings clean ; pnpm typecheck/lint verts. Aucun changement de
contrat serveur ni de schéma Supabase.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TdSFu2vcsS98RjGrHFsWDg
git.cloud-rennais.fr:2222 injoignable depuis cette session (Network is
unreachable, confirmé en nc direct) — le code/tests/docs sont complets
sur cette branche locale, PR pas encore ouverte.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TdSFu2vcsS98RjGrHFsWDg
fix(desktop): Settings > Général — mode de déclenchement au-dessus, une seule carte affichée (T-128)
All checks were successful
ci / server (pull_request) Successful in 15s
ci / desktop-ts (pull_request) Successful in 28s
ci / desktop-rust (pull_request) Successful in 2m38s
6c2ddf0465
Le sélecteur de mode passe au-dessus des deux cartes (au lieu du
raccourci push-to-talk toujours affiché en premier), et la carte
push-to-talk ne s'affiche plus que si ce mode est actif — symétrique
avec la carte « Touche de bascule », déjà conditionnelle. Une seule
carte visible à la fois selon le mode choisi.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TdSFu2vcsS98RjGrHFsWDg
Author
Owner

Review PR #119 — T-128 / ADR-016 (mode « Basculer »)

Vérifications transverses

  • Périmètre : diff limité à apps/desktop/{src-tauri/src/{commands,config,hotkey,lib}.rs, src/lib/tauri.ts, src/settings/pages/General.tsx} + docs/{CLAUDE.md du domaine,DECISIONS,SPEC,STATUS,CHANGELOG}. Aucun fichier packages/contract/supabase/migrations touché — confirmé, pas de label contract requis, pas d'approbation humaine bloquante sur ce point.
  • Build/tests exécutés sur la branche (origin/feat/T-128-desktop-toggle-hotkey, checkout via worktree) : cargo test → 155/155 verts (conforme au chiffre annoncé dans STATUS.md), cargo clippy -- -D warnings → clean, pnpm tsc --noEmit → clean, pnpm lint (eslint) → clean.

1. Rétrocompatibilité AriaConfig — OK

config.rs:104-109 : les 3 champs (hotkey_mode via #[serde(default)] + HotkeyMode: Default, toggle_hotkey/toggle_tap_count via #[serde(default = "...")]) sont bien couverts. Le test aria_config_missing_toggle_fields_falls_back_field_by_field_not_to_full_default (config.rs:210-225) désérialise une vraie chaîne JSON legacy (r#"{"hotkey":"Alt+Shift+K","microphone":null,"locale":"en-US"}"#), pas un ConfigPatch construit à la main — exactement la précaution demandée, et il vérifie que hotkey/locale existants ne sont pas réinitialisés. Rien à redire ici.

2. Mutuelle exclusivité push-to-talk / bascule — BLOQUANT sur les OS non-macOS

macOS : logique correcte. should_swallow_main_key ne renvoie jamais true pour un combo à modificateur seul (main_key: None), et les deux mécanismes (main watcher / ToggleWatcherState) sont proprement gardés par hotkey_mode relu à chaque événement (hotkey.rs région macOS, ~889-928). Aucun risque d'action simultanée, ni d'accaparement du clavier par le simple fait d'avoir le watcher installé.

Sur les autres OS, j'ai vérifié le code source réel de global-hotkey 0.8.0 (version pinnée dans Cargo.lock:1791-1806, celle que tauri-plugin-global-shortcut embarque) plutôt que de me fier à la seule lecture de keyboard-types :

  • Windows (platform_impl/windows/mod.rs::key_to_vk) : la fonction qui mappe un Code vers un VIRTUAL_KEY avant RegisterHotKey n'a aucune entrée pour Code::ControlLeft/AltLeft/ShiftLeft/MetaLeft — elle tombe systématiquement sur _ => return None, donc register() retourne Err(FailedToRegister("Unknown VKCode for ...")).
  • X11/Linux (platform_impl/x11/mod.rs::keycode_to_x11_keysym) : même constat, aucune entrée pour ces 4 codes.

Donc other_os_main::modifier_code (hotkey.rs:334-341) et parse_toggle (hotkey.rs:346-353) parsent avec succès un modificateur seul (ex. "Control", le défaut — config.rs:23), mais l'appel app.global_shortcut().on_shortcut(shortcut, ...) dans register_toggle (hotkey.rs:369-390, l'erreur est jetée avec let _ = à la ligne 372) échoue systématiquement et silencieusement sur Windows et Linux, sans le moindre log::warn! (contrairement à parse_toggle_or_default, qui logue bien un échec de parsing, mais ce n'est pas le chemin emprunté ici puisque le parsing réussit). Même chose pour reregister_toggle (hotkey.rs:394-399) si l'utilisateur retape la même touche ou une autre touche seule.

Conséquence concrète : le mode Basculer, avec sa configuration par défaut (toggle_hotkey = "Control"), ou avec n'importe quel modificateur seul choisi via l'UI (bareModifierOf, General.tsx:57, qui encourage explicitement ce choix), ne fonctionnera jamais sur Windows/Linux, sans aucun message d'erreur ni dans les logs ni dans l'UI — un utilisateur croira juste avoir mal tapé sa séquence. C'est différent du risque déjà documenté dans CLAUDE.md/ADR-016 (« rien ne garantit qu'un raccourci global sans touche principale s'enregistre correctement selon la plateforme ») : ce n'est pas une incertitude, c'est un échec garanti par le code de la dépendance pinnée, pour le cas d'usage par défaut de la fonctionnalité.

À corriger avant merge, a minima l'un de :

  • logger l'échec de on_shortcut (pas seulement celui de parse_toggle) dans register_toggle/reregister_toggle, pour que ce ne soit pas totalement invisible ;
  • et/ou choisir un défaut toggle_hotkey différent pour les OS non-macOS (un vrai chord, ex. "Alt+K") puisqu'un modificateur seul ne pourra jamais s'enregistrer via ce backend sur Windows/X11 ;
  • et/ou, si l'un des deux points ci-dessus est reporté en dette consciente (cohérent avec la façon dont ce fichier traite déjà Windows/Linux comme « jamais testé »), le dire explicitement et de façon affirmative (pas juste « jamais testé ») dans apps/desktop/CLAUDE.md/STATUS.md : « confirmé par lecture du code source de global-hotkey 0.8.0 : un modificateur seul ne peut pas s'enregistrer sur Windows/Linux, le mode Basculer y nécessite un chord complet » — et retirer ou adapter l'option « modificateur seul » de l'UI pour ces OS, ou au moins prévenir l'utilisateur.

Le texte actuel de CLAUDE.md/ADR-016 (« keyboard-types 0.7.0 confirmé par lecture du crate vendu ») est trompeur en l'état : il vérifie que les variantes Code::ControlLeft etc. existent dans keyboard-types, mais pas que le backend global-hotkey sait les enregistrer — ce qu'il ne sait pas faire, précisément.

3. ToggleTapTracker / resynchronisation sur is_recording — OK

on_tap (hotkey.rs) reçoit is_recording recalculé à chaque appel depuis state.session.state() (macOS et autres OS), jamais un flag interne dupliqué — confirmé par le test stopping_then_a_fresh_double_tap_starts_again. Le compteur repart bien de zéro après un StartRecording ou un StopRecording, donc un Esc/une erreur qui termine l'enregistrement autrement ne laisse aucun état incohérent : le prochain appui recompte depuis 1. Rien à redire.

4. RLS/JWT — sans objet, confirmé

Aucun diff hors apps/desktop/docs.

5. UI — cartes mutuellement exclusives — OK

General.tsx : {cfg.hotkey_mode === "push_to_talk" && (...)} / {cfg.hotkey_mode === "toggle" && (...)} — une seule carte visible à la fois, cohérent avec le sélecteur de mode au-dessus (corrigé dans le 3ᵉ commit de la branche, 6c2ddf0).

Non-bloquant (à ne pas laisser bloquer le merge)

  • other_os_main::parse_toggle (hotkey.rs:346) n'accepte qu'un seul modificateur nu, alors que macos_main::parse_toggle_combo accepte plusieurs modificateurs nus combinés (ex. "Control+Shift", testé parse_toggle_combo_accepts_several_bare_modifiers). Incohérence mineure entre OS, actuellement inatteignable depuis l'UI (bareModifierOf n'autorise qu'un seul modificateur tenu à la fois), donc sans impact utilisateur aujourd'hui.
  • register_toggle est appelé sans condition au démarrage (lib.rs) et n'est jamais désenregistré/réenregistré au seul changement de hotkey_mode (seulement au changement de valeur de toggle_hotkey) — actuellement inoffensif partout (macOS : le swallow reste gardé par le mode ; Windows/Linux : la registration d'un modificateur seul échoue de toute façon, cf. point 2) mais latent : si un jour le défaut non-macOS devient un chord qui s'enregistre avec succès, ce chord resterait accaparé au niveau OS même en mode PushToTalk. À garder en tête si le point 2 est corrigé en changeant le défaut vers un chord.

Verdict : REQUEST_CHANGES

  1. Point 2 ci-dessus (bloquant) : le mode Basculer est actuellement non-fonctionnel par défaut sur Windows/Linux, de façon totalement silencieuse (aucun log, aucun signal UI) — corriger a minima le logging de l'échec de registration, idéalement aussi le défaut de toggle_hotkey pour ces OS, avant merge.

Tout le reste (rétrocompatibilité config, resynchronisation ToggleTapTracker, UI, absence de tout changement de contrat/schéma, suivi docs STATUS/CHANGELOG/DECISIONS/SPEC) est solide et vérifié.

## Review PR #119 — T-128 / ADR-016 (mode « Basculer ») ### Vérifications transverses - Périmètre : diff limité à `apps/desktop/{src-tauri/src/{commands,config,hotkey,lib}.rs, src/lib/tauri.ts, src/settings/pages/General.tsx}` + `docs/{CLAUDE.md du domaine,DECISIONS,SPEC,STATUS,CHANGELOG}`. Aucun fichier `packages/contract`/`supabase/migrations` touché — confirmé, pas de label `contract` requis, pas d'approbation humaine bloquante sur ce point. - Build/tests exécutés sur la branche (`origin/feat/T-128-desktop-toggle-hotkey`, checkout via worktree) : `cargo test` → **155/155 verts** (conforme au chiffre annoncé dans `STATUS.md`), `cargo clippy -- -D warnings` → clean, `pnpm tsc --noEmit` → clean, `pnpm lint` (eslint) → clean. ### 1. Rétrocompatibilité `AriaConfig` — OK `config.rs:104-109` : les 3 champs (`hotkey_mode` via `#[serde(default)]` + `HotkeyMode: Default`, `toggle_hotkey`/`toggle_tap_count` via `#[serde(default = "...")]`) sont bien couverts. Le test `aria_config_missing_toggle_fields_falls_back_field_by_field_not_to_full_default` (`config.rs:210-225`) désérialise une **vraie chaîne JSON legacy** (`r#"{"hotkey":"Alt+Shift+K","microphone":null,"locale":"en-US"}"#`), pas un `ConfigPatch` construit à la main — exactement la précaution demandée, et il vérifie que `hotkey`/`locale` existants ne sont pas réinitialisés. Rien à redire ici. ### 2. Mutuelle exclusivité push-to-talk / bascule — **BLOQUANT sur les OS non-macOS** macOS : logique correcte. `should_swallow_main_key` ne renvoie jamais `true` pour un combo à modificateur seul (`main_key: None`), et les deux mécanismes (main watcher / `ToggleWatcherState`) sont proprement gardés par `hotkey_mode` relu à chaque événement (`hotkey.rs` région macOS, ~889-928). Aucun risque d'action simultanée, ni d'accaparement du clavier par le simple fait d'avoir le watcher installé. Sur les autres OS, j'ai vérifié le code source réel de `global-hotkey 0.8.0` (version pinnée dans `Cargo.lock:1791-1806`, celle que `tauri-plugin-global-shortcut` embarque) plutôt que de me fier à la seule lecture de `keyboard-types` : - **Windows** (`platform_impl/windows/mod.rs::key_to_vk`) : la fonction qui mappe un `Code` vers un `VIRTUAL_KEY` avant `RegisterHotKey` **n'a aucune entrée pour `Code::ControlLeft`/`AltLeft`/`ShiftLeft`/`MetaLeft`** — elle tombe systématiquement sur `_ => return None`, donc `register()` retourne `Err(FailedToRegister("Unknown VKCode for ..."))`. - **X11/Linux** (`platform_impl/x11/mod.rs::keycode_to_x11_keysym`) : même constat, aucune entrée pour ces 4 codes. Donc `other_os_main::modifier_code` (`hotkey.rs:334-341`) et `parse_toggle` (`hotkey.rs:346-353`) parsent avec succès un modificateur seul (ex. `"Control"`, le défaut — `config.rs:23`), **mais l'appel `app.global_shortcut().on_shortcut(shortcut, ...)`** dans `register_toggle` (`hotkey.rs:369-390`, l'erreur est jetée avec `let _ =` à la ligne 372) **échoue systématiquement et silencieusement** sur Windows et Linux, sans le moindre `log::warn!` (contrairement à `parse_toggle_or_default`, qui logue bien un échec de *parsing*, mais ce n'est pas le chemin emprunté ici puisque le parsing réussit). Même chose pour `reregister_toggle` (`hotkey.rs:394-399`) si l'utilisateur retape la même touche ou une autre touche seule. **Conséquence concrète** : le mode Basculer, avec sa configuration par défaut (`toggle_hotkey = "Control"`), ou avec n'importe quel modificateur seul choisi via l'UI (`bareModifierOf`, `General.tsx:57`, qui encourage explicitement ce choix), **ne fonctionnera jamais sur Windows/Linux**, sans aucun message d'erreur ni dans les logs ni dans l'UI — un utilisateur croira juste avoir mal tapé sa séquence. C'est différent du risque déjà documenté dans `CLAUDE.md`/ADR-016 (« rien ne garantit qu'un raccourci global sans touche principale s'enregistre correctement selon la plateforme ») : ce n'est pas une incertitude, c'est un échec garanti par le code de la dépendance pinnée, pour le cas d'usage par défaut de la fonctionnalité. À corriger avant merge, a minima l'un de : - logger l'échec de `on_shortcut` (pas seulement celui de `parse_toggle`) dans `register_toggle`/`reregister_toggle`, pour que ce ne soit pas totalement invisible ; - et/ou choisir un défaut `toggle_hotkey` différent pour les OS non-macOS (un vrai chord, ex. `"Alt+K"`) puisqu'un modificateur seul ne pourra jamais s'enregistrer via ce backend sur Windows/X11 ; - et/ou, si l'un des deux points ci-dessus est reporté en dette consciente (cohérent avec la façon dont ce fichier traite déjà Windows/Linux comme « jamais testé »), le dire explicitement et de façon *affirmative* (pas juste « jamais testé ») dans `apps/desktop/CLAUDE.md`/`STATUS.md` : « confirmé par lecture du code source de `global-hotkey 0.8.0` : un modificateur seul ne peut pas s'enregistrer sur Windows/Linux, le mode Basculer y nécessite un chord complet » — et retirer ou adapter l'option « modificateur seul » de l'UI pour ces OS, ou au moins prévenir l'utilisateur. Le texte actuel de `CLAUDE.md`/ADR-016 (« keyboard-types 0.7.0 confirmé par lecture du crate vendu ») est trompeur en l'état : il vérifie que les variantes `Code::ControlLeft` etc. existent dans `keyboard-types`, mais pas que le backend `global-hotkey` sait les enregistrer — ce qu'il ne sait pas faire, précisément. ### 3. `ToggleTapTracker` / resynchronisation sur `is_recording` — OK `on_tap` (`hotkey.rs`) reçoit `is_recording` recalculé à chaque appel depuis `state.session.state()` (macOS et autres OS), jamais un flag interne dupliqué — confirmé par le test `stopping_then_a_fresh_double_tap_starts_again`. Le compteur repart bien de zéro après un `StartRecording` ou un `StopRecording`, donc un `Esc`/une erreur qui termine l'enregistrement autrement ne laisse aucun état incohérent : le prochain appui recompte depuis 1. Rien à redire. ### 4. RLS/JWT — sans objet, confirmé Aucun diff hors `apps/desktop`/`docs`. ### 5. UI — cartes mutuellement exclusives — OK `General.tsx` : `{cfg.hotkey_mode === "push_to_talk" && (...)}` / `{cfg.hotkey_mode === "toggle" && (...)}` — une seule carte visible à la fois, cohérent avec le sélecteur de mode au-dessus (corrigé dans le 3ᵉ commit de la branche, `6c2ddf0`). ### Non-bloquant (à ne pas laisser bloquer le merge) - `other_os_main::parse_toggle` (`hotkey.rs:346`) n'accepte qu'**un seul** modificateur nu, alors que `macos_main::parse_toggle_combo` accepte plusieurs modificateurs nus combinés (ex. `"Control+Shift"`, testé `parse_toggle_combo_accepts_several_bare_modifiers`). Incohérence mineure entre OS, actuellement inatteignable depuis l'UI (`bareModifierOf` n'autorise qu'un seul modificateur tenu à la fois), donc sans impact utilisateur aujourd'hui. - `register_toggle` est appelé sans condition au démarrage (`lib.rs`) et n'est jamais désenregistré/réenregistré au seul changement de `hotkey_mode` (seulement au changement de valeur de `toggle_hotkey`) — actuellement inoffensif partout (macOS : le swallow reste gardé par le mode ; Windows/Linux : la registration d'un modificateur seul échoue de toute façon, cf. point 2) mais latent : si un jour le défaut non-macOS devient un chord qui s'enregistre avec succès, ce chord resterait accaparé au niveau OS même en mode `PushToTalk`. À garder en tête si le point 2 est corrigé en changeant le défaut vers un chord. ### Verdict : **REQUEST_CHANGES** 1. Point 2 ci-dessus (bloquant) : le mode Basculer est actuellement non-fonctionnel par défaut sur Windows/Linux, de façon totalement silencieuse (aucun log, aucun signal UI) — corriger a minima le logging de l'échec de registration, idéalement aussi le défaut de `toggle_hotkey` pour ces OS, avant merge. Tout le reste (rétrocompatibilité config, resynchronisation `ToggleTapTracker`, UI, absence de tout changement de contrat/schéma, suivi docs STATUS/CHANGELOG/DECISIONS/SPEC) est solide et vérifié.
fix(desktop): touche de bascule modificateur-seul non fonctionnelle sur Windows/Linux (T-128)
All checks were successful
ci / server (pull_request) Successful in 14s
ci / desktop-ts (pull_request) Successful in 27s
ci / desktop-rust (pull_request) Successful in 2m38s
c4c01ae1d6
Trouvé par la review qa-regression (PR #119, REQUEST_CHANGES) : lecture
réelle du code source de global-hotkey 0.8.0 confirme qu'aucune entrée
n'existe dans ses backends Windows (key_to_vk)/X11 (keycode_to_x11_keysym)
pour un Code de modificateur seul (ControlLeft/AltLeft/ShiftLeft/MetaLeft)
— la registration échouait donc systématiquement et silencieusement sur
ces OS, y compris avec le défaut "Control", rendant le mode Basculer
totalement inopérant par défaut sans le moindre signal.

- config::DEFAULT_TOGGLE_HOTKEY devient cfg(target_os)-conditionnel :
  "Control" (bare modifier) sur macOS où ça fonctionne nativement via
  CGEventTap, "Alt+K" (chord classique, seul cas supporté par ce crate)
  sur les autres OS.
- hotkey.rs::register_toggle (other_os_main) loggue désormais en warn
  tout échec de on_shortcut, au lieu d'un `let _ =` totalement muet.
- apps/desktop/CLAUDE.md corrigé : l'ancienne mention ne prouvait que
  l'existence des variantes Code dans keyboard-types, pas leur support
  par le backend global-hotkey.

155 tests desktop rust verts, cargo clippy -D warnings clean.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TdSFu2vcsS98RjGrHFsWDg
Author
Owner

Correctif appliqué suite à la review (bug bloquant trouvé) : config::DEFAULT_TOGGLE_HOTKEY devient cfg(target_os)-conditionnel ("Control" sur macOS, "Alt+K" sur les autres OS où un modificateur seul ne s'enregistre pas via global-hotkey 0.8.0), et register_toggle (other_os_main) loggue désormais en warn tout échec de on_shortcut au lieu d'un let _ = muet. apps/desktop/CLAUDE.md et docs/STATUS.md/CHANGELOG.md mis à jour en conséquence. 155 tests desktop rust verts, clippy -D warnings clean. Redemande de review avant merge.

Correctif appliqué suite à la review (bug bloquant trouvé) : `config::DEFAULT_TOGGLE_HOTKEY` devient cfg(target_os)-conditionnel ("Control" sur macOS, "Alt+K" sur les autres OS où un modificateur seul ne s'enregistre pas via global-hotkey 0.8.0), et `register_toggle` (other_os_main) loggue désormais en warn tout échec de `on_shortcut` au lieu d'un `let _ =` muet. apps/desktop/CLAUDE.md et docs/STATUS.md/CHANGELOG.md mis à jour en conséquence. 155 tests desktop rust verts, clippy -D warnings clean. Redemande de review avant merge.
Author
Owner

APPROVE — le correctif (c4c01ae) règle bien le bug bloquant relevé dans la review précédente.

Vérifications effectuées (pas seulement relecture du diff) :

  1. Bug corrigé, confirmé par lecture directe du crate global-hotkey 0.8.0 installé localement (~/.cargo/registry/.../global-hotkey-0.8.0/src/platform_impl/{windows,x11}/mod.rs) : key_to_vk (Windows) et keycode_to_x11_keysym (X11) n'ont effectivement aucune entrée pour un Code de modificateur seul (ControlLeft/AltLeft/ShiftLeft/MetaLeft) — tous deux retombent sur _ => return None / erreur, jamais de panic. Le chemin d'erreur remonte proprement : key_to_vk → None → Err(FailedToRegister(...)) côté global-hotkey::register, propagé via run_main_thread!(...)? dans tauri-plugin-global-shortcut::register_internal, donc on_shortcut retourne bien Err — exactement ce que capte le nouveau if let Err(e) = ... on_shortcut(...) { log::warn!(...) } dans hotkey.rs::other_os_main::register_toggle. Le défaut DEFAULT_TOGGLE_HOTKEY étant désormais "Alt+K" (chord) sur ces OS via #[cfg(not(target_os = "macos"))], ce chemin d'échec n'est plus jamais emprunté par défaut ; il reste possible seulement si l'utilisateur reconfigure explicitement un modificateur seul, et c'est maintenant loggué en warn avec un message explicite (au lieu du let _ = silencieux d'origine). macOS conserve "Control" (fonctionne nativement via CGEventTap/CGEvent::get_flags(), watcher indépendant ToggleWatcherState), donc aucune régression du comportement déjà validé sur cet OS.

  2. Pas de régression, vérifié en exécutant moi-même (worktree sur origin/feat/T-128-desktop-toggle-hotkey, commit c4c01ae) :

    • cargo test (apps/desktop/src-tauri) : 155/155 verts, conforme à ce qu'annonce la PR.
    • cargo clippy --all-targets -- -D warnings : clean, aucun warning.
    • pnpm tsc --noEmit et pnpm lint (apps/desktop) : clean.
    • Nouveau test parse_toggle_default_hotkey_is_a_chord_on_this_os cohérent avec le nouveau défaut par OS ; les tests macOS (ToggleWatcherState/ToggleCombo, défaut "Control" bare) restent inchangés et verts.
  3. Les deux points non-bloquants notés à l'origine restent non-bloquants, aucun des deux n'est affecté par ce commit :

    • parse_toggle (other_os_main) n'accepte toujours qu'un seul modificateur bare (pas de "Control+Shift" bare) alors que parse_toggle_combo (macOS) accepte plusieurs modificateurs bare via try_fold — asymétrie mineure préexistante, sans impact sur le défaut ("Alt+K" est un chord classique, passe par parse dans les deux cas) ni sur aucun scénario testé.
    • register_toggle/register_main restent enregistrés au démarrage indépendamment de hotkey_mode (lib.rs) ; le filtrage se fait à l'exécution du callback (state.config.get().hotkey_mode == ...) plutôt qu'à la registration. Pas de comportement utilisateur incorrect (le mode inactif ne déclenche jamais la session), juste un raccourci global "réservé" inutilement dans l'OS pendant qu'il n'est pas utilisé — cohérent avec ce qui avait déjà été jugé acceptable.

Rien d'autre à signaler : docs (CLAUDE.md, STATUS.md, CHANGELOG.md, DECISIONS.md ADR-016, SPEC.md) cohérents avec le code, pas de fichier hors périmètre apps/desktop, pas de contrat/migration touché.

APPROVE — le correctif (c4c01ae) règle bien le bug bloquant relevé dans la review précédente. Vérifications effectuées (pas seulement relecture du diff) : 1. **Bug corrigé, confirmé par lecture directe du crate `global-hotkey` 0.8.0 installé localement** (`~/.cargo/registry/.../global-hotkey-0.8.0/src/platform_impl/{windows,x11}/mod.rs`) : `key_to_vk` (Windows) et `keycode_to_x11_keysym` (X11) n'ont effectivement **aucune entrée** pour un `Code` de modificateur seul (`ControlLeft`/`AltLeft`/`ShiftLeft`/`MetaLeft`) — tous deux retombent sur `_ => return None` / erreur, jamais de panic. Le chemin d'erreur remonte proprement : `key_to_vk` → `None` → `Err(FailedToRegister(...))` côté `global-hotkey::register`, propagé via `run_main_thread!(...)?` dans `tauri-plugin-global-shortcut::register_internal`, donc `on_shortcut` retourne bien `Err` — exactement ce que capte le nouveau `if let Err(e) = ... on_shortcut(...) { log::warn!(...) }` dans `hotkey.rs::other_os_main::register_toggle`. Le défaut `DEFAULT_TOGGLE_HOTKEY` étant désormais `"Alt+K"` (chord) sur ces OS via `#[cfg(not(target_os = "macos"))]`, ce chemin d'échec n'est plus jamais emprunté par défaut ; il reste possible seulement si l'utilisateur reconfigure explicitement un modificateur seul, et c'est maintenant loggué en `warn` avec un message explicite (au lieu du `let _ =` silencieux d'origine). macOS conserve `"Control"` (fonctionne nativement via `CGEventTap`/`CGEvent::get_flags()`, watcher indépendant `ToggleWatcherState`), donc aucune régression du comportement déjà validé sur cet OS. 2. **Pas de régression, vérifié en exécutant moi-même** (worktree sur `origin/feat/T-128-desktop-toggle-hotkey`, commit `c4c01ae`) : - `cargo test` (apps/desktop/src-tauri) : **155/155 verts**, conforme à ce qu'annonce la PR. - `cargo clippy --all-targets -- -D warnings` : **clean**, aucun warning. - `pnpm tsc --noEmit` et `pnpm lint` (apps/desktop) : **clean**. - Nouveau test `parse_toggle_default_hotkey_is_a_chord_on_this_os` cohérent avec le nouveau défaut par OS ; les tests macOS (`ToggleWatcherState`/`ToggleCombo`, défaut `"Control"` bare) restent inchangés et verts. 3. **Les deux points non-bloquants notés à l'origine restent non-bloquants**, aucun des deux n'est affecté par ce commit : - `parse_toggle` (other_os_main) n'accepte toujours qu'un seul modificateur bare (pas de "Control+Shift" bare) alors que `parse_toggle_combo` (macOS) accepte plusieurs modificateurs bare via `try_fold` — asymétrie mineure préexistante, sans impact sur le défaut (`"Alt+K"` est un chord classique, passe par `parse` dans les deux cas) ni sur aucun scénario testé. - `register_toggle`/`register_main` restent enregistrés au démarrage indépendamment de `hotkey_mode` (`lib.rs`) ; le filtrage se fait à l'exécution du callback (`state.config.get().hotkey_mode == ...`) plutôt qu'à la registration. Pas de comportement utilisateur incorrect (le mode inactif ne déclenche jamais la session), juste un raccourci global "réservé" inutilement dans l'OS pendant qu'il n'est pas utilisé — cohérent avec ce qui avait déjà été jugé acceptable. Rien d'autre à signaler : docs (`CLAUDE.md`, `STATUS.md`, `CHANGELOG.md`, `DECISIONS.md` ADR-016, `SPEC.md`) cohérents avec le code, pas de fichier hors périmètre `apps/desktop`, pas de contrat/migration touché.
ahitosly scheduled this pull request to auto merge when all checks succeed 2026-09-09 18:15:10 +02:00
docs(status): T-128 — 2e review qa-regression APPROVE, merge programmé (PR #119)
All checks were successful
ci / server (pull_request) Successful in 15s
ci / desktop-ts (pull_request) Successful in 28s
ci / desktop-rust (pull_request) Successful in 3m11s
fd4f8ce03a
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TdSFu2vcsS98RjGrHFsWDg
ahitosly deleted branch feat/T-128-desktop-toggle-hotkey 2026-09-09 18:16:05 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
cloud-rennais/aria!119
No description provided.