Address Codex review feedback on PR #6627
- Classify IPv4/IPv6 link-local addresses (169.254.0.0/16, fe80::/10) as LAN in Jellyfin location parsing - they can't traverse a router, so a false WAN reading was possible for common autoconfig/link-local sessions. - Fix portrait video resolution mislabeling - a 1080x1920 clip was classified off its long-axis height (1920) and showed as 1440p. Classify by the short axis instead so orientation doesn't flip the result. - Raise the compact-mode status column breakpoint from 420 to 540px - at 420 the fixed-width user (200px) and status (190px) columns left almost no room for the currentlyPlaying column, the widget's primary content. - Document the new resolution indicator in the media-server widget docs.
This commit is contained in:
1 parent
a4bbed0cb8
commit
76ba13fbad
5 files changed
+31
-9
No files matched your search
@@ -109,7 +109,8 @@ describe("getMediaServerColumnVisibility", () => {
|
||||
test("keeps a stable responsive column model from the zero-sized first render", () => {
|
||||
expect(getMediaServerColumnVisibility(0, false)).toEqual({ user: false, status: false });
|
||||
expect(getMediaServerColumnVisibility(300, false)).toEqual({ user: true, status: false });
|
||||
expect(getMediaServerColumnVisibility(420, false)).toEqual({ user: true, status: true });
|
||||
expect(getMediaServerColumnVisibility(420, false)).toEqual({ user: true, status: false });
|
||||
expect(getMediaServerColumnVisibility(540, false)).toEqual({ user: true, status: true });
|
||||
expect(getMediaServerColumnVisibility(0, true)).toEqual({ user: true, status: true });
|
||||
});
|
||||
});
|
||||
@@ -149,4 +150,10 @@ describe("getResolutionLabel", () => {
|
||||
test("falls back to the raw height when it doesn't clear any known tier", () => {
|
||||
expect(getResolutionLabel(100, 100)).toBe("100p");
|
||||
});
|
||||
|
||||
test("classifies a portrait video by its width, not its long-axis height", () => {
|
||||
// A 1080x1920 portrait phone recording is still a 1080p source, not a 1440p one.
|
||||
expect(getResolutionLabel(1080, 1920)).toBe("1080p");
|
||||
expect(getResolutionLabel(720, 1280)).toBe("720p");
|
||||
});
|
||||
});
|
||||
@@ -51,7 +51,9 @@ type SortState = { column: SortColumn; descending: boolean } | null;
|
||||
|
||||
export const getMediaServerColumnVisibility = (width: number, isAdvanced: boolean) => ({
|
||||
user: isAdvanced || width >= 300,
|
||||
status: isAdvanced || width >= 420,
|
||||
// The user (200px) and status (190px) columns together need a floor here, otherwise the
|
||||
// currentlyPlaying column - the primary content - gets squeezed to almost nothing.
|
||||
status: isAdvanced || width >= 540,
|
||||
});
|
||||
|
||||
function getPlaybackStatus(transcoding: TranscodingDecision | undefined): PlaybackStatus {
|
||||
@@ -80,12 +82,16 @@ function formatBitrate(bitrateKbps: number | null | undefined): string | null {
|
||||
const RESOLUTION_TIER_HEIGHTS = [4320, 2160, 1440, 1080, 720, 480, 360, 240] as const;
|
||||
|
||||
export function getResolutionLabel(width: number, height: number): string {
|
||||
// Letterboxed/cinemascope sources are cropped shorter than their nominal resolution class
|
||||
// (a 1920x804 encode is still "1080p"), so classify off the width-derived 16:9 height instead
|
||||
// of the raw (possibly cropped) height - matches how Plex/Jellyfin label these themselves.
|
||||
const effectiveHeight = Math.max(height, Math.round((width * 9) / 16));
|
||||
const tier = RESOLUTION_TIER_HEIGHTS.find((candidate) => effectiveHeight >= candidate * 0.9);
|
||||
return `${tier ?? effectiveHeight}p`;
|
||||
// Classify off the short axis (height for landscape, width for portrait) so orientation
|
||||
// doesn't flip which dimension drives the label. Letterboxed/cinemascope sources are cropped
|
||||
// shorter than their nominal resolution class (a 1920x804 encode is still "1080p"), so derive
|
||||
// a floor for the short axis from the long axis assuming 16:9 - matches how Plex/Jellyfin label these themselves.
|
||||
const isPortrait = height > width;
|
||||
const shortAxis = isPortrait ? width : height;
|
||||
const longAxis = isPortrait ? height : width;
|
||||
const effectiveShortAxis = Math.max(shortAxis, Math.round((longAxis * 9) / 16));
|
||||
const tier = RESOLUTION_TIER_HEIGHTS.find((candidate) => effectiveShortAxis >= candidate * 0.9);
|
||||
return `${tier ?? effectiveShortAxis}p`;
|
||||
}
|
||||
|
||||
export function getSeasonEpisodeParams(
|
||||
|
||||
Reference in new issue
Block a user