Unify DashboardViewModel instances
This commit is contained in:
@@ -7,7 +7,7 @@ import SwiftUI
|
|||||||
@Environment(\.scenePhase) private var scenePhase
|
@Environment(\.scenePhase) private var scenePhase
|
||||||
@EnvironmentObject private var environments: ExtensionEnvironments
|
@EnvironmentObject private var environments: ExtensionEnvironments
|
||||||
@EnvironmentObject private var profile: ExtensionProfile
|
@EnvironmentObject private var profile: ExtensionProfile
|
||||||
@StateObject private var coordinator = DashboardViewModel()
|
@ObservedObject private var coordinator: DashboardViewModel
|
||||||
@State private var cardConfigurationVersion = 0
|
@State private var cardConfigurationVersion = 0
|
||||||
#if os(iOS) || os(tvOS)
|
#if os(iOS) || os(tvOS)
|
||||||
@State private var showCardManagement = false
|
@State private var showCardManagement = false
|
||||||
@@ -18,20 +18,25 @@ import SwiftUI
|
|||||||
|
|
||||||
private let externalCardConfigurationVersion: Int?
|
private let externalCardConfigurationVersion: Int?
|
||||||
|
|
||||||
public init(externalCardConfigurationVersion: Int? = nil) {
|
public init(coordinator: DashboardViewModel, externalCardConfigurationVersion: Int? = nil) {
|
||||||
|
_coordinator = ObservedObject(wrappedValue: coordinator)
|
||||||
self.externalCardConfigurationVersion = externalCardConfigurationVersion
|
self.externalCardConfigurationVersion = externalCardConfigurationVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
public var body: some View {
|
public var body: some View {
|
||||||
|
viewContent
|
||||||
|
}
|
||||||
|
|
||||||
|
@ViewBuilder private var viewContent: some View {
|
||||||
if coordinator.isLoading {
|
if coordinator.isLoading {
|
||||||
ProgressView().onAppear {
|
ProgressView()
|
||||||
coordinator.onEmptyProfilesChange = {
|
#if os(iOS) || os(tvOS)
|
||||||
environments.emptyProfiles = $0
|
.onAppear {
|
||||||
|
Task {
|
||||||
|
await coordinator.reload()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Task {
|
#endif
|
||||||
await coordinator.reload()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
content.onAppear {
|
content.onAppear {
|
||||||
guard !ApplicationLibrary.inPreview, profile.status.isConnected else {
|
guard !ApplicationLibrary.inPreview, profile.status.isConnected else {
|
||||||
@@ -40,8 +45,7 @@ import SwiftUI
|
|||||||
Task {
|
Task {
|
||||||
await coordinator.reloadSystemProxy()
|
await coordinator.reloadSystemProxy()
|
||||||
}
|
}
|
||||||
}.onChangeCompat(of: profile.status) {
|
}.onChangeCompat(of: profile.status) { status in
|
||||||
status in
|
|
||||||
guard !ApplicationLibrary.inPreview, status == .connected else {
|
guard !ApplicationLibrary.inPreview, status == .connected else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -77,25 +81,21 @@ import SwiftUI
|
|||||||
} else {
|
} else {
|
||||||
environments.connect()
|
environments.connect()
|
||||||
}
|
}
|
||||||
}.onChangeCompat(of: scenePhase) {
|
}.onChangeCompat(of: scenePhase) { phase in
|
||||||
phase in
|
|
||||||
guard phase == .active else {
|
guard phase == .active else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
environments.connect()
|
environments.connect()
|
||||||
}.onChangeCompat(of: profile.status) {
|
}.onChangeCompat(of: profile.status) { status in
|
||||||
status in
|
|
||||||
guard status.isConnected else {
|
guard status.isConnected else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
environments.connect()
|
environments.connect()
|
||||||
}.onReceive(environments.profileUpdate) {
|
}.onReceive(environments.profileUpdate) { _ in
|
||||||
_ in
|
|
||||||
Task {
|
Task {
|
||||||
await coordinator.reload()
|
await coordinator.reload()
|
||||||
}
|
}
|
||||||
}.onReceive(environments.selectedProfileUpdate) {
|
}.onReceive(environments.selectedProfileUpdate) { _ in
|
||||||
_ in
|
|
||||||
Task {
|
Task {
|
||||||
await coordinator.updateSelectedProfile()
|
await coordinator.updateSelectedProfile()
|
||||||
if profile.status.isConnected {
|
if profile.status.isConnected {
|
||||||
@@ -104,20 +104,16 @@ import SwiftUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if os(iOS) || os(tvOS)
|
#if os(iOS) || os(tvOS)
|
||||||
.onReceive(environments.commandClient.$groups) {
|
.onReceive(environments.commandClient.$groups) { _ in
|
||||||
_ in
|
|
||||||
updateButtonVisibility()
|
updateButtonVisibility()
|
||||||
}.onReceive(environments.commandClient.$connections) {
|
}.onReceive(environments.commandClient.$connections) { _ in
|
||||||
_ in
|
|
||||||
updateButtonVisibility()
|
updateButtonVisibility()
|
||||||
}.onReceive(profile.$status) {
|
}.onReceive(profile.$status) { _ in
|
||||||
_ in
|
|
||||||
updateButtonVisibility()
|
updateButtonVisibility()
|
||||||
}.onAppear {
|
}.onAppear {
|
||||||
updateButtonVisibility()
|
updateButtonVisibility()
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
.alert($coordinator.alert)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ViewBuilder private var overviewPage: some View {
|
@ViewBuilder private var overviewPage: some View {
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ public struct DashboardView: View {
|
|||||||
content
|
content
|
||||||
.onAppear {
|
.onAppear {
|
||||||
coordinator.setOpenURL { openURL($0) }
|
coordinator.setOpenURL { openURL($0) }
|
||||||
|
coordinator.setEnvironments(environments)
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
Task { await coordinator.reload() }
|
Task { await coordinator.reload() }
|
||||||
#endif
|
#endif
|
||||||
@@ -133,9 +134,9 @@ public struct DashboardView: View {
|
|||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
private var activeDashboardView: some View {
|
private var activeDashboardView: some View {
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
ActiveDashboardView(externalCardConfigurationVersion: cardConfigurationVersion)
|
ActiveDashboardView(coordinator: coordinator, externalCardConfigurationVersion: cardConfigurationVersion)
|
||||||
#else
|
#else
|
||||||
ActiveDashboardView()
|
ActiveDashboardView(coordinator: coordinator)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,9 +17,13 @@ public final class DashboardViewModel: BaseViewModel {
|
|||||||
@Published public var systemExtensionInstalled = true
|
@Published public var systemExtensionInstalled = true
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public var onEmptyProfilesChange: ((Bool) -> Void)?
|
private weak var environments: ExtensionEnvironments?
|
||||||
private var openURL: ((URL) -> Void)?
|
private var openURL: ((URL) -> Void)?
|
||||||
|
|
||||||
|
public func setEnvironments(_ environments: ExtensionEnvironments) {
|
||||||
|
self.environments = environments
|
||||||
|
}
|
||||||
|
|
||||||
override public init() {
|
override public init() {
|
||||||
super.init()
|
super.init()
|
||||||
isLoading = true
|
isLoading = true
|
||||||
@@ -55,7 +59,7 @@ public final class DashboardViewModel: BaseViewModel {
|
|||||||
do {
|
do {
|
||||||
profileList = try await ProfileManager.list().map { ProfilePreview($0) }
|
profileList = try await ProfileManager.list().map { ProfilePreview($0) }
|
||||||
guard !profileList.isEmpty else {
|
guard !profileList.isEmpty else {
|
||||||
onEmptyProfilesChange?(true)
|
environments?.emptyProfiles = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,7 +73,7 @@ public final class DashboardViewModel: BaseViewModel {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onEmptyProfilesChange?(profileList.isEmpty)
|
environments?.emptyProfiles = profileList.isEmpty
|
||||||
}
|
}
|
||||||
|
|
||||||
public func reloadSystemProxy() async {
|
public func reloadSystemProxy() async {
|
||||||
|
|||||||
@@ -10,13 +10,12 @@ import SwiftUI
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
public class LogViewModel: ObservableObject {
|
public class LogViewModel: BaseViewModel {
|
||||||
@Published public var selectedLogLevel: Int?
|
@Published public var selectedLogLevel: Int?
|
||||||
@Published public var isPaused = false
|
@Published public var isPaused = false
|
||||||
@Published public var searchText = ""
|
@Published public var searchText = ""
|
||||||
@Published public var isSearching = false
|
@Published public var isSearching = false
|
||||||
@Published public var filteredLogs: [LogEntry] = []
|
@Published public var filteredLogs: [LogEntry] = []
|
||||||
@Published public var alert: AlertState?
|
|
||||||
@Published public var showFileExporter = false
|
@Published public var showFileExporter = false
|
||||||
@Published public var logFileURL: URL?
|
@Published public var logFileURL: URL?
|
||||||
|
|
||||||
@@ -42,6 +41,7 @@ public class LogViewModel: ObservableObject {
|
|||||||
|
|
||||||
public init(commandClient: CommandClient) {
|
public init(commandClient: CommandClient) {
|
||||||
self.commandClient = commandClient
|
self.commandClient = commandClient
|
||||||
|
super.init()
|
||||||
|
|
||||||
let debouncedSearchText = $searchText
|
let debouncedSearchText = $searchText
|
||||||
.debounce(for: .milliseconds(300), scheduler: DispatchQueue.main)
|
.debounce(for: .milliseconds(300), scheduler: DispatchQueue.main)
|
||||||
|
|||||||
@@ -3,10 +3,13 @@ import Library
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
final class ServiceLogViewModel: ObservableObject {
|
final class ServiceLogViewModel: BaseViewModel {
|
||||||
@Published var isLoading = true
|
|
||||||
@Published var content = ""
|
@Published var content = ""
|
||||||
@Published var alert: AlertState?
|
|
||||||
|
override init() {
|
||||||
|
super.init()
|
||||||
|
isLoading = true
|
||||||
|
}
|
||||||
|
|
||||||
var isEmpty: Bool {
|
var isEmpty: Bool {
|
||||||
content.isEmpty
|
content.isEmpty
|
||||||
|
|||||||
@@ -2,10 +2,14 @@ import Library
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
final class SettingViewModel: ObservableObject {
|
final class SettingViewModel: BaseViewModel {
|
||||||
@Published var isLoading = true
|
|
||||||
@Published var taiwanFlagAvailable = false
|
@Published var taiwanFlagAvailable = false
|
||||||
|
|
||||||
|
override init() {
|
||||||
|
super.init()
|
||||||
|
isLoading = true
|
||||||
|
}
|
||||||
|
|
||||||
nonisolated func checkTaiwanFlagAvailability() async {
|
nonisolated func checkTaiwanFlagAvailability() async {
|
||||||
let available: Bool
|
let available: Bool
|
||||||
if ApplicationLibrary.inPreview {
|
if ApplicationLibrary.inPreview {
|
||||||
|
|||||||
@@ -5,13 +5,10 @@ import Library
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
public class MainViewModel: ObservableObject {
|
public class MainViewModel: BaseViewModel {
|
||||||
@Published public var selection = NavigationPage.dashboard
|
@Published public var selection = NavigationPage.dashboard
|
||||||
@Published public var importProfile: LibboxProfileContent?
|
@Published public var importProfile: LibboxProfileContent?
|
||||||
@Published public var importRemoteProfile: LibboxImportRemoteProfile?
|
@Published public var importRemoteProfile: LibboxImportRemoteProfile?
|
||||||
@Published public var alert: AlertState?
|
|
||||||
|
|
||||||
public init() {}
|
|
||||||
|
|
||||||
public func onAppear(environments: ExtensionEnvironments) {
|
public func onAppear(environments: ExtensionEnvironments) {
|
||||||
environments.postReload()
|
environments.postReload()
|
||||||
|
|||||||
Reference in New Issue
Block a user