trakt update

This commit is contained in:
tapframe 2025-09-15 17:40:50 +05:30
parent 22a118c383
commit 3b460ec63f
9 changed files with 127 additions and 57 deletions

View file

@ -16,7 +16,7 @@
<application android:name=".MainApplication" android:label="@string/app_name" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:allowBackup="true" android:theme="@style/AppTheme" android:supportsRtl="true">
<meta-data android:name="expo.modules.updates.ENABLED" android:value="true"/>
<meta-data android:name="expo.modules.updates.EXPO_RUNTIME_VERSION" android:value="@string/expo_runtime_version"/>
<meta-data android:name="expo.modules.updates.EXPO_UPDATES_CHECK_ON_LAUNCH" android:value="ALWAYS"/>
<meta-data android:name="expo.modules.updates.EXPO_UPDATES_CHECK_ON_LAUNCH" android:value="ERROR_RECOVERY_ONLY"/>
<meta-data android:name="expo.modules.updates.EXPO_UPDATES_LAUNCH_WAIT_MS" android:value="30000"/>
<meta-data android:name="expo.modules.updates.EXPO_UPDATE_URL" android:value="https://grim-reyna-tapframe-69970143.koyeb.app/api/manifest"/>
<activity android:name=".MainActivity" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout|uiMode|locale|layoutDirection" android:launchMode="singleTask" android:windowSoftInputMode="adjustResize" android:theme="@style/Theme.App.SplashScreen" android:exported="true" android:screenOrientation="unspecified">

View file

@ -3,4 +3,5 @@
<color name="iconBackground">#020404</color>
<color name="colorPrimary">#023c69</color>
<color name="colorPrimaryDark">#020404</color>
<color name="activityBackground">#020404</color>
</resources>

View file

@ -5,6 +5,7 @@
<item name="android:editTextBackground">@drawable/rn_edit_text_material</item>
<item name="colorPrimary">@color/colorPrimary</item>
<item name="android:statusBarColor">#020404</item>
<item name="android:windowBackground">@color/activityBackground</item>
</style>
<style name="ResetEditText" parent="@android:style/Widget.EditText">
<item name="android:padding">0dp</item>

View file

@ -4,6 +4,7 @@
"slug": "nuvio",
"version": "0.6.0-beta.11",
"orientation": "default",
"backgroundColor": "#020404",
"icon": "./assets/ios/AppIcon.appiconset/Icon-App-60x60@3x.png",
"userInterfaceStyle": "dark",
"scheme": "stremioexpo",

View file

