Skip to content

Appstate for startup and onboarding#150

Merged
reez merged 16 commits intoreez:mainfrom
danielnordh:appstate
Jan 17, 2025
Merged

Appstate for startup and onboarding#150
reez merged 16 commits intoreez:mainfrom
danielnordh:appstate

Conversation

@danielnordh
Copy link
Copy Markdown
Collaborator

@danielnordh danielnordh commented Jan 16, 2025

This PR refactors the startup and onboarding flows by using AppState enums instead of .isOnboarding from user defaults.
It removes the unused StartView and viewModel, and adds a LoadingView and ErrorView
Broken out from #145

Summary by CodeRabbit

  • New Features

    • Introduced a new state-driven application management system.
    • Added ErrorView and LoadingView to improve user experience.
  • Removed Features

    • Removed StartView and StartViewModel.
    • Eliminated local onboarding state tracking.
  • Improvements

    • Enhanced application state management with more granular states.
    • Improved error and loading state handling.
    • Updated onboarding logic for better clarity and flow.
    • Refined alert messaging for wallet deletion confirmation.
    • Streamlined initialization of views to incorporate application state.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 16, 2025

Walkthrough

This pull request introduces significant changes to the application's state management system, replacing the previous boolean-based onboarding approach with a more versatile AppState enum that accommodates multiple application states: onboarding, wallet, loading, and error. Key files like StartView, StartViewModel, and local AppStorage flags have been eliminated to streamline state management in LDKNodeMondayApp.swift. Additionally, new views for LoadingView and ErrorView have been added to enhance user experience and state handling.

Changes

File Change Summary
LDKNodeMonday.xcodeproj/project.pbxproj Added LoadingView.swift and ErrorView.swift to build files; Removed StartView.swift and StartViewModel.swift
LDKNodeMondayApp.swift Introduced AppState enum; Replaced isOnboarding with appState; Added state-driven view rendering
OnboardingViewModel.swift Replaced isOnboarding with appState binding; Updated initializer
StartViewModel.swift Completely removed
OnboardingView.swift Removed AppStorage properties; Updated preview initialization
StartView.swift Completely removed
LoadingView.swift New view with centered progress indicator
ErrorView.swift New view to display error messages
BitcoinViewModel.swift Added appState binding; Updated initializer
SettingsViewModel.swift Replaced isOnboarding with appState binding; Updated initializer and error handling
BitcoinView.swift Updated initialization of SettingsView and BitcoinView to include appState
SettingsView.swift Modified alert messages; Removed "Full Reset" button; Updated initialization with appState

Poem

🐰 In the realm of states, a rabbit's delight,
From boolean chains to enum's pure might,
Loading, error, wallet, and more,
Our app now dances across the shore!
State management, oh what a thrill! 🚀


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@danielnordh danielnordh marked this pull request as ready for review January 16, 2025 19:46
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (5)
LDKNodeMonday/View/Home/ErrorView.swift (1)

14-18: Enhance error presentation for better UX.

The current error presentation is very basic. Consider adding:

  • Error icon or symbol
  • Different styling for different error types
  • Action button for retry/refresh
  • Error code display if available

Here's a suggested implementation:

     var body: some View {
         Spacer()
-        Text(error != nil ? error!.localizedDescription : "Unknown error")
+        VStack(spacing: 16) {
+            Image(systemName: "exclamationmark.triangle.fill")
+                .foregroundColor(.red)
+                .font(.system(size: 50))
+            
+            Text(error?.localizedDescription ?? "Unknown error")
+                .multilineTextAlignment(.center)
+                .foregroundColor(.secondary)
+            
+            if error != nil {
+                Button(action: {
+                    // TODO: Add retry action
+                }) {
+                    Text("Retry")
+                        .fontWeight(.semibold)
+                }
+                .buttonStyle(.bordered)
+            }
+        }
+        .padding()
         Spacer()
     }
LDKNodeMonday.xcodeproj/project.pbxproj (1)

