Improve sharing, add YouTube links

This commit is contained in:
Arkadiusz Fal 2021-11-02 20:40:49 +01:00
parent 0091af683f
commit f49453e871
8 changed files with 114 additions and 55 deletions

View File

@ -1,3 +1,4 @@
import AVFoundation
import Foundation
import Siesta
@ -28,7 +29,7 @@ protocol VideosAPI {
func channelPlaylist(_ id: String) -> Resource?
func loadDetails(_ item: PlayerQueueItem, completionHandler: @escaping (PlayerQueueItem) -> Void)
func shareURL(_ item: ContentItem) -> URL?
func shareURL(_ item: ContentItem, frontendHost: String?, time: CMTime?) -> URL?
}
extension VideosAPI {
@ -50,23 +51,33 @@ extension VideosAPI {
}
}
func shareURL(_ item: ContentItem) -> URL? {
guard let frontendHost = account.instance.frontendHost else {
func shareURL(_ item: ContentItem, frontendHost: String? = nil, time: CMTime? = nil) -> URL? {
guard let frontendHost = frontendHost ?? account.instance.frontendHost else {
return nil
}
var urlComponents = account.instance.urlComponents
urlComponents.host = frontendHost
var queryItems = [URLQueryItem]()
switch item.contentType {
case .video:
urlComponents.path = "/watch"
urlComponents.query = "v=\(item.video.videoID)"
queryItems.append(.init(name: "v", value: item.video.videoID))
case .channel:
urlComponents.path = "/channel/\(item.channel.id)"
case .playlist:
urlComponents.path = "/playlist"
urlComponents.query = "list=\(item.playlist.id)"
queryItems.append(.init(name: "list", value: item.playlist.id))
}
if !time.isNil, time!.seconds.isFinite {
queryItems.append(.init(name: "t", value: "\(Int(time!.seconds))s"))
}
if !queryItems.isEmpty {
urlComponents.queryItems = queryItems
}
return urlComponents.url!

View File

@ -381,7 +381,10 @@ final class PlayerModel: ObservableObject {
return
}
self.updateNowPlayingInfo()
#if !os(tvOS)
self.updateNowPlayingInfo()
#endif
self.handleSegments(at: self.player.currentTime())
}
}

View File

@ -85,7 +85,7 @@ struct FavoriteItemView: View {
var label: String {
if case let .playlist(id) = item.section {
return playlistsModel.find(id: id)?.title ?? "Unknown Playlist"
return playlistsModel.find(id: id)?.title ?? "Playlist"
}
return item.section.label

View File

@ -13,6 +13,7 @@ struct VideoDetails: View {
@State private var confirmationShown = false
@State private var presentingAddToPlaylist = false
@State private var presentingShareSheet = false
@State private var shareURL = ""
@State private var currentPage = Page.details
@ -254,7 +255,8 @@ struct VideoDetails: View {
HStack {
ShareButton(
contentItem: ContentItem(video: video),
presentingShareSheet: $presentingShareSheet
presentingShareSheet: $presentingShareSheet,
shareURL: $shareURL
)
Spacer()
@ -286,7 +288,6 @@ struct VideoDetails: View {
.help("Add to Playlist...")
}
.buttonStyle(.plain)
.foregroundColor(.blue)
}
}
.frame(maxHeight: 35)
@ -300,9 +301,7 @@ struct VideoDetails: View {
}
#if os(iOS)
.sheet(isPresented: $presentingShareSheet) {
if let url = accounts.api.shareURL(contentItem) {
ShareSheet(activityItems: [url])
}
ShareSheet(activityItems: [shareURL])
}
#endif
}

View File

@ -66,7 +66,7 @@ struct ChannelPlaylistView: View {
}
#if !os(tvOS)
.toolbar {
ToolbarItem(placement: shareButtonPlacement) {
ToolbarItem(placement: .navigation) {
ShareButton(
contentItem: contentItem,
presentingShareSheet: $presentingShareSheet
@ -84,14 +84,6 @@ struct ChannelPlaylistView: View {
#endif
}
private var shareButtonPlacement: ToolbarItemPlacement {
#if os(iOS)
.navigation
#else
.automatic
#endif
}
private var contentItem: ContentItem {
ContentItem(playlist: playlist)
}

View File

@ -76,7 +76,7 @@ struct ChannelVideosView: View {
#endif
#if !os(tvOS)
.toolbar {
ToolbarItem(placement: shareButtonPlacement) {
ToolbarItem(placement: .navigation) {
ShareButton(
contentItem: contentItem,
presentingShareSheet: $presentingShareSheet
@ -140,14 +140,6 @@ struct ChannelVideosView: View {
}
}
private var shareButtonPlacement: ToolbarItemPlacement {
#if os(iOS)
.navigation
#else
.automatic
#endif
}
private var contentItem: ContentItem {
ContentItem(channel: channel)
}

View File

@ -3,43 +3,105 @@ import SwiftUI
struct ShareButton: View {
let contentItem: ContentItem
@Binding var presentingShareSheet: Bool
@Binding var shareURL: String
@EnvironmentObject<AccountsModel> private var accounts
@EnvironmentObject<PlayerModel> private var player
init(
contentItem: ContentItem,
presentingShareSheet: Binding<Bool>,
shareURL: Binding<String>? = nil
) {
self.contentItem = contentItem
_presentingShareSheet = presentingShareSheet
_shareURL = shareURL ?? .constant("")
}
var body: some View {
Group {
if let url = shareURL {
Button {
#if os(iOS)
presentingShareSheet = true
#else
NSPasteboard.general.clearContents()
NSPasteboard.general.setString(url, forType: .string)
#endif
} label: {
#if os(iOS)
Label("Share", systemImage: "square.and.arrow.up")
#else
EmptyView()
#endif
}
.keyboardShortcut("c")
.foregroundColor(.blue)
.buttonStyle(.plain)
Menu {
instanceActions
youtubeActions
} label: {
Label("Share", systemImage: "square.and.arrow.up")
.labelStyle(.iconOnly)
} else {
EmptyView()
}
.menuStyle(.borderlessButton)
#if os(macOS)
.frame(maxWidth: 35)
#endif
}
private var instanceActions: some View {
Group {
if let url = accounts.api.shareURL(contentItem) {
Button(labelForShareURL(accounts.app.name)) {
shareAction(url)
}
if contentItem.contentType == .video {
Button(labelForShareURL(accounts.app.name, withTime: true)) {
shareAction(
accounts.api.shareURL(
contentItem,
time: player.player.currentTime()
)!
)
}
}
}
}
}
private var shareURL: String? {
accounts.api.shareURL(contentItem)?.absoluteString
private var youtubeActions: some View {
Group {
if let url = accounts.api.shareURL(contentItem, frontendHost: "www.youtube.com") {
Button(labelForShareURL("YouTube")) {
shareAction(url)
}
if contentItem.contentType == .video {
Button(labelForShareURL("YouTube", withTime: true)) {
shareAction(
accounts.api.shareURL(
contentItem,
frontendHost: "www.youtube.com",
time: player.player.currentTime()
)!
)
}
}
}
}
}
private func shareAction(_ url: URL) {
#if os(macOS)
NSPasteboard.general.clearContents()
NSPasteboard.general.setString(url.absoluteString, forType: .string)
#else
shareURL = url.absoluteString
presentingShareSheet = true
#endif
}
private func labelForShareURL(_ app: String, withTime: Bool = false) -> String {
let time = withTime ? "with time" : ""
#if os(macOS)
return "Copy \(app) link \(time)"
#else
return "Share \(app) link \(time)"
#endif
}
}
struct ShareButton_Previews: PreviewProvider {
static var previews: some View {
ShareButton(contentItem: ContentItem(video: Video.fixture), presentingShareSheet: .constant(false))
ShareButton(
contentItem: ContentItem(video: Video.fixture),
presentingShareSheet: .constant(false)
)
.injectFixtureEnvironmentObjects()
}
}

View File

@ -79,7 +79,7 @@ struct EditFavorites: View {
func label(_ item: FavoriteItem) -> String {
if case let .playlist(id) = item.section {
return playlistsModel.find(id: id)?.title ?? "Unknown Playlist"
return playlistsModel.find(id: id)?.title ?? "Playlist"
}
return item.section.label