Skip to content

feat(wework): add quick phrases - #2005

Merged
qdaxb merged 3 commits into
mainfrom
feature/wework-quick-phrases
Jul 17, 2026
Merged

qdaxb merged 3 commits into
mainfrom
feature/wework-quick-phrases

Conversation

@qdaxb

@qdaxb qdaxb commented Jul 16, 2026 •

Copy link
Copy Markdown
Contributor

What changed

  • add a searchable quick-phrase picker to desktop and compact Wework composers
  • append selected phrases to the current draft and switch Normal, Plan, or Goal mode
  • add desktop and mobile settings for creating, editing, deleting, and ordering device-local phrases
  • persist phrases in Tauri app preferences with three editable defaults
  • document the workflow in the Chinese and English coding guides

Why

Frequently reused prompts previously had to be typed or pasted manually. Quick phrases provide a fast pointer and keyboard path while preserving the draft for review before sending.

Validation

  • pnpm --filter wework typecheck
  • pnpm --filter wework lint
  • pnpm --filter wework test (174 files, 1727 tests)
  • cargo check --manifest-path wework/src-tauri/Cargo.toml
  • isolated real-Tauri verification of the picker, draft append, and settings page
  • pre-push ESLint, TypeScript, and unit-test checks

Summary by CodeRabbit

  • New Features
    • Added Quick Phrases across chat composers, with inline menu support for inserting saved snippets (Normal/Plan/Goal) via mouse and keyboard.
    • Introduced a Quick Phrases settings page (desktop + mobile) to add, edit, delete, and reorder phrases, and select their mode.
    • Quick Phrases are saved locally, available offline, and not synced across devices.
  • Documentation
    • Updated English and Chinese user guides with “Use Quick Phrases” instructions.
  • Tests
    • Added UI tests for Quick Phrase selection and Quick Phrases management.

@coderabbitai

coderabbitai Bot commented Jul 16, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6e81e5b8-f858-4770-84e3-68c3ae5e3dce

📥 Commits

Reviewing files that changed from the base of the PR and between 76b3c18 and f3978b6.

📒 Files selected for processing (6)
  • wework/src/components/chat/composer/QuickPhraseMenu.tsx
  • wework/src/components/settings/QuickPhrasesSettingsPage.tsx
  • wework/src/hooks/useQuickPhrases.ts
  • wework/src/i18n/locales/en/common.json
  • wework/src/i18n/locales/zh-CN/common.json
  • wework/src/tauri/appPreferences.ts

📝 Walkthrough

Walkthrough

Quick phrases are added as persisted preferences with defaults and validation, exposed through searchable composer menus, and managed in desktop and mobile settings. English and Chinese documentation describe selection, modes, local storage, and offline behavior.

Changes

Quick phrases

Layer / File(s) Summary
Phrase preferences and synchronization
wework/src/tauri/appPreferences.ts, wework/src-tauri/src/lib.rs, wework/src/hooks/useQuickPhrases.ts, wework/src/tauri/appPreferences.test.ts
Adds quick phrase types, defaults, validation, persistence, preference updates, and change-event synchronization.
Composer quick phrase insertion
wework/src/components/chat/composer/QuickPhraseMenu.tsx, wework/src/components/chat/composer/*Composer.tsx, wework/src/components/chat/composer/ComposerToolbar.tsx, wework/src/components/chat/composer/QuickPhraseMenu.test.tsx
Adds searchable mouse and keyboard phrase selection, then inserts content and applies the selected mode in composers.
Quick phrase settings management
wework/src/components/settings/QuickPhrasesSettingsPage.tsx, wework/src/components/settings/*SettingsPage.tsx, wework/src/i18n/locales/*/common.json, wework/src/components/settings/QuickPhrasesSettingsPage.test.tsx
Adds desktop and mobile settings navigation plus create, edit, delete, reorder, validation, persistence, and localized UI text.
Quick phrase documentation
docs/en/user-guide/coding/git-workspace-projects.md, docs/zh/user-guide/coding/git-workspace-projects.md
Documents quick phrase usage, management, modes, and local offline storage.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant QuickPhraseMenu
  participant ComposerToolbar
  participant Composer
  participant AppPreferences
  User->>QuickPhraseMenu: Search and select phrase
  QuickPhraseMenu->>ComposerToolbar: Forward selected phrase
  ComposerToolbar->>Composer: Insert content and apply mode
  Composer->>AppPreferences: Load persisted phrases
  AppPreferences-->>QuickPhraseMenu: Return phrase list