Line range hint 628-685: Clean up duplicate LDKNode package dependencies.

There are multiple entries for the LDKNode package in the build phases. This could lead to confusion or build issues.

Consider consolidating the LDKNode package references to use a single source:

  • Keep the one from the ldk-node repository
  • Remove the duplicate product dependencies
LDKNodeMonday/App/LDKNodeMondayApp.swift (2)

36-36: Replace unused closure parameters with underscores

The closure parameters oldValue and newValue in the .onChange modifier are not used inside the closure. To eliminate warnings from static analysis tools and adhere to Swift best practices, replace them with underscores _.

Apply this diff to replace the unused parameters:

-                .onChange(of: appState) { oldValue, newValue in
+                .onChange(of: appState) { _, _ in
🧰 Tools
🪛 SwiftLint (0.57.0)

[Warning] 36-36: Unused parameter in a closure should be replaced with _

(unused_closure_parameter)


[Warning] 36-36: Unused parameter in a closure should be replaced with _

(unused_closure_parameter)


60-60: Implement parameter passing to start() function

The TODO comment suggests modifying .start() to take parameters from backupInfo (e.g., seed, network, URL, LSP). Passing these parameters explicitly would enhance flexibility and make the initialization of LightningNodeService more robust.

Would you like assistance in updating the start() function to accept parameters from backupInfo and modifying the call accordingly?

🧰 Tools
🪛 SwiftLint (0.57.0)

[Warning] 60-60: TODOs should be resolved (.start could take parameters f...)

(todo)

LDKNodeMonday/View Model/Home/OnboardingViewModel.swift (1)

12-12: Consider using @Published for appState instead of @Binding in OnboardingViewModel

Using @Binding in a ViewModel can lead to tight coupling between the View and the ViewModel. It's generally recommended to manage the state internally within the ViewModel using @Published properties. The View can then observe these properties using @ObservedObject, promoting better separation of concerns and testability.

Proposed refactor:

In OnboardingViewModel.swift, change appState to an @Published property:

class OnboardingViewModel: ObservableObject {
    @Published var appState: AppState
    // ...

    init() {
        self.appState = .onboarding  // Set the initial state
        // Existing initialization code...
    }

    // ...
}

In OnboardingView.swift, observe the appState from the ViewModel:

struct OnboardingView: View {

    @ObservedObject var viewModel: OnboardingViewModel

    // ...

    var body: some View {
        // Use `viewModel.appState` as needed
    }
}

Also applies to: 80-81

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a75124a and 8ed79ac.

📒 Files selected for processing (8)
  • LDKNodeMonday.xcodeproj/project.pbxproj (5 hunks)
  • LDKNodeMonday/App/LDKNodeMondayApp.swift (2 hunks)
  • LDKNodeMonday/View Model/Home/OnboardingViewModel.swift (3 hunks)
  • LDKNodeMonday/View Model/Home/StartViewModel.swift (0 hunks)
  • LDKNodeMonday/View/Home/ErrorView.swift (1 hunks)
  • LDKNodeMonday/View/Home/LoadingView.swift (1 hunks)
  • LDKNodeMonday/View/Home/OnboardingView.swift (1 hunks)
  • LDKNodeMonday/View/Home/StartView.swift (0 hunks)
💤 Files with no reviewable changes (2)
  • LDKNodeMonday/View/Home/StartView.swift
  • LDKNodeMonday/View Model/Home/StartViewModel.swift
✅ Files skipped from review due to trivial changes (1)
  • LDKNodeMonday/View/Home/LoadingView.swift
🧰 Additional context used
🪛 SwiftLint (0.57.0)
LDKNodeMonday/App/LDKNodeMondayApp.swift

[Warning] 51-51: TODOs should be resolved (Show error on relevant screen,...)

(todo)


[Warning] 60-60: TODOs should be resolved (.start could take parameters f...)

(todo)


[Warning] 36-36: Unused parameter in a closure should be replaced with _

(unused_closure_parameter)


[Warning] 36-36: Unused parameter in a closure should be replaced with _

(unused_closure_parameter)

🔇 Additional comments (4)
LDKNodeMonday/View/Home/ErrorView.swift (1)

21-29: LGTM! Preview provides good test data.

The preview implementation uses appropriate test data with a realistic error message.

LDKNodeMonday.xcodeproj/project.pbxproj (1)

10-11: LGTM! File references are properly configured.

The new files LoadingView.swift and ErrorView.swift are correctly added to the project structure and build phases.

Also applies to: 96-97, 307-308, 628-628, 685-685

LDKNodeMonday/View Model/Home/OnboardingViewModel.swift (1)

112-112: State transition to .wallet is correctly implemented

The assignment of self.appState = .wallet upon successful seed saving correctly transitions the application state, aligning with the new state management approach.

LDKNodeMonday/View/Home/OnboardingView.swift (1)

105-105: Initialization of OnboardingViewModel in Preview is appropriate

The update to initialize the OnboardingViewModel with appState: .constant(.onboarding) in the preview ensures that the onboarding state is correctly represented during development.

Comment thread LDKNodeMonday/View/Home/ErrorView.swift Outdated
Comment thread LDKNodeMonday/App/LDKNodeMondayApp.swift Outdated
Comment thread LDKNodeMonday/App/LDKNodeMondayApp.swift Outdated
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@reez
Copy link
Copy Markdown
Owner

reez commented Jan 16, 2025

I had a node running on my device, then went to Settings -> Full Reset, and it didn't seem to work going back to onboarding (it kind of stayed on settings, yet stopped the node running yet didn't go back to Onboarding but just stayed in the settings and still would show the main wallet view). and then when I deleted or killed the app and then ran it I would get this screen:

IMG_3529

Did you see anything similar when doing Delete Wallet or Full Reset or anything? Could totally be something on my end.

I think something in SettingsViewModel will need some code deleted (and maybe added?) to it though, it still has the isOnboarding code. This PR is nice for this specific reason because a contributor won't have to guess or hunt down where all of this related AppState is, so just re-inforces how great this PR feature is!

This PR is looking good overall otherwise.

@danielnordh
Copy link
Copy Markdown
Collaborator Author

I think something in SettingsViewModel will need some code deleted (and maybe added?) to it though, it still has the isOnboarding code. This PR is nice for this specific reason because a contributor won't have to guess or hunt down where all of this related AppState is, so just re-inforces how great this PR feature is!

Good point, forgot that those had the isOnboarding code. Will fix.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🔭 Outside diff range comments (1)
LDKNodeMonday/View/Settings/SettingsView.swift (1)

Line range hint 1-176: Consider adding state restoration logic.

Based on the PR comments about the app not returning to onboarding after a reset, it seems the SettingsView's delete functionality might need to properly handle state restoration. Consider updating the delete action to explicitly set the appState to .onboarding:

 Button("Yes", role: .destructive) {
     viewModel.delete()
+    viewModel.appState = .onboarding
     dismiss()
 }
🧹 Nitpick comments (6)
LDKNodeMonday/View/Home/BitcoinView.swift (1)

349-352: Enhance preview coverage with multiple AppState cases.

The preview only shows the view in .onboarding state. Consider adding multiple previews to demonstrate how the view behaves in different states (e.g., .wallet, .loading, .error).

Example implementation:

#if DEBUG
    struct BitcoinView_Previews: PreviewProvider {
        static var previews: some View {
            Group {
                BitcoinView(
                    viewModel: .init(appState: .constant(.onboarding), priceClient: .mock),
                    sendNavigationPath: .constant(.init())
                )
                .previewDisplayName("Onboarding State")
                
                BitcoinView(
                    viewModel: .init(appState: .constant(.wallet), priceClient: .mock),
                    sendNavigationPath: .constant(.init())
                )
                .previewDisplayName("Wallet State")
                
                BitcoinView(
                    viewModel: .init(appState: .constant(.loading), priceClient: .mock),
                    sendNavigationPath: .constant(.init())
                )
                .previewDisplayName("Loading State")
                
                BitcoinView(
                    viewModel: .init(appState: .constant(.error), priceClient: .mock),
                    sendNavigationPath: .constant(.init())
                )
                .previewDisplayName("Error State")
            }
        }
    }
#endif
LDKNodeMonday/View Model/Profile/SettingsViewModel.swift (2)

13-13: Consider avoiding @Binding in ViewModel; use @Published and delegate pattern instead

Using @Binding in a ViewModel is unconventional since bindings are intended for use within Views to create a two-way connection between a property and a View. In a ViewModel, it's more appropriate to use @Published properties and communicate changes back to the View using delegate methods or closure callbacks. This approach adheres to the MVVM pattern and enhances the separation of concerns.


64-72: Reduce duplicated error handling code with a helper method

The error handling logic in your delete() method's catch blocks is repetitive. To adhere to the DRY (Don't Repeat Yourself) principle and improve maintainability, consider extracting this logic into a helper method.

