From f83f3db5b44441d3df73a09134352bdba0ec4d13 Mon Sep 17 00:00:00 2001 From: Bryan Montz Date: Thu, 17 Oct 2024 07:27:42 -0500 Subject: [PATCH 1/2] migrate ObservableObject to @Observable where possible #1458 --- CHANGELOG.md | 1 + .../xcshareddata/swiftpm/Package.resolved | 2 +- Nos/Controller/RawEventController.swift | 43 ++++++++----------- Nos/Models/NotificationViewModel.swift | 4 +- Nos/Views/Components/Event/RawEventView.swift | 8 ++-- .../Notifications/NotificationCard.swift | 6 +-- .../OnboardingAgeVerificationView.swift | 2 +- .../OnboardingNotOldEnoughView.swift | 2 +- .../Onboarding/OnboardingStartView.swift | 4 +- Nos/Views/Onboarding/OnboardingView.swift | 18 ++++---- 10 files changed, 41 insertions(+), 49 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 367ccddda..c59c474a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Removed integration with Universal Name Space [#1636](https://github.com/planetary-social/nos/issues/1636) ### Internal Changes +- migrate ObservableObject to @Observable where possible [#1458](https://github.com/planetary-social/nos/issues/1458) ## [0.2.2] - 2024-10-11Z diff --git a/Nos.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Nos.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index b1753bd89..7590212f9 100644 --- a/Nos.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Nos.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -244,5 +244,5 @@ } } ], - "version" : 2 + "version" : 3 } diff --git a/Nos/Controller/RawEventController.swift b/Nos/Controller/RawEventController.swift index 30241f1b3..376c018d4 100644 --- a/Nos/Controller/RawEventController.swift +++ b/Nos/Controller/RawEventController.swift @@ -2,7 +2,7 @@ import Foundation import Logger /// A view model for the RawEventView -@MainActor protocol RawEventViewModel: ObservableObject { +protocol RawEventViewModel { /// The raw message to display in screen var rawMessage: String? { get } @@ -21,17 +21,14 @@ import Logger } /// A controller for the `RawEventView` -@MainActor class RawEventController: RawEventViewModel { +@Observable final class RawEventController: RawEventViewModel { - private var note: Event + private let note: Event + private let dismissHandler: () -> Void - @Published var rawMessage: String? - - @Published var loadingMessage: String? - - @Published var errorMessage: String? - - private var dismissHandler: () -> Void + private(set) var rawMessage: String? + private(set) var loadingMessage: String? + private(set) var errorMessage: String? init(note: Event, dismissHandler: @escaping () -> Void) { self.note = note @@ -52,22 +49,20 @@ import Logger self.rawMessage = rawMessage self.loadingMessage = nil } - + private func loadRawMessage() { loadingMessage = String(localized: .localizable.loading) - Task { [note, weak self] in - var rawMessage: String - let errorMessage = note.content ?? "error" - do { - let data = try JSONSerialization.data( - withJSONObject: note.jsonRepresentation ?? [:], - options: [.prettyPrinted] - ) - rawMessage = String(decoding: data, as: UTF8.self) - } catch { - rawMessage = errorMessage - } - self?.updateRawMessage(rawMessage) + + let rawMessage: String + do { + let data = try JSONSerialization.data( + withJSONObject: note.jsonRepresentation ?? [:], + options: [.prettyPrinted] + ) + rawMessage = String(decoding: data, as: UTF8.self) + } catch { + rawMessage = note.content ?? "error" } + updateRawMessage(rawMessage) } } diff --git a/Nos/Models/NotificationViewModel.swift b/Nos/Models/NotificationViewModel.swift index 121541c78..838bafb13 100644 --- a/Nos/Models/NotificationViewModel.swift +++ b/Nos/Models/NotificationViewModel.swift @@ -8,11 +8,11 @@ import UIKit /// in the .init method of a View. Because of this you must call the async function /// `loadContent()` to populate the `content` variable because it relies on some /// database queries. -class NotificationViewModel: ObservableObject, Identifiable { +@Observable final class NotificationViewModel: Identifiable { let noteID: RawEventID let authorProfilePhotoURL: URL? let actionText: AttributedString - @Published var content: AttributedString? + private(set) var content: AttributedString? let date: Date var id: RawEventID { diff --git a/Nos/Views/Components/Event/RawEventView.swift b/Nos/Views/Components/Event/RawEventView.swift index 737878073..1873ada55 100644 --- a/Nos/Views/Components/Event/RawEventView.swift +++ b/Nos/Views/Components/Event/RawEventView.swift @@ -1,7 +1,7 @@ import SwiftUI struct RawEventView: View where ViewModel: RawEventViewModel { - @ObservedObject var viewModel: ViewModel + let viewModel: ViewModel /// A loading overlay that displays the `loadingMessage` from the view model. private var loadingIndicator: some View { @@ -84,11 +84,11 @@ struct RawEventView: View where ViewModel: RawEventViewModel { fileprivate class PreviewViewModel: RawEventViewModel { - @Published var rawMessage: String? + var rawMessage: String? - @Published var loadingMessage: String? = "Loading..." + var loadingMessage: String? = "Loading..." - @Published var errorMessage: String? + var errorMessage: String? init(_ rawMessage: String) { self.rawMessage = rawMessage diff --git a/Nos/Views/Notifications/NotificationCard.swift b/Nos/Views/Notifications/NotificationCard.swift index 2441195a6..c02de43e3 100644 --- a/Nos/Views/Notifications/NotificationCard.swift +++ b/Nos/Views/Notifications/NotificationCard.swift @@ -9,14 +9,10 @@ struct NotificationCard: View { @EnvironmentObject private var relayService: RelayService @Dependency(\.persistenceController) private var persistenceController - @ObservedObject private var viewModel: NotificationViewModel + let viewModel: NotificationViewModel @State private var relaySubscriptions = SubscriptionCancellables() @State private var content: AttributedString? - init(viewModel: NotificationViewModel) { - self.viewModel = viewModel - } - func showNote() { guard let note = Event.find(by: viewModel.noteID, context: viewContext) else { return diff --git a/Nos/Views/Onboarding/OnboardingAgeVerificationView.swift b/Nos/Views/Onboarding/OnboardingAgeVerificationView.swift index 22e0b2238..7c4bcad0c 100644 --- a/Nos/Views/Onboarding/OnboardingAgeVerificationView.swift +++ b/Nos/Views/Onboarding/OnboardingAgeVerificationView.swift @@ -3,7 +3,7 @@ import SwiftUI /// The Age Verification view in the onboarding. struct OnboardingAgeVerificationView: View { - @EnvironmentObject var state: OnboardingState + @Environment(OnboardingState.self) private var state @Dependency(\.crashReporting) private var crashReporting @Dependency(\.currentUser) private var currentUser diff --git a/Nos/Views/Onboarding/OnboardingNotOldEnoughView.swift b/Nos/Views/Onboarding/OnboardingNotOldEnoughView.swift index af1c2f82d..4b95fb282 100644 --- a/Nos/Views/Onboarding/OnboardingNotOldEnoughView.swift +++ b/Nos/Views/Onboarding/OnboardingNotOldEnoughView.swift @@ -1,7 +1,7 @@ import SwiftUI struct OnboardingNotOldEnoughView: View { - @EnvironmentObject var state: OnboardingState + @Environment(OnboardingState.self) private var state var body: some View { VStack { diff --git a/Nos/Views/Onboarding/OnboardingStartView.swift b/Nos/Views/Onboarding/OnboardingStartView.swift index 0601fe661..3003bf345 100644 --- a/Nos/Views/Onboarding/OnboardingStartView.swift +++ b/Nos/Views/Onboarding/OnboardingStartView.swift @@ -3,7 +3,7 @@ import SwiftUI /// The beginning of the Onboarding views which contains buttons to start creating a new account or log in. struct OnboardingStartView: View { - @EnvironmentObject var state: OnboardingState + @Environment(OnboardingState.self) private var state @Dependency(\.analytics) private var analytics @@ -54,6 +54,6 @@ struct OnboardingStartView: View { #Preview { OnboardingStartView() - .environmentObject(OnboardingState()) + .environment(OnboardingState()) .inject(previewData: PreviewData()) } diff --git a/Nos/Views/Onboarding/OnboardingView.swift b/Nos/Views/Onboarding/OnboardingView.swift index 3acc0d48b..a49d94802 100644 --- a/Nos/Views/Onboarding/OnboardingView.swift +++ b/Nos/Views/Onboarding/OnboardingView.swift @@ -1,13 +1,13 @@ import SwiftUI -class OnboardingState: ObservableObject { - @Published var flow: OnboardingFlow = .createAccount - @Published var step: OnboardingStep = .onboardingStart { +@Observable final class OnboardingState { + var flow: OnboardingFlow = .createAccount + var step: OnboardingStep = .onboardingStart { didSet { path.append(step) } } - @Published var path = NavigationPath() + var path = NavigationPath() } enum OnboardingFlow { @@ -25,7 +25,7 @@ enum OnboardingStep { /// The view that initializes the onboarding navigation stack and shows the first view. struct OnboardingView: View { - @StateObject var state = OnboardingState() + @State var state = OnboardingState() /// Completion to be called when all onboarding steps are complete let completion: @MainActor () -> Void @@ -33,18 +33,18 @@ struct OnboardingView: View { var body: some View { NavigationStack(path: $state.path) { OnboardingStartView() - .environmentObject(state) + .environment(state) .navigationDestination(for: OnboardingStep.self) { step in switch step { case .onboardingStart: OnboardingStartView() - .environmentObject(state) + .environment(state) case .ageVerification: OnboardingAgeVerificationView() - .environmentObject(state) + .environment(state) case .notOldEnough: OnboardingNotOldEnoughView() - .environmentObject(state) + .environment(state) case .login: OnboardingLoginView(completion: completion) case .buildYourNetwork: From cd03c5ace5c8dd84f7c76645decfecbcd6ac0622 Mon Sep 17 00:00:00 2001 From: Josh Brown Date: Thu, 17 Oct 2024 10:52:17 -0400 Subject: [PATCH 2/2] Apply suggestions from code review --- CHANGELOG.md | 2 +- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c59c474a2..a46ada2a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Removed integration with Universal Name Space [#1636](https://github.com/planetary-social/nos/issues/1636) ### Internal Changes -- migrate ObservableObject to @Observable where possible [#1458](https://github.com/planetary-social/nos/issues/1458) +- Migrate ObservableObject to @Observable where possible [#1458](https://github.com/planetary-social/nos/issues/1458) ## [0.2.2] - 2024-10-11Z diff --git a/Nos.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Nos.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 7590212f9..b1753bd89 100644 --- a/Nos.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Nos.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -244,5 +244,5 @@ } } ], - "version" : 3 + "version" : 2 }