mirror of
https://github.com/yattee/yattee.git
synced 2026-10-23 13:12:53 +00:00
Add an optional frontend URL for Piped instances used by browser actions
This commit is contained in:
@@ -16794,6 +16794,17 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"sources.field.frontendURL" : {
|
||||
"comment" : "Field label for optional Piped web frontend URL",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Frontend URL"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"sources.field.name" : {
|
||||
"comment" : "Field label for source name",
|
||||
"localizations" : {
|
||||
@@ -17025,6 +17036,17 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"sources.footer.frontendURL" : {
|
||||
"comment" : "Footer text explaining the optional Piped web frontend URL",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Optional. Piped often serves its web frontend from a different address than the API. When set, it is used for opening this instance in the browser and copying its link. Leave empty to use the API URL."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"sources.footer.proxiesVideos" : {
|
||||
"comment" : "Footer text explaining video proxy option",
|
||||
"localizations" : {
|
||||
|
||||
@@ -58,6 +58,11 @@ struct Instance: Identifiable, Codable, Hashable, Sendable {
|
||||
/// The base URL of the instance.
|
||||
let url: URL
|
||||
|
||||
/// Optional URL of the web frontend, when it differs from the API URL
|
||||
/// (Piped serves its API and frontend from separate hosts). Used for
|
||||
/// browser-facing actions (open in browser, copy link) — never for API calls.
|
||||
var frontendURL: URL?
|
||||
|
||||
/// Optional user-defined name for this instance.
|
||||
var name: String?
|
||||
|
||||
@@ -102,6 +107,7 @@ struct Instance: Identifiable, Codable, Hashable, Sendable {
|
||||
id: UUID = UUID(),
|
||||
type: InstanceType,
|
||||
url: URL,
|
||||
frontendURL: URL? = nil,
|
||||
name: String? = nil,
|
||||
isEnabled: Bool = true,
|
||||
dateAdded: Date = Date(),
|
||||
@@ -113,6 +119,7 @@ struct Instance: Identifiable, Codable, Hashable, Sendable {
|
||||
self.id = id
|
||||
self.type = type
|
||||
self.url = url
|
||||
self.frontendURL = frontendURL
|
||||
self.name = name
|
||||
self.isEnabled = isEnabled
|
||||
self.dateAdded = dateAdded
|
||||
@@ -127,6 +134,7 @@ struct Instance: Identifiable, Codable, Hashable, Sendable {
|
||||
id = try container.decode(UUID.self, forKey: .id)
|
||||
type = try container.decode(InstanceType.self, forKey: .type)
|
||||
url = try container.decode(URL.self, forKey: .url)
|
||||
frontendURL = try container.decodeIfPresent(URL.self, forKey: .frontendURL)
|
||||
name = try container.decodeIfPresent(String.self, forKey: .name)
|
||||
isEnabled = try container.decode(Bool.self, forKey: .isEnabled)
|
||||
dateAdded = try container.decode(Date.self, forKey: .dateAdded)
|
||||
@@ -160,6 +168,12 @@ struct Instance: Identifiable, Codable, Hashable, Sendable {
|
||||
return components.url?.absoluteString ?? url.absoluteString
|
||||
}
|
||||
|
||||
/// The URL browser-facing actions should use: the web frontend when one is
|
||||
/// configured, else the API URL.
|
||||
var browseURL: URL {
|
||||
frontendURL ?? url
|
||||
}
|
||||
|
||||
var contentSource: ContentSource {
|
||||
type.contentSource(for: url)
|
||||
}
|
||||
|
||||
@@ -175,7 +175,7 @@ struct InstanceBrowseView: View {
|
||||
}
|
||||
|
||||
Button {
|
||||
openURL(instance.url)
|
||||
openURL(instance.browseURL)
|
||||
} label: {
|
||||
Label(String(localized: "instance.browse.openInBrowser"), systemImage: "safari")
|
||||
}
|
||||
@@ -257,10 +257,10 @@ struct InstanceBrowseView: View {
|
||||
|
||||
private func copyInstanceURL() {
|
||||
#if os(iOS)
|
||||
UIPasteboard.general.string = instance.url.absoluteString
|
||||
UIPasteboard.general.string = instance.browseURL.absoluteString
|
||||
#elseif os(macOS)
|
||||
NSPasteboard.general.clearContents()
|
||||
NSPasteboard.general.setString(instance.url.absoluteString, forType: .string)
|
||||
NSPasteboard.general.setString(instance.browseURL.absoluteString, forType: .string)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,10 @@ private struct EditRemoteServerContent: View {
|
||||
@State private var allowInvalidCertificates: Bool
|
||||
@State private var proxiesVideos: Bool
|
||||
|
||||
// Piped serves its API and web frontend from separate hosts; browser-facing
|
||||
// actions (open in browser, copy link) use this URL when set.
|
||||
@State private var frontendURLString: String
|
||||
|
||||
// HTTP Basic Auth credentials (for any instance type behind a reverse proxy;
|
||||
// required for Yattee Server, optional for Invidious/Piped/PeerTube).
|
||||
@State private var basicAuthUsername: String = ""
|
||||
@@ -66,6 +70,7 @@ private struct EditRemoteServerContent: View {
|
||||
_isEnabled = State(initialValue: instance.isEnabled)
|
||||
_allowInvalidCertificates = State(initialValue: instance.allowInvalidCertificates)
|
||||
_proxiesVideos = State(initialValue: instance.proxiesVideos)
|
||||
_frontendURLString = State(initialValue: instance.frontendURL?.absoluteString ?? "")
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
@@ -121,6 +126,27 @@ private struct EditRemoteServerContent: View {
|
||||
#endif
|
||||
}
|
||||
|
||||
if instance.type == .piped {
|
||||
Section {
|
||||
#if os(tvOS)
|
||||
TVSettingsTextField(title: String(localized: "sources.field.frontendURL"), text: $frontendURLString)
|
||||
#elseif os(macOS)
|
||||
LabeledContent(String(localized: "sources.field.frontendURL")) {
|
||||
TextField("", text: $frontendURLString)
|
||||
.autocorrectionDisabled()
|
||||
}
|
||||
#else
|
||||
TextField(String(localized: "sources.field.frontendURL"), text: $frontendURLString)
|
||||
.textContentType(.URL)
|
||||
.keyboardType(.URL)
|
||||
.textInputAutocapitalization(.never)
|
||||
.autocorrectionDisabled()
|
||||
#endif
|
||||
} footer: {
|
||||
Text(String(localized: "sources.footer.frontendURL"))
|
||||
}
|
||||
}
|
||||
|
||||
if instance.type == .yatteeServer {
|
||||
// Server Info Section
|
||||
Section {
|
||||
@@ -465,6 +491,11 @@ private struct EditRemoteServerContent: View {
|
||||
updated.allowInvalidCertificates = allowInvalidCertificates
|
||||
updated.proxiesVideos = proxiesVideos
|
||||
|
||||
if instance.type == .piped {
|
||||
let trimmed = frontendURLString.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
updated.frontendURL = trimmed.isEmpty ? nil : Instance.normalizeSourceURL(trimmed)
|
||||
}
|
||||
|
||||
// Save / clear HTTP Basic Auth credentials. Yattee Server never auto-clears
|
||||
// (credentials are required and the user re-enters to overwrite). Piped never
|
||||
// persists them — its session token reuses the same Authorization header.
|
||||
|
||||
Reference in New Issue
Block a user