Here's an example of how you could refactor the error handling:

private func handleNodeIDError(_ error: Error) {
    let errorString: (title: String, detail: String)
    if let nodeError = error as? NodeError {
        errorString = handleNodeError(nodeError)
    } else {
        errorString = (title: "Error", detail: error.localizedDescription)
    }
    DispatchQueue.main.async {
        self.nodeIDError = .init(title: errorString.title, detail: errorString.detail)
    }
}

Then, in your delete() method, you can replace the catch blocks with:

catch {
    handleNodeIDError(error)
}
LDKNodeMonday/View Model/Home/BitcoinViewModel.swift (1)

12-12: Consider documenting the purpose of appState binding.

The appState binding is added but not used in any of the view model's methods. If it's intended for future use, consider adding a documentation comment explaining its purpose.

LDKNodeMonday/App/LDKNodeMondayApp.swift (2)

36-38: Replace unused closure parameters with underscores.

The onChange modifier has unused parameters that can be replaced with underscores.

-.onChange(of: appState) { oldValue, newValue in
+.onChange(of: appState) { _, _ in
🧰 Tools
🪛 SwiftLint (0.57.0)

[Warning] 36-36: Unused parameter in a closure should be replaced with _

(unused_closure_parameter)


[Warning] 36-36: Unused parameter in a closure should be replaced with _

(unused_closure_parameter)


58-76: Consider handling node startup errors differently.

When LightningNodeService.start() fails, it might be better to allow retrying rather than showing a generic error view. Consider adding a .retryNodeStart state or implementing a retry mechanism.

🧰 Tools
🪛 SwiftLint (0.57.0)

[Warning] 60-60: TODOs should be resolved (.start could take parameters f...)

(todo)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9bee911 and 0771fc6.

📒 Files selected for processing (5)
  • LDKNodeMonday/App/LDKNodeMondayApp.swift (2 hunks)
  • LDKNodeMonday/View Model/Home/BitcoinViewModel.swift (2 hunks)
  • LDKNodeMonday/View Model/Profile/SettingsViewModel.swift (3 hunks)
  • LDKNodeMonday/View/Home/BitcoinView.swift (2 hunks)
  • LDKNodeMonday/View/Settings/SettingsView.swift (2 hunks)
🧰 Additional context used
📓 Learnings (1)
LDKNodeMonday/App/LDKNodeMondayApp.swift (1)
Learnt from: danielnordh
PR: reez/Monday#150
File: LDKNodeMonday/App/LDKNodeMondayApp.swift:49-56
Timestamp: 2025-01-16T19:56:11.062Z
Learning: In the LDKNodeMonday app, KeyClient.live.getBackupInfo() returns nil when no backup info is found, rather than throwing an error. The nil case is used to determine if the app should proceed to the onboarding state.
🪛 SwiftLint (0.57.0)
LDKNodeMonday/App/LDKNodeMondayApp.swift

[Warning] 51-51: TODOs should be resolved (Show error on relevant screen,...)

(todo)


[Warning] 60-60: TODOs should be resolved (.start could take parameters f...)

(todo)


[Warning] 36-36: Unused parameter in a closure should be replaced with _

(unused_closure_parameter)


[Warning] 36-36: Unused parameter in a closure should be replaced with _

(unused_closure_parameter)

🔇 Additional comments (8)
LDKNodeMonday/View/Home/BitcoinView.swift (1)

242-242: Verify BitcoinViewModel's appState property initialization.

The SettingsView initialization now requires an appState binding, but the BitcoinViewModel's appState property is not visible in the provided code. This could lead to runtime issues.

Let's verify the BitcoinViewModel implementation:

✅ Verification successful

The BitcoinViewModel implementation is correct and safe.

The appState property is properly implemented in BitcoinViewModel as a @Binding property and correctly initialized, matching the usage pattern in BitcoinView. The code is safe from runtime issues.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for BitcoinViewModel's appState property definition
ast-grep --pattern 'class BitcoinViewModel {
  $$$
  @Published var appState: AppState
  $$$
}'

# Search for BitcoinViewModel's init method to verify appState initialization
ast-grep --pattern 'init(appState: Binding<AppState>, $$$) {
  $$$
  self.appState = appState
  $$$
}'

