Skip to content
Mobile Joe Docs Dashboard
View Markdown

iOS · SwiftUI · SDK 1.0.1

Feature Plans

Let app users explore your plans, vote on features, and follow your roadmap.

Complete the iOS quickstart first. These examples use the configured app and the MobileJoeUI package product.

Create a feature plan

In the dashboard, open Feature Plans and save a plan with status Open. Every status except Draft is visible in your app.

Show the list

Add this screen to your app, or move its navigation link into your existing navigation stack:

import SwiftUI
import MobileJoeUI

struct FeedbackView: View {
  var body: some View {
    NavigationStack {
      List {
        NavigationLink("Feature Plans") {
          FeaturePlansView(
            configuration: .standard(recipient: "[email protected]"),
            presentationMode: .inNavigationStack
          )
        }
      }
      .navigationTitle("Feedback")
    }
  }
}

FeaturePlansView loads data, fetches additional pages while scrolling, and supports pull to refresh. Tapping a plan opens its details. The vote button adds a vote; tapping it again removes that vote.

Search matches titles and descriptions. The toolbar menu offers newest-first or score sorting and the status filters.

Present a sheet

Use .asSheet to get the SDK's navigation stack and close button:

import SwiftUI
import MobileJoeUI

struct FeaturePlansButton: View {
  @State private var showingPlans = false

  var body: some View {
    Button("Feature Plans") { showingPlans = true }
      .sheet(isPresented: $showingPlans) {
        FeaturePlansView(
          configuration: .standard(recipient: "[email protected]"),
          presentationMode: .asSheet
        )
      }
  }
}

Replace [email protected] with your support address. The suggestion button opens the user's email app; it does not create a feature plan. Use .standard(recipient: "") to hide it. For custom localized email content, use FeaturePlansView.Configuration(recipient:subject:body:).

To open a specific plan, pass its ID as selectedFeaturePlanID: after presentationMode:. Your app handles incoming URLs and extracts the ID. Save a Deep link base URL in the Feature Plans settings to copy deep links in the dashboard.

Use your own UI

Import MobileJoe and keep an observable FeaturePlans() model in @State. Read all, and call load(), reload(), vote(_:), featurePlan(id:), or search(for:) on the main actor; set sorting and filtering to change the list.

Verify

Open your saved plan, vote twice, and confirm the score returns to its starting value. Change its dashboard status to Planned, refresh, and check the roadmap filter. If it is missing, check the selected filter and follow Troubleshooting.