Skip to content

feat(pro): redesign Pro detail screen and settings banner#371

Merged
dishit-wednesday merged 5 commits into
mainfrom
change-pro-banner-ui
May 20, 2026
Merged

feat(pro): redesign Pro detail screen and settings banner#371
dishit-wednesday merged 5 commits into
mainfrom
change-pro-banner-ui

Conversation

@dishit-wednesday

Copy link
Copy Markdown
Collaborator
  • Rebuild ProDetailScreen with hero section, dark promo banner, integration grid, and CTA
  • Add persistent dismissible Pro banner to top of SettingsScreen
  • Add Pro nav button (zap icon + PRO badge) in settings list
  • Persist banner dismissed state to AsyncStorage via appStore

Summary

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Refactor (code change that neither fixes a bug nor adds a feature)
  • Chore (build process, CI, dependency updates, etc.)

Screenshots / Screen Recordings

Android

Before After

iOS

Before After

Checklist

General

  • My code follows the project's coding style and conventions
  • I have performed a self-review of my code
  • I have added/updated comments where the logic isn't self-evident
  • My changes generate no new warnings or errors

Testing

  • I have tested on Android (physical device or emulator)
  • I have tested on iOS (physical device or simulator)
  • I have tested in light mode and dark mode
  • Existing tests pass locally (npm test)
  • I have added tests that prove my fix is effective or my feature works

React Native Specific

  • No new native module without corresponding platform implementation (Android + iOS)
  • New native modules are added to the Xcode project build target (project.pbxproj)
  • No hardcoded pixel values — uses SPACING / TYPOGRAPHY constants from the theme
  • Styles use useThemedStyles pattern (not inline or static StyleSheet.create)
  • Animations/gestures work smoothly on both platforms
  • Large lists use FlatList / FlashList (not .map() inside ScrollView)
  • No unnecessary re-renders introduced (check with React DevTools Profiler if unsure)

Performance & Models

  • Downloads / long-running tasks report progress to the UI
  • File paths are resolved correctly on both platforms (no hardcoded / vs \\)
  • Large files (models, assets) are not committed to the repository

Security

  • No secrets, API keys, or credentials are included in the code
  • User input is validated/sanitized where applicable

Related Issues

Additional Notes

- Rebuild ProDetailScreen with hero section, dark promo banner,
  integration grid, and CTA
- Add persistent dismissible Pro banner to top of SettingsScreen
- Add Pro nav button (zap icon + PRO badge) in settings list
- Persist banner dismissed state to AsyncStorage via appStore

@greptile-apps greptile-apps Bot 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.

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request redesigns the Pro Detail screen with a new hero section, promo banner, and integrations grid, while also introducing a dismissible PRO banner to the Settings screen. The appStore was updated to persist the banner's dismissal state. Feedback focuses on restoring the missing back button on the Pro Detail screen, avoiding hardcoded hex colors and percentage-based layout hacks, and removing unused style definitions. Additionally, it is recommended to use a more flexible grid layout for integrations and to increase the tap target size for the banner's dismiss button to improve usability.

Comment on lines +37 to +54
<View style={styles.header}>
<View style={styles.logoRow}>
<View style={styles.logoGrid}>
<View style={styles.logoDotRow}>
<View style={styles.logoDot} />
<View style={styles.logoDot} />
</View>
<View style={styles.featureText}>
<Text style={styles.featureTitle}>{f.title}</Text>
<Text style={styles.featureDesc}>{f.desc}</Text>
<View style={styles.logoDotRow}>
<View style={styles.logoDot} />
<View style={styles.logoDot} />
</View>
</View>
))}
<Text style={styles.logoText}>Off Grid Pro</Text>
</View>
<TouchableOpacity style={styles.getProButton} onPress={handleCTA}>
<Text style={styles.getProButtonText}>Get Pro</Text>
</TouchableOpacity>
</View>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The redesigned header is missing a back button. Since this screen is part of a navigation stack, users need an explicit way to return to the previous screen (Settings). The previous implementation included an arrow-left icon for this purpose.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

The header intentionally keeps the branded logo + 'Get Pro' CTA as a marketing element on this screen — it's a landing/paywall screen, not a standard nav screen. Back navigation is handled by the iOS swipe gesture and Android hardware back button. The screen is presented with slide_from_bottom animation and headerShown: false in the navigator.

Comment on lines +82 to +103
{INTEGRATIONS.slice(0, 2).map(item => (
<View key={item.title} style={styles.gridCard}>
<View style={styles.gridIconWrap}>
<Icon name={item.icon} size={20} color={colors.textSecondary} />
</View>
<Text style={styles.gridCardTitle}>{item.title}</Text>
<Text style={styles.gridCardDesc}>{item.desc}</Text>
</View>
))}
</View>

<View style={styles.gridRow}>
{INTEGRATIONS.slice(2, 4).map(item => (
<View key={item.title} style={styles.gridCard}>
<View style={styles.gridIconWrap}>
<Icon name={item.icon} size={20} color={colors.textSecondary} />
</View>
<Text style={styles.gridCardTitle}>{item.title}</Text>
<Text style={styles.gridCardDesc}>{item.desc}</Text>
</View>
))}
</View>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Manually slicing the INTEGRATIONS array into fixed rows is fragile. If the number of integrations changes, this logic will either miss items or render empty rows. Consider using a more flexible layout approach, such as a container with flexDirection: 'row' and flexWrap: 'wrap'. Avoid creating a shared utility for this logic unless it is used in more than two places to prevent premature abstraction.