Length of output: 202


Script:

#!/bin/bash
# Find BitcoinViewModel file
fd BitcoinViewModel

# Search for appState property and initialization using ripgrep
rg "class BitcoinViewModel" -A 10
rg "@Published.*appState" -A 2
rg "init.*appState.*\{" -A 5

Length of output: 2861

LDKNodeMonday/View/Settings/SettingsView.swift (2)

128-128: LGTM: Improved alert message formatting.

The addition of a newline character improves the readability of the alert message.


175-175: Verify AppState handling in SettingsViewModel.

While the preview has been updated to use the new AppState parameter, based on the PR comments about onboarding issues, the actual SettingsViewModel might still contain legacy .isOnboarding code that needs to be updated.

Let's verify the SettingsViewModel implementation:

✅ Verification successful

SettingsViewModel implementation is correctly using AppState

The ViewModel has been properly updated to use the new AppState pattern and contains no legacy .isOnboarding code. The usage of .onboarding state in the delete() method is intentional and correct, matching the preview implementation.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any remaining isOnboarding references in SettingsViewModel
rg "isOnboarding" --type swift

# Search for AppState usage in SettingsViewModel
ast-grep --pattern 'class SettingsViewModel {
  $$$
  var appState: $_ {
    $$$
  }
  $$$
}'

