Wire up playback reporting, fix duration flash, hide video from audio mini player
Playback reporting (position sync / resume-on-another-device): - player_configure_jellyfin now builds a PlaybackReporter sharing the player controller's Arc, so Start/Progress/Stopped actually reach Jellyfin on every auth path (login/restore/reauth); previously they never did. - The PlaybackReporterWrapper now shares the same Arc the controller and MPV progress loop report through, instead of a dead parallel Option. - Android position callbacks now emit throttled progress reports (30s/item), mirroring the MPV backend. Duration flash on pause: - resolveDuration() prefers the live store duration for the already-loaded track over the runTimeTicks estimate, so pausing no longer clobbers the slider's max to 0 when runTimeTicks is missing. Video leaking into audio mini player: - isVideoItem() also checks the backend PlayerMediaItem mediaType discriminator, so a video started via player_play_item (no Jellyfin `type`, mediaType "video") no longer surfaces in the audio mini player. Middle-truncation of long media names: - New truncateMiddle util applied to track/episode/card/mini-player titles so distinguishing tails (episode numbers, suffixes) stay visible. Adds regression tests for the duration and mini-player fixes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Abbreviate a long string in the middle so both the start and the end stay
|
||||
* visible, e.g. `long_media_name_like_this` -> `long_med…ike_this`.
|
||||
*
|
||||
* Unlike CSS `text-overflow: ellipsis` (which only clips the end), this keeps
|
||||
* the tail of a media name — often the most distinguishing part (episode
|
||||
* number, disambiguating suffix, etc.).
|
||||
*
|
||||
* @param value The string to abbreviate.
|
||||
* @param maxLength Maximum length of the returned string, including the ellipsis.
|
||||
* @param ellipsis The separator inserted in the middle (default `…`).
|
||||
*/
|
||||
export function truncateMiddle(
|
||||
value: string | null | undefined,
|
||||
maxLength = 32,
|
||||
ellipsis = "…",
|
||||
): string {
|
||||
if (value == null) return "";
|
||||
if (maxLength <= 0) return "";
|
||||
if (value.length <= maxLength) return value;
|
||||
|
||||
// Not enough room for any real content around the ellipsis: fall back to a
|
||||
// plain head-truncation so we never return more than maxLength characters.
|
||||
if (maxLength <= ellipsis.length) {
|
||||
return value.slice(0, maxLength);
|
||||
}
|
||||
|
||||
const keep = maxLength - ellipsis.length;
|
||||
const head = Math.ceil(keep / 2);
|
||||
const tail = Math.floor(keep / 2);
|
||||
|
||||
return value.slice(0, head) + ellipsis + (tail > 0 ? value.slice(value.length - tail) : "");
|
||||
}
|
||||
Reference in New Issue
Block a user