Generalize Yattee Server credentials manager to BasicAuthCredentialsManager

Renames YatteeServerCredentialsManager → BasicAuthCredentialsManager so the
same Keychain-backed username/password storage can be reused for any instance
type that sits behind a reverse proxy requiring HTTP Basic Auth. Adds a
one-time migration that moves existing items from the legacy
'com.yattee.yatteeserver' Keychain service to 'com.yattee.basicauth',
preserving the iCloud-sync attribute. No behavior change for end users.
This commit is contained in:
Arkadiusz Fal
2026-04-06 19:45:16 +02:00
parent 240cf23693
commit 8cd3aca96c
12 changed files with 141 additions and 56 deletions

View File

@@ -76,13 +76,13 @@ struct InstanceBrowseView: View {
/// Auth header for Yattee Server instances (when browsing a Yattee Server directly)
private var yatteeServerAuthHeader: String? {
guard instance.type == .yatteeServer else { return nil }
return appEnvironment?.yatteeServerCredentialsManager.basicAuthHeader(for: instance)
return appEnvironment?.basicAuthCredentialsManager.basicAuthHeader(for: instance)
}
/// Auth header for avatar loading (uses Yattee Server for YouTube channel avatars)
private var avatarAuthHeader: String? {
guard let server = yatteeServer else { return nil }
return appEnvironment?.yatteeServerCredentialsManager.basicAuthHeader(for: server)
return appEnvironment?.basicAuthCredentialsManager.basicAuthHeader(for: server)
}
enum BrowseTab: String, CaseIterable, Identifiable {

View File

@@ -54,7 +54,7 @@ struct UnifiedTabView: View {
private var yatteeServerAuthHeader: String? {
guard let server = appEnvironment?.instancesManager.enabledYatteeServerInstances.first else { return nil }
return appEnvironment?.yatteeServerCredentialsManager.basicAuthHeader(for: server)
return appEnvironment?.basicAuthCredentialsManager.basicAuthHeader(for: server)
}
var body: some View {
@@ -329,7 +329,7 @@ struct UnifiedTabView: View {
private var yatteeServerAuthHeader: String? {
guard let server = appEnvironment?.instancesManager.enabledYatteeServerInstances.first else { return nil }
return appEnvironment?.yatteeServerCredentialsManager.basicAuthHeader(for: server)
return appEnvironment?.basicAuthCredentialsManager.basicAuthHeader(for: server)
}
var body: some View {
@@ -554,7 +554,7 @@ struct UnifiedTabView: View {
private var yatteeServerAuthHeader: String? {
guard let server = appEnvironment?.instancesManager.enabledYatteeServerInstances.first else { return nil }
return appEnvironment?.yatteeServerCredentialsManager.basicAuthHeader(for: server)
return appEnvironment?.basicAuthCredentialsManager.basicAuthHeader(for: server)
}
var body: some View {

View File

@@ -529,7 +529,7 @@ struct AddRemoteServerView: View {
allowInvalidCertificates: allowInvalidCertificates
)
appEnvironment.yatteeServerCredentialsManager.setCredentials(
appEnvironment.basicAuthCredentialsManager.setCredentials(
username: yatteeServerUsername,
password: yatteeServerPassword,
for: instance

View File

@@ -346,7 +346,7 @@ private struct EditRemoteServerContent: View {
// Load existing Yattee Server credentials
if instance.type == .yatteeServer,
let credentials = appEnvironment?.yatteeServerCredentialsManager.credentials(for: instance) {
let credentials = appEnvironment?.basicAuthCredentialsManager.credentials(for: instance) {
yatteeServerUsername = credentials.username
yatteeServerPassword = credentials.password
}
@@ -438,7 +438,7 @@ private struct EditRemoteServerContent: View {
// Save Yattee Server credentials if provided
if instance.type == .yatteeServer && !yatteeServerUsername.isEmpty && !yatteeServerPassword.isEmpty {
appEnvironment?.yatteeServerCredentialsManager.setCredentials(
appEnvironment?.basicAuthCredentialsManager.setCredentials(
username: yatteeServerUsername,
password: yatteeServerPassword,
for: instance

View File

@@ -290,7 +290,7 @@ private struct ChannelNotificationToggle: View {
private var authHeader: String? {
guard let server = yatteeServer else { return nil }
return appEnvironment?.yatteeServerCredentialsManager.basicAuthHeader(for: server)
return appEnvironment?.basicAuthCredentialsManager.basicAuthHeader(for: server)
}
private var toggleBinding: Binding<Bool> {

View File

@@ -45,7 +45,7 @@ struct ManageChannelsView: View {
private var yatteeServerURL: URL? { yatteeServer?.url }
private var yatteeServerAuthHeader: String? {
guard let server = yatteeServer else { return nil }
return appEnvironment?.yatteeServerCredentialsManager.basicAuthHeader(for: server)
return appEnvironment?.basicAuthCredentialsManager.basicAuthHeader(for: server)
}
/// Channels filtered by search query and sorted by selected order.
@@ -439,7 +439,7 @@ struct ManageChannelsView: View {
do {
let api = YatteeServerAPI(httpClient: HTTPClient())
let authHeader = appEnvironment.yatteeServerCredentialsManager.basicAuthHeader(for: yatteeServer)
let authHeader = appEnvironment.basicAuthCredentialsManager.basicAuthHeader(for: yatteeServer)
await api.setAuthHeader(authHeader)
let response = try await api.channelsMetadata(channelIDs: channelIDs, instance: yatteeServer)

View File

@@ -52,7 +52,7 @@ struct SubscriptionsView: View {
private var yatteeServerURL: URL? { yatteeServer?.url }
private var yatteeServerAuthHeader: String? {
guard let server = yatteeServer else { return nil }
return appEnvironment?.yatteeServerCredentialsManager.basicAuthHeader(for: server)
return appEnvironment?.basicAuthCredentialsManager.basicAuthHeader(for: server)
}
/// Generates a unique ID based on instances configuration.