Improve open videos layouts

This commit is contained in:
Arkadiusz Fal
2022-11-11 18:50:13 +01:00
parent 6ca6a40aa1
commit 730ba1ea2e
9 changed files with 216 additions and 107 deletions

View File

@@ -10,24 +10,34 @@ struct HistoryView: View {
var body: some View {
LazyVStack {
ForEach(visibleWatches, id: \.videoID) { watch in
PlayerQueueRow(
item: PlayerQueueItem.from(watch, video: player.historyVideo(watch.videoID)),
history: true
)
.onAppear {
player.loadHistoryVideoDetails(watch.videoID)
if visibleWatches.isEmpty {
VStack(alignment: .center, spacing: 20) {
HStack {
Image(systemName: "clock")
Text("Playback history is empty")
}.foregroundColor(.secondary)
}
.contextMenu {
VideoContextMenuView(video: player.historyVideo(watch.videoID) ?? watch.video)
} else {
ForEach(visibleWatches, id: \.videoID) { watch in
PlayerQueueRow(
item: PlayerQueueItem.from(watch, video: player.historyVideo(watch.videoID)),
history: true
)
.onAppear {
player.loadHistoryVideoDetails(watch.videoID)
}
.contextMenu {
VideoContextMenuView(video: player.historyVideo(watch.videoID) ?? watch.video)
}
}
}
#if os(tvOS)
.padding(.horizontal, 40)
#else
.padding(.horizontal, 15)
#endif
}
#if os(tvOS)
.padding(.horizontal, 40)
#else
.padding(.horizontal, 15)
#endif
}
private var visibleWatches: [Watch] {

View File

@@ -24,6 +24,36 @@ struct HomeView: View {
var body: some View {
BrowserPlayerControls {
ScrollView(.vertical, showsIndicators: false) {
HStack {
#if os(tvOS)
OpenVideosButton(text: "Open Video", imageSystemName: "globe") {
NavigationModel.shared.presentingOpenVideos = true
}
.frame(maxWidth: 600)
#else
OpenVideosButton(text: "Files", imageSystemName: "folder") {
NavigationModel.shared.presentingFileImporter = true
}
OpenVideosButton(text: "Paste", imageSystemName: "doc.on.clipboard.fill") {
OpenVideosModel.shared.openURLsFromClipboard(playbackMode: .playNow)
}
OpenVideosButton(imageSystemName: "ellipsis") {
NavigationModel.shared.presentingOpenVideos = true
}
.frame(maxWidth: 40)
#endif
}
#if os(iOS)
.padding(.top, RefreshControl.navigationBarTitleDisplayMode == .inline ? 15 : 0)
#else
.padding(.top, 15)
#endif
#if os(tvOS)
.padding(.horizontal, 40)
#else
.padding(.horizontal, 15)
#endif
if !accounts.current.isNil {
#if os(tvOS)
ForEach(Defaults[.favorites]) { item in
@@ -60,18 +90,7 @@ struct HomeView: View {
HistoryView(limit: homeHistoryItems)
}
#if os(tvOS)
HStack {
Button {
navigation.presentingOpenVideos = true
} label: {
Label("Open Videos...", systemImage: "folder")
.padding(.horizontal, 20)
.padding(.vertical, 10)
}
.buttonStyle(.plain)
}
#else
#if !os(tvOS)
Color.clear.padding(.bottom, 60)
#endif
}

View File

@@ -120,3 +120,10 @@ struct AppSidebarNavigation: View {
#endif
}
}
struct AppSidebarNavigation_Preview: PreviewProvider {
static var previews: some View {
AppSidebarNavigation()
.injectFixtureEnvironmentObjects()
}
}

View File

@@ -85,6 +85,32 @@ struct ContentView: View {
}
)
#if !os(tvOS)
.fileImporter(
isPresented: $navigation.presentingFileImporter,
allowedContentTypes: [.audiovisualContent],
allowsMultipleSelection: true
) { result in
do {
let selectedFiles = try result.get()
let urlsToOpen = selectedFiles.map { url in
if let bookmarkURL = URLBookmarkModel.shared.loadBookmark(url) {
return bookmarkURL
}
if url.startAccessingSecurityScopedResource() {
URLBookmarkModel.shared.saveBookmark(url)
}
return url
}
OpenVideosModel.shared.openURLs(urlsToOpen)
} catch {
NavigationModel.shared.presentAlert(title: "Could not open Files")
}
NavigationModel.shared.presentingOpenVideos = false
}
.onOpenURL {
OpenURLHandler(
accounts: accounts,

View File

@@ -0,0 +1,39 @@
import SwiftUI
struct OpenVideosButton: View {
var text: String?
var imageSystemName: String?
var action: () -> Void = {}
var body: some View {
Button(action: action) {
HStack {
if let imageSystemName {
Image(systemName: imageSystemName)
}
if let text {
Text(text ?? "")
.fontWeight(.bold)
}
}
.padding(.vertical, 10)
.frame(minHeight: 45)
.frame(maxWidth: .infinity)
.contentShape(Rectangle())
}
.foregroundColor(.accentColor)
.buttonStyle(.plain)
.background(buttonBackground)
}
var buttonBackground: some View {
RoundedRectangle(cornerRadius: 4)
.foregroundColor(Color.accentColor.opacity(0.33))
}
}
struct OpenVideosButton_Previews: PreviewProvider {
static var previews: some View {
OpenVideosButton(text: "Open Videos", imageSystemName: "play.circle.fill")
}
}

View File

@@ -18,7 +18,7 @@ struct OpenVideosView: View {
var body: some View {
#if os(macOS)
openVideos
.frame(minWidth: 600, maxWidth: 800, minHeight: 250)
.frame(minWidth: 600, maxWidth: 800, minHeight: 350, maxHeight: 500)
#else
NavigationView {
openVideos
@@ -44,48 +44,45 @@ struct OpenVideosView: View {
VStack(alignment: .leading) {
ZStack(alignment: .topLeading) {
#if os(tvOS)
TextField("URLs to Open", text: $urlsToOpenText)
TextField("URL to Open", text: $urlsToOpenText)
#else
TextEditor(text: $urlsToOpenText)
.padding(2)
.border(Color(white: 0.8), width: 1)
.frame(minHeight: 100, maxHeight: 200)
.frame(minHeight: 100, maxHeight: 250)
#if !os(macOS)
.keyboardType(.URL)
#endif
#endif
}
Text("Enter or paste URLs to open, one per line")
.font(.caption2)
.foregroundColor(.secondary)
Menu {
Picker("Playback Mode", selection: $playbackMode) {
ForEach(OpenVideosModel.PlaybackMode.allCases, id: \.rawValue) { mode in
Text(mode.description).tag(mode)
}
}
} label: {
Text(playbackMode.description)
Group {
#if os(tvOS)
Text("Enter link to open")
#else
Text("Enter links to open, one per line")
#endif
}
.transaction { t in t.disablesAnimations = true }
.labelsHidden()
.padding(.bottom, 5)
.frame(maxWidth: .infinity, alignment: .center)
.font(.caption2)
.foregroundColor(.secondary)
playbackModeControl
Toggle(isOn: $removeQueueItems) {
Text("Clear queue before opening")
Text("Clear Queue before opening")
}
.disabled(!playbackMode.allowsRemovingQueueItems)
.padding(.bottom)
HStack {
Group {
#if os(tvOS)
Spacer()
#endif
openURLsButton
Spacer()
#if !os(tvOS)
Spacer()
openFromClipboardButton
#endif
@@ -100,6 +97,7 @@ struct OpenVideosView: View {
Spacer()
}
.padding()
.alert(isPresented: $navigation.presentingAlertInOpenVideos) { navigation.alert }
#if !os(tvOS)
.fileImporter(
isPresented: $presentingFileImporter,
@@ -122,7 +120,8 @@ struct OpenVideosView: View {
openURLs(selectedFiles)
} catch {
NavigationModel.shared.presentAlert(title: "Could not open Files")
NavigationModel.shared.alert = Alert(title: Text("Could not open Files"))
NavigationModel.shared.presentingAlertInOpenVideos = true
}
presentationMode.wrappedValue.dismiss()
@@ -130,77 +129,64 @@ struct OpenVideosView: View {
#endif
}
var openURLsButton: some View {
Button {
openURLs(urlsToOpenFromText)
} label: {
HStack {
Image(systemName: "network")
Text("Open")
.fontWeight(.bold)
.padding(.vertical, 10)
}
.frame(maxWidth: .infinity)
.contentShape(Rectangle())
.padding(.horizontal, 20)
var playbackModeControl: some View {
HStack {
#if !os(tvOS)
Text("Playback Mode")
Spacer()
#endif
#if os(iOS)
Menu {
playbackModePicker
} label: {
Text(playbackMode.description)
}
#else
playbackModePicker
#if !os(tvOS)
.frame(maxWidth: 200)
#endif
#endif
}
.transaction { t in t.animation = .none }
.padding(.bottom, 5)
.frame(maxWidth: .infinity, alignment: .center)
}
var playbackModePicker: some View {
Picker("Playback Mode", selection: $playbackMode) {
ForEach(OpenVideosModel.PlaybackMode.allCases, id: \.rawValue) { mode in
Text(mode.description).tag(mode)
}
}
.labelsHidden()
}
var openURLsButton: some View {
OpenVideosButton(text: "Open", imageSystemName: "network") {
openURLs(urlsToOpenFromText)
}
.foregroundColor(.accentColor)
.buttonStyle(.plain)
.background(buttonBackground)
.disabled(urlsToOpenFromText.isEmpty)
#if !os(tvOS)
#if os(tvOS)
.frame(maxWidth: 600)
#else
.keyboardShortcut(.defaultAction)
#endif
}
var openFromClipboardButton: some View {
Button {
OpenVideosButton(text: "Paste", imageSystemName: "doc.on.clipboard.fill") {
OpenVideosModel.shared.openURLsFromClipboard(
removeQueueItems: removeQueueItems,
playbackMode: playbackMode
)
} label: {
HStack {
Image(systemName: "doc.on.clipboard.fill")
Text("Paste")
.fontWeight(.bold)
.padding(.vertical, 10)
}
.frame(maxWidth: .infinity)
.contentShape(Rectangle())
.padding(.horizontal, 20)
}
.foregroundColor(.accentColor)
.buttonStyle(.plain)
.background(buttonBackground)
#if !os(tvOS)
.keyboardShortcut(.defaultAction)
#endif
}
var openFilesButton: some View {
Button {
OpenVideosButton(text: "Open Files", imageSystemName: "folder") {
presentingFileImporter = true
} label: {
HStack {
Image(systemName: "folder")
Text("Open Files")
.fontWeight(.bold)
.padding(.vertical, 10)
}
.frame(maxWidth: .infinity)
.contentShape(Rectangle())
.padding(.horizontal, 20)
}
.foregroundColor(.accentColor)
.buttonStyle(.plain)
.background(buttonBackground)
}
var buttonBackground: some View {
RoundedRectangle(cornerRadius: 4)
.foregroundColor(Color.accentColor.opacity(0.33))
}
var urlsToOpenFromText: [URL] {
@@ -217,6 +203,7 @@ struct OpenVideosView: View {
struct OpenVideosView_Previews: PreviewProvider {
static var previews: some View {
OpenVideosView()
.injectFixtureEnvironmentObjects()
#if os(iOS)
.navigationViewStyle(.stack)
#endif