This commit is contained in:
tapframe 2025-10-15 19:56:01 +05:30
parent 6a6a93aec4
commit 7e300e8789
8 changed files with 251 additions and 29 deletions

1
.gitignore vendored
View file

@ -71,3 +71,4 @@ backup_sdk54_upgrade/
SDK54_UPGRADE_SUMMARY.md
SDK54_UPGRADE_SUMMARY.md
build-and-publish-app-releases.sh
bottomnav.md

View file

@ -1,5 +1,5 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
<style name="AppTheme" parent="Theme.Material3.DayNight.NoActionBar">
<item name="android:enforceNavigationBarContrast" tools:targetApi="29">true</item>
<item name="android:editTextBackground">@drawable/rn_edit_text_material</item>
<item name="colorPrimary">@color/colorPrimary</item>

View file

@ -86,7 +86,8 @@
"localNetworkPermission": "Allow $(PRODUCT_NAME) to access your local network",
"supportsBackgroundPlayback": true
}
]
],
"react-native-bottom-tabs"
],
"updates": {
"enabled": true,

View file

@ -1707,6 +1707,53 @@ PODS:
- ReactCommon/turbomodule/core
- ReactNativeDependencies
- Yoga
- react-native-bottom-tabs (0.12.2):
- hermes-engine
- RCTRequired
- RCTTypeSafety
- React-Core
- React-Core-prebuilt
- React-debug
- React-Fabric
- React-featureflags
- React-graphics
- React-ImageManager
- React-jsi
- react-native-bottom-tabs/common (= 0.12.2)
- React-NativeModulesApple
- React-RCTFabric
- React-renderercss
- React-rendererdebug
- React-utils
- ReactCodegen
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- ReactNativeDependencies
- SwiftUIIntrospect (~> 1.0)
- Yoga
- react-native-bottom-tabs/common (0.12.2):
- hermes-engine
- RCTRequired
- RCTTypeSafety
- React-Core
- React-Core-prebuilt
- React-debug
- React-Fabric
- React-featureflags
- React-graphics
- React-ImageManager
- React-jsi
- React-NativeModulesApple
- React-RCTFabric
- React-renderercss
- React-rendererdebug
- React-utils
- ReactCodegen
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- ReactNativeDependencies
- SwiftUIIntrospect (~> 1.0)
- Yoga
- react-native-device-brightness (1.2.7):
- React
- react-native-get-random-values (1.11.0):
@ -2631,6 +2678,7 @@ PODS:
- libwebp (~> 1.0)
- SDWebImage/Core (~> 5.17)
- Sentry/HybridSDK (8.56.1)
- SwiftUIIntrospect (1.3.0)
- Yoga (0.0.0)
DEPENDENCIES:
@ -2712,6 +2760,7 @@ DEPENDENCIES:
- React-Mapbuffer (from `../node_modules/react-native/ReactCommon`)
- React-microtasksnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/microtasks`)
- "react-native-blur (from `../node_modules/@react-native-community/blur`)"
- react-native-bottom-tabs (from `../node_modules/react-native-bottom-tabs`)
- "react-native-device-brightness (from `../node_modules/@adrianso/react-native-device-brightness`)"
- react-native-get-random-values (from `../node_modules/react-native-get-random-values`)
- "react-native-netinfo (from `../node_modules/@react-native-community/netinfo`)"
@ -2773,6 +2822,7 @@ SPEC REPOS:
- SDWebImageAVIFCoder
- SDWebImageWebPCoder
- Sentry
- SwiftUIIntrospect
EXTERNAL SOURCES:
DisplayCriteria:
@ -2934,6 +2984,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/react/nativemodule/microtasks"
react-native-blur:
:path: "../node_modules/@react-native-community/blur"
react-native-bottom-tabs:
:path: "../node_modules/react-native-bottom-tabs"
react-native-device-brightness:
:path: "../node_modules/@adrianso/react-native-device-brightness"
react-native-get-random-values:
@ -3129,6 +3181,7 @@ SPEC CHECKSUMS:
React-Mapbuffer: fbe1da882a187e5898bdf125e1cc6e603d27ecae
React-microtasksnativemodule: 76905804171d8ccbe69329fc84c57eb7934add7f
react-native-blur: 1b00ef07fe0efdc0c40b37139a5268ccad73c72d
react-native-bottom-tabs: e37c9d1565b1ee48c4c0e4b4fa4b804775f82dfa
react-native-device-brightness: 1a997350d060c3df9f303b1df84a4f7c5cbeb924
react-native-get-random-values: d16467cf726c618e9c7a8c3c39c31faa2244bbba
react-native-netinfo: cec9c4e86083cb5b6aba0e0711f563e2fbbff187
@ -3180,6 +3233,7 @@ SPEC CHECKSUMS:
SDWebImageAVIFCoder: afe194a084e851f70228e4be35ef651df0fc5c57
SDWebImageWebPCoder: e38c0a70396191361d60c092933e22c20d5b1380
Sentry: b3ec44d01708fce73f99b544beb57e890eca4406
SwiftUIIntrospect: fee9aa07293ee280373a591e1824e8ddc869ba5d
Yoga: 051f086b5ccf465ff2ed38a2cf5a558ae01aaaa1
PODFILE CHECKSUM: 1db7b3713ca6ad8568e4bdf6b72b92b72ee8199d

87
package-lock.json generated
View file

@ -11,6 +11,7 @@
"dependencies": {
"@adrianso/react-native-device-brightness": "^1.2.7",
"@backpackapp-io/react-native-toast": "^0.14.0",
"@bottom-tabs/react-navigation": "^0.12.2",
"@d11/react-native-fast-image": "^8.8.0",
"@expo/env": "^2.0.7",
"@expo/metro-runtime": "~6.1.2",
@ -66,6 +67,7 @@
"posthog-react-native": "^4.4.0",
"react": "19.1.0",
"react-native": "0.81.4",
"react-native-bottom-tabs": "^0.12.2",
"react-native-gesture-handler": "~2.28.0",
"react-native-get-random-values": "^1.11.0",
"react-native-image-colors": "^2.5.0",
@ -1622,6 +1624,67 @@
"react-native-safe-area-context": ">=4.2.4"
}
},
"node_modules/@bottom-tabs/react-navigation": {
"version": "0.12.2",
"resolved": "https://registry.npmjs.org/@bottom-tabs/react-navigation/-/react-navigation-0.12.2.tgz",
"integrity": "sha512-vQ/7pNcWk2TgveVCBfdQnbLC6zaRbIL2EM4Vsifk/NCCZ49oT1G2K7iXAsCPby9/ofd6ndGOMmsVLFVq5M7fjw==",
"license": "MIT",
"dependencies": {
"color": "^5.0.0"
},
"peerDependencies": {
"@react-navigation/native": ">=7",
"react": "*",
"react-native": "*",
"react-native-bottom-tabs": "*"
}
},
"node_modules/@bottom-tabs/react-navigation/node_modules/color": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/color/-/color-5.0.2.tgz",
"integrity": "sha512-e2hz5BzbUPcYlIRHo8ieAhYgoajrJr+hWoceg6E345TPsATMUKqDgzt8fSXZJJbxfpiPzkWyphz8yn8At7q3fA==",
"license": "MIT",
"dependencies": {
"color-convert": "^3.0.1",
"color-string": "^2.0.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@bottom-tabs/react-navigation/node_modules/color-convert": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-3.1.2.tgz",
"integrity": "sha512-UNqkvCDXstVck3kdowtOTWROIJQwafjOfXSmddoDrXo4cewMKmusCeF22Q24zvjR8nwWib/3S/dfyzPItPEiJg==",
"license": "MIT",
"dependencies": {
"color-name": "^2.0.0"
},
"engines": {
"node": ">=14.6"
}
},
"node_modules/@bottom-tabs/react-navigation/node_modules/color-name": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.2.tgz",
"integrity": "sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==",
"license": "MIT",
"engines": {
"node": ">=12.20"
}
},
"node_modules/@bottom-tabs/react-navigation/node_modules/color-string": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/color-string/-/color-string-2.1.2.tgz",
"integrity": "sha512-RxmjYxbWemV9gKu4zPgiZagUxbH3RQpEIO77XoSSX0ivgABDZ+h8Zuash/EMFLTI4N9QgFPOJ6JQpPZKFxa+dA==",
"license": "MIT",
"dependencies": {
"color-name": "^2.0.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@callstack/react-theme-provider": {
"version": "3.0.9",
"resolved": "https://registry.npmjs.org/@callstack/react-theme-provider/-/react-theme-provider-3.0.9.tgz",
@ -10686,6 +10749,21 @@
}
}
},
"node_modules/react-native-bottom-tabs": {
"version": "0.12.2",
"resolved": "https://registry.npmjs.org/react-native-bottom-tabs/-/react-native-bottom-tabs-0.12.2.tgz",
"integrity": "sha512-OXxYtKbJK8hfV7ZrrS/h3vmoB2WOQQRBuV+cqJ1NJSpKxZNBIwHfbUxGlkgcg/I7x2GlmZ9yDDC3KbQ3ouv69Q==",
"license": "MIT",
"dependencies": {
"react-freeze": "^1.0.0",
"sf-symbols-typescript": "^2.0.0",
"use-latest-callback": "^0.2.1"
},
"peerDependencies": {
"react": "*",
"react-native": "*"
}
},
"node_modules/react-native-elevation": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/react-native-elevation/-/react-native-elevation-1.0.0.tgz",
@ -11943,6 +12021,15 @@
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
"license": "ISC"
},
"node_modules/sf-symbols-typescript": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/sf-symbols-typescript/-/sf-symbols-typescript-2.1.0.tgz",
"integrity": "sha512-ezT7gu/SHTPIOEEoG6TF+O0m5eewl0ZDAO4AtdBi5HjsrUI6JdCG17+Q8+aKp0heM06wZKApRCn5olNbs0Wb/A==",
"license": "MIT",
"engines": {
"node": ">=10"
}
},
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",

View file

@ -11,6 +11,7 @@
"dependencies": {
"@adrianso/react-native-device-brightness": "^1.2.7",
"@backpackapp-io/react-native-toast": "^0.14.0",
"@bottom-tabs/react-navigation": "^0.12.2",
"@d11/react-native-fast-image": "^8.8.0",
"@expo/env": "^2.0.7",
"@expo/metro-runtime": "~6.1.2",
@ -66,6 +67,7 @@
"posthog-react-native": "^4.4.0",
"react": "19.1.0",
"react-native": "0.81.4",
"react-native-bottom-tabs": "^0.12.2",
"react-native-gesture-handler": "~2.28.0",
"react-native-get-random-values": "^1.11.0",
"react-native-image-colors": "^2.5.0",

View file

@ -814,6 +814,78 @@ const MainTabs = () => {
);
};
// iOS: Use native bottom tabs (@bottom-tabs/react-navigation)
if (Platform.OS === 'ios') {
// Dynamically require to avoid impacting Android bundle
const { createNativeBottomTabNavigator } = require('@bottom-tabs/react-navigation');
const IOSTab = createNativeBottomTabNavigator();
return (
<View style={{ flex: 1, backgroundColor: currentTheme.colors.darkBackground }}>
<StatusBar
translucent
barStyle="light-content"
backgroundColor="transparent"
/>
<IOSTab.Navigator
// Native tab bar handles its own visuals; keep options minimal
screenOptions={{
headerShown: false,
tabBarActiveTintColor: currentTheme.colors.primary,
tabBarInactiveTintColor: currentTheme.colors.white,
translucent: true,
// Prefer native lazy/freeze when available; still pass for parity
lazy: true,
freezeOnBlur: true,
}}
>
<IOSTab.Screen
name="Home"
component={HomeScreen}
options={{
title: 'Home',
tabBarIcon: () => ({ sfSymbol: 'house' }),
}}
/>
<IOSTab.Screen
name="Library"
component={LibraryScreen}
options={{
title: 'Library',
tabBarIcon: () => ({ sfSymbol: 'heart' }),
}}
/>
<IOSTab.Screen
name="Search"
component={SearchScreen}
options={{
title: 'Search',
tabBarIcon: () => ({ sfSymbol: 'magnifyingglass' }),
}}
/>
{appSettings?.enableDownloads !== false && (
<IOSTab.Screen
name="Downloads"
component={DownloadsScreen}
options={{
title: 'Downloads',
tabBarIcon: () => ({ sfSymbol: 'arrow.down.circle' }),
}}
/>
)}
<IOSTab.Screen
name="Settings"
component={SettingsScreen}
options={{
title: 'Settings',
tabBarIcon: () => ({ sfSymbol: 'gear' }),
}}
/>
</IOSTab.Navigator>
</View>
);
}
return (
<View style={{ flex: 1, backgroundColor: currentTheme.colors.darkBackground }}>
{/* Common StatusBar for all tabs */}

View file

@ -668,17 +668,7 @@ const CatalogSettingsScreen = () => {
{Platform.OS === 'ios' ? (
<Pressable style={styles.modalOverlay} onPress={() => setIsRenameModalVisible(false)}>
{GlassViewComp && liquidGlassAvailable ? (
<GlassViewComp
style={styles.modalContent}
glassEffectStyle="regular"
>
) : (
<BlurView
style={styles.modalContent}
intensity={90}
tint="default"
>
)}
<GlassViewComp style={styles.modalContent} glassEffectStyle="regular">
<Pressable onPress={(e) => e.stopPropagation()}>
<Text style={styles.modalTitle}>Rename Catalog</Text>
<TextInput
@ -694,9 +684,24 @@ const CatalogSettingsScreen = () => {
<Button title="Save" onPress={handleSaveRename} color={colors.primary} />
</View>
</Pressable>
{GlassViewComp && liquidGlassAvailable ? (
</GlassViewComp>
) : (
<BlurView style={styles.modalContent} intensity={90} tint="default">
<Pressable onPress={(e) => e.stopPropagation()}>
<Text style={styles.modalTitle}>Rename Catalog</Text>
<TextInput
style={styles.modalInput}
value={currentRenameValue}
onChangeText={setCurrentRenameValue}
placeholder="Enter new catalog name"
placeholderTextColor={colors.mediumGray}
autoFocus={true}
/>
<View style={styles.modalButtons}>
<Button title="Cancel" onPress={() => setIsRenameModalVisible(false)} color={colors.mediumGray} />
<Button title="Save" onPress={handleSaveRename} color={colors.primary} />
</View>
</Pressable>
</BlurView>
)}
</Pressable>