⚡️ A Compose-driven architecture for Android apps.

Related tags

App circuit
Overview

Circuit

🚧 Under construction 🚧

This project is very much a work in progress and far from finished!

License

Copyright 2022 Slack Technologies, LLC

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Comments
  • Testing story

    Testing story

    What's our testing story look like?

    Use Turbine/molecule to poke along presenters and UIs? Use snapshot APIs directly? Some mix?

    UI tests for UI, Turbine/snapshot tests for presenters?

    discussion testing 
    opened by ZacSweers 7
  • Refactor CircuitInject

    Refactor CircuitInject

    Refactoring @CircuitInject into @CircuitPresenter and @CircuitUi. Functionally nothing is changing but this change makes the code much more readable and concise.  I'm purposefully omitting the "Inject" keyword because I think it adds unnecessary verbosity. If there is disagreement here I would consider adding an outer class CircuitInject and then have Presenter and Ui as inner classes.

    Also enforcing classes annotated with @CircuitPresenter and @CircuitUi end in 'Presenter' and 'Ui' respectively. This will help add consistency across the codebase and make features more readable.

    opened by showard51 5
  • Tinker with Paparazzi

    Tinker with Paparazzi

    Some early explorations

    • Mostly easy to set up and record baselines
    • Can nicely enforce in CI that files are checked in via lfs
    • Using circuit-core temporarily, not something we probably have much of a use for in circuit itself though. Maybe a multi-screen nav flow where we assert static screens at each step?

    Some early limitations

    • Only works in library modules - https://github.com/cashapp/paparazzi/issues/107
    • Doesn't work on compile SDK 33 yet - https://github.com/cashapp/paparazzi/issues/558
    • Requires extra config for JDK 16+ - https://github.com/cashapp/paparazzi/pull/566
    opened by ZacSweers 5
  • Make event sinks part of state instead

    Make event sinks part of state instead

    This reworks how we handle event sinks by embedding them within our state types instead of making them a top-level component of how Presenter and Ui work. Similar to what we were doing earlier on, but without the testability friction.

    The goal in this is to simplify our API ergonomics and also avoid some friction we've been running into with backing them with Flow.

    @adamp put it well in a private chat

    came out of some discussions from last night and this morning; we had talked before about passing forward the event emitter to a composable content lambda of the presenter, but the "continuation" [reference to how Coroutines passes a Continuation object around] made up of the caller after the return serves the same purpose with a tidier structure

    Which makes the whole thing analogous to passing some state and some callbacks to a regular composable, with all of the scoping behavior and expectations implied by that

    Now a presenter is just this

    class Presenter<UiState : CircuitUiState> {
      @Composable fun present(): UiState
    }
    

    And a simple counter example would be like this

    data class CounterState(val count: Int, val eventSink: (CounterEvent) -> Unit) : CircuitUiState
    
    sealed interface CounterEvent : CircuitUiEvent {
      object Increment : CounterEvent
      object Decrement : CounterEvent
    }
    
    class CounterPresenter<State> {
      @Composable
      override fun present(): State {
        var count by remember { mutableStateOf(0) }
        return CounterState(count) { event ->
          when (event) {
            is Increment -> count++
            is Decrement -> count--
          }
        }
      }
    }
    
    @Composable fun Counter(state: State) {
      Column {
        Text("Count: ${state.count}")
        Button(onClick = { state.eventSink(Increment) } { Text("Increment") }
        Button(onClick = { state.eventSink(Decrement) } { Text("Decrement") }
      }
    }
    

    Pros

    • Simpler in general for multiple reasons detailed in subsequent bullets, but just look at at the line diff on this PR alone
    • Only one type variable on Presenter and Ui types now.
    • Significantly simpler ergonomics with nested events. No ceremony with remembers and flow operators
    • Simpler ergonomics with event-less Uis. Simply omit events, no need for Nothing.
    • Testing is simpler, no manual event flow needed. Instead you tick your presenter along with the returned state's event sink.
      • Forces you to write more realistic tests too. For example – a "no animals" state test immediately stood out in tinkering here because you can't click an animal in that case and have no sink to emit to, so the test issue was obvious here and needed to be addressed.
      @Test
      fun `present - navigate to pet details screen`() = runTest {
        val repository = TestRepository(listOf(animal))
        val presenter = PetListPresenter(navigator, PetListScreen(), repository)
      
        presenter.test {
          assertThat(PetListScreen.State.Loading).isEqualTo(awaitItem())
          val successState = awaitItem()
          check(successState is PetListScreen.State.Success)
          assertThat(successState.animals).isEqualTo(listOf(animal).map { it.toPetListAnimal() })
      
          val clickAnimal = PetListScreen.Event.ClickAnimal(123L, "key")
          successState.eventSink(clickAnimal)
          assertThat(navigator.awaitNextScreen())
            .isEqualTo(PetDetailScreen(clickAnimal.petId, clickAnimal.photoUrlMemoryCacheKey))
        }
      }
      
    • Different state types can have different event handling (e.g. Click may not make sense for Loading states)
    • No ceremony around setting up a channel and multicasting event streams
    • Currently, while functions are treated as implicitly Stable by the compose compiler but not skippable when they're non-composable Unit-returning lambdas with equal-but-unstable captures. This may change though, and would be another free benefit for this case.
    • No risk of dropping events (unlike Flow)
    • Simpler overhead due to no coroutines in basic case

    Neutral (could be pro or con)

    • States could contain event sink functions or expose an interface that Uis could call functions on

    Cons

    • State needs to be unpacked in the presenter function and then bundled up when returned.
      • Could be a good thing though with better granularity. We've already seen cases where we aggregate multiple states into the final one
    • Event sinks being part of state objects may seem surprising at first
      • They do make sense when considering different states have different contexts and events that may emit within them.
    • Simple states (such as Loading) or multiple substates may feel slightly more pedantic if they must expose event sinks or share the same event logic.
      • Pattern so far – write shared event logic once and reuse it, such as a function call or local remembered function var.
    opened by ZacSweers 4
  • Implement rememberRetained and produceRetainedState

    Implement rememberRetained and produceRetainedState

    Resolves #107

    There's possible some blind spots I've missed here and some things we may wanna do differently in the future (commented on those), but overall this works nicely. Confirmed with this now that state's retained in produceRetainedState() and we don't get duplicate loading indicators.

    opened by ZacSweers 4
  • Explore persisting Presenters across config changes

    Explore persisting Presenters across config changes

    Currently we always derive state from the underlying data layers, but maybe we should have a pattern for making Presenter instances persist across configuration changes instead. One benefit is that we could allow presenters to better cache their current state rather than rely on solutions like rememberSaveable to cache the current state or to require the repository to cache the current state.

    The go-to solution here is to hoist them into a ViewModel. Ray Ryan had a an interesting "Continuity" example in his Droidcon NYC talk below that we could draw inspiration from.

    image

    discussion 
    opened by ZacSweers 4
  • Could not find androidx.compose.foundation:foundation:1.3.2.

    Could not find androidx.compose.foundation:foundation:1.3.2.

    recently clone the repo, however facing this issue

    Configuration cache state could not be cached: field `importDirs` of task `:circuit:compileReleaseAidl` of type `com.android.build.gradle.tasks.AidlCompile`: error writing value of type 'org.gradle.api.internal.artifacts.configurations.DefaultConfiguration$ConfigurationFileCollection'
    > Could not resolve all files for configuration ':circuit:releaseCompileClasspath'.
       > Could not find androidx.compose.foundation:foundation:1.3.2.
         Required by:
             project :circuit
    
    bug 
    opened by radityagumay 3
  • Update dependency androidx.profileinstaller:profileinstaller to v1.3.0-SNAPSHOT

    Update dependency androidx.profileinstaller:profileinstaller to v1.3.0-SNAPSHOT

    This PR contains the following updates:

    | Package | Type | Update | Change | |---|---|---|---| | androidx.profileinstaller:profileinstaller (source) | dependencies | patch | 1.3.0-alpha01 -> 1.3.0-SNAPSHOT |


    Configuration

    📅 Schedule: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

    🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

    Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

    🔕 Ignore: Close this PR and you won't be reminded about this update again.


    • [ ] If you want to rebase/retry this PR, click this checkbox.

    This PR has been generated by Renovate Bot.

    opened by slack-oss-bot 3
  • Move PetDetail and PetList UI tests to Robolectric

    Move PetDetail and PetList UI tests to Robolectric

    This runs way faster and gives us quick headless UI testing.

    Open question – do we drop the UI tests entirely? Would be nice to run both but alas there's no test fixtures support still for kotlin android projects

    opened by ZacSweers 3
  • Integrate Paparazzi

    Integrate Paparazzi

    Continuing from #59. Resolves #58

    • Mostly easy to set up and record baselines
    • Can nicely enforce in CI that files are checked in via lfs
    • Made the star app a library with just an apk shell subproject for the application project (see limitation below)
    • Demoes using just a simple grey color for image loading
    • Set up a PreviewUpdateFiltersSheet function and reuse it in a paparazzi tests too
    • Sets up git-lfs in the repo and on CI

    Some limitations

    • Only works in library modules - https://github.com/cashapp/paparazzi/issues/107

    Using an early fork from twitter folks to fix the following issues not released on main yet

    • Doesn't work on compile SDK 33 yet - https://github.com/cashapp/paparazzi/issues/558
    • Requires extra config for JDK 16+ - https://github.com/cashapp/paparazzi/pull/566
    opened by ZacSweers 3
  • Return results to caller

    Return results to caller

    I made some progress returning result, however, there are a few issues and some work yet to be done.

    Problems:

    1. have yet to pass a result to a child presenter via its event sink. The latest commit is a wip attempt at getting this to work
    2. the favorite is not being remembered

    Todo:

    1. the current solution still mutates a regular prop in the navigator. Have yet to look at using mutable state

    See d18b43b5db91a94faae04df5cc984792d27f6eff for a (somewhat) working solution that passes the result via the screen object

    opened by kierse 3
  • Update to Kotlin 1.8

    Update to Kotlin 1.8

    Updates

    • Kotlin
    • KSP
    • MoshiX
    • Compose-compiler
    • Anvil
    • kotlinOptions -> compilerOptions
    • New android source set model for multiplatform
      • https://kotlinlang.org/docs/whatsnew18.html#kotlin-multiplatform-a-new-android-source-set-layout
      • Allows us to merge the circuit-retained android tests finally back into the main artifact

    Waiting on a final anvil and compose release

    opened by ZacSweers 0
  • Add navigator method to clear backstack and set new root screen

    Add navigator method to clear backstack and set new root screen

    Added method to Navigator allowing the caller to clear the backstack and set a new root screen. This addresses #334.

    navigator.goTo(screen1)   // [screen1]
    navigator.goTo(screen2)   // [screen1, screen2]
    ...
    val oldRoot = navigator.reset(screen3) // [screen3], oldRoot == screen1
    
    opened by kierse 0
  • Add support for replacing back stack root Screen

    Add support for replacing back stack root Screen

    Consider the case of a multi-screen sign-in process. Once the user has successfully authenticated, it would be reasonable to clear the back stack (to prevent accidentally returning to the sign-in flow) and replace the root record with a new Screen (say the default landing Screen).

    Currently, you can call popUntil (Navigator.popUntil(predicate: (Screen) -> Boolean)) to remove multiple screens, followed by Navigator.goTo - as long as the root Screen is untouched. Attempts to pop the root screen trigger a call to the Navigator's onRootPop lambda which (by default) calls the Android back handler.

    A couple ideas to achieve this use case:

    1. support popping the root screen if a replacement is provided. This would likely require a new method on the Navigator interface
    2. provide a mechanism for swapping the back stack managed by the Circuit navigator. This would likely be more complex and may not possible give the current architecture.
    enhancement 
    opened by kierse 2
  • Update backstack record screen when returning value

    Update backstack record screen when returning value

    This PR is an experiment exploring a couple new approaches for returning results (https://github.com/slackhq/circuit/issues/8).

    1. A new method on the Navigator: setScreenResult(ScreenResult?)
    2. Added a new interface called ScreenResultHandler who's sole purpose is to return data

    Details While the two approaches use a different API, they both save the returned data in a backstack record for processing once the current screen is popped.

    Rough outline of what happens when a child screen returns a value to a parent:

    1. the child presenter invokes one of the above solutions for returning data
    2. both solutions grab the parent backstack record and add the result to the record args
    3. the child presenter invokes Navigator.pop, indicating it is finished
    4. BasicNavigableCircuitContent extracts the pending screen result and: a. recreates ~updates~ the screen (using new optional method on Screen) b. recreates the backstack record
    5. BasicNavigableCircuitContent updates the composition as before but now using the new screen instance (created at 4a) containing data from processed screen result

    Both approaches have a number of benefits:

    1. screen results will survive a config change along with the backstack
    2. avoids weird/clunky solutions requiring the parent presenter to extract results from the navigator
    3. avoids having to add a nullable property to the navigator
    4. leans into concept of screens being presenter input state

    Additionally, it should be trivial to build a custom interceptor (similar to what was done in #275) to intercept return values and route them to the containing Activity or Fragment for processing and use outside of Circuit.

    Takeaways There were 2 key takeaways for me from this experiment:

    1. I found recreating the screen to be an elegant way of feeding returned data to a receiving presenter
    2. using the backstack to store results has some benefits and avoids awkwardness commonly seen in other approaches
    discussion 
    opened by kierse 1
Releases(0.5.0)
  • 0.5.0(Dec 22, 2022)

    • Enhancement: Circuit no longer requires manual provisioning of its internal backing ViewModels. This is now done automatically by the Circuit itself.
    • Enhancement: circuit-retained is now fully optional and not included as a transitive dependency of circuit-core. If you want to use it, see its installation instructions in its README.
    • Enhancement: Mark Screen as @Immutable.
    • Breaking API Change: LocalCircuitOwner is now just LocalCircuitConfig to be more idiomatic.
    • Breaking API Change: LocalRetainedStateRegistryOwner is now just LocalRetainedStateRegistry to be more idiomatic.
    • Breaking API Change: Continuity is now internal and not publicly exposed since it no longer needs to be manually provided.
    • Breaking API Change: ViewModelBackStackRecordLocalProvider is now internal and not publicly exposed since it no longer needs to be manually provided.
    • Fix: Add missing license info to pom.
    • Dependency updates
      [versions]
      anvil = "2.4.3"
      compose-jb = "1.2.2"
      compose-animation = "1.3.2"
      compose-compiler = "1.3.2"
      compose-foundation = "1.3.1"
      compose-material = "1.3.1"
      compose-material3 = "1.0.1"
      compose-runtime = "1.3.2"
      compose-ui = "1.3.2"
      kotlin = "1.7.22"
      
    Source code(tar.gz)
    Source code(zip)
  • 0.4.0(Dec 7, 2022)

    • Breaking API Change: Presenter and Ui factories' create() functions now offer a CircuitContext parameter in place of a CircuitConfig parameter. This class contains a CircuitConfig, a tagging API, and access to parent contexts. This allows for plumbing your own metadata through Circuit's internals such as tracing tools, logging, etc.
    • Enhancement: New lifecycle functions added to EventListener.
      • onBeforeCreatePresenter
      • onAfterCreatePresenter
      • onBeforeCreateUi
      • onAfterCreateUi
      • onUnavailableContent
      • onStartPresent
      • onDisposePresent
      • onStartContent
      • onDisposeContent
      • dispose
    • Update Compose to 1.3.1.
    • Update Compose (JB) to 1.2.1.
    • Update Molecule to 0.6.1.
    • Added a demo to the STAR sample that shows how to navigate to standard Android components (#275).

    What's Changed

    • Update dependency pymdown-extensions to v9.8 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/270
    • Update compose-jb to v1.2.1 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/269
    • Update dependency androidx.test.espresso:espresso-core to v3.5.0 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/271
    • Update dependency androidx.test.ext:junit to v1.1.4 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/272
    • Update dependency androidx.compose.material3:material3 to v1.0.1 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/274
    • Update compose to v1.3.1 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/273
    • Update dependency mkdocs-material to v8.5.9 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/276
    • Update dagger to v2.44.1 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/278
    • Update dependency app.cash.molecule:molecule-runtime to v0.6.0 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/283
    • Update plugin com.gradle.enterprise to v3.11.4 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/282
    • Update ksp to v1.7.21-1.0.8 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/281
    • Update dependency mkdocs-material to v8.5.10 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/280
    • Revert "Update ksp to v1.7.21-1.0.8" by @jpetote in https://github.com/slackhq/circuit/pull/284
    • Update dependency com.autonomousapps.dependency-analysis to v1.14.1 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/286
    • Update dagger to v2.44.2 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/285
    • Updated STAR demo to support navigating to standard Android by @kierse in https://github.com/slackhq/circuit/pull/275
    • Update leakcanary to v2.10 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/288
    • Update dependency com.github.ben-manes.versions to v0.44.0 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/287
    • Update dependency app.cash.molecule:molecule-runtime to v0.6.1 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/289
    • Update copyright headers by @ZacSweers in https://github.com/slackhq/circuit/pull/290
    • Update dependency io.gitlab.arturbosch.detekt to v1.22.0 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/294
    • Update dependency termcolor to v2.1.1 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/292
    • Update dependency com.autonomousapps.dependency-analysis to v1.15.0 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/293
    • Update dependency com.autonomousapps.dependency-analysis to v1.16.0 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/298
    • Update dependency mkdocs-material-extensions to v1.1.1 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/297
    • Disable snapshots in renovate by @ZacSweers in https://github.com/slackhq/circuit/pull/296
    • Update accompanist to v0.27.1 - autoclosed by @slack-oss-bot in https://github.com/slackhq/circuit/pull/291
    • Fix some mkdocs API links by @ZacSweers in https://github.com/slackhq/circuit/pull/301
    • Enable changelog and discussion links on site by @ZacSweers in https://github.com/slackhq/circuit/pull/303
    • Fix snapshots config in renovate by @ZacSweers in https://github.com/slackhq/circuit/pull/299
    • Update ksp to v1.7.22-1.0.8 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/313
    • Revert "Update ksp to v1.7.22-1.0.8 (#313)" by @kierse in https://github.com/slackhq/circuit/pull/315
    • Update dependency mkdocs-material to v8.5.11 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/316
    • Update accompanist to v0.28.0 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/317
    • Update dependency com.diffplug.spotless to v6.12.0 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/320
    • Update dependency com.autonomousapps.dependency-analysis to v1.17.0 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/319
    • Update dependency dev.zacsweers.moshix to v0.20.0 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/324
    • Update dependency pymdown-extensions to v9.9 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/323
    • Implement CircuitContext by @ZacSweers in https://github.com/slackhq/circuit/pull/325
    • Update benchmark and regenerate baseline profiles by @ZacSweers in https://github.com/slackhq/circuit/pull/326

    Full Changelog: https://github.com/slackhq/circuit/compare/0.3.1...0.4.0

    Source code(tar.gz)
    Source code(zip)
  • 0.3.1(Nov 7, 2022)

    • Enhancement: Add back the onRootPop() parameter in rememberCircuitNavigator() but use LocalOnBackPressedDispatcherOwner for backpress handling by default.
    Source code(tar.gz)
    Source code(zip)
  • 0.3.0(Nov 1, 2022)

    • New: The Overlay API is now extracted to a separate, optional circuit-overlay artifact.
    • New: The circuit-core artifact now packages in baseline profiles.
    • Enhancement: Simplify backstack root pop handling. There is no more onRootPop() option in rememberCircuitNavigator(), instead you should install your own BackHandler() prior to rendering your circuit content to customize back behavior when the circuit Navigator is at root.
    • Fix: circuit-codegen-annotations is now a multiplatform project and doesn't accidentally impose the compose-desktop dependency.

    We've also updated a number of docs around code gen, overlays, and interop (including a new interop sample).

    Source code(tar.gz)
    Source code(zip)
  • 0.2.2(Oct 28, 2022)

    • Enhancement: Code gen now supports non-assisted constructor-injected types.
    • Enhancement: Code gen checks that functions and classes are visible to generated factories.
    Source code(tar.gz)
    Source code(zip)
  • 0.2.1(Oct 27, 2022)

  • 0.2.0(Oct 27, 2022)

    Highlights

    • New: Code gen artifact. This targets specifically using Dagger + Anvil and will generate Presenter and Ui.Factory implementations for you. See CircuitInject for more details.

      ksp("com.slack.circuit:circuit-codegen:x.y.z")
      implementation("com.slack.circuit:circuit-codegen-annotations:x.y.z")
      
    • New: There is now an EventListener API for instrumenting state changes for a given Screen. See its docs for more details.

    • Fix: Rework rememberRetained implementation and support for multiple variables. Previously it only worked with one variable.

    • Fix: Clean up some unnecessary transitive dependencies in misc artifacts.

    Dependency updates

    androidx.activity 1.6.1
    androidx.compose 1.3.0
    Molecule 0.5.0
    

    What's Changed

    • Update dependency org.jline:jline to v3.21.0 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/207
    • Fix snapshots publishing by @ZacSweers in https://github.com/slackhq/circuit/pull/209
    • Update dependency app.cash.molecule:molecule-runtime to v0.5.0 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/211
    • Update dependency com.android.tools.build:gradle to v7.3.1 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/210
    • Integrate dependencyGuard by @ZacSweers in https://github.com/slackhq/circuit/pull/208
    • Integrate Paparazzi by @ZacSweers in https://github.com/slackhq/circuit/pull/204
    • Update dependency mkdocs to v1.4.1 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/213
    • Fix circuit-core coordinates by @ZacSweers in https://github.com/slackhq/circuit/pull/215
    • Update dependency com.github.ben-manes.versions to v0.43.0 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/218
    • Consolidate FakeImageLoader impls by @ZacSweers in https://github.com/slackhq/circuit/pull/217
    • Integrate Detekt + compose detekt rules + kotlinx immutable by @ZacSweers in https://github.com/slackhq/circuit/pull/216
    • Enable build scans on builds by @ZacSweers in https://github.com/slackhq/circuit/pull/220
    • Update plugin com.gradle.enterprise to v3.11.2 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/222
    • EventListener part 2 by @ZacSweers in https://github.com/slackhq/circuit/pull/223
    • Add initial tests for rememberRetained by @ZacSweers in https://github.com/slackhq/circuit/pull/224
    • Update dependency mkdocs-material-extensions to v1.1 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/231
    • Update dependency mkdocs-material to v8.5.7 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/230
    • Update dependency pymdown-extensions to v9.7 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/232
    • Use enterAlwaysScrollBehavior in scaffold by @ZacSweers in https://github.com/slackhq/circuit/pull/228
    • Add leakcanary to instrumentation tests by @ZacSweers in https://github.com/slackhq/circuit/pull/229
    • Add test for clearing unclaimed values by @ZacSweers in https://github.com/slackhq/circuit/pull/226
    • Code Gen for Ui and Presenter Factories by @iamritav in https://github.com/slackhq/circuit/pull/235
    • Update compose to v1.3.0 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/234
    • Update androidx-activity to v1.6.1 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/233
    • Update dependency com.google.android.material:compose-theme-adapter to v1.1.21 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/238
    • Update dependency androidx.compose.material3:material3 to v1.0.0 by @slack-oss-bot in https://github.com/slackhq/circuit/pull/237
    • Support assisted injections + consolidate and clean up APIs by @ZacSweers in https://github.com/slackhq/circuit/pull/236

    Full Changelog: https://github.com/slackhq/circuit/compare/0.1.2...0.2.0

    Source code(tar.gz)
    Source code(zip)
  • 0.1.2(Oct 12, 2022)

  • 0.1.1(Oct 10, 2022)

    • Fix: Accidentally bundling more Compose UI dependencies than necessary.

    What's Changed

    • Fixup spotless config + correctly format build files by @ZacSweers in https://github.com/slackhq/circuit/pull/193
    • Fix compose bundle dependencies by @ZacSweers in https://github.com/slackhq/circuit/pull/196

    Full Changelog: https://github.com/slackhq/circuit/compare/0.1.0...0.1.1

    Source code(tar.gz)
    Source code(zip)
  • 0.1.0(Oct 10, 2022)

    Initial release, see the docs: https://slackhq.github.io/circuit/.

    Note that this library is still under active development and not recommended for production use. We'll do a more formal announcement when that time comes!

    Source code(tar.gz)
    Source code(zip)
Owner
Slack
On a mission to make your working life simpler, more pleasant and more productive.
Slack
🚀A powerful android clean architecture that helps you build your apps faster.

IMStudio ?? Table of Contents Project Structure Convention RxJava Common Scripts Technical Stack Dependencies Library Architecture Case Study Authors

Hau NGUYEN (Leo) 0 Nov 20, 2022
A GitHub user Android apps using Dagger 2, MVVM, Modularization, Clean Architecture, and Airbnb Epoxy

A GitHub user Android apps using Dagger 2, MVVM, Modularization, Clean Architecture, and Airbnb Epoxy.

Alva Yonara Puramandya 3 Dec 28, 2022
An Android base project building on MVVM Architecture Pattern. This can help you build new apps faster

MVVM Explanation If you can't imagine what is MVVM, please read my medium article here first. It can fully explain the revolution of Software architec

Danh Dev 29 Sep 21, 2022
:movie_camera: Movie discovery app showcasing Android best practices with Google's recommended architecture: MVVM + Repository + Offline support + Android Architecture Components + Paging library & Retrofit2.

Popular Movies Stage 1 + Stage 2 Discover the most popular and top rated movies playing. Movies data fetched using themoviedb.org API. ✨ Screenshots M

Yassin AJDI 189 Nov 26, 2022
🛒A Minimal Expense E-Commerce App built to demonstrate the use of modern android architecture components [Navigation, Room, MotionLayout, etc..] with MVVM Architecture. ✔

E-Store A Simple E-Commerce App ?? built to demonstrate the use of modern android architecture component with MVVM Architecture ?? . Made with love ❤️

Ameen Essa 14 Nov 3, 2022
A Simple Expense Tracker App 📱 built to demonstrate the use of modern android architecture component with MVVM Architecture

Expenso ?? A Simple Expense Tracker App ?? built to demonstrate the use of modern android architecture component with MVVM Architecture ?? . Made with

Michel Horacio 1 Dec 28, 2022
Weather application example with Android Architecture components and Clean Architecture

Weather application example with Android Architecture components and Clean Architecture Weather app that shows how to architect an android app in a cl

null 2 Dec 3, 2021
NewsSpac-MVVM-CleanArch-TDD - The App uses MVVM architecture together with Clean architecture

Aplicativo NewsSpace Arquitetura O App utiliza a arquitetura MVVM em conjunto co

null 1 Feb 11, 2022
ArchGuard is a architecture governance tool which can analysis architecture in container, component, code level, create architecure fitness functions, and anaysis system dependencies..

ArchGuard backend ArchGuard is a architecture governance tool which can analysis architecture in container, component, code level, database, create ar

ArchGuard 446 Dec 20, 2022
⌨️ A tool that gives you a massive head start when building Compose based apps. It saves you from time-consuming setup and configuration

⌨️ A tool that gives you a massive head start when building Compose based apps. It saves you from time-consuming setup and configuration

theapache64 467 Dec 23, 2022
Movie Android App written in Kotlin, MVVM, RxJava, Coroutine (Upcoming), Android Architecture Components and Jetpack Compose (Upcoming).

MovieHunt MovieHunt is a sample Android project using The Movie DB API based on MVVM architecture. It showcases the latest Android tech stacks with we

Engine Bai 596 Dec 31, 2022
The JeTrivia is built on a modern Android Development tech stack with MVVM architecture. Kotlin, Coroutine, Flow, StateFlow, Jetpack Compose, Navigation, Room, Hilt, Retrofit2, OkHttp3, kotlinx.serialization, MockK, Truth

JeTrivia ?? In Progress ?? The JeTrivia application is sample based on MVVM architecture. Fetching data from the network via repository pattern and sa

Tolga Bolatcan 5 Mar 31, 2022
An android application architecture exploration in compose

In this project I tried showcasing how to build an Android Application in Jetpack Compose with clean architecture and MVI using some of the jetpack libraries with Kotlin Coroutines & Dagger Hilt.

Felipe Castilhos 4 Dec 13, 2022
Dose a Android app that reminds you medications exactly when your body needs them, building entirely using Kotlin and Jetpack Compose with MVVM + Clean Architecture

??⏰ Dose is a work-in-progress Android app that reminds you medications exactly when your body needs them, building entirely using Kotlin and Jetpack Compose with MVVM + Clean Architecture

Waseef Akhtar 195 Jan 1, 2023
Food Recipes - Android application built with Jetpack compose, MVVM and clean architecture approach.

Food Recipes Android application that consuming (https://spoonacular.com/food-api) "Recipes api". It has been built with clean architecture principles

Mahmoud Elshahat 26 Jan 29, 2023
MVVM + Kotlin + Jetpack Compose +Navigation Compose + Hilt + Retrofit + Unit Testing + Compose Testing + Coroutines + Kotlin Flow + Io mockK

MvvmKotlinJetpackCompose Why do we need an architecture even when you can make an app without it? let's say you created a project without any architec

Sayyed Rizwan 46 Nov 29, 2022
Kotlite (Angkot Elite) Android Apps

Kotlite (Angkot Elite) Android Apps A Part of Kotlite Ridesharing Application Explore the Projects » APK Demo · Report Bug · Request Feature Table of

Bisma Satria 4 Sep 27, 2021
CovidCertificate Apps for Android

COVID Certificate Apps - Android This project is released by the the Federal Office of Information Technology, Systems and Telecommunication FOITT on

Swiss Admin 176 Oct 29, 2022