Add an option to share videos via privacy frontend URLs

When enabled (the default), share links to YouTube videos point to the
active source's web watch page instead of youtube.com. Invidious serves
its frontend at the API URL; Piped uses its configured frontend URL.
Videos the active source can't serve (PeerTube, extracted sources) and
sources without a web frontend keep their original links.

The toggle lives in Settings > Layout & Navigation > Sharing on iOS and
macOS, and is shown only when an enabled source has a web watch page.
This commit is contained in:
Arkadiusz Fal
2026-09-18 23:57:34 +02:00
parent 172d712f25
commit d22abf6088
13 changed files with 128 additions and 8 deletions

View File

@@ -10,6 +10,8 @@
import SwiftUI
struct PlayerPillButtonView: View {
@Environment(\.appEnvironment) private var appEnvironment
let configuration: ControlButtonConfiguration
let isPlaying: Bool
let hasNext: Bool
@@ -199,7 +201,7 @@ struct PlayerPillButtonView: View {
private var shareButton: some View {
Group {
if let video {
ShareLink(item: video.shareURL) {
ShareLink(item: appEnvironment?.shareURL(for: video) ?? video.shareURL) {
genericButtonLabel
}
.buttonStyle(.plain)

View File

@@ -280,7 +280,7 @@ struct VideoContextMenuContent: View {
// Share
#if !os(tvOS)
ShareLink(item: video.shareURL) {
ShareLink(item: appEnvironment?.shareURL(for: video) ?? video.shareURL) {
Label(String(localized: "video.context.share"), systemImage: "square.and.arrow.up")
}
#endif

View File

@@ -191,7 +191,7 @@ struct VideoSwipeActionsModifier: ViewModifier {
private func shareVideo() {
#if os(iOS)
let activityVC = UIActivityViewController(
activityItems: [video.shareURL],
activityItems: [appEnvironment?.shareURL(for: video) ?? video.shareURL],
applicationActivities: nil
)
if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
@@ -217,7 +217,7 @@ struct VideoSwipeActionsModifier: ViewModifier {
#elseif os(macOS)
let pasteboard = NSPasteboard.general
pasteboard.clearContents()
pasteboard.setString(video.shareURL.absoluteString, forType: .string)
pasteboard.setString((appEnvironment?.shareURL(for: video) ?? video.shareURL).absoluteString, forType: .string)
#endif
}

View File

@@ -11,6 +11,8 @@ import SwiftUI
/// Renders a horizontal row of control buttons based on layout configuration.
struct ControlsSectionRenderer: View {
@Environment(\.appEnvironment) private var appEnvironment
let section: LayoutSection
let actions: PlayerControlsActions
let globalSettings: GlobalLayoutSettings
@@ -925,7 +927,7 @@ struct ControlsSectionRenderer: View {
@ViewBuilder
private var shareButton: some View {
if let video = actions.currentVideo {
ShareLink(item: video.shareURL) {
ShareLink(item: appEnvironment?.shareURL(for: video) ?? video.shareURL) {
buttonContent(systemImage: "square.and.arrow.up", tint: .white)
}
}

View File

@@ -572,7 +572,7 @@ struct MiniPlayerView: View {
@ViewBuilder
private func shareButton(config: ControlButtonConfiguration) -> some View {
if let video = currentVideo {
ShareLink(item: video.shareURL) {
ShareLink(item: appEnvironment?.shareURL(for: video) ?? video.shareURL) {
Image(systemName: "square.and.arrow.up")
.font(isTabAccessory ? .title3 : .title2)
.frame(width: 32, height: 32)

View File

@@ -670,7 +670,7 @@ struct MacOSControlsSectionRenderer: View {
@ViewBuilder
private var shareButton: some View {
if let video = actions.currentVideo {
ShareLink(item: video.shareURL) {
ShareLink(item: appEnvironment?.shareURL(for: video) ?? video.shareURL) {
buttonLabel(systemImage: "square.and.arrow.up")
}
.buttonStyle(buttonStyleForContext)

View File

@@ -22,6 +22,7 @@ struct LayoutNavigationSettingsView: View {
#else
VideoActionsSection(settings: settings)
LinkActionSection(settings: settings)
SharingSection(settings: settings)
ClipboardSection(settings: settings)
#endif
#if os(iOS)
@@ -143,6 +144,32 @@ private struct LinkActionSection: View {
}
}
// MARK: - Sharing Section
#if !os(tvOS)
private struct SharingSection: View {
@Environment(\.appEnvironment) private var appEnvironment
@Bindable var settings: SettingsManager
/// Shown only when a source with a web watch page exists — without one
/// the toggle can't change anything.
private var hasPrivacyFrontendSource: Bool {
appEnvironment?.instancesManager.enabledInstances.contains { $0.watchPageBaseURL != nil } ?? false
}
var body: some View {
if hasPrivacyFrontendSource {
SettingsFormSection("settings.behavior.sharing.header", footer: "settings.behavior.privacyFrontendSharing.footer") {
Toggle(
String(localized: "settings.behavior.privacyFrontendSharing"),
isOn: $settings.privacyFrontendSharingEnabled
)
}
}
}
}
#endif
// MARK: - Clipboard Section
private struct ClipboardSection: View {

View File

@@ -1173,7 +1173,7 @@ struct VideoInfoView: View {
// Share button
if let video = displayedVideo {
ShareLink(item: video.shareURL) {
ShareLink(item: appEnvironment?.shareURL(for: video) ?? video.shareURL) {
#if os(macOS)
Label(String(localized: "video.share"), systemImage: "square.and.arrow.up")
.font(.body)