Loading

Suggested reviewers: icycrystal4

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 35.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding quick phrases to Wework.
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
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/wework-quick-phrases

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.

@qdaxb
qdaxb marked this pull request as ready for review July 16, 2026 18:05

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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)
wework/src/hooks/useQuickPhrases.ts (1)

13-26: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low value

Prevent stale data from overwriting newer event updates.

If an APP_PREFERENCES_CHANGED_EVENT is dispatched while the initial getAppPreferences() promise is still pending, the event handler updates the state with the newer data, but the promise resolution will subsequently overwrite it with the stale initial data. Tracking whether an event was received prevents this race condition.

♻️ Proposed refactor
   useEffect(() => {
     let active = true
+    let hasReceivedEvent = false
     void getAppPreferences().then(preferences => {
-      if (active) setPhrases(preferences.quickPhrases)
+      if (active && !hasReceivedEvent) setPhrases(preferences.quickPhrases)
     })
     const handleChange = (event: Event) => {
+      hasReceivedEvent = true
       setPhrases((event as CustomEvent<AppPreferences>).detail.quickPhrases)
     }
     window.addEventListener(APP_PREFERENCES_CHANGED_EVENT, handleChange)
     return () => {
       active = false
       window.removeEventListener(APP_PREFERENCES_CHANGED_EVENT, handleChange)
     }
   }, [])
🤖 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 `@wework/src/hooks/useQuickPhrases.ts` around lines 13 - 26, Update the effect
in useQuickPhrases so the pending getAppPreferences resolution cannot overwrite
state after an APP_PREFERENCES_CHANGED_EVENT has delivered newer preferences.
Track whether the change handler has received an event, and only apply the
initial promise result when no event has been received; preserve the existing
listener cleanup and active-unmount guard.
wework/src/components/chat/composer/QuickPhraseMenu.tsx (1)

30-38: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Improve keyboard navigation and manage button UX.

Consider adding auto-scrolling so the selected item is always visible when navigating the phrase list via ArrowUp/ArrowDown. Additionally, explicitly close the menu when clicking the "Manage quick phrases..." button, in case the composer remains mounted during navigation.

♻️ Proposed UX improvements

Update the useEffect block to add auto-scrolling, and update the manage button onClick:

   useEffect(() => {
     if (!open) return
     inputRef.current?.focus()
+
+    const selectedEl = rootRef.current?.querySelector('[aria-selected="true"]')
+    selectedEl?.scrollIntoView({ block: 'nearest' })
+
     const close = (event: PointerEvent) => {
       if (!rootRef.current?.contains(event.target as Node)) setOpen(false)
     }
     window.addEventListener('pointerdown', close)
     return () => window.removeEventListener('pointerdown', close)
-  }, [open])
+  }, [open, selectedIndex])

And for the manage button:

           <button
             type="button"
             data-testid="manage-quick-phrases-button"
-            onClick={() => navigateTo('/settings/personal/quick-phrases')}
+            onClick={() => {
+              setOpen(false)
+              navigateTo('/settings/personal/quick-phrases')
+            }}
             className="mt-1 flex h-8 w-full items-center gap-2 border-t border-border px-2 pt-1 text-sm text-text-secondary hover:text-text-primary"
           >

Also applies to: 133-133

🤖 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 `@wework/src/components/chat/composer/QuickPhraseMenu.tsx` around lines 30 -
38, Update the QuickPhraseMenu keyboard-navigation flow around the existing
useEffect so the currently selected phrase is automatically scrolled into view
after ArrowUp/ArrowDown changes selection. Also update the “Manage quick
phrases...” button handler to call setOpen(false) before navigation, ensuring
the menu closes even when the composer remains mounted.
wework/src/tauri/appPreferences.ts (1)

182-191: 🗄️ Data Integrity & Integration | 🔵 Trivial | 💤 Low value

