mirror of
https://github.com/yattee/yattee.git
synced 2024-12-22 21:43:41 +00:00
Save last used account instead of having to set default
This commit is contained in:
parent
00d706766c
commit
2d075e7b3a
@ -3,7 +3,7 @@ import Defaults
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
final class AccountsModel: ObservableObject {
|
final class AccountsModel: ObservableObject {
|
||||||
@Published private(set) var account: Instance.Account!
|
@Published private(set) var current: Instance.Account!
|
||||||
|
|
||||||
@Published private(set) var invidious = InvidiousAPI()
|
@Published private(set) var invidious = InvidiousAPI()
|
||||||
@Published private(set) var piped = PipedAPI()
|
@Published private(set) var piped = PipedAPI()
|
||||||
@ -11,15 +11,23 @@ final class AccountsModel: ObservableObject {
|
|||||||
private var cancellables = [AnyCancellable]()
|
private var cancellables = [AnyCancellable]()
|
||||||
|
|
||||||
var all: [Instance.Account] {
|
var all: [Instance.Account] {
|
||||||
Defaults[.instances].map(\.anonymousAccount) + Defaults[.accounts]
|
Defaults[.accounts]
|
||||||
|
}
|
||||||
|
|
||||||
|
var lastUsed: Instance.Account? {
|
||||||
|
guard let id = Defaults[.lastAccountID] else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return AccountsModel.find(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
var isEmpty: Bool {
|
var isEmpty: Bool {
|
||||||
account.isNil
|
current.isNil
|
||||||
}
|
}
|
||||||
|
|
||||||
var signedIn: Bool {
|
var signedIn: Bool {
|
||||||
!isEmpty && !account.anonymous
|
!isEmpty && !current.anonymous
|
||||||
}
|
}
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
@ -32,12 +40,12 @@ final class AccountsModel: ObservableObject {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func setAccount(_ account: Instance.Account! = nil) {
|
func setCurrent(_ account: Instance.Account! = nil) {
|
||||||
guard account != self.account else {
|
guard account != current else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
self.account = account
|
current = account
|
||||||
|
|
||||||
guard !account.isNil else {
|
guard !account.isNil else {
|
||||||
return
|
return
|
||||||
@ -49,5 +57,25 @@ final class AccountsModel: ObservableObject {
|
|||||||
case .piped:
|
case .piped:
|
||||||
piped.setAccount(account)
|
piped.setAccount(account)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Defaults[.lastAccountID] = account.anonymous ? nil : account.id
|
||||||
|
Defaults[.lastInstanceID] = account.instanceID
|
||||||
|
}
|
||||||
|
|
||||||
|
static func find(_ id: Instance.Account.ID) -> Instance.Account? {
|
||||||
|
Defaults[.accounts].first { $0.id == id }
|
||||||
|
}
|
||||||
|
|
||||||
|
static func add(instance: Instance, name: String, sid: String) -> Instance.Account {
|
||||||
|
let account = Instance.Account(instanceID: instance.id, name: name, url: instance.url, sid: sid)
|
||||||
|
Defaults[.accounts].append(account)
|
||||||
|
|
||||||
|
return account
|
||||||
|
}
|
||||||
|
|
||||||
|
static func remove(_ account: Instance.Account) {
|
||||||
|
if let accountIndex = Defaults[.accounts].firstIndex(where: { $0.id == account.id }) {
|
||||||
|
Defaults[.accounts].remove(at: accountIndex)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,17 +14,17 @@ struct Instance: Defaults.Serializable, Hashable, Identifiable {
|
|||||||
static var bridge = AccountsBridge()
|
static var bridge = AccountsBridge()
|
||||||
|
|
||||||
let id: String
|
let id: String
|
||||||
let instanceID: UUID
|
let instanceID: String
|
||||||
var name: String?
|
var name: String?
|
||||||
let url: String
|
let url: String
|
||||||
let sid: String
|
let sid: String
|
||||||
let anonymous: Bool
|
let anonymous: Bool
|
||||||
|
|
||||||
init(id: String? = nil, instanceID: UUID? = nil, name: String? = nil, url: String? = nil, sid: String? = nil, anonymous: Bool = false) {
|
init(id: String? = nil, instanceID: String? = nil, name: String? = nil, url: String? = nil, sid: String? = nil, anonymous: Bool = false) {
|
||||||
self.anonymous = anonymous
|
self.anonymous = anonymous
|
||||||
|
|
||||||
self.id = id ?? (anonymous ? "anonymous-\(instanceID!)" : UUID().uuidString)
|
self.id = id ?? (anonymous ? "anonymous-\(instanceID!)" : UUID().uuidString)
|
||||||
self.instanceID = instanceID ?? UUID()
|
self.instanceID = instanceID ?? UUID().uuidString
|
||||||
self.name = name
|
self.name = name
|
||||||
self.url = url ?? ""
|
self.url = url ?? ""
|
||||||
self.sid = sid ?? ""
|
self.sid = sid ?? ""
|
||||||
@ -62,7 +62,7 @@ struct Instance: Defaults.Serializable, Hashable, Identifiable {
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
"id": value.id,
|
"id": value.id,
|
||||||
"instanceID": value.instanceID.uuidString,
|
"instanceID": value.instanceID,
|
||||||
"name": value.name ?? "",
|
"name": value.name ?? "",
|
||||||
"url": value.url,
|
"url": value.url,
|
||||||
"sid": value.sid
|
"sid": value.sid
|
||||||
@ -80,10 +80,9 @@ struct Instance: Defaults.Serializable, Hashable, Identifiable {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
let instanceUUID = UUID(uuidString: instanceID)!
|
|
||||||
let name = object["name"] ?? ""
|
let name = object["name"] ?? ""
|
||||||
|
|
||||||
return Account(id: id, instanceID: instanceUUID, name: name, url: url, sid: sid)
|
return Account(id: id, instanceID: instanceID, name: name, url: url, sid: sid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -91,13 +90,13 @@ struct Instance: Defaults.Serializable, Hashable, Identifiable {
|
|||||||
static var bridge = InstancesBridge()
|
static var bridge = InstancesBridge()
|
||||||
|
|
||||||
let app: App
|
let app: App
|
||||||
let id: UUID
|
let id: String
|
||||||
let name: String
|
let name: String
|
||||||
let url: String
|
let url: String
|
||||||
|
|
||||||
init(app: App, id: UUID? = nil, name: String, url: String) {
|
init(app: App, id: String? = nil, name: String, url: String) {
|
||||||
self.app = app
|
self.app = app
|
||||||
self.id = id ?? UUID()
|
self.id = id ?? UUID().uuidString
|
||||||
self.name = name
|
self.name = name
|
||||||
self.url = url
|
self.url = url
|
||||||
}
|
}
|
||||||
@ -133,7 +132,7 @@ struct Instance: Defaults.Serializable, Hashable, Identifiable {
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
"app": value.app.rawValue,
|
"app": value.app.rawValue,
|
||||||
"id": value.id.uuidString,
|
"id": value.id,
|
||||||
"name": value.name,
|
"name": value.name,
|
||||||
"url": value.url
|
"url": value.url
|
||||||
]
|
]
|
||||||
@ -149,10 +148,9 @@ struct Instance: Defaults.Serializable, Hashable, Identifiable {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
let uuid = UUID(uuidString: id)
|
|
||||||
let name = object["name"] ?? ""
|
let name = object["name"] ?? ""
|
||||||
|
|
||||||
return Instance(app: app, id: uuid, name: name, url: url)
|
return Instance(app: app, id: id, name: name, url: url)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,21 +2,19 @@ import Defaults
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
final class InstancesModel: ObservableObject {
|
final class InstancesModel: ObservableObject {
|
||||||
@Published var defaultAccount: Instance.Account?
|
|
||||||
|
|
||||||
var all: [Instance] {
|
var all: [Instance] {
|
||||||
Defaults[.instances]
|
Defaults[.instances]
|
||||||
}
|
}
|
||||||
|
|
||||||
init() {
|
var lastUsed: Instance? {
|
||||||
guard let id = Defaults[.defaultAccountID] else {
|
guard let id = Defaults[.lastInstanceID] else {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultAccount = findAccount(id)
|
return InstancesModel.find(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
func find(_ id: Instance.ID?) -> Instance? {
|
static func find(_ id: Instance.ID?) -> Instance? {
|
||||||
guard id != nil else {
|
guard id != nil else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -24,48 +22,26 @@ final class InstancesModel: ObservableObject {
|
|||||||
return Defaults[.instances].first { $0.id == id }
|
return Defaults[.instances].first { $0.id == id }
|
||||||
}
|
}
|
||||||
|
|
||||||
func accounts(_ id: Instance.ID?) -> [Instance.Account] {
|
static func accounts(_ id: Instance.ID?) -> [Instance.Account] {
|
||||||
Defaults[.accounts].filter { $0.instanceID == id }
|
Defaults[.accounts].filter { $0.instanceID == id }
|
||||||
}
|
}
|
||||||
|
|
||||||
func add(app: Instance.App, name: String, url: String) -> Instance {
|
static func add(app: Instance.App, name: String, url: String) -> Instance {
|
||||||
let instance = Instance(app: app, name: name, url: url)
|
let instance = Instance(app: app, id: UUID().uuidString, name: name, url: url)
|
||||||
Defaults[.instances].append(instance)
|
Defaults[.instances].append(instance)
|
||||||
|
|
||||||
return instance
|
return instance
|
||||||
}
|
}
|
||||||
|
|
||||||
func remove(_ instance: Instance) {
|
static func remove(_ instance: Instance) {
|
||||||
let accounts = accounts(instance.id)
|
let accounts = InstancesModel.accounts(instance.id)
|
||||||
if let index = Defaults[.instances].firstIndex(where: { $0.id == instance.id }) {
|
if let index = Defaults[.instances].firstIndex(where: { $0.id == instance.id }) {
|
||||||
Defaults[.instances].remove(at: index)
|
Defaults[.instances].remove(at: index)
|
||||||
accounts.forEach { removeAccount($0) }
|
accounts.forEach { AccountsModel.remove($0) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func findAccount(_ id: Instance.Account.ID) -> Instance.Account? {
|
static func setLastAccount(_ account: Instance.Account?) {
|
||||||
Defaults[.accounts].first { $0.id == id }
|
Defaults[.lastAccountID] = account?.id
|
||||||
}
|
|
||||||
|
|
||||||
func addAccount(instance: Instance, name: String, sid: String) -> Instance.Account {
|
|
||||||
let account = Instance.Account(instanceID: instance.id, name: name, url: instance.url, sid: sid)
|
|
||||||
Defaults[.accounts].append(account)
|
|
||||||
|
|
||||||
return account
|
|
||||||
}
|
|
||||||
|
|
||||||
func removeAccount(_ account: Instance.Account) {
|
|
||||||
if let accountIndex = Defaults[.accounts].firstIndex(where: { $0.id == account.id }) {
|
|
||||||
Defaults[.accounts].remove(at: accountIndex)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func setDefaultAccount(_ account: Instance.Account?) {
|
|
||||||
Defaults[.defaultAccountID] = account?.id
|
|
||||||
defaultAccount = account
|
|
||||||
}
|
|
||||||
|
|
||||||
func resetDefaultAccount() {
|
|
||||||
setDefaultAccount(nil)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,6 @@
|
|||||||
37484C1B26FC837400287258 /* PlaybackSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37484C1826FC837400287258 /* PlaybackSettingsView.swift */; };
|
37484C1B26FC837400287258 /* PlaybackSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37484C1826FC837400287258 /* PlaybackSettingsView.swift */; };
|
||||||
37484C1D26FC83A400287258 /* InstancesSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37484C1C26FC83A400287258 /* InstancesSettingsView.swift */; };
|
37484C1D26FC83A400287258 /* InstancesSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37484C1C26FC83A400287258 /* InstancesSettingsView.swift */; };
|
||||||
37484C1F26FC83A400287258 /* InstancesSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37484C1C26FC83A400287258 /* InstancesSettingsView.swift */; };
|
37484C1F26FC83A400287258 /* InstancesSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37484C1C26FC83A400287258 /* InstancesSettingsView.swift */; };
|
||||||
37484C2226FC83C400287258 /* AccountSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37484C2026FC83C400287258 /* AccountSettingsView.swift */; };
|
|
||||||
37484C2526FC83E000287258 /* InstanceFormView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37484C2426FC83E000287258 /* InstanceFormView.swift */; };
|
37484C2526FC83E000287258 /* InstanceFormView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37484C2426FC83E000287258 /* InstanceFormView.swift */; };
|
||||||
37484C2626FC83E000287258 /* InstanceFormView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37484C2426FC83E000287258 /* InstanceFormView.swift */; };
|
37484C2626FC83E000287258 /* InstanceFormView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37484C2426FC83E000287258 /* InstanceFormView.swift */; };
|
||||||
37484C2726FC83E000287258 /* InstanceFormView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37484C2426FC83E000287258 /* InstanceFormView.swift */; };
|
37484C2726FC83E000287258 /* InstanceFormView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37484C2426FC83E000287258 /* InstanceFormView.swift */; };
|
||||||
@ -325,9 +324,6 @@
|
|||||||
37F64FE526FE70A60081B69E /* RedrawOnViewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37F64FE326FE70A60081B69E /* RedrawOnViewModifier.swift */; };
|
37F64FE526FE70A60081B69E /* RedrawOnViewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37F64FE326FE70A60081B69E /* RedrawOnViewModifier.swift */; };
|
||||||
37F64FE626FE70A60081B69E /* RedrawOnViewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37F64FE326FE70A60081B69E /* RedrawOnViewModifier.swift */; };
|
37F64FE626FE70A60081B69E /* RedrawOnViewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37F64FE326FE70A60081B69E /* RedrawOnViewModifier.swift */; };
|
||||||
37FD43DC270470B70073EE42 /* InstancesSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FD43DB270470B70073EE42 /* InstancesSettingsView.swift */; };
|
37FD43DC270470B70073EE42 /* InstancesSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FD43DB270470B70073EE42 /* InstancesSettingsView.swift */; };
|
||||||
37FD43DE2704717F0073EE42 /* DefaultAccountHint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FD43DD2704717F0073EE42 /* DefaultAccountHint.swift */; };
|
|
||||||
37FD43DF2704717F0073EE42 /* DefaultAccountHint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FD43DD2704717F0073EE42 /* DefaultAccountHint.swift */; };
|
|
||||||
37FD43E02704717F0073EE42 /* DefaultAccountHint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FD43DD2704717F0073EE42 /* DefaultAccountHint.swift */; };
|
|
||||||
37FD43E32704847C0073EE42 /* View+Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FD43E22704847C0073EE42 /* View+Fixtures.swift */; };
|
37FD43E32704847C0073EE42 /* View+Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FD43E22704847C0073EE42 /* View+Fixtures.swift */; };
|
||||||
37FD43E42704847C0073EE42 /* View+Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FD43E22704847C0073EE42 /* View+Fixtures.swift */; };
|
37FD43E42704847C0073EE42 /* View+Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FD43E22704847C0073EE42 /* View+Fixtures.swift */; };
|
||||||
37FD43E52704847C0073EE42 /* View+Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FD43E22704847C0073EE42 /* View+Fixtures.swift */; };
|
37FD43E52704847C0073EE42 /* View+Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37FD43E22704847C0073EE42 /* View+Fixtures.swift */; };
|
||||||
@ -390,7 +386,6 @@
|
|||||||
3748186D26A769D60084E870 /* DetailBadge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailBadge.swift; sourceTree = "<group>"; };
|
3748186D26A769D60084E870 /* DetailBadge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailBadge.swift; sourceTree = "<group>"; };
|
||||||
37484C1826FC837400287258 /* PlaybackSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaybackSettingsView.swift; sourceTree = "<group>"; };
|
37484C1826FC837400287258 /* PlaybackSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaybackSettingsView.swift; sourceTree = "<group>"; };
|
||||||
37484C1C26FC83A400287258 /* InstancesSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstancesSettingsView.swift; sourceTree = "<group>"; };
|
37484C1C26FC83A400287258 /* InstancesSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstancesSettingsView.swift; sourceTree = "<group>"; };
|
||||||
37484C2026FC83C400287258 /* AccountSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountSettingsView.swift; sourceTree = "<group>"; };
|
|
||||||
37484C2426FC83E000287258 /* InstanceFormView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstanceFormView.swift; sourceTree = "<group>"; };
|
37484C2426FC83E000287258 /* InstanceFormView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstanceFormView.swift; sourceTree = "<group>"; };
|
||||||
37484C2826FC83FF00287258 /* AccountFormView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountFormView.swift; sourceTree = "<group>"; };
|
37484C2826FC83FF00287258 /* AccountFormView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountFormView.swift; sourceTree = "<group>"; };
|
||||||
37484C2C26FC844700287258 /* AccountsSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountsSettingsView.swift; sourceTree = "<group>"; };
|
37484C2C26FC844700287258 /* AccountsSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountsSettingsView.swift; sourceTree = "<group>"; };
|
||||||
@ -481,7 +476,6 @@
|
|||||||
37F4AE7126828F0900BD60EA /* VideosCellsVertical.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideosCellsVertical.swift; sourceTree = "<group>"; };
|
37F4AE7126828F0900BD60EA /* VideosCellsVertical.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideosCellsVertical.swift; sourceTree = "<group>"; };
|
||||||
37F64FE326FE70A60081B69E /* RedrawOnViewModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RedrawOnViewModifier.swift; sourceTree = "<group>"; };
|
37F64FE326FE70A60081B69E /* RedrawOnViewModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RedrawOnViewModifier.swift; sourceTree = "<group>"; };
|
||||||
37FD43DB270470B70073EE42 /* InstancesSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstancesSettingsView.swift; sourceTree = "<group>"; };
|
37FD43DB270470B70073EE42 /* InstancesSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstancesSettingsView.swift; sourceTree = "<group>"; };
|
||||||
37FD43DD2704717F0073EE42 /* DefaultAccountHint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultAccountHint.swift; sourceTree = "<group>"; };
|
|
||||||
37FD43E22704847C0073EE42 /* View+Fixtures.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+Fixtures.swift"; sourceTree = "<group>"; };
|
37FD43E22704847C0073EE42 /* View+Fixtures.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+Fixtures.swift"; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
@ -653,7 +647,6 @@
|
|||||||
children = (
|
children = (
|
||||||
37484C2826FC83FF00287258 /* AccountFormView.swift */,
|
37484C2826FC83FF00287258 /* AccountFormView.swift */,
|
||||||
37484C2C26FC844700287258 /* AccountsSettingsView.swift */,
|
37484C2C26FC844700287258 /* AccountsSettingsView.swift */,
|
||||||
37FD43DD2704717F0073EE42 /* DefaultAccountHint.swift */,
|
|
||||||
37484C2426FC83E000287258 /* InstanceFormView.swift */,
|
37484C2426FC83E000287258 /* InstanceFormView.swift */,
|
||||||
37484C1C26FC83A400287258 /* InstancesSettingsView.swift */,
|
37484C1C26FC83A400287258 /* InstancesSettingsView.swift */,
|
||||||
37484C1826FC837400287258 /* PlaybackSettingsView.swift */,
|
37484C1826FC837400287258 /* PlaybackSettingsView.swift */,
|
||||||
@ -865,7 +858,6 @@
|
|||||||
37FD43E1270472060073EE42 /* Settings */ = {
|
37FD43E1270472060073EE42 /* Settings */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
37484C2026FC83C400287258 /* AccountSettingsView.swift */,
|
|
||||||
37FD43DB270470B70073EE42 /* InstancesSettingsView.swift */,
|
37FD43DB270470B70073EE42 /* InstancesSettingsView.swift */,
|
||||||
);
|
);
|
||||||
path = Settings;
|
path = Settings;
|
||||||
@ -1291,7 +1283,6 @@
|
|||||||
3748186626A7627F0084E870 /* Video+Fixtures.swift in Sources */,
|
3748186626A7627F0084E870 /* Video+Fixtures.swift in Sources */,
|
||||||
37BA794726DC2E56002A0235 /* AppSidebarSubscriptions.swift in Sources */,
|
37BA794726DC2E56002A0235 /* AppSidebarSubscriptions.swift in Sources */,
|
||||||
377FC7DC267A081800A6BBAF /* PopularView.swift in Sources */,
|
377FC7DC267A081800A6BBAF /* PopularView.swift in Sources */,
|
||||||
37FD43DE2704717F0073EE42 /* DefaultAccountHint.swift in Sources */,
|
|
||||||
37CC3F4C270CFE1700608308 /* PlayerQueueView.swift in Sources */,
|
37CC3F4C270CFE1700608308 /* PlayerQueueView.swift in Sources */,
|
||||||
3705B182267B4E4900704544 /* TrendingCategory.swift in Sources */,
|
3705B182267B4E4900704544 /* TrendingCategory.swift in Sources */,
|
||||||
3700155F271B12DD0049C794 /* SiestaConfiguration.swift in Sources */,
|
3700155F271B12DD0049C794 /* SiestaConfiguration.swift in Sources */,
|
||||||
@ -1372,7 +1363,6 @@
|
|||||||
37CEE4C22677B697005A1EFE /* Stream.swift in Sources */,
|
37CEE4C22677B697005A1EFE /* Stream.swift in Sources */,
|
||||||
371F2F1B269B43D300E4A7AB /* NavigationModel.swift in Sources */,
|
371F2F1B269B43D300E4A7AB /* NavigationModel.swift in Sources */,
|
||||||
37001564271B1F250049C794 /* AccountsModel.swift in Sources */,
|
37001564271B1F250049C794 /* AccountsModel.swift in Sources */,
|
||||||
37FD43DF2704717F0073EE42 /* DefaultAccountHint.swift in Sources */,
|
|
||||||
3761ABFE26F0F8DE00AA496F /* EnvironmentValues.swift in Sources */,
|
3761ABFE26F0F8DE00AA496F /* EnvironmentValues.swift in Sources */,
|
||||||
37BA795026DC3E0E002A0235 /* Int+Format.swift in Sources */,
|
37BA795026DC3E0E002A0235 /* Int+Format.swift in Sources */,
|
||||||
3743CA4F270EFE3400E4D32B /* PlayerQueueRow.swift in Sources */,
|
3743CA4F270EFE3400E4D32B /* PlayerQueueRow.swift in Sources */,
|
||||||
@ -1443,7 +1433,6 @@
|
|||||||
37BA794026DB8F97002A0235 /* ChannelVideosView.swift in Sources */,
|
37BA794026DB8F97002A0235 /* ChannelVideosView.swift in Sources */,
|
||||||
3711404026B206A6005B3555 /* SearchModel.swift in Sources */,
|
3711404026B206A6005B3555 /* SearchModel.swift in Sources */,
|
||||||
37484C2A26FC83FF00287258 /* AccountFormView.swift in Sources */,
|
37484C2A26FC83FF00287258 /* AccountFormView.swift in Sources */,
|
||||||
37484C2226FC83C400287258 /* AccountSettingsView.swift in Sources */,
|
|
||||||
37BE0BD026A0E2D50092E2DB /* VideoPlayerView.swift in Sources */,
|
37BE0BD026A0E2D50092E2DB /* VideoPlayerView.swift in Sources */,
|
||||||
373CFAEC26975CBF003CB2C6 /* PlaylistFormView.swift in Sources */,
|
373CFAEC26975CBF003CB2C6 /* PlaylistFormView.swift in Sources */,
|
||||||
37977584268922F600DD52A8 /* InvidiousAPI.swift in Sources */,
|
37977584268922F600DD52A8 /* InvidiousAPI.swift in Sources */,
|
||||||
@ -1477,7 +1466,6 @@
|
|||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
37FD43E02704717F0073EE42 /* DefaultAccountHint.swift in Sources */,
|
|
||||||
37AAF28026737550007FC770 /* SearchView.swift in Sources */,
|
37AAF28026737550007FC770 /* SearchView.swift in Sources */,
|
||||||
3788AC2D26F6842D00F6BAA9 /* WatchNowSectionBody.swift in Sources */,
|
3788AC2D26F6842D00F6BAA9 /* WatchNowSectionBody.swift in Sources */,
|
||||||
37EAD871267B9ED100D9E01B /* Segment.swift in Sources */,
|
37EAD871267B9ED100D9E01B /* Segment.swift in Sources */,
|
||||||
|
@ -1,12 +1,22 @@
|
|||||||
import Defaults
|
import Defaults
|
||||||
|
import Foundation
|
||||||
|
|
||||||
extension Defaults.Keys {
|
extension Defaults.Keys {
|
||||||
|
static let invidiousInstanceID = "default-invidious-instance"
|
||||||
|
static let pipedInstanceID = "default-piped-instance"
|
||||||
|
|
||||||
static let instances = Key<[Instance]>("instances", default: [
|
static let instances = Key<[Instance]>("instances", default: [
|
||||||
.init(app: .piped, name: "Public", url: "https://pipedapi.kavin.rocks"),
|
.init(app: .piped, id: pipedInstanceID, name: "Public", url: "https://pipedapi.kavin.rocks"),
|
||||||
.init(app: .invidious, name: "Private", url: "https://invidious.home.arekf.net")
|
.init(app: .invidious, id: invidiousInstanceID, name: "Private", url: "https://invidious.home.arekf.net")
|
||||||
])
|
])
|
||||||
static let accounts = Key<[Instance.Account]>("accounts", default: [])
|
static let accounts = Key<[Instance.Account]>("accounts", default: [
|
||||||
static let defaultAccountID = Key<String?>("defaultAccountID")
|
.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)
|
static let quality = Key<Stream.ResolutionSetting>("quality", default: .hd720pFirstThenBest)
|
||||||
|
|
||||||
|
@ -4,24 +4,29 @@ import SwiftUI
|
|||||||
struct AccountsMenuView: View {
|
struct AccountsMenuView: View {
|
||||||
@EnvironmentObject<AccountsModel> private var model
|
@EnvironmentObject<AccountsModel> private var model
|
||||||
|
|
||||||
|
@Default(.accounts) private var accounts
|
||||||
@Default(.instances) private var instances
|
@Default(.instances) private var instances
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Menu {
|
Menu {
|
||||||
ForEach(model.all, id: \.id) { account in
|
ForEach(allAccounts, id: \.id) { account in
|
||||||
Button(accountButtonTitle(account: account)) {
|
Button(accountButtonTitle(account: account)) {
|
||||||
model.setAccount(account)
|
model.setCurrent(account)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} label: {
|
} label: {
|
||||||
Label(model.account?.name ?? "Select Account", systemImage: "person.crop.circle")
|
Label(model.current?.name ?? "Select Account", systemImage: "person.crop.circle")
|
||||||
.labelStyle(.titleAndIcon)
|
.labelStyle(.titleAndIcon)
|
||||||
}
|
}
|
||||||
.disabled(instances.isEmpty)
|
.disabled(instances.isEmpty)
|
||||||
.transaction { t in t.animation = .none }
|
.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
|
instances.count > 1 ? "\(account.description) — \(account.instance.description)" : account.description
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,8 +62,8 @@ struct AppSidebarNavigation: View {
|
|||||||
.help(
|
.help(
|
||||||
"Switch Instances and Accounts\n" +
|
"Switch Instances and Accounts\n" +
|
||||||
"Current Instance: \n" +
|
"Current Instance: \n" +
|
||||||
"\(accounts.account?.url ?? "Not Set")\n" +
|
"\(accounts.current?.url ?? "Not Set")\n" +
|
||||||
"Current User: \(accounts.account?.description ?? "Not set")"
|
"Current User: \(accounts.current?.description ?? "Not set")"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,15 +85,17 @@ struct ContentView: View {
|
|||||||
SiestaLog.Category.enabled = .common
|
SiestaLog.Category.enabled = .common
|
||||||
|
|
||||||
// TODO: Remove when piped supports videos information
|
// TODO: Remove when piped supports videos information
|
||||||
if let account = instances.defaultAccount ??
|
if let account = accounts.lastUsed ??
|
||||||
accounts.all.first(where: { $0.instance.app == .invidious })
|
instances.lastUsed?.anonymousAccount ??
|
||||||
|
instances.all.first?.anonymousAccount
|
||||||
{
|
{
|
||||||
accounts.setAccount(account)
|
accounts.setCurrent(account)
|
||||||
}
|
}
|
||||||
|
|
||||||
if accounts.account.isNil {
|
if accounts.current.isNil {
|
||||||
navigation.presentingWelcomeScreen = true
|
navigation.presentingWelcomeScreen = true
|
||||||
}
|
}
|
||||||
|
|
||||||
player.accounts = accounts
|
player.accounts = accounts
|
||||||
playlists.accounts = accounts
|
playlists.accounts = accounts
|
||||||
search.accounts = accounts
|
search.accounts = accounts
|
||||||
@ -101,7 +103,7 @@ struct ContentView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func openWelcomeScreenIfAccountEmpty() {
|
func openWelcomeScreenIfAccountEmpty() {
|
||||||
guard accounts.isEmpty else {
|
guard Defaults[.instances].isEmpty else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,6 @@ struct PearvidiousApp: App {
|
|||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
Settings {
|
Settings {
|
||||||
SettingsView()
|
SettingsView()
|
||||||
.environmentObject(InvidiousAPI())
|
|
||||||
.environmentObject(InstancesModel())
|
.environmentObject(InstancesModel())
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -122,8 +122,7 @@ struct VideoPlayerView: View {
|
|||||||
VStack(spacing: 10) {
|
VStack(spacing: 10) {
|
||||||
#if !os(tvOS)
|
#if !os(tvOS)
|
||||||
Image(systemName: "ticket")
|
Image(systemName: "ticket")
|
||||||
.font(.system(size: 80))
|
.font(.system(size: 120))
|
||||||
Text("What are we watching next?")
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
Spacer()
|
Spacer()
|
||||||
|
@ -124,7 +124,7 @@ struct AccountFormView: View {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let account = instances.addAccount(instance: instance, name: name, sid: sid)
|
let account = AccountsModel.add(instance: instance, name: name, sid: sid)
|
||||||
selectedAccount?.wrappedValue = account
|
selectedAccount?.wrappedValue = account
|
||||||
|
|
||||||
dismiss()
|
dismiss()
|
||||||
|
@ -6,10 +6,11 @@ struct AccountsSettingsView: View {
|
|||||||
@State private var accountsChanged = false
|
@State private var accountsChanged = false
|
||||||
@State private var presentingAccountForm = false
|
@State private var presentingAccountForm = false
|
||||||
|
|
||||||
|
@EnvironmentObject<AccountsModel> private var model
|
||||||
@EnvironmentObject<InstancesModel> private var instances
|
@EnvironmentObject<InstancesModel> private var instances
|
||||||
|
|
||||||
var instance: Instance! {
|
var instance: Instance! {
|
||||||
instances.find(instanceID)
|
InstancesModel.find(instanceID)
|
||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
@ -27,41 +28,18 @@ struct AccountsSettingsView: View {
|
|||||||
var accounts: some View {
|
var accounts: some View {
|
||||||
List {
|
List {
|
||||||
Section(header: Text("Accounts"), footer: sectionFooter) {
|
Section(header: Text("Accounts"), footer: sectionFooter) {
|
||||||
ForEach(instances.accounts(instanceID), id: \.self) { account in
|
ForEach(InstancesModel.accounts(instanceID), id: \.self) { account in
|
||||||
#if os(iOS)
|
#if os(tvOS)
|
||||||
HStack(spacing: 2) {
|
Button(account.description) {}
|
||||||
Text(account.description)
|
.contextMenu {
|
||||||
if instances.defaultAccount == account {
|
Button("Remove", role: .destructive) { removeAccount(account) }
|
||||||
Text("— default")
|
Button("Cancel", role: .cancel) {}
|
||||||
.foregroundColor(.secondary)
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
.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
|
#else
|
||||||
Button(action: { toggleDefault(account) }) {
|
Text(account.description)
|
||||||
HStack(spacing: 2) {
|
.swipeActions(edge: .trailing, allowsFullSwipe: false) {
|
||||||
Text(account.description)
|
Button("Remove", role: .destructive) { removeAccount(account) }
|
||||||
if instances.defaultAccount == account {
|
|
||||||
Text("— default")
|
|
||||||
.foregroundColor(.secondary)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
.contextMenu {
|
|
||||||
Button("Toggle Default") { toggleDefault(account) }
|
|
||||||
Button("Remove", role: .destructive) { removeAccount(account) }
|
|
||||||
Button("Cancel", role: .cancel) {}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
.redrawOn(change: accountsChanged)
|
.redrawOn(change: accountsChanged)
|
||||||
@ -83,33 +61,15 @@ struct AccountsSettingsView: View {
|
|||||||
|
|
||||||
private var sectionFooter: some View {
|
private var sectionFooter: some View {
|
||||||
#if os(iOS)
|
#if os(iOS)
|
||||||
Text("Swipe right to toggle default account, swipe left to remove")
|
Text("Swipe to remove account")
|
||||||
#else
|
#else
|
||||||
Text("Tap to toggle default account, tap and hold to remove")
|
Text("Tap and hold to remove account")
|
||||||
.foregroundColor(.secondary)
|
.foregroundColor(.secondary)
|
||||||
#endif
|
#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) {
|
private func removeAccount(_ account: Instance.Account) {
|
||||||
instances.removeAccount(account)
|
AccountsModel.remove(account)
|
||||||
accountsChanged.toggle()
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
savedInstanceID = instancesModel.add(app: app, name: name, url: url).id
|
savedInstanceID = InstancesModel.add(app: app, name: name, url: url).id
|
||||||
|
|
||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ struct InstancesSettingsView: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Group {
|
Group {
|
||||||
Section(header: Text("Instances"), footer: DefaultAccountHint()) {
|
Section(header: Text("Instances")) {
|
||||||
ForEach(instances) { instance in
|
ForEach(instances) { instance in
|
||||||
Group {
|
Group {
|
||||||
NavigationLink(instance.longDescription) {
|
NavigationLink(instance.longDescription) {
|
||||||
@ -55,16 +55,12 @@ struct InstancesSettingsView: View {
|
|||||||
|
|
||||||
private func removeInstanceButton(_ instance: Instance) -> some View {
|
private func removeInstanceButton(_ instance: Instance) -> some View {
|
||||||
Button("Remove", role: .destructive) {
|
Button("Remove", role: .destructive) {
|
||||||
if accounts.account?.instance == instance {
|
if accounts.current?.instance == instance {
|
||||||
accounts.setAccount(nil)
|
accounts.setCurrent(nil)
|
||||||
}
|
}
|
||||||
instancesModel.remove(instance)
|
InstancesModel.remove(instance)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func resetDefaultAccount() {
|
|
||||||
instancesModel.resetDefaultAccount()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct InstancesSettingsView_Previews: PreviewProvider {
|
struct InstancesSettingsView_Previews: PreviewProvider {
|
||||||
|
@ -21,7 +21,7 @@ struct SubscriptionsView: View {
|
|||||||
.onAppear {
|
.onAppear {
|
||||||
loadResources()
|
loadResources()
|
||||||
}
|
}
|
||||||
.onChange(of: accounts.account) { _ in
|
.onChange(of: accounts.current) { _ in
|
||||||
loadResources(force: true)
|
loadResources(force: true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,10 @@ struct VideoContextMenuView: View {
|
|||||||
removeFromPlaylistButton(playlistID: id)
|
removeFromPlaylistButton(playlistID: id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if os(tvOS)
|
||||||
|
Button("Cancel", role: .cancel) {}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
var playNowButton: some View {
|
var playNowButton: some View {
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import Defaults
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct WelcomeScreen: View {
|
struct WelcomeScreen: View {
|
||||||
@ -6,6 +7,8 @@ struct WelcomeScreen: View {
|
|||||||
@EnvironmentObject<AccountsModel> private var accounts
|
@EnvironmentObject<AccountsModel> private var accounts
|
||||||
@EnvironmentObject<NavigationModel> private var navigation
|
@EnvironmentObject<NavigationModel> private var navigation
|
||||||
|
|
||||||
|
@Default(.accounts) private var allAccounts
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack {
|
VStack {
|
||||||
Spacer()
|
Spacer()
|
||||||
@ -14,7 +17,7 @@ struct WelcomeScreen: View {
|
|||||||
.font(.largeTitle)
|
.font(.largeTitle)
|
||||||
.padding(.bottom, 10)
|
.padding(.bottom, 10)
|
||||||
|
|
||||||
if accounts.all.isEmpty {
|
if allAccounts.isEmpty {
|
||||||
Text("To start, configure your Instances in Settings")
|
Text("To start, configure your Instances in Settings")
|
||||||
.foregroundColor(.secondary)
|
.foregroundColor(.secondary)
|
||||||
} else {
|
} else {
|
||||||
@ -28,12 +31,12 @@ struct WelcomeScreen: View {
|
|||||||
} label: {
|
} label: {
|
||||||
Text("Start")
|
Text("Start")
|
||||||
}
|
}
|
||||||
.opacity(accounts.account.isNil ? 0 : 1)
|
.opacity(accounts.current.isNil ? 0 : 1)
|
||||||
.disabled(accounts.account.isNil)
|
.disabled(accounts.current.isNil)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
AccountsMenuView()
|
AccountsMenuView()
|
||||||
.onChange(of: accounts.account) { _ in
|
.onChange(of: accounts.current) { _ in
|
||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
|
@ -21,7 +21,7 @@ struct WatchNowSection: View {
|
|||||||
resource.addObserver(store)
|
resource.addObserver(store)
|
||||||
resource.loadIfNeeded()
|
resource.loadIfNeeded()
|
||||||
}
|
}
|
||||||
.onChange(of: accounts.account) { _ in
|
.onChange(of: accounts.current) { _ in
|
||||||
resource.load()
|
resource.load()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ struct WatchNowView: View {
|
|||||||
var body: some View {
|
var body: some View {
|
||||||
PlayerControlsView {
|
PlayerControlsView {
|
||||||
ScrollView(.vertical, showsIndicators: false) {
|
ScrollView(.vertical, showsIndicators: false) {
|
||||||
if !accounts.account.isNil {
|
if !accounts.current.isNil {
|
||||||
VStack(alignment: .leading, spacing: 0) {
|
VStack(alignment: .leading, spacing: 0) {
|
||||||
if api.signedIn {
|
if api.signedIn {
|
||||||
WatchNowSection(resource: api.feed, label: "Subscriptions")
|
WatchNowSection(resource: api.feed, label: "Subscriptions")
|
||||||
|
@ -1,54 +0,0 @@
|
|||||||
import Defaults
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
struct AccountSettingsView: View {
|
|
||||||
let account: Instance.Account
|
|
||||||
@Binding var selectedAccount: Instance.Account?
|
|
||||||
|
|
||||||
@State private var presentingRemovalConfirmationDialog = false
|
|
||||||
|
|
||||||
@EnvironmentObject<InstancesModel> private var instances
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
HStack {
|
|
||||||
HStack(spacing: 2) {
|
|
||||||
Text(account.description)
|
|
||||||
if instances.defaultAccount == account {
|
|
||||||
Text("— default")
|
|
||||||
.foregroundColor(.secondary)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Spacer()
|
|
||||||
|
|
||||||
HStack {
|
|
||||||
if instances.defaultAccount != account {
|
|
||||||
Button("Make default", action: makeDefault)
|
|
||||||
} else {
|
|
||||||
Button("Reset default", action: resetDefault)
|
|
||||||
}
|
|
||||||
Button("Remove", role: .destructive) {
|
|
||||||
presentingRemovalConfirmationDialog = true
|
|
||||||
}
|
|
||||||
.confirmationDialog(
|
|
||||||
"Are you sure you want to remove \(account.description) account?",
|
|
||||||
isPresented: $presentingRemovalConfirmationDialog
|
|
||||||
) {
|
|
||||||
Button("Remove", role: .destructive) {
|
|
||||||
instances.removeAccount(account)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.foregroundColor(.red)
|
|
||||||
}
|
|
||||||
.opacity(account == selectedAccount ? 1 : 0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func makeDefault() {
|
|
||||||
instances.setDefaultAccount(account)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func resetDefault() {
|
|
||||||
instances.resetDefaultAccount()
|
|
||||||
}
|
|
||||||
}
|
|
@ -9,7 +9,8 @@ struct InstancesSettingsView: View {
|
|||||||
@State private var presentingInstanceForm = false
|
@State private var presentingInstanceForm = false
|
||||||
@State private var savedFormInstanceID: Instance.ID?
|
@State private var savedFormInstanceID: Instance.ID?
|
||||||
|
|
||||||
@State private var presentingConfirmationDialog = false
|
@State private var presentingAccountRemovalConfirmation = false
|
||||||
|
@State private var presentingInstanceRemovalConfirmation = false
|
||||||
|
|
||||||
@EnvironmentObject<AccountsModel> private var accounts
|
@EnvironmentObject<AccountsModel> private var accounts
|
||||||
@EnvironmentObject<InstancesModel> private var model
|
@EnvironmentObject<InstancesModel> private var model
|
||||||
@ -41,8 +42,26 @@ struct InstancesSettingsView: View {
|
|||||||
.foregroundColor(.secondary)
|
.foregroundColor(.secondary)
|
||||||
}
|
}
|
||||||
ForEach(selectedInstanceAccounts) { account in
|
ForEach(selectedInstanceAccounts) { account in
|
||||||
AccountSettingsView(account: account, selectedAccount: $selectedAccount)
|
HStack {
|
||||||
.tag(account)
|
Text(account.description)
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
Button("Remove", role: .destructive) {
|
||||||
|
presentingAccountRemovalConfirmation = true
|
||||||
|
}
|
||||||
|
.foregroundColor(.red)
|
||||||
|
.opacity(account == selectedAccount ? 1 : 0)
|
||||||
|
}
|
||||||
|
.tag(account)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.confirmationDialog(
|
||||||
|
"Are you sure you want to remove \(selectedAccount?.description ?? "") account?",
|
||||||
|
isPresented: $presentingAccountRemovalConfirmation
|
||||||
|
) {
|
||||||
|
Button("Remove", role: .destructive) {
|
||||||
|
AccountsModel.remove(selectedAccount!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.listStyle(.inset(alternatesRowBackgrounds: true))
|
.listStyle(.inset(alternatesRowBackgrounds: true))
|
||||||
@ -58,28 +77,27 @@ struct InstancesSettingsView: View {
|
|||||||
|
|
||||||
if selectedInstance != nil {
|
if selectedInstance != nil {
|
||||||
HStack {
|
HStack {
|
||||||
if selectedInstance.supportsAccounts {
|
Button("Add Account...") {
|
||||||
Button("Add Account...") {
|
selectedAccount = nil
|
||||||
selectedAccount = nil
|
presentingAccountForm = true
|
||||||
presentingAccountForm = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
.disabled(!selectedInstance.supportsAccounts)
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
Button("Remove Instance", role: .destructive) {
|
Button("Remove Instance", role: .destructive) {
|
||||||
presentingConfirmationDialog = true
|
presentingInstanceRemovalConfirmation = true
|
||||||
}
|
}
|
||||||
.confirmationDialog(
|
.confirmationDialog(
|
||||||
"Are you sure you want to remove \(selectedInstance!.longDescription) instance?",
|
"Are you sure you want to remove \(selectedInstance!.longDescription) instance?",
|
||||||
isPresented: $presentingConfirmationDialog
|
isPresented: $presentingInstanceRemovalConfirmation
|
||||||
) {
|
) {
|
||||||
Button("Remove Instance", role: .destructive) {
|
Button("Remove Instance", role: .destructive) {
|
||||||
if accounts.account?.instance == selectedInstance {
|
if accounts.current?.instance == selectedInstance {
|
||||||
accounts.setAccount(nil)
|
accounts.setCurrent(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
model.remove(selectedInstance!)
|
InstancesModel.remove(selectedInstance!)
|
||||||
selectedInstanceID = instances.last?.id
|
selectedInstanceID = instances.last?.id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -91,9 +109,6 @@ struct InstancesSettingsView: View {
|
|||||||
Button("Add Instance...") {
|
Button("Add Instance...") {
|
||||||
presentingInstanceForm = true
|
presentingInstanceForm = true
|
||||||
}
|
}
|
||||||
|
|
||||||
DefaultAccountHint()
|
|
||||||
.padding(.top, 10)
|
|
||||||
}
|
}
|
||||||
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
|
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
|
||||||
|
|
||||||
@ -116,7 +131,7 @@ struct InstancesSettingsView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var selectedInstance: Instance! {
|
var selectedInstance: Instance! {
|
||||||
model.find(selectedInstanceID)
|
InstancesModel.find(selectedInstanceID)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var selectedInstanceAccounts: [Instance.Account] {
|
private var selectedInstanceAccounts: [Instance.Account] {
|
||||||
@ -124,7 +139,7 @@ struct InstancesSettingsView: View {
|
|||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
return model.accounts(selectedInstanceID)
|
return InstancesModel.accounts(selectedInstanceID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,22 +6,23 @@ struct AccountSelectionView: View {
|
|||||||
var showHeader = true
|
var showHeader = true
|
||||||
|
|
||||||
@EnvironmentObject<InstancesModel> private var instancesModel
|
@EnvironmentObject<InstancesModel> private var instancesModel
|
||||||
@EnvironmentObject<AccountsModel> private var accounts
|
@EnvironmentObject<AccountsModel> private var accountsModel
|
||||||
|
|
||||||
|
@Default(.accounts) private var accounts
|
||||||
@Default(.instances) private var instances
|
@Default(.instances) private var instances
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Section(header: Text(showHeader ? "Current Account" : "")) {
|
Section(header: Text(showHeader ? "Current Account" : "")) {
|
||||||
Button(accountButtonTitle(account: accounts.account)) {
|
Button(accountButtonTitle(account: accountsModel.current)) {
|
||||||
if let account = nextAccount {
|
if let account = nextAccount {
|
||||||
accounts.setAccount(account)
|
accountsModel.setCurrent(account)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.disabled(instances.isEmpty)
|
.disabled(instances.isEmpty)
|
||||||
.contextMenu {
|
.contextMenu {
|
||||||
ForEach(accounts.all) { account in
|
ForEach(allAccounts) { account in
|
||||||
Button(accountButtonTitle(account: account)) {
|
Button(accountButtonTitle(account: account)) {
|
||||||
accounts.setAccount(account)
|
accountsModel.setCurrent(account)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,8 +32,12 @@ struct AccountSelectionView: View {
|
|||||||
.id(UUID())
|
.id(UUID())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var allAccounts: [Instance.Account] {
|
||||||
|
accounts + instances.map(\.anonymousAccount)
|
||||||
|
}
|
||||||
|
|
||||||
private var nextAccount: Instance.Account? {
|
private var nextAccount: Instance.Account? {
|
||||||
accounts.all.next(after: accounts.account)
|
allAccounts.next(after: accountsModel.current)
|
||||||
}
|
}
|
||||||
|
|
||||||
func accountButtonTitle(account: Instance.Account! = nil) -> String {
|
func accountButtonTitle(account: Instance.Account! = nil) -> String {
|
||||||
|
Loading…
Reference in New Issue
Block a user