ui: open YouTube URLs inline on the welcome screen
This commit is contained in:
@@ -186,7 +186,7 @@ Terebi reports facts, not watched status. A consumer such as Tubular decides com
|
|||||||
|
|
||||||
The layout follows [IINA's video-first window](https://iina.io/img/screenshot.png) and the supplied screenshots: a 32-point transparent titlebar with native traffic lights and file icon, plus a frosted 440 × 68-point floating controller. Conjure-inspired **Sunset** styling uses translucent dark-brown glass, warm cream primary text, sand secondary text, and a fixed orange accent for the volume fill, active pin, and drop target. Native slider thumbs and buffered ranges share the palette; warning symbols retain their semantic yellow. Shared vertical padding and an optical offset for symbol/slider insets balance the controller's visible top and bottom margins in both play and pause states. The controller starts centered with a four-percent bottom inset and keeps its relative position when the window changes size.
|
The layout follows [IINA's video-first window](https://iina.io/img/screenshot.png) and the supplied screenshots: a 32-point transparent titlebar with native traffic lights and file icon, plus a frosted 440 × 68-point floating controller. Conjure-inspired **Sunset** styling uses translucent dark-brown glass, warm cream primary text, sand secondary text, and a fixed orange accent for the volume fill, active pin, and drop target. Native slider thumbs and buffered ranges share the palette; warning symbols retain their semantic yellow. Shared vertical padding and an optical offset for symbol/slider insets balance the controller's visible top and bottom margins in both play and pause states. The controller starts centered with a four-percent bottom inset and keeps its relative position when the window changes size.
|
||||||
|
|
||||||
The empty player uses the same tinted HUD-glass material, faint warm outlines, 12-point rounded corners, and Sunset palette in a centered welcome card. File and YouTube opening actions share a consistently sized row with a subtle orange fill; the card fits the 400 × 240-point minimum window, and the full window still accepts media-file and YouTube-link drops.
|
The empty player uses the same tinted HUD-glass material, faint warm outlines, 12-point rounded corners, and Sunset palette in a centered welcome card. File and YouTube opening actions are separate, equally sized buttons with a 10-point gap and subtle orange fills. The YouTube button reveals and focuses an inline URL field below the buttons, spanning their combined width including the gap; Return or the arrow button submits through the existing YouTube URL validation. Other URL-opening entry points retain their dialog. The card fits the minimum window, and the full window still accepts media-file and YouTube-link drops.
|
||||||
|
|
||||||
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.
|
||||||
|
|
||||||
|
|||||||
@@ -1257,6 +1257,9 @@ private struct PlayerContent: View {
|
|||||||
@Environment(\.accessibilityReduceMotion) private var reduceMotion
|
@Environment(\.accessibilityReduceMotion) private var reduceMotion
|
||||||
@State private var showsRemainingTime = false
|
@State private var showsRemainingTime = false
|
||||||
@State private var dropTargeted = false
|
@State private var dropTargeted = false
|
||||||
|
@State private var showsYouTubeInput = false
|
||||||
|
@State private var youTubeURL = ""
|
||||||
|
@FocusState private var youTubeInputFocused: Bool
|
||||||
@State private var controlSize = CGSize(width: 440, height: 68)
|
@State private var controlSize = CGSize(width: 440, height: 68)
|
||||||
// Relative offsets preserve the dragged position across resize/fullscreen.
|
// Relative offsets preserve the dragged position across resize/fullscreen.
|
||||||
@State private var controlOffset = CGSize.zero
|
@State private var controlOffset = CGSize.zero
|
||||||
@@ -1541,26 +1544,56 @@ private struct PlayerContent: View {
|
|||||||
}
|
}
|
||||||
Spacer(minLength: 0)
|
Spacer(minLength: 0)
|
||||||
}
|
}
|
||||||
HStack(spacing: 0) {
|
HStack(spacing: 10) {
|
||||||
Button(action: model.openPanel) {
|
Button(action: model.openPanel) {
|
||||||
Label("Open File…", systemImage: "doc")
|
Label("Open File…", systemImage: "doc")
|
||||||
.frame(maxWidth: .infinity, minHeight: 40)
|
.frame(maxWidth: .infinity, minHeight: 40)
|
||||||
.contentShape(Rectangle())
|
.contentShape(Rectangle())
|
||||||
}
|
}
|
||||||
Divider().frame(height: 20).accessibilityHidden(true)
|
.background(Color(SunsetPalette.actionFill), in: RoundedRectangle(cornerRadius: 8))
|
||||||
Button(action: model.openYouTubePanel) {
|
Button {
|
||||||
|
showsYouTubeInput = true
|
||||||
|
youTubeInputFocused = true
|
||||||
|
} label: {
|
||||||
Label("YouTube URL…", systemImage: "link")
|
Label("YouTube URL…", systemImage: "link")
|
||||||
.frame(maxWidth: .infinity, minHeight: 40)
|
.frame(maxWidth: .infinity, minHeight: 40)
|
||||||
.contentShape(Rectangle())
|
.contentShape(Rectangle())
|
||||||
}
|
}
|
||||||
.accessibilityLabel("Open YouTube URL…")
|
.accessibilityLabel("Open YouTube URL…")
|
||||||
|
.background(Color(SunsetPalette.actionFill), in: RoundedRectangle(cornerRadius: 8))
|
||||||
}
|
}
|
||||||
.font(.system(size: 13, weight: .medium))
|
.font(.system(size: 13, weight: .medium))
|
||||||
.foregroundStyle(Color(SunsetPalette.text))
|
.foregroundStyle(Color(SunsetPalette.text))
|
||||||
.imageScale(.large)
|
.imageScale(.large)
|
||||||
.buttonStyle(.plain)
|
.buttonStyle(.plain)
|
||||||
.disabled(!model.canOpen)
|
.disabled(!model.canOpen)
|
||||||
|
if showsYouTubeInput {
|
||||||
|
HStack(spacing: 8) {
|
||||||
|
TextField("YouTube video URL", text: $youTubeURL)
|
||||||
|
.textFieldStyle(.plain)
|
||||||
|
.focused($youTubeInputFocused)
|
||||||
|
.accessibilityLabel("YouTube video URL")
|
||||||
|
.onAppear { youTubeInputFocused = true }
|
||||||
|
.onSubmit { model.openYouTube(youTubeURL) }
|
||||||
|
Button {
|
||||||
|
model.openYouTube(youTubeURL)
|
||||||
|
} label: {
|
||||||
|
Image(systemName: "arrow.right")
|
||||||
|
.frame(width: 24, height: 24)
|
||||||
|
.contentShape(Rectangle())
|
||||||
|
}
|
||||||
|
.buttonStyle(.plain)
|
||||||
|
.accessibilityLabel("Open YouTube Video")
|
||||||
|
.help("Open YouTube Video")
|
||||||
|
.disabled(youTubeURL.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty)
|
||||||
|
}
|
||||||
|
.font(.system(size: 13))
|
||||||
|
.foregroundStyle(Color(SunsetPalette.text))
|
||||||
|
.padding(.horizontal, 12)
|
||||||
|
.frame(height: 40)
|
||||||
.background(Color(SunsetPalette.actionFill), in: RoundedRectangle(cornerRadius: 8))
|
.background(Color(SunsetPalette.actionFill), in: RoundedRectangle(cornerRadius: 8))
|
||||||
|
.disabled(!model.canOpen)
|
||||||
|
}
|
||||||
Text("Drop a media file or YouTube link here")
|
Text("Drop a media file or YouTube link here")
|
||||||
.font(.system(size: 12))
|
.font(.system(size: 12))
|
||||||
.foregroundStyle(Color(SunsetPalette.secondaryText))
|
.foregroundStyle(Color(SunsetPalette.secondaryText))
|
||||||
|
|||||||
Reference in New Issue
Block a user