/ components / EnhancedBackButton.tsx
EnhancedBackButton.tsx
1 import React, { useState } from 'react'; 2 import { View, StyleSheet, useColorScheme, Pressable } from 'react-native'; 3 import { Ionicons } from '@expo/vector-icons'; 4 import { Colors, ColorScheme } from '@/constants/Colors'; 5 import { useNavigationHistory } from '@/hooks/useNavigationHistory'; 6 import NavigationHistoryPanel from './NavigationHistoryPanel'; 7 8 interface EnhancedBackButtonProps { 9 size?: number; 10 color?: string; 11 style?: any; 12 showHistoryOnLongPress?: boolean; 13 customOnPress?: () => void; 14 disabled?: boolean; 15 } 16 17 const EnhancedBackButton: React.FC<EnhancedBackButtonProps> = ({ 18 size = 24, 19 color, 20 style, 21 showHistoryOnLongPress = true, 22 customOnPress, 23 disabled = false, 24 }) => { 25 const colorScheme = useColorScheme() as ColorScheme; 26 const { handleBackPress, canGoBack, currentDepth } = useNavigationHistory(); 27 const [showHistoryPanel, setShowHistoryPanel] = useState(false); 28 const [isPressed, setIsPressed] = useState(false); 29 30 const colors = Colors[colorScheme]; 31 const buttonColor = color || colors.text; 32 const isDisabled = disabled || !canGoBack; 33 34 const handlePress = async () => { 35 if (isDisabled) return; 36 37 if (customOnPress) { 38 customOnPress(); 39 } else { 40 await handleBackPress('tap'); 41 } 42 }; 43 44 const handleLongPress = () => { 45 if (isDisabled || !showHistoryOnLongPress) return; 46 setShowHistoryPanel(true); 47 }; 48 49 const getBackgroundColor = () => { 50 if (isDisabled) return 'transparent'; 51 if (isPressed) return colors.primary + '20'; 52 return 'transparent'; 53 }; 54 55 return ( 56 <> 57 <Pressable 58 style={[ 59 styles.container, 60 { 61 backgroundColor: getBackgroundColor(), 62 opacity: isDisabled ? 0.3 : 1, 63 }, 64 style, 65 ]} 66 onPress={handlePress} 67 onLongPress={handleLongPress} 68 onPressIn={() => setIsPressed(true)} 69 onPressOut={() => setIsPressed(false)} 70 disabled={isDisabled} 71 delayLongPress={500} 72 > 73 <View style={styles.iconContainer}> 74 <Ionicons name="arrow-back" size={size} color={buttonColor} /> 75 {currentDepth > 1 && ( 76 <View 77 style={[ 78 styles.depthIndicator, 79 { backgroundColor: colors.primary }, 80 ]} 81 > 82 <Ionicons 83 name="ellipsis-horizontal" 84 size={size * 0.5} 85 color={colors.background} 86 /> 87 </View> 88 )} 89 </View> 90 </Pressable> 91 92 <NavigationHistoryPanel 93 visible={showHistoryPanel} 94 onClose={() => setShowHistoryPanel(false)} 95 /> 96 </> 97 ); 98 }; 99 100 interface FloatingBackButtonProps extends EnhancedBackButtonProps { 101 position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'; 102 offset?: { x: number; y: number }; 103 } 104 105 export const FloatingBackButton: React.FC<FloatingBackButtonProps> = ({ 106 position = 'top-left', 107 offset = { x: 20, y: 60 }, 108 size = 28, 109 ...props 110 }) => { 111 const colorScheme = useColorScheme() as ColorScheme; 112 const colors = Colors[colorScheme]; 113 114 const getPositionStyle = () => { 115 const baseStyle = { 116 position: 'absolute' as const, 117 width: 48, 118 height: 48, 119 borderRadius: 24, 120 backgroundColor: colors.card, 121 shadowColor: '#000', 122 shadowOffset: { width: 0, height: 2 }, 123 shadowOpacity: 0.25, 124 shadowRadius: 3.84, 125 elevation: 5, 126 justifyContent: 'center' as const, 127 alignItems: 'center' as const, 128 }; 129 130 switch (position) { 131 case 'top-left': 132 return { ...baseStyle, top: offset.y, left: offset.x }; 133 case 'top-right': 134 return { ...baseStyle, top: offset.y, right: offset.x }; 135 case 'bottom-left': 136 return { ...baseStyle, bottom: offset.y, left: offset.x }; 137 case 'bottom-right': 138 return { ...baseStyle, bottom: offset.y, right: offset.x }; 139 default: 140 return { ...baseStyle, top: offset.y, left: offset.x }; 141 } 142 }; 143 144 return ( 145 <EnhancedBackButton {...props} size={size} style={getPositionStyle()} /> 146 ); 147 }; 148 149 const styles = StyleSheet.create({ 150 container: { 151 padding: 8, 152 borderRadius: 20, 153 justifyContent: 'center', 154 alignItems: 'center', 155 minWidth: 40, 156 minHeight: 40, 157 }, 158 iconContainer: { 159 position: 'relative', 160 justifyContent: 'center', 161 alignItems: 'center', 162 }, 163 depthIndicator: { 164 position: 'absolute', 165 top: -4, 166 right: -4, 167 width: 16, 168 height: 16, 169 borderRadius: 8, 170 justifyContent: 'center', 171 alignItems: 'center', 172 }, 173 }); 174 175 export default EnhancedBackButton;