-
Notifications
You must be signed in to change notification settings - Fork 13
[TASK-11943] Sprint 94 Prod release #899
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
[TASK-11760] feat: return total transacted
feat: update profile avatar colors
feat: standalone receipts without drawer + share receipt
[wip] fix: try to check passkey existence
feat: show add money prompt modal wen zero balance
…peanut-ui into fix/device-modal
fix: check device support using user agent
fix: claim flow ux and bugs
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
WalkthroughThis update introduces new PWA support features, device/browser environment detection utilities, and UI enhancements for onboarding and transaction flows. Major changes include assetlinks for Android app association, improved setup and install flows for PWAs, new modal components for iOS install and add-money prompts, expanded color utilities, avatar styling updates, and enhancements to user profile and transaction details displays. Changes
Possibly related PRs
Suggested reviewers
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
⏰ Context from checks skipped due to timeout of 90000ms (1)
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 15
🧹 Nitpick comments (10)
src/components/AddWithdraw/components/AddWithdrawCountriesList.tsx (1)
64-65
: Good transition to new color utility structure, but simplify redundant conditional.The update to use
lightShade
from the new color utility structure is correct. However, the color assignment can be simplified since both conditions set the color to 'black'.Apply this diff to simplify the redundant conditional:
- color: method.icon === ('bank' as IconName) ? 'black' : 'black', + color: 'black',src/components/Global/PeanutActionDetailsCard/index.tsx (1)
88-100
: Optimize duplicategetColorForUsername
calls for better performance.The logic correctly implements the dual-shade color system and properly handles the ENS recipient type. However,
getColorForUsername(recipientName)
is called twice with the same arguments, which could impact performance.Consider memoizing the color result:
+ const userColors = useMemo(() => getColorForUsername(recipientName), [recipientName]) inlineStyle={{ backgroundColor: viewType === 'SUCCESS' ? '#29CC6A' : transactionType === 'ADD_MONEY' || recipientType === 'ADDRESS' || recipientType === 'ENS' ? '#FFC900' - : getColorForUsername(recipientName).lightShade, + : userColors.lightShade, color: viewType === 'SUCCESS' ? AVATAR_TEXT_DARK : transactionType === 'ADD_MONEY' || recipientType === 'ADDRESS' || recipientType === 'ENS' ? AVATAR_TEXT_DARK - : getColorForUsername(recipientName).darkShade, + : userColors.darkShade, }}Don't forget to import
useMemo
from React if not already imported.src/components/Profile/AvatarWithBadge.tsx (1)
73-76
: Optimize duplicategetColorForUsername
calls and approve styling logic.The dual-shade color implementation is excellent - using
lightShade
for background anddarkShade
for border/text provides good visual hierarchy and contrast. However,getColorForUsername(name)
is called multiple times with the same argument.Consider memoizing the color result:
+ const userColors = useMemo(() => name ? getColorForUsername(name) : null, [name]) + return ( <div className={'relative'}> {/* the main avatar circle */} <div className={twMerge( `flex items-center justify-center rounded-full font-bold`, sizeClasses[size], className )} style={{ - background: name ? getColorForUsername(name).lightShade : undefined, - border: name && !icon ? `1px solid ${getColorForUsername(name).darkShade}` : undefined, - color: name ? getColorForUsername(name).darkShade : !icon ? textColor : undefined, + background: userColors?.lightShade, + border: name && !icon ? `1px solid ${userColors?.darkShade}` : undefined, + color: userColors?.darkShade || (!icon ? textColor : undefined), ...inlineStyle, }} >src/components/TransactionDetails/TransactionDetailsDrawer.tsx (1)
225-235
: Remove unnecessary Fragment wrapperThe Fragment is redundant here since it only contains conditional content that can be rendered directly.
- {transaction.status === 'cancelled' && - transaction.extraDataForDrawer?.originalUserRole === EHistoryUserRole.BOTH && - transaction.cancelledDate && ( - <> - {transaction.cancelledDate && ( - <PaymentInfoRow - label="Cancelled" - value={formatDate(transaction.cancelledDate as Date)} - hideBottomBorder={ - !transaction.fee && !transaction.memo && !transaction.attachmentUrl - } - /> - )} - </> - )} + {transaction.status === 'cancelled' && + transaction.extraDataForDrawer?.originalUserRole === EHistoryUserRole.BOTH && + transaction.cancelledDate && ( + <PaymentInfoRow + label="Cancelled" + value={formatDate(transaction.cancelledDate as Date)} + hideBottomBorder={ + !transaction.fee && !transaction.memo && !transaction.attachmentUrl + } + /> + )}🧰 Tools
🪛 Biome (1.9.4)
[error] 225-235: Avoid using unnecessary Fragment.
A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment(lint/complexity/noUselessFragments)
src/components/Setup/Views/Welcome.tsx (1)
61-61
: Minor: Consider consistent capitalization.The button text "Log In" uses title case while most other buttons use sentence case. Consider using "Log in" for consistency with common UI patterns.
- Log In + Log insrc/components/Setup/Setup.utils.ts (1)
1-1
: Consider potential import path fragility.The relative import path
'../Global/UnsupportedBrowserModal'
could break if the file structure changes. Consider using an absolute import or exportinginAppSignatures
from a constants file.-import { inAppSignatures } from '../Global/UnsupportedBrowserModal' +import { inAppSignatures } from '@/constants/browser-detection'Or create a centralized constants file to avoid coupling this utility to a modal component.
src/components/Global/IOSInstallPWAModal/index.tsx (1)
47-82
: Consider explicit handling for Firefox browserFirefox is detected in
getIOSBrowserType
but falls into the else block (lines 66-81) with instructions to open in Safari. If this is intentional because Firefox on iOS doesn't support PWA installation, consider making this more explicit for better code clarity.- // default to standard instructions (Chrome, Safari, Arc) - if (browserType === 'safari' || browserType === 'chrome' || browserType === 'other') { + // browsers that support PWA installation on iOS + if (browserType === 'safari' || browserType === 'chrome') { descriptionTextJsx = ( <p className="flex flex-col items-center gap-1 text-sm text-grey-1"> <span className="flex items-center gap-2"> Tap the <span className="flex items-center gap-1 font-bold"> <Icon name="share" size={16} /> Share icon </span> </span> <span> {' '} then on <span className="font-bold"> "Add To Home Screen"</span> </span> </p> ) - } else { - // fallback for Brave and potentially other non-standard WebKit browsers + } else if (browserType === 'firefox' || browserType === 'brave' || browserType === 'other') { + // browsers that don't support PWA installation on iOS descriptionTextJsx = (src/components/Global/UnsupportedBrowserModal/index.tsx (1)
107-124
: Remove redundantvisible
propThe
visible={true}
prop on line 109 is redundant since the component already handles visibility by returningnull
on lines 71-73 when the modal shouldn't be shown.<ActionModal - visible={true} onClose={handleModalClose} title="Open this link in your browser"
src/app/(setup)/setup/page.tsx (1)
176-177
: Document the intentionally empty onClose handlerThe empty function for
onClose
might be confusing to other developers. Consider adding a comment to clarify that this modal is intentionally not closeable.visible={true} - onClose={() => {}} // no action on close for this modal + onClose={() => { + // Intentionally empty - this modal cannot be closed by the user + }} title="Device not supported!"src/components/Setup/Views/InstallPWA.tsx (1)
104-113
: Consider alternative to opening new tab after PWA installation.Opening a new tab to
/setup
after installation might confuse users. Consider:
- Showing instructions to open the installed PWA from home screen
- Using a more descriptive button label
- Avoiding multiple tabs with the same content
Instead of automatically opening a new tab, consider showing instructions:
-} else { - const link = document.createElement('a') - link.href = '/setup' - link.target = '_blank' - document.body.appendChild(link) - link.click() - document.body.removeChild(link) -} +} else { + // Show instructions to user to open PWA from home screen + toast.info('Please open Peanut from your home screen to continue in the app') +}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
src/assets/peanut/peanutman-waving.svg
is excluded by!**/*.svg
📒 Files selected for processing (46)
public/.well-known/assetlinks.json
(1 hunks)src/app/(mobile-ui)/history/layout.tsx
(1 hunks)src/app/(mobile-ui)/home/page.tsx
(6 hunks)src/app/(mobile-ui)/layout.tsx
(1 hunks)src/app/(setup)/setup/page.tsx
(4 hunks)src/app/[...recipient]/client.tsx
(4 hunks)src/app/manifest.ts
(1 hunks)src/app/sitemap.ts
(1 hunks)src/assets/peanut/index.ts
(1 hunks)src/components/0_Bruddle/Button.tsx
(1 hunks)src/components/AddMoney/views/NetworkSelection.view.tsx
(1 hunks)src/components/AddWithdraw/components/AddWithdrawCountriesList.tsx
(1 hunks)src/components/Claim/Claim.consts.ts
(1 hunks)src/components/Claim/Claim.tsx
(3 hunks)src/components/Claim/Link/Initial.view.tsx
(8 hunks)src/components/Global/ErrorAlert/index.tsx
(1 hunks)src/components/Global/IOSInstallPWAModal/index.tsx
(1 hunks)src/components/Global/PeanutActionDetailsCard/index.tsx
(2 hunks)src/components/Global/TokenSelector/TokenSelector.tsx
(0 hunks)src/components/Global/UnsupportedBrowserModal/index.tsx
(1 hunks)src/components/Home/AddMoneyPromptModal/index.tsx
(1 hunks)src/components/Profile/AvatarWithBadge.tsx
(1 hunks)src/components/Profile/components/ProfileHeader.tsx
(2 hunks)src/components/Profile/components/PublicProfile.tsx
(5 hunks)src/components/Request/direct-request/views/Initial.direct.request.view.tsx
(0 hunks)src/components/Setup/Setup.consts.tsx
(2 hunks)src/components/Setup/Setup.types.ts
(3 hunks)src/components/Setup/Setup.utils.ts
(1 hunks)src/components/Setup/Views/ContactInfo.tsx
(0 hunks)src/components/Setup/Views/InstallPWA.tsx
(2 hunks)src/components/Setup/Views/SetupPasskey.tsx
(2 hunks)src/components/Setup/Views/Signup.tsx
(4 hunks)src/components/Setup/Views/Welcome.tsx
(3 hunks)src/components/Setup/components/SetupWrapper.tsx
(6 hunks)src/components/Setup/components/StepTransition.tsx
(0 hunks)src/components/TransactionDetails/TransactionAvatarBadge.tsx
(1 hunks)src/components/TransactionDetails/TransactionDetailsDrawer.tsx
(5 hunks)src/components/User/UserCard.tsx
(2 hunks)src/context/authContext.tsx
(2 hunks)src/context/kernelClient.context.tsx
(1 hunks)src/hooks/useTransactionHistory.ts
(1 hunks)src/hooks/useZeroDev.ts
(5 hunks)src/interfaces/interfaces.ts
(1 hunks)src/services/users.ts
(3 hunks)src/utils/color.utils.ts
(3 hunks)src/utils/general.utils.ts
(1 hunks)
💤 Files with no reviewable changes (4)
- src/components/Request/direct-request/views/Initial.direct.request.view.tsx
- src/components/Global/TokenSelector/TokenSelector.tsx
- src/components/Setup/Views/ContactInfo.tsx
- src/components/Setup/components/StepTransition.tsx
🧰 Additional context used
🧠 Learnings (1)
src/components/Claim/Link/Initial.view.tsx (1)
Learnt from: jjramirezn
PR: peanutprotocol/peanut-ui#551
File: src/components/Request/Create/Views/Initial.view.tsx:151-156
Timestamp: 2024-12-02T17:19:18.532Z
Learning: In the `InitialView` component at `src/components/Request/Create/Views/Initial.view.tsx`, when setting the default chain and token in the `useEffect` triggered by `isPeanutWallet`, it's acceptable to omit the setters from the dependency array and not include additional error handling for invalid defaults.
🧬 Code Graph Analysis (15)
src/hooks/useTransactionHistory.ts (1)
src/constants/general.consts.ts (1)
BASE_URL
(43-43)
src/components/AddWithdraw/components/AddWithdrawCountriesList.tsx (2)
src/utils/color.utils.ts (1)
getColorForUsername
(51-69)src/components/Global/Icons/Icon.tsx (1)
IconName
(51-98)
src/context/kernelClient.context.tsx (2)
src/context/authContext.tsx (1)
useAuth
(202-208)src/utils/general.utils.ts (1)
getFromLocalStorage
(108-123)
src/components/Setup/Views/SetupPasskey.tsx (2)
src/components/0_Bruddle/Button.tsx (1)
Button
(69-130)src/redux/slices/setup-slice.ts (1)
setupActions
(50-50)
src/components/User/UserCard.tsx (1)
src/utils/color.utils.ts (2)
getColorForUsername
(51-69)AVATAR_TEXT_DARK
(44-44)
src/services/users.ts (2)
src/utils/sentry.utils.ts (1)
fetchWithSentry
(11-89)src/constants/general.consts.ts (1)
PEANUT_API_URL
(37-41)
src/components/Profile/AvatarWithBadge.tsx (1)
src/utils/color.utils.ts (1)
getColorForUsername
(51-69)
src/components/Global/PeanutActionDetailsCard/index.tsx (1)
src/utils/color.utils.ts (2)
getColorForUsername
(51-69)AVATAR_TEXT_DARK
(44-44)
src/components/Setup/Setup.utils.ts (1)
src/components/Global/UnsupportedBrowserModal/index.tsx (1)
inAppSignatures
(9-35)
src/app/[...recipient]/client.tsx (1)
src/components/TransactionDetails/TransactionDetailsDrawer.tsx (1)
TransactionDetailsReceipt
(80-445)
src/components/Profile/components/PublicProfile.tsx (2)
src/context/authContext.tsx (1)
useAuth
(202-208)src/utils/general.utils.ts (1)
formatExtendedNumber
(998-1046)
src/components/Global/ErrorAlert/index.tsx (1)
src/components/Global/Icons/Icon.tsx (1)
Icon
(155-164)
src/components/Home/AddMoneyPromptModal/index.tsx (1)
src/components/Global/ActionModal/index.tsx (1)
ActionModalButtonProps
(8-11)
src/app/(setup)/setup/page.tsx (4)
src/components/Setup/Setup.utils.ts (3)
getDeviceTypeForLogic
(31-40)isDeviceOsSupported
(15-28)isLikelyWebview
(4-12)src/components/Setup/Setup.types.ts (2)
ScreenId
(1-11)BeforeInstallPromptEvent
(51-58)src/redux/slices/setup-slice.ts (1)
setupActions
(50-50)src/components/Global/Icons/Icon.tsx (1)
IconName
(51-98)
src/components/Global/IOSInstallPWAModal/index.tsx (2)
src/components/Global/Icons/Icon.tsx (1)
Icon
(155-164)src/components/Global/ActionModal/index.tsx (1)
ActionModalButtonProps
(8-11)
🪛 Biome (1.9.4)
src/components/Setup/Views/InstallPWA.tsx
[error] 46-46: Avoid redundant double-negation.
It is not necessary to use double-negation when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant double-negation
(lint/complexity/noExtraBooleanCast)
[error] 182-221: This case is falling through to the next case.
Add a break
or return
statement to the end of this case to prevent fallthrough.
(lint/suspicious/noFallthroughSwitchClause)
src/components/TransactionDetails/TransactionDetailsDrawer.tsx
[error] 225-235: Avoid using unnecessary Fragment.
A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment
(lint/complexity/noUselessFragments)
src/components/Setup/components/SetupWrapper.tsx
[error] 101-101: Avoid redundant double-negation.
It is not necessary to use double-negation when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant double-negation
(lint/complexity/noExtraBooleanCast)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: Deploy-Preview
🔇 Additional comments (79)
src/components/Profile/components/ProfileHeader.tsx (1)
18-18
: Well-implemented conditional share button feature.The addition of the
showShareButton
prop with a default value oftrue
maintains backward compatibility while allowing fine-grained control over the share button visibility. The conditional rendering is clean and follows React best practices.Also applies to: 21-27, 46-62
src/services/users.ts (1)
28-29
: LGTM: Type extension for transaction totals.The addition of
totalUsdSent
andtotalUsdReceived
properties to theApiUser
type is well-aligned with the UI requirements in PublicProfile.tsx.src/components/Profile/components/PublicProfile.tsx (3)
35-37
: LGTM: State management for transaction totals.The state variables are properly initialized and the
useAuth
hook integration follows the established pattern.
52-53
: LGTM: API data integration.The transaction totals are correctly set from the API response data.
73-79
: LGTM: Proper use of ProfileHeader with disabled share button.The integration correctly utilizes the new
showShareButton={false}
prop to disable the share functionality in the public profile context.src/components/0_Bruddle/Button.tsx (1)
43-43
: LGTM! Button variant styling update looks good.The change from
'bg-primary-3'
to'bg-white'
for the'primary-soft'
variant aligns with the broader UI updates mentioned in the PR.src/components/TransactionDetails/TransactionAvatarBadge.tsx (1)
83-84
: Excellent implementation of the new dual-shade color model.The transition from single background color to using
lightShade
for background anddarkShade
for text color maintains proper contrast while aligning with the refactored color utility structure.src/components/User/UserCard.tsx (2)
2-2
: Good addition of color constant import for maintainability.Adding
AVATAR_TEXT_DARK
to the imports improves code maintainability by replacing hardcoded color values with named constants.
55-59
: Excellent implementation of the dual-shade color model with improved consistency.The transition to using
lightShade
/darkShade
from the new color utility structure is well-implemented. The use of theAVATAR_TEXT_DARK
constant instead of hardcoded#FFD700
improves maintainability and provides better semantic meaning.src/components/Global/PeanutActionDetailsCard/index.tsx (1)
5-5
: LGTM: Import addition aligns with dual-shade color system.The import of
AVATAR_TEXT_DARK
is consistent with the new color utility structure.src/utils/color.utils.ts (3)
7-35
: Excellent refactor to dual-shade color system.The transition from single hex colors to objects with
lightShade
anddarkShade
properties is a well-designed improvement that provides better flexibility for creating consistent color hierarchies across the UI.
51-69
:✅ Verification successful
Approve function refactor with return type change.
The updated
getColorForUsername
function correctly implements the dual-shade system. This is a breaking change that requires updating all call sites to use the new object structure instead of the previous single string return value.Verify that all existing usages of
getColorForUsername
have been updated to handle the new return type:
🏁 Script executed:
#!/bin/bash # Search for any remaining usages that might expect the old string return type rg -A 5 -B 2 "getColorForUsername.*\." --type ts --type tsxLength of output: 89
🏁 Script executed:
#!/bin/bash # Search for all usages of getColorForUsername across .ts and .tsx files rg "getColorForUsername" -g '*.ts' -g '*.tsx' -nLength of output: 2032
🏁 Script executed:
#!/bin/bash # Show context around usage in TransactionAvatarBadge to verify handling of returned object rg -A5 -B5 "getColorForUsername" -n src/components/TransactionDetails/TransactionAvatarBadge.tsxLength of output: 981
All usages updated to the new return type
I’ve verified that every call site now accesses the returned object’s
darkShade
andlightShade
properties instead of expecting a single string. No instances ofgetColorForUsername(...)
being used as a plain string remain.Checked files:
- src/components/AddWithdraw/components/AddWithdrawCountriesList.tsx
- src/components/Profile/AvatarWithBadge.tsx
- src/components/Global/PeanutActionDetailsCard/index.tsx
- src/components/User/UserCard.tsx
- src/components/TransactionDetails/TransactionAvatarBadge.tsx
38-39
:❓ Verification inconclusive
Verify hardcoded color values align with design system.
The hardcoded
AVATAR_LINK_BG
value#FF90E8
and the use ofyellow.darkShade
forAVATAR_WALLET_BG
should be consistent with the design system.
🏁 Script executed:
#!/bin/bash # Search for any remaining references to old color constants that might need updating rg -A 3 -B 3 "AVATAR_(LINK|WALLET)_BG|backgroundColor.*getColorForUsername" --type ts --type tsxLength of output: 126
To catch all occurrences and inspect your color tokens, let’s broaden the search (the previous
--type tsx
flag isn’t recognized here).
🏁 Script executed:
#!/bin/bash # 1) Look for any usage of the AVATAR constants or getColorForUsername across .ts/.tsx rg 'AVATAR_(LINK|WALLET)_BG|backgroundColor.*getColorForUsername' -g '*.ts' -g '*.tsx' -A 3 -B 3 # 2) Locate where COLORS_MAPPING is defined to confirm the yellow.darkShade value rg 'export const COLORS_MAPPING' -g '*.ts' -A 5 # 3) Check if the hardcoded hex #FF90E8 appears elsewhere (e.g. design tokens JSON) rg '#FF90E8' -g '*.json' -g '*.ts' -g '*.tsx'Length of output: 6803
Verify avatar background colors against design tokens
Please confirm that both hardcoded and mapped values align with the design system:
- In
src/utils/color.utils.ts
:
AVATAR_LINK_BG = '#FF90E8'
(also used as the caret color insrc/components/SearchUsers/SearchInput.tsx
). Ensure this hex matches the official “link” color token, and if so, replace it with that token instead of hardcoding.AVATAR_WALLET_BG = COLORS_MAPPING.yellow.darkShade
. Verify thatyellow.darkShade
corresponds to the spec’d wallet/avatar background color and update the mapping if it doesn’t.src/hooks/useTransactionHistory.ts (1)
169-173
: LGTM! Consistent link generation for DIRECT_SEND transactions.The addition of link generation for
DIRECT_SEND
transactions follows the exact same pattern as theREQUEST
case, ensuring consistency in how transaction links are constructed across different transaction types.src/components/Claim/Claim.consts.ts (1)
59-60
: LGTM! Clean interface extension for external wallet functionality.The addition of
claimToExternalWallet
state and setter follows standard React patterns and clearly extends the interface to support external wallet claiming functionality.src/components/Claim/Claim.tsx (3)
54-54
: LGTM! External wallet state added consistently.The new
claimToExternalWallet
state variable aligns with the interface changes and follows React state management patterns.
273-274
: LGTM! Props correctly passed to FlowManager.The new
claimToExternalWallet
state and setter are properly passed to theFlowManager
component, maintaining the data flow consistency.
281-281
: LGTM! Component replacement aligns with UI refactor.The replacement of
TransactionDetailsDrawer
withTransactionDetailsReceipt
is consistent with the component restructuring seen across multiple files, properly separating the drawer container from the receipt content.src/app/[...recipient]/client.tsx (4)
258-262
: LGTM! Improved username resolution with fallback chain.The enhanced username resolution provides a robust fallback chain:
recipientAccount?.user?.username
→recipientAccount?.identifier
→chargeDetails.requestLink.recipientAddress
, ensuring a display value is always available.
262-262
: LGTM! Clear user role determination.The
originalUserRole
variable clearly determines whether the current user is the recipient or sender, improving code readability and logic clarity.
274-276
: LGTM! Refined link transaction logic.The
isLinkTransaction
flag is now more precise, only set to true when the original user role is SENDER and matches the current user. The explicit setting oforiginalUserRole
improves transaction context tracking.
402-403
: LGTM! Proper conditional rendering with new component.The conditional rendering correctly checks if the drawer is open and the selected transaction matches before rendering the
TransactionDetailsReceipt
component, maintaining the intended UI behavior.src/components/TransactionDetails/TransactionDetailsDrawer.tsx (1)
31-78
: Well-structured component separationThe refactoring to separate the drawer container from the receipt content is a good architectural improvement. The addition of dynamic height calculation and internal loading state management enhances the user experience.
src/components/Claim/Link/Initial.view.tsx (1)
571-573
: Good UX improvements for username recipientsThe disabled state for TokenSelector and the informative text for username recipients clearly communicate the constraints to users. This improves the user experience by setting proper expectations.
Also applies to: 605-609
src/components/Global/ErrorAlert/index.tsx (6)
1-1
: Good addition of twMerge for flexible styling.The import of
twMerge
supports the enhanced styling flexibility introduced in this refactor.
5-7
: Enhanced props interface with better typing.The updated props interface improves the component's flexibility by:
- Removing the unused
label
prop- Adding
className
with proper TypeScript typing- Adding
iconSize
andiconClassName
for icon customization
11-11
: Good default value for iconSize.The default
iconSize
of 16 provides a reasonable baseline while allowing customization.
13-13
: Proper use of twMerge for class composition.The implementation correctly uses
twMerge
to combine default classes with optional custom classes, allowing for proper Tailwind CSS class overrides.
14-14
: Good icon styling implementation.The icon implementation properly:
- Uses the configurable
iconSize
prop- Applies
twMerge
for flexible class composition- Maintains proper spacing with
mt-0.5 min-w-fit
15-15
: Simplified description styling is appropriate.Removing explicit font classes from the description div allows it to inherit styling from the container, which is cleaner and more maintainable.
src/app/(mobile-ui)/history/layout.tsx (1)
6-6
: Title shortened appropriately for mobile UI.The change from "Transaction History | Peanut" to "History | Peanut" is appropriate for mobile UI, providing a more concise title while maintaining clarity. The description on line 7-8 still provides the full context for SEO purposes.
src/assets/peanut/index.ts (1)
10-10
: New asset export follows established pattern.The addition of
PEANUTMAN_WAVING
follows the established naming convention and export pattern used for other Peanut assets in this file.src/components/AddMoney/views/NetworkSelection.view.tsx (1)
38-38
: LGTM! Layout alignment improvement.The addition of
self-start
class improves the component's alignment behavior within its parent flex/grid container, ensuring consistent layout positioning.src/interfaces/interfaces.ts (1)
377-377
: LGTM! Well-structured PWA tracking addition.The
hasPwaInstalled
boolean property provides clear tracking of PWA installation status in the user profile, supporting the new PWA functionality being introduced.src/app/(mobile-ui)/layout.tsx (1)
75-81
: LGTM! Code quality improvement.Adding curly braces around the return statement improves code readability and ensures proper block scoping while maintaining the same functional behavior.
src/utils/general.utils.ts (1)
707-707
: LGTM! Consistent PWA preference tracking.The optional
isPwaInstalled
property appropriately extends user preferences to track PWA installation status, complementing the similar addition to the user profile interface.src/context/kernelClient.context.tsx (2)
125-125
: LGTM: Correct import addition for logout functionality.The addition of
logoutUser
to the destructuring is necessary for the new logout call below and follows the existing pattern.
132-135
:✅ Verification successful
Good defensive programming to prevent mixed authentication states.
Explicitly calling
logoutUser()
when no WebAuthn key is found prevents inconsistent authentication state. The logic is sound and the comment clearly explains the intent.Verify that this logout call doesn't create any circular dependencies or infinite loops:
🏁 Script executed:
#!/bin/bash # Description: Check for potential circular dependencies between KernelClientProvider and logout functionality # Search for logoutUser implementations and calls to understand the flow ast-grep --pattern 'const logoutUser = $_' echo "=== logoutUser implementations ===" # Search for any useEffect or initialization that might conflict rg -A 5 -B 5 "logoutUser\(\)" src/context/ echo "=== logoutUser calls in context files ===" # Check if logout clears localStorage items that might trigger this useEffect again rg -A 3 -B 3 "removeItem.*web.*authn" src/Length of output: 3663
Logout logic is safe and free of loops
The
useEffect
inkernelClient.context.tsx
runs only once on mount (empty dependency array), so callinglogoutUser()
won’t re-trigger that effect. Additionally,logoutUser
ends with arouter.replace('/setup')
rather than a state change in this component, so the provider won’t remount and no infinite loop or circular dependency occurs.Great work—this change can be approved.
src/app/manifest.ts (1)
34-45
: Excellent PWA best practice implementation.Adding icons with
purpose: 'any'
alongside the existingpurpose: 'maskable'
icons ensures optimal compatibility across different platforms and devices. This follows PWA manifest best practices where:
maskable
icons work well with Android's adaptive/themed iconsany
purpose icons serve as fallbacks for other platformspublic/.well-known/assetlinks.json (1)
1-16
:✅ Verification successful
Correctly implemented Android Digital Asset Links for PWA support.
The assetlinks.json file is properly structured for Android PWA integration:
query_webapk
permission enables checking WebAPK installation statushandle_all_urls
permission allows the PWA to handle domain URLs- JSON syntax and structure follow Google's Digital Asset Links specification
Verify that the manifest URL is accessible and matches the actual manifest location:
🏁 Script executed:
#!/bin/bash # Description: Verify the manifest URL referenced in assetlinks.json is accessible # Check if the manifest URL returns a valid response curl -s -o /dev/null -w "%{http_code}" "https://peanut.me/manifest.webmanifest" echo "HTTP status code for manifest URL" # Also check the site URL curl -s -o /dev/null -w "%{http_code}" "https://peanut.me" echo "HTTP status code for main site URL"Length of output: 300
Asset Links Validated – PWA Integration Approved
The
assetlinks.json
file is correctly structured for Android PWA support, and the referenced URLs are accessible:
- https://peanut.me/manifest.webmanifest → HTTP 200
- https://peanut.me → HTTP 200
No further changes required.
src/context/authContext.tsx (3)
2-2
: LGTM: Necessary imports for enhanced logout functionality.The added imports support the logout improvements:
useToast
- ensures toast notifications work properlyuseQueryClient
- for query cache invalidation during logoutcaptureException
- for improved error reporting with SentryAlso applies to: 9-9, 12-12
160-163
: Good session management for PWA prompt state.Clearing the iOS PWA prompt session flag on logout ensures that the prompt can be shown again in new sessions. The browser environment check prevents SSR issues.
172-172
: Enhanced error reporting with Sentry integration.Adding
captureException(error)
improves error observability for logout failures while maintaining existing user feedback through console logs and toast notifications.src/hooks/useZeroDev.ts (3)
22-31
: LGTM! Excellent addition of custom error class.The
PasskeyError
class provides structured error handling with error codes, which will improve error reporting and user experience throughout the authentication flow.
42-42
: Good catch fixing the typo.Fixed
DOMAIM
toDOMAIN
in the comment.
89-101
: Excellent error handling improvements.The enhanced error handling provides better user experience by:
- Specifically handling
NotAllowedError
(user canceled) with a helpful message andLOGIN_CANCELED
code- Providing generic error handling with
LOGIN_ERROR
code for other failures- Maintaining consistent error structure with the new
PasskeyError
classThis aligns well with the error handling patterns mentioned in the AI summary for setup flow components.
src/components/Setup/Views/SetupPasskey.tsx (1)
53-76
: LGTM! Good UI restructuring and button text improvement.The nested div structure provides better layout control and spacing. Changing the button text from "Add a Passkey" to "Set it up" is more concise and user-friendly.
src/components/Setup/Setup.types.ts (4)
8-8
: LGTM! Good addition of new screen type.Adding the
'android-initial-pwa-install'
screen type supports the new Android PWA installation flow.
13-13
: LGTM! Layout type update aligns with new flow.Removing
'welcome'
and adding'android-initial-pwa-install'
to the LayoutType properly supports the updated setup flow structure.
27-27
: LGTM! Consistent ScreenProps update.Adding the corresponding
ScreenProps
entry maintains type consistency.
47-48
: LGTM! Useful addition of styling class properties.The optional
titleClassName
andcontentClassName
properties provide flexibility for customizing setup step styling.src/app/(mobile-ui)/home/page.tsx (5)
8-8
: LGTM! Clean import additions for new modal components.The imports for
IOSInstallPWAModal
andAddMoneyPromptModal
are properly added.Also applies to: 26-26
43-44
: LGTM! Appropriate state management for modals.Clean state initialization for both modal visibility controls.
81-97
: LGTM! Comprehensive iOS PWA install detection.The detection logic is well-implemented:
- Proper iOS device detection including iPad with MacIntel platform
- Checks standalone mode to avoid showing in PWA
- Uses session storage to prevent showing multiple times
- Respects user preference
hasPwaInstalled
This provides a good user experience without being intrusive.
99-115
: LGTM! Smart add money prompt logic with proper prioritization.The logic is well-designed:
- Shows only when balance is zero
- Respects session storage to avoid spam
- Properly prioritizes iOS PWA modal over add money prompt
- Works across all devices/display modes when appropriate
The comments clearly explain the conditions, making the code maintainable.
171-175
: LGTM! Clean modal rendering with proper controls.Both modals are properly integrated with their respective visibility state and close handlers.
src/components/Setup/Views/Welcome.tsx (4)
1-1
: LGTM: Correct Next.js client directive.The 'use client' directive is properly placed for a component using client-side hooks.
22-22
: Good fix: Complete useEffect dependency array.Adding
push
to the dependency array resolves the React Hook exhaustive-deps ESLint warning and ensures proper behavior if the router instance changes.
24-33
: Excellent centralized error handling implementation.The
handleError
function properly:
- Provides user-friendly error messages for specific error codes
- Includes fallback for unexpected errors
- Integrates with Sentry for error tracking with contextual information
This is a significant improvement over inline error handling.
38-46
: UI improvements with consistent styling.The button updates improve the user experience:
- Consistent
shadowSize="4"
andh-11
height across buttons- New
variant="primary-soft"
provides visual hierarchy- "Create your wallet" text is more descriptive than generic "Sign up"
src/components/Setup/Views/Signup.tsx (7)
1-2
: Good component swap for improved error UX.Replacing the generic
Card
import with the specializedErrorAlert
component will provide better error presentation with consistent styling across the app.
103-105
: UI simplification improves maintainability.Removing the
Card
wrapper and using fragment with styled divs creates a cleaner, more flexible layout structure.
108-108
: Improved placeholder text for clarity."Enter a username" is more direct and actionable than "Choose your username".
115-122
: Good button improvements.The changes enhance UX:
- Consistent width (
w-4/12
) and height (h-12
)- Loading state tied to actual operation (
isLoading
instead ofisChanging
)- "Next" is more appropriate for a multi-step flow than "Create"
124-128
: Enhanced error presentation.Using
ErrorAlert
with customizable props (className
,iconSize
) provides consistent error styling and better visual hierarchy than plain paragraphs.
138-140
: Improved link accessibility.Separating "T&C" and "Privacy Policy" into individual underlined spans makes it clearer that both are clickable links, improving user understanding.
42-44
:❓ Verification inconclusive
Breaking change: Username validation regex excludes underscores.
The regex change from presumably allowing underscores to explicitly disallowing them (
^[a-z][a-z0-9]{3,11}$
) could affect existing users with underscore-containing usernames.Please verify that this change is intentional and that existing users with underscores in their usernames are properly handled:
🏁 Script executed:
#!/bin/bash # Search for any existing user validation or migration logic rg -A 5 -B 5 "username.*underscore|underscore.*username" rg -A 5 -B 5 "^[a-z][a-z0-9_]"Length of output: 91951
Please confirm underscore handling in username validation
I see the signup form now uses
username.match(/^[a-z][a-z0-9]{3,11}$/)
, which prohibits underscores. I did not find any migration, normalization, or backend‐aligned logic to handle existing usernames containing underscores. This may block current users whose usernames include_
.• File:
src/components/Setup/Views/Signup.tsx
(lines 42–44)
• Regex now disallows_
, but no fallback or migration exists
• No other validation or normalization for_
in the codebaseCan you verify that:
- The backend validation rule also forbids underscores?
- Any existing underscore‐based usernames are migrated or otherwise handled?
- Documentation and UI error messages are updated to reflect this stricter rule?
src/components/Home/AddMoneyPromptModal/index.tsx (5)
8-11
: Clean and appropriate interface design.The
AddMoneyPromptModalProps
interface is well-defined with the essential props for modal control (visible
for state,onClose
for callback).
16-19
: Proper navigation and cleanup logic.The
handleAddMoney
function correctly:
- Navigates to the add-money page
- Closes the modal to prevent UI conflicts
- Uses Next.js router push for client-side navigation
21-34
: Well-structured CTA button configuration.The button array follows the
ActionModalButtonProps
interface correctly with:
- Clear action-oriented text ("Add money now" vs "I'll do it later")
- Appropriate styling variants (primary vs transparent)
- Proper event handlers for each action
36-45
: User-friendly content structure.The title and description provide clear context:
- Direct title explains the action needed
- Description explains why funding is necessary
- Line breaks improve readability
48-61
: Comprehensive ActionModal configuration.The modal is properly configured with:
- Custom icon styling to remove default container constraints
- Appropriate text styling classes
- Hidden close button to enforce CTA interaction
- Content padding adjustments for better visual presentation
src/components/Setup/Setup.utils.ts (3)
4-12
: Robust webview detection with PWA consideration.The
isLikelyWebview
function correctly:
- Handles undefined navigator (SSR scenarios)
- Excludes standalone PWAs from webview classification
- Uses case-insensitive regex matching against known signatures
- Provides proper fallback behavior
This prevents false positives for legitimate PWA usage.
15-28
: Comprehensive OS version validation.The
isDeviceOsSupported
function properly:
- Handles missing user agent gracefully
- Parses Android versions correctly with flexible decimal handling
- Supports both iPhone OS and iPad CPU OS patterns for iOS
- Uses appropriate minimum version requirements (Android 9+, iOS 16+)
- Defaults to supported for unknown OS types
The regex patterns cover the common user agent variations.
31-40
: Thorough device type detection.The
getDeviceTypeForLogic
function correctly:
- Handles missing user agent with desktop fallback
- Detects iPad with touch support (important for newer iPads reporting as Mac)
- Uses case-insensitive Android detection
- Provides clear return type options
The MacIntel check for iPad is essential since newer iPads can report as Mac in their user agent.
src/components/Setup/Views/InstallPWA.tsx (2)
16-96
: Well-structured PWA installation handling.Good implementation with:
- Device-specific installation flows
- Proper error handling and user feedback
- Clean state management for installation progress
🧰 Tools
🪛 Biome (1.9.4)
[error] 46-46: Avoid redundant double-negation.
It is not necessary to use double-negation when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant double-negation(lint/complexity/noExtraBooleanCast)
179-182
:⚠️ Potential issueAdd missing break statement to prevent unintended fallthrough.
The
android-initial-pwa-install
case is missing a break statement, causing it to fall through to thepwa-install
case.case 'android-initial-pwa-install': return <AndroidPWASpecificInstallFlow /> + break case 'pwa-install':
Likely an incorrect or invalid review comment.
src/components/Setup/components/SetupWrapper.tsx (2)
38-42
: Good addition of Android-specific layout type.The new
android-initial-pwa-install
layout type is well-integrated with appropriate responsive styling.
21-25
: Excellent addition of granular styling controls.The new
titleClassName
,contentClassName
, and refinedimageClassName
props provide good flexibility for component customization while maintaining backward compatibility.Also applies to: 224-231
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LFG
No description provided.