Length of output: 126


Script:

#!/bin/bash
# First locate the ViewModel file
fd -e swift "SettingsViewModel"

# Then examine its contents
echo "=== File contents ==="
for f in $(fd -e swift "SettingsViewModel"); do
    echo "File: $f"
    echo "---"
    cat "$f"
    echo "---"
done

Length of output: 661


Script:

#!/bin/bash
# Read the file contents with proper path handling
echo "=== SettingsViewModel Contents ==="
cat "LDKNodeMonday/View Model/Profile/SettingsViewModel.swift"

# Search for specific patterns in this file
echo -e "\n=== AppState Usage ==="
rg "AppState" "LDKNodeMonday/View Model/Profile/SettingsViewModel.swift" || true

echo -e "\n=== isOnboarding References ==="
rg "isOnboarding" "LDKNodeMonday/View Model/Profile/SettingsViewModel.swift" || true

Length of output: 4274

LDKNodeMonday/View Model/Profile/SettingsViewModel.swift (1)

22-23: Ensure proper initialization of @Binding property

When initializing an @Binding property in a class, assigning to self._appState = appState is correct. However, as mentioned earlier, consider whether using @Binding in the ViewModel is the optimal approach for state management.

LDKNodeMonday/View Model/Home/BitcoinViewModel.swift (1)

