fix: keep compact title progress adjacent and truncate the title tail

This commit is contained in:
2026-10-12 16:28:25 +02:00
parent 35fa89e492
commit daac27be8d
3 changed files with 27 additions and 19 deletions
+3 -3
View File
@@ -21,9 +21,9 @@ struct SystemPlaybackChecks {
let times: [(Double, Double, String)] = [ let times: [(Double, Double, String)] = [
(12.9, 45.9, "12 / 45 s"), (12.9, 45.9, "12 / 45 s"),
(59, 59.999, "59 / 59 s"), (59, 59.999, "59 / 59 s"),
(0, 60, "00:00 / 01:00 min"), (0, 60, "00:00 / 01:00 m"),
(312, 2528, "05:12 / 42:08 min"), (312, 2528, "05:12 / 42:08 m"),
(3599, 3599.999, "59:59 / 59:59 min"), (3599, 3599.999, "59:59 / 59:59 m"),
(59, 3600, "00:00 / 01:00 h"), (59, 3600, "00:00 / 01:00 h"),
(4980, 7800, "01:23 / 02:10 h"), (4980, 7800, "01:23 / 02:10 h"),
(-5, 45, "0 / 45 s"), (-5, 45, "0 / 45 s"),
+2 -2
View File
@@ -193,9 +193,9 @@ The inline URL field, including its placeholder, uses the same 12-point system f
With no media open, the full window uses native behind-window HUD glass with a 35%-opaque brown tint. Static, cached amber/rust radial gradients add ambient color only to the empty screen; they disappear during loading or errors, and are never drawn over video or playback chrome. Glass title/control/error surfaces use the same brown tint with half-point sand outlines. Decorative drawing does not intercept input. The idle Metal surface stays attached but hidden; opening media restores a solid black background and letterboxing without tinting the video, and closing it restores the ambient frosted background. macOS controls the material’s appearance, including Reduce Transparency. With no media open, the full window uses native behind-window HUD glass with a 35%-opaque brown tint. Static, cached amber/rust radial gradients add ambient color only to the empty screen; they disappear during loading or errors, and are never drawn over video or playback chrome. Glass title/control/error surfaces use the same brown tint with half-point sand outlines. Decorative drawing does not intercept input. The idle Metal surface stays attached but hidden; opening media restores a solid black background and letterboxing without tinting the video, and closing it restores the ambient frosted background. macOS controls the material’s appearance, including Reduce Transparency.
Normal and compact titlebars have no full-width glass strip or separator: content extends beneath AppKit’s transparent titlebar using `fullSizeContentView`, `titlebarAppearsTransparent`, and `titlebarSeparatorStyle = .none`. Normal-mode titles and their file icons have a small rounded HUD-glass backdrop for legibility; the pin stays over the existing background. Compact titles sit in a controls-style frosted box with 8-point top/left insets, matching the controller’s bottom inset. The title truncates in the middle before the progress does, and the box fits the 160-point minimum width. Native traffic lights and window dragging are preserved. Normal and compact titlebars have no full-width glass strip or separator: content extends beneath AppKit’s transparent titlebar using `fullSizeContentView`, `titlebarAppearsTransparent`, and `titlebarSeparatorStyle = .none`. Normal-mode titles and their file icons have a small rounded HUD-glass backdrop for legibility; the pin stays over the existing background. Compact titles sit in a content-sized, left-aligned frosted box with 8-point top/left insets, matching the controller’s bottom inset. Title and progress remain adjacent with no expanding gap. When they cannot fit, the title truncates at the end with an ellipsis while progress stays visible; the box fits the 160-point minimum width. Native traffic lights and window dragging are preserved.
Compact titles default to `<title> · <position> / <duration> <unit>`, using acknowledged playback position rather than slider previews. Total duration selects the format: below one minute, `12 / 45 s`; from one minute to below one hour, `05:12 / 42:08 min`; from one hour onward, `01:23 / 02:10 h`. Values truncate to the displayed precision. Set `[ui].compact_title_progress = "percentage"` to append only a whole percentage number (`<title> · 59`, without a percent sign), or `"none"` for title-only display. Percentages truncate and stay within 0–100. Loading, failed, live, unknown-duration and closed media have no progress suffix. Normal-mode titles remain unchanged. Compact titles default to `<title> · <position> / <duration> <unit>`, using acknowledged playback position rather than slider previews. Total duration selects the format: below one minute, `12 / 45 s`; from one minute to below one hour, `05:12 / 42:08 m`; from one hour onward, `01:23 / 02:10 h`. Values truncate to the displayed precision. Set `[ui].compact_title_progress = "percentage"` to append only a whole percentage number (`<title> · 59`, without a percent sign), or `"none"` for title-only display. Percentages truncate and stay within 0–100. Loading, failed, live, unknown-duration and closed media have no progress suffix. Normal-mode titles remain unchanged.
Opening video fits the window to its display aspect ratio, including non-square pixels, and constrains subsequent window resizing. Fullscreen retains the normal letterboxed renderer; audio-only playback and close release the aspect constraint. Extreme ratios that cannot fit both the screen and usable controls keep a freely resizable letterboxed window. Opening video fits the window to its display aspect ratio, including non-square pixels, and constrains subsequent window resizing. Fullscreen retains the normal letterboxed renderer; audio-only playback and close release the aspect constraint. Extreme ratios that cannot fit both the screen and usable controls keep a freely resizable letterboxed window.
+22 -14
View File
@@ -14,7 +14,7 @@ func compactProgressText(position: Double, duration: Double, format: CompactTitl
let totalUnits = total / divisor let totalUnits = total / divisor
let currentTime = String(format: "%02lld:%02lld", Int64(currentUnits / 60), Int64(currentUnits % 60)) let currentTime = String(format: "%02lld:%02lld", Int64(currentUnits / 60), Int64(currentUnits % 60))
let totalTime = String(format: "%02lld:%02lld", Int64(totalUnits / 60), Int64(totalUnits % 60)) let totalTime = String(format: "%02lld:%02lld", Int64(totalUnits / 60), Int64(totalUnits % 60))
return "\(currentTime) / \(totalTime) \(duration < 3600 ? "min" : "h")" return "\(currentTime) / \(totalTime) \(duration < 3600 ? "m" : "h")"
} }
@MainActor @MainActor
@@ -1286,6 +1286,22 @@ private struct PlayerContent: View {
@State private var controlOffset = CGSize.zero @State private var controlOffset = CGSize.zero
@State private var dragOrigin = CGSize.zero @State private var dragOrigin = CGSize.zero
private func compactTitleLabel(progress: String?, constrained: Bool) -> some View {
HStack(spacing: 0) {
Text(model.fileName ?? "terebi")
.lineLimit(1)
.truncationMode(.tail)
.frame(minWidth: 0, maxWidth: constrained ? .infinity : nil, alignment: .leading)
.clipped()
if let progress {
Text(" · \(progress)")
.monospacedDigit()
.accessibilityLabel(model.compactTitleProgress == .percentage ? "\(progress) percent" : progress)
.fixedSize(horizontal: true, vertical: false)
}
}
}
private func toggleYouTubeInput() { private func toggleYouTubeInput() {
if showsYouTubeInput { youTubeInputFocused = false } if showsYouTubeInput { youTubeInputFocused = false }
withAnimation(reduceMotion ? nil : .easeInOut(duration: 0.22)) { withAnimation(reduceMotion ? nil : .easeInOut(duration: 0.22)) {
@@ -1659,20 +1675,12 @@ private struct PlayerContent: View {
.allowsHitTesting(false) .allowsHitTesting(false)
} }
let progress = model.isCompact || model.compactWindow.isTransitioning ? model.compactProgress : nil
ZStack(alignment: .top) { ZStack(alignment: .top) {
let progress = model.isCompact || model.compactWindow.isTransitioning ? model.compactProgress : nil ViewThatFits(in: .horizontal) {
HStack(spacing: 0) { compactTitleLabel(progress: progress, constrained: false)
Text(model.fileName ?? "terebi") .fixedSize(horizontal: true, vertical: false)
.lineLimit(1) compactTitleLabel(progress: progress, constrained: true)
.truncationMode(.middle)
.frame(minWidth: 0, maxWidth: progress == nil ? nil : .infinity, alignment: .leading)
.clipped()
if let progress {
Text(" · \(progress)")
.monospacedDigit()
.accessibilityLabel(model.compactTitleProgress == .percentage ? "\(progress) percent" : progress)
.fixedSize(horizontal: true, vertical: false)
}
} }
.font(.system(size: 11, weight: .medium)) .font(.system(size: 11, weight: .medium))
.accessibilityElement(children: .combine) .accessibilityElement(children: .combine)