Skip to content

Turn Autocomplete and Translate on or off per app or per window from the field icon - #847

Draft
senadaruc wants to merge 4 commits into
FuJacob:mainfrom
senadaruc:feat/field-icon-scope-menu
Draft

senadaruc wants to merge 4 commits into
FuJacob:mainfrom
senadaruc:feat/field-icon-scope-menu

Conversation

@senadaruc

Copy link
Copy Markdown

Summary

Builds on #845 (translation). This branch contains #845's commit; review only the last commit.

Clicking Cotabby's field-edge icon opens a small popup for the focused app and window:

  • Autocomplete and Translate each get an "In " switch and a This window choice: Same as app / On / Off. The window's choice wins.
  • A window is identified by its app plus its normalized title, with unread badges like (3) dropped. Chats in Teams or WhatsApp can therefore be configured individually.
  • App switches write to the existing owners (the disabled-apps list and the translation app list), so Settings and the popup always agree.
  • The icon is now clickable. Where autocomplete is off, the icon stays visible but dimmed, because it's the way to turn autocomplete back on.
  • The popup is a non-activating panel, so the host app keeps keyboard focus. It closes on an outside click, on Escape, or when focus moves to another app or window.

Design

  • WindowFeatureScope (pure, Support/Settings): window keys and the precedence rule. It also adjusts the disabled-apps set for the focused window, so every existing autocomplete availability gate respects window choices without changing their signatures.
  • WindowFeatureOverrideStore: window choices in UserDefaults, capped at 500 windows per feature.
  • The coordinator reads the window choice through a closure (windowAutocompleteOverride), so its tests need no store.

Test plan

  • 8 new unit tests (WindowFeatureScopeTests, WindowFeatureOverrideStoreTests).
  • Full suite: 2671 tests, 0 failures.
  • Hand test in Teams and WhatsApp: turn autocomplete off for one chat, check other chats; turn translate on for one chat only.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LptEE4YbaWL55YwQRnTt74

senadaruc and others added 2 commits October 2, 2026 16:07
Settings → Translation (off by default) translates chats in apps the user
picks (WhatsApp, Teams, Telegram, Slack, Outlook, Mail, Messages):

- Incoming: every 2 s, and right after scrolling, TranslationCoordinator
  captures the frontmost chat window (new captureActiveWindow), reads it
  with Vision OCR using language hints, groups lines into messages
  (MessageBlockGrouper: conversation area above the reply field,
  timestamps and low-confidence lines dropped), and draws each
  translation under its message in a click-through overlay. Unchanged
  windows are skipped by a pixel fingerprint.
- Replies: when the user writes in their reading language in a chat whose
  language is known, the reply is translated after a 700 ms pause and
  shown in a card under the field; ⌃⌥T (recordable) replaces the draft
  via select-all + paste with the clipboard restored. Never sends.
- Engines: Apple Translation (TranslationSession(installedSource:target:),
  on-device) for its ~20 languages; for pairs it lacks, such as
  Macedonian, the selected Open Source model with a few-shot prompt, as
  the bundled models are base models. Results are cached in memory only.
- TranslationLanguagePolicy is conservative (≥12 letters, ≥0.8
  confidence, no links or numbers) and recognizes Macedonian by its
  alphabet, since Natural Language reports it as Bulgarian.

Respects Cotabby's own gates (globally on, not paused, app not disabled,
Low Power Mode), never reads secure fields, and stores nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…the field icon

Clicking Cotabby's field-edge icon opens a small popup for the focused
app and window. It has an app switch and a window choice (same as app,
on, off) for Autocomplete and for Translate. A window is its app plus its
normalized title (unread badges like "(3) " dropped), so a Teams or
WhatsApp chat can be configured on its own.

- WindowFeatureScope (pure): window keys, "window choice wins over the
  app", and the disabled-apps set adjusted for the focused window, which
  every existing autocomplete gate now reads.
- WindowFeatureOverrideStore: window choices in UserDefaults, bounded to
  500 windows per feature.
- App switches write to the existing owners (disabled-apps list, the
  translation app list), so Settings and the popup agree.
- The icon is clickable, and stays visible but dimmed where autocomplete
  is off, since it is the way back on. The popup is a non-activating
  panel, so the host app keeps keyboard focus.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LptEE4YbaWL55YwQRnTt74
@coderabbitai

coderabbitai Bot commented Oct 2, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

senadaruc and others added 2 commits October 2, 2026 18:56
- Smaller popup (216pt): one row per feature with a compact switch, a
  mini "This window: App / On / Off" picker, Settings as a gear icon.
- A SwiftUI switch instead of the system one: the popup panel is never
  key (the host keeps focus), and AppKit drew inactive-window switches
  gray, so "on" looked "off". The hosting view accepts the first click.
- Teams, Slack and WhatsApp (Chromium/Electron) do not link the web
  field to its window in the AX tree, so no window title was found and
  the popup offered app switches only. FocusedInputSnapshot gains
  appFocusedWindowTitle (the app's focused-window title, read only when
  the field-relative read fails) and featureScopeWindowTitle. It is used
  only for window choices and the translation conversation key, never
  for prompts or session identity. This also fixes reply translation in
  Teams, whose conversation key never matched the incoming one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LptEE4YbaWL55YwQRnTt74

This branch has not been deployed

No deployments
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