feat: add 1-click copy to text translation#605
Conversation
📝 WalkthroughWalkthroughA new ChangesIcon Glyph and TextTranslator Copy Button
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related issues
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/pages/popup/tabs/TextTranslator/TextTranslator.tsx (1)
480-484: 💤 Low valueConsider handling clipboard API errors.
navigator.clipboard.writeText()returns a Promise that can reject (e.g., due to permissions). While unlikely in an extension popup, adding a.catch()would improve robustness.Example with error handling
onPress={() => { - if (resultText !== null) { - navigator.clipboard.writeText(resultText); + if (translation !== null) { + navigator.clipboard.writeText(translation.text).catch(() => { + // Optionally show error feedback to user + }); } }}🤖 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 `@src/pages/popup/tabs/TextTranslator/TextTranslator.tsx` around lines 480 - 484, The onPress handler currently calls navigator.clipboard.writeText(resultText) without handling rejections; update the onPress in TextTranslator (the inline handler that checks resultText !== null) to await or chain a .then/.catch on navigator.clipboard.writeText(resultText) and handle errors (e.g., show a user-facing toast/alert or log via console/processLogger) so permission or runtime failures are caught and reported; ensure you still guard for resultText null before calling writeText and keep the handler idempotent for multiple presses.
🤖 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 `@src/pages/popup/tabs/TextTranslator/TextTranslator.tsx`:
- Around line 478-490: The copy Button currently only disables when translation
or resultText are null, which still allows copying the placeholder ('...') or an
error string; update the Button's disabled condition to also check the
inTranslateProcess flag and errorMessage state (e.g., disabled={translation ===
null || resultText === null || inTranslateProcess || !!errorMessage}) and
tighten the onPress guard to only call navigator.clipboard.writeText(resultText)
when resultText is a valid completed translation (not the placeholder), e.g.,
ensure resultText !== '...' and errorMessage is falsy before copying; modify
references around the Button, navigator.clipboard.writeText, and the
translation/resultText state to implement this change.
---
Nitpick comments:
In `@src/pages/popup/tabs/TextTranslator/TextTranslator.tsx`:
- Around line 480-484: The onPress handler currently calls
navigator.clipboard.writeText(resultText) without handling rejections; update
the onPress in TextTranslator (the inline handler that checks resultText !==
null) to await or chain a .then/.catch on
navigator.clipboard.writeText(resultText) and handle errors (e.g., show a
user-facing toast/alert or log via console/processLogger) so permission or
runtime failures are caught and reported; ensure you still guard for resultText
null before calling writeText and keep the handler idempotent for multiple
presses.
🪄 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 Plus
Run ID: ef0bb297-edc8-4497-96dd-10b4b5686141
⛔ Files ignored due to path filters (17)
.DS_Storeis excluded by!**/.DS_Store.github/.DS_Storeis excluded by!**/.DS_Storedocs/.DS_Storeis excluded by!**/.DS_Storepackages/.DS_Storeis excluded by!**/.DS_Storesrc/.DS_Storeis excluded by!**/.DS_Storesrc/components/.DS_Storeis excluded by!**/.DS_Storesrc/components/primitives/.DS_Storeis excluded by!**/.DS_Storesrc/components/primitives/Button/.DS_Storeis excluded by!**/.DS_Storesrc/components/primitives/Icon/.DS_Storeis excluded by!**/.DS_Storesrc/components/primitives/Icon/Icon.assets/.DS_Storeis excluded by!**/.DS_Storesrc/components/primitives/Icon/Icon.assets/Material/.DS_Storeis excluded by!**/.DS_Storesrc/components/primitives/Icon/Icon.assets/Material/content_copy.svgis excluded by!**/*.svgsrc/components/primitives/Modal/.DS_Storeis excluded by!**/.DS_Storesrc/components/primitives/Notification/.DS_Storeis excluded by!**/.DS_Storethirdparty/.DS_Storeis excluded by!**/.DS_Storethirdparty/bergamot/.DS_Storeis excluded by!**/.DS_Storethirdparty/bergamot/src/.DS_Storeis excluded by!**/.DS_Store
📒 Files selected for processing (3)
src/components/primitives/Icon/Icon.bundle/desktop.tssrc/components/primitives/Icon/_glyph/Icon_glyph_content-copy.tsxsrc/pages/popup/tabs/TextTranslator/TextTranslator.tsx
| <Button | ||
| disabled={translation === null || resultText === null} | ||
| onPress={() => { | ||
| if (resultText !== null) { | ||
| navigator.clipboard.writeText(resultText); | ||
| } | ||
| }} | ||
| view="clear" | ||
| size="s" | ||
| title={getMessage('common_copy')} | ||
| > | ||
| <Icon glyph="content-copy" scalable={false} /> | ||
| </Button> |
There was a problem hiding this comment.
Copy button can copy placeholder or error text.
The disabled condition translation === null || resultText === null allows copying when resultText is '...' (during translation) or an error message. If the user had a previous successful translation and then triggers a new one or encounters an error, the button remains enabled with undesirable content.
Consider adding inTranslateProcess and errorMessage to the disabled condition:
Proposed fix
<Button
- disabled={translation === null || resultText === null}
+ disabled={translation === null || inTranslateProcess || errorMessage !== null}
onPress={() => {
- if (resultText !== null) {
- navigator.clipboard.writeText(resultText);
+ if (translation !== null) {
+ navigator.clipboard.writeText(translation.text);
}
}}
view="clear"
size="s"
title={getMessage('common_copy')}
>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <Button | |
| disabled={translation === null || resultText === null} | |
| onPress={() => { | |
| if (resultText !== null) { | |
| navigator.clipboard.writeText(resultText); | |
| } | |
| }} | |
| view="clear" | |
| size="s" | |
| title={getMessage('common_copy')} | |
| > | |
| <Icon glyph="content-copy" scalable={false} /> | |
| </Button> | |
| <Button | |
| disabled={translation === null || inTranslateProcess || errorMessage !== null} | |
| onPress={() => { | |
| if (translation !== null) { | |
| navigator.clipboard.writeText(translation.text); | |
| } | |
| }} | |
| view="clear" | |
| size="s" | |
| title={getMessage('common_copy')} | |
| > | |
| <Icon glyph="content-copy" scalable={false} /> | |
| </Button> |
🤖 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 `@src/pages/popup/tabs/TextTranslator/TextTranslator.tsx` around lines 478 -
490, The copy Button currently only disables when translation or resultText are
null, which still allows copying the placeholder ('...') or an error string;
update the Button's disabled condition to also check the inTranslateProcess flag
and errorMessage state (e.g., disabled={translation === null || resultText ===
null || inTranslateProcess || !!errorMessage}) and tighten the onPress guard to
only call navigator.clipboard.writeText(resultText) when resultText is a valid
completed translation (not the placeholder), e.g., ensure resultText !== '...'
and errorMessage is falsy before copying; modify references around the Button,
navigator.clipboard.writeText, and the translation/resultText state to implement
this change.
There was a problem hiding this comment.
Please delete all irrelevant files
| disabled={translation === null || resultText === null} | ||
| onPress={() => { | ||
| if (resultText !== null) { | ||
| navigator.clipboard.writeText(resultText); |
There was a problem hiding this comment.
As @CodeRabbit said, we should only copy text in translation
There was a problem hiding this comment.
@vitonsky, agreed. The current code copies resultText, which can be '...' (while a new translation is in progress but a previous translation still exists) or an error string like [error message] — neither should be copied to the clipboard.
The fix is to copy translation.text directly and tighten the disabled condition:
<Button
disabled={translation === null}
onPress={() => {
if (translation !== null) {
navigator.clipboard.writeText(translation.text);
}
}}
view="clear"
size="s"
title={getMessage('common_copy')}
>
<Icon glyph="content-copy" scalable={false} />
</Button>This ensures:
- Only the actual translated text is ever copied.
- The button is disabled whenever there is no valid translation object, regardless of
resultTextstate.
Closes #601
Feature request: Add a 1-click translation button to the 'Text Translation' section of the project.
Currently, if a user is translating text in the 'Text Translation' feature, they must manually highlight and copy text before they are able to use it. This is inefficient and can be sped up.
This 1-click copy button saves the user about 1-2 seconds per text copy, which compounds heavily over time.
Summary by CodeRabbit