Minor controls improvements

This commit is contained in:
Arkadiusz Fal 2022-06-15 00:41:49 +02:00
parent cb89c4d53d
commit 7a6698897a
6 changed files with 89 additions and 93 deletions

View File

@ -1,5 +1,5 @@
import CoreMedia
import AVFAudio
import CoreMedia
import Defaults
import Foundation
@ -34,7 +34,6 @@ extension PlayerModel {
if let duration = playerItemDuration, segment.endTime.seconds >= duration.seconds - 3 {
logger.error("segment end time is: \(segment.end) when player item duration is: \(duration.seconds)")
DispatchQueue.main.async { [weak self] in
guard let self = self else {
return

View File

@ -164,6 +164,22 @@ class Stream: Equatable, Hashable, Identifiable {
return kind == .hls ? "adaptive (HLS)" : "\(resolution.name)\(kind == .stream ? " (\(kind.rawValue))" : "")"
}
var shortQuality: String {
if resolution == .hd4320p60 || resolution == .hd4320p {
return "8K"
} else if resolution == .hd2160p60 ||
resolution == .hd2160p50 ||
resolution == .hd2160p48 ||
resolution == .hd2160p
{
return "4K"
} else if kind == .hls {
return "HLS"
} else {
return resolution.name
}
}
var description: String {
let formatString = format == .unknown ? "" : " (\(format.rawValue))"
return "\(quality)\(formatString) - \(instance?.description ?? "")"

View File

@ -30,26 +30,17 @@ struct PlayerControls: View {
var body: some View {
VStack {
ZStack(alignment: .bottom) {
VStack(spacing: 0) {
Group {
HStack {
statusBar
.lineLimit(1)
.padding(3)
#if os(macOS)
.background(VisualEffectBlur(material: .hudWindow))
#elseif os(iOS)
.background(VisualEffectBlur(blurStyle: .systemThinMaterial))
#endif
.mask(RoundedRectangle(cornerRadius: 3))
Spacer()
}
VStack(alignment: .trailing, spacing: 4) {
#if !os(tvOS)
buttonsBar
.padding(.top, 4)
.padding(.horizontal, 4)
}
HStack(spacing: 4) {
qualityButton
backendButton
}
#else
Text(player.stream?.description ?? "")
#endif
Spacer()
@ -77,6 +68,8 @@ struct PlayerControls: View {
.padding(.horizontal, 16)
}
}
.padding(.top, 4)
.padding(.horizontal, 4)
.opacity(model.presentingControls ? 1 : 0)
}
#if os(tvOS)
@ -128,29 +121,6 @@ struct PlayerControls: View {
)
}
var statusBar: some View {
HStack(spacing: 4) {
Text(playbackStatus)
Text("")
#if !os(tvOS)
ToggleBackendButton()
Text("")
StreamControl()
#if os(macOS)
.frame(maxWidth: 300)
#endif
#else
Text(player.stream?.description ?? "")
#endif
}
.foregroundColor(.primary)
.padding(.trailing, 4)
.font(.system(size: 14))
}
private var hidePlayerButton: some View {
button("Hide", systemImage: "chevron.down") {
player.hide()
@ -256,6 +226,45 @@ struct PlayerControls: View {
#endif
}
@ViewBuilder private var qualityButton: some View {
#if os(macOS)
StreamControl()
.labelsHidden()
.frame(maxWidth: 300)
#elseif os(iOS)
Menu {
StreamControl()
.frame(width: 45, height: 30)
#if os(iOS)
.background(VisualEffectBlur(blurStyle: .systemThinMaterial))
#endif
.mask(RoundedRectangle(cornerRadius: 3))
} label: {
Text(player.streamSelection?.shortQuality ?? "loading")
.frame(width: 140, height: 30)
.foregroundColor(.primary)
}
.buttonStyle(.plain)
.foregroundColor(.primary)
.frame(width: 140, height: 30)
#if os(macOS)
.background(VisualEffectBlur(material: .hudWindow))
#elseif os(iOS)
.background(VisualEffectBlur(blurStyle: .systemThinMaterial))
#endif
.mask(RoundedRectangle(cornerRadius: 3))
#endif
}
@ViewBuilder private var backendButton: some View {
button(player.activeBackend.label, width: 100) {
player.saveTime {
player.changeActiveBackend(from: player.activeBackend, to: player.activeBackend.next())
model.resetTimer()
}
}
}
private var closeVideoButton: some View {
button("Close", systemImage: "xmark") {
player.pause()
@ -351,7 +360,6 @@ struct PlayerControls: View {
#endif
}
.font(.system(size: 20))
.padding(.horizontal, 4)
}
private var restartVideoButton: some View {
@ -380,8 +388,10 @@ struct PlayerControls: View {
func button(
_ label: String,
systemImage: String = "arrow.up.left.and.arrow.down.right",
systemImage: String? = nil,
size: Double = 30,
width: Double? = nil,
height: Double? = nil,
cornerRadius: Double = 3,
active: Bool = false,
action: @escaping () -> Void = {}
@ -390,14 +400,21 @@ struct PlayerControls: View {
action()
model.resetTimer()
} label: {
Label(label, systemImage: systemImage)
.labelStyle(.iconOnly)
.padding()
.contentShape(Rectangle())
Group {
if let image = systemImage {
Label(label, systemImage: image)
.labelStyle(.iconOnly)
} else {
Label(label, systemImage: "")
.labelStyle(.titleOnly)
}
}
.padding()
.contentShape(Rectangle())
}
.buttonStyle(.plain)
.foregroundColor(active ? .accentColor : .primary)
.frame(width: size, height: size)
.frame(width: width ?? size, height: height ?? size)
#if os(macOS)
.background(VisualEffectBlur(material: .hudWindow))
#elseif os(iOS)

View File

@ -1,23 +0,0 @@
import SwiftUI
struct ToggleBackendButton: View {
@EnvironmentObject<PlayerControlsModel> private var controls
@EnvironmentObject<PlayerModel> private var player
var body: some View {
Button {
player.saveTime {
player.changeActiveBackend(from: player.activeBackend, to: player.activeBackend.next())
controls.resetTimer()
}
} label: {
Text(player.activeBackend.label)
}
}
}
struct ToggleBackendButton_Previews: PreviewProvider {
static var previews: some View {
ToggleBackendButton()
}
}

View File

@ -29,27 +29,22 @@ struct StreamControl: View {
.disabled(player.isLoadingAvailableStreams)
#else
Menu {
Picker("", selection: $player.streamSelection) {
ForEach(InstancesModel.all) { instance in
let instanceStreams = availableStreamsForInstance(instance)
if !instanceStreams.values.isEmpty {
let kinds = Array(instanceStreams.keys).sorted { $0 < $1 }
Picker("", selection: $player.streamSelection) {
ForEach(kinds, id: \.self) { key in
ForEach(instanceStreams[key] ?? []) { stream in
Text(stream.description).tag(Stream?.some(stream))
}
if kinds.count > 1 {
Divider()
}
ForEach(kinds, id: \.self) { key in
ForEach(instanceStreams[key] ?? []) { stream in
Text(stream.description).tag(Stream?.some(stream))
}
}
}
}
} label: {
Text(player.streamSelection?.quality ?? "no playable streams")
}
.frame(minWidth: 110)
.fixedSize(horizontal: true, vertical: true)
.disabled(player.isLoadingAvailableStreams)
#endif
}

View File

@ -136,8 +136,6 @@
371114EB27B94C8800C2EF7B /* RepeatingTimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 371114EA27B94C8800C2EF7B /* RepeatingTimer.swift */; };
371114EC27B94C8800C2EF7B /* RepeatingTimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 371114EA27B94C8800C2EF7B /* RepeatingTimer.swift */; };
371114ED27B94C8800C2EF7B /* RepeatingTimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 371114EA27B94C8800C2EF7B /* RepeatingTimer.swift */; };
371114EF27B951B800C2EF7B /* ToggleBackendButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 371114EE27B951B800C2EF7B /* ToggleBackendButton.swift */; };
371114F027B951B800C2EF7B /* ToggleBackendButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 371114EE27B951B800C2EF7B /* ToggleBackendButton.swift */; };
3711403F26B206A6005B3555 /* SearchModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3711403E26B206A6005B3555 /* SearchModel.swift */; };
3711404026B206A6005B3555 /* SearchModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3711403E26B206A6005B3555 /* SearchModel.swift */; };
3711404126B206A6005B3555 /* SearchModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3711403E26B206A6005B3555 /* SearchModel.swift */; };
@ -349,7 +347,6 @@
376CD21626FBE18D001E1AC1 /* Instance+Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 376CD21526FBE18D001E1AC1 /* Instance+Fixtures.swift */; };
376CD21726FBE18D001E1AC1 /* Instance+Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 376CD21526FBE18D001E1AC1 /* Instance+Fixtures.swift */; };
376CD21826FBE18D001E1AC1 /* Instance+Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 376CD21526FBE18D001E1AC1 /* Instance+Fixtures.swift */; };
3772000F27E8EC8800CB2475 /* ToggleBackendButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 371114EE27B951B800C2EF7B /* ToggleBackendButton.swift */; };
3772002727E8EDF000CB2475 /* libmpv.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3772001327E8ED1600CB2475 /* libmpv.a */; };
3772002827E8EDF000CB2475 /* libswscale.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3772001A27E8ED1700CB2475 /* libswscale.a */; };
3772002927E8EDF000CB2475 /* libavutil.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3772001627E8ED1700CB2475 /* libavutil.a */; };
@ -847,7 +844,6 @@
370F4FC827CC16CB001B35DC /* libbrotlicommon.1.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libbrotlicommon.1.dylib; sourceTree = "<group>"; };
370F500A27CC176F001B35DC /* BridgingHeader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BridgingHeader.h; sourceTree = "<group>"; };
371114EA27B94C8800C2EF7B /* RepeatingTimer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RepeatingTimer.swift; sourceTree = "<group>"; };
371114EE27B951B800C2EF7B /* ToggleBackendButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToggleBackendButton.swift; sourceTree = "<group>"; };
3711403E26B206A6005B3555 /* SearchModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchModel.swift; sourceTree = "<group>"; };
37130A5A277657090033018A /* Yattee.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Yattee.xcdatamodel; sourceTree = "<group>"; };
37130A5E277657300033018A /* PersistenceController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PersistenceController.swift; sourceTree = "<group>"; };
@ -1315,7 +1311,6 @@
isa = PBXGroup;
children = (
37030FFE27B04DCC00ECDDAA /* PlayerControls.swift */,
371114EE27B951B800C2EF7B /* ToggleBackendButton.swift */,
);
path = Controls;
sourceTree = "<group>";
@ -2620,7 +2615,6 @@
37732FF42703D32400F04329 /* Sidebar.swift in Sources */,
37D4B19726717E1500C925CA /* Video.swift in Sources */,
37484C2926FC83FF00287258 /* AccountForm.swift in Sources */,
371114EF27B951B800C2EF7B /* ToggleBackendButton.swift in Sources */,
37E70927271CDDAE00D34DDE /* OpenSettingsButton.swift in Sources */,
371F2F1A269B43D300E4A7AB /* NavigationModel.swift in Sources */,
37EBD8C627AF26B300F1C24B /* AVPlayerBackend.swift in Sources */,
@ -2742,7 +2736,6 @@
37B795912771DAE0001CF27B /* OpenURLHandler.swift in Sources */,
37DD87C8271C9CFE0027CBF9 /* PlayerStreams.swift in Sources */,
376578922685490700D4EA09 /* PlaylistsView.swift in Sources */,
371114F027B951B800C2EF7B /* ToggleBackendButton.swift in Sources */,
37F9619C27BD89E000058149 /* TapRecognizerViewModifier.swift in Sources */,
37484C2626FC83E000287258 /* InstanceForm.swift in Sources */,
37D526E42720B4BE00ED2F5E /* View+SwipeGesture.swift in Sources */,
@ -3035,7 +3028,6 @@
37BC50AE2778BCBA00510953 /* HistoryModel.swift in Sources */,
37D526E02720AC4400ED2F5E /* VideosAPI.swift in Sources */,
37599F36272B44000087F250 /* FavoritesModel.swift in Sources */,
3772000F27E8EC8800CB2475 /* ToggleBackendButton.swift in Sources */,
3705B184267B4E4900704544 /* TrendingCategory.swift in Sources */,
37E084AD2753D95F00039B7D /* AccountsNavigationLink.swift in Sources */,
371B7E6C2759791900D21217 /* CommentsModel.swift in Sources */,