mirror of
https://github.com/yattee/yattee.git
synced 2025-08-09 20:24:06 +00:00
Save last used account instead of having to set default
This commit is contained in:
@@ -1,12 +1,22 @@
|
||||
import Defaults
|
||||
import Foundation
|
||||
|
||||
extension Defaults.Keys {
|
||||
static let invidiousInstanceID = "default-invidious-instance"
|
||||
static let pipedInstanceID = "default-piped-instance"
|
||||
|
||||
static let instances = Key<[Instance]>("instances", default: [
|
||||
.init(app: .piped, name: "Public", url: "https://pipedapi.kavin.rocks"),
|
||||
.init(app: .invidious, name: "Private", url: "https://invidious.home.arekf.net")
|
||||
.init(app: .piped, id: pipedInstanceID, name: "Public", url: "https://pipedapi.kavin.rocks"),
|
||||
.init(app: .invidious, id: invidiousInstanceID, name: "Private", url: "https://invidious.home.arekf.net")
|
||||
])
|
||||
static let accounts = Key<[Instance.Account]>("accounts", default: [])
|
||||
static let defaultAccountID = Key<String?>("defaultAccountID")
|
||||
static let accounts = Key<[Instance.Account]>("accounts", default: [
|
||||
.init(instanceID: invidiousInstanceID,
|
||||
name: "arekf",
|
||||
url: "https://invidious.home.arekf.net",
|
||||
sid: "ki55SJbaQmm0bOxUWctGAQLYPQRgk-CXDPw5Dp4oBmI=")
|
||||
])
|
||||
static let lastAccountID = Key<Instance.Account.ID?>("lastAccountID")
|
||||
static let lastInstanceID = Key<Instance.ID?>("lastInstanceID")
|
||||
|
||||
static let quality = Key<Stream.ResolutionSetting>("quality", default: .hd720pFirstThenBest)
|
||||
|
||||
|
@@ -4,24 +4,29 @@ import SwiftUI
|
||||
struct AccountsMenuView: View {
|
||||
@EnvironmentObject<AccountsModel> private var model
|
||||
|
||||
@Default(.accounts) private var accounts
|
||||
@Default(.instances) private var instances
|
||||
|
||||
var body: some View {
|
||||
Menu {
|
||||
ForEach(model.all, id: \.id) { account in
|
||||
ForEach(allAccounts, id: \.id) { account in
|
||||
Button(accountButtonTitle(account: account)) {
|
||||
model.setAccount(account)
|
||||
model.setCurrent(account)
|
||||
}
|
||||
}
|
||||
} label: {
|
||||
Label(model.account?.name ?? "Select Account", systemImage: "person.crop.circle")
|
||||
Label(model.current?.name ?? "Select Account", systemImage: "person.crop.circle")
|
||||
.labelStyle(.titleAndIcon)
|
||||
}
|
||||
.disabled(instances.isEmpty)
|
||||
.transaction { t in t.animation = .none }
|
||||
}
|
||||
|
||||
func accountButtonTitle(account: Instance.Account) -> String {
|
||||
private var allAccounts: [Instance.Account] {
|
||||
accounts + instances.map(\.anonymousAccount)
|
||||
}
|
||||
|
||||
private func accountButtonTitle(account: Instance.Account) -> String {
|
||||
instances.count > 1 ? "\(account.description) — \(account.instance.description)" : account.description
|
||||
}
|
||||
}
|
||||
|
@@ -62,8 +62,8 @@ struct AppSidebarNavigation: View {
|
||||
.help(
|
||||
"Switch Instances and Accounts\n" +
|
||||
"Current Instance: \n" +
|
||||
"\(accounts.account?.url ?? "Not Set")\n" +
|
||||
"Current User: \(accounts.account?.description ?? "Not set")"
|
||||
"\(accounts.current?.url ?? "Not Set")\n" +
|
||||
"Current User: \(accounts.current?.description ?? "Not set")"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@@ -85,15 +85,17 @@ struct ContentView: View {
|
||||
SiestaLog.Category.enabled = .common
|
||||
|
||||
// TODO: Remove when piped supports videos information
|
||||
if let account = instances.defaultAccount ??
|
||||
accounts.all.first(where: { $0.instance.app == .invidious })
|
||||
if let account = accounts.lastUsed ??
|
||||
instances.lastUsed?.anonymousAccount ??
|
||||
instances.all.first?.anonymousAccount
|
||||
{
|
||||
accounts.setAccount(account)
|
||||
accounts.setCurrent(account)
|
||||
}
|
||||
|
||||
if accounts.account.isNil {
|
||||
if accounts.current.isNil {
|
||||
navigation.presentingWelcomeScreen = true
|
||||
}
|
||||
|
||||
player.accounts = accounts
|
||||
playlists.accounts = accounts
|
||||
search.accounts = accounts
|
||||
@@ -101,7 +103,7 @@ struct ContentView: View {
|
||||
}
|
||||
|
||||
func openWelcomeScreenIfAccountEmpty() {
|
||||
guard accounts.isEmpty else {
|
||||
guard Defaults[.instances].isEmpty else {
|
||||
return
|
||||
}
|
||||
|
||||
|
@@ -16,7 +16,6 @@ struct PearvidiousApp: App {
|
||||
#if os(macOS)
|
||||
Settings {
|
||||
SettingsView()
|
||||
.environmentObject(InvidiousAPI())
|
||||
.environmentObject(InstancesModel())
|
||||
}
|
||||
#endif
|
||||
|
@@ -122,8 +122,7 @@ struct VideoPlayerView: View {
|
||||
VStack(spacing: 10) {
|
||||
#if !os(tvOS)
|
||||
Image(systemName: "ticket")
|
||||
.font(.system(size: 80))
|
||||
Text("What are we watching next?")
|
||||
.font(.system(size: 120))
|
||||
#endif
|
||||
}
|
||||
Spacer()
|
||||
|
@@ -124,7 +124,7 @@ struct AccountFormView: View {
|
||||
return
|
||||
}
|
||||
|
||||
let account = instances.addAccount(instance: instance, name: name, sid: sid)
|
||||
let account = AccountsModel.add(instance: instance, name: name, sid: sid)
|
||||
selectedAccount?.wrappedValue = account
|
||||
|
||||
dismiss()
|
||||
|
@@ -6,10 +6,11 @@ struct AccountsSettingsView: View {
|
||||
@State private var accountsChanged = false
|
||||
@State private var presentingAccountForm = false
|
||||
|
||||
@EnvironmentObject<AccountsModel> private var model
|
||||
@EnvironmentObject<InstancesModel> private var instances
|
||||
|
||||
var instance: Instance! {
|
||||
instances.find(instanceID)
|
||||
InstancesModel.find(instanceID)
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
@@ -27,41 +28,18 @@ struct AccountsSettingsView: View {
|
||||
var accounts: some View {
|
||||
List {
|
||||
Section(header: Text("Accounts"), footer: sectionFooter) {
|
||||
ForEach(instances.accounts(instanceID), id: \.self) { account in
|
||||
#if os(iOS)
|
||||
HStack(spacing: 2) {
|
||||
Text(account.description)
|
||||
if instances.defaultAccount == account {
|
||||
Text("— default")
|
||||
.foregroundColor(.secondary)
|
||||
ForEach(InstancesModel.accounts(instanceID), id: \.self) { account in
|
||||
#if os(tvOS)
|
||||
Button(account.description) {}
|
||||
.contextMenu {
|
||||
Button("Remove", role: .destructive) { removeAccount(account) }
|
||||
Button("Cancel", role: .cancel) {}
|
||||
}
|
||||
}
|
||||
.swipeActions(edge: .leading, allowsFullSwipe: true) {
|
||||
if instances.defaultAccount != account {
|
||||
Button("Make Default") { makeDefault(account) }
|
||||
} else {
|
||||
Button("Reset Default", action: resetDefaultAccount)
|
||||
}
|
||||
}
|
||||
.swipeActions(edge: .trailing, allowsFullSwipe: false) {
|
||||
Button("Remove", role: .destructive) { removeAccount(account) }
|
||||
}
|
||||
|
||||
#else
|
||||
Button(action: { toggleDefault(account) }) {
|
||||
HStack(spacing: 2) {
|
||||
Text(account.description)
|
||||
if instances.defaultAccount == account {
|
||||
Text("— default")
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
Text(account.description)
|
||||
.swipeActions(edge: .trailing, allowsFullSwipe: false) {
|
||||
Button("Remove", role: .destructive) { removeAccount(account) }
|
||||
}
|
||||
}
|
||||
.contextMenu {
|
||||
Button("Toggle Default") { toggleDefault(account) }
|
||||
Button("Remove", role: .destructive) { removeAccount(account) }
|
||||
Button("Cancel", role: .cancel) {}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
.redrawOn(change: accountsChanged)
|
||||
@@ -83,33 +61,15 @@ struct AccountsSettingsView: View {
|
||||
|
||||
private var sectionFooter: some View {
|
||||
#if os(iOS)
|
||||
Text("Swipe right to toggle default account, swipe left to remove")
|
||||
Text("Swipe to remove account")
|
||||
#else
|
||||
Text("Tap to toggle default account, tap and hold to remove")
|
||||
Text("Tap and hold to remove account")
|
||||
.foregroundColor(.secondary)
|
||||
#endif
|
||||
}
|
||||
|
||||
private func makeDefault(_ account: Instance.Account) {
|
||||
instances.setDefaultAccount(account)
|
||||
accountsChanged.toggle()
|
||||
}
|
||||
|
||||
private func toggleDefault(_ account: Instance.Account) {
|
||||
if account == instances.defaultAccount {
|
||||
resetDefaultAccount()
|
||||
} else {
|
||||
makeDefault(account)
|
||||
}
|
||||
}
|
||||
|
||||
private func resetDefaultAccount() {
|
||||
instances.resetDefaultAccount()
|
||||
accountsChanged.toggle()
|
||||
}
|
||||
|
||||
private func removeAccount(_ account: Instance.Account) {
|
||||
instances.removeAccount(account)
|
||||
AccountsModel.remove(account)
|
||||
accountsChanged.toggle()
|
||||
}
|
||||
}
|
||||
|
@@ -1,38 +0,0 @@
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
struct DefaultAccountHint: View {
|
||||
@EnvironmentObject<InstancesModel> private var instancesModel
|
||||
|
||||
var body: some View {
|
||||
Group {
|
||||
if !instancesModel.defaultAccount.isNil {
|
||||
VStack {
|
||||
HStack(spacing: 2) {
|
||||
hintText
|
||||
.truncationMode(.middle)
|
||||
.lineLimit(1)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Text("You have no default account set")
|
||||
}
|
||||
}
|
||||
#if os(tvOS)
|
||||
.foregroundColor(.gray)
|
||||
#elseif os(macOS)
|
||||
.font(.caption2)
|
||||
.foregroundColor(.secondary)
|
||||
#endif
|
||||
}
|
||||
|
||||
var hintText: some View {
|
||||
Group {
|
||||
if let account = instancesModel.defaultAccount {
|
||||
Text(
|
||||
"**\(account.description)** account on instance **\(account.instance.shortDescription)** is your default."
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -146,7 +146,7 @@ struct InstanceFormView: View {
|
||||
return
|
||||
}
|
||||
|
||||
savedInstanceID = instancesModel.add(app: app, name: name, url: url).id
|
||||
savedInstanceID = InstancesModel.add(app: app, name: name, url: url).id
|
||||
|
||||
dismiss()
|
||||
}
|
||||
|
@@ -17,7 +17,7 @@ struct InstancesSettingsView: View {
|
||||
|
||||
var body: some View {
|
||||
Group {
|
||||
Section(header: Text("Instances"), footer: DefaultAccountHint()) {
|
||||
Section(header: Text("Instances")) {
|
||||
ForEach(instances) { instance in
|
||||
Group {
|
||||
NavigationLink(instance.longDescription) {
|
||||
@@ -55,16 +55,12 @@ struct InstancesSettingsView: View {
|
||||
|
||||
private func removeInstanceButton(_ instance: Instance) -> some View {
|
||||
Button("Remove", role: .destructive) {
|
||||
if accounts.account?.instance == instance {
|
||||
accounts.setAccount(nil)
|
||||
if accounts.current?.instance == instance {
|
||||
accounts.setCurrent(nil)
|
||||
}
|
||||
instancesModel.remove(instance)
|
||||
InstancesModel.remove(instance)
|
||||
}
|
||||
}
|
||||
|
||||
private func resetDefaultAccount() {
|
||||
instancesModel.resetDefaultAccount()
|
||||
}
|
||||
}
|
||||
|
||||
struct InstancesSettingsView_Previews: PreviewProvider {
|
||||
|
@@ -21,7 +21,7 @@ struct SubscriptionsView: View {
|
||||
.onAppear {
|
||||
loadResources()
|
||||
}
|
||||
.onChange(of: accounts.account) { _ in
|
||||
.onChange(of: accounts.current) { _ in
|
||||
loadResources(force: true)
|
||||
}
|
||||
}
|
||||
|
@@ -39,6 +39,10 @@ struct VideoContextMenuView: View {
|
||||
removeFromPlaylistButton(playlistID: id)
|
||||
}
|
||||
}
|
||||
|
||||
#if os(tvOS)
|
||||
Button("Cancel", role: .cancel) {}
|
||||
#endif
|
||||
}
|
||||
|
||||
var playNowButton: some View {
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import Defaults
|
||||
import SwiftUI
|
||||
|
||||
struct WelcomeScreen: View {
|
||||
@@ -6,6 +7,8 @@ struct WelcomeScreen: View {
|
||||
@EnvironmentObject<AccountsModel> private var accounts
|
||||
@EnvironmentObject<NavigationModel> private var navigation
|
||||
|
||||
@Default(.accounts) private var allAccounts
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
Spacer()
|
||||
@@ -14,7 +17,7 @@ struct WelcomeScreen: View {
|
||||
.font(.largeTitle)
|
||||
.padding(.bottom, 10)
|
||||
|
||||
if accounts.all.isEmpty {
|
||||
if allAccounts.isEmpty {
|
||||
Text("To start, configure your Instances in Settings")
|
||||
.foregroundColor(.secondary)
|
||||
} else {
|
||||
@@ -28,12 +31,12 @@ struct WelcomeScreen: View {
|
||||
} label: {
|
||||
Text("Start")
|
||||
}
|
||||
.opacity(accounts.account.isNil ? 0 : 1)
|
||||
.disabled(accounts.account.isNil)
|
||||
.opacity(accounts.current.isNil ? 0 : 1)
|
||||
.disabled(accounts.current.isNil)
|
||||
|
||||
#else
|
||||
AccountsMenuView()
|
||||
.onChange(of: accounts.account) { _ in
|
||||
.onChange(of: accounts.current) { _ in
|
||||
dismiss()
|
||||
}
|
||||
#if os(macOS)
|
||||
|
@@ -21,7 +21,7 @@ struct WatchNowSection: View {
|
||||
resource.addObserver(store)
|
||||
resource.loadIfNeeded()
|
||||
}
|
||||
.onChange(of: accounts.account) { _ in
|
||||
.onChange(of: accounts.current) { _ in
|
||||
resource.load()
|
||||
}
|
||||
}
|
||||
|
@@ -12,7 +12,7 @@ struct WatchNowView: View {
|
||||
var body: some View {
|
||||
PlayerControlsView {
|
||||
ScrollView(.vertical, showsIndicators: false) {
|
||||
if !accounts.account.isNil {
|
||||
if !accounts.current.isNil {
|
||||
VStack(alignment: .leading, spacing: 0) {
|
||||
if api.signedIn {
|
||||
WatchNowSection(resource: api.feed, label: "Subscriptions")
|
||||
|
Reference in New Issue
Block a user