-
Notifications
You must be signed in to change notification settings - Fork 4
FIX: dark mode theme, update alert dialogs, and UI consistency improvements #72
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: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,26 +1,41 @@ | ||||||||||||||||||||||||||||||||||||||||||||
| import { NavigationContainer } from '@react-navigation/native'; | ||||||||||||||||||||||||||||||||||||||||||||
| import React from 'react'; | ||||||||||||||||||||||||||||||||||||||||||||
| import { useColorScheme } from 'react-native'; | ||||||||||||||||||||||||||||||||||||||||||||
| import { SafeAreaProvider } from 'react-native-safe-area-context'; | ||||||||||||||||||||||||||||||||||||||||||||
| import { SizeClassProvider } from './components/Context/SizeClassProvider'; | ||||||||||||||||||||||||||||||||||||||||||||
| import { SettingsProvider } from './components/Context/SettingsProvider'; | ||||||||||||||||||||||||||||||||||||||||||||
| import { BlueDefaultTheme } from './components/themes'; | ||||||||||||||||||||||||||||||||||||||||||||
| import { BlueCurrentTheme, BlueDarkTheme, BlueDefaultTheme } from './components/themes'; | ||||||||||||||||||||||||||||||||||||||||||||
| import MasterView from './navigation/MasterView'; | ||||||||||||||||||||||||||||||||||||||||||||
| import { navigationRef } from './NavigationService'; | ||||||||||||||||||||||||||||||||||||||||||||
| import { useLogger } from '@react-navigation/devtools'; | ||||||||||||||||||||||||||||||||||||||||||||
| import { StorageProvider } from './components/Context/StorageProvider'; | ||||||||||||||||||||||||||||||||||||||||||||
| import { initializeIndexer } from './blue_modules/SilentPaymentIndexer'; | ||||||||||||||||||||||||||||||||||||||||||||
| import CustomAlert, { CustomAlertHandle } from './components/CustomAlert'; | ||||||||||||||||||||||||||||||||||||||||||||
| import { setCustomAlertRef } from './components/Alert'; | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| const App = () => { | ||||||||||||||||||||||||||||||||||||||||||||
| initializeIndexer({ | ||||||||||||||||||||||||||||||||||||||||||||
| baseUrl: 'https://cushionlike-isabel-retrievable.ngrok-free.dev/', | ||||||||||||||||||||||||||||||||||||||||||||
| timeout: 100000, // 100 seconds for blockchain scanning operations (increased for slower connections) | ||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||
| const customAlertRef = React.useRef<CustomAlertHandle>(null); | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| React.useEffect(() => { | ||||||||||||||||||||||||||||||||||||||||||||
| setCustomAlertRef(customAlertRef.current); | ||||||||||||||||||||||||||||||||||||||||||||
| initializeIndexer({ | ||||||||||||||||||||||||||||||||||||||||||||
| baseUrl: 'https://cushionlike-isabel-retrievable.ngrok-free.dev/', | ||||||||||||||||||||||||||||||||||||||||||||
| timeout: 100000, // 100 seconds for blockchain scanning operations (increased for slower connections) | ||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||
| return () => setCustomAlertRef(null); | ||||||||||||||||||||||||||||||||||||||||||||
| }, []); | ||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+17
to
+26
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| const colorScheme = useColorScheme(); | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| React.useEffect(() => { | ||||||||||||||||||||||||||||||||||||||||||||
| BlueCurrentTheme.updateColorScheme(); | ||||||||||||||||||||||||||||||||||||||||||||
| }, [colorScheme]); | ||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+30
to
+32
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. dead code |
||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| useLogger(navigationRef); | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||||||||||||||
| <SizeClassProvider> | ||||||||||||||||||||||||||||||||||||||||||||
| <NavigationContainer ref={navigationRef} theme={BlueDefaultTheme}> | ||||||||||||||||||||||||||||||||||||||||||||
| <NavigationContainer ref={navigationRef} theme={colorScheme === 'dark' ? BlueDarkTheme : BlueDefaultTheme}> | ||||||||||||||||||||||||||||||||||||||||||||
| <SafeAreaProvider> | ||||||||||||||||||||||||||||||||||||||||||||
|
chaitika marked this conversation as resolved.
|
||||||||||||||||||||||||||||||||||||||||||||
| <StorageProvider> | ||||||||||||||||||||||||||||||||||||||||||||
| <SettingsProvider> | ||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -29,6 +44,7 @@ const App = () => { | |||||||||||||||||||||||||||||||||||||||||||
| </StorageProvider> | ||||||||||||||||||||||||||||||||||||||||||||
| </SafeAreaProvider> | ||||||||||||||||||||||||||||||||||||||||||||
| </NavigationContainer> | ||||||||||||||||||||||||||||||||||||||||||||
| <CustomAlert ref={customAlertRef} /> | ||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this should be mounted once at the app root level and can work globally across screens, please move this to just below |
||||||||||||||||||||||||||||||||||||||||||||
| </SizeClassProvider> | ||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,119 @@ | ||||||||||
| import React, { useCallback, useImperativeHandle, useState, forwardRef } from 'react'; | ||||||||||
| import { Modal, View, Text, TouchableOpacity, StyleSheet, AlertButton, AlertOptions, Appearance } from 'react-native'; | ||||||||||
| import { BlueDefaultTheme, BlueDarkTheme } from './themes'; | ||||||||||
|
|
||||||||||
| export interface CustomAlertHandle { | ||||||||||
| show: (title: string | undefined, message: string | undefined, buttons: AlertButton[], options: AlertOptions) => void; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| const CustomAlert = forwardRef<CustomAlertHandle>((_, ref) => { | ||||||||||
| const [visible, setVisible] = useState(false); | ||||||||||
| const [title, setTitle] = useState<string | undefined>(); | ||||||||||
| const [message, setMessage] = useState(''); | ||||||||||
| const [buttons, setButtons] = useState<AlertButton[]>([]); | ||||||||||
| const [options, setOptions] = useState<AlertOptions>({}); | ||||||||||
|
|
||||||||||
| const isDark = Appearance.getColorScheme() === 'dark'; | ||||||||||
| const colors = isDark ? BlueDarkTheme.colors : BlueDefaultTheme.colors; | ||||||||||
|
Comment on lines
+16
to
+17
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. instead of
Suggested change
|
||||||||||
|
|
||||||||||
| const dismiss = useCallback(() => setVisible(false), []); | ||||||||||
|
|
||||||||||
| useImperativeHandle(ref, () => ({ | ||||||||||
| show: (t, m, b, o) => { | ||||||||||
| setTitle(t); | ||||||||||
| setMessage(m ?? ''); | ||||||||||
| setButtons(b); | ||||||||||
| setOptions(o); | ||||||||||
| setVisible(true); | ||||||||||
| }, | ||||||||||
| })); | ||||||||||
|
|
||||||||||
| const handlePress = useCallback( | ||||||||||
| (onPress?: () => void) => { | ||||||||||
| dismiss(); | ||||||||||
| onPress?.(); | ||||||||||
| }, | ||||||||||
| [dismiss], | ||||||||||
| ); | ||||||||||
|
|
||||||||||
| const getButtonTextStyle = (style?: string) => { | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
| switch (style) { | ||||||||||
| case 'destructive': | ||||||||||
| return { color: colors.redText, fontWeight: '600' as const }; | ||||||||||
| case 'cancel': | ||||||||||
| return { color: colors.foregroundColor, fontWeight: '600' as const }; | ||||||||||
| default: | ||||||||||
| return { color: colors.primary }; | ||||||||||
| } | ||||||||||
| }; | ||||||||||
|
|
||||||||||
| return ( | ||||||||||
| <Modal transparent visible={visible} animationType="fade" onRequestClose={options.cancelable ? dismiss : undefined}> | ||||||||||
| <View style={styles.overlay}> | ||||||||||
| <View style={[styles.container, { backgroundColor: colors.elevated }]}> | ||||||||||
| {title ? <Text style={[styles.title, { color: colors.foregroundColor }]}>{title}</Text> : null} | ||||||||||
| <Text style={[styles.message, { color: colors.foregroundColor }]}>{message}</Text> | ||||||||||
| <View style={[styles.buttonRow, { borderTopColor: colors.lightBorder }]}> | ||||||||||
| {buttons.map((button, index) => ( | ||||||||||
| <TouchableOpacity | ||||||||||
| key={index} | ||||||||||
| accessibilityRole="button" | ||||||||||
| accessibilityLabel={button.text} | ||||||||||
| style={[ | ||||||||||
|
Check warning on line 62 in components/CustomAlert.tsx
|
||||||||||
| styles.button, | ||||||||||
| index > 0 && { borderLeftWidth: StyleSheet.hairlineWidth, borderLeftColor: colors.lightBorder }, | ||||||||||
|
chaitika marked this conversation as resolved.
|
||||||||||
| ]} | ||||||||||
| onPress={() => handlePress(button.onPress ?? undefined)} | ||||||||||
| > | ||||||||||
| <Text style={[styles.buttonText, getButtonTextStyle(button.style)]}>{button.text}</Text> | ||||||||||
| </TouchableOpacity> | ||||||||||
| ))} | ||||||||||
| </View> | ||||||||||
| </View> | ||||||||||
| </View> | ||||||||||
| </Modal> | ||||||||||
| ); | ||||||||||
| }); | ||||||||||
|
|
||||||||||
| const styles = StyleSheet.create({ | ||||||||||
| overlay: { | ||||||||||
| flex: 1, | ||||||||||
| backgroundColor: 'rgba(0, 0, 0, 0.5)', | ||||||||||
| justifyContent: 'center', | ||||||||||
| alignItems: 'center', | ||||||||||
| }, | ||||||||||
| container: { | ||||||||||
| width: '80%', | ||||||||||
| borderRadius: 14, | ||||||||||
| paddingTop: 20, | ||||||||||
| overflow: 'hidden', | ||||||||||
| }, | ||||||||||
| title: { | ||||||||||
| fontSize: 17, | ||||||||||
| fontWeight: '600', | ||||||||||
| textAlign: 'center', | ||||||||||
| marginBottom: 4, | ||||||||||
| paddingHorizontal: 20, | ||||||||||
| }, | ||||||||||
| message: { | ||||||||||
| fontSize: 14, | ||||||||||
| textAlign: 'center', | ||||||||||
| paddingHorizontal: 20, | ||||||||||
| paddingBottom: 20, | ||||||||||
| }, | ||||||||||
| buttonRow: { | ||||||||||
| flexDirection: 'row', | ||||||||||
| borderTopWidth: StyleSheet.hairlineWidth, | ||||||||||
| }, | ||||||||||
| button: { | ||||||||||
| flex: 1, | ||||||||||
| paddingVertical: 12, | ||||||||||
| alignItems: 'center', | ||||||||||
| justifyContent: 'center', | ||||||||||
| }, | ||||||||||
| buttonText: { | ||||||||||
| fontSize: 16, | ||||||||||
| }, | ||||||||||
| }); | ||||||||||
|
|
||||||||||
| export default CustomAlert; | ||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -411,11 +411,12 @@ | |
| "details_address": "Address", | ||
| "details_advanced": "Advanced", | ||
| "details_are_you_sure": "Are you sure?", | ||
| "delete_wallet_warning": "You'll need your seed phrase to restore access.", | ||
| "details_connected_to": "Connected to", | ||
| "details_del_wb_err": "The provided balance amount does not match this wallet’s balance. Please try again.", | ||
| "details_del_wb_q": "This wallet has a balance. Before proceeding, please be aware that you will not be able to recover the funds without this wallet’s seed phrase. In order to avoid accidental removal, please enter your wallet’s balance of {balance} satoshis.", | ||
| "details_delete": "Delete", | ||
| "details_delete_wallet": "Delete Wallet", | ||
| "details_delete_wallet": "⚠️ Delete Wallet?", | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. get rid of the emoji here. localization files carry text context |
||
| "details_derivation_path": "derivation path", | ||
| "details_display": "Display in Home Screen", | ||
| "details_export_backup": "Export/Backup", | ||
|
|
@@ -427,7 +428,7 @@ | |
| "details_title": "Wallet", | ||
| "details_type": "Type", | ||
| "details_use_with_hardware_wallet": "Use with Hardware Wallet", | ||
| "details_yes_delete": "Yes, delete", | ||
| "details_yes_delete": "Delete", | ||
| "enter_bip38_password": "Enter password to decrypt", | ||
| "export_title": "Wallet Export", | ||
| "import_do_import": "Import", | ||
|
|
@@ -465,6 +466,7 @@ | |
| "list_title": "Wallets", | ||
| "list_tryagain": "Try again", | ||
| "no_ln_wallet_error": "Before paying a Lightning invoice, you must first add a Lightning wallet.", | ||
| "no_wallet_to_delete": "No wallet available to delete", | ||
| "looks_like_bip38": "This looks like a password-protected private key (BIP38).", | ||
| "manage_title": "Manage Wallets", | ||
| "no_results_found": "No results found.", | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,7 +3,7 @@ import { ActivityIndicator, StyleSheet, View } from 'react-native'; | |
|
|
||
| export const LazyLoadingIndicator = () => ( | ||
| <View style={styles.root}> | ||
| <ActivityIndicator size="large" /> | ||
| <ActivityIndicator size="large" color="#754CE8" /> | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we shouldn't hard-code colors |
||
| </View> | ||
| ); | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,4 @@ | ||
| import React, { useCallback } from 'react'; | ||
| import { Alert } from 'react-native'; | ||
| import ListItem from '../../components/ListItem'; | ||
| import { useStorage } from '../../hooks/context/useStorage'; | ||
| import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback'; | ||
|
|
@@ -8,6 +7,7 @@ import { useExtendedNavigation } from '../../hooks/useExtendedNavigation'; | |
| import { DetailViewStackParamList } from '../../navigation/DetailViewStackParamList'; | ||
| import { NativeStackNavigationProp } from '@react-navigation/native-stack'; | ||
| import { CommonActions } from '@react-navigation/native'; | ||
| import presentAlert from '../../components/Alert'; | ||
|
|
||
| type NavigationProps = NativeStackNavigationProp<DetailViewStackParamList, 'DeleteWallet'>; | ||
|
|
||
|
|
@@ -18,14 +18,14 @@ const DeleteWallet: React.FC = () => { | |
| const handleDeleteWallet = useCallback(async () => { | ||
| const wallet = wallets.length > 0 ? wallets[0] : null; | ||
| if (!wallet) { | ||
| Alert.alert(loc.wallets.list_empty_txs1, 'No wallet available to delete'); | ||
| presentAlert({ title: loc.wallets.list_empty_txs1, message: loc.wallets.no_wallet_to_delete }); | ||
| return; | ||
| } | ||
|
|
||
| Alert.alert( | ||
| loc.wallets.details_delete_wallet, | ||
| loc.wallets.details_are_you_sure, | ||
| [ | ||
| presentAlert({ | ||
| title: loc.wallets.details_delete_wallet, | ||
| message: loc.wallets.delete_wallet_warning, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i think the message should be a combination of both, are you sure + you will need your seed phrase |
||
| buttons: [ | ||
| { | ||
| text: loc._.cancel, | ||
| style: 'cancel', | ||
|
|
@@ -47,8 +47,8 @@ const DeleteWallet: React.FC = () => { | |
| }, | ||
| }, | ||
| ], | ||
| { cancelable: false }, | ||
| ); | ||
| options: { cancelable: false }, | ||
| }); | ||
| }, [wallets, handleWalletDeletion, dispatch]); | ||
|
|
||
| if (wallets.length === 0) { | ||
|
|
||
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 dont like the approach of using useRef inside a useEffect