-
Notifications
You must be signed in to change notification settings - Fork 437
feat: improve banner logic #2693
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
base: main
Are you sure you want to change the base?
Conversation
The latest updates on your projects. Learn more about Vercel for GitHub.
|
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.
Pull Request Overview
This PR improves the banner display logic to prevent brief flashing of incorrect banners and adds support for Arbitrum limit orders campaigns. The changes ensure that only the intended banner for the user's selected or intended chain is shown, rather than showing all configured campaigns.
- Modified banner selection logic to show only the intended chain's campaign instead of all available campaigns
- Added support for Arbitrum limit orders banner campaign
- Introduced logic to determine the intended chain ID based on localStorage and URL parameters
Reviewed Changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
File | Description |
---|---|
src/layouts/TopBarNotify.tsx | Updated to use campaign-specific chain ID for localStorage operations instead of current chain ID |
src/layouts/MainLayout.tsx | Added intended chain ID detection logic and filtering to show only relevant campaigns |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
src/layouts/TopBarNotify.tsx
Outdated
const firstChainId = chainIds[0]; | ||
return firstChainId ? campaigns[firstChainId] || null : null; |
Copilot
AI
Oct 2, 2025
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.
The logic assumes the first chain ID from Object.keys() is the intended campaign, but Object.keys() order is not guaranteed to be consistent. This could lead to unpredictable banner selection when multiple campaigns are available.
const firstChainId = chainIds[0]; | |
return firstChainId ? campaigns[firstChainId] || null : null; | |
if (chainIds.length === 0) return null; | |
if (currentChainId && campaigns[currentChainId]) { | |
return campaigns[currentChainId]; | |
} | |
// fallback: select the campaign with the lowest chainId | |
const minChainId = Math.min(...chainIds); | |
return campaigns[minChainId] || null; |
Copilot uses AI. Check for mistakes.
src/layouts/MainLayout.tsx
Outdated
const filteredCampaigns: NetworkCampaigns = isCampaignChainId(intendedChainId) | ||
? { [intendedChainId]: campaignConfigs[intendedChainId]! } | ||
: {}; |
Copilot
AI
Oct 2, 2025
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.
Using non-null assertion operator (!) without proper null checking could cause runtime errors if campaignConfigs[intendedChainId] is undefined. Consider using optional chaining or explicit null checking.
const filteredCampaigns: NetworkCampaigns = isCampaignChainId(intendedChainId) | |
? { [intendedChainId]: campaignConfigs[intendedChainId]! } | |
: {}; | |
const campaign = campaignConfigs[intendedChainId]; | |
const filteredCampaigns: NetworkCampaigns = | |
isCampaignChainId(intendedChainId) && campaign !== undefined | |
? { [intendedChainId]: campaign } | |
: {}; |
Copilot uses AI. Check for mistakes.
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.
💡 Codex Review
Here are some automated review suggestions for this pull request.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting
src/layouts/MainLayout.tsx
Outdated
const campaignConfigs = getCampaignConfigs(openSwitch, openMarket); | ||
|
||
const intendedChainId = getIntendedChainId(); | ||
|
||
const isCampaignChainId = (chainId: ChainId): chainId is CampaignChainId => { | ||
return chainId in campaignConfigs; | ||
}; | ||
|
||
const filteredCampaigns: NetworkCampaigns = isCampaignChainId(intendedChainId) | ||
? { [intendedChainId]: campaignConfigs[intendedChainId]! } | ||
: {}; |
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.
Keep banner campaigns in sync with market changes
The new filteredCampaigns
is derived from getIntendedChainId()
using only localStorage/URL and is computed once in MainLayout
. Because this component subscribes only to setCurrentMarket
, it never re-renders when the user switches markets or when a marketName
query param overrides a stale localStorage value. Meanwhile TopBarNotify
now shows the first entry it receives, so after the initial render the banner stays locked to whatever chain was chosen at load time (e.g. start on mainnet, switch to Base, but the mainnet campaign continues to display). The banner logic therefore regresses compared to before. Consider deriving the campaign from the store’s currentChainId
or recomputing filteredCampaigns
when the selected market changes.
Useful? React with 👍 / 👎.
|
📦 Next.js Bundle Analysis for aave-uiThis analysis was generated by the Next.js Bundle Analysis action. 🤖 This PR introduced no changes to the JavaScript bundle! 🙌 |
|
📦 Next.js Bundle Analysis for aave-uiThis analysis was generated by the Next.js Bundle Analysis action. 🤖 This PR introduced no changes to the JavaScript bundle! 🙌 |
|
📦 Next.js Bundle Analysis for aave-uiThis analysis was generated by the Next.js Bundle Analysis action. 🤖 This PR introduced no changes to the JavaScript bundle! 🙌 |
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.
Pull Request Overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
src/layouts/TopBarNotify.tsx
Outdated
}; | ||
|
||
const currentCampaign = getCurrentCampaign(); | ||
const campaignChainId = currentChainId; |
Copilot
AI
Oct 2, 2025
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.
The variable campaignChainId
is redundant as it simply aliases currentChainId
. Consider removing this variable and using currentChainId
directly throughout the component to reduce unnecessary indirection.
Copilot uses AI. Check for mistakes.
src/layouts/TopBarNotify.tsx
Outdated
// Use stored preference for this chain | ||
setShowWarning(warningBarOpen !== 'false'); | ||
} | ||
}, [currentCampaign, campaignChainId, currentChainId]); |
Copilot
AI
Oct 2, 2025
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.
The dependency array includes both campaignChainId
and currentChainId
which are the same value. Since campaignChainId
is just an alias for currentChainId
, only currentChainId
should be included in the dependency array.
}, [currentCampaign, campaignChainId, currentChainId]); | |
}, [currentCampaign, currentChainId]); |
Copilot uses AI. Check for mistakes.
|
📦 Next.js Bundle Analysis for aave-uiThis analysis was generated by the Next.js Bundle Analysis action. 🤖 This PR introduced no changes to the JavaScript bundle! 🙌 |
src/layouts/MainLayout.tsx
Outdated
}; | ||
|
||
const campaignConfigs = getCampaignConfigs(openMarket); | ||
const campaignConfigs = getCampaignConfigs(openSwitch, openMarket); |
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.
would move getCampaignConfigs to a hook useBannerCampaigns so we can get openSwitch (or others in the future) right in there and just pass the chain id
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.
done in 33af445
src/layouts/MainLayout.tsx
Outdated
icon: string; | ||
} | ||
|
||
type CampaignChainId = ChainId.base | ChainId.mainnet | ChainId.arbitrum_one; |
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.
why not just use generic ChainId if down here we use Partial of chains ids
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.
yeah good point 33af445
src/layouts/MainLayout.tsx
Outdated
buttonText: string; | ||
buttonAction: ButtonAction; | ||
bannerVersion: string; | ||
icon: string; |
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.
does it make sense to make the icon optional for future solo-text campaings
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.
yes 33af445
src/layouts/MainLayout.tsx
Outdated
// Priority 3: URL params marketName | ||
const urlMarket = getQueryParameter('marketName'); | ||
if (urlMarket && marketsData[urlMarket as CustomMarket]) { | ||
return marketsData[urlMarket as CustomMarket].chainId; | ||
} |
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.
shouldn't this be prioritized e.g. someone opens a shared link but been using other network
src/layouts/MainLayout.tsx
Outdated
// icon: '/icons/networks/arbitrum.svg', | ||
// }, | ||
[ChainId.arbitrum_one]: { | ||
notifyText: 'Limit orders are now live on Arbitrum', |
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.
not sure how translations work but can we ensure banner messages will be translated this way? otherwise we can set notifyText type as react node and just use
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.
i see
` {currentCampaign.notifyText}
`
just checking if it's enough
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.
yeah we dont really use translations much but added b2f5f50
src/layouts/MainLayout.tsx
Outdated
openMarket: (market: CustomMarket) => void | ||
) => ({ | ||
): CampaignConfigs => ({ | ||
[ChainId.base]: { |
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.
nit/v2: we can leverage vercel configs or amplitude feature flags to automatically change campaings without commiting new code
useEffect(() => { | ||
if (showWarning) { | ||
const timer = setTimeout(() => { | ||
setSlideIn(true); | ||
}, 100); | ||
|
||
return () => clearTimeout(timer); | ||
} else { | ||
setSlideIn(false); | ||
} | ||
}, [currentCampaign, currentChainId]); | ||
}, [showWarning]); |
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.
cant this be replaced by a showWarning fn that has the timeout inside?
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.
General Changes
Developer Notes
Add any notes here that may be helpful for reviewers.
Reviewer Checklist
Please ensure you, as the reviewer(s), have gone through this checklist to ensure that the code changes are ready to ship safely and to help mitigate any downstream issues that may occur.
.env.example
file as well as the pertinant.github/actions/*
files