### Complete Component with Factory Annotations Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/Annotations.md An example of a complete component class annotated with @Factory and @GenerateFactory. This setup is for creating a singleton instance with generated factory methods. ```kotlin @Factory // Koin: create single instance @GenerateFactory // Generate factory internal class UserProfileComponent( @InjectedParam componentContext: AppComponentContext, @InjectedParam override val navigation: UserProfileNavigation, private val getUserUseCase: GetUserUseCase, private val userPersistence: UserPersistence, ) : ScreenComponent( componentContext = componentContext, defaultState = ProfileViewState(), ) { // Component implementation } ``` -------------------------------- ### Example of launchWithHandler Usage Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/UseCaseExecutionScope.md Demonstrates how to use launchWithHandler to execute a use case and handle its success or failure. ```kotlin component.launchWithHandler { val result = someUseCase.execute(Unit, cancelPrevious = false) if (result.isSuccess) { // Handle success } } ``` -------------------------------- ### Complete Navigation Example: Parent Component Logic Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/ResultFlow.md A comprehensive example showing how a parent component sets up a ResultFlow, collects results for different picker types (fruit/vegetable), and navigates to the respective pickers. It handles the results using a when statement. ```kotlin sealed class PickerResult : Parcelable { @Parcelize data class FruitSelected(val fruit: String) : PickerResult() @Parcelize data class VegetableSelected(val vegetable: String) : PickerResult() } // In parent navigation interface SecondScreenNavigation { fun navigateToPicker(resultFlow: ResultFlow) fun navigateToVegetablePicker(resultFlow: ResultFlow) } // In parent component private fun openFruitPicker() { val resultFlow = ResultFlow() resultFlow .onEach { result -> when (result) { is PickerResult.FruitSelected -> { componentState.update { it.copy(selectedFruit = result.fruit) } } is PickerResult.VegetableSelected -> { // This shouldn't happen in fruit picker } } } .launchIn(componentCoroutineScope) navigation.navigateToPicker(resultFlow) } ``` -------------------------------- ### Send UI Event Example Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/BaseComponent.md Example of sending a UI event when a specific condition is met, such as reaching a predefined threshold. ```kotlin if (count == ALERT_THRESHOLD) { sendUiEvent(MyScreenEvent.ShowToast("Threshold reached!")) } ``` -------------------------------- ### Fetch Policy Usage Examples Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/GraphQLAPI.md Demonstrates how to specify a fetch policy when making a GraphQL request. ```kotlin // Network only - always fresh data val result = api.getEpisodes(fetchPolicy = FetchPolicy.NetworkOnly) // Cache first - faster, may be stale val result = api.getEpisodes(fetchPolicy = FetchPolicy.CacheFirst) ``` -------------------------------- ### UserPreferences Example Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/Persistence.md Example demonstrating how to use PrimitivePersistence within a UserPreferences class to manage login status and user ID. ```kotlin @Single internal class UserPreferences( private val primitivePersistence: PrimitivePersistence ) { private companion object { val IS_LOGGED_IN_KEY = booleanPreferencesKey("is_logged_in") val USER_ID_KEY = stringPreferencesKey("user_id") } suspend fun setLoggedIn(isLoggedIn: Boolean) { primitivePersistence.save(IS_LOGGED_IN_KEY, isLoggedIn) } suspend fun isLoggedIn(): Boolean? { return primitivePersistence.get(IS_LOGGED_IN_KEY) } fun observeLoggedIn(): Flow { return primitivePersistence.observe(IS_LOGGED_IN_KEY) } } ``` -------------------------------- ### Example Usage of Platform Bindings Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/PlatformBindings.md Demonstrates how to access platform information using the `platformBindings` instance. Retrieves OS name and other details. ```kotlin val platformInfo = platformBindings.platform() val osName = platformInfo.osName // e.g., "Android" or "iOS" ``` -------------------------------- ### Example: Extracting Path and Query Parameters Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/DeepLinking.md Demonstrates how to use `DeepLink.from`, `pathParameter`, and `queryParameter` to parse a URI and extract specific arguments. ```kotlin val regex = Regex("""kmptemplate://home/third/(?.+)""") val deepLink = DeepLink.from(regex, "kmptemplate://home/third/myvalue") val arg = deepLink?.pathParameter("argument") // "myvalue" val deepLinkQuery = DeepLink.from( regex = Regex("""kmptemplate://home/third.*"""), uri = "kmptemplate://home/third?arg=myvalue" ) val queryArg = deepLinkQuery?.queryParameter("arg") // "myvalue" ``` -------------------------------- ### CounterComponent Implementation Example Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/BaseComponent.md Example implementation of a CounterComponent extending BaseComponent. It manages counter state and sends UI events upon reaching a specific count. ```kotlin data class CounterViewState( val count: Int = 0, val isLoading: Boolean = false ) sealed class CounterEvent { data class ShowToast(val message: String) : CounterEvent() } @Factory internal class CounterComponent( @InjectedParam componentContext: AppComponentContext, private val counterUseCase: CounterUseCase, ) : BaseComponent( componentContext = componentContext, defaultState = CounterViewState(), ) { init { startCounter() } private fun startCounter() { counterUseCase.execute(CounterUseCaseArgs(500.milliseconds)) { onNext { count -> componentState.update { it.copy(count = count.toInt()) } if (count == 10L) { sendUiEvent(CounterEvent.ShowToast("Reached 10!")) } } } } } ``` -------------------------------- ### Generated Factory Method Example Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/Annotations.md An approximate example of a factory object generated by the code processor. It shows how to create instances of a component with dependencies injected. ```kotlin object MyComponentFactory { fun createComponent( componentContext: AppComponentContext, myUseCase: MyUseCase = get(), ): MyComponent { return MyComponent( componentContext = componentContext, myUseCase = myUseCase ) } } ``` -------------------------------- ### Incorrect Binding Syntax using Binding(get:set:) Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/iosApp/CLAUDE.md Illustrates the verbose and incorrect method of creating bindings using the Binding(get:set:) initializer, which should be avoided. ```swift // Wrong TabView(selection: Binding( get: { model.selectedTab }, set: { model.onTabSelected($0) } )) { ... } ``` -------------------------------- ### UseCaseConfig Builder Example Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/UseCaseExecution.md Demonstrates customizing the error handling for a UseCase execution. Allows for specific error type handling and re-throwing unknown errors. ```kotlin myUseCase.execute(args) { onError { when (error) { is NetworkError.ConnectionError -> { componentState.update { it.copy(error = "No internet") } } is NetworkError -> { componentState.update { it.copy(error = "Network error") } } else -> { throw error // Re-throw unknown errors } } } } ``` -------------------------------- ### Implement GetUserUseCase Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/UseCase.md Example implementation of a UseCase for fetching a user. It depends on UserRepository and defines arguments for the user ID. ```kotlin @Factory internal class GetUserUseCase( private val userRepository: UserRepository ) : UseCase() { override suspend fun build(args: GetUserArgs): User { return userRepository.getUser(args.userId) } } data class GetUserArgs(val userId: String) ``` -------------------------------- ### Example: Resolving a Deep Link URI Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/DeepLinking.md Illustrates how to use the `DeepLinkResolver.resolve` method and handle the resulting `DeepLinkDestination`, including navigating based on specific screen arguments. ```kotlin val destination = deepLinkResolver.resolve("kmptemplate://home/third?arg=test") when (destination) { is DeepLinkDestination.ThirdScreen -> { // Navigate with destination.argument } else -> { // Handle invalid or unknown deep link } } ``` -------------------------------- ### Factory Component with Injected Parameters Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/Annotations.md An example of a component annotated with @Factory and @GenerateFactory, demonstrating dependency injection for parameters. ```kotlin @Factory @GenerateFactory internal class HomeComponent( @InjectedParam componentContext: AppComponentContext, private val homeUseCase: HomeUseCase, ) : BaseComponent( componentContext, defaultState = HomeViewState() ) ``` -------------------------------- ### StateFlow Conversion Example Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/BaseComponent.md Demonstrates converting a Flow of user data into a StateFlow representing the user's view state, using the asStateFlow extension function. ```kotlin val userFlow: Flow = userRepository.getUser() .map { componentState.value.copy(user = it) } val userStateFlow: StateFlow = userFlow.asStateFlow() ``` -------------------------------- ### Add GenerateFactory Annotation Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/Annotations.md Example demonstrating the addition of @GenerateFactory annotation to a class that should have a factory generated. ```kotlin @Factory @GenerateFactory // Add this class MyComponent(...) ``` -------------------------------- ### GraphQL Error Handling Example Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/GraphQLAPI.md Illustrates how to handle various network and GraphQL errors when fetching data using the NetworkResult wrapper. ```kotlin when (val result = api.getEpisodes()) { is NetworkResult.Success -> { val episodes = result.data // Process episodes } is NetworkResult.Failure -> { when (val error = result.error) { is NetworkError.CloudError -> { // Server-side GraphQL error logger.e { "GraphQL error: ${error.code}" } } is NetworkError.CloudHttpError -> { // HTTP error logger.e { "HTTP ${error.httpCode}" } } is NetworkError.ConnectionError -> { // Network unavailable logger.e { "No connection" } } is NetworkError.UnknownError -> { // Unexpected error logger.e(error.cause) { "Unknown error" } } } } } ``` -------------------------------- ### GetPersonUseCase Implementation Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/RESTAPI.md Example of a UseCase that utilizes the StarWarsApi to fetch a Person. It handles success and failure cases from the NetworkResult. ```kotlin @Factory internal class GetPersonUseCase( private val starWarsApi: StarWarsApi ) : UseCase() { override suspend fun build(args: GetPersonArgs): Person { return when (val result = starWarsApi.getPerson(args.personId)) { is NetworkResult.Success -> result.data is NetworkResult.Failure -> throw result.error } } } data class GetPersonArgs(val personId: Int) ``` -------------------------------- ### UseCaseConfig Class Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/types.md Configuration for use case execution callbacks, including start, success, error, and disposePrevious options. ```kotlin class UseCaseConfig private constructor( val onStart: () -> Unit, val onSuccess: (T) -> Unit, val onError: (Throwable) -> Unit, val disposePrevious: Boolean, ) ``` -------------------------------- ### Loading Episodes in Component Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/GraphQLAPI.md Example of how to call the getEpisodesUseCase within a component to load and update the UI state with episodes or display an error message. ```kotlin private fun loadEpisodes() { getEpisodesUseCase.execute { onNext {\n episodes -> componentState.update { state -> state.copy(episodes = episodes) } } onError {\n error -> logger.e(error) { "Failed to load episodes" } componentState.update { state -> state.copy(error = "Could not load episodes") } } } } ``` -------------------------------- ### UseCase.execute (No Arguments) Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/UseCaseExecution.md Executes a single-shot use case that requires Unit as arguments. Configuration allows for callbacks on start, success, and error, as well as controlling the cancellation of previous executions. ```APIDOC ## UseCase.execute (No Arguments) ### Description Executes a single-shot use case that requires Unit as arguments. Configuration allows for callbacks on start, success, and error, as well as controlling the cancellation of previous executions. ### Method Signature ```kotlin fun UseCase.execute(config: UseCaseConfig.Builder.() -> Unit) ``` ### Parameters #### Configuration Lambda - **config** (UseCaseConfig.Builder.() -> Unit) - Required - Configuration lambda for setting up callbacks and behavior. ### Configuration Builder - **onStart** (() -> Unit) - Optional - Called before execution. - **onSuccess** ((T) -> Unit) - Optional - Called on successful execution with the result. - **onError** ((Throwable) -> Unit) - Optional - Called on execution error. - **disposePrevious** (Boolean) - Optional - Defaults to true. If true, cancels any previous execution of this use case. ### Example ```kotlin myUseCase.execute { onStart { /* handle start */ } onSuccess { result -> /* handle success */ } onError { error -> /* handle error */ } disposePrevious(true) } ``` ``` -------------------------------- ### Add Serializable Annotation Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/Annotations.md Example showing how to add the @Serializable annotation to a data class to make it serializable. ```kotlin @Serializable // Add this data class MyData(val id: String) ``` -------------------------------- ### Access moko-resources Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/configuration.md Demonstrates how to access shared string and drawable resources using the MR object. Includes an example of string formatting. ```kotlin // Access shared resources val string = MR.strings.app_name val drawable = MR.drawables.ic_launcher // String formatting MR.strings.welcome.format(userName) ``` -------------------------------- ### Download Apollo Schema Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/README.md Downloads the latest Apollo schema from introspection. This is part of the GraphQL network setup. ```gradle :shared:network:graphql:downloadApolloSchemaFromIntrospection ``` -------------------------------- ### Composable UI Function Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/Annotations.md A basic example of a @Composable function from Jetpack Compose, used for building Android UI. ```kotlin import androidx.compose.runtime.Composable @Composable fun MyScreen(viewState: MyViewState) { // Compose UI } ``` -------------------------------- ### Implement WatchUserProfileUseCase Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/UseCase.md Example implementation of a FlowUseCase for observing user profile changes. It takes a user ID and returns a Flow of UserProfile. ```kotlin @Factory internal class WatchUserProfileUseCase( private val userRepository: UserRepository ) : FlowUseCase() { override fun build(args: String): Flow { return userRepository.watchProfile(userId = args) } } ``` -------------------------------- ### Execute FlowUseCase with Arguments Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/UseCaseExecution.md Executes a FlowUseCase with specific arguments and a configuration lambda. Handles start, next, error, and completion events. ```kotlin data class WatchUserArgs(val userId: String) watchUserUseCase.execute(WatchUserArgs(userId = "123")) { onStart { componentState.update { it.copy(isLoading = true) } } onNext { user -> componentState.update { it.copy(user = user, isLoading = false) } } onError { componentState.update { it.copy(error = error, isLoading = false) } } onComplete { println("Watch completed") } } ``` -------------------------------- ### Complete Navigation Example: Child Component Logic Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/ResultFlow.md Shows the child component's logic for selecting an item and sending it back to the parent using ResultFlow. It sends a specific result type (e.g., FruitSelected) and then navigates back. ```kotlin // In child component private fun selectFruit(fruit: String) { launchWithHandler { resultFlow.sendResult(PickerResult.FruitSelected(fruit)) navigation.pop() } } ``` -------------------------------- ### Execute UseCase with Unit Arguments Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/UseCaseExecution.md Execute a use case that requires Unit as arguments. Configure callbacks for start, success, and error events, and control the cancellation of previous executions. ```kotlin fun UseCase.execute(config: UseCaseConfig.Builder.() -> Unit) ``` ```kotlin myUseCase.execute { onStart { componentState.update { it.copy(isLoading = true) } } onSuccess { componentState.update { it.copy(data = result, isLoading = false) } } onError { componentState.update { it.copy(error = error.message, isLoading = false) } } disposePrevious(true) // Default behavior } ``` -------------------------------- ### Example of getOrCancel Usage Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/UseCaseExecutionScope.md Shows how to use the getOrCancel extension function within a launchWithHandler block to retrieve user data or cancel the coroutine if an error occurs. ```kotlin launchWithHandler { val user = getUserUseCase.execute(userId).getOrCancel() // Use user... } ``` -------------------------------- ### Execute Simple FlowUseCase Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/UseCaseExecution.md Executes a FlowUseCase without arguments, handling start, next, error, and completion events. Ensures previous executions are disposed. ```kotlin counterUseCase.execute { onStart { println("Counter started") } onNext { count -> componentState.update { it.copy(counter = count) } } onError { error -> println("Counter error: ${error.message}") } onComplete { println("Counter completed") } disposePrevious(true) } ``` -------------------------------- ### FlowUseCaseConfig Class Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/types.md Configuration for flow use case execution, including callbacks for start, next, error, complete, disposePrevious, and an optional mapper. ```kotlin class FlowUseCaseConfig private constructor( val onStart: () -> Unit, val onNext: (M) -> Unit, val onError: (Throwable) -> Unit, val onComplete: () -> Unit, val disposePrevious: Boolean, val onMap: ((T) -> M)? = null, ) ``` -------------------------------- ### Project Structure Overview Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/README.md Illustrates the directory structure of the shared module within the KMP Futured Template project, highlighting key subdirectories for application setup, features, network clients, persistence, platform integration, resources, use cases, and navigation helpers. ```tree shared/ ├── app/ # Application setup and initialization ├── feature/ # Feature modules, components, and domain logic ├── network/ │ ├── graphql/ # GraphQL client (Apollo) │ └── rest/ # REST client (Ktorfit) ├── persistence/ # DataStore persistence layer ├── platform/ # Platform bindings and native integration ├── resources/ # Shared resources (strings, images) ├── arkitekt-cr-usecases/ # Use case base classes and execution scopes └── arkitekt-decompose/ # Decompose extensions and navigation helpers ``` -------------------------------- ### Execute FlowUseCase with Unit Arguments Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/UseCaseExecution.md Execute a flow-based use case that requires Unit as arguments. Configure callbacks for start, next emission, error, completion, and previous flow cancellation. ```kotlin fun FlowUseCase.execute( config: FlowUseCaseConfig.Builder.() -> Unit ) ``` -------------------------------- ### Try-Catch in Suspending Code with Error Handling Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/README.md Use a `launchWithHandler` block to execute suspending code with built-in error handling. This example demonstrates catching specific network errors and updating the UI state. ```kotlin launchWithHandler { try { val data = useCase.execute(args).getOrThrow() } catch (error: NetworkError.ConnectionError) { updateState { copy(error = "No connection") } } } ``` -------------------------------- ### Component Load Person Logic Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/RESTAPI.md Demonstrates how to call the getPersonUseCase within a component and update the UI state based on the result (success, error, or start). ```kotlin private fun loadPerson(personId: Int) { getPersonUseCase.execute(GetPersonArgs(personId = personId)) { onSuccess { person -> componentState.update { state -> state.copy( person = person, isLoading = false ) } } onError { error -> componentState.update { state -> state.copy( error = formatError(error), isLoading = false ) } } onStart { componentState.update { it.copy(isLoading = true) } } } } private fun formatError(error: Throwable): String { return when (error) { is NetworkError.CloudHttpError -> { when (error.httpCode) { 404 -> "Person not found" else -> "Server error (${error.httpCode})" } } is NetworkError.ConnectionError -> "No internet connection" else -> "Unknown error occurred" } } ``` -------------------------------- ### Local Swift Package Manager Integration Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/configuration.md Example of importing a local Swift Package Manager module in an iOS project. Assumes the package is located at 'iosApp/shared/KMP/'. ```swift // Local SPM package at iosApp/shared/KMP/ import KMP ``` -------------------------------- ### Bottom Tab Navigation Host Component Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/NavigationExtensions.md An example implementation of a navigation host component for bottom tab navigation using Decompose. It utilizes StackNavigator to manage the tab stack and child stacks for each tab's content. ```kotlin @Factory internal class SignedInNavHostComponent( @InjectedParam componentContext: AppComponentContext, ) : BaseComponent( componentContext, defaultState = SignedInNavHostViewState() ) { private val tabNavigator = StackNavigator() private val stack = childStack( source = tabNavigator, serializer = NavigationTab.serializer(), initialConfiguration = { NavigationTab.Home }, handleBackButton = false, childFactory = { config, context -> when (config) { NavigationTab.Home -> createHomeTab(context) NavigationTab.Profile -> createProfileTab(context) } } ) override fun onTabSelected(tab: NavigationTab) { tabNavigator.switchTab(configuration = tab) } } ``` -------------------------------- ### Get Episodes Use Case Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/GraphQLAPI.md A use case for fetching episodes using the RickAndMortyApi. It handles success and failure scenarios, emitting the episode data or throwing an error. ```kotlin @Factory internal class GetEpisodesUseCase( private val rickAndMortyApi: RickAndMortyApi ) : FlowUseCase>() { override fun build(args: Unit): Flow> = flow { when (val result = rickAndMortyApi.getEpisodes()) { is NetworkResult.Success -> { emit(result.data) } is NetworkResult.Failure -> { throw result.error } } } } ``` -------------------------------- ### Initialize Project Template Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/README.md Use this script to set up the KMP template. It renames directories and package names to match your project's specifications. ```shell ./init_template.sh ``` -------------------------------- ### KmpApplication.initializeSharedApplication Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/KmpApplication.md Initializes the shared KMP application, setting up dependency injection, crash reporting, and logging. ```APIDOC ## KmpApplication.initializeSharedApplication ### Description Initializes the shared application with dependency injection, crash reporting, and logging. ### Method ```kotlin fun initializeSharedApplication( platformBindings: PlatformBindings, appDeclaration: KoinAppDeclaration? = null, ) ``` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```kotlin // In Android MainActivity or iOS app initialization KmpApplication.initializeSharedApplication( platformBindings = AndroidPlatformBindings(), appDeclaration = { // Optional: add custom Koin modules modules(customModule) } ) ``` ### Response #### Success Response (Unit) Returns Unit upon successful initialization. #### Response Example None (returns Unit) ### Throws - Throws an exception if platform bindings are not valid - Throws if Koin cannot be initialized (e.g., already initialized) ``` -------------------------------- ### FlowUseCase.execute (No Arguments) Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/UseCaseExecution.md Executes a flow-based use case that requires Unit as arguments. The configuration lambda allows setting callbacks for when the flow starts, emits values, encounters errors, or completes, and also controls the cancellation of previous flow executions. ```APIDOC ## FlowUseCase.execute (No Arguments) ### Description Executes a flow-based use case that requires Unit as arguments. The configuration lambda allows setting callbacks for when the flow starts, emits values, encounters errors, or completes, and also controls the cancellation of previous flow executions. ### Method Signature ```kotlin fun FlowUseCase.execute( config: FlowUseCaseConfig.Builder.() -> Unit ) ``` ### Parameters #### Configuration Lambda - **config** (FlowUseCaseConfig.Builder.() -> Unit) - Required - Configuration lambda for setting up callbacks and behavior. ### Configuration Builder - **onStart** (() -> Unit) - Optional - Called when the flow starts. - **onNext** ((T) -> Unit) - Optional - Called for each value emitted by the flow. - **onError** ((Throwable) -> Unit) - Optional - Called when an error occurs in the flow. - **onComplete** (() -> Unit) - Optional - Called when the flow completes successfully. - **disposePrevious** (Boolean) - Optional - Defaults to true. If true, cancels any previous execution of this flow use case. ``` -------------------------------- ### Build Product Flavor with Gradle Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/configuration.md Builds a specific product flavor (e.g., production) using a Gradle command with a system property override. ```bash ./gradlew task -P buildkonfig.flavor=prod ``` -------------------------------- ### PrimitivePersistence Get Method Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/Persistence.md Retrieves a persisted value by its key. Returns null if the value is not found. ```kotlin suspend fun get(key: Preferences.Key): T? ``` -------------------------------- ### Initialize KMP Application with Platform Bindings Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/PlatformBindings.md Initialize the shared KMP application by providing an implementation of PlatformBindings. This is typically done during the application's initialization phase. ```kotlin KmpApplication.initializeSharedApplication( platformBindings = PlatformBindingsImpl(), // Provided by platform ) ``` -------------------------------- ### Using KMP Localization Keys Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/iosApp/CLAUDE.md Demonstrates the correct way to use KMP localization keys with the `.localized` extension for accessing translated strings from `strings.xml`. ```swift // Correct Text(Localizable.first_screen_title.localized) Button(Localizable.first_screen_button.localized, action: model.onNext) // Wrong — hardcoded string Text("First Screen") ``` -------------------------------- ### platform() Method Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/PlatformBindings.md Returns information about the current platform and application, including OS name, version, app version, and build type. ```APIDOC ## Method: platform Returns information about the current platform and application. ```kotlin fun platform(): Platform ``` ### Return Type `Platform` — Platform information object ### Example ```kotlin val platformInfo = platformBindings.platform() val osName = platformInfo.osName // e.g., "Android" or "iOS" ``` ``` -------------------------------- ### Run All Tests Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/CLAUDE.md Execute all unit and integration tests for the project. ```bash ./gradlew test ``` -------------------------------- ### Load and Observe User Profile in Components Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/Persistence.md Demonstrates how to load a user profile on component initialization and set up a reactive observer for profile updates. This is useful for updating UI components when profile data changes. ```kotlin import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach private fun loadUserProfile() { launchWithHandler { val profile = profilePersistence.getProfile() if (profile != null) { componentState.update { it.copy(userProfile = profile) } } } } private fun observeProfile() { profilePersistence.observeProfile() .onEach { profile -> componentState.update { it.copy(userProfile = profile) } } .launchIn(componentCoroutineScope) } ``` -------------------------------- ### Handle CloudError in Network Result Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/errors.md Example of how to check for and handle a CloudError when processing a NetworkResult. It extracts the specific error code for further handling. ```kotlin when (result) { is NetworkResult.Failure -> { when (result.error) { is NetworkError.CloudError -> { val code = (result.error as NetworkError.CloudError).code // Handle specific error code } else -> {} } } else -> {} } ``` -------------------------------- ### Basic Component for Fetching Episodes Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/GraphQLAPI.md Demonstrates a basic component that fetches episodes using a use case. It handles loading states, successful data retrieval, and errors. ```kotlin import com.future.apix.core.component.BaseComponent import com.future.apix.core.component.context.AppComponentContext import com.future.apix.core.component.context.InjectedParam import com.future.apix.core.component.context.componentContext import com.future.apix.core.component.context.doOnCreate import com.future.apix.core.component.context.update import com.future.apix.core.component.context.Factory @Factory internal class EpisodesComponent( @InjectedParam componentContext: AppComponentContext, private val getEpisodesUseCase: GetEpisodesUseCase, ) : BaseComponent( componentContext, defaultState = EpisodesViewState() ) { init { doOnCreate { loadEpisodes() } } private fun loadEpisodes() { getEpisodesUseCase.execute { onNext { episodes -> componentState.update { it.copy(episodes = episodes, isLoading = false) } } onError { error -> componentState.update { it.copy(error = error.toString(), isLoading = false) } } onStart { componentState.update { it.copy(isLoading = true) } } } } } ``` -------------------------------- ### Manual KMP Package Build with Flavor Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/README.md Manually builds the KMP package, allowing specification of the product flavor. The default flavor is 'dev'. ```bash ./gradlew assembleAndCopyDebugSwiftPackage -P buildkonfig.flavor=[dev|prod] ``` -------------------------------- ### Correct Binding Syntax with @State Model Properties Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/iosApp/CLAUDE.md Demonstrates the correct and concise way to create bindings to properties of an @State model using the '$' projection syntax. ```swift // Correct TabView(selection: $model.selectedTab) { ... } .sheet(item: $model.sheetItem) { ... } .alert("", isPresented: $model.alert.isPresented) { ... } ``` -------------------------------- ### Serializable Data Class for Apollo Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/Annotations.md Example of a data class generated by Apollo from a GraphQL schema, marked with @Serializable for Kotlinx serialization. ```kotlin import kotlinx.serialization.Serializable // Apollo generates these from GraphQL schema @Serializable data class EpisodeFragment( val id: String, val name: String, val episode: String, ) ``` -------------------------------- ### Usage of Generated Factory in Navigation Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/Annotations.md Illustrates how to use the generated factory to create and navigate to a component. Dependencies not explicitly passed are expected to be auto-injected from Koin. ```kotlin // In parent component private fun openUserProfile(userId: String) { val profileComponent = UserProfileComponentFactory.createComponent( componentContext = childComponentContext, navigation = myNavigation // Other dependencies auto-injected from Koin ) navigator.push(profileComponent) } ``` -------------------------------- ### Custom Error Handling Implementation Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/UseCaseExecutionScope.md Example of overriding defaultErrorHandler to log errors to analytics and update the UI state with the error message. ```kotlin class MyComponent : UseCaseExecutionScope { override fun defaultErrorHandler(exception: Throwable) { // Log to analytics analyticsService.logError(exception) // Update UI state viewState.value = viewState.value.copy(error = exception.message) } } ``` -------------------------------- ### Pattern Matching with NetworkResult Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/NetworkResult.md Demonstrates how to use Kotlin's 'when' statement to handle both Success and Failure cases of a NetworkResult. ```kotlin when (val result = api.getEpisodes()) { is NetworkResult.Success -> { val episodes = result.data // Process episodes } is NetworkResult.Failure -> { val error = result.error // Handle error } } ``` -------------------------------- ### Execute UseCase and FlowUseCase in Component Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/UseCase.md Demonstrates how to execute single-shot UseCases and reactive FlowUseCases within a component using their respective execution scopes. ```kotlin class MyComponent : UseCaseExecutionScope { // Execute single-shot use case private fun loadUser(userId: String) { getUserUseCase.execute(GetUserArgs(userId = userId)) { onSuccess { user -> // Handle user } onError { error -> // Handle error } } } // Execute flow use case private fun observeUserProfile(userId: String) { watchUserProfileUseCase.execute(userId) { onNext { profile -> // Handle each emitted profile } onError { error -> // Handle error } onComplete { // Flow completed } } } } ``` -------------------------------- ### Get Person Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/RESTAPI.md Fetches a single person by their unique ID from the Star Wars API. Handles success, not found, and server errors. ```APIDOC ## GET /api/people/{id} ### Description Fetches a single person by ID from the Star Wars API. ### Method GET ### Endpoint `https://swapi.dev/api/people/{id}` ### Parameters #### Path Parameters - **id** (Int) - Required - The unique ID of the person to fetch. ### Request Example (No request body for GET requests) ### Response #### Success Response (200) - **data** (Person) - The fetched person object. #### Response Example ```json { "name": "Luke Skywalker", "homeworld": "https://swapi.dev/api/planets/1/", "gender": "male", "url": "https://swapi.dev/api/people/1/" } ``` #### Error Handling - **404 Not Found**: Person with the specified ID not found. - **500 Internal Server Error**: An error occurred on the server. - **Network Errors**: Includes connection errors and unknown errors during the request. ``` -------------------------------- ### JsonPersistence Get Method Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/Persistence.md Retrieves and deserializes a persisted JSON object. Returns null if not found. Throws SerializationException on deserialization failure. ```kotlin suspend inline fun get( key: Preferences.Key ): T? ``` -------------------------------- ### Generate Apollo Sources Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/README.md Generates Apollo sources, which rebuilds models after modifying queries or mutations. This is part of the GraphQL network setup. ```gradle :shared:network:graphql:generateApolloSources ``` -------------------------------- ### Execute UseCase with Arguments Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/UseCaseExecution.md Execute a use case with provided arguments. This method handles argument passing, callback execution on the main thread, and error logging. ```kotlin fun UseCase.execute( args: ARGS, config: UseCaseConfig.Builder.() -> Unit, ) ``` ```kotlin data class GetUserArgs(val userId: String) getUserUseCase.execute(GetUserArgs(userId = "123")) { onStart { println("Loading user...") } onSuccess { println("Got user: ${user.name}") componentState.update { it.copy(user = user) } } onError { println("Failed to load: ${error.message}") } } ``` -------------------------------- ### Component for Fetching Paginated Episodes Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/GraphQLAPI.md Illustrates how to implement pagination for fetching more episodes. It appends new episodes to the existing list and updates the current page number. ```kotlin // Fetch next page of results private fun loadMoreEpisodes() { getEpisodesPageUseCase.execute(GetEpisodesPageArgs(page = currentPage + 1)) { onNext { episodes -> componentState.update { state -> state.copy( episodes = state.episodes + episodes, currentPage = currentPage + 1 ) } } onError { error -> // Handle error } } } ``` -------------------------------- ### UseCase.execute (With Arguments) Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/UseCaseExecution.md Executes a single-shot use case with provided arguments. It supports callbacks and manages execution flow, including cancellation of previous runs and error logging. ```APIDOC ## UseCase.execute (With Arguments) ### Description Executes a single-shot use case with provided arguments. It supports callbacks and manages execution flow, including cancellation of previous runs and error logging. ### Method Signature ```kotlin fun UseCase.execute( args: ARGS, config: UseCaseConfig.Builder.() -> Unit, ) ``` ### Parameters #### Path Parameters - **args** (ARGS) - Required - Arguments for the use case. - **config** (UseCaseConfig.Builder.() -> Unit) - Required - Configuration lambda for setting up callbacks and behavior. ### Configuration Builder - **onStart** (() -> Unit) - Optional - Called before execution. - **onSuccess** ((T) -> Unit) - Optional - Called on successful execution with the result. - **onError** ((Throwable) -> Unit) - Optional - Called on execution error. - **disposePrevious** (Boolean) - Optional - Defaults to true. If true, cancels any previous execution of this use case. ### Behavior - Executes use case with provided arguments. - Cancels previous execution (default) based on `disposePrevious`. - Calls callbacks on the main thread. - Logs errors via `UseCaseErrorHandler.globalOnErrorLogger`. ### Execution Flow ``` onStart() called ↓ build(args) executes on worker thread ↓ Success? → onSuccess(result) on main thread ↓ Error? → UseCaseErrorHandler.globalOnErrorLogger(error) → onError(error) on main thread → throw error (unless onError overridden) ``` ### Example with Arguments ```kotlin data class GetUserArgs(val userId: String) getUserUseCase.execute(GetUserArgs(userId = "123")) { onStart { println("Loading user...") } onSuccess { user -> println("Got user: ${user.name}") } onError { error -> println("Failed to load: ${error.message}") } } ``` ``` -------------------------------- ### Catch UnknownError for Logging and Reporting Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/errors.md Example of catching a NetworkError.UnknownError to log the unexpected error and report it to a crash reporting service. This is crucial for identifying and fixing bugs. ```kotlin try { val result = api.getEpisodes().getOrThrow() } catch (error: NetworkError.UnknownError) { logger.e(error) { "Unexpected network error" } // Report to analytics/crash reporting crashlytics.recordException(error) } ``` -------------------------------- ### Build Swift Package with Build Flavor Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/README.md Build the Swift Package for iOS, passing the KMP build flavor dynamically from an environment variable. This ensures the correct flavor is used during the build process. ```shell ./gradlew assembleAndCopyDebugSwiftPackage -P buildkonfig.flavor=$(KMP_BUILD_FLAVOR) ``` -------------------------------- ### Using NetworkResult in Use Cases Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/NetworkResult.md Shows how to integrate NetworkResult within a UseCase, unwrapping the data on success or throwing the error on failure. ```kotlin @Factory internal class GetCharacterUseCase( private val rickAndMortyApi: RickAndMortyApi ) : UseCase() { override suspend fun build(args: Int): CharacterData { return when (val result = rickAndMortyApi.getCharacter(args)) { is NetworkResult.Success -> result.data is NetworkResult.Failure -> throw result.error } } } ``` -------------------------------- ### Parent Component: Opening a Picker with ResultFlow Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/ResultFlow.md Demonstrates how a parent component opens a child component (e.g., a picker) and sets up a ResultFlow to receive results back. It collects results using onEach and launches the flow collection in a coroutine scope. ```kotlin sealed class SecondScreenConfig : Parcelable { data class PickerScreen( val resultFlow: ResultFlow ) : SecondScreenConfig() } @Factory internal class SecondComponent( @InjectedParam componentContext: AppComponentContext, @InjectedParam override val navigation: SecondScreenNavigation, ) : ScreenComponent( componentContext = componentContext, defaultState = SecondViewState(), ) { override fun openPicker() { val resultFlow = ResultFlow() // Collect results from child resultFlow .onEach { result -> handlePickerResult(result) } .launchIn(componentCoroutineScope) // Navigate to picker with result flow navigation.navigateToPicker(resultFlow) } private fun handlePickerResult(result: PickerResult) { componentState.update { state -> state.copy(selectedItem = result.item) } } } ``` -------------------------------- ### Multiple API Implementations with Qualifiers Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/Annotations.md Demonstrates defining multiple implementations of an interface (UserApi) using @Qualifier annotations for differentiation. ```kotlin @Qualifier annotation class MockApi @Qualifier annotation class RealApi @Factory @RealApi class RealUserApi : UserApi @Factory @MockApi class MockUserApi : UserApi ``` -------------------------------- ### Handle CloudHttpError by HTTP Code Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/errors.md Example of catching a NetworkError.CloudHttpError and handling different HTTP status codes. This allows for specific responses to various client and server errors. ```kotlin try { val person = api.getPerson(1).getOrThrow() } catch (error: NetworkError.CloudHttpError) { when (error.httpCode) { 404 -> println("Resource not found") 500 -> println("Server error, try again later") else -> println("HTTP ${error.httpCode}") } } ``` -------------------------------- ### Specify Build Flavor via Gradle Flag Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/README.md Specify the product flavor (e.g., 'dev' or 'prod') for Gradle tasks using a project property. ```shell ./gradlew whateverTask -P buildkonfig.flavor=dev ``` -------------------------------- ### kotlinx.serialization @SerialName Annotation Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/Annotations.md Example of using the @SerialName annotation from kotlinx.serialization. This annotation maps Kotlin property names to different JSON field names during serialization and deserialization. ```kotlin @Serializable data class Person( @SerialName("name") val name: String? = null, @SerialName("homeworld") val homeworld: String? = null, ) ``` -------------------------------- ### Execute Suspend UseCase and Get Result Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/UseCaseExecution.md Synchronously execute a suspend use case and obtain a Result object. This allows for direct handling of success or failure outcomes. ```kotlin suspend fun UseCase.execute( args: ARGS, cancelPrevious: Boolean = true, ): Result ``` ```kotlin launchWithHandler { val result = getUserUseCase.execute(GetUserArgs(userId = "123")) result.onSuccess { user -> componentState.update { it.copy(user = user) } }.onFailure { error -> componentState.update { it.copy(error = error) } } } ``` ```kotlin launchWithHandler { try { val user = getUserUseCase.execute(GetUserArgs(userId = "123")).getOrThrow() // Use user } catch (error: Throwable) { // Handle error } } ``` -------------------------------- ### Assemble and Copy Release Swift Package Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/README.md Assembles the release KMP XCFramework and copies it into the local iOS Swift Package. This task is typically not used directly; building the KMP target in Xcode is preferred. ```gradle assembleAndCopyReleaseSwiftPackage ``` -------------------------------- ### Get Result Value or Cancel Coroutine Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/UseCaseExecutionScope.md Extension function for Result that returns the successful value or throws CancellationException if the Result is a failure. Useful for simplifying use case execution flow. ```kotlin fun Result.getOrCancel(): T ``` -------------------------------- ### Set Development Product Flavor (iOS) Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/configuration.md Configures the iOS build to use development API endpoints by setting the KMP_BUILD_FLAVOR in the .xcconfig file. ```text # Build configuration (.xcconfig files) KMP_BUILD_FLAVOR = dev ``` -------------------------------- ### Assemble and Copy Debug Swift Package Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/README.md Assembles the debug KMP XCFramework and copies it into the local iOS Swift Package. This task is typically not used directly; building the KMP target in Xcode is preferred. ```gradle assembleAndCopyDebugSwiftPackage ``` -------------------------------- ### Initialize Shared KMP Application Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/KmpApplication.md Use this function to initialize the shared KMP application. It requires platform-specific bindings and can optionally accept a Koin module declaration for custom configurations. ```kotlin fun initializeSharedApplication( platformBindings: PlatformBindings, appDeclaration: KoinAppDeclaration? = null, ) ``` ```kotlin // In Android MainActivity or iOS app initialization KmpApplication.initializeSharedApplication( platformBindings = AndroidPlatformBindings(), appDeclaration = { // Optional: add custom Koin modules modules(customModule) } ) ``` -------------------------------- ### Handling Architecture Errors during Component Initialization Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/errors.md Architecture errors can occur during Decompose component initialization, factory method generation, or navigation configuration. This example shows a Koin injection error if a required dependency is missing. ```kotlin // Koin injection error if dependencies are missing @Factory internal class MyComponent( @InjectedParam componentContext: AppComponentContext, private val requiredDependency: SomeDependency // Fails if not in Koin ) ``` -------------------------------- ### Usage of GenerateFactory and Koin Factory Annotations Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/Annotations.md Demonstrates how to apply @Factory and @GenerateFactory annotations to a class. This is used for dependency injection via Koin and automatic factory method generation. ```kotlin @Factory // Koin annotation for DI @GenerateFactory // Generate factory method internal class MyComponent( @InjectedParam componentContext: AppComponentContext, private val myUseCase: MyUseCase, ) : BaseComponent(componentContext, MyViewState()) ``` -------------------------------- ### Build and Copy Debug Swift Package Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/CLAUDE.md Builds the debug XCFramework for Swift Package Manager and copies it to the appropriate location. ```bash ./gradlew assembleAndCopyDebugSwiftPackage ``` -------------------------------- ### Mock API Implementation Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/RESTAPI.md Create a mock implementation of StarWarsApi for testing purposes, returning specific data or errors based on the personId. ```kotlin internal class MockStarWarsApi : StarWarsApi { override suspend fun getPerson(personId: Int): NetworkResult { return when (personId) { 1 -> NetworkResult.Success( Person( name = "Luke Skywalker", homeworld = "https://swapi.dev/api/planets/1/", gender = "male", url = "https://swapi.dev/api/people/1/" ) ) else -> NetworkResult.Failure( NetworkError.CloudHttpError(404, "Not found") ) } } } ``` -------------------------------- ### Debug Mock for SwiftUI Previews Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/iosApp/CLAUDE.md Provides a mock implementation of a ComponentModel for use in SwiftUI previews during development. It includes sample data and placeholder actions. ```swift #if DEBUG @Observable final class MyComponentModelMock: MyComponentModelProtocol { var title = "Preview Title" var alert: AlertModel? func onAction() {} } #endif ``` -------------------------------- ### Set iOS Build Environment Variables Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/configuration.md Configures iOS build settings like framework type, build flavor, and build mode using environment variables. ```text KMP_FRAMEWORK_BUILD_TYPE=debug # or "release" KMP_BUILD_FLAVOR=dev # or "prod" KMP_BUILD_MODE=simulator # or "device", "all" ``` -------------------------------- ### Run ktlint Checks and Formatting Source: https://github.com/futuredapp/kmp-futured-template/blob/develop/_autodocs/configuration.md Gradle commands to execute ktlint for code style checks and auto-formatting. ```bash ./gradlew lintCheck # Run checks ./gradlew ktlintFormat # Auto-format ```