37-39: LGTM! Initializer correctly handles the new appState binding.

The initializer properly initializes the appState binding using the underscore prefix convention.

LDKNodeMonday/App/LDKNodeMondayApp.swift (3)

15-16: LGTM! Clear state initialization.

Good choice initializing appState to .loading by default.


22-33: LGTM! Clean state-based view switching.

The switch statement provides a clear separation of views based on application state.


87-92: LGTM! Clear and concise AppState enum.

The enum cases clearly represent all possible application states.

Comment thread LDKNodeMonday/View Model/Profile/SettingsViewModel.swift Outdated
Comment thread LDKNodeMonday/App/LDKNodeMondayApp.swift Outdated
Comment thread LDKNodeMonday/App/LDKNodeMondayApp.swift
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (4)
LDKNodeMonday/App/LDKNodeMondayApp.swift (3)

22-33: Consider handling nil error case in ErrorView.

The error view is initialized with a potentially nil error. Consider providing a default error message when self.appError is nil.

-                    ErrorView(error: self.appError)
+                    ErrorView(error: self.appError ?? NSError(domain: "LDKNodeMonday", code: -1, userInfo: [NSLocalizedDescriptionKey: "An unknown error occurred"]))

36-41: Replace unused closure parameters with underscores.

The closure parameters are unused and can be replaced with underscores as per Swift best practices.

