Skip to content

feat: add clipboard paste shortcut with Stellar address validation to… - #36

Open
avatGit wants to merge 1 commit into
MJ-RWA:mainfrom
avatGit:feature/address-paste-button
Open

feat: add clipboard paste shortcut with Stellar address validation to…#36
avatGit wants to merge 1 commit into
MJ-RWA:mainfrom
avatGit:feature/address-paste-button

Conversation

@avatGit

@avatGitavatGit commented Jun 22, 2026

Copy link
Copy Markdown

Summary

Addresses the issue where mobile users have to manually type or paste Stellar public keys. This PR adds a reusable AddressInput component with a paste icon button next to destination fields, significantly improving mobile UX.

Changes

  • Create: src/components/AddressInput.tsx (handles clipboard access and validation)
  • Modify: src/pages/SendPage.tsx & src/pages/SchedulePage.tsx (replaced old input fields)

Key Features

  • Uses navigator.clipboard.readText() to auto-fill the field.
  • Validates the pasted key using StellarSdk.StrKey.isValidEd25519PublicKey().
  • Shows clear error/success feedback using react-hot-toast.

Closes#3
Recording 2026-06-23 011729

Summary by CodeRabbit

  • New Features
    • Introduced an improved address input component featuring an integrated paste button, making Stellar address entry simpler and more convenient across Schedule and Send pages.
    • Real-time validation ensures only valid Stellar addresses are accepted, providing clear error notifications for invalid entries, empty clipboard, or permission issues.

@avatGit
avatGit requested a review from MJ-RWA as a code ownerJune 22, 2026 23:19
@vercel

vercelBot commented Jun 22, 2026

Copy link
Copy Markdown

@avatGit is attempting to deploy a commit to the MJ X Dev's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitaiBot commented Jun 22, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

A new reusable AddressInput React component is added with a clipboard paste button. It validates clipboard content as a Stellar Ed25519 public key using StellarSdk and reports outcomes via react-hot-toast. SendPage and SchedulePage replace their plain destination <input> elements with this component.

Changes

AddressInput Component and Integration

Layer / File(s)Summary
AddressInput component definition
apps/src/components/AddressInput.tsx
Defines AddressInputProps (value, onChange, placeholder, className), an async paste handler that checks clipboard availability, reads and trims text, validates it via StellarSdk.StrKey.isValidEd25519PublicKey, calls onChange on success, and reports all outcomes (clipboard unavailable, empty, invalid address, permission error) via react-hot-toast. Renders a text input with an absolutely-positioned paste icon button.
SendPage and SchedulePage integration
apps/src/pages/SendPage.tsx, apps/src/pages/SchedulePage.tsx
Imports AddressInput in both pages and replaces the plain destination <input> elements with the new component, passing value, onChange (bound to setDestination), placeholder, and monospace className props.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 Hop, hop! No more typing keys by paw,
A paste button lands with clipboard's draw.
G... addresses fill with a click,
Invalid ones get a toast — real quick!
The bunny cheers: smooth sends, no trick. 🌟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 0.00% 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 nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title accurately summarizes the main change: adding clipboard paste functionality with Stellar address validation to address input components.
Linked Issues check✅ PassedAll core requirements from issue #3 are met: AddressInput component created with clipboard paste button, integrated into SendPage and SchedulePage, validates via StellarSdk.StrKey.isValidEd25519PublicKey, and provides toast feedback.
Out of Scope Changes check✅ PassedAll changes are directly scoped to the linked issue: new AddressInput component creation and integration into two destination address fields as specified.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (4)
apps/src/pages/SchedulePage.tsx (1)

108-114: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Minor formatting inconsistencies.

Line 113 has trailing whitespace after />, and line 114 has leading whitespace before </div>. While these don't affect functionality, they create inconsistent formatting.

♻️ Formatting cleanup
 <AddressInput value={destination} onChange={setDestination} placeholder="G..."
className="font-mono text-sm"
- /> - </div>+ />+ </div>
🤖 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 `@apps/src/pages/SchedulePage.tsx` around lines 108 - 114, Remove the trailing
whitespace after the AddressInput component's closing tag `/>` on line 113, and
remove the excessive leading whitespace before the closing `</div>` tag on line
114 to ensure consistent formatting and proper indentation alignment with the
rest of the component.
apps/src/components/AddressInput.tsx (3)

44-44: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove empty comment.

The empty comment on line 44 serves no purpose and reduces code clarity.