@ -3,29 +3,42 @@ import { View, StyleSheet, Animated, Easing } from 'react-native';
import TraktIcon from '../../../assets/rating-icons/trakt.svg';
export const TraktLoadingSpinner = () => {
const spinValue = useRef(new Animated.Value(0)).current;
const pulseValue = useRef(new Animated.Value(0)).current;
useEffect(() => {
const spin = Animated.loop(
Animated.timing(spinValue, {
const pulse = Animated.loop(
Animated.sequence([
Animated.timing(pulseValue, {
toValue: 1,
duration: 1500,
easing: Easing.linear,
duration: 900,
easing: Easing.inOut(Easing.ease),
useNativeDriver: true,
}),
Animated.timing(pulseValue, {
toValue: 0,
duration: 900,
easing: Easing.inOut(Easing.ease),
useNativeDriver: true,
})
])
);
spin.start();
return () => spin.stop();
}, [spinValue]);
pulse.start();
return () => pulse.stop();
}, [pulseValue]);
const rotation = spinValue.interpolate({
const opacity = pulseValue.interpolate({
inputRange: [0, 1],
outputRange: ['0deg', '360deg'],
outputRange: [0.65, 1],
});
const scale = pulseValue.interpolate({
inputRange: [0, 1],
outputRange: [0.95, 1.05],
});
return (
<View style={styles.container}>
<Animated.View style={{ transform: [{ rotate: rotation }] }}>
<Animated.View style={{ opacity, transform: [{ scale }] }}>
<TraktIcon width={80} height={80} />
</Animated.View>
</View>

View file

@ -326,6 +326,17 @@ const TraktSettingsScreen: React.FC = () => {
]}>
Sync Settings
</Text>
<View style={[
styles.infoBox,
{ backgroundColor: isDarkMode ? currentTheme.colors.elevation1 : '#F5F7FB', borderColor: isDarkMode ? 'rgba(255,255,255,0.06)' : '#E3E8F0' }
]}>
<Text style={[
styles.infoText,
{ color: isDarkMode ? currentTheme.colors.mediumEmphasis : currentTheme.colors.textMutedDark }
]}>
When connected to Trakt, Continue Watching is sourced from Trakt. Account sync for watch progress is disabled to avoid conflicts.
</Text>
</View>
<View style={styles.settingItem}>
<View style={{ flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' }}>
<View style={{ flex: 1 }}>
@ -564,6 +575,16 @@ const styles = StyleSheet.create({
settingDescription: {
fontSize: 14,
},
infoBox: {
padding: 12,
borderRadius: 8,
borderWidth: 1,
marginBottom: 16,
},
infoText: {
fontSize: 13,
lineHeight: 18,
},
});
export default TraktSettingsScreen;

View file

@ -7,6 +7,7 @@ import { catalogService, StreamingContent } from './catalogService';
// import localScraperService from './localScraperService';
import { settingsEmitter } from '../hooks/useSettings';
import { logger } from '../utils/logger';
import { traktService } from './traktService';
type WatchProgressRow = {
user_id: string;
@ -81,6 +82,7 @@ class SyncService {
const user = await accountService.getCurrentUser();
if (!user) return;
const userId = user.id;
const traktActive = await traktService.isAuthenticated();
const addChannel = (table: string, handler: (payload: any) => void) => {
const channel = supabase
@ -91,6 +93,8 @@ class SyncService {
logger.log(`[Sync] Realtime subscribed: ${table}`);
};
// Watch progress realtime is disabled when Trakt is active
if (!traktActive) {
// Watch progress: apply granular updates (ignore self-caused pushes via suppressPush)
addChannel('watch_progress', async (payload) => {
try {
@ -129,6 +133,9 @@ class SyncService {
this.suppressPush = false;
}
});
} else {
logger.log('[Sync] Trakt active → skipping watch_progress realtime subscription');
}
const debouncedPull = (payload?: any) => {
if (payload?.table) logger.log(`[Sync][rt] change on ${payload.table} → debounced fullPull`);
@ -352,9 +359,10 @@ class SyncService {
const user = await accountService.getCurrentUser();
if (!user) return;
const userId = user.id;
const traktActive = await traktService.isAuthenticated();
await Promise.allSettled([
(async () => {
(!traktActive ? (async () => {
logger.log('[Sync] pull watch_progress');
const { data: wp } = await supabase
.from('watch_progress')
@ -397,7 +405,7 @@ class SyncService {
}
} catch {}
}
})(),
})() : Promise.resolve()),
(async () => {
logger.log('[Sync] pull user_settings');
const { data: us } = await supabase
@ -673,6 +681,13 @@ class SyncService {
async pushWatchProgress(): Promise<void> {
const user = await accountService.getCurrentUser();
if (!user) return;
// When Trakt is authenticated, disable account push for continue watching
try {
if (await traktService.isAuthenticated()) {
logger.log('[Sync] Trakt active → skipping push watch_progress');
return;
}
} catch {}
const userId = user.id;
const unsynced = await storageService.getUnsyncedProgress();
logger.log(`[Sync] push watch_progress rows=${unsynced.length}`);
@ -746,6 +761,13 @@ class SyncService {
private async softDeleteWatchProgress(type: string, id: string, episodeId?: string): Promise<void> {
const user = await accountService.getCurrentUser();
if (!user) return;
// When Trakt is authenticated, do not propagate deletes to account server for watch progress
try {
if (await traktService.isAuthenticated()) {
logger.log('[Sync] Trakt active → skipping softDelete watch_progress');
return;
}
} catch {}
try {
const { error } = await supabase
.from('watch_progress')

1
src/types/svg.d.ts vendored
View file

@ -1,3 +1,4 @@
import * as React from 'react';
declare module '*.svg' {
import { SvgProps } from 'react-native-svg';
const content: React.FC<SvgProps>;

View file

@ -5,6 +5,16 @@
"jsx": "react-jsx",
"esModuleInterop": true,
"target": "es2017",
"downlevelIteration": true
}
"downlevelIteration": true,
"typeRoots": [
"./node_modules/@types",
"./src/types"
]
},
"include": [
"src/**/*",
"App.tsx",
"index.ts",
"assets/**/*.svg"
]
}