mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-04-21 16:51:57 +00:00
Merge branch 'main' into saimuelbr/main
This commit is contained in:
commit
e6faa7c59f
30 changed files with 21611 additions and 20166 deletions
|
|
@ -768,7 +768,17 @@ const AndroidVideoPlayer: React.FC = () => {
|
|||
onProgress={handleProgress}
|
||||
onSeek={(data) => {
|
||||
playerState.isSeeking.current = false;
|
||||
if (data.currentTime) traktAutosync.handleProgressUpdate(data.currentTime, playerState.duration, true);
|
||||
if (data.currentTime) {
|
||||
if (id && type && playerState.duration > 0) {
|
||||
void storageService.setWatchProgress(id, type, {
|
||||
currentTime: data.currentTime,
|
||||
duration: playerState.duration,
|
||||
lastUpdated: Date.now(),
|
||||
addonId: currentStreamProvider
|
||||
}, episodeId);
|
||||
}
|
||||
traktAutosync.handleProgressUpdate(data.currentTime, playerState.duration, true);
|
||||
}
|
||||
}}
|
||||
onEnd={() => {
|
||||
if (modals.showEpisodeStreamsModal) return;
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ import { useTraktAutosync } from '../../hooks/useTraktAutosync';
|
|||
import { useMetadata } from '../../hooks/useMetadata';
|
||||
import { usePlayerGestureControls } from '../../hooks/usePlayerGestureControls';
|
||||
import stremioService from '../../services/stremioService';
|
||||
import { storageService } from '../../services/storageService';
|
||||
import { logger } from '../../utils/logger';
|
||||
|
||||
// Utils
|
||||
|
|
@ -227,7 +228,15 @@ const KSPlayerCore: React.FC = () => {
|
|||
currentTime,
|
||||
duration,
|
||||
isSeeking,
|
||||
isMounted
|
||||
isMounted,
|
||||
onSeekComplete: (timeInSeconds) => {
|
||||
if (!id || !type || duration <= 0) return;
|
||||
void storageService.setWatchProgress(id, type, {
|
||||
currentTime: timeInSeconds,
|
||||
duration,
|
||||
lastUpdated: Date.now()
|
||||
}, episodeId);
|
||||
}
|
||||
});
|
||||
|
||||
const watchProgress = useWatchProgress(
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ interface PlayerControlsConfig {
|
|||
duration: number;
|
||||
isSeeking: MutableRefObject<boolean>;
|
||||
isMounted: MutableRefObject<boolean>;
|
||||
onSeekComplete?: (timeInSeconds: number) => void;
|
||||
}
|
||||
|
||||
export const usePlayerControls = (config: PlayerControlsConfig) => {
|
||||
|
|
@ -27,7 +28,8 @@ export const usePlayerControls = (config: PlayerControlsConfig) => {
|
|||
currentTime,
|
||||
duration,
|
||||
isSeeking,
|
||||
isMounted
|
||||
isMounted,
|
||||
onSeekComplete
|
||||
} = config;
|
||||
|
||||
// iOS seeking helpers
|
||||
|
|
@ -54,6 +56,7 @@ export const usePlayerControls = (config: PlayerControlsConfig) => {
|
|||
|
||||
// Actually perform the seek
|
||||
playerRef.current.seek(timeInSeconds);
|
||||
onSeekComplete?.(timeInSeconds);
|
||||
|
||||
// Debounce the seeking state reset
|
||||
seekTimeoutRef.current = setTimeout(() => {
|
||||
|
|
@ -62,7 +65,7 @@ export const usePlayerControls = (config: PlayerControlsConfig) => {
|
|||
}
|
||||
}, 500);
|
||||
}
|
||||
}, [duration, paused, playerRef, isSeeking, isMounted]);
|
||||
}, [duration, paused, playerRef, isSeeking, isMounted, onSeekComplete]);
|
||||
|
||||
const skip = useCallback((seconds: number) => {
|
||||
seekToTime(currentTime + seconds);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { useState, useEffect, useRef } from 'react';
|
||||
import { AppState, AppStateStatus } from 'react-native';
|
||||
import { AppState } from 'react-native';
|
||||
import { storageService } from '../../../services/storageService';
|
||||
import { logger } from '../../../utils/logger';
|
||||
import { useSettings } from '../../../hooks/useSettings';
|
||||
|
|
@ -19,10 +19,9 @@ export const useWatchProgress = (
|
|||
const [savedDuration, setSavedDuration] = useState<number | null>(null);
|
||||
const [initialPosition, setInitialPosition] = useState<number | null>(null);
|
||||
const [showResumeOverlay, setShowResumeOverlay] = useState(false);
|
||||
const [progressSaveInterval, setProgressSaveInterval] = useState<NodeJS.Timeout | null>(null);
|
||||
|
||||
const { settings: appSettings } = useSettings();
|
||||
const initialSeekTargetRef = useRef<number | null>(null);
|
||||
const wasPausedRef = useRef<boolean>(paused);
|
||||
|
||||
// Values refs for unmount cleanup
|
||||
const currentTimeRef = useRef(currentTime);
|
||||
|
|
@ -126,22 +125,16 @@ export const useWatchProgress = (
|
|||
}
|
||||
};
|
||||
|
||||
// Save Interval
|
||||
|
||||
useEffect(() => {
|
||||
if (id && type && !paused && duration > 0) {
|
||||
if (progressSaveInterval) clearInterval(progressSaveInterval);
|
||||
|
||||
const interval = setInterval(() => {
|
||||
saveWatchProgress();
|
||||
}, 10000);
|
||||
|
||||
setProgressSaveInterval(interval);
|
||||
return () => {
|
||||
clearInterval(interval);
|
||||
setProgressSaveInterval(null);
|
||||
};
|
||||
if (wasPausedRef.current !== paused) {
|
||||
const becamePaused = paused;
|
||||
wasPausedRef.current = paused;
|
||||
if (becamePaused) {
|
||||
void saveWatchProgress();
|
||||
}
|
||||
}
|
||||
}, [id, type, paused, currentTime, duration]);
|
||||
}, [paused]);
|
||||
|
||||
// Unmount Save - deferred to allow navigation to complete first
|
||||
useEffect(() => {
|
||||
|
|
|
|||
|
|
@ -759,7 +759,65 @@
|
|||
},
|
||||
"clear_data_desc": "سيؤدي هذا إلى إعادة تعيين كل الإعدادات ومسح كل البيانات المخزنة مؤقتاً. هل أنت متأكد؟",
|
||||
"app_updates": "تحديثات التطبيق",
|
||||
"about_nuvio": "حول Nuvio"
|
||||
"about_nuvio": "حول Nuvio",
|
||||
"cloud_sync": {
|
||||
"title": "Nuvio Sync",
|
||||
"description": "Sync data across your Nuvio devices",
|
||||
"hero_title": "Cloud Sync",
|
||||
"hero_subtitle": "Keep your addons, progress, and library aligned across all devices.",
|
||||
"auth": {
|
||||
"account": "Account",
|
||||
"not_configured": "Supabase not configured",
|
||||
"not_authenticated": "Not authenticated",
|
||||
"email_session": "Email session",
|
||||
"signed_in_as": "Signed in as {{email}}",
|
||||
"not_signed_in": "Not signed in",
|
||||
"effective_owner": "Effective owner: {{id}}"
|
||||
},
|
||||
"stats": {
|
||||
"title": "Database Statistics",
|
||||
"plugins": "Plugins",
|
||||
"addons": "Addons",
|
||||
"watch_progress": "Watch Progress",
|
||||
"library_items": "Library Items",
|
||||
"watched_items": "Watched Items",
|
||||
"signin_required": "Sign in to load remote data counts."
|
||||
},
|
||||
"actions": {
|
||||
"title": "Actions",
|
||||
"description": "Pull to update this device from the cloud, or push from this device as the latest source.",
|
||||
"pull_btn": "Pull from Cloud",
|
||||
"push_btn": "Push from Device",
|
||||
"manage_account": "Manage Account",
|
||||
"sign_out": "Sign Out",
|
||||
"sign_in_up": "Sign In / Up"
|
||||
},
|
||||
"alerts": {
|
||||
"pull_success_title": "Cloud Data Pulled",
|
||||
"pull_success_msg": "The latest cloud data has been downloaded to this device.",
|
||||
"pull_failed_title": "Pull Failed",
|
||||
"pull_failed_msg": "Failed to download data from the cloud",
|
||||
"push_success_title": "Push Completed",
|
||||
"push_success_msg": "Device data has been uploaded to the cloud.",
|
||||
"push_failed_title": "Push Failed",
|
||||
"push_failed_msg": "Failed to upload local data",
|
||||
"sign_out_failed": "Sign Out Failed",
|
||||
"sign_out_failed_title": "Logout Error"
|
||||
},
|
||||
"external_sync": {
|
||||
"title": "External Sync Priority",
|
||||
"active_msg": "{{services}} is active. Watch progress and library updates are managed by these services instead of Nuvio cloud database.",
|
||||
"inactive_msg": "If Trakt or Simkl sync is enabled, watch progress and library updates will use those services instead of Nuvio cloud database."
|
||||
},
|
||||
"pre_auth": {
|
||||
"title": "Before Syncing",
|
||||
"description": "Sign in to start cloud sync and keep your data consistent across devices.",
|
||||
"point_1": "• Addons and plugins settings",
|
||||
"point_2": "• Watch progress and library",
|
||||
"env_warning": "Set EXPO_PUBLIC_SUPABASE_URL and EXPO_PUBLIC_SUPABASE_ANON_KEY to enable sync."
|
||||
},
|
||||
"connection": "Connection"
|
||||
}
|
||||
},
|
||||
"privacy": {
|
||||
"title": "الخصوصية والبيانات",
|
||||
|
|
|
|||
|
|
@ -764,7 +764,65 @@
|
|||
},
|
||||
"clear_data_desc": "Това ще нулира всички настройки и ще изчисти всички кеширани данни. Сигурни ли сте?",
|
||||
"app_updates": "Обновявания на приложението",
|
||||
"about_nuvio": "Относно Nuvio"
|
||||
"about_nuvio": "Относно Nuvio",
|
||||
"cloud_sync": {
|
||||
"title": "Nuvio Sync",
|
||||
"description": "Sync data across your Nuvio devices",
|
||||
"hero_title": "Cloud Sync",
|
||||
"hero_subtitle": "Keep your addons, progress, and library aligned across all devices.",
|
||||
"auth": {
|
||||
"account": "Account",
|
||||
"not_configured": "Supabase not configured",
|
||||
"not_authenticated": "Not authenticated",
|
||||
"email_session": "Email session",
|
||||
"signed_in_as": "Signed in as {{email}}",
|
||||
"not_signed_in": "Not signed in",
|
||||
"effective_owner": "Effective owner: {{id}}"
|
||||
},
|
||||
"stats": {
|
||||
"title": "Database Statistics",
|
||||
"plugins": "Plugins",
|
||||
"addons": "Addons",
|
||||
"watch_progress": "Watch Progress",
|
||||
"library_items": "Library Items",
|
||||
"watched_items": "Watched Items",
|
||||
"signin_required": "Sign in to load remote data counts."
|
||||
},
|
||||
"actions": {
|
||||
"title": "Actions",
|
||||
"description": "Pull to update this device from the cloud, or push from this device as the latest source.",
|
||||
"pull_btn": "Pull from Cloud",
|
||||
"push_btn": "Push from Device",
|
||||
"manage_account": "Manage Account",
|
||||
"sign_out": "Sign Out",
|
||||
"sign_in_up": "Sign In / Up"
|
||||
},
|
||||
"alerts": {
|
||||
"pull_success_title": "Cloud Data Pulled",
|
||||
"pull_success_msg": "The latest cloud data has been downloaded to this device.",
|
||||
"pull_failed_title": "Pull Failed",
|
||||
"pull_failed_msg": "Failed to download data from the cloud",
|
||||
"push_success_title": "Push Completed",
|
||||
"push_success_msg": "Device data has been uploaded to the cloud.",
|
||||
"push_failed_title": "Push Failed",
|
||||
"push_failed_msg": "Failed to upload local data",
|
||||
"sign_out_failed": "Sign Out Failed",
|
||||
"sign_out_failed_title": "Logout Error"
|
||||
},
|
||||
"external_sync": {
|
||||
"title": "External Sync Priority",
|
||||
"active_msg": "{{services}} is active. Watch progress and library updates are managed by these services instead of Nuvio cloud database.",
|
||||
"inactive_msg": "If Trakt or Simkl sync is enabled, watch progress and library updates will use those services instead of Nuvio cloud database."
|
||||
},
|
||||
"pre_auth": {
|
||||
"title": "Before Syncing",
|
||||
"description": "Sign in to start cloud sync and keep your data consistent across devices.",
|
||||
"point_1": "• Addons and plugins settings",
|
||||
"point_2": "• Watch progress and library",
|
||||
"env_warning": "Set EXPO_PUBLIC_SUPABASE_URL and EXPO_PUBLIC_SUPABASE_ANON_KEY to enable sync."
|
||||
},
|
||||
"connection": "Connection"
|
||||
}
|
||||
},
|
||||
"privacy": {
|
||||
"title": "Поверителност и данни",
|
||||
|
|
|
|||
|
|
@ -765,7 +765,65 @@
|
|||
},
|
||||
"clear_data_desc": "Això restablirà tota la configuració i esborrarà totes les dades en memòria cau. Estàs segur?",
|
||||
"app_updates": "Actualitzacions de l'aplicació",
|
||||
"about_nuvio": "Quant a Nuvio"
|
||||
"about_nuvio": "Quant a Nuvio",
|
||||
"cloud_sync": {
|
||||
"title": "Nuvio Sync",
|
||||
"description": "Sync data across your Nuvio devices",
|
||||
"hero_title": "Cloud Sync",
|
||||
"hero_subtitle": "Keep your addons, progress, and library aligned across all devices.",
|
||||
"auth": {
|
||||
"account": "Account",
|
||||
"not_configured": "Supabase not configured",
|
||||
"not_authenticated": "Not authenticated",
|
||||
"email_session": "Email session",
|
||||
"signed_in_as": "Signed in as {{email}}",
|
||||
"not_signed_in": "Not signed in",
|
||||
"effective_owner": "Effective owner: {{id}}"
|
||||
},
|
||||
"stats": {
|
||||
"title": "Database Statistics",
|
||||
"plugins": "Plugins",
|
||||
"addons": "Addons",
|
||||
"watch_progress": "Watch Progress",
|
||||
"library_items": "Library Items",
|
||||
"watched_items": "Watched Items",
|
||||
"signin_required": "Sign in to load remote data counts."
|
||||
},
|
||||
"actions": {
|
||||
"title": "Actions",
|
||||
"description": "Pull to update this device from the cloud, or push from this device as the latest source.",
|
||||
"pull_btn": "Pull from Cloud",
|
||||
"push_btn": "Push from Device",
|
||||
"manage_account": "Manage Account",
|
||||
"sign_out": "Sign Out",
|
||||
"sign_in_up": "Sign In / Up"
|
||||
},
|
||||
"alerts": {
|
||||
"pull_success_title": "Cloud Data Pulled",
|
||||
"pull_success_msg": "The latest cloud data has been downloaded to this device.",
|
||||
"pull_failed_title": "Pull Failed",
|
||||
"pull_failed_msg": "Failed to download data from the cloud",
|
||||
"push_success_title": "Push Completed",
|
||||
"push_success_msg": "Device data has been uploaded to the cloud.",
|
||||
"push_failed_title": "Push Failed",
|
||||
"push_failed_msg": "Failed to upload local data",
|
||||
"sign_out_failed": "Sign Out Failed",
|
||||
"sign_out_failed_title": "Logout Error"
|
||||
},
|
||||
"external_sync": {
|
||||
"title": "External Sync Priority",
|
||||
"active_msg": "{{services}} is active. Watch progress and library updates are managed by these services instead of Nuvio cloud database.",
|
||||
"inactive_msg": "If Trakt or Simkl sync is enabled, watch progress and library updates will use those services instead of Nuvio cloud database."
|
||||
},
|
||||
"pre_auth": {
|
||||
"title": "Before Syncing",
|
||||
"description": "Sign in to start cloud sync and keep your data consistent across devices.",
|
||||
"point_1": "• Addons and plugins settings",
|
||||
"point_2": "• Watch progress and library",
|
||||
"env_warning": "Set EXPO_PUBLIC_SUPABASE_URL and EXPO_PUBLIC_SUPABASE_ANON_KEY to enable sync."
|
||||
},
|
||||
"connection": "Connection"
|
||||
}
|
||||
},
|
||||
"privacy": {
|
||||
"title": "Privadesa i dades",
|
||||
|
|
|
|||
|
|
@ -754,7 +754,65 @@
|
|||
},
|
||||
"clear_data_desc": "Tímto dojde k resetování všech nastavení a vymazání všech dat v mezipaměti. Jste si jisti?",
|
||||
"app_updates": "Aktualizace aplikace",
|
||||
"about_nuvio": "O aplikaci Nuvio"
|
||||
"about_nuvio": "O aplikaci Nuvio",
|
||||
"cloud_sync": {
|
||||
"title": "Nuvio Sync",
|
||||
"description": "Sync data across your Nuvio devices",
|
||||
"hero_title": "Cloud Sync",
|
||||
"hero_subtitle": "Keep your addons, progress, and library aligned across all devices.",
|
||||
"auth": {
|
||||
"account": "Account",
|
||||
"not_configured": "Supabase not configured",
|
||||
"not_authenticated": "Not authenticated",
|
||||
"email_session": "Email session",
|
||||
"signed_in_as": "Signed in as {{email}}",
|
||||
"not_signed_in": "Not signed in",
|
||||
"effective_owner": "Effective owner: {{id}}"
|
||||
},
|
||||
"stats": {
|
||||
"title": "Database Statistics",
|
||||
"plugins": "Plugins",
|
||||
"addons": "Addons",
|
||||
"watch_progress": "Watch Progress",
|
||||
"library_items": "Library Items",
|
||||
"watched_items": "Watched Items",
|
||||
"signin_required": "Sign in to load remote data counts."
|
||||
},
|
||||
"actions": {
|
||||
"title": "Actions",
|
||||
"description": "Pull to update this device from the cloud, or push from this device as the latest source.",
|
||||
"pull_btn": "Pull from Cloud",
|
||||
"push_btn": "Push from Device",
|
||||
"manage_account": "Manage Account",
|
||||
"sign_out": "Sign Out",
|
||||
"sign_in_up": "Sign In / Up"
|
||||
},
|
||||
"alerts": {
|
||||
"pull_success_title": "Cloud Data Pulled",
|
||||
"pull_success_msg": "The latest cloud data has been downloaded to this device.",
|
||||
"pull_failed_title": "Pull Failed",
|
||||
"pull_failed_msg": "Failed to download data from the cloud",
|
||||
"push_success_title": "Push Completed",
|
||||
"push_success_msg": "Device data has been uploaded to the cloud.",
|
||||
"push_failed_title": "Push Failed",
|
||||
"push_failed_msg": "Failed to upload local data",
|
||||
"sign_out_failed": "Sign Out Failed",
|
||||
"sign_out_failed_title": "Logout Error"
|
||||
},
|
||||
"external_sync": {
|
||||
"title": "External Sync Priority",
|
||||
"active_msg": "{{services}} is active. Watch progress and library updates are managed by these services instead of Nuvio cloud database.",
|
||||
"inactive_msg": "If Trakt or Simkl sync is enabled, watch progress and library updates will use those services instead of Nuvio cloud database."
|
||||
},
|
||||
"pre_auth": {
|
||||
"title": "Before Syncing",
|
||||
"description": "Sign in to start cloud sync and keep your data consistent across devices.",
|
||||
"point_1": "• Addons and plugins settings",
|
||||
"point_2": "• Watch progress and library",
|
||||
"env_warning": "Set EXPO_PUBLIC_SUPABASE_URL and EXPO_PUBLIC_SUPABASE_ANON_KEY to enable sync."
|
||||
},
|
||||
"connection": "Connection"
|
||||
}
|
||||
},
|
||||
"privacy": {
|
||||
"title": "Soukromí a data",
|
||||
|
|
|
|||
|
|
@ -759,7 +759,65 @@
|
|||
},
|
||||
"clear_data_desc": "Dies setzt alle Einstellungen zurück und löscht alle zwischengespeicherten Daten. Sind Sie sicher?",
|
||||
"app_updates": "App-Updates",
|
||||
"about_nuvio": "Über Nuvio"
|
||||
"about_nuvio": "Über Nuvio",
|
||||
"cloud_sync": {
|
||||
"title": "Nuvio Sync",
|
||||
"description": "Sync data across your Nuvio devices",
|
||||
"hero_title": "Cloud Sync",
|
||||
"hero_subtitle": "Keep your addons, progress, and library aligned across all devices.",
|
||||
"auth": {
|
||||
"account": "Account",
|
||||
"not_configured": "Supabase not configured",
|
||||
"not_authenticated": "Not authenticated",
|
||||
"email_session": "Email session",
|
||||
"signed_in_as": "Signed in as {{email}}",
|
||||
"not_signed_in": "Not signed in",
|
||||
"effective_owner": "Effective owner: {{id}}"
|
||||
},
|
||||
"stats": {
|
||||
"title": "Database Statistics",
|
||||
"plugins": "Plugins",
|
||||
"addons": "Addons",
|
||||
"watch_progress": "Watch Progress",
|
||||
"library_items": "Library Items",
|
||||
"watched_items": "Watched Items",
|
||||
"signin_required": "Sign in to load remote data counts."
|
||||
},
|
||||
"actions": {
|
||||
"title": "Actions",
|
||||
"description": "Pull to update this device from the cloud, or push from this device as the latest source.",
|
||||
"pull_btn": "Pull from Cloud",
|
||||
"push_btn": "Push from Device",
|
||||
"manage_account": "Manage Account",
|
||||
"sign_out": "Sign Out",
|
||||
"sign_in_up": "Sign In / Up"
|
||||
},
|
||||
"alerts": {
|
||||
"pull_success_title": "Cloud Data Pulled",
|
||||
"pull_success_msg": "The latest cloud data has been downloaded to this device.",
|
||||
"pull_failed_title": "Pull Failed",
|
||||
"pull_failed_msg": "Failed to download data from the cloud",
|
||||
"push_success_title": "Push Completed",
|
||||
"push_success_msg": "Device data has been uploaded to the cloud.",
|
||||
"push_failed_title": "Push Failed",
|
||||
"push_failed_msg": "Failed to upload local data",
|
||||
"sign_out_failed": "Sign Out Failed",
|
||||
"sign_out_failed_title": "Logout Error"
|
||||
},
|
||||
"external_sync": {
|
||||
"title": "External Sync Priority",
|
||||
"active_msg": "{{services}} is active. Watch progress and library updates are managed by these services instead of Nuvio cloud database.",
|
||||
"inactive_msg": "If Trakt or Simkl sync is enabled, watch progress and library updates will use those services instead of Nuvio cloud database."
|
||||
},
|
||||
"pre_auth": {
|
||||
"title": "Before Syncing",
|
||||
"description": "Sign in to start cloud sync and keep your data consistent across devices.",
|
||||
"point_1": "• Addons and plugins settings",
|
||||
"point_2": "• Watch progress and library",
|
||||
"env_warning": "Set EXPO_PUBLIC_SUPABASE_URL and EXPO_PUBLIC_SUPABASE_ANON_KEY to enable sync."
|
||||
},
|
||||
"connection": "Connection"
|
||||
}
|
||||
},
|
||||
"privacy": {
|
||||
"title": "Datenschutz & Daten",
|
||||
|
|
|
|||
|
|
@ -765,65 +765,65 @@
|
|||
},
|
||||
"clear_data_desc": "This will reset all settings and clear all cached data. Are you sure?",
|
||||
"app_updates": "App Updates",
|
||||
"about_nuvio": "About Nuvio"
|
||||
},
|
||||
"cloud_sync": {
|
||||
"title": "Nuvio Sync",
|
||||
"description": "Sync data across your Nuvio devices",
|
||||
"hero_title": "Cloud Sync",
|
||||
"hero_subtitle": "Keep your addons, progress, and library aligned across all devices.",
|
||||
"auth": {
|
||||
"account": "Account",
|
||||
"not_configured": "Supabase not configured",
|
||||
"not_authenticated": "Not authenticated",
|
||||
"email_session": "Email session",
|
||||
"signed_in_as": "Signed in as {{email}}",
|
||||
"not_signed_in": "Not signed in",
|
||||
"effective_owner": "Effective owner: {{id}}"
|
||||
},
|
||||
"stats": {
|
||||
"title": "Database Statistics",
|
||||
"plugins": "Plugins",
|
||||
"addons": "Addons",
|
||||
"watch_progress": "Watch Progress",
|
||||
"library_items": "Library Items",
|
||||
"watched_items": "Watched Items",
|
||||
"signin_required": "Sign in to load remote data counts."
|
||||
},
|
||||
"actions": {
|
||||
"title": "Actions",
|
||||
"description": "Pull to update this device from the cloud, or push from this device as the latest source.",
|
||||
"pull_btn": "Pull from Cloud",
|
||||
"push_btn": "Push from Device",
|
||||
"manage_account": "Manage Account",
|
||||
"sign_out": "Sign Out",
|
||||
"sign_in_up": "Sign In / Up"
|
||||
},
|
||||
"alerts": {
|
||||
"pull_success_title": "Cloud Data Pulled",
|
||||
"pull_success_msg": "The latest cloud data has been downloaded to this device.",
|
||||
"pull_failed_title": "Pull Failed",
|
||||
"pull_failed_msg": "Failed to download data from the cloud",
|
||||
"push_success_title": "Push Completed",
|
||||
"push_success_msg": "Device data has been uploaded to the cloud.",
|
||||
"push_failed_title": "Push Failed",
|
||||
"push_failed_msg": "Failed to upload local data",
|
||||
"sign_out_failed": "Sign Out Failed",
|
||||
"sign_out_failed_title": "Logout Error"
|
||||
},
|
||||
"external_sync": {
|
||||
"title": "External Sync Priority",
|
||||
"active_msg": "{{services}} is active. Watch progress and library updates are managed by these services instead of Nuvio cloud database.",
|
||||
"inactive_msg": "If Trakt or Simkl sync is enabled, watch progress and library updates will use those services instead of Nuvio cloud database."
|
||||
},
|
||||
"pre_auth": {
|
||||
"title": "Before Syncing",
|
||||
"description": "Sign in to start cloud sync and keep your data consistent across devices.",
|
||||
"point_1": "• Addons and plugins settings",
|
||||
"point_2": "• Watch progress and library",
|
||||
"env_warning": "Set EXPO_PUBLIC_SUPABASE_URL and EXPO_PUBLIC_SUPABASE_ANON_KEY to enable sync."
|
||||
},
|
||||
"connection": "Connection"
|
||||
"about_nuvio": "About Nuvio",
|
||||
"cloud_sync": {
|
||||
"title": "Nuvio Sync",
|
||||
"description": "Sync data across your Nuvio devices",
|
||||
"hero_title": "Cloud Sync",
|
||||
"hero_subtitle": "Keep your addons, progress, and library aligned across all devices.",
|
||||
"auth": {
|
||||
"account": "Account",
|
||||
"not_configured": "Supabase not configured",
|
||||
"not_authenticated": "Not authenticated",
|
||||
"email_session": "Email session",
|
||||
"signed_in_as": "Signed in as {{email}}",
|
||||
"not_signed_in": "Not signed in",
|
||||
"effective_owner": "Effective owner: {{id}}"
|
||||
},
|
||||
"stats": {
|
||||
"title": "Database Statistics",
|
||||
"plugins": "Plugins",
|
||||
"addons": "Addons",
|
||||
"watch_progress": "Watch Progress",
|
||||
"library_items": "Library Items",
|
||||
"watched_items": "Watched Items",
|
||||
"signin_required": "Sign in to load remote data counts."
|
||||
},
|
||||
"actions": {
|
||||
"title": "Actions",
|
||||
"description": "Pull to update this device from the cloud, or push from this device as the latest source.",
|
||||
"pull_btn": "Pull from Cloud",
|
||||
"push_btn": "Push from Device",
|
||||
"manage_account": "Manage Account",
|
||||
"sign_out": "Sign Out",
|
||||
"sign_in_up": "Sign In / Up"
|
||||
},
|
||||
"alerts": {
|
||||
"pull_success_title": "Cloud Data Pulled",
|
||||
"pull_success_msg": "The latest cloud data has been downloaded to this device.",
|
||||
"pull_failed_title": "Pull Failed",
|
||||
"pull_failed_msg": "Failed to download data from the cloud",
|
||||
"push_success_title": "Push Completed",
|
||||
"push_success_msg": "Device data has been uploaded to the cloud.",
|
||||
"push_failed_title": "Push Failed",
|
||||
"push_failed_msg": "Failed to upload local data",
|
||||
"sign_out_failed": "Sign Out Failed",
|
||||
"sign_out_failed_title": "Logout Error"
|
||||
},
|
||||
"external_sync": {
|
||||
"title": "External Sync Priority",
|
||||
"active_msg": "{{services}} is active. Watch progress and library updates are managed by these services instead of Nuvio cloud database.",
|
||||
"inactive_msg": "If Trakt or Simkl sync is enabled, watch progress and library updates will use those services instead of Nuvio cloud database."
|
||||
},
|
||||
"pre_auth": {
|
||||
"title": "Before Syncing",
|
||||
"description": "Sign in to start cloud sync and keep your data consistent across devices.",
|
||||
"point_1": "• Addons and plugins settings",
|
||||
"point_2": "• Watch progress and library",
|
||||
"env_warning": "Set EXPO_PUBLIC_SUPABASE_URL and EXPO_PUBLIC_SUPABASE_ANON_KEY to enable sync."
|
||||
},
|
||||
"connection": "Connection"
|
||||
}
|
||||
},
|
||||
"privacy": {
|
||||
"title": "Privacy & Data",
|
||||
|
|
|
|||
|
|
@ -759,7 +759,65 @@
|
|||
},
|
||||
"clear_data_desc": "Esto restablecerá todos los ajustes y borrará todos los datos almacenados en caché. ¿Estás seguro?",
|
||||
"app_updates": "Actualizaciones de la app",
|
||||
"about_nuvio": "Acerca de Nuvio"
|
||||
"about_nuvio": "Acerca de Nuvio",
|
||||
"cloud_sync": {
|
||||
"title": "Nuvio Sync",
|
||||
"description": "Sync data across your Nuvio devices",
|
||||
"hero_title": "Cloud Sync",
|
||||
"hero_subtitle": "Keep your addons, progress, and library aligned across all devices.",
|
||||
"auth": {
|
||||
"account": "Account",
|
||||
"not_configured": "Supabase not configured",
|
||||
"not_authenticated": "Not authenticated",
|
||||
"email_session": "Email session",
|
||||
"signed_in_as": "Signed in as {{email}}",
|
||||
"not_signed_in": "Not signed in",
|
||||
"effective_owner": "Effective owner: {{id}}"
|
||||
},
|
||||
"stats": {
|
||||
"title": "Database Statistics",
|
||||
"plugins": "Plugins",
|
||||
"addons": "Addons",
|
||||
"watch_progress": "Watch Progress",
|
||||
"library_items": "Library Items",
|
||||
"watched_items": "Watched Items",
|
||||
"signin_required": "Sign in to load remote data counts."
|
||||
},
|
||||
"actions": {
|
||||
"title": "Actions",
|
||||
"description": "Pull to update this device from the cloud, or push from this device as the latest source.",
|
||||
"pull_btn": "Pull from Cloud",
|
||||
"push_btn": "Push from Device",
|
||||
"manage_account": "Manage Account",
|
||||
"sign_out": "Sign Out",
|
||||
"sign_in_up": "Sign In / Up"
|
||||
},
|
||||
"alerts": {
|
||||
"pull_success_title": "Cloud Data Pulled",
|
||||
"pull_success_msg": "The latest cloud data has been downloaded to this device.",
|
||||
"pull_failed_title": "Pull Failed",
|
||||
"pull_failed_msg": "Failed to download data from the cloud",
|
||||
"push_success_title": "Push Completed",
|
||||
"push_success_msg": "Device data has been uploaded to the cloud.",
|
||||
"push_failed_title": "Push Failed",
|
||||
"push_failed_msg": "Failed to upload local data",
|
||||
"sign_out_failed": "Sign Out Failed",
|
||||
"sign_out_failed_title": "Logout Error"
|
||||
},
|
||||
"external_sync": {
|
||||
"title": "External Sync Priority",
|
||||
"active_msg": "{{services}} is active. Watch progress and library updates are managed by these services instead of Nuvio cloud database.",
|
||||
"inactive_msg": "If Trakt or Simkl sync is enabled, watch progress and library updates will use those services instead of Nuvio cloud database."
|
||||
},
|
||||
"pre_auth": {
|
||||
"title": "Before Syncing",
|
||||
"description": "Sign in to start cloud sync and keep your data consistent across devices.",
|
||||
"point_1": "• Addons and plugins settings",
|
||||
"point_2": "• Watch progress and library",
|
||||
"env_warning": "Set EXPO_PUBLIC_SUPABASE_URL and EXPO_PUBLIC_SUPABASE_ANON_KEY to enable sync."
|
||||
},
|
||||
"connection": "Connection"
|
||||
}
|
||||
},
|
||||
"privacy": {
|
||||
"title": "Privacidad y Datos",
|
||||
|
|
|
|||
|
|
@ -764,7 +764,65 @@
|
|||
},
|
||||
"clear_data_desc": "I-re-reset nito ang lahat ng settings at buburahin ang lahat ng cached data. Sigurado ka ba?",
|
||||
"app_updates": "Mga Update ng App",
|
||||
"about_nuvio": "Tungkol sa Nuvio"
|
||||
"about_nuvio": "Tungkol sa Nuvio",
|
||||
"cloud_sync": {
|
||||
"title": "Nuvio Sync",
|
||||
"description": "Sync data across your Nuvio devices",
|
||||
"hero_title": "Cloud Sync",
|
||||
"hero_subtitle": "Keep your addons, progress, and library aligned across all devices.",
|
||||
"auth": {
|
||||
"account": "Account",
|
||||
"not_configured": "Supabase not configured",
|
||||
"not_authenticated": "Not authenticated",
|
||||
"email_session": "Email session",
|
||||
"signed_in_as": "Signed in as {{email}}",
|
||||
"not_signed_in": "Not signed in",
|
||||
"effective_owner": "Effective owner: {{id}}"
|
||||
},
|
||||
"stats": {
|
||||
"title": "Database Statistics",
|
||||
"plugins": "Plugins",
|
||||
"addons": "Addons",
|
||||
"watch_progress": "Watch Progress",
|
||||
"library_items": "Library Items",
|
||||
"watched_items": "Watched Items",
|
||||
"signin_required": "Sign in to load remote data counts."
|
||||
},
|
||||
"actions": {
|
||||
"title": "Actions",
|
||||
"description": "Pull to update this device from the cloud, or push from this device as the latest source.",
|
||||
"pull_btn": "Pull from Cloud",
|
||||
"push_btn": "Push from Device",
|
||||
"manage_account": "Manage Account",
|
||||
"sign_out": "Sign Out",
|
||||
"sign_in_up": "Sign In / Up"
|
||||
},
|
||||
"alerts": {
|
||||
"pull_success_title": "Cloud Data Pulled",
|
||||
"pull_success_msg": "The latest cloud data has been downloaded to this device.",
|
||||
"pull_failed_title": "Pull Failed",
|
||||
"pull_failed_msg": "Failed to download data from the cloud",
|
||||
"push_success_title": "Push Completed",
|
||||
"push_success_msg": "Device data has been uploaded to the cloud.",
|
||||
"push_failed_title": "Push Failed",
|
||||
"push_failed_msg": "Failed to upload local data",
|
||||
"sign_out_failed": "Sign Out Failed",
|
||||
"sign_out_failed_title": "Logout Error"
|
||||
},
|
||||
"external_sync": {
|
||||
"title": "External Sync Priority",
|
||||
"active_msg": "{{services}} is active. Watch progress and library updates are managed by these services instead of Nuvio cloud database.",
|
||||
"inactive_msg": "If Trakt or Simkl sync is enabled, watch progress and library updates will use those services instead of Nuvio cloud database."
|
||||
},
|
||||
"pre_auth": {
|
||||
"title": "Before Syncing",
|
||||
"description": "Sign in to start cloud sync and keep your data consistent across devices.",
|
||||
"point_1": "• Addons and plugins settings",
|
||||
"point_2": "• Watch progress and library",
|
||||
"env_warning": "Set EXPO_PUBLIC_SUPABASE_URL and EXPO_PUBLIC_SUPABASE_ANON_KEY to enable sync."
|
||||
},
|
||||
"connection": "Connection"
|
||||
}
|
||||
},
|
||||
"privacy": {
|
||||
"title": "Privacy at Data",
|
||||
|
|
|
|||
|
|
@ -759,7 +759,65 @@
|
|||
},
|
||||
"clear_data_desc": "Cela réinitialisera tous les paramètres et effacera toutes les données en cache. Êtes-vous sûr ?",
|
||||
"app_updates": "Mises à jour de l'application",
|
||||
"about_nuvio": "À propos de Nuvio"
|
||||
"about_nuvio": "À propos de Nuvio",
|
||||
"cloud_sync": {
|
||||
"title": "Nuvio Sync",
|
||||
"description": "Sync data across your Nuvio devices",
|
||||
"hero_title": "Cloud Sync",
|
||||
"hero_subtitle": "Keep your addons, progress, and library aligned across all devices.",
|
||||
"auth": {
|
||||
"account": "Account",
|
||||
"not_configured": "Supabase not configured",
|
||||
"not_authenticated": "Not authenticated",
|
||||
"email_session": "Email session",
|
||||
"signed_in_as": "Signed in as {{email}}",
|
||||
"not_signed_in": "Not signed in",
|
||||
"effective_owner": "Effective owner: {{id}}"
|
||||
},
|
||||
"stats": {
|
||||
"title": "Database Statistics",
|
||||
"plugins": "Plugins",
|
||||
"addons": "Addons",
|
||||
"watch_progress": "Watch Progress",
|
||||
"library_items": "Library Items",
|
||||
"watched_items": "Watched Items",
|
||||
"signin_required": "Sign in to load remote data counts."
|
||||
},
|
||||
"actions": {
|
||||
"title": "Actions",
|
||||
"description": "Pull to update this device from the cloud, or push from this device as the latest source.",
|
||||
"pull_btn": "Pull from Cloud",
|
||||
"push_btn": "Push from Device",
|
||||
"manage_account": "Manage Account",
|
||||
"sign_out": "Sign Out",
|
||||
"sign_in_up": "Sign In / Up"
|
||||
},
|
||||
"alerts": {
|
||||
"pull_success_title": "Cloud Data Pulled",
|
||||
"pull_success_msg": "The latest cloud data has been downloaded to this device.",
|
||||
"pull_failed_title": "Pull Failed",
|
||||
"pull_failed_msg": "Failed to download data from the cloud",
|
||||
"push_success_title": "Push Completed",
|
||||
"push_success_msg": "Device data has been uploaded to the cloud.",
|
||||
"push_failed_title": "Push Failed",
|
||||
"push_failed_msg": "Failed to upload local data",
|
||||
"sign_out_failed": "Sign Out Failed",
|
||||
"sign_out_failed_title": "Logout Error"
|
||||
},
|
||||
"external_sync": {
|
||||
"title": "External Sync Priority",
|
||||
"active_msg": "{{services}} is active. Watch progress and library updates are managed by these services instead of Nuvio cloud database.",
|
||||
"inactive_msg": "If Trakt or Simkl sync is enabled, watch progress and library updates will use those services instead of Nuvio cloud database."
|
||||
},
|
||||
"pre_auth": {
|
||||
"title": "Before Syncing",
|
||||
"description": "Sign in to start cloud sync and keep your data consistent across devices.",
|
||||
"point_1": "• Addons and plugins settings",
|
||||
"point_2": "• Watch progress and library",
|
||||
"env_warning": "Set EXPO_PUBLIC_SUPABASE_URL and EXPO_PUBLIC_SUPABASE_ANON_KEY to enable sync."
|
||||
},
|
||||
"connection": "Connection"
|
||||
}
|
||||
},
|
||||
"privacy": {
|
||||
"title": "Confidentialité et Données",
|
||||
|
|
|
|||
|
|
@ -764,7 +764,65 @@
|
|||
},
|
||||
"clear_data_desc": "פעולה זו תאפס את כל ההגדרות ותנקה את כל המידע השמור. האם אתם בטוחים?",
|
||||
"app_updates": "עדכוני אפליקציה",
|
||||
"about_nuvio": "אודות Nuvio"
|
||||
"about_nuvio": "אודות Nuvio",
|
||||
"cloud_sync": {
|
||||
"title": "Nuvio Sync",
|
||||
"description": "Sync data across your Nuvio devices",
|
||||
"hero_title": "Cloud Sync",
|
||||
"hero_subtitle": "Keep your addons, progress, and library aligned across all devices.",
|
||||
"auth": {
|
||||
"account": "Account",
|
||||
"not_configured": "Supabase not configured",
|
||||
"not_authenticated": "Not authenticated",
|
||||
"email_session": "Email session",
|
||||
"signed_in_as": "Signed in as {{email}}",
|
||||
"not_signed_in": "Not signed in",
|
||||
"effective_owner": "Effective owner: {{id}}"
|
||||
},
|
||||
"stats": {
|
||||
"title": "Database Statistics",
|
||||
"plugins": "Plugins",
|
||||
"addons": "Addons",
|
||||
"watch_progress": "Watch Progress",
|
||||
"library_items": "Library Items",
|
||||
"watched_items": "Watched Items",
|
||||
"signin_required": "Sign in to load remote data counts."
|
||||
},
|
||||
"actions": {
|
||||
"title": "Actions",
|
||||
"description": "Pull to update this device from the cloud, or push from this device as the latest source.",
|
||||
"pull_btn": "Pull from Cloud",
|
||||
"push_btn": "Push from Device",
|
||||
"manage_account": "Manage Account",
|
||||
"sign_out": "Sign Out",
|
||||
"sign_in_up": "Sign In / Up"
|
||||
},
|
||||
"alerts": {
|
||||
"pull_success_title": "Cloud Data Pulled",
|
||||
"pull_success_msg": "The latest cloud data has been downloaded to this device.",
|
||||
"pull_failed_title": "Pull Failed",
|
||||
"pull_failed_msg": "Failed to download data from the cloud",
|
||||
"push_success_title": "Push Completed",
|
||||
"push_success_msg": "Device data has been uploaded to the cloud.",
|
||||
"push_failed_title": "Push Failed",
|
||||
"push_failed_msg": "Failed to upload local data",
|
||||
"sign_out_failed": "Sign Out Failed",
|
||||
"sign_out_failed_title": "Logout Error"
|
||||
},
|
||||
"external_sync": {
|
||||
"title": "External Sync Priority",
|
||||
"active_msg": "{{services}} is active. Watch progress and library updates are managed by these services instead of Nuvio cloud database.",
|
||||
"inactive_msg": "If Trakt or Simkl sync is enabled, watch progress and library updates will use those services instead of Nuvio cloud database."
|
||||
},
|
||||
"pre_auth": {
|
||||
"title": "Before Syncing",
|
||||
"description": "Sign in to start cloud sync and keep your data consistent across devices.",
|
||||
"point_1": "• Addons and plugins settings",
|
||||
"point_2": "• Watch progress and library",
|
||||
"env_warning": "Set EXPO_PUBLIC_SUPABASE_URL and EXPO_PUBLIC_SUPABASE_ANON_KEY to enable sync."
|
||||
},
|
||||
"connection": "Connection"
|
||||
}
|
||||
},
|
||||
"privacy": {
|
||||
"title": "פרטיות ומידע",
|
||||
|
|
|
|||
|
|
@ -759,7 +759,65 @@
|
|||
},
|
||||
"clear_data_desc": "यह सभी सेटिंग्स को रीसेट कर देगा और सभी कैश किए गए डेटा को साफ़ कर देगा। क्या आप सुनिश्चित हैं?",
|
||||
"app_updates": "ऐप अपडेट",
|
||||
"about_nuvio": "Nuvio के बारे में"
|
||||
"about_nuvio": "Nuvio के बारे में",
|
||||
"cloud_sync": {
|
||||
"title": "Nuvio Sync",
|
||||
"description": "Sync data across your Nuvio devices",
|
||||
"hero_title": "Cloud Sync",
|
||||
"hero_subtitle": "Keep your addons, progress, and library aligned across all devices.",
|
||||
"auth": {
|
||||
"account": "Account",
|
||||
"not_configured": "Supabase not configured",
|
||||
"not_authenticated": "Not authenticated",
|
||||
"email_session": "Email session",
|
||||
"signed_in_as": "Signed in as {{email}}",
|
||||
"not_signed_in": "Not signed in",
|
||||
"effective_owner": "Effective owner: {{id}}"
|
||||
},
|
||||
"stats": {
|
||||
"title": "Database Statistics",
|
||||
"plugins": "Plugins",
|
||||
"addons": "Addons",
|
||||
"watch_progress": "Watch Progress",
|
||||
"library_items": "Library Items",
|
||||
"watched_items": "Watched Items",
|
||||
"signin_required": "Sign in to load remote data counts."
|
||||
},
|
||||
"actions": {
|
||||
"title": "Actions",
|
||||
"description": "Pull to update this device from the cloud, or push from this device as the latest source.",
|
||||
"pull_btn": "Pull from Cloud",
|
||||
"push_btn": "Push from Device",
|
||||
"manage_account": "Manage Account",
|
||||
"sign_out": "Sign Out",
|
||||
"sign_in_up": "Sign In / Up"
|
||||
},
|
||||
"alerts": {
|
||||
"pull_success_title": "Cloud Data Pulled",
|
||||
"pull_success_msg": "The latest cloud data has been downloaded to this device.",
|
||||
"pull_failed_title": "Pull Failed",
|
||||
"pull_failed_msg": "Failed to download data from the cloud",
|
||||
"push_success_title": "Push Completed",
|
||||
"push_success_msg": "Device data has been uploaded to the cloud.",
|
||||
"push_failed_title": "Push Failed",
|
||||
"push_failed_msg": "Failed to upload local data",
|
||||
"sign_out_failed": "Sign Out Failed",
|
||||
"sign_out_failed_title": "Logout Error"
|
||||
},
|
||||
"external_sync": {
|
||||
"title": "External Sync Priority",
|
||||
"active_msg": "{{services}} is active. Watch progress and library updates are managed by these services instead of Nuvio cloud database.",
|
||||
"inactive_msg": "If Trakt or Simkl sync is enabled, watch progress and library updates will use those services instead of Nuvio cloud database."
|
||||
},
|
||||
"pre_auth": {
|
||||
"title": "Before Syncing",
|
||||
"description": "Sign in to start cloud sync and keep your data consistent across devices.",
|
||||
"point_1": "• Addons and plugins settings",
|
||||
"point_2": "• Watch progress and library",
|
||||
"env_warning": "Set EXPO_PUBLIC_SUPABASE_URL and EXPO_PUBLIC_SUPABASE_ANON_KEY to enable sync."
|
||||
},
|
||||
"connection": "Connection"
|
||||
}
|
||||
},
|
||||
"privacy": {
|
||||
"title": "गोपनीयता और डेटा",
|
||||
|
|
|
|||
|
|
@ -747,7 +747,65 @@
|
|||
},
|
||||
"clear_data_desc": "Ovo će resetirati sve postavke i obrisati sve privremene podatke. Jeste li sigurni?",
|
||||
"app_updates": "Ažuriranja aplikacije",
|
||||
"about_nuvio": "O Nuviju"
|
||||
"about_nuvio": "O Nuviju",
|
||||
"cloud_sync": {
|
||||
"title": "Nuvio Sync",
|
||||
"description": "Sync data across your Nuvio devices",
|
||||
"hero_title": "Cloud Sync",
|
||||
"hero_subtitle": "Keep your addons, progress, and library aligned across all devices.",
|
||||
"auth": {
|
||||
"account": "Account",
|
||||
"not_configured": "Supabase not configured",
|
||||
"not_authenticated": "Not authenticated",
|
||||
"email_session": "Email session",
|
||||
"signed_in_as": "Signed in as {{email}}",
|
||||
"not_signed_in": "Not signed in",
|
||||
"effective_owner": "Effective owner: {{id}}"
|
||||
},
|
||||
"stats": {
|
||||
"title": "Database Statistics",
|
||||
"plugins": "Plugins",
|
||||
"addons": "Addons",
|
||||
"watch_progress": "Watch Progress",
|
||||
"library_items": "Library Items",
|
||||
"watched_items": "Watched Items",
|
||||
"signin_required": "Sign in to load remote data counts."
|
||||
},
|
||||
"actions": {
|
||||
"title": "Actions",
|
||||
"description": "Pull to update this device from the cloud, or push from this device as the latest source.",
|
||||
"pull_btn": "Pull from Cloud",
|
||||
"push_btn": "Push from Device",
|
||||
"manage_account": "Manage Account",
|
||||
"sign_out": "Sign Out",
|
||||
"sign_in_up": "Sign In / Up"
|
||||
},
|
||||
"alerts": {
|
||||
"pull_success_title": "Cloud Data Pulled",
|
||||
"pull_success_msg": "The latest cloud data has been downloaded to this device.",
|
||||
"pull_failed_title": "Pull Failed",
|
||||
"pull_failed_msg": "Failed to download data from the cloud",
|
||||
"push_success_title": "Push Completed",
|
||||
"push_success_msg": "Device data has been uploaded to the cloud.",
|
||||
"push_failed_title": "Push Failed",
|
||||
"push_failed_msg": "Failed to upload local data",
|
||||
"sign_out_failed": "Sign Out Failed",
|
||||
"sign_out_failed_title": "Logout Error"
|
||||
},
|
||||
"external_sync": {
|
||||
"title": "External Sync Priority",
|
||||
"active_msg": "{{services}} is active. Watch progress and library updates are managed by these services instead of Nuvio cloud database.",
|
||||
"inactive_msg": "If Trakt or Simkl sync is enabled, watch progress and library updates will use those services instead of Nuvio cloud database."
|
||||
},
|
||||
"pre_auth": {
|
||||
"title": "Before Syncing",
|
||||
"description": "Sign in to start cloud sync and keep your data consistent across devices.",
|
||||
"point_1": "• Addons and plugins settings",
|
||||
"point_2": "• Watch progress and library",
|
||||
"env_warning": "Set EXPO_PUBLIC_SUPABASE_URL and EXPO_PUBLIC_SUPABASE_ANON_KEY to enable sync."
|
||||
},
|
||||
"connection": "Connection"
|
||||
}
|
||||
},
|
||||
"privacy": {
|
||||
"title": "Privatnost i Podaci",
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -764,7 +764,65 @@
|
|||
},
|
||||
"clear_data_desc": "Dit zal alle instellingen resetten en alle gecachte gegevens wissen. Weet je het zeker?",
|
||||
"app_updates": "App Updates",
|
||||
"about_nuvio": "Over Nuvio"
|
||||
"about_nuvio": "Over Nuvio",
|
||||
"cloud_sync": {
|
||||
"title": "Nuvio Sync",
|
||||
"description": "Sync data across your Nuvio devices",
|
||||
"hero_title": "Cloud Sync",
|
||||
"hero_subtitle": "Keep your addons, progress, and library aligned across all devices.",
|
||||
"auth": {
|
||||
"account": "Account",
|
||||
"not_configured": "Supabase not configured",
|
||||
"not_authenticated": "Not authenticated",
|
||||
"email_session": "Email session",
|
||||
"signed_in_as": "Signed in as {{email}}",
|
||||
"not_signed_in": "Not signed in",
|
||||
"effective_owner": "Effective owner: {{id}}"
|
||||
},
|
||||
"stats": {
|
||||
"title": "Database Statistics",
|
||||
"plugins": "Plugins",
|
||||
"addons": "Addons",
|
||||
"watch_progress": "Watch Progress",
|
||||
"library_items": "Library Items",
|
||||
"watched_items": "Watched Items",
|
||||
"signin_required": "Sign in to load remote data counts."
|
||||
},
|
||||
"actions": {
|
||||
"title": "Actions",
|
||||
"description": "Pull to update this device from the cloud, or push from this device as the latest source.",
|
||||
"pull_btn": "Pull from Cloud",
|
||||
"push_btn": "Push from Device",
|
||||
"manage_account": "Manage Account",
|
||||
"sign_out": "Sign Out",
|
||||
"sign_in_up": "Sign In / Up"
|
||||
},
|
||||
"alerts": {
|
||||
"pull_success_title": "Cloud Data Pulled",
|
||||
"pull_success_msg": "The latest cloud data has been downloaded to this device.",
|
||||
"pull_failed_title": "Pull Failed",
|
||||
"pull_failed_msg": "Failed to download data from the cloud",
|
||||
"push_success_title": "Push Completed",
|
||||
"push_success_msg": "Device data has been uploaded to the cloud.",
|
||||
"push_failed_title": "Push Failed",
|
||||
"push_failed_msg": "Failed to upload local data",
|
||||
"sign_out_failed": "Sign Out Failed",
|
||||
"sign_out_failed_title": "Logout Error"
|
||||
},
|
||||
"external_sync": {
|
||||
"title": "External Sync Priority",
|
||||
"active_msg": "{{services}} is active. Watch progress and library updates are managed by these services instead of Nuvio cloud database.",
|
||||
"inactive_msg": "If Trakt or Simkl sync is enabled, watch progress and library updates will use those services instead of Nuvio cloud database."
|
||||
},
|
||||
"pre_auth": {
|
||||
"title": "Before Syncing",
|
||||
"description": "Sign in to start cloud sync and keep your data consistent across devices.",
|
||||
"point_1": "• Addons and plugins settings",
|
||||
"point_2": "• Watch progress and library",
|
||||
"env_warning": "Set EXPO_PUBLIC_SUPABASE_URL and EXPO_PUBLIC_SUPABASE_ANON_KEY to enable sync."
|
||||
},
|
||||
"connection": "Connection"
|
||||
}
|
||||
},
|
||||
"privacy": {
|
||||
"title": "Privacy & Gegevens",
|
||||
|
|
|
|||
|
|
@ -764,7 +764,65 @@
|
|||
},
|
||||
"clear_data_desc": "To zresetuje wszystkie ustawienia i wyczyści pamięć podręczną. Czy na pewno?",
|
||||
"app_updates": "Aktualizacje aplikacji",
|
||||
"about_nuvio": "O Nuvio"
|
||||
"about_nuvio": "O Nuvio",
|
||||
"cloud_sync": {
|
||||
"title": "Nuvio Sync",
|
||||
"description": "Sync data across your Nuvio devices",
|
||||
"hero_title": "Cloud Sync",
|
||||
"hero_subtitle": "Keep your addons, progress, and library aligned across all devices.",
|
||||
"auth": {
|
||||
"account": "Account",
|
||||
"not_configured": "Supabase not configured",
|
||||
"not_authenticated": "Not authenticated",
|
||||
"email_session": "Email session",
|
||||
"signed_in_as": "Signed in as {{email}}",
|
||||
"not_signed_in": "Not signed in",
|
||||
"effective_owner": "Effective owner: {{id}}"
|
||||
},
|
||||
"stats": {
|
||||
"title": "Database Statistics",
|
||||
"plugins": "Plugins",
|
||||
"addons": "Addons",
|
||||
"watch_progress": "Watch Progress",
|
||||
"library_items": "Library Items",
|
||||
"watched_items": "Watched Items",
|
||||
"signin_required": "Sign in to load remote data counts."
|
||||
},
|
||||
"actions": {
|
||||
"title": "Actions",
|
||||
"description": "Pull to update this device from the cloud, or push from this device as the latest source.",
|
||||
"pull_btn": "Pull from Cloud",
|
||||
"push_btn": "Push from Device",
|
||||
"manage_account": "Manage Account",
|
||||
"sign_out": "Sign Out",
|
||||
"sign_in_up": "Sign In / Up"
|
||||
},
|
||||
"alerts": {
|
||||
"pull_success_title": "Cloud Data Pulled",
|
||||
"pull_success_msg": "The latest cloud data has been downloaded to this device.",
|
||||
"pull_failed_title": "Pull Failed",
|
||||
"pull_failed_msg": "Failed to download data from the cloud",
|
||||
"push_success_title": "Push Completed",
|
||||
"push_success_msg": "Device data has been uploaded to the cloud.",
|
||||
"push_failed_title": "Push Failed",
|
||||
"push_failed_msg": "Failed to upload local data",
|
||||
"sign_out_failed": "Sign Out Failed",
|
||||
"sign_out_failed_title": "Logout Error"
|
||||
},
|
||||
"external_sync": {
|
||||
"title": "External Sync Priority",
|
||||
"active_msg": "{{services}} is active. Watch progress and library updates are managed by these services instead of Nuvio cloud database.",
|
||||
"inactive_msg": "If Trakt or Simkl sync is enabled, watch progress and library updates will use those services instead of Nuvio cloud database."
|
||||
},
|
||||
"pre_auth": {
|
||||
"title": "Before Syncing",
|
||||
"description": "Sign in to start cloud sync and keep your data consistent across devices.",
|
||||
"point_1": "• Addons and plugins settings",
|
||||
"point_2": "• Watch progress and library",
|
||||
"env_warning": "Set EXPO_PUBLIC_SUPABASE_URL and EXPO_PUBLIC_SUPABASE_ANON_KEY to enable sync."
|
||||
},
|
||||
"connection": "Connection"
|
||||
}
|
||||
},
|
||||
"privacy": {
|
||||
"title": "Prywatność i Dane",
|
||||
|
|
|
|||
|
|
@ -773,65 +773,65 @@
|
|||
},
|
||||
"clear_data_desc": "Isso redefinirá todas as configurações e limpará todos os dados em cache. Você tem certeza?",
|
||||
"app_updates": "Atualizações do App",
|
||||
"about_nuvio": "Sobre o Nuvio"
|
||||
},
|
||||
"cloud_sync": {
|
||||
"title": "Nuvio Sync",
|
||||
"description": "Sincronize dados entre seus dispositivos Nuvio",
|
||||
"hero_title": "Sincronização na Nuvem",
|
||||
"hero_subtitle": "Mantenha seus addons, progresso e biblioteca alinhados em todos os dispositivos.",
|
||||
"auth": {
|
||||
"account": "Conta",
|
||||
"not_configured": "Supabase não configurado",
|
||||
"not_authenticated": "Não autenticado",
|
||||
"email_session": "Sessão de email",
|
||||
"signed_in_as": "Logado como {{email}}",
|
||||
"not_signed_in": "Não logado",
|
||||
"effective_owner": "Proprietário efetivo: {{id}}"
|
||||
},
|
||||
"stats": {
|
||||
"title": "Estatísticas do Banco de Dados",
|
||||
"plugins": "Plugins",
|
||||
"addons": "Addons",
|
||||
"watch_progress": "Progresso",
|
||||
"library_items": "Itens na Biblioteca",
|
||||
"watched_items": "Itens Assistidos",
|
||||
"signin_required": "Faça login para carregar contagens de dados remotos."
|
||||
},
|
||||
"actions": {
|
||||
"title": "Ações",
|
||||
"description": "Baixe para atualizar este dispositivo a partir da nuvem, ou envie deste dispositivo como a fonte mais recente.",
|
||||
"pull_btn": "Baixar da Nuvem",
|
||||
"push_btn": "Enviar deste Dispositivo",
|
||||
"manage_account": "Gerenciar Conta",
|
||||
"sign_out": "Sair",
|
||||
"sign_in_up": "Entrar / Cadastrar"
|
||||
},
|
||||
"alerts": {
|
||||
"pull_success_title": "Dados da Nuvem Baixados",
|
||||
"pull_success_msg": "Os dados mais recentes da nuvem foram baixados para este dispositivo.",
|
||||
"pull_failed_title": "Falha ao Baixar",
|
||||
"pull_failed_msg": "Falha ao baixar dados da nuvem",
|
||||
"push_success_title": "Envio Concluído",
|
||||
"push_success_msg": "Os dados deste dispositivo foram enviados para a nuvem.",
|
||||
"push_failed_title": "Falha ao Enviar",
|
||||
"push_failed_msg": "Falha ao enviar dados locais",
|
||||
"sign_out_failed": "Falha ao Sair",
|
||||
"sign_out_failed_title": "Erro de Saida"
|
||||
},
|
||||
"external_sync": {
|
||||
"title": "Prioridade de Sincronização Externa",
|
||||
"active_msg": "{{services}} está ativo. O progresso e atualizações da biblioteca são gerenciados por esses serviços em vez do banco de dados Nuvio.",
|
||||
"inactive_msg": "Se a sincronização do Trakt ou Simkl estiver ativada, o progresso e a biblioteca usarão esses serviços em vez do banco de dados Nuvio."
|
||||
},
|
||||
"pre_auth": {
|
||||
"title": "Antes de Sincronizar",
|
||||
"description": "Faça login para iniciar a sincronização na nuvem e manter seus dados consistentes entre dispositivos.",
|
||||
"point_1": "• Configurações de addons e plugins",
|
||||
"point_2": "• Progresso de exibição e biblioteca",
|
||||
"env_warning": "Defina EXPO_PUBLIC_SUPABASE_URL e EXPO_PUBLIC_SUPABASE_ANON_KEY para habilitar a sincronização."
|
||||
},
|
||||
"connection": "Conexão"
|
||||
"about_nuvio": "Sobre o Nuvio",
|
||||
"cloud_sync": {
|
||||
"title": "Nuvio Sync",
|
||||
"description": "Sincronize dados entre seus dispositivos Nuvio",
|
||||
"hero_title": "Sincronização na Nuvem",
|
||||
"hero_subtitle": "Mantenha seus addons, progresso e biblioteca alinhados em todos os dispositivos.",
|
||||
"auth": {
|
||||
"account": "Conta",
|
||||
"not_configured": "Supabase não configurado",
|
||||
"not_authenticated": "Não autenticado",
|
||||
"email_session": "Sessão de email",
|
||||
"signed_in_as": "Logado como {{email}}",
|
||||
"not_signed_in": "Não logado",
|
||||
"effective_owner": "Proprietário efetivo: {{id}}"
|
||||
},
|
||||
"stats": {
|
||||
"title": "Estatísticas do Banco de Dados",
|
||||
"plugins": "Plugins",
|
||||
"addons": "Addons",
|
||||
"watch_progress": "Progresso",
|
||||
"library_items": "Itens na Biblioteca",
|
||||
"watched_items": "Itens Assistidos",
|
||||
"signin_required": "Faça login para carregar contagens de dados remotos."
|
||||
},
|
||||
"actions": {
|
||||
"title": "Ações",
|
||||
"description": "Baixe para atualizar este dispositivo a partir da nuvem, ou envie deste dispositivo como a fonte mais recente.",
|
||||
"pull_btn": "Baixar da Nuvem",
|
||||
"push_btn": "Enviar deste Dispositivo",
|
||||
"manage_account": "Gerenciar Conta",
|
||||
"sign_out": "Sair",
|
||||
"sign_in_up": "Entrar / Cadastrar"
|
||||
},
|
||||
"alerts": {
|
||||
"pull_success_title": "Dados da Nuvem Baixados",
|
||||
"pull_success_msg": "Os dados mais recentes da nuvem foram baixados para este dispositivo.",
|
||||
"pull_failed_title": "Falha ao Baixar",
|
||||
"pull_failed_msg": "Falha ao baixar dados da nuvem",
|
||||
"push_success_title": "Envio Concluído",
|
||||
"push_success_msg": "Os dados deste dispositivo foram enviados para a nuvem.",
|
||||
"push_failed_title": "Falha ao Enviar",
|
||||
"push_failed_msg": "Falha ao enviar dados locais",
|
||||
"sign_out_failed": "Falha ao Sair",
|
||||
"sign_out_failed_title": "Erro de Saida"
|
||||
},
|
||||
"external_sync": {
|
||||
"title": "Prioridade de Sincronização Externa",
|
||||
"active_msg": "{{services}} está ativo. O progresso e atualizações da biblioteca são gerenciados por esses serviços em vez do banco de dados Nuvio.",
|
||||
"inactive_msg": "Se a sincronização do Trakt ou Simkl estiver ativada, o progresso e a biblioteca usarão esses serviços em vez do banco de dados Nuvio."
|
||||
},
|
||||
"pre_auth": {
|
||||
"title": "Antes de Sincronizar",
|
||||
"description": "Faça login para iniciar a sincronização na nuvem e manter seus dados consistentes entre dispositivos.",
|
||||
"point_1": "• Configurações de addons e plugins",
|
||||
"point_2": "• Progresso de exibição e biblioteca",
|
||||
"env_warning": "Defina EXPO_PUBLIC_SUPABASE_URL e EXPO_PUBLIC_SUPABASE_ANON_KEY para habilitar a sincronização."
|
||||
},
|
||||
"connection": "Conexão"
|
||||
}
|
||||
},
|
||||
"privacy": {
|
||||
"title": "Privacidade e Dados",
|
||||
|
|
|
|||
|
|
@ -771,7 +771,65 @@
|
|||
},
|
||||
"clear_data_desc": "Isso redefinirá todas as configurações e limpará todos os dados em cache. Tens a certeza?",
|
||||
"app_updates": "Atualizações da App",
|
||||
"about_nuvio": "Sobre o Nuvio"
|
||||
"about_nuvio": "Sobre o Nuvio",
|
||||
"cloud_sync": {
|
||||
"title": "Nuvio Sync",
|
||||
"description": "Sync data across your Nuvio devices",
|
||||
"hero_title": "Cloud Sync",
|
||||
"hero_subtitle": "Keep your addons, progress, and library aligned across all devices.",
|
||||
"auth": {
|
||||
"account": "Account",
|
||||
"not_configured": "Supabase not configured",
|
||||
"not_authenticated": "Not authenticated",
|
||||
"email_session": "Email session",
|
||||
"signed_in_as": "Signed in as {{email}}",
|
||||
"not_signed_in": "Not signed in",
|
||||
"effective_owner": "Effective owner: {{id}}"
|
||||
},
|
||||
"stats": {
|
||||
"title": "Database Statistics",
|
||||
"plugins": "Plugins",
|
||||
"addons": "Addons",
|
||||
"watch_progress": "Watch Progress",
|
||||
"library_items": "Library Items",
|
||||
"watched_items": "Watched Items",
|
||||
"signin_required": "Sign in to load remote data counts."
|
||||
},
|
||||
"actions": {
|
||||
"title": "Actions",
|
||||
"description": "Pull to update this device from the cloud, or push from this device as the latest source.",
|
||||
"pull_btn": "Pull from Cloud",
|
||||
"push_btn": "Push from Device",
|
||||
"manage_account": "Manage Account",
|
||||
"sign_out": "Sign Out",
|
||||
"sign_in_up": "Sign In / Up"
|
||||
},
|
||||
"alerts": {
|
||||
"pull_success_title": "Cloud Data Pulled",
|
||||
"pull_success_msg": "The latest cloud data has been downloaded to this device.",
|
||||
"pull_failed_title": "Pull Failed",
|
||||
"pull_failed_msg": "Failed to download data from the cloud",
|
||||
"push_success_title": "Push Completed",
|
||||
"push_success_msg": "Device data has been uploaded to the cloud.",
|
||||
"push_failed_title": "Push Failed",
|
||||
"push_failed_msg": "Failed to upload local data",
|
||||
"sign_out_failed": "Sign Out Failed",
|
||||
"sign_out_failed_title": "Logout Error"
|
||||
},
|
||||
"external_sync": {
|
||||
"title": "External Sync Priority",
|
||||
"active_msg": "{{services}} is active. Watch progress and library updates are managed by these services instead of Nuvio cloud database.",
|
||||
"inactive_msg": "If Trakt or Simkl sync is enabled, watch progress and library updates will use those services instead of Nuvio cloud database."
|
||||
},
|
||||
"pre_auth": {
|
||||
"title": "Before Syncing",
|
||||
"description": "Sign in to start cloud sync and keep your data consistent across devices.",
|
||||
"point_1": "• Addons and plugins settings",
|
||||
"point_2": "• Watch progress and library",
|
||||
"env_warning": "Set EXPO_PUBLIC_SUPABASE_URL and EXPO_PUBLIC_SUPABASE_ANON_KEY to enable sync."
|
||||
},
|
||||
"connection": "Connection"
|
||||
}
|
||||
},
|
||||
"privacy": {
|
||||
"title": "Privacidade e Dados",
|
||||
|
|
|
|||
|
|
@ -764,7 +764,65 @@
|
|||
},
|
||||
"clear_data_desc": "Această acțiune va reseta toate setările și va șterge toate datele cache. Ești sigur?",
|
||||
"app_updates": "Actualizări aplicație",
|
||||
"about_nuvio": "Despre Nuvio"
|
||||
"about_nuvio": "Despre Nuvio",
|
||||
"cloud_sync": {
|
||||
"title": "Nuvio Sync",
|
||||
"description": "Sync data across your Nuvio devices",
|
||||
"hero_title": "Cloud Sync",
|
||||
"hero_subtitle": "Keep your addons, progress, and library aligned across all devices.",
|
||||
"auth": {
|
||||
"account": "Account",
|
||||
"not_configured": "Supabase not configured",
|
||||
"not_authenticated": "Not authenticated",
|
||||
"email_session": "Email session",
|
||||
"signed_in_as": "Signed in as {{email}}",
|
||||
"not_signed_in": "Not signed in",
|
||||
"effective_owner": "Effective owner: {{id}}"
|
||||
},
|
||||
"stats": {
|
||||
"title": "Database Statistics",
|
||||
"plugins": "Plugins",
|
||||
"addons": "Addons",
|
||||
"watch_progress": "Watch Progress",
|
||||
"library_items": "Library Items",
|
||||
"watched_items": "Watched Items",
|
||||
"signin_required": "Sign in to load remote data counts."
|
||||
},
|
||||
"actions": {
|
||||
"title": "Actions",
|
||||
"description": "Pull to update this device from the cloud, or push from this device as the latest source.",
|
||||
"pull_btn": "Pull from Cloud",
|
||||
"push_btn": "Push from Device",
|
||||
"manage_account": "Manage Account",
|
||||
"sign_out": "Sign Out",
|
||||
"sign_in_up": "Sign In / Up"
|
||||
},
|
||||
"alerts": {
|
||||
"pull_success_title": "Cloud Data Pulled",
|
||||
"pull_success_msg": "The latest cloud data has been downloaded to this device.",
|
||||
"pull_failed_title": "Pull Failed",
|
||||
"pull_failed_msg": "Failed to download data from the cloud",
|
||||
"push_success_title": "Push Completed",
|
||||
"push_success_msg": "Device data has been uploaded to the cloud.",
|
||||
"push_failed_title": "Push Failed",
|
||||
"push_failed_msg": "Failed to upload local data",
|
||||
"sign_out_failed": "Sign Out Failed",
|
||||
"sign_out_failed_title": "Logout Error"
|
||||
},
|
||||
"external_sync": {
|
||||
"title": "External Sync Priority",
|
||||
"active_msg": "{{services}} is active. Watch progress and library updates are managed by these services instead of Nuvio cloud database.",
|
||||
"inactive_msg": "If Trakt or Simkl sync is enabled, watch progress and library updates will use those services instead of Nuvio cloud database."
|
||||
},
|
||||
"pre_auth": {
|
||||
"title": "Before Syncing",
|
||||
"description": "Sign in to start cloud sync and keep your data consistent across devices.",
|
||||
"point_1": "• Addons and plugins settings",
|
||||
"point_2": "• Watch progress and library",
|
||||
"env_warning": "Set EXPO_PUBLIC_SUPABASE_URL and EXPO_PUBLIC_SUPABASE_ANON_KEY to enable sync."
|
||||
},
|
||||
"connection": "Connection"
|
||||
}
|
||||
},
|
||||
"privacy": {
|
||||
"title": "Confidențialitate și Date",
|
||||
|
|
|
|||
|
|
@ -764,7 +764,65 @@
|
|||
},
|
||||
"clear_data_desc": "Это сбросит все настройки и очистит кэш. Вы уверены?",
|
||||
"app_updates": "Обновления приложения",
|
||||
"about_nuvio": "О Nuvio"
|
||||
"about_nuvio": "О Nuvio",
|
||||
"cloud_sync": {
|
||||
"title": "Nuvio Sync",
|
||||
"description": "Sync data across your Nuvio devices",
|
||||
"hero_title": "Cloud Sync",
|
||||
"hero_subtitle": "Keep your addons, progress, and library aligned across all devices.",
|
||||
"auth": {
|
||||
"account": "Account",
|
||||
"not_configured": "Supabase not configured",
|
||||
"not_authenticated": "Not authenticated",
|
||||
"email_session": "Email session",
|
||||
"signed_in_as": "Signed in as {{email}}",
|
||||
"not_signed_in": "Not signed in",
|
||||
"effective_owner": "Effective owner: {{id}}"
|
||||
},
|
||||
"stats": {
|
||||
"title": "Database Statistics",
|
||||
"plugins": "Plugins",
|
||||
"addons": "Addons",
|
||||
"watch_progress": "Watch Progress",
|
||||
"library_items": "Library Items",
|
||||
"watched_items": "Watched Items",
|
||||
"signin_required": "Sign in to load remote data counts."
|
||||
},
|
||||
"actions": {
|
||||
"title": "Actions",
|
||||
"description": "Pull to update this device from the cloud, or push from this device as the latest source.",
|
||||
"pull_btn": "Pull from Cloud",
|
||||
"push_btn": "Push from Device",
|
||||
"manage_account": "Manage Account",
|
||||
"sign_out": "Sign Out",
|
||||
"sign_in_up": "Sign In / Up"
|
||||
},
|
||||
"alerts": {
|
||||
"pull_success_title": "Cloud Data Pulled",
|
||||
"pull_success_msg": "The latest cloud data has been downloaded to this device.",
|
||||
"pull_failed_title": "Pull Failed",
|
||||
"pull_failed_msg": "Failed to download data from the cloud",
|
||||
"push_success_title": "Push Completed",
|
||||
"push_success_msg": "Device data has been uploaded to the cloud.",
|
||||
"push_failed_title": "Push Failed",
|
||||
"push_failed_msg": "Failed to upload local data",
|
||||
"sign_out_failed": "Sign Out Failed",
|
||||
"sign_out_failed_title": "Logout Error"
|
||||
},
|
||||
"external_sync": {
|
||||
"title": "External Sync Priority",
|
||||
"active_msg": "{{services}} is active. Watch progress and library updates are managed by these services instead of Nuvio cloud database.",
|
||||
"inactive_msg": "If Trakt or Simkl sync is enabled, watch progress and library updates will use those services instead of Nuvio cloud database."
|
||||
},
|
||||
"pre_auth": {
|
||||
"title": "Before Syncing",
|
||||
"description": "Sign in to start cloud sync and keep your data consistent across devices.",
|
||||
"point_1": "• Addons and plugins settings",
|
||||
"point_2": "• Watch progress and library",
|
||||
"env_warning": "Set EXPO_PUBLIC_SUPABASE_URL and EXPO_PUBLIC_SUPABASE_ANON_KEY to enable sync."
|
||||
},
|
||||
"connection": "Connection"
|
||||
}
|
||||
},
|
||||
"privacy": {
|
||||
"title": "Конфиденциальность",
|
||||
|
|
|
|||
|
|
@ -764,7 +764,65 @@
|
|||
},
|
||||
"clear_data_desc": "To bo ponastavilo vse nastavitve in počistilo predpomnilnik. Ste prepričani?",
|
||||
"app_updates": "Posodobitve aplikacije",
|
||||
"about_nuvio": "O Nuvio"
|
||||
"about_nuvio": "O Nuvio",
|
||||
"cloud_sync": {
|
||||
"title": "Nuvio Sync",
|
||||
"description": "Sync data across your Nuvio devices",
|
||||
"hero_title": "Cloud Sync",
|
||||
"hero_subtitle": "Keep your addons, progress, and library aligned across all devices.",
|
||||
"auth": {
|
||||
"account": "Account",
|
||||
"not_configured": "Supabase not configured",
|
||||
"not_authenticated": "Not authenticated",
|
||||
"email_session": "Email session",
|
||||
"signed_in_as": "Signed in as {{email}}",
|
||||
"not_signed_in": "Not signed in",
|
||||
"effective_owner": "Effective owner: {{id}}"
|
||||
},
|
||||
"stats": {
|
||||
"title": "Database Statistics",
|
||||
"plugins": "Plugins",
|
||||
"addons": "Addons",
|
||||
"watch_progress": "Watch Progress",
|
||||
"library_items": "Library Items",
|
||||
"watched_items": "Watched Items",
|
||||
"signin_required": "Sign in to load remote data counts."
|
||||
},
|
||||
"actions": {
|
||||
"title": "Actions",
|
||||
"description": "Pull to update this device from the cloud, or push from this device as the latest source.",
|
||||
"pull_btn": "Pull from Cloud",
|
||||
"push_btn": "Push from Device",
|
||||
"manage_account": "Manage Account",
|
||||
"sign_out": "Sign Out",
|
||||
"sign_in_up": "Sign In / Up"
|
||||
},
|
||||
"alerts": {
|
||||
"pull_success_title": "Cloud Data Pulled",
|
||||
"pull_success_msg": "The latest cloud data has been downloaded to this device.",
|
||||
"pull_failed_title": "Pull Failed",
|
||||
"pull_failed_msg": "Failed to download data from the cloud",
|
||||
"push_success_title": "Push Completed",
|
||||
"push_success_msg": "Device data has been uploaded to the cloud.",
|
||||
"push_failed_title": "Push Failed",
|
||||
"push_failed_msg": "Failed to upload local data",
|
||||
"sign_out_failed": "Sign Out Failed",
|
||||
"sign_out_failed_title": "Logout Error"
|
||||
},
|
||||
"external_sync": {
|
||||
"title": "External Sync Priority",
|
||||
"active_msg": "{{services}} is active. Watch progress and library updates are managed by these services instead of Nuvio cloud database.",
|
||||
"inactive_msg": "If Trakt or Simkl sync is enabled, watch progress and library updates will use those services instead of Nuvio cloud database."
|
||||
},
|
||||
"pre_auth": {
|
||||
"title": "Before Syncing",
|
||||
"description": "Sign in to start cloud sync and keep your data consistent across devices.",
|
||||
"point_1": "• Addons and plugins settings",
|
||||
"point_2": "• Watch progress and library",
|
||||
"env_warning": "Set EXPO_PUBLIC_SUPABASE_URL and EXPO_PUBLIC_SUPABASE_ANON_KEY to enable sync."
|
||||
},
|
||||
"connection": "Connection"
|
||||
}
|
||||
},
|
||||
"privacy": {
|
||||
"title": "Zasebnost in podatki",
|
||||
|
|
|
|||
|
|
@ -764,7 +764,65 @@
|
|||
},
|
||||
"clear_data_desc": "Kjo do të rikthejë të gjitha cilësimet dhe do të fshijë të gjithë cache-in. Jeni të sigurt?",
|
||||
"app_updates": "Përditësimet e Aplikacionit",
|
||||
"about_nuvio": "Rreth Nuvio"
|
||||
"about_nuvio": "Rreth Nuvio",
|
||||
"cloud_sync": {
|
||||
"title": "Nuvio Sync",
|
||||
"description": "Sync data across your Nuvio devices",
|
||||
"hero_title": "Cloud Sync",
|
||||
"hero_subtitle": "Keep your addons, progress, and library aligned across all devices.",
|
||||
"auth": {
|
||||
"account": "Account",
|
||||
"not_configured": "Supabase not configured",
|
||||
"not_authenticated": "Not authenticated",
|
||||
"email_session": "Email session",
|
||||
"signed_in_as": "Signed in as {{email}}",
|
||||
"not_signed_in": "Not signed in",
|
||||
"effective_owner": "Effective owner: {{id}}"
|
||||
},
|
||||
"stats": {
|
||||
"title": "Database Statistics",
|
||||
"plugins": "Plugins",
|
||||
"addons": "Addons",
|
||||
"watch_progress": "Watch Progress",
|
||||
"library_items": "Library Items",
|
||||
"watched_items": "Watched Items",
|
||||
"signin_required": "Sign in to load remote data counts."
|
||||
},
|
||||
"actions": {
|
||||
"title": "Actions",
|
||||
"description": "Pull to update this device from the cloud, or push from this device as the latest source.",
|
||||
"pull_btn": "Pull from Cloud",
|
||||
"push_btn": "Push from Device",
|
||||
"manage_account": "Manage Account",
|
||||
"sign_out": "Sign Out",
|
||||
"sign_in_up": "Sign In / Up"
|
||||
},
|
||||
"alerts": {
|
||||
"pull_success_title": "Cloud Data Pulled",
|
||||
"pull_success_msg": "The latest cloud data has been downloaded to this device.",
|
||||
"pull_failed_title": "Pull Failed",
|
||||
"pull_failed_msg": "Failed to download data from the cloud",
|
||||
"push_success_title": "Push Completed",
|
||||
"push_success_msg": "Device data has been uploaded to the cloud.",
|
||||
"push_failed_title": "Push Failed",
|
||||
"push_failed_msg": "Failed to upload local data",
|
||||
"sign_out_failed": "Sign Out Failed",
|
||||
"sign_out_failed_title": "Logout Error"
|
||||
},
|
||||
"external_sync": {
|
||||
"title": "External Sync Priority",
|
||||
"active_msg": "{{services}} is active. Watch progress and library updates are managed by these services instead of Nuvio cloud database.",
|
||||
"inactive_msg": "If Trakt or Simkl sync is enabled, watch progress and library updates will use those services instead of Nuvio cloud database."
|
||||
},
|
||||
"pre_auth": {
|
||||
"title": "Before Syncing",
|
||||
"description": "Sign in to start cloud sync and keep your data consistent across devices.",
|
||||
"point_1": "• Addons and plugins settings",
|
||||
"point_2": "• Watch progress and library",
|
||||
"env_warning": "Set EXPO_PUBLIC_SUPABASE_URL and EXPO_PUBLIC_SUPABASE_ANON_KEY to enable sync."
|
||||
},
|
||||
"connection": "Connection"
|
||||
}
|
||||
},
|
||||
"privacy": {
|
||||
"title": "Privatësia & Të dhënat",
|
||||
|
|
|
|||
|
|
@ -1,426 +1,426 @@
|
|||
{
|
||||
"common": {
|
||||
"loading": "Учитавање...",
|
||||
"cancel": "Одустани",
|
||||
"save": "Сачувај",
|
||||
"delete": "Обриши",
|
||||
"edit": "Уреди",
|
||||
"search": "Претражи",
|
||||
"error": "Грешка",
|
||||
"success": "Успех",
|
||||
"ok": "У реду",
|
||||
"unknown": "Непознато",
|
||||
"retry": "Покушај поново",
|
||||
"try_again": "Покушај поново",
|
||||
"go_back": "Иди назад",
|
||||
"settings": "Подешавања",
|
||||
"close": "Затвори",
|
||||
"enable": "Омогући",
|
||||
"disable": "Искључи",
|
||||
"show_more": "Прикажи више",
|
||||
"show_less": "Прикажи мање",
|
||||
"load_more": "Учитај више",
|
||||
"unknown_date": "Непознат датум",
|
||||
"anonymous_user": "Анонимни корисник",
|
||||
"time": {
|
||||
"now": "Управо сада",
|
||||
"minutes_ago": "пре {{count}} мин",
|
||||
"hours_ago": "пре {{count}} ч",
|
||||
"days_ago": "пре {{count}} д"
|
||||
"common": {
|
||||
"loading": "Учитавање...",
|
||||
"cancel": "Одустани",
|
||||
"save": "Сачувај",
|
||||
"delete": "Обриши",
|
||||
"edit": "Уреди",
|
||||
"search": "Претражи",
|
||||
"error": "Грешка",
|
||||
"success": "Успех",
|
||||
"ok": "У реду",
|
||||
"unknown": "Непознато",
|
||||
"retry": "Покушај поново",
|
||||
"try_again": "Покушај поново",
|
||||
"go_back": "Иди назад",
|
||||
"settings": "Подешавања",
|
||||
"close": "Затвори",
|
||||
"enable": "Омогући",
|
||||
"disable": "Искључи",
|
||||
"show_more": "Прикажи више",
|
||||
"show_less": "Прикажи мање",
|
||||
"load_more": "Учитај више",
|
||||
"unknown_date": "Непознат датум",
|
||||
"anonymous_user": "Анонимни корисник",
|
||||
"time": {
|
||||
"now": "Управо сада",
|
||||
"minutes_ago": "пре {{count}} мин",
|
||||
"hours_ago": "пре {{count}} ч",
|
||||
"days_ago": "пре {{count}} д"
|
||||
},
|
||||
"days_short": {
|
||||
"sun": "Нед",
|
||||
"mon": "Пон",
|
||||
"tue": "Уто",
|
||||
"wed": "Сре",
|
||||
"thu": "Чет",
|
||||
"fri": "Пет",
|
||||
"sat": "Суб"
|
||||
},
|
||||
"email": "Е-пошта",
|
||||
"status": "Статус"
|
||||
},
|
||||
"days_short": {
|
||||
"sun": "Нед",
|
||||
"mon": "Пон",
|
||||
"tue": "Уто",
|
||||
"wed": "Сре",
|
||||
"thu": "Чет",
|
||||
"fri": "Пет",
|
||||
"sat": "Суб"
|
||||
"home": {
|
||||
"categories": {
|
||||
"movies": "Филмови",
|
||||
"series": "Серије",
|
||||
"channels": "Канали"
|
||||
},
|
||||
"movies": "Филмови",
|
||||
"tv_shows": "Cерије",
|
||||
"load_more_catalogs": "Учитај више каталога",
|
||||
"no_content": "Садржај није доступан",
|
||||
"add_catalogs": "Додај каталоге",
|
||||
"sign_in_available": "Пријава доступна",
|
||||
"sign_in_desc": "Можете се пријавити било када у Подешавања → Налог",
|
||||
"view_all": "Види све",
|
||||
"this_week": "Ове недеље",
|
||||
"upcoming": "Надолазеће",
|
||||
"recently_released": "Недавно објављено",
|
||||
"no_scheduled_episodes": "Серије без заказаних епизода",
|
||||
"check_back_later": "Проверите касније",
|
||||
"continue_watching": "Настави са гледањем",
|
||||
"up_next": "Следеће на реду",
|
||||
"up_next_caps": "СЛЕДЕЋЕ",
|
||||
"released": "Објављено",
|
||||
"new": "Ново",
|
||||
"tba": "Биће објављено",
|
||||
"new_episodes": "{{count}} нове епизоде",
|
||||
"season_short": "С{{season}}",
|
||||
"episode_short": "Е{{episode}}",
|
||||
"season": "Сезона {{season}}",
|
||||
"episode": "Епизода {{episode}}",
|
||||
"movie": "Филм",
|
||||
"series": "Серија",
|
||||
"tv_show": "Cерија",
|
||||
"percent_watched": "{{percent}}% одгледано",
|
||||
"view_details": "Види детаље",
|
||||
"remove": "Уклони",
|
||||
"play": "Пусти",
|
||||
"play_now": "Пусти одмах",
|
||||
"resume": "Настави",
|
||||
"info": "Инфо",
|
||||
"more_info": "Више информација",
|
||||
"my_list": "Моја листа",
|
||||
"save": "Сачувај",
|
||||
"saved": "Сачувано",
|
||||
"retry": "Покушај поново",
|
||||
"install_addons": "Инсталирај додатке",
|
||||
"settings": "Подешавања",
|
||||
"no_featured_content": "Нема истакнутог садржаја",
|
||||
"couldnt_load_featured": "Учитавање истакнутог садржаја није успело",
|
||||
"no_featured_desc": "Инсталирајте додатке са каталозима или промените извор садржаја у подешавањима.",
|
||||
"load_error_desc": "Дошло је до проблема при преузимању садржаја. Проверите везу и покушајте поново.",
|
||||
"no_featured_available": "Нема доступног истакнутог садржаја",
|
||||
"no_description": "Опис није доступан"
|
||||
},
|
||||
"email": "Е-пошта",
|
||||
"status": "Статус"
|
||||
},
|
||||
"home": {
|
||||
"categories": {
|
||||
"movies": "Филмови",
|
||||
"series": "Серије",
|
||||
"channels": "Канали"
|
||||
"navigation": {
|
||||
"home": "Почетна",
|
||||
"library": "Библиотека",
|
||||
"search": "Претрага",
|
||||
"downloads": "Преузимања",
|
||||
"settings": "Подешавања"
|
||||
},
|
||||
"movies": "Филмови",
|
||||
"tv_shows": "Cерије",
|
||||
"load_more_catalogs": "Учитај више каталога",
|
||||
"no_content": "Садржај није доступан",
|
||||
"add_catalogs": "Додај каталоге",
|
||||
"sign_in_available": "Пријава доступна",
|
||||
"sign_in_desc": "Можете се пријавити било када у Подешавања → Налог",
|
||||
"view_all": "Види све",
|
||||
"this_week": "Ове недеље",
|
||||
"upcoming": "Надолазеће",
|
||||
"recently_released": "Недавно објављено",
|
||||
"no_scheduled_episodes": "Серије без заказаних епизода",
|
||||
"check_back_later": "Проверите касније",
|
||||
"continue_watching": "Настави са гледањем",
|
||||
"up_next": "Следеће на реду",
|
||||
"up_next_caps": "СЛЕДЕЋЕ",
|
||||
"released": "Објављено",
|
||||
"new": "Ново",
|
||||
"tba": "Биће објављено",
|
||||
"new_episodes": "{{count}} нове епизоде",
|
||||
"season_short": "С{{season}}",
|
||||
"episode_short": "Е{{episode}}",
|
||||
"season": "Сезона {{season}}",
|
||||
"episode": "Епизода {{episode}}",
|
||||
"movie": "Филм",
|
||||
"series": "Серија",
|
||||
"tv_show": "Cерија",
|
||||
"percent_watched": "{{percent}}% одгледано",
|
||||
"view_details": "Види детаље",
|
||||
"remove": "Уклони",
|
||||
"play": "Пусти",
|
||||
"play_now": "Пусти одмах",
|
||||
"resume": "Настави",
|
||||
"info": "Инфо",
|
||||
"more_info": "Више информација",
|
||||
"my_list": "Моја листа",
|
||||
"save": "Сачувај",
|
||||
"saved": "Сачувано",
|
||||
"retry": "Покушај поново",
|
||||
"install_addons": "Инсталирај додатке",
|
||||
"settings": "Подешавања",
|
||||
"no_featured_content": "Нема истакнутог садржаја",
|
||||
"couldnt_load_featured": "Учитавање истакнутог садржаја није успело",
|
||||
"no_featured_desc": "Инсталирајте додатке са каталозима или промените извор садржаја у подешавањима.",
|
||||
"load_error_desc": "Дошло је до проблема при преузимању садржаја. Проверите везу и покушајте поново.",
|
||||
"no_featured_available": "Нема доступног истакнутог садржаја",
|
||||
"no_description": "Опис није доступан"
|
||||
},
|
||||
"navigation": {
|
||||
"home": "Почетна",
|
||||
"library": "Библиотека",
|
||||
"search": "Претрага",
|
||||
"downloads": "Преузимања",
|
||||
"settings": "Подешавања"
|
||||
},
|
||||
"search": {
|
||||
"title": "Претрага",
|
||||
"recent_searches": "Недавне претраге",
|
||||
"discover": "Откриј",
|
||||
"movies": "Филмови",
|
||||
"tv_shows": "Cерије",
|
||||
"select_catalog": "Изабери каталог",
|
||||
"all_genres": "Сви жанрови",
|
||||
"discovering": "Откривање садржаја...",
|
||||
"show_more": "Прикажи више ({{count}})",
|
||||
"no_content_found": "Садржај није пронађен",
|
||||
"try_different": "Покушајте други жанр или каталог",
|
||||
"select_catalog_desc": "Изаберите каталог за истраживање",
|
||||
"tap_catalog_desc": "Додирните дугме каталога изнад за почетак",
|
||||
"placeholder": "Претражи филмове, серије...",
|
||||
"keep_typing": "Наставите са куцањем...",
|
||||
"type_characters": "Упишите најмање 2 знака за претрагу",
|
||||
"no_results": "Нема резултата",
|
||||
"try_keywords": "Покушајте са другим кључним речима",
|
||||
"select_type": "Изабери тип",
|
||||
"browse_movies": "Прегледај каталоге филмова",
|
||||
"browse_tv": "Прегледај каталоге cерија",
|
||||
"select_genre": "Изабери жанр",
|
||||
"show_all_content": "Прикажи сав садржај",
|
||||
"genres_count": "{{count}} жанрова"
|
||||
},
|
||||
"library": {
|
||||
"title": "Библиотека",
|
||||
"watched": "Одгледано",
|
||||
"continue": "Настави",
|
||||
"watchlist": "Листа за гледање",
|
||||
"collection": "Колекција",
|
||||
"rated": "Оцењено",
|
||||
"items": "ставки",
|
||||
"trakt_collections": "Trakt колекције",
|
||||
"trakt_collection": "Trakt колекција",
|
||||
"no_trakt": "Нема Trakt колекција",
|
||||
"no_trakt_desc": "Ваше Trakt колекције ће се појавити овде након коришћења Trakt-а",
|
||||
"load_collections": "Учитај колекције",
|
||||
"empty_folder": "Нема садржаја у {{folder}}",
|
||||
"empty_folder_desc": "Ова колекција је празна",
|
||||
"refresh": "Освежи",
|
||||
"no_movies": "Још нема филмова",
|
||||
"no_series": "Још нема cерија",
|
||||
"no_content": "Још нема садржаја",
|
||||
"add_content_desc": "Додајте садржај у своју библиотеку да бисте га видели овде",
|
||||
"find_something": "Пронађи нешто за гледање",
|
||||
"removed_from_library": "Уклоњено из библиотеке",
|
||||
"item_removed": "Ставка је уклоњена из ваше библиотеке",
|
||||
"failed_update_library": "Ажурирање библиотеке није успело",
|
||||
"unable_remove": "Неуспело уклањање ставке из библиотеке",
|
||||
"marked_watched": "Означено као одгледано",
|
||||
"marked_unwatched": "Означено као неодгледано",
|
||||
"item_marked_watched": "Ставка је означена као одгледана",
|
||||
"item_marked_unwatched": "Ставка је означена као неодгледана",
|
||||
"failed_update_watched": "Ажурирање статуса гледања није успело",
|
||||
"unable_update_watched": "Неуспело ажурирање статуса гледања",
|
||||
"added_to_library": "Додато у библиотеку",
|
||||
"item_added": "Додато у вашу локалну библиотеку",
|
||||
"add_to_library": "Додај у библиотеку",
|
||||
"remove_from_library": "Уклони из библиотеке",
|
||||
"mark_watched": "Означи као одгледано",
|
||||
"mark_unwatched": "Означи као неодгледано",
|
||||
"share": "Подели",
|
||||
"add_to_watchlist": "Додај на Trakt листу гледања",
|
||||
"remove_from_watchlist": "Уклони са Trakt листе гледања",
|
||||
"added_to_watchlist": "Додато на листу гледања",
|
||||
"added_to_watchlist_desc": "Додато на вашу Trakt листу гледања",
|
||||
"removed_from_watchlist": "Уклоњено са листе гледања",
|
||||
"removed_from_watchlist_desc": "Уклоњено са ваше Trakt листе гледања",
|
||||
"add_to_collection": "Додај у Trakt колекцију",
|
||||
"remove_from_collection": "Уклони из Trakt колекције",
|
||||
"added_to_collection": "Додато у колекцију",
|
||||
"added_to_collection_desc": "Додато у вашу Trakt колекцију",
|
||||
"removed_from_collection": "Уклоњено из колекције",
|
||||
"removed_from_collection_desc": "Уклоњено из ваше Trakt колекције"
|
||||
},
|
||||
"metadata": {
|
||||
"unable_to_load": "Учитавање садржаја није успело",
|
||||
"error_code": "Код грешке: {{code}}",
|
||||
"content_not_found": "Садржај није пронађен",
|
||||
"content_not_found_desc": "Овај садржај не постоји или је можда уклоњен.",
|
||||
"server_error": "Грешка сервера",
|
||||
"server_error_desc": "Сервер је привремено недоступан. Покушајте касније.",
|
||||
"bad_gateway": "Лош gateway",
|
||||
"bad_gateway_desc": "Сервер има потешкоћа. Покушајте касније.",
|
||||
"service_unavailable": "Услуга недоступна",
|
||||
"service_unavailable_desc": "Услуга је тренутно недоступна због одржавања.",
|
||||
"too_many_requests": "Превише захтева",
|
||||
"too_many_requests_desc": "Шаљете превише захтева. Молимо сачекајте тренутак.",
|
||||
"request_timeout": "Истек захтева",
|
||||
"request_timeout_desc": "Захтев је трајао предуго. Покушајте поново.",
|
||||
"network_error": "Мрежна грешка",
|
||||
"network_error_desc": "Проверите интернет везу и покушајте поново.",
|
||||
"auth_error": "Грешка у аутентификацији",
|
||||
"auth_error_desc": "Проверите подешавања налога и покушајте поново.",
|
||||
"access_denied": "Приступ одбијен",
|
||||
"access_denied_desc": "Немате дозволу за приступ овом садржају.",
|
||||
"connection_error": "Грешка у вези",
|
||||
"streams_unavailable": "Стримови недоступни",
|
||||
"streams_unavailable_desc": "Извори за стримовање су тренутно недоступни.",
|
||||
"unknown_error": "Непозната грешка",
|
||||
"something_went_wrong": "Нешто је пошло по злу. Покушајте поново.",
|
||||
"cast": "Глумачка постава",
|
||||
"more_like_this": "Слично овоме",
|
||||
"collection": "Колекција",
|
||||
"episodes": "Епизоде",
|
||||
"seasons": "Сезоне",
|
||||
"posters": "Постери",
|
||||
"banners": "Банери",
|
||||
"specials": "Специјали",
|
||||
"season_number": "Сезона {{number}}",
|
||||
"episode_count": "{{count}} епизода",
|
||||
"episode_count_plural": "{{count}} епизода",
|
||||
"no_episodes": "Нема доступних епизода",
|
||||
"no_episodes_for_season": "Нема доступних епизода за сезону {{season}}",
|
||||
"episodes_not_released": "Епизоде можда још нису објављене",
|
||||
"no_description": "Опис није доступан",
|
||||
"episode_label": "ЕПИЗОДА {{number}}",
|
||||
"watch_again": "Гледај поново",
|
||||
"completed": "Завршено",
|
||||
"play_episode": "Пусти С{{season}}Е{{episode}}",
|
||||
"play": "Пусти",
|
||||
"watched": "Одгледано",
|
||||
"watched_on_trakt": "Одгледано на Trakt-у",
|
||||
"synced_with_trakt": "Синхронизовано са Trakt-ом",
|
||||
"saved": "Сачувано",
|
||||
"director": "Режисер",
|
||||
"directors": "Режисери",
|
||||
"creator": "Креатор",
|
||||
"creators": "Креатори",
|
||||
"production": "Продукција",
|
||||
"network": "Мрежа",
|
||||
"mark_watched": "Означи као одгледано",
|
||||
"mark_unwatched": "Означи као неодгледано",
|
||||
"marking": "Означавање...",
|
||||
"removing": "Уклањање...",
|
||||
"unmark_season": "Одозначи сезону {{season}}",
|
||||
"mark_season": "Означи сезону {{season}}",
|
||||
"resume": "Настави",
|
||||
"spoiler_warning": "Упозорење о спојлерима",
|
||||
"spoiler_warning_desc": "Овај коментар садржи спојлере. Да ли сте сигурни да желите да га откријете?",
|
||||
"cancel": "Одустани",
|
||||
"reveal_spoilers": "Откриј спојлере",
|
||||
"movie_details": "Детаљи о филму",
|
||||
"show_details": "Детаљи о серији",
|
||||
"tagline": "Слоган",
|
||||
"status": "Статус",
|
||||
"release_date": "Датум објаве",
|
||||
"runtime": "Трајање",
|
||||
"budget": "Буџет",
|
||||
"revenue": "Приход",
|
||||
"origin_country": "Земља порекла",
|
||||
"original_language": "Оригинални језик",
|
||||
"first_air_date": "Прво емитовање",
|
||||
"last_air_date": "Последње емитовање",
|
||||
"total_episodes": "Укупно епизода",
|
||||
"episode_runtime": "Трајање епизоде",
|
||||
"created_by": "Креирао",
|
||||
"backdrop_gallery": "Галерија позадина",
|
||||
"loading_episodes": "Учитавање епизода...",
|
||||
"no_episodes_available": "Нема доступних епизода",
|
||||
"play_next": "Пусти С{{season}}Е{{episode}}",
|
||||
"play_next_episode": "Пусти следећу епизоду",
|
||||
"save": "Сачувај",
|
||||
"percent_watched_trakt": "{{percent}}% одгледано ({{traktPercent}}% на Trakt-у)",
|
||||
"synced_with_trakt_progress": "Синхронизовано са Trakt-ом",
|
||||
"using_trakt_progress": "Користи се Trakt напредак",
|
||||
"added_to_collection_hero": "Додато у колекцију",
|
||||
"added_to_collection_desc_hero": "Додато у вашу Trakt колекцију",
|
||||
"removed_from_collection_hero": "Уклоњено из колекције",
|
||||
"removed_from_collection_desc_hero": "Уклоњено из ваше Trakt колекције",
|
||||
"mark_as_watched": "Означи као одгледано",
|
||||
"mark_as_unwatched": "Означи као неодгледано"
|
||||
},
|
||||
"cast": {
|
||||
"biography": "Биографија",
|
||||
"known_for": "Познат по",
|
||||
"personal_info": "Лични подаци",
|
||||
"born_in": "Рођен у {{place}}",
|
||||
"filmography": "Филмографија",
|
||||
"also_known_as": "Познат и као",
|
||||
"no_info_available": "Додатне информације нису доступне",
|
||||
"as_character": "као {{character}}",
|
||||
"loading_details": "Учитавање детаља...",
|
||||
"years_old": "{{age}} година",
|
||||
"view_filmography": "Види филмографију",
|
||||
"filter": "Филтер",
|
||||
"sort_by": "Сортирај по",
|
||||
"sort_popular": "Популарно",
|
||||
"sort_latest": "Најновије",
|
||||
"sort_upcoming": "Надолазеће",
|
||||
"upcoming_badge": "НАДОЛАЗЕЋЕ",
|
||||
"coming_soon": "Ускоро стиже",
|
||||
"filmography_count": "Филмографија • {{count}} наслова",
|
||||
"loading_filmography": "Учитавање филмографије...",
|
||||
"load_more_remaining": "Учитај још ({{count}} преостало)",
|
||||
"alert_error_title": "Грешка",
|
||||
"alert_error_message": "Неуспело учитавање \"{{title}}\". Покушајте касније.",
|
||||
"alert_ok": "У реду",
|
||||
"no_upcoming": "Нема надолазећих објава за овог глумца",
|
||||
"no_content": "Нема доступног садржаја за овог глумца",
|
||||
"no_movies": "Нема доступних филмова за овог глумца",
|
||||
"no_tv": "Нема доступних серија за овог глумца"
|
||||
},
|
||||
"comments": {
|
||||
"title": "Trakt коментари",
|
||||
"spoiler_warning": "⚠️ Овај коментар садржи спојлере. Додирните да откријете.",
|
||||
"spoiler": "Спојлер",
|
||||
"contains_spoilers": "Садржи спојлере",
|
||||
"reveal": "Откриј",
|
||||
"vip": "VIP",
|
||||
"unavailable": "Коментари недоступни",
|
||||
"no_comments": "Још нема коментара на Trakt-у",
|
||||
"not_in_database": "Овај садржај можда још није у Trakt бази података",
|
||||
"check_trakt": "Провери Trakt"
|
||||
},
|
||||
"trailers": {
|
||||
"title": "Трејлери",
|
||||
"official_trailers": "Званични трејлери",
|
||||
"official_trailer": "Званични трејлер",
|
||||
"teasers": "Тизери",
|
||||
"teaser": "Тизер",
|
||||
"clips_scenes": "Клипови и сцене",
|
||||
"clip": "Клип",
|
||||
"featurettes": "Кратки филмови о снимању",
|
||||
"featurette": "Кратки филм о снимању",
|
||||
"behind_the_scenes": "Иза кулиса",
|
||||
"no_trailers": "Нема доступних трејлера",
|
||||
"unavailable": "Трејлер недоступан",
|
||||
"unavailable_desc": "Овај трејлер није могуће учитати тренутно.",
|
||||
"unable_to_play": "Није могуће пустити трејлер. Покушајте поново.",
|
||||
"watch_on_youtube": "Гледај на YouTube-у"
|
||||
},
|
||||
"catalog": {
|
||||
"no_content_found": "Садржај није пронађен",
|
||||
"no_content_filters": "Нема садржаја за изабране филтере",
|
||||
"loading_content": "Учитавање садржаја...",
|
||||
"back": "Назад",
|
||||
"in_theaters": "У биоскопима",
|
||||
"all": "Све",
|
||||
"failed_tmdb": "Неуспело учитавање садржаја са TMDB",
|
||||
"movies": "Филмови",
|
||||
"tv_shows": "Cерије",
|
||||
"channels": "Канали"
|
||||
},
|
||||
"streams": {
|
||||
"back_to_episodes": "Назад на епизоде",
|
||||
"back_to_info": "Назад на инфо",
|
||||
"fetching_from": "Преузимање са:",
|
||||
"no_sources_available": "Нема доступних извора за стримовање",
|
||||
"add_sources_desc": "Молимо додајте изворе у подешавањима",
|
||||
"add_sources": "Додај изворе",
|
||||
"finding_streams": "Проналажење доступних стримова...",
|
||||
"finding_best_stream": "Проналажење најбољег стрима за аутоматско пуштање...",
|
||||
"still_fetching": "Преузимање стримова је још у току...",
|
||||
"no_streams_available": "Нема доступних стримова",
|
||||
"starting_best_stream": "Покретање најбољег стрима...",
|
||||
"loading_more_sources": "Учитавање додатних извора..."
|
||||
},
|
||||
"player_ui": {
|
||||
"via": "преко {{name}}",
|
||||
"audio_tracks": "Аудио траке",
|
||||
"no_audio_tracks": "Нема доступних аудио трака",
|
||||
"playback_speed": "Брзина репродукције",
|
||||
"on_hold": "На чекању",
|
||||
"playback_error": "Грешка при репродукцији",
|
||||
"unknown_error": "Дошло је до непознате грешке током репродукције.",
|
||||
"copy_error": "Копирај детаље о грешци",
|
||||
"copied_to_clipboard": "Копирано у привремени меморију",
|
||||
"dismiss": "Одбаци",
|
||||
"continue_watching": "Настави са гледањем",
|
||||
"start_over": "Крени испочетка",
|
||||
"resume": "Настави",
|
||||
"change_source": "Промени извор",
|
||||
"switching_source": "Промена извора...",
|
||||
"no_sources_found": "Извори нису пронађени",
|
||||
"sources": "Извори",
|
||||
"finding_sources": "Проналажење извора...",
|
||||
"unknown_source": "Непознат извор",
|
||||
"sources_limited": "Извори могу бити ограничени због грешака провајдера.",
|
||||
"episodes": "Епизоде",
|
||||
"specials": "Специјали",
|
||||
"season": "Сезона {{season}}",
|
||||
"stream": "Стрим {{number}}",
|
||||
"subtitles": "Титлови",
|
||||
"built_in": "Уграђени",
|
||||
"addons": "Додаци",
|
||||
"style": "Стил",
|
||||
"none": "Ниједан",
|
||||
"search_online_subtitles": "Претражи титлове на мрежи",
|
||||
"preview": "Преглед",
|
||||
"quick_presets": "Брза подешавања",
|
||||
"default": "Подразумевано",
|
||||
"yellow": "Жуто",
|
||||
"high_contrast": "Висок контраст",
|
||||
"large": "Велико",
|
||||
"core": "Језгро",
|
||||
"font_size": "Величина фонта",
|
||||
"show_background": "Прикажи позадину",
|
||||
"advanced": "Напредно",
|
||||
"position": "Позиција",
|
||||
"text_color": "Боја текста",
|
||||
"align": "Поравнање",
|
||||
"bottom_offset": "Размак од дна",
|
||||
"background_opacity": "Провидност позадине",
|
||||
"text_shadow": "Сенка текста",
|
||||
"on": "Укључено",
|
||||
"off": "Искључено",
|
||||
"outline_color": "Боја оквира",
|
||||
"outline": "Оквир",
|
||||
"outline_width": "Ширина оквира",
|
||||
"letter_spacing": "Размак између слова",
|
||||
"line_height": "Висина линије",
|
||||
"timing_offset": "Временски помак (с)",
|
||||
"visual_sync": "Визуелна синхронизација",
|
||||
"timing_hint": "Померите титлове раније (-) или касније (+) за синхронизацију.",
|
||||
"reset_defaults": "Врати на подразумевано"
|
||||
},
|
||||
"downloads": {
|
||||
"search": {
|
||||
"title": "Претрага",
|
||||
"recent_searches": "Недавне претраге",
|
||||
"discover": "Откриј",
|
||||
"movies": "Филмови",
|
||||
"tv_shows": "Cерије",
|
||||
"select_catalog": "Изабери каталог",
|
||||
"all_genres": "Сви жанрови",
|
||||
"discovering": "Откривање садржаја...",
|
||||
"show_more": "Прикажи више ({{count}})",
|
||||
"no_content_found": "Садржај није пронађен",
|
||||
"try_different": "Покушајте други жанр или каталог",
|
||||
"select_catalog_desc": "Изаберите каталог за истраживање",
|
||||
"tap_catalog_desc": "Додирните дугме каталога изнад за почетак",
|
||||
"placeholder": "Претражи филмове, серије...",
|
||||
"keep_typing": "Наставите са куцањем...",
|
||||
"type_characters": "Упишите најмање 2 знака за претрагу",
|
||||
"no_results": "Нема резултата",
|
||||
"try_keywords": "Покушајте са другим кључним речима",
|
||||
"select_type": "Изабери тип",
|
||||
"browse_movies": "Прегледај каталоге филмова",
|
||||
"browse_tv": "Прегледај каталоге cерија",
|
||||
"select_genre": "Изабери жанр",
|
||||
"show_all_content": "Прикажи сав садржај",
|
||||
"genres_count": "{{count}} жанрова"
|
||||
},
|
||||
"library": {
|
||||
"title": "Библиотека",
|
||||
"watched": "Одгледано",
|
||||
"continue": "Настави",
|
||||
"watchlist": "Листа за гледање",
|
||||
"collection": "Колекција",
|
||||
"rated": "Оцењено",
|
||||
"items": "ставки",
|
||||
"trakt_collections": "Trakt колекције",
|
||||
"trakt_collection": "Trakt колекција",
|
||||
"no_trakt": "Нема Trakt колекција",
|
||||
"no_trakt_desc": "Ваше Trakt колекције ће се појавити овде након коришћења Trakt-а",
|
||||
"load_collections": "Учитај колекције",
|
||||
"empty_folder": "Нема садржаја у {{folder}}",
|
||||
"empty_folder_desc": "Ова колекција је празна",
|
||||
"refresh": "Освежи",
|
||||
"no_movies": "Још нема филмова",
|
||||
"no_series": "Још нема cерија",
|
||||
"no_content": "Још нема садржаја",
|
||||
"add_content_desc": "Додајте садржај у своју библиотеку да бисте га видели овде",
|
||||
"find_something": "Пронађи нешто за гледање",
|
||||
"removed_from_library": "Уклоњено из библиотеке",
|
||||
"item_removed": "Ставка је уклоњена из ваше библиотеке",
|
||||
"failed_update_library": "Ажурирање библиотеке није успело",
|
||||
"unable_remove": "Неуспело уклањање ставке из библиотеке",
|
||||
"marked_watched": "Означено као одгледано",
|
||||
"marked_unwatched": "Означено као неодгледано",
|
||||
"item_marked_watched": "Ставка је означена као одгледана",
|
||||
"item_marked_unwatched": "Ставка је означена као неодгледана",
|
||||
"failed_update_watched": "Ажурирање статуса гледања није успело",
|
||||
"unable_update_watched": "Неуспело ажурирање статуса гледања",
|
||||
"added_to_library": "Додато у библиотеку",
|
||||
"item_added": "Додато у вашу локалну библиотеку",
|
||||
"add_to_library": "Додај у библиотеку",
|
||||
"remove_from_library": "Уклони из библиотеке",
|
||||
"mark_watched": "Означи као одгледано",
|
||||
"mark_unwatched": "Означи као неодгледано",
|
||||
"share": "Подели",
|
||||
"add_to_watchlist": "Додај на Trakt листу гледања",
|
||||
"remove_from_watchlist": "Уклони са Trakt листе гледања",
|
||||
"added_to_watchlist": "Додато на листу гледања",
|
||||
"added_to_watchlist_desc": "Додато на вашу Trakt листу гледања",
|
||||
"removed_from_watchlist": "Уклоњено са листе гледања",
|
||||
"removed_from_watchlist_desc": "Уклоњено са ваше Trakt листе гледања",
|
||||
"add_to_collection": "Додај у Trakt колекцију",
|
||||
"remove_from_collection": "Уклони из Trakt колекције",
|
||||
"added_to_collection": "Додато у колекцију",
|
||||
"added_to_collection_desc": "Додато у вашу Trakt колекцију",
|
||||
"removed_from_collection": "Уклоњено из колекције",
|
||||
"removed_from_collection_desc": "Уклоњено из ваше Trakt колекције"
|
||||
},
|
||||
"metadata": {
|
||||
"unable_to_load": "Учитавање садржаја није успело",
|
||||
"error_code": "Код грешке: {{code}}",
|
||||
"content_not_found": "Садржај није пронађен",
|
||||
"content_not_found_desc": "Овај садржај не постоји или је можда уклоњен.",
|
||||
"server_error": "Грешка сервера",
|
||||
"server_error_desc": "Сервер је привремено недоступан. Покушајте касније.",
|
||||
"bad_gateway": "Лош gateway",
|
||||
"bad_gateway_desc": "Сервер има потешкоћа. Покушајте касније.",
|
||||
"service_unavailable": "Услуга недоступна",
|
||||
"service_unavailable_desc": "Услуга је тренутно недоступна због одржавања.",
|
||||
"too_many_requests": "Превише захтева",
|
||||
"too_many_requests_desc": "Шаљете превише захтева. Молимо сачекајте тренутак.",
|
||||
"request_timeout": "Истек захтева",
|
||||
"request_timeout_desc": "Захтев је трајао предуго. Покушајте поново.",
|
||||
"network_error": "Мрежна грешка",
|
||||
"network_error_desc": "Проверите интернет везу и покушајте поново.",
|
||||
"auth_error": "Грешка у аутентификацији",
|
||||
"auth_error_desc": "Проверите подешавања налога и покушајте поново.",
|
||||
"access_denied": "Приступ одбијен",
|
||||
"access_denied_desc": "Немате дозволу за приступ овом садржају.",
|
||||
"connection_error": "Грешка у вези",
|
||||
"streams_unavailable": "Стримови недоступни",
|
||||
"streams_unavailable_desc": "Извори за стримовање су тренутно недоступни.",
|
||||
"unknown_error": "Непозната грешка",
|
||||
"something_went_wrong": "Нешто је пошло по злу. Покушајте поново.",
|
||||
"cast": "Глумачка постава",
|
||||
"more_like_this": "Слично овоме",
|
||||
"collection": "Колекција",
|
||||
"episodes": "Епизоде",
|
||||
"seasons": "Сезоне",
|
||||
"posters": "Постери",
|
||||
"banners": "Банери",
|
||||
"specials": "Специјали",
|
||||
"season_number": "Сезона {{number}}",
|
||||
"episode_count": "{{count}} епизода",
|
||||
"episode_count_plural": "{{count}} епизода",
|
||||
"no_episodes": "Нема доступних епизода",
|
||||
"no_episodes_for_season": "Нема доступних епизода за сезону {{season}}",
|
||||
"episodes_not_released": "Епизоде можда још нису објављене",
|
||||
"no_description": "Опис није доступан",
|
||||
"episode_label": "ЕПИЗОДА {{number}}",
|
||||
"watch_again": "Гледај поново",
|
||||
"completed": "Завршено",
|
||||
"play_episode": "Пусти С{{season}}Е{{episode}}",
|
||||
"play": "Пусти",
|
||||
"watched": "Одгледано",
|
||||
"watched_on_trakt": "Одгледано на Trakt-у",
|
||||
"synced_with_trakt": "Синхронизовано са Trakt-ом",
|
||||
"saved": "Сачувано",
|
||||
"director": "Режисер",
|
||||
"directors": "Режисери",
|
||||
"creator": "Креатор",
|
||||
"creators": "Креатори",
|
||||
"production": "Продукција",
|
||||
"network": "Мрежа",
|
||||
"mark_watched": "Означи као одгледано",
|
||||
"mark_unwatched": "Означи као неодгледано",
|
||||
"marking": "Означавање...",
|
||||
"removing": "Уклањање...",
|
||||
"unmark_season": "Одозначи сезону {{season}}",
|
||||
"mark_season": "Означи сезону {{season}}",
|
||||
"resume": "Настави",
|
||||
"spoiler_warning": "Упозорење о спојлерима",
|
||||
"spoiler_warning_desc": "Овај коментар садржи спојлере. Да ли сте сигурни да желите да га откријете?",
|
||||
"cancel": "Одустани",
|
||||
"reveal_spoilers": "Откриј спојлере",
|
||||
"movie_details": "Детаљи о филму",
|
||||
"show_details": "Детаљи о серији",
|
||||
"tagline": "Слоган",
|
||||
"status": "Статус",
|
||||
"release_date": "Датум објаве",
|
||||
"runtime": "Трајање",
|
||||
"budget": "Буџет",
|
||||
"revenue": "Приход",
|
||||
"origin_country": "Земља порекла",
|
||||
"original_language": "Оригинални језик",
|
||||
"first_air_date": "Прво емитовање",
|
||||
"last_air_date": "Последње емитовање",
|
||||
"total_episodes": "Укупно епизода",
|
||||
"episode_runtime": "Трајање епизоде",
|
||||
"created_by": "Креирао",
|
||||
"backdrop_gallery": "Галерија позадина",
|
||||
"loading_episodes": "Учитавање епизода...",
|
||||
"no_episodes_available": "Нема доступних епизода",
|
||||
"play_next": "Пусти С{{season}}Е{{episode}}",
|
||||
"play_next_episode": "Пусти следећу епизоду",
|
||||
"save": "Сачувај",
|
||||
"percent_watched_trakt": "{{percent}}% одгледано ({{traktPercent}}% на Trakt-у)",
|
||||
"synced_with_trakt_progress": "Синхронизовано са Trakt-ом",
|
||||
"using_trakt_progress": "Користи се Trakt напредак",
|
||||
"added_to_collection_hero": "Додато у колекцију",
|
||||
"added_to_collection_desc_hero": "Додато у вашу Trakt колекцију",
|
||||
"removed_from_collection_hero": "Уклоњено из колекције",
|
||||
"removed_from_collection_desc_hero": "Уклоњено из ваше Trakt колекције",
|
||||
"mark_as_watched": "Означи као одгледано",
|
||||
"mark_as_unwatched": "Означи као неодгледано"
|
||||
},
|
||||
"cast": {
|
||||
"biography": "Биографија",
|
||||
"known_for": "Познат по",
|
||||
"personal_info": "Лични подаци",
|
||||
"born_in": "Рођен у {{place}}",
|
||||
"filmography": "Филмографија",
|
||||
"also_known_as": "Познат и као",
|
||||
"no_info_available": "Додатне информације нису доступне",
|
||||
"as_character": "као {{character}}",
|
||||
"loading_details": "Учитавање детаља...",
|
||||
"years_old": "{{age}} година",
|
||||
"view_filmography": "Види филмографију",
|
||||
"filter": "Филтер",
|
||||
"sort_by": "Сортирај по",
|
||||
"sort_popular": "Популарно",
|
||||
"sort_latest": "Најновије",
|
||||
"sort_upcoming": "Надолазеће",
|
||||
"upcoming_badge": "НАДОЛАЗЕЋЕ",
|
||||
"coming_soon": "Ускоро стиже",
|
||||
"filmography_count": "Филмографија • {{count}} наслова",
|
||||
"loading_filmography": "Учитавање филмографије...",
|
||||
"load_more_remaining": "Учитај још ({{count}} преостало)",
|
||||
"alert_error_title": "Грешка",
|
||||
"alert_error_message": "Неуспело учитавање \"{{title}}\". Покушајте касније.",
|
||||
"alert_ok": "У реду",
|
||||
"no_upcoming": "Нема надолазећих објава за овог глумца",
|
||||
"no_content": "Нема доступног садржаја за овог глумца",
|
||||
"no_movies": "Нема доступних филмова за овог глумца",
|
||||
"no_tv": "Нема доступних серија за овог глумца"
|
||||
},
|
||||
"comments": {
|
||||
"title": "Trakt коментари",
|
||||
"spoiler_warning": "⚠️ Овај коментар садржи спојлере. Додирните да откријете.",
|
||||
"spoiler": "Спојлер",
|
||||
"contains_spoilers": "Садржи спојлере",
|
||||
"reveal": "Откриј",
|
||||
"vip": "VIP",
|
||||
"unavailable": "Коментари недоступни",
|
||||
"no_comments": "Још нема коментара на Trakt-у",
|
||||
"not_in_database": "Овај садржај можда још није у Trakt бази података",
|
||||
"check_trakt": "Провери Trakt"
|
||||
},
|
||||
"trailers": {
|
||||
"title": "Трејлери",
|
||||
"official_trailers": "Званични трејлери",
|
||||
"official_trailer": "Званични трејлер",
|
||||
"teasers": "Тизери",
|
||||
"teaser": "Тизер",
|
||||
"clips_scenes": "Клипови и сцене",
|
||||
"clip": "Клип",
|
||||
"featurettes": "Кратки филмови о снимању",
|
||||
"featurette": "Кратки филм о снимању",
|
||||
"behind_the_scenes": "Иза кулиса",
|
||||
"no_trailers": "Нема доступних трејлера",
|
||||
"unavailable": "Трејлер недоступан",
|
||||
"unavailable_desc": "Овај трејлер није могуће учитати тренутно.",
|
||||
"unable_to_play": "Није могуће пустити трејлер. Покушајте поново.",
|
||||
"watch_on_youtube": "Гледај на YouTube-у"
|
||||
},
|
||||
"catalog": {
|
||||
"no_content_found": "Садржај није пронађен",
|
||||
"no_content_filters": "Нема садржаја за изабране филтере",
|
||||
"loading_content": "Учитавање садржаја...",
|
||||
"back": "Назад",
|
||||
"in_theaters": "У биоскопима",
|
||||
"all": "Све",
|
||||
"failed_tmdb": "Неуспело учитавање садржаја са TMDB",
|
||||
"movies": "Филмови",
|
||||
"tv_shows": "Cерије",
|
||||
"channels": "Канали"
|
||||
},
|
||||
"streams": {
|
||||
"back_to_episodes": "Назад на епизоде",
|
||||
"back_to_info": "Назад на инфо",
|
||||
"fetching_from": "Преузимање са:",
|
||||
"no_sources_available": "Нема доступних извора за стримовање",
|
||||
"add_sources_desc": "Молимо додајте изворе у подешавањима",
|
||||
"add_sources": "Додај изворе",
|
||||
"finding_streams": "Проналажење доступних стримова...",
|
||||
"finding_best_stream": "Проналажење најбољег стрима за аутоматско пуштање...",
|
||||
"still_fetching": "Преузимање стримова је још у току...",
|
||||
"no_streams_available": "Нема доступних стримова",
|
||||
"starting_best_stream": "Покретање најбољег стрима...",
|
||||
"loading_more_sources": "Учитавање додатних извора..."
|
||||
},
|
||||
"player_ui": {
|
||||
"via": "преко {{name}}",
|
||||
"audio_tracks": "Аудио траке",
|
||||
"no_audio_tracks": "Нема доступних аудио трака",
|
||||
"playback_speed": "Брзина репродукције",
|
||||
"on_hold": "На чекању",
|
||||
"playback_error": "Грешка при репродукцији",
|
||||
"unknown_error": "Дошло је до непознате грешке током репродукције.",
|
||||
"copy_error": "Копирај детаље о грешци",
|
||||
"copied_to_clipboard": "Копирано у привремени меморију",
|
||||
"dismiss": "Одбаци",
|
||||
"continue_watching": "Настави са гледањем",
|
||||
"start_over": "Крени испочетка",
|
||||
"resume": "Настави",
|
||||
"change_source": "Промени извор",
|
||||
"switching_source": "Промена извора...",
|
||||
"no_sources_found": "Извори нису пронађени",
|
||||
"sources": "Извори",
|
||||
"finding_sources": "Проналажење извора...",
|
||||
"unknown_source": "Непознат извор",
|
||||
"sources_limited": "Извори могу бити ограничени због грешака провајдера.",
|
||||
"episodes": "Епизоде",
|
||||
"specials": "Специјали",
|
||||
"season": "Сезона {{season}}",
|
||||
"stream": "Стрим {{number}}",
|
||||
"subtitles": "Титлови",
|
||||
"built_in": "Уграђени",
|
||||
"addons": "Додаци",
|
||||
"style": "Стил",
|
||||
"none": "Ниједан",
|
||||
"search_online_subtitles": "Претражи титлове на мрежи",
|
||||
"preview": "Преглед",
|
||||
"quick_presets": "Брза подешавања",
|
||||
"default": "Подразумевано",
|
||||
"yellow": "Жуто",
|
||||
"high_contrast": "Висок контраст",
|
||||
"large": "Велико",
|
||||
"core": "Језгро",
|
||||
"font_size": "Величина фонта",
|
||||
"show_background": "Прикажи позадину",
|
||||
"advanced": "Напредно",
|
||||
"position": "Позиција",
|
||||
"text_color": "Боја текста",
|
||||
"align": "Поравнање",
|
||||
"bottom_offset": "Размак од дна",
|
||||
"background_opacity": "Провидност позадине",
|
||||
"text_shadow": "Сенка текста",
|
||||
"on": "Укључено",
|
||||
"off": "Искључено",
|
||||
"outline_color": "Боја оквира",
|
||||
"outline": "Оквир",
|
||||
"outline_width": "Ширина оквира",
|
||||
"letter_spacing": "Размак између слова",
|
||||
"line_height": "Висина линије",
|
||||
"timing_offset": "Временски помак (с)",
|
||||
"visual_sync": "Визуелна синхронизација",
|
||||
"timing_hint": "Померите титлове раније (-) или касније (+) за синхронизацију.",
|
||||
"reset_defaults": "Врати на подразумевано"
|
||||
},
|
||||
"downloads": {
|
||||
"title": "Преузимања",
|
||||
"no_downloads": "Још нема преузимања",
|
||||
"no_downloads_desc": "Преузети садржај ће се појавити овде за гледање ван мреже",
|
||||
|
|
@ -758,7 +758,65 @@
|
|||
},
|
||||
"clear_data_desc": "Ово ће ресетовати сва подешавања и обрисати кеш. Да ли сте сигурни?",
|
||||
"app_updates": "Ажурирања апликације",
|
||||
"about_nuvio": "О Nuvio апликацији"
|
||||
"about_nuvio": "О Nuvio апликацији",
|
||||
"cloud_sync": {
|
||||
"title": "Nuvio Sync",
|
||||
"description": "Sync data across your Nuvio devices",
|
||||
"hero_title": "Cloud Sync",
|
||||
"hero_subtitle": "Keep your addons, progress, and library aligned across all devices.",
|
||||
"auth": {
|
||||
"account": "Account",
|
||||
"not_configured": "Supabase not configured",
|
||||
"not_authenticated": "Not authenticated",
|
||||
"email_session": "Email session",
|
||||
"signed_in_as": "Signed in as {{email}}",
|
||||
"not_signed_in": "Not signed in",
|
||||
"effective_owner": "Effective owner: {{id}}"
|
||||
},
|
||||
"stats": {
|
||||
"title": "Database Statistics",
|
||||
"plugins": "Plugins",
|
||||
"addons": "Addons",
|
||||
"watch_progress": "Watch Progress",
|
||||
"library_items": "Library Items",
|
||||
"watched_items": "Watched Items",
|
||||
"signin_required": "Sign in to load remote data counts."
|
||||
},
|
||||
"actions": {
|
||||
"title": "Actions",
|
||||
"description": "Pull to update this device from the cloud, or push from this device as the latest source.",
|
||||
"pull_btn": "Pull from Cloud",
|
||||
"push_btn": "Push from Device",
|
||||
"manage_account": "Manage Account",
|
||||
"sign_out": "Sign Out",
|
||||
"sign_in_up": "Sign In / Up"
|
||||
},
|
||||
"alerts": {
|
||||
"pull_success_title": "Cloud Data Pulled",
|
||||
"pull_success_msg": "The latest cloud data has been downloaded to this device.",
|
||||
"pull_failed_title": "Pull Failed",
|
||||
"pull_failed_msg": "Failed to download data from the cloud",
|
||||
"push_success_title": "Push Completed",
|
||||
"push_success_msg": "Device data has been uploaded to the cloud.",
|
||||
"push_failed_title": "Push Failed",
|
||||
"push_failed_msg": "Failed to upload local data",
|
||||
"sign_out_failed": "Sign Out Failed",
|
||||
"sign_out_failed_title": "Logout Error"
|
||||
},
|
||||
"external_sync": {
|
||||
"title": "External Sync Priority",
|
||||
"active_msg": "{{services}} is active. Watch progress and library updates are managed by these services instead of Nuvio cloud database.",
|
||||
"inactive_msg": "If Trakt or Simkl sync is enabled, watch progress and library updates will use those services instead of Nuvio cloud database."
|
||||
},
|
||||
"pre_auth": {
|
||||
"title": "Before Syncing",
|
||||
"description": "Sign in to start cloud sync and keep your data consistent across devices.",
|
||||
"point_1": "• Addons and plugins settings",
|
||||
"point_2": "• Watch progress and library",
|
||||
"env_warning": "Set EXPO_PUBLIC_SUPABASE_URL and EXPO_PUBLIC_SUPABASE_ANON_KEY to enable sync."
|
||||
},
|
||||
"connection": "Connection"
|
||||
}
|
||||
},
|
||||
"privacy": {
|
||||
"title": "Приватност и Подаци",
|
||||
|
|
|
|||
|
|
@ -764,7 +764,65 @@
|
|||
},
|
||||
"clear_data_desc": "Bu işlem tüm ayarları sıfırlayacak ve tüm önbelleği temizleyecektir. Emin misiniz?",
|
||||
"app_updates": "Uygulama Güncellemeleri",
|
||||
"about_nuvio": "Nuvio Hakkında"
|
||||
"about_nuvio": "Nuvio Hakkında",
|
||||
"cloud_sync": {
|
||||
"title": "Nuvio Sync",
|
||||
"description": "Sync data across your Nuvio devices",
|
||||
"hero_title": "Cloud Sync",
|
||||
"hero_subtitle": "Keep your addons, progress, and library aligned across all devices.",
|
||||
"auth": {
|
||||
"account": "Account",
|
||||
"not_configured": "Supabase not configured",
|
||||
"not_authenticated": "Not authenticated",
|
||||
"email_session": "Email session",
|
||||
"signed_in_as": "Signed in as {{email}}",
|
||||
"not_signed_in": "Not signed in",
|
||||
"effective_owner": "Effective owner: {{id}}"
|
||||
},
|
||||
"stats": {
|
||||
"title": "Database Statistics",
|
||||
"plugins": "Plugins",
|
||||
"addons": "Addons",
|
||||
"watch_progress": "Watch Progress",
|
||||
"library_items": "Library Items",
|
||||
"watched_items": "Watched Items",
|
||||
"signin_required": "Sign in to load remote data counts."
|
||||
},
|
||||
"actions": {
|
||||
"title": "Actions",
|
||||
"description": "Pull to update this device from the cloud, or push from this device as the latest source.",
|
||||
"pull_btn": "Pull from Cloud",
|
||||
"push_btn": "Push from Device",
|
||||
"manage_account": "Manage Account",
|
||||
"sign_out": "Sign Out",
|
||||
"sign_in_up": "Sign In / Up"
|
||||
},
|
||||
"alerts": {
|
||||
"pull_success_title": "Cloud Data Pulled",
|
||||
"pull_success_msg": "The latest cloud data has been downloaded to this device.",
|
||||
"pull_failed_title": "Pull Failed",
|
||||
"pull_failed_msg": "Failed to download data from the cloud",
|
||||
"push_success_title": "Push Completed",
|
||||
"push_success_msg": "Device data has been uploaded to the cloud.",
|
||||
"push_failed_title": "Push Failed",
|
||||
"push_failed_msg": "Failed to upload local data",
|
||||
"sign_out_failed": "Sign Out Failed",
|
||||
"sign_out_failed_title": "Logout Error"
|
||||
},
|
||||
"external_sync": {
|
||||
"title": "External Sync Priority",
|
||||
"active_msg": "{{services}} is active. Watch progress and library updates are managed by these services instead of Nuvio cloud database.",
|
||||
"inactive_msg": "If Trakt or Simkl sync is enabled, watch progress and library updates will use those services instead of Nuvio cloud database."
|
||||
},
|
||||
"pre_auth": {
|
||||
"title": "Before Syncing",
|
||||
"description": "Sign in to start cloud sync and keep your data consistent across devices.",
|
||||
"point_1": "• Addons and plugins settings",
|
||||
"point_2": "• Watch progress and library",
|
||||
"env_warning": "Set EXPO_PUBLIC_SUPABASE_URL and EXPO_PUBLIC_SUPABASE_ANON_KEY to enable sync."
|
||||
},
|
||||
"connection": "Connection"
|
||||
}
|
||||
},
|
||||
"privacy": {
|
||||
"title": "Gizlilik ve Veri",
|
||||
|
|
|
|||
|
|
@ -759,7 +759,65 @@
|
|||
},
|
||||
"clear_data_desc": "这将重置所有设置并清除所有缓存数据。您确定吗?",
|
||||
"app_updates": "应用更新",
|
||||
"about_nuvio": "关于 Nuvio"
|
||||
"about_nuvio": "关于 Nuvio",
|
||||
"cloud_sync": {
|
||||
"title": "Nuvio Sync",
|
||||
"description": "Sync data across your Nuvio devices",
|
||||
"hero_title": "Cloud Sync",
|
||||
"hero_subtitle": "Keep your addons, progress, and library aligned across all devices.",
|
||||
"auth": {
|
||||
"account": "Account",
|
||||
"not_configured": "Supabase not configured",
|
||||
"not_authenticated": "Not authenticated",
|
||||
"email_session": "Email session",
|
||||
"signed_in_as": "Signed in as {{email}}",
|
||||
"not_signed_in": "Not signed in",
|
||||
"effective_owner": "Effective owner: {{id}}"
|
||||
},
|
||||
"stats": {
|
||||
"title": "Database Statistics",
|
||||
"plugins": "Plugins",
|
||||
"addons": "Addons",
|
||||
"watch_progress": "Watch Progress",
|
||||
"library_items": "Library Items",
|
||||
"watched_items": "Watched Items",
|
||||
"signin_required": "Sign in to load remote data counts."
|
||||
},
|
||||
"actions": {
|
||||
"title": "Actions",
|
||||
"description": "Pull to update this device from the cloud, or push from this device as the latest source.",
|
||||
"pull_btn": "Pull from Cloud",
|
||||
"push_btn": "Push from Device",
|
||||
"manage_account": "Manage Account",
|
||||
"sign_out": "Sign Out",
|
||||
"sign_in_up": "Sign In / Up"
|
||||
},
|
||||
"alerts": {
|
||||
"pull_success_title": "Cloud Data Pulled",
|
||||
"pull_success_msg": "The latest cloud data has been downloaded to this device.",
|
||||
"pull_failed_title": "Pull Failed",
|
||||
"pull_failed_msg": "Failed to download data from the cloud",
|
||||
"push_success_title": "Push Completed",
|
||||
"push_success_msg": "Device data has been uploaded to the cloud.",
|
||||
"push_failed_title": "Push Failed",
|
||||
"push_failed_msg": "Failed to upload local data",
|
||||
"sign_out_failed": "Sign Out Failed",
|
||||
"sign_out_failed_title": "Logout Error"
|
||||
},
|
||||
"external_sync": {
|
||||
"title": "External Sync Priority",
|
||||
"active_msg": "{{services}} is active. Watch progress and library updates are managed by these services instead of Nuvio cloud database.",
|
||||
"inactive_msg": "If Trakt or Simkl sync is enabled, watch progress and library updates will use those services instead of Nuvio cloud database."
|
||||
},
|
||||
"pre_auth": {
|
||||
"title": "Before Syncing",
|
||||
"description": "Sign in to start cloud sync and keep your data consistent across devices.",
|
||||
"point_1": "• Addons and plugins settings",
|
||||
"point_2": "• Watch progress and library",
|
||||
"env_warning": "Set EXPO_PUBLIC_SUPABASE_URL and EXPO_PUBLIC_SUPABASE_ANON_KEY to enable sync."
|
||||
},
|
||||
"connection": "Connection"
|
||||
}
|
||||
},
|
||||
"privacy": {
|
||||
"title": "隐私和数据",
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import { catalogService, StreamingContent } from './catalogService';
|
|||
import { storageService } from './storageService';
|
||||
import { watchedService, LocalWatchedItem } from './watchedService';
|
||||
import { TraktService } from './traktService';
|
||||
import { SimklService } from './simklService';
|
||||
|
||||
const SUPABASE_SESSION_KEY = '@supabase:session';
|
||||
const DEFAULT_SYNC_DEBOUNCE_MS = 2000;
|
||||
|
|
@ -123,6 +124,7 @@ class SupabaseSyncService {
|
|||
private readonly foregroundPullCooldownMs = 30000;
|
||||
private pendingWatchProgressDeleteKeys = new Set<string>();
|
||||
private watchProgressDeleteTimer: ReturnType<typeof setTimeout> | null = null;
|
||||
private watchProgressPushedSignatures = new Map<string, string>();
|
||||
|
||||
private pendingPushTimers: Record<PushTarget, ReturnType<typeof setTimeout> | null> = {
|
||||
plugins: null,
|
||||
|
|
@ -236,6 +238,7 @@ class SupabaseSyncService {
|
|||
}
|
||||
|
||||
this.session = null;
|
||||
this.watchProgressPushedSignatures.clear();
|
||||
await mmkvStorage.removeItem(SUPABASE_SESSION_KEY);
|
||||
}
|
||||
|
||||
|
|
@ -277,13 +280,15 @@ class SupabaseSyncService {
|
|||
await this.pushPluginsFromLocal();
|
||||
await this.pushAddonsFromLocal();
|
||||
|
||||
const traktConnected = await this.isTraktConnected();
|
||||
if (traktConnected) {
|
||||
await this.pushLibraryFromLocal();
|
||||
const externalProgressSyncConnected = await this.isExternalProgressSyncConnected();
|
||||
if (externalProgressSyncConnected) {
|
||||
logger.log('[SupabaseSyncService] External sync (Trakt/Simkl) is connected; skipping watch progress/watched-items push, keeping library sync.');
|
||||
logger.log('[SupabaseSyncService] pushAllLocalData: complete');
|
||||
return;
|
||||
}
|
||||
|
||||
await this.pushWatchProgressFromLocal();
|
||||
await this.pushLibraryFromLocal();
|
||||
await this.pushWatchedItemsFromLocal();
|
||||
logger.log('[SupabaseSyncService] pushAllLocalData: complete');
|
||||
}
|
||||
|
|
@ -296,13 +301,14 @@ class SupabaseSyncService {
|
|||
await this.pullPluginsToLocal();
|
||||
await this.pullAddonsToLocal();
|
||||
|
||||
const traktConnected = await this.isTraktConnected();
|
||||
if (traktConnected) {
|
||||
await this.pullLibraryToLocal();
|
||||
const externalProgressSyncConnected = await this.isExternalProgressSyncConnected();
|
||||
if (externalProgressSyncConnected) {
|
||||
logger.log('[SupabaseSyncService] External sync (Trakt/Simkl) is connected; skipping watch progress/watched-items pull, keeping library sync.');
|
||||
return;
|
||||
}
|
||||
|
||||
await this.pullWatchProgressToLocal();
|
||||
await this.pullLibraryToLocal();
|
||||
await this.pullWatchedItemsToLocal();
|
||||
});
|
||||
logger.log('[SupabaseSyncService] pullAllToLocal: complete');
|
||||
|
|
@ -493,9 +499,18 @@ class SupabaseSyncService {
|
|||
logger.warn('[SupabaseSyncService] runStartupSync: one or more pull steps failed; skipped startup push-by-design');
|
||||
}
|
||||
|
||||
const traktConnected = await this.isTraktConnected();
|
||||
if (traktConnected) {
|
||||
logger.log('[SupabaseSyncService] Trakt is connected; skipping progress/library/watched Supabase sync.');
|
||||
const libraryPullOk = await this.safeRun('pull_library', async () => {
|
||||
await this.withSuppressedPushes(async () => {
|
||||
await this.pullLibraryToLocal();
|
||||
});
|
||||
});
|
||||
|
||||
const externalProgressSyncConnected = await this.isExternalProgressSyncConnected();
|
||||
if (externalProgressSyncConnected) {
|
||||
logger.log('[SupabaseSyncService] External sync (Trakt/Simkl) is connected; skipping watch progress/watched-items Supabase sync (library still synced).');
|
||||
if (!libraryPullOk) {
|
||||
logger.warn('[SupabaseSyncService] runStartupSync: library pull failed while external sync priority is active');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -505,12 +520,6 @@ class SupabaseSyncService {
|
|||
});
|
||||
});
|
||||
|
||||
const libraryPullOk = await this.safeRun('pull_library', async () => {
|
||||
await this.withSuppressedPushes(async () => {
|
||||
await this.pullLibraryToLocal();
|
||||
});
|
||||
});
|
||||
|
||||
const watchedPullOk = await this.safeRun('pull_watched_items', async () => {
|
||||
await this.withSuppressedPushes(async () => {
|
||||
await this.pullWatchedItemsToLocal();
|
||||
|
|
@ -629,8 +638,8 @@ class SupabaseSyncService {
|
|||
return;
|
||||
}
|
||||
|
||||
const traktConnected = await this.isTraktConnected();
|
||||
if (traktConnected) return;
|
||||
const externalProgressSyncConnected = await this.isExternalProgressSyncConnected();
|
||||
if (externalProgressSyncConnected) return;
|
||||
|
||||
try {
|
||||
logger.log(`[SupabaseSyncService] flushWatchProgressDeletes: deleting ${keys.length} keys`);
|
||||
|
|
@ -700,12 +709,12 @@ class SupabaseSyncService {
|
|||
return;
|
||||
}
|
||||
|
||||
const traktConnected = await this.isTraktConnected();
|
||||
if (traktConnected) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (target === 'watch_progress') {
|
||||
const externalProgressSyncConnected = await this.isExternalProgressSyncConnected();
|
||||
if (externalProgressSyncConnected) {
|
||||
logger.log('[SupabaseSyncService] executeScheduledPush: skipping watch_progress due to external sync priority (Trakt/Simkl)');
|
||||
return;
|
||||
}
|
||||
await this.pushWatchProgressFromLocal();
|
||||
logger.log(`[SupabaseSyncService] executeScheduledPush: target=${target}:done`);
|
||||
return;
|
||||
|
|
@ -716,6 +725,12 @@ class SupabaseSyncService {
|
|||
return;
|
||||
}
|
||||
|
||||
const externalProgressSyncConnected = await this.isExternalProgressSyncConnected();
|
||||
if (externalProgressSyncConnected) {
|
||||
logger.log('[SupabaseSyncService] executeScheduledPush: skipping watched_items due to external sync priority (Trakt/Simkl)');
|
||||
return;
|
||||
}
|
||||
|
||||
await this.pushWatchedItemsFromLocal();
|
||||
logger.log(`[SupabaseSyncService] executeScheduledPush: target=${target}:done`);
|
||||
}
|
||||
|
|
@ -745,6 +760,8 @@ class SupabaseSyncService {
|
|||
}
|
||||
|
||||
private async setSession(session: SupabaseSession): Promise<void> {
|
||||
// Reset per-entry push cache on session changes to avoid cross-account state bleed.
|
||||
this.watchProgressPushedSignatures.clear();
|
||||
this.session = session;
|
||||
await mmkvStorage.setItem(SUPABASE_SESSION_KEY, JSON.stringify(session));
|
||||
}
|
||||
|
|
@ -775,6 +792,7 @@ class SupabaseSyncService {
|
|||
} catch (error) {
|
||||
logger.error('[SupabaseSyncService] Failed to refresh session:', error);
|
||||
this.session = null;
|
||||
this.watchProgressPushedSignatures.clear();
|
||||
await mmkvStorage.removeItem(SUPABASE_SESSION_KEY);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -791,6 +809,7 @@ class SupabaseSyncService {
|
|||
} catch (error) {
|
||||
logger.error('[SupabaseSyncService] Token refresh failed:', error);
|
||||
this.session = null;
|
||||
this.watchProgressPushedSignatures.clear();
|
||||
await mmkvStorage.removeItem(SUPABASE_SESSION_KEY);
|
||||
return null;
|
||||
}
|
||||
|
|
@ -997,6 +1016,22 @@ class SupabaseSyncService {
|
|||
};
|
||||
}
|
||||
|
||||
private getWatchProgressEntrySignature(value: { currentTime?: number; duration?: number; lastUpdated?: number }): string {
|
||||
return [
|
||||
Number(value.currentTime || 0),
|
||||
Number(value.duration || 0),
|
||||
Number(value.lastUpdated || 0),
|
||||
].join('|');
|
||||
}
|
||||
|
||||
private buildLocalWatchProgressKey(
|
||||
contentType: 'movie' | 'series',
|
||||
contentId: string,
|
||||
episodeId?: string
|
||||
): string {
|
||||
return `${contentType}:${contentId}${episodeId ? `:${episodeId}` : ''}`;
|
||||
}
|
||||
|
||||
private toStreamingContent(item: LibraryRow): StreamingContent {
|
||||
const type = item.content_type === 'movie' ? 'movie' : 'series';
|
||||
const posterShape = (item.poster_shape || 'POSTER').toLowerCase() as 'poster' | 'square' | 'landscape';
|
||||
|
|
@ -1037,6 +1072,19 @@ class SupabaseSyncService {
|
|||
}
|
||||
}
|
||||
|
||||
private async isSimklConnected(): Promise<boolean> {
|
||||
try {
|
||||
return await SimklService.getInstance().isAuthenticated();
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private async isExternalProgressSyncConnected(): Promise<boolean> {
|
||||
if (await this.isTraktConnected()) return true;
|
||||
return await this.isSimklConnected();
|
||||
}
|
||||
|
||||
private async pullPluginsToLocal(): Promise<void> {
|
||||
const token = await this.getValidAccessToken();
|
||||
if (!token) return;
|
||||
|
|
@ -1254,11 +1302,10 @@ class SupabaseSyncService {
|
|||
const type = row.content_type === 'movie' ? 'movie' : 'series';
|
||||
const season = row.season == null ? null : Number(row.season);
|
||||
const episode = row.episode == null ? null : Number(row.episode);
|
||||
remoteSet.add(`${type}:${row.content_id}:${season ?? ''}:${episode ?? ''}`);
|
||||
|
||||
const episodeId = type === 'series' && season != null && episode != null
|
||||
? `${row.content_id}:${season}:${episode}`
|
||||
: undefined;
|
||||
remoteSet.add(this.buildLocalWatchProgressKey(type, row.content_id, episodeId));
|
||||
|
||||
const local = await storageService.getWatchProgress(row.content_id, type, episodeId);
|
||||
const remoteLastWatched = this.normalizeEpochMs(row.last_watched);
|
||||
|
|
@ -1284,15 +1331,46 @@ class SupabaseSyncService {
|
|||
);
|
||||
}
|
||||
|
||||
logger.log(`[SupabaseSyncService] pullWatchProgressToLocal: merged ${(rows || []).length} remote entries (no local prune)`);
|
||||
// Remote-first continue watching: remove local entries that no longer exist remotely.
|
||||
// This intentionally treats the successful remote pull as authoritative.
|
||||
const allLocal = await storageService.getAllWatchProgress();
|
||||
let pruned = 0;
|
||||
for (const [localKey] of Object.entries(allLocal)) {
|
||||
if (remoteSet.has(localKey)) continue;
|
||||
|
||||
const parsed = this.parseWatchProgressKey(localKey);
|
||||
if (!parsed) continue;
|
||||
|
||||
const episodeId = parsed.videoId && parsed.videoId !== parsed.contentId ? parsed.videoId : undefined;
|
||||
await storageService.removeWatchProgress(parsed.contentId, parsed.contentType, episodeId);
|
||||
this.watchProgressPushedSignatures.delete(localKey);
|
||||
pruned += 1;
|
||||
}
|
||||
|
||||
logger.log(`[SupabaseSyncService] pullWatchProgressToLocal: merged=${(rows || []).length} prunedLocalMissing=${pruned}`);
|
||||
}
|
||||
|
||||
private async pushWatchProgressFromLocal(): Promise<void> {
|
||||
const all = await storageService.getAllWatchProgress();
|
||||
const entries: WatchProgressRow[] = Object.entries(all).reduce<WatchProgressRow[]>((acc, [key, value]) => {
|
||||
const nextSeenKeys = new Set<string>();
|
||||
const changedEntries: Array<{ key: string; row: WatchProgressRow; signature: string }> = [];
|
||||
|
||||
for (const [key, value] of Object.entries(all)) {
|
||||
nextSeenKeys.add(key);
|
||||
const signature = this.getWatchProgressEntrySignature(value);
|
||||
if (this.watchProgressPushedSignatures.get(key) === signature) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const parsed = this.parseWatchProgressKey(key);
|
||||
if (!parsed) return acc;
|
||||
acc.push({
|
||||
if (!parsed) {
|
||||
continue;
|
||||
}
|
||||
|
||||
changedEntries.push({
|
||||
key,
|
||||
signature,
|
||||
row: {
|
||||
content_id: parsed.contentId,
|
||||
content_type: parsed.contentType,
|
||||
video_id: parsed.videoId,
|
||||
|
|
@ -1302,11 +1380,30 @@ class SupabaseSyncService {
|
|||
duration: this.secondsToMsLong(value.duration),
|
||||
last_watched: this.normalizeEpochMs(value.lastUpdated || Date.now()),
|
||||
progress_key: parsed.progressKey,
|
||||
},
|
||||
});
|
||||
return acc;
|
||||
}, []);
|
||||
}
|
||||
|
||||
await this.callRpc<void>('sync_push_watch_progress', { p_entries: entries });
|
||||
// Prune signatures for entries no longer present locally (deletes are handled separately).
|
||||
for (const existingKey of Array.from(this.watchProgressPushedSignatures.keys())) {
|
||||
if (!nextSeenKeys.has(existingKey)) {
|
||||
this.watchProgressPushedSignatures.delete(existingKey);
|
||||
}
|
||||
}
|
||||
|
||||
if (changedEntries.length === 0) {
|
||||
logger.log('[SupabaseSyncService] pushWatchProgressFromLocal: no changed entries; skipping push');
|
||||
return;
|
||||
}
|
||||
|
||||
await this.callRpc<void>('sync_push_watch_progress', {
|
||||
p_entries: changedEntries.map((entry) => entry.row),
|
||||
});
|
||||
|
||||
for (const entry of changedEntries) {
|
||||
this.watchProgressPushedSignatures.set(entry.key, entry.signature);
|
||||
}
|
||||
logger.log(`[SupabaseSyncService] pushWatchProgressFromLocal: pushedChanged=${changedEntries.length} totalLocal=${Object.keys(all).length}`);
|
||||
}
|
||||
|
||||
private async pullLibraryToLocal(): Promise<void> {
|
||||
|
|
|
|||
Loading…
Reference in a new issue