References
  1. Avoid premature abstraction. A shared utility for duplicated logic should be considered only when the logic is used in more than two places.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

The INTEGRATIONS array is intentionally fixed at 4 items — these map to the 4 core product features and won't change. Introducing flexWrap or a utility for a static 4-item list would be premature abstraction. If items are added in future, the layout can be revisited then.

Comment thread src/screens/ProDetailScreen/index.tsx Outdated
promoBanner: {
marginHorizontal: SPACING.xl,
marginBottom: SPACING.xl,
backgroundColor: '#1C2B22',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Avoid hardcoding hex colors like #1C2B22. These should be defined in the theme configuration to ensure consistency and support for potential future theme changes.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Acknowledged. The dark green (#1C2B22 / gradient stops) is a one-off branded surface for this marketing screen and doesn't belong in the general theme palette. Adding a proSurface token to the theme would be the right fix but is out of scope for this PR. Tracked for a follow-up.

Comment thread src/screens/ProDetailScreen/index.tsx Outdated
Comment on lines 359 to 385
footer: {
paddingHorizontal: SPACING.xl,
paddingTop: SPACING.xl,
borderTopWidth: 1,
borderTopColor: colors.border,
alignItems: 'center' as const,
gap: SPACING.md,
},
footerBrand: {
...TYPOGRAPHY.body,
color: colors.text,
},
footerLinks: {
flexDirection: 'row' as const,
gap: SPACING.lg,
flexWrap: 'wrap' as const,
justifyContent: 'center' as const,
},
footerLink: {
...TYPOGRAPHY.bodySmall,
color: colors.textSecondary,
},
footerCopy: {
...TYPOGRAPHY.meta,
color: colors.textMuted,
textAlign: 'center' as const,
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The footer styles and its sub-properties are defined but never used in the component's render method. Please either implement the footer UI or remove the dead style definitions.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed — dead footer styles have been removed in a follow-up commit.

Comment on lines +129 to +131
<TouchableOpacity onPress={() => setProBannerDismissed(true)} style={styles.proCloseButton}>
<Icon name="x" size={16} color={colors.textMuted} />
</TouchableOpacity>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The dismiss button for the Pro banner has a very small tap target. Interactive elements should have a minimum tap target size of at least 36px to improve usability on touch devices.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Acknowledged. The tap target is small but acceptable for a secondary dismiss action on a banner. Will revisit if flagged in user testing.

Comment thread src/screens/SettingsScreen.tsx Outdated
flexDirection: 'row' as const,
alignItems: 'center' as const,
gap: SPACING.sm,
width: '48%' as const,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Using a hardcoded percentage width (48%) for grid items is a layout hack that can lead to inconsistencies across different screen sizes. It is better to use flex: 1 on the items within a row or leverage gap with flexWrap on the parent container.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed — replaced the 48% width hack with an explicit row-based layout using flex: 1 on each item, so the grid scales correctly across all screen sizes.

@codecov

codecov Bot commented May 20, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 50.00000% with 9 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.83%. Comparing base (ecbfcd7) to head (d40373f).

Files with missing lines Patch % Lines
src/screens/ProDetailScreen/index.tsx 33.33% 4 Missing ⚠️
src/screens/SettingsScreen.tsx 66.66% 2 Missing and 1 partial ⚠️
src/screens/HomeScreen/index.tsx 50.00% 1 Missing ⚠️
src/stores/appStore.ts 0.00% 1 Missing ⚠️

❌ Your patch check has failed because the patch coverage (50.00%) is below the target coverage (80.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #371      +/-   ##
==========================================
- Coverage   82.85%   82.83%   -0.03%     
==========================================
  Files         235      235              
  Lines       12017    12027      +10     
  Branches     3283     3286       +3     
==========================================
+ Hits         9957     9962       +5     
- Misses       1203     1207       +4     
- Partials      857      858       +1     
Files with missing lines Coverage Δ
src/screens/HomeScreen/styles.ts 100.00% <ø> (ø)
src/screens/HomeScreen/index.tsx 89.28% <50.00%> (-3.31%) ⬇️
src/stores/appStore.ts 81.81% <0.00%> (-0.95%) ⬇️
src/screens/SettingsScreen.tsx 56.36% <66.66%> (+1.04%) ⬆️
src/screens/ProDetailScreen/index.tsx 23.07% <33.33%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

LinearGradient on iOS does not constrain child width like a View,
causing the banner subtitle to render on one line and overflow the
screen, and leaving a white gap below the MCP card.

- Wrap banner and MCP card contents in a View, with LinearGradient
  as an absolute-filled background
- Drop Menlo font from banner title/subtitle (system font is narrower
  and renders consistently across iOS/Android)
- Remove unused useWindowDimensions / bannerWidth calculation
@sonarqubecloud

Copy link
Copy Markdown

@dishit-wednesday dishit-wednesday merged commit 4e1ca92 into main May 20, 2026
6 of 7 checks passed
Sign up for free to 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.

1 participant