feat: auto-skip to next source after 5 s on playback error#409
feat: auto-skip to next source after 5 s on playback error#409test01203 wants to merge 8 commits into
Conversation
Vanilla JS + Supabase single-page app served alongside the existing arvio.tv marketing site. No build step required — just static files. Features: - Google OAuth login (via Supabase GoTrue) - Dashboard with watch stats and recent activity - Profiles view — shows all ARVIO sub-profiles with active/kids badges - Addons manager — lists all Stremio + Telegram addons with enabled status - Watch History — paginated by movie/tv/all, delete individual entries - Watchlist — view and remove items - AI Subtitle Translation — toggle on/off, select model (Groq Llama 70B / Gemini Flash 2.5), configure auto-select and hearing-impaired removal; settings saved directly to cloud sync payload - Settings — card layout, language, OLED mode, skip profile selection Data layer: reads/writes the cloud sync payload stored in profiles.addons.__arvioAccountSyncPayload (same format the TV app uses), and queries watch_history/watchlist tables directly via Supabase REST. Co-Authored-By: koby455 <koby455@gmail.com>
Android TV app (CloudSyncRepository.kt): - Inject PluginDataStore into CloudSyncRepository - buildCloudPayload: export pluginRepositories, pluginScrapers, pluginsEnabled into __arvioAccountSyncPayload so plugins survive device wipes / multi-device - applyCloudPayload: restore repositories + scrapers from cloud on first launch (scraper JS code stays local-only for security; only metadata is synced) Companion web app (app.js): - Add IPTV section: shows all M3U playlists per profile with M3U/EPG URLs, enabled status, favourite groups and favourite channels - Add Plugins section: shows all plugin repositories (name, URL, scraper count, last updated) and individual scrapers (name, version, supported types, content languages, enabled status) with global plugins toggle - Add both to sidebar navigation Co-Authored-By: koby455 <koby455@gmail.com>
- All navigation labels, section titles, badges, toasts, and helper text translated to English in app.js and index.html - Auth screen subtitle and Google button label now in English - timeAgo() helper uses English relative-time strings - Hebrew remains fully supported as a selectable app language (setting stored in cloud sync payload as before) - Add mock-preview.html: standalone demo page with generic sample data for screenshots / PR previews (no Supabase dependency) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…cPayload - Add escapeHtml() helper and apply it to every cloud value injected into innerHTML: user display name/email/avatar initial, profile names, addon name/description/logo, IPTV playlist name/URL/EPG/profile label/fav groups+channels, plugin repo name/URL, scraper name/description/version/logo/types/languages, history title/poster, watchlist tmdb_id, settings user ID - Add safeUrl() helper (https/http only) and use it for all image src attributes that come from cloud data (addon logos, scraper logos, user avatar) - saveSyncPayload now reads the existing wrapper first and only updates __arvioAccountSyncPayload and __arvioAccountSyncUpdatedAt, preserving any other fields the TV app may have written Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Normalizes the URL via the browser's URL parser before use and HTML-escapes it, preventing quote/attribute injection from synced logo or avatar URLs in innerHTML img src attributes. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When a source fails to play, ARVIO now starts a 5-second countdown
and automatically advances to the next available source. A live
ticker ('Skipping to next source in 3…') is shown inside the error
modal so the user knows what is about to happen. A CANCEL SKIP button
lets them abort the countdown and stay on the current error screen.
The feature is toggled from Settings → Playback → Auto-skip failed
sources (default: On) and is persisted per profile to ARVIO Cloud via
the existing PROFILE_SETTINGS sync path.
Details
-------
PlayerScreen.kt
• New state var autoSkipCountdown (Int, -1 = inactive) and
autoSkipEnabled (Boolean, default true, loaded from DataStore key
*_auto_skip_failed_source on startup).
• LaunchedEffect(uiState.error, autoSkipEnabled): fires when an error
appears and there are ≥2 streams and the feature is on; counts from
5 → 0 with 1-second delay ticks, then calls tryAdvanceToNextStream().
Resets to -1 when the error clears or the user cancels.
• Error modal: shows countdown text and CANCEL SKIP button while
autoSkipCountdown > 0.
SettingsViewModel.kt
• autoSkipFailedSource Boolean field added to SettingsUiState.
• autoSkipFailedSourceKey() profile-scoped key helper.
• Loaded and defaulted to true in loadSettings().
• setAutoSkipFailedSource(Boolean) persists and syncs to cloud.
SettingsScreen.kt
• Row 38 added to the playback section (just after single-source
autoplay, row 11).
• Toggle wired in TvGeneralSettingsRows when-block and keyboard
handler. Mobile settings row also added.
|
Thanks, this is a useful feature idea and I do want this in ARVIO, but this PR needs fixes before merge. I tested the exact merge into current main. It merges cleanly, but it does not compile. Issues I found:
Once these are fixed and both Play/Sideload Kotlin compile passes, I think the feature is worth merging. |
Fixes five issues raised in code review: 1. Remove duplicate errorModalFocusIndex declaration that broke compileSideloadDebugKotlin with cascading errors. 2. Replace unresolved Icons.Default.SkipNext in SettingsScreen with Icons.Default.Schedule (already imported in that file). 3. Fix cancel-skip race condition: add autoSkipCancelled Boolean flag that is set to true by the CANCEL SKIP button and checked inside the countdown loop, so pressing Cancel can never let the coroutine still advance to the next source after the countdown finishes. 4. Read the setting properly via uiState instead of fragile DataStore scan: add autoSkipFailedSource to PlayerUiState, load it in PlayerViewModel using the typed profileBooleanKey helper (same pattern as autoPlayNext), and derive it in PlayerScreen from uiState.autoSkipFailedSource. The LaunchedEffect key now also includes uiState.streams.size so re-evaluates when new streams arrive. 5. Wire cloud sync: add autoSkipFailedSource to CloudProfileSettings data class, add per-profile key helpers, include it in both the buildCloudSnapshotJson() snapshot and the applyCloudPayload() restore path (both per-profile and the active-profile fallback), matching the exact pattern used for autoPlaySingleSource.
|
Thank you for the detailed review — all five issues are now fixed in the latest push: 1. Duplicate 2. 3. Cancel-skip race condition — added a separate 4. Fragile DataStore reading — the PlayerScreen no longer reads DataStore directly.
The 5. Cloud sync not wired —
This matches the exact pattern used for |
What this adds
When a source fails to play, ARVIO now automatically skips to the next available source after 5 seconds — with a live countdown so the user knows exactly what's happening and can cancel if needed.
User experience
tryAdvanceToNextStream()is called automaticallyThe feature only triggers when there are ≥ 2 streams available and the error is a real playback error (not the setup/no-addons guide).
Settings toggle
Settings → Playback → Auto-skip failed sources (default: On)
PROFILE_SETTINGSpathImplementation — 3 files, 80 insertions
PlayerScreen.ktautoSkipCountdown: Int-1= inactive,5..1= countingautoSkipEnabled: Boolean*_auto_skip_failed_sourceLaunchedEffect(uiState.error, autoSkipEnabled)tryAdvanceToNextStream()at zeroThe countdown resets to
-1whenever the error clears, the user cancels, or the feature is off.SettingsViewModel.ktval autoSkipFailedSource: Boolean = trueadded toSettingsUiStateautoSkipFailedSourceKey()— profile-scoped DataStore key helpertrue) inloadSettings()setAutoSkipFailedSource(Boolean)— persists locally and callssyncLocalStateToCloud()SettingsScreen.kt"playback"section list (just after row 11 = single-source autoplay)when (38)case inTvGeneralSettingsRowsrenders aSettingsToggleRowMobileSettingsRowadded alongside the existing autoplay toggle🤖 Generated with Claude Code