-.onChange(of: appState) { oldValue, newValue in
+.onChange(of: appState) { _, _ in
🧰 Tools
🪛 SwiftLint (0.57.0)

[Warning] 36-36: Unused parameter in a closure should be replaced with _

(unused_closure_parameter)


[Warning] 36-36: Unused parameter in a closure should be replaced with _

(unused_closure_parameter)


51-64: Consider specific error handling for node startup.

The error handling is generic and could benefit from more specific error cases to provide better user feedback.

 do {
     try await LightningNodeService.shared.start()
     LightningNodeService.shared.listenForEvents()
     await MainActor.run {
         self.appState = .wallet
     }
-} catch let error {
+} catch let error as LightningNodeError {
     debugPrint(error)
     await MainActor.run {
         self.appError = error
         self.appState = .error
     }
+} catch {
+    debugPrint("Unexpected error during node startup: \(error)")
+    await MainActor.run {
+        self.appError = NSError(
+            domain: "LDKNodeMonday",
+            code: -1,
+            userInfo: [NSLocalizedDescriptionKey: "Failed to start Lightning node: \(error.localizedDescription)"]
+        )
+        self.appState = .error
+    }
 }
🧰 Tools
🪛 SwiftLint (0.57.0)

[Warning] 52-52: TODOs should be resolved (.start could take parameters f...)

(todo)

LDKNodeMonday/View Model/Profile/SettingsViewModel.swift (1)

52-72: LGTM! Well-structured delete implementation with proper error handling.

The changes demonstrate several improvements:

  • Safe node stopping with status check
  • Logical operation ordering
  • Proper use of injected keyClient
  • Clean state transition to onboarding
  • Comprehensive error handling

Consider extracting the error handling logic into a reusable method since similar patterns appear in other methods (getNetwork, getEsploraUrl):

private func handleError(_ error: Error, completion: @escaping (MondayError) -> Void) {
    if let nodeError = error as? NodeError {
        let errorString = handleNodeError(nodeError)
        DispatchQueue.main.async {
            completion(.init(title: errorString.title, detail: errorString.detail))
        }
    } else {
        DispatchQueue.main.async {
            completion(.init(title: "Error", detail: error.localizedDescription))
        }
    }
}

Usage:

} catch let error {
    handleError(error) { error in
        self.nodeIDError = error
    }
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0771fc6 and 6efca82.

📒 Files selected for processing (2)
  • LDKNodeMonday/App/LDKNodeMondayApp.swift (2 hunks)
  • LDKNodeMonday/View Model/Profile/SettingsViewModel.swift (3 hunks)
🧰 Additional context used
📓 Learnings (1)
LDKNodeMonday/App/LDKNodeMondayApp.swift (1)
Learnt from: danielnordh
PR: reez/Monday#150
File: LDKNodeMonday/App/LDKNodeMondayApp.swift:49-56
Timestamp: 2025-01-16T19:56:11.062Z
Learning: In the LDKNodeMonday app, KeyClient.live.getBackupInfo() returns nil when no backup info is found, rather than throwing an error. The nil case is used to determine if the app should proceed to the onboarding state.
🪛 SwiftLint (0.57.0)
LDKNodeMonday/App/LDKNodeMondayApp.swift

[Warning] 52-52: TODOs should be resolved (.start could take parameters f...)

(todo)


[Warning] 36-36: Unused parameter in a closure should be replaced with _

(unused_closure_parameter)


[Warning] 36-36: Unused parameter in a closure should be replaced with _

(unused_closure_parameter)

🔇 Additional comments (5)
LDKNodeMonday/App/LDKNodeMondayApp.swift (3)

12-16: LGTM! Clean state management setup.

The state management implementation using @State properties follows SwiftUI best practices.


52-52: Address TODO: Enhance start method with backup parameters.

The TODO suggests that the start method could be enhanced to use backup parameters. This would improve flexibility and configuration options.

Would you like me to help implement the parameter passing from backupInfo to the start method?

🧰 Tools
🪛 SwiftLint (0.57.0)

[Warning] 52-52: TODOs should be resolved (.start could take parameters f...)

(todo)


79-84: LGTM! Well-structured state enum.

The AppState enum is clear, concise, and appropriately scoped with the public modifier.

LDKNodeMonday/View Model/Profile/SettingsViewModel.swift (2)

13-13: LGTM! Clean transition to AppState binding.

The changes correctly implement the new state management approach using @Binding var appState: AppState instead of @AppStorage("isOnboarding").

Also applies to: 22-24


52-61: Verify reset functionality addresses reported issues.

Based on the PR comments about reset issues, let's verify that this implementation properly handles device reset scenarios.

Run the following script to check for any remaining isOnboarding references that might affect the reset behavior:

✅ Verification successful

Reset implementation is correct and comprehensive

The implementation properly handles the reset scenario by:

  • Cleaning up all necessary data (LightningNodeService, keyClient)
  • Correctly transitioning to onboarding state
  • No conflicting persistent state that could prevent proper reset
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for any remaining isOnboarding references that might affect reset behavior

echo "Searching for remaining isOnboarding references..."
rg --type swift "isOnboarding"

echo "Searching for UserDefaults access that might affect reset..."
ast-grep --pattern 'UserDefaults.standard' 

Length of output: 315


Script:

#!/bin/bash
# Search for app state related code and state transitions

echo "Searching for AppState enum and related code..."
rg --type swift "enum.*AppState"
rg --type swift "appState.*="

echo "Searching for state persistence..."
rg --type swift "UserDefaults|@AppStorage"

echo "Searching for other potential reset handlers..."
rg --type swift "func.*reset|reset\("

Length of output: 1534

@danielnordh
Copy link
Copy Markdown
Collaborator Author

danielnordh commented Jan 17, 2025

I think something in SettingsViewModel will need some code deleted (and maybe added?) to it though, it still has the isOnboarding code. This PR is nice for this specific reason because a contributor won't have to guess or hunt down where all of this related AppState is, so just re-inforces how great this PR feature is!

Fixed this by:

  • Keeping 'Delete Wallet', but removing 'Full Reset' which is not needed atm.
  • Using AppState.onboarding instead of .isOnboarding
  • Also made the delete() more reliable by handling cases where calling .stop on node would abort if node was not running

Should be good to go now.
Have tested creating and deleting wallets multiple times in a row without issues.

@reez
Copy link
Copy Markdown
Owner

reez commented Jan 17, 2025

ACK, great job!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants