feat: Share receipt to social + native sharing#874
feat: Share receipt to social + native sharing#874C0mberry wants to merge 7 commits intosolana-foundation:masterfrom
Conversation
* share to X init * init share native * removed native sharing for desctop and fixed btn height * move back native sharing desktop * add sentry error handling * fix tests * add native share for mobile only * codestyle update
|
@C0mberry is attempting to deploy a commit to the Solana Foundation Team on Vercel. A member of the Team first needs to authorize it. |
Greptile SummaryThis PR adds social and native sharing capabilities to the transaction receipt view. On mobile devices (detected via Key changes:
Confidence Score: 3/5
Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[ReceiptView mounts] --> B{useCanNativeShare}
B -->|navigator.share + canShare + isMobileDevice| C[canNativeShare = true]
B -->|otherwise| D[canNativeShare = false]
C --> E[Render native Share button]
D --> F[Render PopoverButton]
E -->|onClick| G[handleNativeShare]
G --> H{navigator.canShare shareData ?}
H -->|false / undefined| I[silent return]
H -->|true| J[navigator.share url + title]
J -->|resolved| K[trackShareNative]
J -->|AbortError| L[silent return]
J -->|other error| M[throw → unhandled rejection]
F --> N[Share Popover opens]
N --> O[ShareOnXShareItem]
N --> P[CopyLinkShareItem]
O -->|handleClick| Q[globalThis.open x.com intent noreferrer]
Q -->|win != null| R[trackShareOnX]
Q -->|win == null popup blocked or noopener| S[analytics skipped]
P -->|onCopy| T[trackShareCopyLink]
Last reviewed commit: 284783b |
|
@greptile-apps issue was addressed |
|
@greptile-apps issue was addressed |
|
|
||
| useEffect(() => { | ||
| const hasCoarsePointer = window.matchMedia('(pointer: coarse)').matches; | ||
| const hasNoHover = window.matchMedia('(hover: none)').matches; |
There was a problem hiding this comment.
WDYT about moving this code into a separate hook? That should allow using it at other palces
There was a problem hiding this comment.
suggestion: I agree that this should at least be extracted to a local hook, like useCanNativeShare, because having raw implementation details in a UI component is inappropriate. Additionally, the heuristic itself is undocumented. It would be better to include either comments or meaningful helper function names, such as isMobileDevice
|
|
||
| useEffect(() => { | ||
| const hasCoarsePointer = window.matchMedia('(pointer: coarse)').matches; | ||
| const hasNoHover = window.matchMedia('(hover: none)').matches; |
There was a problem hiding this comment.
suggestion: I agree that this should at least be extracted to a local hook, like useCanNativeShare, because having raw implementation details in a UI component is inappropriate. Additionally, the heuristic itself is undocumented. It would be better to include either comments or meaningful helper function names, such as isMobileDevice
| receiptAnalytics.trackShareNative(signature); | ||
| } catch (e) { | ||
| if (e instanceof Error && e.name === 'AbortError') return; | ||
| Sentry.captureException(e); |
There was a problem hiding this comment.
thought: I don't think this kind of error deserves sentry logging, but the decision is yours. Wdyt @rogaldh?
There was a problem hiding this comment.
Agreed. Too harsh for the inability to share. To inform the user would be enough. We have a toast for that
| import { NextRequest } from 'next/server'; | ||
| import { beforeEach, describe, expect, it, vi } from 'vitest'; | ||
|
|
||
| vi.mock('@sentry/nextjs', () => ({ |
There was a problem hiding this comment.
thougth: This isn't really an issue, but it might not be clear for everyone. According to FSD, everything is correct; however, barrel imports can leak unwanted elements in the development environment. Perhaps, in addition to the index, we could have something like server.ts to support separate feature API surfaces. Then, the import for server routes could look like this: import { X } from "@features/receipt/server"
There was a problem hiding this comment.
I also agree. Having everything exported to a single place mixes client and server code. That's why we have to mock something that is not even used.
Let's split the backend endpoint code into a separate file, server.ts.
I do not like barrel files very much, but according to the FSD, it seems reasonable and also allows us to expose a "public" API for the feature.
TY @askov for noticing this.
There was a problem hiding this comment.
Now we can remove this sentry mock, it does nothing
| @@ -0,0 +1,10 @@ | |||
| export function XIcon() { | |||
There was a problem hiding this comment.
nit: Typically, such icons should have aria-hidden attributes since they're purely decorative. However, I'm not sure if the other icons in our project follow this recommendation.
There was a problem hiding this comment.
That is fair, but AFAIK, event react-feathers icons do not have this attribute. Pure SVGs, same as this. So this should be applied to each icon specifically.
I do like the suggestions. Let's maybe implement a wrapper or similar solution to apply this attribute to make icons a11y-friendly. @C0mberry @askov thoughts?
|
@greptile-apps issue was addressed |
|
@greptile-apps issue was addressed |
Description
Type of change
Screenshots
Testing
Open http://localhost:3000/tx/4izwTCUeRGAMGReXeXDumiBzAgXPGz6KzccacCf1WU5YXCCpSDjAQT7J6D6dY45bL1NW9AiqwCuWEnz3hbGtZS2y?view=receipt on desktop
See share popup
Open the same link on mobile
See native sharing menu
Related Issues
HOO-320
HOO-319
Checklist
build:infoscript to update build information