UI changes

This commit is contained in:
tapframe 2025-10-05 19:58:24 +05:30
parent 6db159e944
commit 15ab70b524
4 changed files with 155 additions and 60 deletions

View file

@ -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,

View file

@ -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';

View file

@ -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]);

View file

@ -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',