Ensure runtime type safety for id.

Since value is unknown and you are defensively validating title and content, it is highly recommended to also validate that id is a string. If an external source provides a non-string truthy value for id (e.g., a number), it will bypass the truthiness check and violate the QuickPhrase interface contract.

♻️ Proposed refactor
 function normalizeQuickPhrase(value: unknown): QuickPhrase[] {
   if (!value || typeof value !== 'object') return []
   const record = value as Partial<QuickPhrase>
+  const id = typeof record.id === 'string' ? record.id : ''
   const title = typeof record.title === 'string' ? record.title.trim() : ''
   const content = typeof record.content === 'string' ? record.content.trim() : ''
   const mode = record.mode
-  if (!record.id || !title || !content || !['normal', 'plan', 'goal'].includes(mode ?? ''))
+  if (!id || !title || !content || !['normal', 'plan', 'goal'].includes(mode ?? ''))
     return []
-  return [{ id: record.id, title, content, mode: mode as QuickPhraseMode }]
+  return [{ id, title, content, mode: mode as QuickPhraseMode }]
 }
🤖 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 `@wework/src/tauri/appPreferences.ts` around lines 182 - 191, Update
normalizeQuickPhrase to validate record.id is a non-empty string before
constructing the QuickPhrase result, replacing the current truthiness-only check
while preserving the existing title, content, and mode validation.
🤖 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 `@wework/src/components/settings/QuickPhrasesSettingsPage.tsx`:
- Around line 110-115: Localize the Goal mode label in both the mode display
span and the radio button label, replacing the hardcoded text with the existing
useTranslation function t. Add the quick_phrase_mode_goal key with English and
zh-CN values to the corresponding common.json locale files.

---

Nitpick comments:
In `@wework/src/components/chat/composer/QuickPhraseMenu.tsx`:
- Around line 30-38: Update the QuickPhraseMenu keyboard-navigation flow around
the existing useEffect so the currently selected phrase is automatically
scrolled into view after ArrowUp/ArrowDown changes selection. Also update the
“Manage quick phrases...” button handler to call setOpen(false) before
navigation, ensuring the menu closes even when the composer remains mounted.

In `@wework/src/hooks/useQuickPhrases.ts`:
- Around line 13-26: Update the effect in useQuickPhrases so the pending
getAppPreferences resolution cannot overwrite state after an
APP_PREFERENCES_CHANGED_EVENT has delivered newer preferences. Track whether the
change handler has received an event, and only apply the initial promise result
when no event has been received; preserve the existing listener cleanup and
active-unmount guard.

In `@wework/src/tauri/appPreferences.ts`:
- Around line 182-191: Update normalizeQuickPhrase to validate record.id is a
non-empty string before constructing the QuickPhrase result, replacing the
current truthiness-only check while preserving the existing title, content, and
mode validation.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2ebafce1-201d-4548-9981-8437b3d0f558

📥 Commits

Reviewing files that changed from the base of the PR and between c7ea373 and 76b3c18.

📒 Files selected for processing (17)
  • docs/en/user-guide/coding/git-workspace-projects.md
  • docs/zh/user-guide/coding/git-workspace-projects.md
  • wework/src-tauri/src/lib.rs
  • wework/src/components/chat/composer/CompactChatComposer.tsx
  • wework/src/components/chat/composer/ComposerToolbar.tsx
  • wework/src/components/chat/composer/ProjectChatComposer.tsx
  • wework/src/components/chat/composer/QuickPhraseMenu.test.tsx
  • wework/src/components/chat/composer/QuickPhraseMenu.tsx
  • wework/src/components/settings/ConnectionsSettingsPage.tsx
  • wework/src/components/settings/MobileSettingsPage.tsx
  • wework/src/components/settings/QuickPhrasesSettingsPage.test.tsx
  • wework/src/components/settings/QuickPhrasesSettingsPage.tsx
  • wework/src/hooks/useQuickPhrases.ts
  • wework/src/i18n/locales/en/common.json
  • wework/src/i18n/locales/zh-CN/common.json
  • wework/src/tauri/appPreferences.test.ts
  • wework/src/tauri/appPreferences.ts

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