This commit is contained in:
世界
2023-10-02 22:12:33 +08:00
parent c1c4f084b9
commit c5a29e0956
16 changed files with 256 additions and 247 deletions
@@ -7,17 +7,15 @@ public struct EditProfileView: View {
@Environment(\.openWindow) private var openWindow
#endif
@EnvironmentObject private var environments: ExtensionEnvironments
@Environment(\.dismiss) private var dismiss
@EnvironmentObject private var profile: Profile
@State private var isLoading = false
@State private var isChanged = false
@State private var alert: Alert?
private let updateCallback: (() -> Void)?
public init(_ updateCallback: (() -> Void)? = nil) {
self.updateCallback = updateCallback
}
public init() {}
public var body: some View {
FormView {
FormItem("Name") {
@@ -170,7 +168,7 @@ public struct EditProfileView: View {
do {
try await Task.sleep(nanoseconds: UInt64(100 * Double(NSEC_PER_MSEC)))
try await profile.updateRemoteProfile()
await performCallback()
environments.profileUpdate.send()
} catch {
alert = Alert(error)
}
@@ -183,7 +181,7 @@ public struct EditProfileView: View {
alert = Alert(error)
return
}
await performCallback()
environments.profileUpdate.send()
dismiss()
}
@@ -201,14 +199,6 @@ public struct EditProfileView: View {
}
isChanged = false
isLoading = false
await performCallback()
}
private func performCallback() async {
if let updateCallback {
updateCallback()
} else {
NotificationCenter.default.post(name: ProfileView.notificationName, object: nil)
}
environments.profileUpdate.send()
}
}
@@ -9,6 +9,7 @@ public struct NewProfileView: View {
public static let windowID = "new-profile"
#endif
@EnvironmentObject private var environments: ExtensionEnvironments
@Environment(\.dismiss) private var dismiss
@State private var isSaving = false
@@ -27,9 +28,7 @@ public struct NewProfileView: View {
public let url: String
}
private let callback: (() async -> Void)?
public init(_ importRequest: ImportRequest? = nil, _ callback: (() async -> Void)? = nil) {
self.callback = callback
public init(_ importRequest: ImportRequest? = nil) {
if let importRequest {
_profileName = .init(initialValue: importRequest.name)
_profileType = .init(initialValue: .remote)
@@ -156,12 +155,9 @@ public struct NewProfileView: View {
alert = Alert(error)
return
}
if let callback {
await callback()
}
environments.profileUpdate.send()
dismiss()
#if os(macOS)
NotificationCenter.default.post(name: ProfileView.notificationName, object: nil)
resetFields()
#endif
}
@@ -6,8 +6,7 @@ import SwiftUI
@MainActor
public struct ProfileView: View {
public static let notificationName = Notification.Name("\(FilePath.packageName).update-profile")
@EnvironmentObject private var environments: ExtensionEnvironments
@Environment(\.importProfile) private var importProfile
@Environment(\.importRemoteProfile) private var importRemoteProfile
@State private var importRemoteProfileRequest: NewProfileView.ImportRequest?
@@ -17,7 +16,7 @@ public struct ProfileView: View {
@State private var isUpdating = false
@State private var alert: Alert?
@State private var profileList: [Profile] = []
@State private var profileList: [ProfilePreview] = []
#if os(iOS) || os(tvOS)
@State private var editMode = EditMode.inactive
@@ -29,10 +28,7 @@ public struct ProfileView: View {
@Environment(\.devicePickerSupports) private var devicePickerSupports
#endif
@State private var observer: Any?
public init() {}
public var body: some View {
VStack {
if isLoading {
@@ -46,17 +42,13 @@ public struct ProfileView: View {
ZStack {
if let importRemoteProfileRequest {
NavigationDestinationCompat(isPresented: $importRemoteProfilePresented) {
NewProfileView(importRemoteProfileRequest) {
await doReload()
}
NewProfileView(importRemoteProfileRequest)
}
}
FormView {
#if os(iOS)
NavigationLink {
NewProfileView {
await doReload()
}
NewProfileView()
} label: {
Text("New Profile").foregroundColor(.accentColor)
}
@@ -64,9 +56,7 @@ public struct ProfileView: View {
#elseif os(tvOS)
Section {
NavigationLink {
NewProfileView {
await doReload()
}
NewProfileView()
} label: {
Text("New Profile").foregroundColor(.accentColor)
}
@@ -85,7 +75,7 @@ public struct ProfileView: View {
Text("Empty profiles")
} else {
List {
ForEach(profileList, id: \.mustID) { profile in
ForEach(profileList, id: \.id) { profile in
viewBuilder {
if editMode.isEditing == true {
Text(profile.name)
@@ -106,7 +96,7 @@ public struct ProfileView: View {
} else {
FormView {
List {
ForEach(profileList, id: \.mustID) { profile in
ForEach(profileList, id: \.id) { profile in
ProfileItem(self, profile)
}
.onMove(perform: moveProfile)
@@ -128,15 +118,6 @@ public struct ProfileView: View {
importRemoteProfile.wrappedValue = nil
createImportRemoteProfileDialog(remoteProfile)
}
#if os(macOS)
if observer == nil {
observer = NotificationCenter.default.addObserver(forName: ProfileView.notificationName, object: nil, queue: .main) { _ in
Task {
await doReload()
}
}
}
#endif
}
.onChangeCompat(of: importProfile.wrappedValue) { newValue in
if let newValue {
@@ -150,23 +131,14 @@ public struct ProfileView: View {
createImportRemoteProfileDialog(newValue)
}
}
#if os(macOS)
.onDisappear {
if let observer {
NotificationCenter.default.removeObserver(observer)
}
observer = nil
.onReceive(environments.profileUpdate) { _ in
profileList = []
isLoading = true
// not updated, but why?
// Task {
// await doReload()
// }
}
.toolbar {
ToolbarItem {
Button {
openWindow(id: NewProfileView.windowID)
} label: {
Label("New Profile", systemImage: "plus.square.fill")
}
}
}
#endif
#if os(iOS)
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
@@ -232,18 +204,15 @@ public struct ProfileView: View {
private func doReload() async {
if ApplicationLibrary.inPreview {
profileList = [
Profile(id: 0, name: "profile local", type: .local, path: ""),
Profile(id: 1, name: "profile remote", type: .remote, path: "", lastUpdated: Date(timeIntervalSince1970: 0)),
ProfilePreview(Profile(id: 0, name: "profile local", type: .local, path: "")),
ProfilePreview(Profile(id: 1, name: "profile remote", type: .remote, path: "", lastUpdated: Date(timeIntervalSince1970: 0))),
]
} else {
defer {
isLoading = false
}
do {
if !profileList.isEmpty {
profileList.removeAll()
}
profileList = try await ProfileManager.list()
profileList = try await ProfileManager.list().map { ProfilePreview($0) }
} catch {
alert = Alert(error)
return
@@ -279,11 +248,12 @@ public struct ProfileView: View {
private func moveProfile(from source: IndexSet, to destination: Int) {
profileList.move(fromOffsets: source, toOffset: destination)
for (index, profile) in profileList.enumerated() {
profile.order = UInt32(index)
profileList[index].order = UInt32(index)
profile.origin.order = UInt32(index)
}
Task {
do {
try await ProfileManager.update(profileList)
try await ProfileManager.update(profileList.map(\.origin))
} catch {
alert = Alert(error)
}
@@ -292,7 +262,7 @@ public struct ProfileView: View {
private func deleteProfile(where profileIndex: IndexSet) {
let profileToDelete = profileIndex.map { index in
profileList[index]
profileList[index].origin
}
profileList.remove(atOffsets: profileIndex)
Task {
@@ -306,16 +276,16 @@ public struct ProfileView: View {
public struct ProfileItem: View {
private let parent: ProfileView
private let profile: Profile
public init(_ parent: ProfileView, _ profile: Profile) {
@State private var profile: ProfilePreview
public init(_ parent: ProfileView, _ profile: ProfilePreview) {
self.parent = parent
self.profile = profile
_profile = State(initialValue: profile)
}
public var body: some View {
#if os(iOS) || os(macOS)
if #available(iOS 16.0, macOS 13.0,*) {
body0.draggable(profile)
body0.draggable(profile.origin)
} else {
body0
}
@@ -329,23 +299,20 @@ public struct ProfileView: View {
viewBuilder {
#if !os(macOS)
NavigationLink {
EditProfileView {
Task {
await parent.doReload()
}
}.environmentObject(profile)
EditProfileView().environmentObject(profile.origin)
} label: {
Text(profile.name)
}
.contextMenu {
ProfileShareButton(parent.$alert, profile) {
ProfileShareButton(parent.$alert, profile.origin) {
Label("Share", systemImage: "square.and.arrow.up.fill")
}
if profile.type == .remote {
Button {
parent.isUpdating = true
Task {
await parent.updateProfile(profile)
await parent.updateProfile(profile.origin)
profile = ProfilePreview(profile.origin)
}
} label: {
Label("Update", systemImage: "arrow.clockwise")
@@ -353,7 +320,7 @@ public struct ProfileView: View {
}
Button(role: .destructive) {
Task {
await parent.deleteProfile(profile)
await parent.deleteProfile(profile.origin)
}
} label: {
Label("Delete", systemImage: "trash.fill")
@@ -365,7 +332,7 @@ public struct ProfileView: View {
Text(profile.name)
if profile.type == .remote {
Spacer(minLength: 4)
Text("Last Updated: \(profile.lastUpdatedString)").font(.caption)
Text("Last Updated: \(profile.origin.lastUpdatedString)").font(.caption)
}
}
HStack {
@@ -373,23 +340,24 @@ public struct ProfileView: View {
Button {
parent.isUpdating = true
Task {
await parent.updateProfile(profile)
await parent.updateProfile(profile.origin)
profile = ProfilePreview(profile.origin)
}
} label: {
Image(systemName: "arrow.clockwise")
}
}
ProfileShareButton(parent.$alert, profile) {
ProfileShareButton(parent.$alert, profile.origin) {
Image(systemName: "square.and.arrow.up.fill")
}
Button {
parent.openWindow(id: EditProfileWindowView.windowID, value: profile.mustID)
parent.openWindow(id: EditProfileWindowView.windowID, value: profile.id)
} label: {
Image(systemName: "pencil")
}
Button {
Task {
await parent.deleteProfile(profile)
await parent.deleteProfile(profile.origin)
}
} label: {
Image(systemName: "trash.fill")