Unify favourite writes through SyncUserFavorite so remote mounted media is
stored locally and proxied to the upstream Emby server. Emby clients now
query favourites from the local table (including remote pseudo IDs), and
remote item payloads merge local IsFavorite state.
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: truewhile <truewhile@users.noreply.github.com>
* Rebrand MMTL to MeBox across codebase and assets
Rename the project display name, Go module path, environment variable
prefix (MEBOX_*), Docker image references, and UI branding from MMTL/mmtl
to MeBox/mebox. Replace logo assets with the new MeBox icon and keep
legacy SQLite migration support for existing mmtl.db deployments.
Co-authored-by: truewhile <truewhile@users.noreply.github.com>
* Fix logo icons: use cube-only crop without truncated text
Previous icon generation cropped too much of the source image, including
partial MeBox wordmark text that was cut off in square icon containers.
Regenerate logo-64/192/512, favicon, and SVG from cube-only region.
Co-authored-by: truewhile <truewhile@users.noreply.github.com>
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: truewhile <truewhile@users.noreply.github.com>
* Add favourite buttons to library list and series detail pages
Co-authored-by: truewhile <truewhile@users.noreply.github.com>
* Fix favourites list for remote Emby mounted media
Co-authored-by: truewhile <truewhile@users.noreply.github.com>
* Route favourites to library series detail when appropriate
Co-authored-by: truewhile <truewhile@users.noreply.github.com>
* Fix favourites link to library series for remote anime paths
Co-authored-by: truewhile <truewhile@users.noreply.github.com>
* Fix remote Emby playback history and continue watching
- Preserve duration_ms when web player reports duration=0
- Add GET /playback/:id/resume for reliable per-item resume
- Switch home continue watching to /watch-history/continue API
- Set library_id on remote media for play-profile visibility
- Keep continue-watching rows when remote metadata hydration fails
Co-authored-by: truewhile <truewhile@users.noreply.github.com>
* Fix mobile sort dropdown overflowing off-screen
Align dropdown to button left edge on small screens and cap width
to viewport so sort options stay fully visible on mobile.
Co-authored-by: truewhile <truewhile@users.noreply.github.com>
* Remove stale Windows binary backup files
Co-authored-by: truewhile <truewhile@users.noreply.github.com>
* Fix STRM account edit form not echoing saved config
Return config_preview from account API for server/url/username and
secret flags. Merge partial config updates so empty password/token
fields do not wipe stored credentials.
Co-authored-by: truewhile <truewhile@users.noreply.github.com>
* perf(strm): speed up OpenList metadata downloads with provider-aware concurrency
- Split download semaphore: 115 stays capped at 3 for WAF safety; OpenList/CloudDrive2
WebDAV metadata uses strm.download_threads (default raised to 6, max 16)
- Scope 115 WAF cooldown to 115 tasks only so OpenList downloads are not paused
- Requeue claimed tasks back to pending when slot acquisition fails or 115 is cooling
- Add tests for separate semaphores and requeue behavior
Co-authored-by: truewhile <truewhile@users.noreply.github.com>
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: truewhile <truewhile@users.noreply.github.com>
Backend
- service/ffprobe.go: thin ffprobe wrapper, parses duration / resolution /
codecs into a typed ProbeResult. 30s per-file timeout.
- service/tmdb.go: minimal TMDb provider (search/movie). Disabled when no
api key; supports tmdb_api_proxy / tmdb_image_proxy overrides for users
behind a firewall.
- service/scraper.go: filename cleaner (handles bracketed tags, scene
noise tokens, year extraction), per-row + per-library enrichment with a
4 RPS throttle and WS hub progress events. Unit-tested.
- service/scanner.go: now invokes ffprobe per file and kicks the TMDb
scraper in the background once a library scan finishes.
- service/transcoder.go: per-media ffmpeg HLS job manager; outputs
index.m3u8 + seg_NNNNN.ts under cache/hls/<id>; cancels jobs on
shutdown; publishes 'transcode' WS events.
- service/stream.go: serves HLS playlist (with 30s wait-for-ready) and
.ts segments with path-traversal protection. Adds Probe() helper used
by the admin 'reprobe' button.
- service/image_proxy.go: cached, host-allow-listed reverse proxy for
TMDb / Bangumi / Douban / Fanart / TheTVDB images so the SPA never
hits a CORS or GFW issue.
- service/playback.go: history upsert, favourites toggle, playlist CRUD
+ ordered items. RecentHistory joins with model.Media in one extra
query so the home page can render a 'Continue Watching' row.
- handler/streaming.go + handler/playback.go: REST endpoints for HLS,
image proxy, scrape (one + library), reprobe, history, favourites,
playlists.
- handler/handler.go: registers /api/hls/:id/{index.m3u8,:seg}, /api/img,
/api/history, /api/favourites/:id, /api/playlists/* with proper
auth/admin guards.
Frontend
- api/client.ts: imageURL() helper; hlsURL() endpoint; reuses the JWT in
a query parameter for <video src> and <img src>.
- api/playback.ts: typed helpers for history, favourites, playlists.
- components/MediaCard.tsx: optional 'progress' prop renders a thin
bottom progress bar, used by the new Continue Watching row.
- pages/HomePage.tsx: two rows (Continue Watching + Recently Added);
falls back to the empty-state hint when both are empty.
- pages/PlayerPage.tsx: hls.js (lazy-imported) with auto-fallback to
direct play; ?mode=hls|direct query toggle; resume position written
every 10s while playing.
- pages/MediaDetailPage.tsx: heart toggle + admin 'rescrape' / 'reprobe'
buttons + dedicated 'HLS 转码播放' CTA.
- pages/FavouritesPage.tsx, PlaylistsPage.tsx, PlaylistDetailPage.tsx:
new screens.
- components/Layout.tsx + App.tsx: sidebar links for Favourites and
Playlists; routes are now lazily code-split via React.lazy + Suspense
so the initial bundle stays at ~243 KB / 82 KB gzipped (hls.js is
fetched only on first HLS playback).
Verified: go build, go vet, go test (incl. CleanQuery cases) all pass;
frontend tsc -b && vite build emits 9 route chunks plus a deferred hls
chunk.