Minor UI changes

This commit is contained in:
Arkadiusz Fal
2022-06-25 01:39:29 +02:00
parent 7b09805b81
commit c940fb3198
20 changed files with 247 additions and 436 deletions

View File

@@ -8,6 +8,7 @@ struct BrowserPlayerControls<Content: View, Toolbar: View>: View {
}
let content: Content
let toolbar: Toolbar?
init(
context _: Context? = nil,
@@ -15,7 +16,7 @@ struct BrowserPlayerControls<Content: View, Toolbar: View>: View {
@ViewBuilder content: @escaping () -> Content
) {
self.content = content()
toolbar()
self.toolbar = toolbar()
}
init(
@@ -26,195 +27,29 @@ struct BrowserPlayerControls<Content: View, Toolbar: View>: View {
}
var body: some View {
if #available(iOS 15.0, macOS 12.0, *) {
_ = Self._printChanges()
}
// TODO: remove
#if DEBUG
if #available(iOS 15.0, macOS 12.0, *) {
Self._printChanges()
}
#endif
return VStack(spacing: 0) {
return ZStack(alignment: .bottomLeading) {
content
#if !os(tvOS)
ControlsBar()
.edgesIgnoringSafeArea(.bottom)
VStack(spacing: 0) {
toolbar
.borderTop(height: 0.4, color: Color("ControlsBorderColor"))
.modifier(ControlBackgroundModifier())
ControlsBar()
.edgesIgnoringSafeArea(.bottom)
}
#endif
}
}
}
// struct BrowserPlayerControls<Content: View, Toolbar: View>: View {
// enum Context {
// case browser, player
// }
//
// let context: Context
// let content: Content
// let toolbar: Toolbar?
//
// @Environment(\.navigationStyle) private var navigationStyle
// @EnvironmentObject<PlayerControlsModel> private var playerControls
// @EnvironmentObject<PlayerModel> private var model
//
// var barHeight: Double {
// 75
// }
//
// init(
// context: Context? = nil,
// @ViewBuilder toolbar: @escaping () -> Toolbar? = { nil },
// @ViewBuilder content: @escaping () -> Content
// ) {
// self.context = context ?? .browser
// self.content = content()
// self.toolbar = toolbar()
// }
//
// init(
// context: Context? = nil,
// @ViewBuilder content: @escaping () -> Content
// ) where Toolbar == EmptyView {
// self.init(context: context, toolbar: { EmptyView() }, content: content)
// }
//
// var body: some View {
// ZStack(alignment: .bottomLeading) {
// VStack(spacing: 0) {
// content
//
// Color.clear.frame(height: barHeight)
// }
// #if !os(tvOS)
// .frame(minHeight: 0, maxHeight: .infinity)
// #endif
//
//
// VStack {
// #if !os(tvOS)
// #if !os(macOS)
// toolbar
// .frame(height: 100)
// .offset(x: 0, y: -28)
// #endif
//
// if context != .player || !playerControls.playingFullscreen {
// controls
// }
// #endif
// }
// .borderTop(height: 0.4, color: Color("ControlsBorderColor"))
// #if os(macOS)
// .background(VisualEffectBlur(material: .sidebar))
// #elseif os(iOS)
// .background(VisualEffectBlur(blurStyle: .systemThinMaterial).edgesIgnoringSafeArea(.all))
// #endif
// }
// .background(Color.debug)
// }
//
// private var controls: some View {
// VStack(spacing: 0) {
// TimelineView(duration: playerControls.durationBinding, current: playerControls.currentTimeBinding)
// .foregroundColor(.secondary)
//
// Button(action: {
// model.togglePlayer()
// }) {
// HStack(spacing: 8) {
// authorAvatar
//
// VStack(alignment: .leading, spacing: 5) {
// Text(model.currentVideo?.title ?? "Not playing")
// .font(.headline)
// .foregroundColor(model.currentVideo.isNil ? .secondary : .accentColor)
// .lineLimit(1)
//
// Text(model.currentVideo?.author ?? "")
// .font(.subheadline)
// .foregroundColor(.secondary)
// .lineLimit(1)
// }
//
// Spacer()
//
// HStack {
// Group {
// if !model.currentItem.isNil {
// Button {
// model.closeCurrentItem()
// model.closePiP()
// } label: {
// Label("Close Video", systemImage: "xmark")
// .padding(.horizontal, 4)
// .contentShape(Rectangle())
// }
// }
//
// if playerControls.isPlaying {
// Button(action: {
// model.pause()
// }) {
// Label("Pause", systemImage: "pause.fill")
// .padding(.horizontal, 4)
// .contentShape(Rectangle())
// }
// } else {
// Button(action: {
// model.play()
// }) {
// Label("Play", systemImage: "play.fill")
// .padding(.horizontal, 4)
// .contentShape(Rectangle())
// }
// }
// }
// .disabled(playerControls.isLoadingVideo || model.currentItem.isNil)
// .font(.system(size: 30))
// .frame(minWidth: 30)
//
// Button(action: { model.advanceToNextItem() }) {
// Label("Next", systemImage: "forward.fill")
// .padding(.vertical)
// .contentShape(Rectangle())
// }
// .disabled(model.queue.isEmpty)
// }
// }
// .buttonStyle(.plain)
// .contentShape(Rectangle())
// }
// }
// .buttonStyle(.plain)
// .labelStyle(.iconOnly)
// .padding(.horizontal)
// .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: barHeight)
// .borderTop(height: 0.4, color: Color("ControlsBorderColor"))
// .borderBottom(height: navigationStyle == .sidebar ? 0 : 0.4, color: Color("ControlsBorderColor"))
// }
//
// private var authorAvatar: some View {
// Group {
// if let video = model.currentItem?.video, let url = video.channel.thumbnailURL {
// WebImage(url: url)
// .resizable()
// .placeholder {
// Rectangle().fill(Color("PlaceholderColor"))
// }
// .retryOnAppear(true)
// .indicator(.activity)
// .clipShape(Circle())
// .frame(width: 44, height: 44, alignment: .leading)
// }
// }
// }
//
// private var progressViewValue: Double {
// [model.time?.seconds, model.videoDuration].compactMap { $0 }.min() ?? 0
// }
//
// private var progressViewTotal: Double {
// model.videoDuration ?? 100
// }
// }
//
struct PlayerControlsView_Previews: PreviewProvider {
static var previews: some View {
BrowserPlayerControls(context: .player) {

View File

@@ -1,13 +1,8 @@
import Defaults
import SDWebImageSwiftUI
import SwiftUI
import SwiftUIPager
struct ControlsBar: View {
enum Pages: CaseIterable {
case details, controls
}
@EnvironmentObject<AccountsModel> private var accounts
@EnvironmentObject<NavigationModel> private var navigation
@EnvironmentObject<PlayerControlsModel> private var playerControls
@@ -19,27 +14,28 @@ struct ControlsBar: View {
@State private var presentingShareSheet = false
@State private var shareURL: URL?
@StateObject private var controlsPage = Page.first()
var presentingControls = true
var backgroundEnabled = true
var borderTop = true
var borderBottom = true
var detailsTogglePlayer = true
var body: some View {
VStack(spacing: 0) {
Pager(page: controlsPage, data: Pages.allCases, id: \.self) { index in
switch index {
case .details:
details
default:
controls
}
HStack(spacing: 0) {
detailsButton
if presentingControls {
controls
.frame(maxWidth: 120)
}
.pagingPriority(.simultaneous)
}
.buttonStyle(.plain)
.labelStyle(.iconOnly)
.padding(.horizontal)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: barHeight)
.borderTop(height: 0.4, color: Color("ControlsBorderColor"))
.borderBottom(height: 0.4, color: Color("ControlsBorderColor"))
.modifier(ControlBackgroundModifier(edgesIgnoringSafeArea: .bottom))
.borderTop(height: borderTop ? 0.4 : 0, color: Color("ControlsBorderColor"))
.borderBottom(height: borderBottom ? 0.4 : 0, color: Color("ControlsBorderColor"))
.modifier(ControlBackgroundModifier(enabled: backgroundEnabled, edgesIgnoringSafeArea: .bottom))
#if os(iOS)
.background(
EmptyView().sheet(isPresented: $presentingShareSheet) {
@@ -51,6 +47,19 @@ struct ControlsBar: View {
#endif
}
@ViewBuilder var detailsButton: some View {
if detailsTogglePlayer {
Button {
model.togglePlayer()
} label: {
details
.contentShape(Rectangle())
}
} else {
details
}
}
var controls: some View {
HStack(spacing: 4) {
Group {
@@ -59,32 +68,18 @@ struct ControlsBar: View {
model.closePiP()
} label: {
Label("Close Video", systemImage: "xmark")
.padding(.horizontal, 4)
.padding(.vertical, 10)
.frame(maxWidth: .infinity)
.contentShape(Rectangle())
}
Spacer()
Button(action: { model.backend.seek(to: 0) }) {
Label("Restart", systemImage: "backward.end.fill")
.contentShape(Rectangle())
}
Spacer()
Button {
model.backend.seek(relative: .secondsInDefaultTimescale(-10))
} label: {
Label("Backward", systemImage: "gobackward.10")
}
Spacer()
if playerControls.isPlaying {
Button(action: {
model.pause()
}) {
Label("Pause", systemImage: "pause.fill")
.padding(.horizontal, 4)
.padding(.vertical, 10)
.frame(maxWidth: .infinity)
.contentShape(Rectangle())
}
} else {
@@ -92,38 +87,27 @@ struct ControlsBar: View {
model.play()
}) {
Label("Play", systemImage: "play.fill")
.padding(.horizontal, 4)
.padding(.vertical, 10)
.frame(maxWidth: .infinity)
.contentShape(Rectangle())
}
}
Spacer()
Button {
model.backend.seek(relative: .secondsInDefaultTimescale(10))
} label: {
Label("Forward", systemImage: "goforward.10")
}
Spacer()
}
.disabled(playerControls.isLoadingVideo || model.currentItem.isNil)
Button(action: { model.advanceToNextItem() }) {
Label("Next", systemImage: "forward.fill")
.padding(.vertical, 10)
.frame(maxWidth: .infinity)
.contentShape(Rectangle())
}
.disabled(model.queue.isEmpty)
Spacer()
}
.padding(.vertical)
.font(.system(size: 24))
.frame(maxWidth: .infinity)
}
var barHeight: Double {
75
55
}
var details: some View {
@@ -147,8 +131,6 @@ struct ControlsBar: View {
if let video = model.currentVideo {
Group {
Section {
Text(video.title)
if accounts.app.supportsUserPlaylists && accounts.signedIn {
Section {
Button {
@@ -165,14 +147,14 @@ struct ControlsBar: View {
}
}
}
ShareButton(
contentItem: .init(video: model.currentVideo),
presentingShareSheet: $presentingShareSheet,
shareURL: $shareURL
)
}
ShareButton(
contentItem: .init(video: model.currentVideo),
presentingShareSheet: $presentingShareSheet,
shareURL: $shareURL
)
Section {
Button {
NavigationModel.openChannel(
@@ -208,6 +190,12 @@ struct ControlsBar: View {
}
}
}
Button {
model.closeCurrentItem()
} label: {
Label("Close Video", systemImage: "xmark")
}
}
.labelStyle(.automatic)
}
@@ -234,9 +222,7 @@ struct ControlsBar: View {
}
private var authorAvatar: some View {
Button {
model.togglePlayer()
} label: {
Group {
if let video = model.currentItem?.video, let url = video.channel.thumbnailURL {
WebImage(url: url)
.resizable()
@@ -246,9 +232,15 @@ struct ControlsBar: View {
.retryOnAppear(true)
.indicator(.activity)
} else {
Image(systemName: "play.rectangle")
.foregroundColor(.accentColor)
.font(.system(size: 30))
ZStack {
Color(white: 0.8)
.opacity(0.5)
Image(systemName: "play.rectangle")
.foregroundColor(.accentColor)
.font(.system(size: 20))
.contentShape(Rectangle())
}
}
}
.frame(width: 44, height: 44, alignment: .leading)