♻️ Suggested cleanup
 } catch (error) {
- //
toast.error("Clipboard access permission denied");
🤖 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 `@apps/src/components/AddressInput.tsx` at line 44, Remove the empty comment
line in the AddressInput.tsx component at line 44. The standalone comment marker
"//" with no text following it provides no value and should be deleted entirely
to improve code clarity and cleanliness.

51-67: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

The className prop is applied to the wrapper div, not the input element.

The className prop passed from parent components (e.g., "font-mono text-sm" in SendPage and SchedulePage) is applied to the outer wrapper <div> on line 51, not to the <input> element on line 52, which has its own fixed className. This means font and text styling passed via className won't affect the input's appearance as might be expected.

If the intent is to allow parent components to style the input element, consider either:

  1. Accepting separate wrapperClassName and inputClassName props
  2. Applying the className prop to the input element instead
  3. Documenting that className styles the wrapper
🤖 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 `@apps/src/components/AddressInput.tsx` around lines 51 - 67, The AddressInput
component applies the className prop to the outer wrapper div instead of the
input element, which prevents parent components from styling the input itself
(e.g., font-mono, text-sm won't affect the input's appearance). Move the
className prop from the wrapper div to the input element on line 52, or
alternatively refactor the component to accept separate wrapperClassName and
inputClassName props to give parents control over styling both the wrapper and
the input element independently.

43-47: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Error message may be misleading for non-permission failures.

The catch block assumes all errors from navigator.clipboard.readText() are permission denials, but the API can fail for other reasons (e.g., the page is not in a secure context despite navigator.clipboard existing, or other runtime errors). While the actual error is logged to console, the toast message might confuse users in edge cases.

♻️ Optional improvement for error clarity
 } catch (error) {
- toast.error("Clipboard access permission denied");+ toast.error("Unable to access clipboard");
console.error("Clipboard Error: ", error);
🤖 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 `@apps/src/components/AddressInput.tsx` around lines 43 - 47, The catch block
for navigator.clipboard.readText() assumes all errors are permission denials and
displays a misleading toast message. Instead of showing a generic permission
error, inspect the caught error object to determine the actual cause (permission
error, insecure context, or other runtime errors) and display an appropriate
toast message using toast.error() based on the specific error condition. This
ensures users see an accurate error message for their particular failure
scenario.
🤖 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.
Nitpick comments:
In `@apps/src/components/AddressInput.tsx`:
- Line 44: Remove the empty comment line in the AddressInput.tsx component at
line 44. The standalone comment marker "//" with no text following it provides
no value and should be deleted entirely to improve code clarity and cleanliness.
- Around line 51-67: The AddressInput component applies the className prop to
the outer wrapper div instead of the input element, which prevents parent
components from styling the input itself (e.g., font-mono, text-sm won't affect
the input's appearance). Move the className prop from the wrapper div to the
input element on line 52, or alternatively refactor the component to accept
separate wrapperClassName and inputClassName props to give parents control over
styling both the wrapper and the input element independently.
- Around line 43-47: The catch block for navigator.clipboard.readText() assumes
all errors are permission denials and displays a misleading toast message.
Instead of showing a generic permission error, inspect the caught error object
to determine the actual cause (permission error, insecure context, or other
runtime errors) and display an appropriate toast message using toast.error()
based on the specific error condition. This ensures users see an accurate error
message for their particular failure scenario.
In `@apps/src/pages/SchedulePage.tsx`:
- Around line 108-114: Remove the trailing whitespace after the AddressInput
component's closing tag `/>` on line 113, and remove the excessive leading
whitespace before the closing `</div>` tag on line 114 to ensure consistent
formatting and proper indentation alignment with the rest of the component.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 40bb9572-a28f-4421-a00e-8888b94b9ea9

📥 Commits

Reviewing files that changed from the base of the PR and between 867ba1e and c36170a.

📒 Files selected for processing (3)
  • apps/src/components/AddressInput.tsx
  • apps/src/pages/SchedulePage.tsx
  • apps/src/pages/SendPage.tsx

Sign up for freeto 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.

Issue #1 — Add clipboard paste button on address input fields

1 participant

@avatGit
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
feat: add clipboard paste shortcut with Stellar address validation to… by avatGit · Pull Request #36 · MJ-RWA/Stellarflow · GitHub
Skip to content

feat: add clipboard paste shortcut with Stellar address validation to… - #36

Open
avatGit wants to merge 1 commit into
MJ-RWA:mainfrom
avatGit:feature/address-paste-button
Open

feat: add clipboard paste shortcut with Stellar address validation to…#36
avatGit wants to merge 1 commit into
MJ-RWA:mainfrom
avatGit:feature/address-paste-button

Conversation

@avatGit

@avatGitavatGit commented Jun 22, 2026

Copy link
Copy Markdown

Summary

Addresses the issue where mobile users have to manually type or paste Stellar public keys. This PR adds a reusable AddressInput component with a paste icon button next to destination fields, significantly improving mobile UX.

Changes

  • Create: src/components/AddressInput.tsx (handles clipboard access and validation)
  • Modify: src/pages/SendPage.tsx & src/pages/SchedulePage.tsx (replaced old input fields)

Key Features

  • Uses navigator.clipboard.readText() to auto-fill the field.
  • Validates the pasted key using StellarSdk.StrKey.isValidEd25519PublicKey().
  • Shows clear error/success feedback using react-hot-toast.

Closes#3
Recording 2026-06-23 011729

Summary by CodeRabbit

  • New Features
    • Introduced an improved address input component featuring an integrated paste button, making Stellar address entry simpler and more convenient across Schedule and Send pages.
    • Real-time validation ensures only valid Stellar addresses are accepted, providing clear error notifications for invalid entries, empty clipboard, or permission issues.

@avatGit
avatGit requested a review from MJ-RWA as a code ownerJune 22, 2026 23:19
@vercel

vercelBot commented Jun 22, 2026

Copy link
Copy Markdown

@avatGit is attempting to deploy a commit to the MJ X Dev's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitaiBot commented Jun 22, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

A new reusable AddressInput React component is added with a clipboard paste button. It validates clipboard content as a Stellar Ed25519 public key using StellarSdk and reports outcomes via react-hot-toast. SendPage and SchedulePage replace their plain destination <input> elements with this component.

Changes

AddressInput Component and Integration

Layer / File(s)Summary
AddressInput component definition
apps/src/components/AddressInput.tsx
Defines AddressInputProps (value, onChange, placeholder, className), an async paste handler that checks clipboard availability, reads and trims text, validates it via StellarSdk.StrKey.isValidEd25519PublicKey, calls onChange on success, and reports all outcomes (clipboard unavailable, empty, invalid address, permission error) via react-hot-toast. Renders a text input with an absolutely-positioned paste icon button.
SendPage and SchedulePage integration
apps/src/pages/SendPage.tsx, apps/src/pages/SchedulePage.tsx
Imports AddressInput in both pages and replaces the plain destination <input> elements with the new component, passing value, onChange (bound to setDestination), placeholder, and monospace className props.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 Hop, hop! No more typing keys by paw,
A paste button lands with clipboard's draw.
G... addresses fill with a click,
Invalid ones get a toast — real quick!
The bunny cheers: smooth sends, no trick. 🌟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 0.00% 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 nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title accurately summarizes the main change: adding clipboard paste functionality with Stellar address validation to address input components.
Linked Issues check✅ PassedAll core requirements from issue #3 are met: AddressInput component created with clipboard paste button, integrated into SendPage and SchedulePage, validates via StellarSdk.StrKey.isValidEd25519PublicKey, and provides toast feedback.
Out of Scope Changes check✅ PassedAll changes are directly scoped to the linked issue: new AddressInput component creation and integration into two destination address fields as specified.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (4)
apps/src/pages/SchedulePage.tsx (1)

108-114: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Minor formatting inconsistencies.

Line 113 has trailing whitespace after />, and line 114 has leading whitespace before </div>. While these don't affect functionality, they create inconsistent formatting.

♻️ Formatting cleanup
 <AddressInput value={destination} onChange={setDestination} placeholder="G..."
className="font-mono text-sm"
- /> - </div>+ />+ </div>
🤖 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 `@apps/src/pages/SchedulePage.tsx` around lines 108 - 114, Remove the trailing
whitespace after the AddressInput component's closing tag `/>` on line 113, and
remove the excessive leading whitespace before the closing `</div>` tag on line
114 to ensure consistent formatting and proper indentation alignment with the
rest of the component.
apps/src/components/AddressInput.tsx (3)

44-44: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove empty comment.

The empty comment on line 44 serves no purpose and reduces code clarity.

♻️ Suggested cleanup
 } catch (error) {
- //
toast.error("Clipboard access permission denied");
🤖 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 `@apps/src/components/AddressInput.tsx` at line 44, Remove the empty comment
line in the AddressInput.tsx component at line 44. The standalone comment marker
"//" with no text following it provides no value and should be deleted entirely
to improve code clarity and cleanliness.

51-67: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

The className prop is applied to the wrapper div, not the input element.

The className prop passed from parent components (e.g., "font-mono text-sm" in SendPage and SchedulePage) is applied to the outer wrapper <div> on line 51, not to the <input> element on line 52, which has its own fixed className. This means font and text styling passed via className won't affect the input's appearance as might be expected.

If the intent is to allow parent components to style the input element, consider either:

  1. Accepting separate wrapperClassName and inputClassName props
  2. Applying the className prop to the input element instead
  3. Documenting that className styles the wrapper
🤖 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 `@apps/src/components/AddressInput.tsx` around lines 51 - 67, The AddressInput
component applies the className prop to the outer wrapper div instead of the
input element, which prevents parent components from styling the input itself
(e.g., font-mono, text-sm won't affect the input's appearance). Move the
className prop from the wrapper div to the input element on line 52, or
alternatively refactor the component to accept separate wrapperClassName and
inputClassName props to give parents control over styling both the wrapper and
the input element independently.

43-47: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Error message may be misleading for non-permission failures.

The catch block assumes all errors from navigator.clipboard.readText() are permission denials, but the API can fail for other reasons (e.g., the page is not in a secure context despite navigator.clipboard existing, or other runtime errors). While the actual error is logged to console, the toast message might confuse users in edge cases.

♻️ Optional improvement for error clarity
 } catch (error) {
- toast.error("Clipboard access permission denied");+ toast.error("Unable to access clipboard");
console.error("Clipboard Error: ", error);
🤖 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 `@apps/src/components/AddressInput.tsx` around lines 43 - 47, The catch block
for navigator.clipboard.readText() assumes all errors are permission denials and
displays a misleading toast message. Instead of showing a generic permission
error, inspect the caught error object to determine the actual cause (permission
error, insecure context, or other runtime errors) and display an appropriate
toast message using toast.error() based on the specific error condition. This
ensures users see an accurate error message for their particular failure
scenario.
🤖 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.
Nitpick comments:
In `@apps/src/components/AddressInput.tsx`:
- Line 44: Remove the empty comment line in the AddressInput.tsx component at
line 44. The standalone comment marker "//" with no text following it provides
no value and should be deleted entirely to improve code clarity and cleanliness.
- Around line 51-67: The AddressInput component applies the className prop to
the outer wrapper div instead of the input element, which prevents parent
components from styling the input itself (e.g., font-mono, text-sm won't affect
the input's appearance). Move the className prop from the wrapper div to the
input element on line 52, or alternatively refactor the component to accept
separate wrapperClassName and inputClassName props to give parents control over
styling both the wrapper and the input element independently.
- Around line 43-47: The catch block for navigator.clipboard.readText() assumes
all errors are permission denials and displays a misleading toast message.
Instead of showing a generic permission error, inspect the caught error object
to determine the actual cause (permission error, insecure context, or other
runtime errors) and display an appropriate toast message using toast.error()
based on the specific error condition. This ensures users see an accurate error
message for their particular failure scenario.
In `@apps/src/pages/SchedulePage.tsx`:
- Around line 108-114: Remove the trailing whitespace after the AddressInput
component's closing tag `/>` on line 113, and remove the excessive leading
whitespace before the closing `</div>` tag on line 114 to ensure consistent
formatting and proper indentation alignment with the rest of the component.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 40bb9572-a28f-4421-a00e-8888b94b9ea9

📥 Commits

Reviewing files that changed from the base of the PR and between 867ba1e and c36170a.

📒 Files selected for processing (3)
  • apps/src/components/AddressInput.tsx
  • apps/src/pages/SchedulePage.tsx
  • apps/src/pages/SendPage.tsx

Sign up for freeto 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.

Issue #1 — Add clipboard paste button on address input fields

1 participant

@avatGit
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' feat: add clipboard paste shortcut with Stellar address validation to… by avatGit · Pull Request #36 · MJ-RWA/Stellarflow · GitHub
Skip to content

feat: add clipboard paste shortcut with Stellar address validation to… - #36

Open
avatGit wants to merge 1 commit into
MJ-RWA:mainfrom
avatGit:feature/address-paste-button
Open

feat: add clipboard paste shortcut with Stellar address validation to…#36
avatGit wants to merge 1 commit into
MJ-RWA:mainfrom
avatGit:feature/address-paste-button

Conversation

@avatGit

@avatGitavatGit commented Jun 22, 2026

Copy link
Copy Markdown

Summary

Addresses the issue where mobile users have to manually type or paste Stellar public keys. This PR adds a reusable AddressInput component with a paste icon button next to destination fields, significantly improving mobile UX.

Changes

  • Create: src/components/AddressInput.tsx (handles clipboard access and validation)
  • Modify: src/pages/SendPage.tsx & src/pages/SchedulePage.tsx (replaced old input fields)

Key Features

  • Uses navigator.clipboard.readText() to auto-fill the field.
  • Validates the pasted key using StellarSdk.StrKey.isValidEd25519PublicKey().
  • Shows clear error/success feedback using react-hot-toast.

Closes#3
Recording 2026-06-23 011729

Summary by CodeRabbit

  • New Features
    • Introduced an improved address input component featuring an integrated paste button, making Stellar address entry simpler and more convenient across Schedule and Send pages.
    • Real-time validation ensures only valid Stellar addresses are accepted, providing clear error notifications for invalid entries, empty clipboard, or permission issues.

@avatGit
avatGit requested a review from MJ-RWA as a code ownerJune 22, 2026 23:19
@vercel

vercelBot commented Jun 22, 2026

Copy link
Copy Markdown

@avatGit is attempting to deploy a commit to the MJ X Dev's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitaiBot commented Jun 22, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

A new reusable AddressInput React component is added with a clipboard paste button. It validates clipboard content as a Stellar Ed25519 public key using StellarSdk and reports outcomes via react-hot-toast. SendPage and SchedulePage replace their plain destination <input> elements with this component.

Changes

AddressInput Component and Integration

Layer / File(s)Summary
AddressInput component definition
apps/src/components/AddressInput.tsx
Defines AddressInputProps (value, onChange, placeholder, className), an async paste handler that checks clipboard availability, reads and trims text, validates it via StellarSdk.StrKey.isValidEd25519PublicKey, calls onChange on success, and reports all outcomes (clipboard unavailable, empty, invalid address, permission error) via react-hot-toast. Renders a text input with an absolutely-positioned paste icon button.
SendPage and SchedulePage integration
apps/src/pages/SendPage.tsx, apps/src/pages/SchedulePage.tsx
Imports AddressInput in both pages and replaces the plain destination <input> elements with the new component, passing value, onChange (bound to setDestination), placeholder, and monospace className props.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 Hop, hop! No more typing keys by paw,
A paste button lands with clipboard's draw.
G... addresses fill with a click,
Invalid ones get a toast — real quick!
The bunny cheers: smooth sends, no trick. 🌟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 0.00% 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 nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title accurately summarizes the main change: adding clipboard paste functionality with Stellar address validation to address input components.
Linked Issues check✅ PassedAll core requirements from issue #3 are met: AddressInput component created with clipboard paste button, integrated into SendPage and SchedulePage, validates via StellarSdk.StrKey.isValidEd25519PublicKey, and provides toast feedback.
Out of Scope Changes check✅ PassedAll changes are directly scoped to the linked issue: new AddressInput component creation and integration into two destination address fields as specified.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (4)
apps/src/pages/SchedulePage.tsx (1)

108-114: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Minor formatting inconsistencies.

Line 113 has trailing whitespace after />, and line 114 has leading whitespace before </div>. While these don't affect functionality, they create inconsistent formatting.

♻️ Formatting cleanup
 <AddressInput value={destination} onChange={setDestination} placeholder="G..."
className="font-mono text-sm"
- /> - </div>+ />+ </div>
🤖 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 `@apps/src/pages/SchedulePage.tsx` around lines 108 - 114, Remove the trailing
whitespace after the AddressInput component's closing tag `/>` on line 113, and
remove the excessive leading whitespace before the closing `</div>` tag on line
114 to ensure consistent formatting and proper indentation alignment with the
rest of the component.
apps/src/components/AddressInput.tsx (3)

44-44: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove empty comment.

The empty comment on line 44 serves no purpose and reduces code clarity.

♻️ Suggested cleanup
 } catch (error) {
- //
toast.error("Clipboard access permission denied");
🤖 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 `@apps/src/components/AddressInput.tsx` at line 44, Remove the empty comment
line in the AddressInput.tsx component at line 44. The standalone comment marker
"//" with no text following it provides no value and should be deleted entirely
to improve code clarity and cleanliness.

51-67: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

The className prop is applied to the wrapper div, not the input element.

The className prop passed from parent components (e.g., "font-mono text-sm" in SendPage and SchedulePage) is applied to the outer wrapper <div> on line 51, not to the <input> element on line 52, which has its own fixed className. This means font and text styling passed via className won't affect the input's appearance as might be expected.

If the intent is to allow parent components to style the input element, consider either:

  1. Accepting separate wrapperClassName and inputClassName props
  2. Applying the className prop to the input element instead
  3. Documenting that className styles the wrapper
🤖 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 `@apps/src/components/AddressInput.tsx` around lines 51 - 67, The AddressInput
component applies the className prop to the outer wrapper div instead of the
input element, which prevents parent components from styling the input itself
(e.g., font-mono, text-sm won't affect the input's appearance). Move the
className prop from the wrapper div to the input element on line 52, or
alternatively refactor the component to accept separate wrapperClassName and
inputClassName props to give parents control over styling both the wrapper and
the input element independently.

43-47: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Error message may be misleading for non-permission failures.

The catch block assumes all errors from navigator.clipboard.readText() are permission denials, but the API can fail for other reasons (e.g., the page is not in a secure context despite navigator.clipboard existing, or other runtime errors). While the actual error is logged to console, the toast message might confuse users in edge cases.

♻️ Optional improvement for error clarity
 } catch (error) {
- toast.error("Clipboard access permission denied");+ toast.error("Unable to access clipboard");
console.error("Clipboard Error: ", error);
🤖 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 `@apps/src/components/AddressInput.tsx` around lines 43 - 47, The catch block
for navigator.clipboard.readText() assumes all errors are permission denials and
displays a misleading toast message. Instead of showing a generic permission
error, inspect the caught error object to determine the actual cause (permission
error, insecure context, or other runtime errors) and display an appropriate
toast message using toast.error() based on the specific error condition. This
ensures users see an accurate error message for their particular failure
scenario.
🤖 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.
Nitpick comments:
In `@apps/src/components/AddressInput.tsx`:
- Line 44: Remove the empty comment line in the AddressInput.tsx component at
line 44. The standalone comment marker "//" with no text following it provides
no value and should be deleted entirely to improve code clarity and cleanliness.
- Around line 51-67: The AddressInput component applies the className prop to
the outer wrapper div instead of the input element, which prevents parent
components from styling the input itself (e.g., font-mono, text-sm won't affect
the input's appearance). Move the className prop from the wrapper div to the
input element on line 52, or alternatively refactor the component to accept
separate wrapperClassName and inputClassName props to give parents control over
styling both the wrapper and the input element independently.
- Around line 43-47: The catch block for navigator.clipboard.readText() assumes
all errors are permission denials and displays a misleading toast message.
Instead of showing a generic permission error, inspect the caught error object
to determine the actual cause (permission error, insecure context, or other
runtime errors) and display an appropriate toast message using toast.error()
based on the specific error condition. This ensures users see an accurate error
message for their particular failure scenario.
In `@apps/src/pages/SchedulePage.tsx`:
- Around line 108-114: Remove the trailing whitespace after the AddressInput
component's closing tag `/>` on line 113, and remove the excessive leading
whitespace before the closing `</div>` tag on line 114 to ensure consistent
formatting and proper indentation alignment with the rest of the component.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 40bb9572-a28f-4421-a00e-8888b94b9ea9

📥 Commits

Reviewing files that changed from the base of the PR and between 867ba1e and c36170a.

📒 Files selected for processing (3)
  • apps/src/components/AddressInput.tsx
  • apps/src/pages/SchedulePage.tsx
  • apps/src/pages/SendPage.tsx

Sign up for freeto 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.

Issue #1 — Add clipboard paste button on address input fields

1 participant

@avatGit
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' feat: add clipboard paste shortcut with Stellar address validation to… by avatGit · Pull Request #36 · MJ-RWA/Stellarflow · GitHub
Skip to content

feat: add clipboard paste shortcut with Stellar address validation to… - #36

Open
avatGit wants to merge 1 commit into
MJ-RWA:mainfrom
avatGit:feature/address-paste-button
Open

feat: add clipboard paste shortcut with Stellar address validation to…#36
avatGit wants to merge 1 commit into
MJ-RWA:mainfrom
avatGit:feature/address-paste-button

Conversation

@avatGit

@avatGitavatGit commented Jun 22, 2026

Copy link
Copy Markdown

Summary

Addresses the issue where mobile users have to manually type or paste Stellar public keys. This PR adds a reusable AddressInput component with a paste icon button next to destination fields, significantly improving mobile UX.

Changes

  • Create: src/components/AddressInput.tsx (handles clipboard access and validation)
  • Modify: src/pages/SendPage.tsx & src/pages/SchedulePage.tsx (replaced old input fields)

Key Features

  • Uses navigator.clipboard.readText() to auto-fill the field.
  • Validates the pasted key using StellarSdk.StrKey.isValidEd25519PublicKey().
  • Shows clear error/success feedback using react-hot-toast.

Closes#3
Recording 2026-06-23 011729

Summary by CodeRabbit

  • New Features
    • Introduced an improved address input component featuring an integrated paste button, making Stellar address entry simpler and more convenient across Schedule and Send pages.
    • Real-time validation ensures only valid Stellar addresses are accepted, providing clear error notifications for invalid entries, empty clipboard, or permission issues.

@avatGit
avatGit requested a review from MJ-RWA as a code ownerJune 22, 2026 23:19
@vercel

vercelBot commented Jun 22, 2026

Copy link
Copy Markdown

@avatGit is attempting to deploy a commit to the MJ X Dev's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitaiBot commented Jun 22, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

A new reusable AddressInput React component is added with a clipboard paste button. It validates clipboard content as a Stellar Ed25519 public key using StellarSdk and reports outcomes via react-hot-toast. SendPage and SchedulePage replace their plain destination <input> elements with this component.

Changes

AddressInput Component and Integration

Layer / File(s)Summary
AddressInput component definition
apps/src/components/AddressInput.tsx
Defines AddressInputProps (value, onChange, placeholder, className), an async paste handler that checks clipboard availability, reads and trims text, validates it via StellarSdk.StrKey.isValidEd25519PublicKey, calls onChange on success, and reports all outcomes (clipboard unavailable, empty, invalid address, permission error) via react-hot-toast. Renders a text input with an absolutely-positioned paste icon button.
SendPage and SchedulePage integration
apps/src/pages/SendPage.tsx, apps/src/pages/SchedulePage.tsx
Imports AddressInput in both pages and replaces the plain destination <input> elements with the new component, passing value, onChange (bound to setDestination), placeholder, and monospace className props.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 Hop, hop! No more typing keys by paw,
A paste button lands with clipboard's draw.
G... addresses fill with a click,
Invalid ones get a toast — real quick!
The bunny cheers: smooth sends, no trick. 🌟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 0.00% 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 nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title accurately summarizes the main change: adding clipboard paste functionality with Stellar address validation to address input components.
Linked Issues check✅ PassedAll core requirements from issue #3 are met: AddressInput component created with clipboard paste button, integrated into SendPage and SchedulePage, validates via StellarSdk.StrKey.isValidEd25519PublicKey, and provides toast feedback.
Out of Scope Changes check✅ PassedAll changes are directly scoped to the linked issue: new AddressInput component creation and integration into two destination address fields as specified.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (4)
apps/src/pages/SchedulePage.tsx (1)

108-114: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Minor formatting inconsistencies.

Line 113 has trailing whitespace after />, and line 114 has leading whitespace before </div>. While these don't affect functionality, they create inconsistent formatting.

♻️ Formatting cleanup
 <AddressInput value={destination} onChange={setDestination} placeholder="G..."
className="font-mono text-sm"
- /> - </div>+ />+ </div>
🤖 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 `@apps/src/pages/SchedulePage.tsx` around lines 108 - 114, Remove the trailing
whitespace after the AddressInput component's closing tag `/>` on line 113, and
remove the excessive leading whitespace before the closing `</div>` tag on line
114 to ensure consistent formatting and proper indentation alignment with the
rest of the component.
apps/src/components/AddressInput.tsx (3)

44-44: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove empty comment.

The empty comment on line 44 serves no purpose and reduces code clarity.

♻️ Suggested cleanup
 } catch (error) {
- //
toast.error("Clipboard access permission denied");
🤖 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 `@apps/src/components/AddressInput.tsx` at line 44, Remove the empty comment
line in the AddressInput.tsx component at line 44. The standalone comment marker
"//" with no text following it provides no value and should be deleted entirely
to improve code clarity and cleanliness.

51-67: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

The className prop is applied to the wrapper div, not the input element.

The className prop passed from parent components (e.g., "font-mono text-sm" in SendPage and SchedulePage) is applied to the outer wrapper <div> on line 51, not to the <input> element on line 52, which has its own fixed className. This means font and text styling passed via className won't affect the input's appearance as might be expected.

If the intent is to allow parent components to style the input element, consider either:

  1. Accepting separate wrapperClassName and inputClassName props
  2. Applying the className prop to the input element instead
  3. Documenting that className styles the wrapper
🤖 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 `@apps/src/components/AddressInput.tsx` around lines 51 - 67, The AddressInput
component applies the className prop to the outer wrapper div instead of the
input element, which prevents parent components from styling the input itself
(e.g., font-mono, text-sm won't affect the input's appearance). Move the
className prop from the wrapper div to the input element on line 52, or
alternatively refactor the component to accept separate wrapperClassName and
inputClassName props to give parents control over styling both the wrapper and
the input element independently.

43-47: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Error message may be misleading for non-permission failures.

The catch block assumes all errors from navigator.clipboard.readText() are permission denials, but the API can fail for other reasons (e.g., the page is not in a secure context despite navigator.clipboard existing, or other runtime errors). While the actual error is logged to console, the toast message might confuse users in edge cases.

♻️ Optional improvement for error clarity
 } catch (error) {
- toast.error("Clipboard access permission denied");+ toast.error("Unable to access clipboard");
console.error("Clipboard Error: ", error);
🤖 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 `@apps/src/components/AddressInput.tsx` around lines 43 - 47, The catch block
for navigator.clipboard.readText() assumes all errors are permission denials and
displays a misleading toast message. Instead of showing a generic permission
error, inspect the caught error object to determine the actual cause (permission
error, insecure context, or other runtime errors) and display an appropriate
toast message using toast.error() based on the specific error condition. This
ensures users see an accurate error message for their particular failure
scenario.
🤖 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.
Nitpick comments:
In `@apps/src/components/AddressInput.tsx`:
- Line 44: Remove the empty comment line in the AddressInput.tsx component at
line 44. The standalone comment marker "//" with no text following it provides
no value and should be deleted entirely to improve code clarity and cleanliness.
- Around line 51-67: The AddressInput component applies the className prop to
the outer wrapper div instead of the input element, which prevents parent
components from styling the input itself (e.g., font-mono, text-sm won't affect
the input's appearance). Move the className prop from the wrapper div to the
input element on line 52, or alternatively refactor the component to accept
separate wrapperClassName and inputClassName props to give parents control over
styling both the wrapper and the input element independently.
- Around line 43-47: The catch block for navigator.clipboard.readText() assumes
all errors are permission denials and displays a misleading toast message.
Instead of showing a generic permission error, inspect the caught error object
to determine the actual cause (permission error, insecure context, or other
runtime errors) and display an appropriate toast message using toast.error()
based on the specific error condition. This ensures users see an accurate error
message for their particular failure scenario.
In `@apps/src/pages/SchedulePage.tsx`:
- Around line 108-114: Remove the trailing whitespace after the AddressInput
component's closing tag `/>` on line 113, and remove the excessive leading
whitespace before the closing `</div>` tag on line 114 to ensure consistent
formatting and proper indentation alignment with the rest of the component.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 40bb9572-a28f-4421-a00e-8888b94b9ea9

📥 Commits

Reviewing files that changed from the base of the PR and between 867ba1e and c36170a.

📒 Files selected for processing (3)
  • apps/src/components/AddressInput.tsx
  • apps/src/pages/SchedulePage.tsx
  • apps/src/pages/SendPage.tsx

Sign up for freeto 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.

Issue #1 — Add clipboard paste button on address input fields

1 participant

@avatGit
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' feat: add clipboard paste shortcut with Stellar address validation to… by avatGit · Pull Request #36 · MJ-RWA/Stellarflow · GitHub
Skip to content

feat: add clipboard paste shortcut with Stellar address validation to… - #36

Open
avatGit wants to merge 1 commit into
MJ-RWA:mainfrom
avatGit:feature/address-paste-button
Open

feat: add clipboard paste shortcut with Stellar address validation to…#36
avatGit wants to merge 1 commit into
MJ-RWA:mainfrom
avatGit:feature/address-paste-button

Conversation

@avatGit

@avatGitavatGit commented Jun 22, 2026

Copy link
Copy Markdown

Summary

Addresses the issue where mobile users have to manually type or paste Stellar public keys. This PR adds a reusable AddressInput component with a paste icon button next to destination fields, significantly improving mobile UX.

Changes

  • Create: src/components/AddressInput.tsx (handles clipboard access and validation)
  • Modify: src/pages/SendPage.tsx & src/pages/SchedulePage.tsx (replaced old input fields)

Key Features

  • Uses navigator.clipboard.readText() to auto-fill the field.
  • Validates the pasted key using StellarSdk.StrKey.isValidEd25519PublicKey().
  • Shows clear error/success feedback using react-hot-toast.

Closes#3
Recording 2026-06-23 011729

Summary by CodeRabbit

  • New Features
    • Introduced an improved address input component featuring an integrated paste button, making Stellar address entry simpler and more convenient across Schedule and Send pages.
    • Real-time validation ensures only valid Stellar addresses are accepted, providing clear error notifications for invalid entries, empty clipboard, or permission issues.

@avatGit
avatGit requested a review from MJ-RWA as a code ownerJune 22, 2026 23:19
@vercel

vercelBot commented Jun 22, 2026

Copy link
Copy Markdown

@avatGit is attempting to deploy a commit to the MJ X Dev's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitaiBot commented Jun 22, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

A new reusable AddressInput React component is added with a clipboard paste button. It validates clipboard content as a Stellar Ed25519 public key using StellarSdk and reports outcomes via react-hot-toast. SendPage and SchedulePage replace their plain destination <input> elements with this component.

Changes

AddressInput Component and Integration

Layer / File(s)Summary
AddressInput component definition
apps/src/components/AddressInput.tsx
Defines AddressInputProps (value, onChange, placeholder, className), an async paste handler that checks clipboard availability, reads and trims text, validates it via StellarSdk.StrKey.isValidEd25519PublicKey, calls onChange on success, and reports all outcomes (clipboard unavailable, empty, invalid address, permission error) via react-hot-toast. Renders a text input with an absolutely-positioned paste icon button.
SendPage and SchedulePage integration
apps/src/pages/SendPage.tsx, apps/src/pages/SchedulePage.tsx
Imports AddressInput in both pages and replaces the plain destination <input> elements with the new component, passing value, onChange (bound to setDestination), placeholder, and monospace className props.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 Hop, hop! No more typing keys by paw,
A paste button lands with clipboard's draw.
G... addresses fill with a click,
Invalid ones get a toast — real quick!
The bunny cheers: smooth sends, no trick. 🌟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 0.00% 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 nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title accurately summarizes the main change: adding clipboard paste functionality with Stellar address validation to address input components.
Linked Issues check✅ PassedAll core requirements from issue #3 are met: AddressInput component created with clipboard paste button, integrated into SendPage and SchedulePage, validates via StellarSdk.StrKey.isValidEd25519PublicKey, and provides toast feedback.
Out of Scope Changes check✅ PassedAll changes are directly scoped to the linked issue: new AddressInput component creation and integration into two destination address fields as specified.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (4)
apps/src/pages/SchedulePage.tsx (1)

108-114: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Minor formatting inconsistencies.

Line 113 has trailing whitespace after />, and line 114 has leading whitespace before </div>. While these don't affect functionality, they create inconsistent formatting.

♻️ Formatting cleanup
 <AddressInput value={destination} onChange={setDestination} placeholder="G..."
className="font-mono text-sm"
- /> - </div>+ />+ </div>
🤖 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 `@apps/src/pages/SchedulePage.tsx` around lines 108 - 114, Remove the trailing
whitespace after the AddressInput component's closing tag `/>` on line 113, and
remove the excessive leading whitespace before the closing `</div>` tag on line
114 to ensure consistent formatting and proper indentation alignment with the
rest of the component.
apps/src/components/AddressInput.tsx (3)

44-44: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove empty comment.

The empty comment on line 44 serves no purpose and reduces code clarity.

♻️ Suggested cleanup
 } catch (error) {
- //
toast.error("Clipboard access permission denied");
🤖 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 `@apps/src/components/AddressInput.tsx` at line 44, Remove the empty comment
line in the AddressInput.tsx component at line 44. The standalone comment marker
"//" with no text following it provides no value and should be deleted entirely
to improve code clarity and cleanliness.

51-67: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

The className prop is applied to the wrapper div, not the input element.

The className prop passed from parent components (e.g., "font-mono text-sm" in SendPage and SchedulePage) is applied to the outer wrapper <div> on line 51, not to the <input> element on line 52, which has its own fixed className. This means font and text styling passed via className won't affect the input's appearance as might be expected.

If the intent is to allow parent components to style the input element, consider either:

  1. Accepting separate wrapperClassName and inputClassName props
  2. Applying the className prop to the input element instead
  3. Documenting that className styles the wrapper
🤖 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 `@apps/src/components/AddressInput.tsx` around lines 51 - 67, The AddressInput
component applies the className prop to the outer wrapper div instead of the
input element, which prevents parent components from styling the input itself
(e.g., font-mono, text-sm won't affect the input's appearance). Move the
className prop from the wrapper div to the input element on line 52, or
alternatively refactor the component to accept separate wrapperClassName and
inputClassName props to give parents control over styling both the wrapper and
the input element independently.

43-47: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Error message may be misleading for non-permission failures.

The catch block assumes all errors from navigator.clipboard.readText() are permission denials, but the API can fail for other reasons (e.g., the page is not in a secure context despite navigator.clipboard existing, or other runtime errors). While the actual error is logged to console, the toast message might confuse users in edge cases.

♻️ Optional improvement for error clarity
 } catch (error) {
- toast.error("Clipboard access permission denied");+ toast.error("Unable to access clipboard");
console.error("Clipboard Error: ", error);
🤖 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 `@apps/src/components/AddressInput.tsx` around lines 43 - 47, The catch block
for navigator.clipboard.readText() assumes all errors are permission denials and
displays a misleading toast message. Instead of showing a generic permission
error, inspect the caught error object to determine the actual cause (permission
error, insecure context, or other runtime errors) and display an appropriate
toast message using toast.error() based on the specific error condition. This
ensures users see an accurate error message for their particular failure
scenario.
🤖 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.
Nitpick comments:
In `@apps/src/components/AddressInput.tsx`:
- Line 44: Remove the empty comment line in the AddressInput.tsx component at
line 44. The standalone comment marker "//" with no text following it provides
no value and should be deleted entirely to improve code clarity and cleanliness.
- Around line 51-67: The AddressInput component applies the className prop to
the outer wrapper div instead of the input element, which prevents parent
components from styling the input itself (e.g., font-mono, text-sm won't affect
the input's appearance). Move the className prop from the wrapper div to the
input element on line 52, or alternatively refactor the component to accept
separate wrapperClassName and inputClassName props to give parents control over
styling both the wrapper and the input element independently.
- Around line 43-47: The catch block for navigator.clipboard.readText() assumes
all errors are permission denials and displays a misleading toast message.
Instead of showing a generic permission error, inspect the caught error object
to determine the actual cause (permission error, insecure context, or other
runtime errors) and display an appropriate toast message using toast.error()
based on the specific error condition. This ensures users see an accurate error
message for their particular failure scenario.
In `@apps/src/pages/SchedulePage.tsx`:
- Around line 108-114: Remove the trailing whitespace after the AddressInput
component's closing tag `/>` on line 113, and remove the excessive leading
whitespace before the closing `</div>` tag on line 114 to ensure consistent
formatting and proper indentation alignment with the rest of the component.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 40bb9572-a28f-4421-a00e-8888b94b9ea9

📥 Commits

Reviewing files that changed from the base of the PR and between 867ba1e and c36170a.

📒 Files selected for processing (3)
  • apps/src/components/AddressInput.tsx
  • apps/src/pages/SchedulePage.tsx
  • apps/src/pages/SendPage.tsx

Sign up for freeto 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.

Issue #1 — Add clipboard paste button on address input fields

1 participant

@avatGit
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' feat: add clipboard paste shortcut with Stellar address validation to… by avatGit · Pull Request #36 · MJ-RWA/Stellarflow · GitHub
Skip to content

feat: add clipboard paste shortcut with Stellar address validation to… - #36

Open
avatGit wants to merge 1 commit into
MJ-RWA:mainfrom
avatGit:feature/address-paste-button
Open

feat: add clipboard paste shortcut with Stellar address validation to…#36
avatGit wants to merge 1 commit into
MJ-RWA:mainfrom
avatGit:feature/address-paste-button

Conversation

@avatGit

@avatGitavatGit commented Jun 22, 2026

Copy link
Copy Markdown

Summary

Addresses the issue where mobile users have to manually type or paste Stellar public keys. This PR adds a reusable AddressInput component with a paste icon button next to destination fields, significantly improving mobile UX.

Changes

  • Create: src/components/AddressInput.tsx (handles clipboard access and validation)
  • Modify: src/pages/SendPage.tsx & src/pages/SchedulePage.tsx (replaced old input fields)

Key Features

  • Uses navigator.clipboard.readText() to auto-fill the field.
  • Validates the pasted key using StellarSdk.StrKey.isValidEd25519PublicKey().
  • Shows clear error/success feedback using react-hot-toast.

Closes#3
Recording 2026-06-23 011729

Summary by CodeRabbit

  • New Features
    • Introduced an improved address input component featuring an integrated paste button, making Stellar address entry simpler and more convenient across Schedule and Send pages.
    • Real-time validation ensures only valid Stellar addresses are accepted, providing clear error notifications for invalid entries, empty clipboard, or permission issues.

@avatGit
avatGit requested a review from MJ-RWA as a code ownerJune 22, 2026 23:19
@vercel

vercelBot commented Jun 22, 2026

Copy link
Copy Markdown

@avatGit is attempting to deploy a commit to the MJ X Dev's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitaiBot commented Jun 22, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

A new reusable AddressInput React component is added with a clipboard paste button. It validates clipboard content as a Stellar Ed25519 public key using StellarSdk and reports outcomes via react-hot-toast. SendPage and SchedulePage replace their plain destination <input> elements with this component.

Changes

AddressInput Component and Integration

Layer / File(s)Summary
AddressInput component definition
apps/src/components/AddressInput.tsx
Defines AddressInputProps (value, onChange, placeholder, className), an async paste handler that checks clipboard availability, reads and trims text, validates it via StellarSdk.StrKey.isValidEd25519PublicKey, calls onChange on success, and reports all outcomes (clipboard unavailable, empty, invalid address, permission error) via react-hot-toast. Renders a text input with an absolutely-positioned paste icon button.
SendPage and SchedulePage integration
apps/src/pages/SendPage.tsx, apps/src/pages/SchedulePage.tsx
Imports AddressInput in both pages and replaces the plain destination <input> elements with the new component, passing value, onChange (bound to setDestination), placeholder, and monospace className props.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 Hop, hop! No more typing keys by paw,
A paste button lands with clipboard's draw.
G... addresses fill with a click,
Invalid ones get a toast — real quick!
The bunny cheers: smooth sends, no trick. 🌟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 0.00% 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 nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title accurately summarizes the main change: adding clipboard paste functionality with Stellar address validation to address input components.
Linked Issues check✅ PassedAll core requirements from issue #3 are met: AddressInput component created with clipboard paste button, integrated into SendPage and SchedulePage, validates via StellarSdk.StrKey.isValidEd25519PublicKey, and provides toast feedback.
Out of Scope Changes check✅ PassedAll changes are directly scoped to the linked issue: new AddressInput component creation and integration into two destination address fields as specified.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (4)
apps/src/pages/SchedulePage.tsx (1)

108-114: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Minor formatting inconsistencies.

Line 113 has trailing whitespace after />, and line 114 has leading whitespace before </div>. While these don't affect functionality, they create inconsistent formatting.

♻️ Formatting cleanup
 <AddressInput value={destination} onChange={setDestination} placeholder="G..."
className="font-mono text-sm"
- /> - </div>+ />+ </div>
🤖 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 `@apps/src/pages/SchedulePage.tsx` around lines 108 - 114, Remove the trailing
whitespace after the AddressInput component's closing tag `/>` on line 113, and
remove the excessive leading whitespace before the closing `</div>` tag on line
114 to ensure consistent formatting and proper indentation alignment with the
rest of the component.
apps/src/components/AddressInput.tsx (3)

44-44: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove empty comment.

The empty comment on line 44 serves no purpose and reduces code clarity.

♻️ Suggested cleanup
 } catch (error) {
- //
toast.error("Clipboard access permission denied");
🤖 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 `@apps/src/components/AddressInput.tsx` at line 44, Remove the empty comment
line in the AddressInput.tsx component at line 44. The standalone comment marker
"//" with no text following it provides no value and should be deleted entirely
to improve code clarity and cleanliness.

51-67: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

The className prop is applied to the wrapper div, not the input element.

The className prop passed from parent components (e.g., "font-mono text-sm" in SendPage and SchedulePage) is applied to the outer wrapper <div> on line 51, not to the <input> element on line 52, which has its own fixed className. This means font and text styling passed via className won't affect the input's appearance as might be expected.

If the intent is to allow parent components to style the input element, consider either:

  1. Accepting separate wrapperClassName and inputClassName props
  2. Applying the className prop to the input element instead
  3. Documenting that className styles the wrapper
🤖 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 `@apps/src/components/AddressInput.tsx` around lines 51 - 67, The AddressInput
component applies the className prop to the outer wrapper div instead of the
input element, which prevents parent components from styling the input itself
(e.g., font-mono, text-sm won't affect the input's appearance). Move the
className prop from the wrapper div to the input element on line 52, or
alternatively refactor the component to accept separate wrapperClassName and
inputClassName props to give parents control over styling both the wrapper and
the input element independently.

43-47: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Error message may be misleading for non-permission failures.

The catch block assumes all errors from navigator.clipboard.readText() are permission denials, but the API can fail for other reasons (e.g., the page is not in a secure context despite navigator.clipboard existing, or other runtime errors). While the actual error is logged to console, the toast message might confuse users in edge cases.

♻️ Optional improvement for error clarity
 } catch (error) {
- toast.error("Clipboard access permission denied");+ toast.error("Unable to access clipboard");
console.error("Clipboard Error: ", error);
🤖 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 `@apps/src/components/AddressInput.tsx` around lines 43 - 47, The catch block
for navigator.clipboard.readText() assumes all errors are permission denials and
displays a misleading toast message. Instead of showing a generic permission
error, inspect the caught error object to determine the actual cause (permission
error, insecure context, or other runtime errors) and display an appropriate
toast message using toast.error() based on the specific error condition. This
ensures users see an accurate error message for their particular failure
scenario.
🤖 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.
Nitpick comments:
In `@apps/src/components/AddressInput.tsx`:
- Line 44: Remove the empty comment line in the AddressInput.tsx component at
line 44. The standalone comment marker "//" with no text following it provides
no value and should be deleted entirely to improve code clarity and cleanliness.
- Around line 51-67: The AddressInput component applies the className prop to
the outer wrapper div instead of the input element, which prevents parent
components from styling the input itself (e.g., font-mono, text-sm won't affect
the input's appearance). Move the className prop from the wrapper div to the
input element on line 52, or alternatively refactor the component to accept
separate wrapperClassName and inputClassName props to give parents control over
styling both the wrapper and the input element independently.
- Around line 43-47: The catch block for navigator.clipboard.readText() assumes
all errors are permission denials and displays a misleading toast message.
Instead of showing a generic permission error, inspect the caught error object
to determine the actual cause (permission error, insecure context, or other
runtime errors) and display an appropriate toast message using toast.error()
based on the specific error condition. This ensures users see an accurate error
message for their particular failure scenario.
In `@apps/src/pages/SchedulePage.tsx`:
- Around line 108-114: Remove the trailing whitespace after the AddressInput
component's closing tag `/>` on line 113, and remove the excessive leading
whitespace before the closing `</div>` tag on line 114 to ensure consistent
formatting and proper indentation alignment with the rest of the component.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 40bb9572-a28f-4421-a00e-8888b94b9ea9

📥 Commits

Reviewing files that changed from the base of the PR and between 867ba1e and c36170a.

📒 Files selected for processing (3)
  • apps/src/components/AddressInput.tsx
  • apps/src/pages/SchedulePage.tsx
  • apps/src/pages/SendPage.tsx

Sign up for freeto 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.

Issue #1 — Add clipboard paste button on address input fields

1 participant

@avatGit
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' feat: add clipboard paste shortcut with Stellar address validation to… by avatGit · Pull Request #36 · MJ-RWA/Stellarflow · GitHub
Skip to content

feat: add clipboard paste shortcut with Stellar address validation to… - #36

Open
avatGit wants to merge 1 commit into
MJ-RWA:mainfrom
avatGit:feature/address-paste-button
Open

feat: add clipboard paste shortcut with Stellar address validation to…#36
avatGit wants to merge 1 commit into
MJ-RWA:mainfrom
avatGit:feature/address-paste-button

Conversation

@avatGit

@avatGitavatGit commented Jun 22, 2026

Copy link
Copy Markdown

Summary

Addresses the issue where mobile users have to manually type or paste Stellar public keys. This PR adds a reusable AddressInput component with a paste icon button next to destination fields, significantly improving mobile UX.

Changes

  • Create: src/components/AddressInput.tsx (handles clipboard access and validation)
  • Modify: src/pages/SendPage.tsx & src/pages/SchedulePage.tsx (replaced old input fields)

Key Features

  • Uses navigator.clipboard.readText() to auto-fill the field.
  • Validates the pasted key using StellarSdk.StrKey.isValidEd25519PublicKey().
  • Shows clear error/success feedback using react-hot-toast.

Closes#3
Recording 2026-06-23 011729

Summary by CodeRabbit

  • New Features
    • Introduced an improved address input component featuring an integrated paste button, making Stellar address entry simpler and more convenient across Schedule and Send pages.
    • Real-time validation ensures only valid Stellar addresses are accepted, providing clear error notifications for invalid entries, empty clipboard, or permission issues.

@avatGit
avatGit requested a review from MJ-RWA as a code ownerJune 22, 2026 23:19
@vercel

vercelBot commented Jun 22, 2026

Copy link
Copy Markdown

@avatGit is attempting to deploy a commit to the MJ X Dev's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitaiBot commented Jun 22, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

A new reusable AddressInput React component is added with a clipboard paste button. It validates clipboard content as a Stellar Ed25519 public key using StellarSdk and reports outcomes via react-hot-toast. SendPage and SchedulePage replace their plain destination <input> elements with this component.

Changes

AddressInput Component and Integration

Layer / File(s)Summary
AddressInput component definition
apps/src/components/AddressInput.tsx
Defines AddressInputProps (value, onChange, placeholder, className), an async paste handler that checks clipboard availability, reads and trims text, validates it via StellarSdk.StrKey.isValidEd25519PublicKey, calls onChange on success, and reports all outcomes (clipboard unavailable, empty, invalid address, permission error) via react-hot-toast. Renders a text input with an absolutely-positioned paste icon button.
SendPage and SchedulePage integration
apps/src/pages/SendPage.tsx, apps/src/pages/SchedulePage.tsx
Imports AddressInput in both pages and replaces the plain destination <input> elements with the new component, passing value, onChange (bound to setDestination), placeholder, and monospace className props.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 Hop, hop! No more typing keys by paw,
A paste button lands with clipboard's draw.
G... addresses fill with a click,
Invalid ones get a toast — real quick!
The bunny cheers: smooth sends, no trick. 🌟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 0.00% 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 nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title accurately summarizes the main change: adding clipboard paste functionality with Stellar address validation to address input components.
Linked Issues check✅ PassedAll core requirements from issue #3 are met: AddressInput component created with clipboard paste button, integrated into SendPage and SchedulePage, validates via StellarSdk.StrKey.isValidEd25519PublicKey, and provides toast feedback.
Out of Scope Changes check✅ PassedAll changes are directly scoped to the linked issue: new AddressInput component creation and integration into two destination address fields as specified.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (4)
apps/src/pages/SchedulePage.tsx (1)

108-114: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Minor formatting inconsistencies.

Line 113 has trailing whitespace after />, and line 114 has leading whitespace before </div>. While these don't affect functionality, they create inconsistent formatting.

♻️ Formatting cleanup
 <AddressInput value={destination} onChange={setDestination} placeholder="G..."
className="font-mono text-sm"
- /> - </div>+ />+ </div>
🤖 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 `@apps/src/pages/SchedulePage.tsx` around lines 108 - 114, Remove the trailing
whitespace after the AddressInput component's closing tag `/>` on line 113, and
remove the excessive leading whitespace before the closing `</div>` tag on line
114 to ensure consistent formatting and proper indentation alignment with the
rest of the component.
apps/src/components/AddressInput.tsx (3)

44-44: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove empty comment.

The empty comment on line 44 serves no purpose and reduces code clarity.

♻️ Suggested cleanup
 } catch (error) {
- //
toast.error("Clipboard access permission denied");
🤖 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 `@apps/src/components/AddressInput.tsx` at line 44, Remove the empty comment
line in the AddressInput.tsx component at line 44. The standalone comment marker
"//" with no text following it provides no value and should be deleted entirely
to improve code clarity and cleanliness.

51-67: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

The className prop is applied to the wrapper div, not the input element.

The className prop passed from parent components (e.g., "font-mono text-sm" in SendPage and SchedulePage) is applied to the outer wrapper <div> on line 51, not to the <input> element on line 52, which has its own fixed className. This means font and text styling passed via className won't affect the input's appearance as might be expected.

If the intent is to allow parent components to style the input element, consider either:

  1. Accepting separate wrapperClassName and inputClassName props
  2. Applying the className prop to the input element instead
  3. Documenting that className styles the wrapper
🤖 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 `@apps/src/components/AddressInput.tsx` around lines 51 - 67, The AddressInput
component applies the className prop to the outer wrapper div instead of the
input element, which prevents parent components from styling the input itself
(e.g., font-mono, text-sm won't affect the input's appearance). Move the
className prop from the wrapper div to the input element on line 52, or
alternatively refactor the component to accept separate wrapperClassName and
inputClassName props to give parents control over styling both the wrapper and
the input element independently.

43-47: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Error message may be misleading for non-permission failures.

The catch block assumes all errors from navigator.clipboard.readText() are permission denials, but the API can fail for other reasons (e.g., the page is not in a secure context despite navigator.clipboard existing, or other runtime errors). While the actual error is logged to console, the toast message might confuse users in edge cases.

♻️ Optional improvement for error clarity
 } catch (error) {
- toast.error("Clipboard access permission denied");+ toast.error("Unable to access clipboard");
console.error("Clipboard Error: ", error);
🤖 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 `@apps/src/components/AddressInput.tsx` around lines 43 - 47, The catch block
for navigator.clipboard.readText() assumes all errors are permission denials and
displays a misleading toast message. Instead of showing a generic permission
error, inspect the caught error object to determine the actual cause (permission
error, insecure context, or other runtime errors) and display an appropriate
toast message using toast.error() based on the specific error condition. This
ensures users see an accurate error message for their particular failure
scenario.
🤖 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.
Nitpick comments:
In `@apps/src/components/AddressInput.tsx`:
- Line 44: Remove the empty comment line in the AddressInput.tsx component at
line 44. The standalone comment marker "//" with no text following it provides
no value and should be deleted entirely to improve code clarity and cleanliness.
- Around line 51-67: The AddressInput component applies the className prop to
the outer wrapper div instead of the input element, which prevents parent
components from styling the input itself (e.g., font-mono, text-sm won't affect
the input's appearance). Move the className prop from the wrapper div to the
input element on line 52, or alternatively refactor the component to accept
separate wrapperClassName and inputClassName props to give parents control over
styling both the wrapper and the input element independently.
- Around line 43-47: The catch block for navigator.clipboard.readText() assumes
all errors are permission denials and displays a misleading toast message.
Instead of showing a generic permission error, inspect the caught error object
to determine the actual cause (permission error, insecure context, or other
runtime errors) and display an appropriate toast message using toast.error()
based on the specific error condition. This ensures users see an accurate error
message for their particular failure scenario.
In `@apps/src/pages/SchedulePage.tsx`:
- Around line 108-114: Remove the trailing whitespace after the AddressInput
component's closing tag `/>` on line 113, and remove the excessive leading
whitespace before the closing `</div>` tag on line 114 to ensure consistent
formatting and proper indentation alignment with the rest of the component.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 40bb9572-a28f-4421-a00e-8888b94b9ea9

📥 Commits

Reviewing files that changed from the base of the PR and between 867ba1e and c36170a.

📒 Files selected for processing (3)
  • apps/src/components/AddressInput.tsx
  • apps/src/pages/SchedulePage.tsx
  • apps/src/pages/SendPage.tsx

Sign up for freeto 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.

Issue #1 — Add clipboard paste button on address input fields

1 participant

@avatGit
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); feat: add clipboard paste shortcut with Stellar address validation to… by avatGit · Pull Request #36 · MJ-RWA/Stellarflow · GitHub
Skip to content

feat: add clipboard paste shortcut with Stellar address validation to… - #36

Open
avatGit wants to merge 1 commit into
MJ-RWA:mainfrom
avatGit:feature/address-paste-button
Open

feat: add clipboard paste shortcut with Stellar address validation to…#36
avatGit wants to merge 1 commit into
MJ-RWA:mainfrom
avatGit:feature/address-paste-button

Conversation

@avatGit

@avatGitavatGit commented Jun 22, 2026

Copy link
Copy Markdown

Summary

Addresses the issue where mobile users have to manually type or paste Stellar public keys. This PR adds a reusable AddressInput component with a paste icon button next to destination fields, significantly improving mobile UX.

Changes

  • Create: src/components/AddressInput.tsx (handles clipboard access and validation)
  • Modify: src/pages/SendPage.tsx & src/pages/SchedulePage.tsx (replaced old input fields)

Key Features

  • Uses navigator.clipboard.readText() to auto-fill the field.
  • Validates the pasted key using StellarSdk.StrKey.isValidEd25519PublicKey().
  • Shows clear error/success feedback using react-hot-toast.

Closes#3
Recording 2026-06-23 011729

Summary by CodeRabbit

  • New Features
    • Introduced an improved address input component featuring an integrated paste button, making Stellar address entry simpler and more convenient across Schedule and Send pages.
    • Real-time validation ensures only valid Stellar addresses are accepted, providing clear error notifications for invalid entries, empty clipboard, or permission issues.

@avatGit
avatGit requested a review from MJ-RWA as a code ownerJune 22, 2026 23:19
@vercel

vercelBot commented Jun 22, 2026

Copy link
Copy Markdown

@avatGit is attempting to deploy a commit to the MJ X Dev's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitaiBot commented Jun 22, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

A new reusable AddressInput React component is added with a clipboard paste button. It validates clipboard content as a Stellar Ed25519 public key using StellarSdk and reports outcomes via react-hot-toast. SendPage and SchedulePage replace their plain destination <input> elements with this component.

Changes

AddressInput Component and Integration

Layer / File(s)Summary
AddressInput component definition
apps/src/components/AddressInput.tsx
Defines AddressInputProps (value, onChange, placeholder, className), an async paste handler that checks clipboard availability, reads and trims text, validates it via StellarSdk.StrKey.isValidEd25519PublicKey, calls onChange on success, and reports all outcomes (clipboard unavailable, empty, invalid address, permission error) via react-hot-toast. Renders a text input with an absolutely-positioned paste icon button.
SendPage and SchedulePage integration
apps/src/pages/SendPage.tsx, apps/src/pages/SchedulePage.tsx
Imports AddressInput in both pages and replaces the plain destination <input> elements with the new component, passing value, onChange (bound to setDestination), placeholder, and monospace className props.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 Hop, hop! No more typing keys by paw,
A paste button lands with clipboard's draw.
G... addresses fill with a click,
Invalid ones get a toast — real quick!
The bunny cheers: smooth sends, no trick. 🌟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 0.00% 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 nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title accurately summarizes the main change: adding clipboard paste functionality with Stellar address validation to address input components.
Linked Issues check✅ PassedAll core requirements from issue #3 are met: AddressInput component created with clipboard paste button, integrated into SendPage and SchedulePage, validates via StellarSdk.StrKey.isValidEd25519PublicKey, and provides toast feedback.
Out of Scope Changes check✅ PassedAll changes are directly scoped to the linked issue: new AddressInput component creation and integration into two destination address fields as specified.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (4)
apps/src/pages/SchedulePage.tsx (1)

108-114: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Minor formatting inconsistencies.

Line 113 has trailing whitespace after />, and line 114 has leading whitespace before </div>. While these don't affect functionality, they create inconsistent formatting.

♻️ Formatting cleanup
 <AddressInput value={destination} onChange={setDestination} placeholder="G..."
className="font-mono text-sm"
- /> - </div>+ />+ </div>
🤖 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 `@apps/src/pages/SchedulePage.tsx` around lines 108 - 114, Remove the trailing
whitespace after the AddressInput component's closing tag `/>` on line 113, and
remove the excessive leading whitespace before the closing `</div>` tag on line
114 to ensure consistent formatting and proper indentation alignment with the
rest of the component.
apps/src/components/AddressInput.tsx (3)

44-44: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove empty comment.

The empty comment on line 44 serves no purpose and reduces code clarity.

♻️ Suggested cleanup
 } catch (error) {
- //
toast.error("Clipboard access permission denied");
🤖 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 `@apps/src/components/AddressInput.tsx` at line 44, Remove the empty comment
line in the AddressInput.tsx component at line 44. The standalone comment marker
"//" with no text following it provides no value and should be deleted entirely
to improve code clarity and cleanliness.

51-67: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

The className prop is applied to the wrapper div, not the input element.

The className prop passed from parent components (e.g., "font-mono text-sm" in SendPage and SchedulePage) is applied to the outer wrapper <div> on line 51, not to the <input> element on line 52, which has its own fixed className. This means font and text styling passed via className won't affect the input's appearance as might be expected.

If the intent is to allow parent components to style the input element, consider either:

  1. Accepting separate wrapperClassName and inputClassName props
  2. Applying the className prop to the input element instead
  3. Documenting that className styles the wrapper
🤖 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 `@apps/src/components/AddressInput.tsx` around lines 51 - 67, The AddressInput
component applies the className prop to the outer wrapper div instead of the
input element, which prevents parent components from styling the input itself
(e.g., font-mono, text-sm won't affect the input's appearance). Move the
className prop from the wrapper div to the input element on line 52, or
alternatively refactor the component to accept separate wrapperClassName and
inputClassName props to give parents control over styling both the wrapper and
the input element independently.

43-47: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Error message may be misleading for non-permission failures.

The catch block assumes all errors from navigator.clipboard.readText() are permission denials, but the API can fail for other reasons (e.g., the page is not in a secure context despite navigator.clipboard existing, or other runtime errors). While the actual error is logged to console, the toast message might confuse users in edge cases.

♻️ Optional improvement for error clarity
 } catch (error) {
- toast.error("Clipboard access permission denied");+ toast.error("Unable to access clipboard");
console.error("Clipboard Error: ", error);
🤖 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 `@apps/src/components/AddressInput.tsx` around lines 43 - 47, The catch block
for navigator.clipboard.readText() assumes all errors are permission denials and
displays a misleading toast message. Instead of showing a generic permission
error, inspect the caught error object to determine the actual cause (permission
error, insecure context, or other runtime errors) and display an appropriate
toast message using toast.error() based on the specific error condition. This
ensures users see an accurate error message for their particular failure
scenario.
🤖 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.
Nitpick comments:
In `@apps/src/components/AddressInput.tsx`:
- Line 44: Remove the empty comment line in the AddressInput.tsx component at
line 44. The standalone comment marker "//" with no text following it provides
no value and should be deleted entirely to improve code clarity and cleanliness.
- Around line 51-67: The AddressInput component applies the className prop to
the outer wrapper div instead of the input element, which prevents parent
components from styling the input itself (e.g., font-mono, text-sm won't affect
the input's appearance). Move the className prop from the wrapper div to the
input element on line 52, or alternatively refactor the component to accept
separate wrapperClassName and inputClassName props to give parents control over
styling both the wrapper and the input element independently.
- Around line 43-47: The catch block for navigator.clipboard.readText() assumes
all errors are permission denials and displays a misleading toast message.
Instead of showing a generic permission error, inspect the caught error object
to determine the actual cause (permission error, insecure context, or other
runtime errors) and display an appropriate toast message using toast.error()
based on the specific error condition. This ensures users see an accurate error
message for their particular failure scenario.
In `@apps/src/pages/SchedulePage.tsx`:
- Around line 108-114: Remove the trailing whitespace after the AddressInput
component's closing tag `/>` on line 113, and remove the excessive leading
whitespace before the closing `</div>` tag on line 114 to ensure consistent
formatting and proper indentation alignment with the rest of the component.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 40bb9572-a28f-4421-a00e-8888b94b9ea9

📥 Commits

Reviewing files that changed from the base of the PR and between 867ba1e and c36170a.

📒 Files selected for processing (3)
  • apps/src/components/AddressInput.tsx
  • apps/src/pages/SchedulePage.tsx
  • apps/src/pages/SendPage.tsx

Sign up for freeto 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.

Issue #1 — Add clipboard paste button on address input fields

1 participant

@avatGit