Add ARVIO Companion web app with Hebrew/English i18n#377
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>
|
One thing should be fixed before merge/deploy though: the companion app renders a lot of synced/user-controlled data with raw innerHTML. Profile names, IPTV playlist names/URLs, plugin repo/scraper names/descriptions/logos, addon info, watch history titles, and even account display info should be escaped before rendering. Otherwise a bad synced value could inject HTML/script into the companion page. Please add an escapeHtml() helper for text, a safeUrl() helper for image/link attributes, and use those everywhere cloud/Supabase data is interpolated into HTML. Or even better, render those values with DOM textContent instead of innerHTML. Also small safety improvement: saveSyncPayload currently rewrites the whole profiles.addons wrapper. Please preserve any existing wrapper fields and only update __arvioAccountSyncPayload and __arvioAccountSyncUpdatedAt. |
…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>
|
Thanks for the review! Both issues are now fixed in the latest commit. XSS / innerHTML escaping Added two helpers:
saveSyncPayload wrapper preservation
|
|
One last small safety fix before merge: safeUrl() validates the URL with new URL(url), but then returns the original input string. Please return the normalized u.href instead, preferably escaped before putting it into img src attributes. That avoids weird quote/attribute edge cases in synced logo/avatar URLs. After that I think this is good to merge |
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>
|
Done! Fixed in commit 89c9bc5.
// Before
return (u.protocol === 'https:' || u.protocol === 'http:') ? url : '';
// After
return (u.protocol === 'https:' || u.protocol === 'http:') ? escapeHtml(u.href) : '';
|
Summary
/companion/— lets users manage their ARVIO account from any browserlocalStorage)STRINGSobject witht()helper — supports pluralization via function values and RTL/LTR switchingWhat changed
netlify-arvio-tv-site/companion/(new directory)index.htmlstyle.cssapp.jsmock-preview.htmlKey app.js additions
STRINGSobject with completeen+hetranslations for every string in the appt(key, ...args)helper resolves strings/pluralizers by current languagesetLang(lang)switches language live — updates<html lang/dir>, re-renders shell + active sectionעב/EN) in the sidebar user rowData
Reads from Supabase
profiles.addons.__arvioAccountSyncPayload(same cloud sync payload as the TV app). Watch history and watchlist use dedicated Supabase tables. AI and general settings are written back via the same payload.Reviewer notes
mock-preview.htmlis for development/screenshot use only and is not linked from productionhttps://arvio.tv/companion/must be added to Supabase Auth → URL Configuration before deployment