mirror of
https://github.com/movixcorp/MovixOpenSource.git
synced 2026-07-27 05:02:08 +00:00
Nettoyage massif côté frontend, grosse passe perf, app mobile v2.5.3
(écran qui ne s'éteint plus + fix build), extracteur Uqload HLS sur
extensions/userscript, redirection réseau-bloqué via passerelle
explicative et cast cross-receiver/cross-browser.
Nettoyage Firebase & code mort
- Drop firebase + @firebase/firestore (package.json + vite.config
optimizeDeps + alias)
- Suppression src/config/firebase.ts (jamais utilisé)
- Suppression services morts : adminService, commentService, logService,
notificationService + composants liés (AdminLogin, CommentSection,
CommentItem, ReactionBar) + types/Comment.ts
- Suppression scripts non-utilisés : bundle-report.mjs, publish-app.mjs
- Net : -3 449 lignes
Perf carrousels & TMDB images
- useTmdbImages : 1 seul fetch TMDB pour logo + poster (au lieu de 2),
prefetch idle au mount du carousel + dedup via inflight map (0 doublon
entre prefetch et hooks), include_image_language=fr,en,null pour
récupérer les versions FR-prioritisées
- EmblaCarousel : pré-décode des posters off-DOM (img.decode) en idle
pour éliminer le coût de décode pendant le scroll horizontal, priority
cap statique (eager + fetchpriority=high pour les N premières cards
selon viewport), suppression du tracking visibleSlides (state churn)
- content-visibility:auto sur slides hors viewport (skip layout/paint
natif), exclu des slides Top 10 pour ne pas clipper le digit débordant
- will-change:transform pré-promotion compositing layer (PC only via
hover:hover)
- Embla duration 25 → 15 (snap plus rapide, moins de frames composées)
- Boutons nav carousel : suppression backdrop-blur (cher), bg opaque
- LazyImage : width/height attrs pour éviter CLS + alléger placeholder
Top progress bar (style YouTube)
- TopProgressBar : asymptote vers 85% pendant chunk loads, fill 100%
smooth + fade out à la fin, 120ms grace period pour suppress flash
sur chunks cachés
- lazyWithRetry tracke les loads actifs + dispatch chunk:load:start /
chunk:load:end events sur window
- Routes loaders supportent { silent: true } pour skip le tracking sur
les prefetch (PrefetchLink hover + IDLE_PREFETCH au mount)
SW redirect → passerelle movix.health explicative
- buildMirrorUrl() factorise la construction d'URL miroir avec contexte
- handleNavigation passe ?from=&reason=unreachable&error=&via= à la
gateway pour qu'elle affiche une popup explicative au user au lieu
d'un redirect silencieux
- MOVIX_FORCE_REDIRECT message handler passe reason=api-errors
- blockDetection.ts transmet la dernière erreur axios au SW
- index.html : cache-bust du Cast SDK URL (cb=Date.now()) pour éviter
qu'un SDK stale ne reste coincé en cache navigateur/SW
Cast (Chromecast + AirPlay + Remote Playback API)
- loadMediaOnCastWithFallback : retry sur 3 MIME HLS différents
(application/vnd.apple.mpegurl, x-mpegurl, x-mpegURL) — certains
receivers rejettent le premier choix selon firmware
- Subtitles externes attachés au cast (CastSubtitleTrack) via
chrome.cast.media.Track + TextTrackStyle par défaut (50% black
background, edge outline) lisible sur la majorité des TV
- isRemotePlaybackSupported : fallback W3C Remote Playback API pour
Firefox / Edge avec cast extension bloquée / Brave avec shields →
device discovery + picker via video.remote.prompt()
- initializeAirPlay supporte désormais les deux paths (WebKit AirPlay
pour Safari + Remote Playback pour les autres)
- Détection castSdkBlocked : si le SDK Cast ne charge pas en 5s
(adblock, FAI, shield), affiche un message d'erreur explicite au
lieu du générique "aucun device trouvé"
- 7 nouvelles strings i18n FR + EN pour les états cast :
castUnavailable, castUnavailableNoDevices,
castUnavailableUnsupportedBrowser, castUnavailableSdkBlocked,
castUnavailableHelpChromecast, castUnavailableHelpAirPlay,
castUnavailableSeeHelp
App mobile Android v2.5.3 (versionCode 12)
- AndroidManifest : android:keepScreenOn="true" sur MainActivity →
l'écran ne s'éteint plus pendant le visionnage (avant le user devait
toucher l'écran toutes les 30s pour pas que le téléphone se lock en
plein film)
- build.gradle : exclude androidx.legacy:legacy-support-core-utils
(tiré transitivement par mediarouter → palette) qui embarquait ses
propres androidx.autofill.R$attr → "duplicate class" au mergeDexRelease
contre le module androidx.autofill:autofill:1.1.0 d'appcompat
- gradle.properties : android.nonTransitiveRClass=true pour empêcher
chaque lib de regénérer ses R classes transitivement (même cause
racine du duplicate class)
- version.json bumped 2.5.2 → 2.5.3, nouvel APK (-17KB), release notes
FR : "Correction extraction du lecteur Uqload" + "L'écran ne s'éteint
plus lors de l'utilisation de l'app"
- apkUrl repointé sur le repo Movix-STMG (au lieu de movixcorp)
Userscript + Extensions Chrome/Firefox — Uqload HLS
- extractUqload : préfère désormais le master.m3u8 multi-bitrate (qualité
adaptative) au v.mp4 single-quality. Regex tente d'abord
/master\.m3u8/, sinon n'importe quel .m3u8, et fallback sur l'ancien
pattern v.mp4 si rien trouvé. Les 3 cibles (Chrome MV3, Firefox MV2,
Tampermonkey) sont synchronisées sur la même logique.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
109 lines
3.8 KiB
JSON
109 lines
3.8 KiB
JSON
{
|
|
"name": "streaming-site",
|
|
"private": true,
|
|
"version": "0.1.0",
|
|
"type": "module",
|
|
"scripts": {
|
|
"dev": "vite",
|
|
"build": "vite build",
|
|
"build:cf": "vite build",
|
|
"build:coolify": "vite build",
|
|
"build:report": "vite build && node scripts/bundle-report.mjs",
|
|
"lint": "eslint .",
|
|
"preview": "vite preview",
|
|
"start": "node server/index.js",
|
|
"start:coolify": "node server/index.js",
|
|
"dev:server": "node server/index.js",
|
|
"app:publish": "node scripts/publish-app.mjs",
|
|
"wasm:watchparty-sync:setup": "rustup target add wasm32-unknown-unknown && cargo install wasm-bindgen-cli",
|
|
"wasm:watchparty-sync:build": "cargo build --manifest-path wasm/watchparty-sync/Cargo.toml --target wasm32-unknown-unknown --release && wasm-bindgen --target web --out-dir public/wasm/watchparty-sync wasm/watchparty-sync/target/wasm32-unknown-unknown/release/watchparty_sync.wasm",
|
|
"wasm:watchparty-sync:build:dev": "cargo build --manifest-path wasm/watchparty-sync/Cargo.toml --target wasm32-unknown-unknown && wasm-bindgen --target web --out-dir public/wasm/watchparty-sync wasm/watchparty-sync/target/wasm32-unknown-unknown/debug/watchparty_sync.wasm"
|
|
},
|
|
"dependencies": {
|
|
"@dnd-kit/core": "^6.3.1",
|
|
"@dnd-kit/modifiers": "^9.0.0",
|
|
"@dnd-kit/sortable": "^10.0.0",
|
|
"@dnd-kit/utilities": "^3.2.2",
|
|
"@emoji-mart/data": "^1.2.1",
|
|
"@emoji-mart/react": "^1.1.1",
|
|
"@headlessui/react": "^2.2.0",
|
|
"@hono/node-server": "^1.19.14",
|
|
"@radix-ui/react-dialog": "^1.1.15",
|
|
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
|
"@radix-ui/react-select": "^2.2.6",
|
|
"@radix-ui/react-slot": "^1.2.3",
|
|
"@radix-ui/react-tooltip": "^1.2.8",
|
|
"@tanstack/react-virtual": "^3.13.24",
|
|
"axios": "^1.13.2",
|
|
"canvas-confetti": "^1.9.4",
|
|
"class-variance-authority": "^0.7.1",
|
|
"clsx": "^2.1.1",
|
|
"dashjs": "^5.1.1",
|
|
"date-fns": "^4.1.0",
|
|
"embla-carousel": "^8.6.0",
|
|
"embla-carousel-autoplay": "^8.6.0",
|
|
"embla-carousel-react": "^8.6.0",
|
|
"emoji-mart": "^5.6.0",
|
|
"file-saver": "^2.0.5",
|
|
"framer-motion": "11.11.10",
|
|
"hls.js": "^1.6.16",
|
|
"hono": "^4.12.14",
|
|
"i18next": "^25.8.10",
|
|
"i18next-browser-languagedetector": "^8.2.1",
|
|
"jszip": "^3.10.1",
|
|
"lenis": "^1.3.23",
|
|
"lucide-react": "^0.344.0",
|
|
"mpegts.js": "^1.8.0",
|
|
"pako": "^2.1.0",
|
|
"qrcode": "^1.5.4",
|
|
"react": "^18.3.1",
|
|
"react-colorful": "^5.6.1",
|
|
"react-country-flag": "^3.1.0",
|
|
"react-dom": "^18.3.1",
|
|
"react-force-graph-2d": "^1.29.1",
|
|
"react-helmet-async": "^2.0.5",
|
|
"react-i18next": "^16.5.4",
|
|
"react-input-mask": "^2.0.4",
|
|
"react-loading-skeleton": "^3.5.0",
|
|
"react-markdown": "^10.1.0",
|
|
"react-router-dom": "^6.22.3",
|
|
"react-snowfall": "^2.4.0",
|
|
"remark-emoji": "^5.0.1",
|
|
"remark-gfm": "^4.0.1",
|
|
"shaka-player": "^5.0.0",
|
|
"socket.io-client": "^4.8.1",
|
|
"sonner": "^2.0.7",
|
|
"tailwind-merge": "^3.4.0",
|
|
"tailwindcss-animate": "^1.0.7",
|
|
"uuid": "^11.1.0",
|
|
"video.js": "^8.23.4",
|
|
"web-haptics": "^0.0.6"
|
|
},
|
|
"devDependencies": {
|
|
"@eslint/js": "^9.9.1",
|
|
"@types/file-saver": "^2.0.7",
|
|
"@types/react": "^18.3.5",
|
|
"@types/react-dom": "^18.3.0",
|
|
"@types/react-input-mask": "^3.0.6",
|
|
"@types/uuid": "^10.0.0",
|
|
"@types/video.js": "^7.3.58",
|
|
"@vitejs/plugin-basic-ssl": "^2.3.0",
|
|
"@vitejs/plugin-react": "^6.0.1",
|
|
"autoprefixer": "^10.4.18",
|
|
"eslint": "^9.9.1",
|
|
"eslint-plugin-react-hooks": "^5.1.0-rc.0",
|
|
"eslint-plugin-react-refresh": "^0.4.11",
|
|
"eslint-plugin-unused-imports": "^4.3.0",
|
|
"globals": "^15.9.0",
|
|
"postcss": "^8.4.35",
|
|
"rollup-plugin-visualizer": "^7.0.1",
|
|
"tailwindcss": "^3.4.1",
|
|
"typescript": "^5.5.3",
|
|
"typescript-eslint": "^8.3.0",
|
|
"vite": "^8.0.11",
|
|
"wrangler": "^4.15.1"
|
|
},
|
|
"overrides": {
|
|
"framer-motion": "11.11.10"
|
|
}
|
|
}
|