From 7a6698897a367540d27060a1433644b264b2d121 Mon Sep 17 00:00:00 2001 From: Arkadiusz Fal Date: Wed, 15 Jun 2022 00:41:49 +0200 Subject: [PATCH] Minor controls improvements --- Model/Player/PlayerSponsorBlock.swift | 3 +- Model/Stream.swift | 16 +++ Shared/Player/Controls/PlayerControls.swift | 115 ++++++++++-------- .../Player/Controls/ToggleBackendButton.swift | 23 ---- Shared/Player/StreamControl.swift | 17 +-- Yattee.xcodeproj/project.pbxproj | 8 -- 6 files changed, 89 insertions(+), 93 deletions(-) delete mode 100644 Shared/Player/Controls/ToggleBackendButton.swift diff --git a/Model/Player/PlayerSponsorBlock.swift b/Model/Player/PlayerSponsorBlock.swift index d6628aca..a231a3b6 100644 --- a/Model/Player/PlayerSponsorBlock.swift +++ b/Model/Player/PlayerSponsorBlock.swift @@ -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 diff --git a/Model/Stream.swift b/Model/Stream.swift index 3ad7f9cd..0003c117 100644 --- a/Model/Stream.swift +++ b/Model/Stream.swift @@ -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 ?? "")" diff --git a/Shared/Player/Controls/PlayerControls.swift b/Shared/Player/Controls/PlayerControls.swift index 0f88cc54..207cc081 100644 --- a/Shared/Player/Controls/PlayerControls.swift +++ b/Shared/Player/Controls/PlayerControls.swift @@ -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) diff --git a/Shared/Player/Controls/ToggleBackendButton.swift b/Shared/Player/Controls/ToggleBackendButton.swift deleted file mode 100644 index ae2da73b..00000000 --- a/Shared/Player/Controls/ToggleBackendButton.swift +++ /dev/null @@ -1,23 +0,0 @@ -import SwiftUI - -struct ToggleBackendButton: View { - @EnvironmentObject private var controls - @EnvironmentObject 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() - } -} diff --git a/Shared/Player/StreamControl.swift b/Shared/Player/StreamControl.swift index f83df616..41cd7712 100644 --- a/Shared/Player/StreamControl.swift +++ b/Shared/Player/StreamControl.swift @@ -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 } diff --git a/Yattee.xcodeproj/project.pbxproj b/Yattee.xcodeproj/project.pbxproj index de4cb3e2..e50ece96 100644 --- a/Yattee.xcodeproj/project.pbxproj +++ b/Yattee.xcodeproj/project.pbxproj @@ -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 = ""; }; 370F500A27CC176F001B35DC /* BridgingHeader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BridgingHeader.h; sourceTree = ""; }; 371114EA27B94C8800C2EF7B /* RepeatingTimer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RepeatingTimer.swift; sourceTree = ""; }; - 371114EE27B951B800C2EF7B /* ToggleBackendButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToggleBackendButton.swift; sourceTree = ""; }; 3711403E26B206A6005B3555 /* SearchModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchModel.swift; sourceTree = ""; }; 37130A5A277657090033018A /* Yattee.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Yattee.xcdatamodel; sourceTree = ""; }; 37130A5E277657300033018A /* PersistenceController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PersistenceController.swift; sourceTree = ""; }; @@ -1315,7 +1311,6 @@ isa = PBXGroup; children = ( 37030FFE27B04DCC00ECDDAA /* PlayerControls.swift */, - 371114EE27B951B800C2EF7B /* ToggleBackendButton.swift */, ); path = Controls; sourceTree = ""; @@ -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 */,