Giter Club home page Giter Club logo

githubsearchkmm's Introduction

GithubSearchKMM

Github Repos Search - Kotlin Multiplatform Mobile using Jetpack Compose, SwiftUI, FlowRedux, Coroutines Flow, Dagger Hilt, Koin Dependency Injection, shared KMP ViewModel, Clean Architecture

Android Build CI iOS Build CI Validate Gradle Wrapper API Kotlin Hits License: MIT codecov Platform

Minimal Kotlin Multiplatform project with SwiftUI, Jetpack Compose.

  • Android (Jetpack compose)
  • iOS (SwiftUI)

Liked some of my work? Buy me a coffee (or more likely a beer)

Buy Me A Coffee

Modern Development

  • Kotlin Multiplatform
  • Jetpack Compose
  • Kotlin Coroutines & Flows
  • Dagger Hilt
  • SwiftUI
  • Koin Dependency Injection
  • FlowRedux State Management
  • Shared KMP ViewModel
  • Clean Architecture

Tech Stacks

Screenshots

Android (Light theme)

Android (Dark theme)

iOS (Light theme)

iOS (Dark theme)

Overall Architecture

What is shared?

  • domain: Domain models, UseCases, Repositories.
  • presentation: ViewModels, ViewState, ViewSingleEvent, ViewAction.
  • data: Repository Implementations, Remote Data Source, Local Data Source.
  • utils: Utilities, Logging Library

Unidirectional data flow - FlowRedux

RxRedux In a Nutshell

public sealed interface FlowReduxStore<Action, State> {
  public val coroutineScope: CoroutineScope

  public val stateFlow: StateFlow<State>

  /** Get streams of actions.
   *
   * This [Flow] includes dispatched [Action]s (via [dispatch] function)
   * and [Action]s returned from [SideEffect]s.
   */
  public val actionSharedFlow: SharedFlow<Action>

  /**
   * @return false if cannot dispatch action ([coroutineScope] was cancelled).
   */
  public fun dispatch(action: Action): Boolean
}

Multiplatform ViewModel

open class GithubSearchViewModel(
  searchRepoItemsUseCase: SearchRepoItemsUseCase,
) : ViewModel() {
  private val store = viewModelScope.createFlowReduxStore(
    initialState = GithubSearchState.initial(),
    sideEffects = GithubSearchSideEffects(
      searchRepoItemsUseCase = searchRepoItemsUseCase,
    ).sideEffects,
    reducer = { state, action -> action.reduce(state) }
  )
  private val eventChannel = store.actionSharedFlow
    .mapNotNull { it.toGithubSearchSingleEventOrNull() }
    .buffer(Channel.UNLIMITED)
    .produceIn(viewModelScope)

  fun dispatch(action: GithubSearchAction) = store.dispatch(action)
  val stateFlow: StateFlow<GithubSearchState> by store::stateFlow
  val eventFlow: Flow<GithubSearchSingleEvent> get() = eventChannel.receiveAsFlow()
}

Platform ViewModel

Android

Extends GithubSearchViewModel to use Dagger Constructor Injection.

@HiltViewModel
class DaggerGithubSearchViewModel @Inject constructor(searchRepoItemsUseCase: SearchRepoItemsUseCase) :
  GithubSearchViewModel(searchRepoItemsUseCase)

iOS

Conform to ObservableObject and use @Published property wrapper.

import Foundation
import Combine
import shared
import sharedSwift

@MainActor
class IOSGithubSearchViewModel: ObservableObject {
  private let vm: GithubSearchViewModel

  @Published private(set) var state: GithubSearchState
  let eventPublisher: AnyPublisher<GithubSearchSingleEventKs, Never>

  init(vm: GithubSearchViewModel) {
    self.vm = vm

    self.eventPublisher = vm.eventFlow.asNonNullPublisher()
      .assertNoFailure()
      .map(GithubSearchSingleEventKs.init)
      .eraseToAnyPublisher()

    self.state = vm.stateFlow.typedValue()
    vm.stateFlow.subscribeNonNullFlow(
      scope: vm.viewModelScope,
      onValue: { [weak self] in self?.state = $0 }
    )
  }

  @discardableResult
  func dispatch(action: GithubSearchAction) -> Bool {
    self.vm.dispatch(action: action)
  }

  deinit {
    Napier.d("\(self)::deinit")
    vm.clear()
  }
}

Download APK

Building & Develop

  • Android Studio Chipmunk | 2021.2.1 (note: Java 11 is now the minimum version required).

  • XCode 13.2 or later (due to use of new Swift 5.5 concurrency APIs).

  • Clone project: git clone https://github.com/hoc081098/GithubSearchKMM.git

  • Android: open project by Android Studio and run as usual.

  • iOS

    cd GithubSearchKMM
    
    # generate podspec files for cocopods intergration. with integration will be generated swift files for cocoapod
    ./gradlew kSwiftsharedPodspec
    
    # go to ios dir
    cd iosApp
    
    # install pods
    pod install
    
    # now we can open xcworkspace and build ios project
    # or open via XCode GUI
    open iosApp.xcworkspace

    There's a Build Phase script that will do the magic. 🧞
    Cmd + B to build
    Cmd + R to run.

LOC

--------------------------------------------------------------------------------
 Language             Files        Lines        Blank      Comment         Code
--------------------------------------------------------------------------------
 Kotlin                  78         4422          496          373         3553
 Swift                   16          861          110           98          653
 Markdown                 1          219           43            0          176
 JSON                     5          133            0            0          133
 Bourne Shell             1          240           28          110          102
 Batch                    1           91           21            0           70
 XML                      7           73            6            0           67
--------------------------------------------------------------------------------
 Total                  109         6039          704          581         4754
--------------------------------------------------------------------------------

githubsearchkmm's People

Contributors

hoc081098 avatar renovate[bot] avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.