diff --git a/react-native-toast-message b/react-native-toast-message
deleted file mode 160000
index e2db539..0000000
--- a/react-native-toast-message
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit e2db539be40ab3caeef8de3725d5017474f71679
diff --git a/src/components/home/ContentItem.tsx b/src/components/home/ContentItem.tsx
index 4635834..3a23b17 100644
--- a/src/components/home/ContentItem.tsx
+++ b/src/components/home/ContentItem.tsx
@@ -3,7 +3,7 @@ import { Toast } from 'toastify-react-native';
import { DeviceEventEmitter } from 'react-native';
import { View, TouchableOpacity, ActivityIndicator, StyleSheet, Dimensions, Platform, Text, Animated, Share } from 'react-native';
import FastImage from '@d11/react-native-fast-image';
-import { MaterialIcons } from '@expo/vector-icons';
+import { MaterialIcons, Feather } from '@expo/vector-icons';
import { useTheme } from '../../contexts/ThemeContext';
import { useSettings } from '../../hooks/useSettings';
import { catalogService, StreamingContent } from '../../services/catalogService';
@@ -279,7 +279,7 @@ const ContentItem = ({ item, onPress, shouldLoadImage: shouldLoadImageProp, defe
)}
{inLibrary && (
-
+
)}
diff --git a/src/components/home/FeaturedContent.tsx b/src/components/home/FeaturedContent.tsx
index 8437f6a..d02b19e 100644
--- a/src/components/home/FeaturedContent.tsx
+++ b/src/components/home/FeaturedContent.tsx
@@ -16,7 +16,7 @@ import { NavigationProp, useNavigation } from '@react-navigation/native';
import { RootStackParamList } from '../../navigation/AppNavigator';
import { LinearGradient } from 'expo-linear-gradient';
import FastImage from '@d11/react-native-fast-image';
-import { MaterialIcons } from '@expo/vector-icons';
+import { MaterialIcons, Feather } from '@expo/vector-icons';
import Animated, {
FadeIn,
useAnimatedStyle,
@@ -518,11 +518,7 @@ const FeaturedContent = ({ featuredContent, isSaved, handleSaveToLibrary, loadin
onPress={handleSaveToLibrary}
activeOpacity={0.7}
>
-
+
{isSaved ? "Saved" : "My List"}
@@ -628,11 +624,7 @@ const FeaturedContent = ({ featuredContent, isSaved, handleSaveToLibrary, loadin
onPress={handleSaveToLibrary}
activeOpacity={0.7}
>
-
+
{isSaved ? "Saved" : "Save"}
diff --git a/src/components/icons/MDBListIcon.tsx b/src/components/icons/MDBListIcon.tsx
new file mode 100644
index 0000000..85ae970
--- /dev/null
+++ b/src/components/icons/MDBListIcon.tsx
@@ -0,0 +1,36 @@
+import React from 'react';
+import Svg, { Path } from 'react-native-svg';
+
+interface MDBListIconProps {
+ size?: number;
+ colorPrimary?: string; // main brand color
+ colorSecondary?: string; // inner glyph color
+}
+
+// MDBList logo built from provided SVG paths. Colors are kept as in the source.
+const MDBListIcon: React.FC = ({ size = 24, colorPrimary = '#4284CA', colorSecondary = '#FBFCFE' }) => {
+ // Original SVG is 200x200; maintain square aspect.
+ return (
+
+ );
+};
+
+export default MDBListIcon;
+
+
diff --git a/src/components/icons/TMDBIcon.tsx b/src/components/icons/TMDBIcon.tsx
new file mode 100644
index 0000000..fe73008
--- /dev/null
+++ b/src/components/icons/TMDBIcon.tsx
@@ -0,0 +1,34 @@
+import React from 'react';
+import Svg, { Defs, LinearGradient, Stop, Path } from 'react-native-svg';
+
+interface TMDBIconProps {
+ size?: number;
+ color?: string; // primary theme color to tint the logo
+}
+
+// TMDB logo rendered via react-native-svg. The gradient is themed using the provided color.
+const TMDBIcon: React.FC = ({ size = 24, color = '#00b3e5' }) => {
+ // Maintain aspect ratio from original viewBox 185.04 x 133.4
+ const width = size * (185.04 / 133.4);
+ const height = size;
+
+ return (
+
+ );
+};
+
+export default TMDBIcon;
+
+
diff --git a/src/components/metadata/FloatingHeader.tsx b/src/components/metadata/FloatingHeader.tsx
index efcdeeb..73f1d36 100644
--- a/src/components/metadata/FloatingHeader.tsx
+++ b/src/components/metadata/FloatingHeader.tsx
@@ -8,7 +8,7 @@ import {
Dimensions,
} from 'react-native';
import { BlurView as ExpoBlurView } from 'expo-blur';
-import { MaterialIcons } from '@expo/vector-icons';
+import { MaterialIcons, Feather } from '@expo/vector-icons';
import FastImage from '@d11/react-native-fast-image';
import Animated, {
useAnimatedStyle,
@@ -115,11 +115,7 @@ const FloatingHeader: React.FC = ({
onPress={handleToggleLibrary}
hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
>
-
+
@@ -164,11 +160,7 @@ const FloatingHeader: React.FC = ({
onPress={handleToggleLibrary}
hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
>
-
+
diff --git a/src/components/metadata/HeroSection.tsx b/src/components/metadata/HeroSection.tsx
index 87824a8..da0ff84 100644
--- a/src/components/metadata/HeroSection.tsx
+++ b/src/components/metadata/HeroSection.tsx
@@ -12,7 +12,7 @@ import {
} from 'react-native';
import { useFocusEffect, useIsFocused } from '@react-navigation/native';
-import { MaterialIcons } from '@expo/vector-icons';
+import { MaterialIcons, Entypo, Feather } from '@expo/vector-icons';
import { LinearGradient } from 'expo-linear-gradient';
// Replaced FastImage with standard Image for logos
import { BlurView as ExpoBlurView } from 'expo-blur';
@@ -285,8 +285,8 @@ const ActionButtons = memo(({
) : (
)}
-
@@ -1451,8 +1451,8 @@ const HeroSection: React.FC = memo(({
borderRadius: 20,
}}
>
-
diff --git a/src/navigation/AppNavigator.tsx b/src/navigation/AppNavigator.tsx
index ca05e52..72eb7c3 100644
--- a/src/navigation/AppNavigator.tsx
+++ b/src/navigation/AppNavigator.tsx
@@ -7,7 +7,7 @@ import AsyncStorage from '@react-native-async-storage/async-storage';
import { PaperProvider, MD3DarkTheme, MD3LightTheme, adaptNavigationTheme } from 'react-native-paper';
import type { MD3Theme } from 'react-native-paper';
import type { BottomTabBarProps } from '@react-navigation/bottom-tabs';
-import { MaterialCommunityIcons } from '@expo/vector-icons';
+import { MaterialCommunityIcons, Feather, Ionicons } from '@expo/vector-icons';
import { LinearGradient } from 'expo-linear-gradient';
import { BlurView } from 'expo-blur';
import { colors } from '../styles/colors';
@@ -352,17 +352,14 @@ export const CustomNavigationDarkTheme: Theme = {
fonts,
};
-type IconNameType = 'home' | 'home-outline' | 'compass' | 'compass-outline' |
- 'play-box-multiple' | 'play-box-multiple-outline' |
- 'puzzle' | 'puzzle-outline' |
- 'cog' | 'cog-outline' | 'feature-search' | 'feature-search-outline' |
- 'magnify' | 'heart' | 'heart-outline' | 'download' | 'download-outline';
+type IconNameType = string;
// Add TabIcon component
-const TabIcon = React.memo(({ focused, color, iconName }: {
+const TabIcon = React.memo(({ focused, color, iconName, iconLibrary = 'material' }: {
focused: boolean;
color: string;
iconName: IconNameType;
+ iconLibrary?: 'material' | 'feather' | 'ionicons';
}) => {
const scaleAnim = useRef(new Animated.Value(1)).current;
@@ -375,8 +372,11 @@ const TabIcon = React.memo(({ focused, color, iconName }: {
}).start();
}, [focused]);
- // Use outline variant when available, but keep single-form icons (like 'magnify') the same
+ // Use outline variant when available for Material icons; Feather has single-form icons
const finalIconName = (() => {
+ if (iconLibrary === 'feather') {
+ return iconName;
+ }
if (iconName === 'magnify') return 'magnify';
return focused ? iconName : `${iconName}-outline` as IconNameType;
})();
@@ -387,11 +387,25 @@ const TabIcon = React.memo(({ focused, color, iconName }: {
justifyContent: 'center',
transform: [{ scale: scaleAnim }]
}}>
-
+ {iconLibrary === 'feather' ? (
+
+ ) : iconLibrary === 'ionicons' ? (
+
+ ) : (
+
+ )}
);
});
@@ -698,21 +712,27 @@ const MainTabs = () => {
};
let iconName: IconNameType = 'home';
+ let iconLibrary: 'material' | 'feather' | 'ionicons' = 'material';
switch (route.name) {
case 'Home':
iconName = 'home';
+ iconLibrary = 'feather';
break;
case 'Library':
- iconName = 'heart';
+ iconName = 'library';
+ iconLibrary = 'ionicons';
break;
case 'Search':
- iconName = 'magnify';
+ iconName = 'search';
+ iconLibrary = 'feather';
break;
case 'Downloads':
iconName = 'download';
+ iconLibrary = 'feather';
break;
case 'Settings':
- iconName = 'cog';
+ iconName = 'settings';
+ iconLibrary = 'feather';
break;
}
@@ -732,6 +752,7 @@ const MainTabs = () => {
focused={isFocused}
color={isFocused ? currentTheme.colors.primary : currentTheme.colors.white}
iconName={iconName}
+ iconLibrary={iconLibrary}
/>
{
onPress={() => navigation.navigate('Calendar')}
activeOpacity={0.7}
>
-
diff --git a/src/screens/SearchScreen.tsx b/src/screens/SearchScreen.tsx
index be92d0b..22f1555 100644
--- a/src/screens/SearchScreen.tsx
+++ b/src/screens/SearchScreen.tsx
@@ -20,7 +20,7 @@ import {
} from 'react-native';
import { useNavigation } from '@react-navigation/native';
import { NavigationProp } from '@react-navigation/native';
-import { MaterialIcons } from '@expo/vector-icons';
+import { MaterialIcons, Feather } from '@expo/vector-icons';
import { catalogService, StreamingContent, GroupedSearchResults, AddonSearchResults } from '../services/catalogService';
import FastImage from '@d11/react-native-fast-image';
import debounce from 'lodash/debounce';
@@ -579,7 +579,7 @@ const SearchScreen = () => {
{/* Bookmark and watched icons top right, bookmark to the left of watched */}
{inLibrary && (
-
+
)}
{watched && (
diff --git a/src/screens/SettingsScreen.tsx b/src/screens/SettingsScreen.tsx
index 118e206..20b3e9d 100644
--- a/src/screens/SettingsScreen.tsx
+++ b/src/screens/SettingsScreen.tsx
@@ -18,7 +18,7 @@ import AsyncStorage from '@react-native-async-storage/async-storage';
import { useNavigation } from '@react-navigation/native';
import { NavigationProp } from '@react-navigation/native';
import FastImage from '@d11/react-native-fast-image';
-import { MaterialIcons } from '@expo/vector-icons';
+import { Feather } from '@expo/vector-icons';
import { Picker } from '@react-native-picker/picker';
import { useSettings, DEFAULT_SETTINGS } from '../hooks/useSettings';
import { RootStackParamList } from '../navigation/AppNavigator';
@@ -33,6 +33,8 @@ import { getDisplayedAppVersion } from '../utils/version';
import CustomAlert from '../components/CustomAlert';
import PluginIcon from '../components/icons/PluginIcon';
import TraktIcon from '../components/icons/TraktIcon';
+import TMDBIcon from '../components/icons/TMDBIcon';
+import MDBListIcon from '../components/icons/MDBListIcon';
const { width, height } = Dimensions.get('window');
const isTablet = width >= 768;
@@ -41,17 +43,17 @@ const ANDROID_STATUSBAR_HEIGHT = StatusBar.currentHeight || 0;
// Settings categories for tablet sidebar
const SETTINGS_CATEGORIES = [
- { id: 'account', title: 'Account', icon: 'account-circle' as keyof typeof MaterialIcons.glyphMap },
- { id: 'content', title: 'Content & Discovery', icon: 'explore' as keyof typeof MaterialIcons.glyphMap },
- { id: 'appearance', title: 'Appearance', icon: 'palette' as keyof typeof MaterialIcons.glyphMap },
- { id: 'integrations', title: 'Integrations', icon: 'extension' as keyof typeof MaterialIcons.glyphMap },
- { id: 'ai', title: 'AI Assistant', icon: 'smart-toy' as keyof typeof MaterialIcons.glyphMap },
- { id: 'playback', title: 'Playback', icon: 'play-circle-outline' as keyof typeof MaterialIcons.glyphMap },
- { id: 'backup', title: 'Backup & Restore', icon: 'save' as keyof typeof MaterialIcons.glyphMap },
- { id: 'updates', title: 'Updates', icon: 'system-update' as keyof typeof MaterialIcons.glyphMap },
- { id: 'about', title: 'About', icon: 'info-outline' as keyof typeof MaterialIcons.glyphMap },
- { id: 'developer', title: 'Developer', icon: 'code' as keyof typeof MaterialIcons.glyphMap },
- { id: 'cache', title: 'Cache', icon: 'cached' as keyof typeof MaterialIcons.glyphMap },
+ { id: 'account', title: 'Account', icon: 'user' as string },
+ { id: 'content', title: 'Content & Discovery', icon: 'compass' as string },
+ { id: 'appearance', title: 'Appearance', icon: 'sliders' as string },
+ { id: 'integrations', title: 'Integrations', icon: 'layers' as string },
+ { id: 'ai', title: 'AI Assistant', icon: 'cpu' as string },
+ { id: 'playback', title: 'Playback', icon: 'play-circle' as string },
+ { id: 'backup', title: 'Backup & Restore', icon: 'archive' as string },
+ { id: 'updates', title: 'Updates', icon: 'refresh-ccw' as string },
+ { id: 'about', title: 'About', icon: 'info' as string },
+ { id: 'developer', title: 'Developer', icon: 'code' as string },
+ { id: 'cache', title: 'Cache', icon: 'database' as string },
];
// Card component with minimalistic style
@@ -94,7 +96,7 @@ const SettingsCard: React.FC = ({ children, title, isTablet =
interface SettingItemProps {
title: string;
description?: string;
- icon?: keyof typeof MaterialIcons.glyphMap;
+ icon?: string;
customIcon?: React.ReactNode;
renderControl?: () => React.ReactNode;
isLast?: boolean;
@@ -139,8 +141,8 @@ const SettingItem: React.FC = ({
{customIcon ? (
customIcon
) : (
-
@@ -216,8 +218,8 @@ const Sidebar: React.FC = ({ selectedCategory, onCategorySelect, c
]}
onPress={() => onCategorySelect(category.id)}
>
- {
);
const ChevronRight = () => (
- {
navigation.navigate('Addons')}
isTablet={isTablet}
@@ -470,7 +472,7 @@ const SettingsScreen: React.FC = () => {
navigation.navigate('CatalogSettings')}
isTablet={isTablet}
@@ -493,7 +495,7 @@ const SettingsScreen: React.FC = () => {
navigation.navigate('ThemeSettings')}
isTablet={isTablet}
@@ -501,7 +503,7 @@ const SettingsScreen: React.FC = () => {
(
{
}
renderControl={ChevronRight}
onPress={() => navigation.navigate('MDBListSettings')}
isTablet={isTablet}
@@ -528,7 +530,7 @@ const SettingsScreen: React.FC = () => {
}
renderControl={ChevronRight}
onPress={() => navigation.navigate('TMDBSettings')}
isLast={true}
@@ -543,7 +545,7 @@ const SettingsScreen: React.FC = () => {
navigation.navigate('AISettings')}
isLast={true}
@@ -561,7 +563,7 @@ const SettingsScreen: React.FC = () => {
? (settings?.preferredPlayer === 'internal' ? 'Built-in' : settings?.preferredPlayer?.toUpperCase() || 'Built-in')
: (settings?.useExternalPlayer ? 'External' : 'Built-in')
}
- icon="play-circle-outline"
+ icon="play-circle"
renderControl={ChevronRight}
onPress={() => navigation.navigate('PlayerSettings')}
isTablet={isTablet}
@@ -569,7 +571,7 @@ const SettingsScreen: React.FC = () => {
(
{
navigation.navigate('NotificationSettings')}
isLast={true}
@@ -618,7 +620,7 @@ const SettingsScreen: React.FC = () => {
/>
Sentry.showFeedbackWidget()}
renderControl={ChevronRight}
isTablet={isTablet}
@@ -626,7 +628,7 @@ const SettingsScreen: React.FC = () => {
@@ -638,14 +640,14 @@ const SettingsScreen: React.FC = () => {
navigation.navigate('Onboarding')}
renderControl={ChevronRight}
isTablet={isTablet}
/>
{
try {
await AsyncStorage.removeItem('hasCompletedOnboarding');
@@ -659,7 +661,7 @@ const SettingsScreen: React.FC = () => {
/>
{
openAlert(
'Clear All Data',
@@ -691,7 +693,7 @@ const SettingsScreen: React.FC = () => {
{
navigation.navigate('Backup')}
isLast={true}
@@ -720,7 +722,7 @@ const SettingsScreen: React.FC = () => {
{
diff --git a/toastify-react-native b/toastify-react-native
deleted file mode 160000
index 17a44eb..0000000
--- a/toastify-react-native
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 17a44eb5d18612611cc9b0eca269101ddbf0311b