UI changes
This commit is contained in:
parent
6db159e944
commit
15ab70b524
4 changed files with 155 additions and 60 deletions
|
|
@ -11,10 +11,12 @@ import {
|
||||||
ScrollView,
|
ScrollView,
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import { MaterialIcons } from '@expo/vector-icons';
|
import { MaterialIcons } from '@expo/vector-icons';
|
||||||
|
import TraktIcon from '../../../assets/rating-icons/trakt.svg';
|
||||||
import { useTheme } from '../../contexts/ThemeContext';
|
import { useTheme } from '../../contexts/ThemeContext';
|
||||||
import { TraktContentComment } from '../../services/traktService';
|
import { TraktContentComment } from '../../services/traktService';
|
||||||
import { logger } from '../../utils/logger';
|
import { logger } from '../../utils/logger';
|
||||||
import { useTraktComments } from '../../hooks/useTraktComments';
|
import { useTraktComments } from '../../hooks/useTraktComments';
|
||||||
|
import { useSettings } from '../../hooks/useSettings';
|
||||||
import BottomSheet, { BottomSheetView } from '@gorhom/bottom-sheet';
|
import BottomSheet, { BottomSheetView } from '@gorhom/bottom-sheet';
|
||||||
|
|
||||||
const { width } = Dimensions.get('window');
|
const { width } = Dimensions.get('window');
|
||||||
|
|
@ -134,16 +136,23 @@ const CompactCommentCard: React.FC<{
|
||||||
}}
|
}}
|
||||||
activeOpacity={0.7}
|
activeOpacity={0.7}
|
||||||
>
|
>
|
||||||
|
{/* Trakt Icon - Top Right Corner */}
|
||||||
|
<View style={styles.traktIconContainer}>
|
||||||
|
<TraktIcon width={16} height={16} />
|
||||||
|
</View>
|
||||||
|
|
||||||
{/* Header Section - Fixed at top */}
|
{/* Header Section - Fixed at top */}
|
||||||
<View style={styles.compactHeader}>
|
<View style={styles.compactHeader}>
|
||||||
<Text style={[styles.compactUsername, { color: theme.colors.highEmphasis }]}>
|
<View style={styles.usernameContainer}>
|
||||||
{username}
|
<Text style={[styles.compactUsername, { color: theme.colors.highEmphasis }]}>
|
||||||
</Text>
|
{username}
|
||||||
{user.vip && (
|
</Text>
|
||||||
<View style={styles.miniVipBadge}>
|
{user.vip && (
|
||||||
<Text style={styles.miniVipText}>VIP</Text>
|
<View style={styles.miniVipBadge}>
|
||||||
</View>
|
<Text style={styles.miniVipText}>VIP</Text>
|
||||||
)}
|
</View>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{/* Rating - Show stars */}
|
{/* Rating - Show stars */}
|
||||||
|
|
@ -400,6 +409,7 @@ export const CommentsSection: React.FC<CommentsSectionProps> = ({
|
||||||
onCommentPress,
|
onCommentPress,
|
||||||
}) => {
|
}) => {
|
||||||
const { currentTheme } = useTheme();
|
const { currentTheme } = useTheme();
|
||||||
|
const { settings } = useSettings();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
comments,
|
comments,
|
||||||
|
|
@ -468,8 +478,17 @@ export const CommentsSection: React.FC<CommentsSectionProps> = ({
|
||||||
);
|
);
|
||||||
}, [loading, error, currentTheme]);
|
}, [loading, error, currentTheme]);
|
||||||
|
|
||||||
// Don't show section if not authenticated
|
// Don't show section if not authenticated, if comments are disabled in settings, or if still checking authentication
|
||||||
if (!isAuthenticated) {
|
// Only show when authentication is definitively true and settings allow it
|
||||||
|
if (isAuthenticated !== true || !settings.showTraktComments) {
|
||||||
|
// Show loading state only if we're checking authentication but settings allow comments
|
||||||
|
if (isAuthenticated === null && settings.showTraktComments) {
|
||||||
|
return (
|
||||||
|
<View style={styles.loadingContainer}>
|
||||||
|
<ActivityIndicator size="small" color={currentTheme.colors.primary} />
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -787,10 +806,15 @@ const styles = StyleSheet.create({
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
marginBottom: 8,
|
marginBottom: 8,
|
||||||
},
|
},
|
||||||
|
usernameContainer: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
compactUsername: {
|
compactUsername: {
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: '600',
|
fontWeight: '600',
|
||||||
flex: 1,
|
marginRight: 8,
|
||||||
},
|
},
|
||||||
miniVipBadge: {
|
miniVipBadge: {
|
||||||
backgroundColor: '#FFD700',
|
backgroundColor: '#FFD700',
|
||||||
|
|
@ -799,6 +823,12 @@ const styles = StyleSheet.create({
|
||||||
borderRadius: 6,
|
borderRadius: 6,
|
||||||
marginLeft: 6,
|
marginLeft: 6,
|
||||||
},
|
},
|
||||||
|
traktIconContainer: {
|
||||||
|
position: 'absolute',
|
||||||
|
top: 8,
|
||||||
|
right: 8,
|
||||||
|
zIndex: 1,
|
||||||
|
},
|
||||||
miniVipText: {
|
miniVipText: {
|
||||||
fontSize: 9,
|
fontSize: 9,
|
||||||
fontWeight: '700',
|
fontWeight: '700',
|
||||||
|
|
@ -983,7 +1013,7 @@ const styles = StyleSheet.create({
|
||||||
loadingContainer: {
|
loadingContainer: {
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
paddingVertical: 40,
|
paddingVertical: 20,
|
||||||
},
|
},
|
||||||
loadingText: {
|
loadingText: {
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,8 @@ export interface AppSettings {
|
||||||
// Metadata enrichment
|
// Metadata enrichment
|
||||||
enrichMetadataWithTMDB: boolean; // Use TMDB to enrich metadata (cast, certification, posters, fallbacks)
|
enrichMetadataWithTMDB: boolean; // Use TMDB to enrich metadata (cast, certification, posters, fallbacks)
|
||||||
useTmdbLocalizedMetadata: boolean; // Use TMDB localized metadata (titles, overviews) per tmdbLanguagePreference
|
useTmdbLocalizedMetadata: boolean; // Use TMDB localized metadata (titles, overviews) per tmdbLanguagePreference
|
||||||
|
// Trakt integration
|
||||||
|
showTraktComments: boolean; // Show Trakt comments in metadata screens
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DEFAULT_SETTINGS: AppSettings = {
|
export const DEFAULT_SETTINGS: AppSettings = {
|
||||||
|
|
@ -130,6 +132,8 @@ export const DEFAULT_SETTINGS: AppSettings = {
|
||||||
// Metadata enrichment
|
// Metadata enrichment
|
||||||
enrichMetadataWithTMDB: true,
|
enrichMetadataWithTMDB: true,
|
||||||
useTmdbLocalizedMetadata: false,
|
useTmdbLocalizedMetadata: false,
|
||||||
|
// Trakt integration
|
||||||
|
showTraktComments: true, // Show Trakt comments by default when authenticated
|
||||||
};
|
};
|
||||||
|
|
||||||
const SETTINGS_STORAGE_KEY = 'app_settings';
|
const SETTINGS_STORAGE_KEY = 'app_settings';
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ export const useTraktComments = ({
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const [hasMore, setHasMore] = useState(false);
|
const [hasMore, setHasMore] = useState(false);
|
||||||
const [page, setPage] = useState(1);
|
const [page, setPage] = useState(1);
|
||||||
const [isAuthenticated, setIsAuthenticated] = useState(false);
|
const [isAuthenticated, setIsAuthenticated] = useState<boolean | null>(null);
|
||||||
|
|
||||||
const COMMENTS_PER_PAGE = 10;
|
const COMMENTS_PER_PAGE = 10;
|
||||||
|
|
||||||
|
|
@ -42,12 +42,14 @@ export const useTraktComments = ({
|
||||||
};
|
};
|
||||||
|
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
|
// Set to null initially to indicate we're checking
|
||||||
|
setIsAuthenticated(null);
|
||||||
checkAuth();
|
checkAuth();
|
||||||
}
|
}
|
||||||
}, [enabled]);
|
}, [enabled]);
|
||||||
|
|
||||||
const loadComments = useCallback(async (pageNum: number = 1, append: boolean = false) => {
|
const loadComments = useCallback(async (pageNum: number = 1, append: boolean = false) => {
|
||||||
if (!enabled || !imdbId || !isAuthenticated) {
|
if (!enabled || !imdbId || isAuthenticated !== true) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -103,7 +105,7 @@ export const useTraktComments = ({
|
||||||
}, [enabled, imdbId, tmdbId, type, season, episode, isAuthenticated]);
|
}, [enabled, imdbId, tmdbId, type, season, episode, isAuthenticated]);
|
||||||
|
|
||||||
const loadMore = useCallback(() => {
|
const loadMore = useCallback(() => {
|
||||||
if (!loading && hasMore && isAuthenticated) {
|
if (!loading && hasMore && isAuthenticated === true) {
|
||||||
loadComments(page + 1, true);
|
loadComments(page + 1, true);
|
||||||
}
|
}
|
||||||
}, [loading, hasMore, page, loadComments, isAuthenticated]);
|
}, [loading, hasMore, page, loadComments, isAuthenticated]);
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ const redirectUri = makeRedirectUri({
|
||||||
});
|
});
|
||||||
|
|
||||||
const TraktSettingsScreen: React.FC = () => {
|
const TraktSettingsScreen: React.FC = () => {
|
||||||
const { settings } = useSettings();
|
const { settings, updateSetting } = useSettings();
|
||||||
const isDarkMode = settings.enableDarkMode;
|
const isDarkMode = settings.enableDarkMode;
|
||||||
const navigation = useNavigation();
|
const navigation = useNavigation();
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
|
@ -247,7 +247,7 @@ const TraktSettingsScreen: React.FC = () => {
|
||||||
>
|
>
|
||||||
<View style={[
|
<View style={[
|
||||||
styles.card,
|
styles.card,
|
||||||
{ backgroundColor: isDarkMode ? currentTheme.colors.elevation2 : currentTheme.colors.white }
|
{ backgroundColor: currentTheme.colors.elevation2 }
|
||||||
]}>
|
]}>
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<View style={styles.loadingContainer}>
|
<View style={styles.loadingContainer}>
|
||||||
|
|
@ -357,67 +357,73 @@ const TraktSettingsScreen: React.FC = () => {
|
||||||
<View style={styles.settingsSection}>
|
<View style={styles.settingsSection}>
|
||||||
<Text style={[
|
<Text style={[
|
||||||
styles.sectionTitle,
|
styles.sectionTitle,
|
||||||
{ color: isDarkMode ? currentTheme.colors.highEmphasis : currentTheme.colors.textDark }
|
{ color: currentTheme.colors.highEmphasis }
|
||||||
]}>
|
]}>
|
||||||
Sync Settings
|
Sync Settings
|
||||||
</Text>
|
</Text>
|
||||||
<View style={[
|
<View style={[
|
||||||
styles.infoBox,
|
styles.infoBox,
|
||||||
{ backgroundColor: isDarkMode ? currentTheme.colors.elevation1 : '#F5F7FB', borderColor: isDarkMode ? 'rgba(255,255,255,0.06)' : '#E3E8F0' }
|
{ backgroundColor: currentTheme.colors.elevation1, borderColor: currentTheme.colors.border }
|
||||||
]}>
|
]}>
|
||||||
<Text style={[
|
<Text style={[
|
||||||
styles.infoText,
|
styles.infoText,
|
||||||
{ color: isDarkMode ? currentTheme.colors.mediumEmphasis : currentTheme.colors.textMutedDark }
|
{ color: currentTheme.colors.mediumEmphasis }
|
||||||
]}>
|
]}>
|
||||||
When connected to Trakt, Continue Watching is sourced from Trakt. Account sync for watch progress is disabled to avoid conflicts.
|
When connected to Trakt, Continue Watching is sourced from Trakt. Account sync for watch progress is disabled to avoid conflicts.
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.settingItem}>
|
<View style={styles.settingItem}>
|
||||||
<View style={{ flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' }}>
|
<View style={styles.settingContent}>
|
||||||
<View style={{ flex: 1 }}>
|
<View style={styles.settingTextContainer}>
|
||||||
<Text style={[
|
<Text style={[
|
||||||
styles.settingLabel,
|
styles.settingLabel,
|
||||||
{ color: isDarkMode ? currentTheme.colors.highEmphasis : currentTheme.colors.textDark }
|
{ color: currentTheme.colors.highEmphasis }
|
||||||
]}>
|
]}>
|
||||||
Auto-sync playback progress
|
Auto-sync playback progress
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={[
|
<Text style={[
|
||||||
styles.settingDescription,
|
styles.settingDescription,
|
||||||
{ color: isDarkMode ? currentTheme.colors.mediumEmphasis : currentTheme.colors.textMutedDark }
|
{ color: currentTheme.colors.mediumEmphasis }
|
||||||
]}>
|
]}>
|
||||||
Automatically sync watch progress to Trakt
|
Automatically sync watch progress to Trakt
|
||||||
</Text>
|
</Text>
|
||||||
|
</View>
|
||||||
|
<View style={styles.settingToggleContainer}>
|
||||||
|
<Switch
|
||||||
|
value={autosyncSettings.enabled}
|
||||||
|
onValueChange={setAutosyncEnabled}
|
||||||
|
trackColor={{
|
||||||
|
false: currentTheme.colors.border,
|
||||||
|
true: currentTheme.colors.primary + '80'
|
||||||
|
}}
|
||||||
|
thumbColor={autosyncSettings.enabled ? currentTheme.colors.white : currentTheme.colors.mediumEmphasis}
|
||||||
|
/>
|
||||||
</View>
|
</View>
|
||||||
<Switch
|
|
||||||
value={autosyncSettings.enabled}
|
|
||||||
onValueChange={setAutosyncEnabled}
|
|
||||||
trackColor={{
|
|
||||||
false: isDarkMode ? 'rgba(120,120,128,0.3)' : 'rgba(120,120,128,0.2)',
|
|
||||||
true: currentTheme.colors.primary + '80'
|
|
||||||
}}
|
|
||||||
thumbColor={autosyncSettings.enabled ? currentTheme.colors.primary : (isDarkMode ? '#ffffff' : '#f4f3f4')}
|
|
||||||
/>
|
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.settingItem}>
|
<View style={styles.settingItem}>
|
||||||
<Text style={[
|
<View style={styles.settingContent}>
|
||||||
styles.settingLabel,
|
<View style={styles.settingTextContainer}>
|
||||||
{ color: isDarkMode ? currentTheme.colors.highEmphasis : currentTheme.colors.textDark }
|
<Text style={[
|
||||||
]}>
|
styles.settingLabel,
|
||||||
Import watched history
|
{ color: currentTheme.colors.highEmphasis }
|
||||||
</Text>
|
]}>
|
||||||
<Text style={[
|
Import watched history
|
||||||
styles.settingDescription,
|
</Text>
|
||||||
{ color: isDarkMode ? currentTheme.colors.mediumEmphasis : currentTheme.colors.textMutedDark }
|
<Text style={[
|
||||||
]}>
|
styles.settingDescription,
|
||||||
Use "Sync Now" to import your watch history and progress from Trakt
|
{ color: currentTheme.colors.mediumEmphasis }
|
||||||
</Text>
|
]}>
|
||||||
|
Use "Sync Now" to import your watch history and progress from Trakt
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
</View>
|
</View>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={[
|
style={[
|
||||||
styles.button,
|
styles.button,
|
||||||
{
|
{
|
||||||
backgroundColor: isDarkMode ? currentTheme.colors.primary + '40' : currentTheme.colors.primary + '20',
|
backgroundColor: currentTheme.colors.card,
|
||||||
opacity: isSyncing ? 0.6 : 1
|
opacity: isSyncing ? 0.6 : 1
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
|
|
@ -431,20 +437,58 @@ const TraktSettingsScreen: React.FC = () => {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{isSyncing ? (
|
{isSyncing ? (
|
||||||
<ActivityIndicator
|
<ActivityIndicator
|
||||||
size="small"
|
size="small"
|
||||||
color={isDarkMode ? currentTheme.colors.primary : currentTheme.colors.primary}
|
color={currentTheme.colors.primary}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<Text style={[
|
<Text style={[
|
||||||
styles.buttonText,
|
styles.buttonText,
|
||||||
{ color: isDarkMode ? currentTheme.colors.primary : currentTheme.colors.primary }
|
{ color: currentTheme.colors.primary }
|
||||||
]}>
|
]}>
|
||||||
Sync Now
|
Sync Now
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
|
||||||
|
{/* Display Settings Section */}
|
||||||
|
<Text style={[
|
||||||
|
styles.sectionTitle,
|
||||||
|
{ color: currentTheme.colors.highEmphasis, marginTop: 24 }
|
||||||
|
]}>
|
||||||
|
Display Settings
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<View style={styles.settingItem}>
|
||||||
|
<View style={styles.settingContent}>
|
||||||
|
<View style={styles.settingTextContainer}>
|
||||||
|
<Text style={[
|
||||||
|
styles.settingLabel,
|
||||||
|
{ color: currentTheme.colors.highEmphasis }
|
||||||
|
]}>
|
||||||
|
Show Trakt Comments
|
||||||
|
</Text>
|
||||||
|
<Text style={[
|
||||||
|
styles.settingDescription,
|
||||||
|
{ color: currentTheme.colors.mediumEmphasis }
|
||||||
|
]}>
|
||||||
|
Display Trakt comments in metadata screens when available
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
<View style={styles.settingToggleContainer}>
|
||||||
|
<Switch
|
||||||
|
value={settings.showTraktComments}
|
||||||
|
onValueChange={(value) => updateSetting('showTraktComments', value)}
|
||||||
|
trackColor={{
|
||||||
|
false: currentTheme.colors.border,
|
||||||
|
true: currentTheme.colors.primary + '80'
|
||||||
|
}}
|
||||||
|
thumbColor={settings.showTraktComments ? currentTheme.colors.white : currentTheme.colors.mediumEmphasis}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
@ -612,10 +656,25 @@ const styles = StyleSheet.create({
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
fontWeight: '600',
|
fontWeight: '600',
|
||||||
marginBottom: 16,
|
marginBottom: 16,
|
||||||
|
marginTop: 8,
|
||||||
},
|
},
|
||||||
settingItem: {
|
settingItem: {
|
||||||
marginBottom: 16,
|
marginBottom: 16,
|
||||||
},
|
},
|
||||||
|
settingContent: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
alignItems: 'center',
|
||||||
|
minHeight: 60,
|
||||||
|
},
|
||||||
|
settingTextContainer: {
|
||||||
|
flex: 1,
|
||||||
|
marginRight: 16,
|
||||||
|
},
|
||||||
|
settingToggleContainer: {
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
settingLabel: {
|
settingLabel: {
|
||||||
fontSize: 15,
|
fontSize: 15,
|
||||||
fontWeight: '500',
|
fontWeight: '500',
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue