├── .github
├── CODEOWNERS
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── enhancement.md
├── dependabot.yml
└── pull_request_template.md
├── .gitignore
├── .idea
├── copyright
│ ├── Apache_2_0.xml
│ └── profiles_settings.xml
├── kotlinc.xml
└── vcs.xml
├── CHANGELOG.md
├── LICENSE
├── README.md
├── app
├── .gitignore
├── build.gradle.kts
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── kotlin
│ └── mini
│ │ └── android
│ │ └── sample
│ │ ├── MainActivity.kt
│ │ ├── SampleActions.kt
│ │ ├── SampleScreen.kt
│ │ ├── StoreSampleActivity.kt
│ │ ├── ViewModelSampleActivity.kt
│ │ └── ui
│ │ └── theme
│ │ ├── Color.kt
│ │ ├── Theme.kt
│ │ └── Type.kt
│ └── res
│ ├── drawable
│ ├── ic_launcher_background.xml
│ ├── ic_launcher_foreground.xml
│ └── ic_launcher_monochrome.xml
│ ├── mipmap-anydpi-v26
│ ├── ic_launcher.xml
│ └── ic_launcher_round.xml
│ ├── mipmap-hdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-mdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxxhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ └── values
│ ├── colors.xml
│ ├── dimens.xml
│ ├── strings.xml
│ └── styles.xml
├── build.gradle.kts
├── convention-plugins
├── .gitignore
├── build.gradle.kts
├── settings.gradle.kts
└── src
│ └── main
│ └── kotlin
│ └── mini
│ └── android
│ └── plugins
│ ├── AndroidAppConventionPlugin.kt
│ ├── AndroidLibConventionPlugin.kt
│ ├── JavaLibConventionPlugin.kt
│ └── extensions
│ ├── MavenPomExtensions.kt
│ └── ProjectExtensions.kt
├── gradle.properties
├── gradle
├── libs.versions.toml
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── jitpack.yml
├── mini-android
├── .gitignore
├── build.gradle.kts
├── mini-android.pro
├── proguard-rules.pro
└── src
│ └── main
│ └── java
│ └── mini
│ └── android
│ ├── FluxActivity.kt
│ ├── FluxFragment.kt
│ ├── FluxStoreViewModel.kt
│ └── FluxViewModel.kt
├── mini-common
├── .gitignore
├── build.gradle.kts
└── src
│ ├── main
│ ├── java
│ │ └── mini
│ │ │ ├── AndroidInterop.kt
│ │ │ ├── Annotations.kt
│ │ │ ├── CloseableTracker.kt
│ │ │ ├── CompositeCloseable.kt
│ │ │ ├── DiffAdapter.kt
│ │ │ ├── Dispatcher.kt
│ │ │ ├── LoggerMiddleware.kt
│ │ │ ├── Middleware.kt
│ │ │ ├── Mini.kt
│ │ │ ├── Misc.kt
│ │ │ ├── NestedStateContainer.kt
│ │ │ ├── Resource.kt
│ │ │ ├── State.kt
│ │ │ ├── StateContainer.kt
│ │ │ ├── Store.kt
│ │ │ ├── StoreFlow.kt
│ │ │ └── Threading.kt
│ └── resources
│ │ └── META-INF
│ │ └── proguard
│ │ └── mini-common.pro
│ └── test
│ └── kotlin
│ └── mini
│ ├── CompositeCloseableTest.kt
│ ├── DispatcherTest.kt
│ ├── LoggerMiddlewareTest.kt
│ ├── ResourceTest.kt
│ ├── SampleStore.kt
│ ├── StoreFlowTest.kt
│ ├── StoreTest.kt
│ ├── TestAction.kt
│ └── TestDispatcher.kt
├── mini-kodein-android-compose
├── .gitignore
├── build.gradle.kts
├── mini-kodein-android-compose.pro
├── proguard-rules.pro
└── src
│ └── main
│ └── java
│ └── mini
│ └── kodein
│ └── android
│ └── compose
│ └── KodeinAndroidComposeUtils.kt
├── mini-kodein-android
├── .gitignore
├── build.gradle.kts
├── mini-kodein-android.pro
├── proguard-rules.pro
└── src
│ └── main
│ ├── java
│ └── mini
│ │ └── kodein
│ │ └── android
│ │ ├── FluxTypedViewModel.kt
│ │ ├── KodeinAndroidUtils.kt
│ │ └── TypedViewModel.kt
│ └── res
│ └── values
│ └── strings.xml
├── mini-kodein
├── .gitignore
├── build.gradle.kts
└── src
│ └── main
│ ├── java
│ └── mini
│ │ └── kodein
│ │ └── KodeinUtils.kt
│ └── resources
│ └── META-INF
│ └── proguard
│ └── mini-kodein.pro
├── mini-processor-test
├── .gitignore
├── build.gradle.kts
└── src
│ ├── main
│ └── java
│ │ └── mini
│ │ └── test
│ │ ├── AnyAction.kt
│ │ ├── BasicState.kt
│ │ └── ReducersStore.kt
│ └── test
│ └── java
│ └── mini
│ └── test
│ └── ReducersStoreTest.kt
├── mini-processor
├── .gitignore
├── build.gradle.kts
└── src
│ └── main
│ ├── java
│ └── mini
│ │ └── processor
│ │ ├── common
│ │ ├── ContainerBuilders.kt
│ │ ├── ModelGeneratorDelegate.kt
│ │ ├── ProcessorException.kt
│ │ ├── actions
│ │ │ ├── ActionModels.kt
│ │ │ ├── ActionTypesGenerator.kt
│ │ │ └── ActionTypesGeneratorDelegate.kt
│ │ └── reducers
│ │ │ ├── ReducersGenerator.kt
│ │ │ ├── ReducersGeneratorDelegate.kt
│ │ │ └── ReducersModels.kt
│ │ ├── kapt
│ │ ├── MiniAnnotationProcessor.java
│ │ ├── Processor.kt
│ │ ├── ProcessorUtils.kt
│ │ ├── actions
│ │ │ ├── KaptActionModel.kt
│ │ │ └── KaptActionTypesGeneratorDelegate.kt
│ │ └── reducers
│ │ │ ├── KaptReducersGeneratorDelegate.kt
│ │ │ └── KaptReducersModels.kt
│ │ └── ksp
│ │ ├── MiniSymbolProcessor.kt
│ │ ├── MiniSymbolProcessorProvider.kt
│ │ ├── SymbolProcessorUtils.kt
│ │ ├── actions
│ │ ├── KspActionModel.kt
│ │ └── KspActionTypesGeneratorDelegate.kt
│ │ └── reducers
│ │ ├── KspReducersGeneratorDelegate.kt
│ │ └── KspReducersModels.kt
│ └── resources
│ └── META-INF
│ └── services
│ ├── com.google.devtools.ksp.processing.SymbolProcessorProvider
│ └── javax.annotation.processing.Processor
├── mini-testing
├── .gitignore
├── build.gradle.kts
└── src
│ └── main
│ └── java
│ └── mini
│ └── testing
│ ├── CleanStateRule.kt
│ ├── TestDispatcherMiddleware.kt
│ └── TestDispatcherRule.kt
└── settings.gradle.kts
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | # This is a comment.
2 | # Each line is a file pattern followed by one or more owners.
3 |
4 | # Current code owners
5 | # - @nicolasmertanen -> Nicolás Mertanen
6 | # - @finxo -> Alejandro Lopez
7 | # - @FrangSierra -> Francisco García
8 | # - @adriangl -> Adrián García
9 | # - @yamidragut -> Estefanía Sarasola
10 | # - @Babelia13 -> Sara Lucía Pérez
11 |
12 | * @nicolasmertanen @finxo @FrangSierra @adriangl @yamidragut @Babelia13
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: bug
6 | assignees: adriangl
7 |
8 | ---
9 |
10 | **Device and SW details (please complete the following information):**
11 | - Device: [e.g. Google Pixel 3]
12 | - OS: [e.g. Android 9]
13 | - Library Version [e.g. 1.0.0]
14 |
15 | **Summary and background of the bug**
16 | A clear and concise description of what the bug is.
17 |
18 | **Steps to reproduce**
19 | Steps to reproduce the behavior:
20 | 1. Go to '...'
21 | 2. Click on '....'
22 | 3. Scroll down to '....'
23 | 4. See error
24 |
25 | Also attach notes or stack traces if applicable.
26 |
27 | **Expected behavior**
28 | A clear and concise description of what you expected to happen.
29 |
30 | **Current behavior**
31 | The summary of what currently happens in your use case.
32 |
33 | **Additional context**
34 | Add any other context about the problem here.
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/enhancement.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Enhancement
3 | about: Create a report to propose new features and improvements
4 | title: ''
5 | labels: enhancement
6 | assignees: adriangl
7 |
8 | ---
9 |
10 | **Summary and context of the enhancement**
11 | A clear and concise description of what the enhancement is and why it
12 | should be added.
13 |
14 | **Suggested implementation**
15 | Add suggestions about how the enhancement should be implemented.
16 |
17 | **Additional documentation**
18 | Useful links to review the enhancement.
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | # Updates for Gradle dependencies used in the app
4 | - package-ecosystem: gradle
5 | directory: "/"
6 | schedule:
7 | interval: "monthly"
8 | open-pull-requests-limit: 10
9 |
--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
1 | ### Github issue (delete if this does not apply)
2 | https://github.com/hyperdevs-team/mini-kotlin/issues/change_me_issue_number
3 |
4 | ### PR's key points
5 |
6 | ### How to review this PR?
7 |
8 | ### Related Issues (delete if this does not apply)
9 |
10 | ### Definition of Done
11 | - [ ] Tests pass
12 | - [ ] Works with Proguard
13 | - [ ] There is no outcommented or debug code left
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 | .externalNativeBuild
10 |
11 |
12 | # Created by https://www.gitignore.io/api/java,gradle,intellij,osx,windows,linux
13 |
14 | ### Intellij ###
15 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
16 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
17 |
18 | # User-specific stuff:
19 | .idea/**/workspace.xml
20 | .idea/**/tasks.xml
21 | .idea/**/usage.statistics.xml
22 | .idea/**/dictionaries
23 | .idea/**/shelf
24 |
25 | # Generated files
26 | .idea/**/contentModel.xml
27 | .idea/**/libraries-with-intellij-classes.xml
28 |
29 | # Sensitive or high-churn files:
30 | .idea/**/dataSources/
31 | .idea/**/dataSources.ids
32 | .idea/**/dataSources.xml
33 | .idea/**/dataSources.local.xml
34 | .idea/**/sqlDataSources.xml
35 | .idea/**/dynamic.xml
36 | .idea/**/uiDesigner.xml
37 | .idea/**/dbnavigator.xml
38 |
39 | # Gradle:
40 | .idea/**/gradle.xml
41 | .idea/**/libraries
42 |
43 | # Mongo Explorer plugin:
44 | .idea/**/mongoSettings.xml
45 |
46 | ## File-based project format:
47 | *.iws
48 |
49 | ## Plugin-specific files:
50 |
51 | # IntelliJ
52 | /out/
53 | *.iml
54 | .idea/encodings.xml
55 | .idea/vcs.xml
56 | .idea/codeStyles/Project.xml
57 | .idea/workspace.xml
58 | .idea/tasks.xml
59 | .idea/libraries
60 | .idea/dictionaries
61 | .idea/runConfigurations.xml
62 | .idea/terminal.xml
63 | .idea/inspectionProfiles/
64 | .idea/jarRepositories.xml
65 | .idea/modules
66 | .idea/markdown-exported-files.xml
67 | .idea/markdown-navigator.xml
68 | .idea/markdown-navigator-enh.xml
69 | .idea/markdown-navigator/
70 | .idea/misc.xml
71 | .idea/modules.xml
72 | .idea/caches
73 | .idea/compiler.xml
74 | .idea/assetWizardSettings.xml
75 | .idea/navEditor.xml
76 | .idea/.name
77 | .idea/deploymentTargetSelector.xml
78 | .idea/migrations.xml
79 | .idea/other.xml
80 |
81 | # mpeltonen/sbt-idea plugin
82 | .idea_modules/
83 |
84 | # JIRA plugin
85 | atlassian-ide-plugin.xml
86 |
87 | # Cursive Clojure plugin
88 | .idea/replstate.xml
89 |
90 | # Crashlytics plugin (for Android Studio and IntelliJ)
91 | com_crashlytics_export_strings.xml
92 | crashlytics.properties
93 | crashlytics-build.properties
94 | fabric.properties
95 |
96 | # Editor-based Rest Client
97 | .idea/httpRequests
98 |
99 | # Android studio 3.1+ serialized cache file
100 | .idea/caches/build_file_checksums.ser
101 |
102 | ### Intellij Patch ###
103 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
104 |
105 | # *.iml
106 | # modules.xml
107 | # .idea/misc.xml
108 | # *.ipr
109 |
110 | ### Java ###
111 | # Compiled class file
112 | *.class
113 |
114 | # Log file
115 | *.message
116 |
117 | # BlueJ files
118 | *.ctxt
119 |
120 | # Mobile Tools for Java (J2ME)
121 | .mtj.tmp/
122 |
123 | # Package Files #
124 | *.jar
125 | *.war
126 | *.ear
127 | *.zip
128 | *.tar.gz
129 | *.rar
130 |
131 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
132 | hs_err_pid*
133 |
134 | ### Linux ###
135 | *~
136 |
137 | # temporary files which can be created if a process still has a handle open of a deleted file
138 | .fuse_hidden*
139 |
140 | # KDE directory preferences
141 | .directory
142 |
143 | # Linux trash folder which might appear on any partition or disk
144 | .Trash-*
145 |
146 | # .nfs files are created when an open file is removed but is still being accessed
147 | .nfs*
148 |
149 | ### OSX ###
150 | *.DS_Store
151 | .AppleDouble
152 | .LSOverride
153 |
154 | # Icon must end with two \r
155 | Icon
156 |
157 | # Thumbnails
158 | ._*
159 |
160 | # Files that might appear in the root of a volume
161 | .DocumentRevisions-V100
162 | .fseventsd
163 | .Spotlight-V100
164 | .TemporaryItems
165 | .Trashes
166 | .VolumeIcon.icns
167 | .com.apple.timemachine.donotpresent
168 |
169 | # Directories potentially created on remote AFP share
170 | .AppleDB
171 | .AppleDesktop
172 | Network Trash Folder
173 | Temporary Items
174 | .apdisk
175 |
176 | ### Windows ###
177 | # Windows thumbnail cache files
178 | Thumbs.db
179 | ehthumbs.db
180 | ehthumbs_vista.db
181 |
182 | # Folder config file
183 | Desktop.ini
184 |
185 | # Recycle Bin used on file shares
186 | $RECYCLE.BIN/
187 |
188 | # Windows Installer files
189 | *.cab
190 | *.msi
191 | *.msm
192 | *.msp
193 |
194 | # Windows shortcuts
195 | *.lnk
196 |
197 | ### Gradle ###
198 | .gradle
199 | /build/
200 |
201 | # Ignore Gradle GUI config
202 | gradle-app.setting
203 |
204 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
205 | !gradle-wrapper.jar
206 |
207 | # Cache of project
208 | .gradletasknamecache
209 |
210 | # # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
211 | # gradle/wrapper/gradle-wrapper.properties
212 |
213 | # End of https://www.gitignore.io/api/java,gradle,intellij,osx,windows,linux
214 |
--------------------------------------------------------------------------------
/.idea/copyright/Apache_2_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/kotlinc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2024 HyperDevs
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | plugins {
18 | alias(libs.plugins.android.application)
19 | alias(libs.plugins.kotlin.android)
20 | // alias(libs.plugins.kotlin.kapt)
21 | alias(libs.plugins.kotlin.ksp)
22 | alias(libs.plugins.convention.androidApp)
23 | }
24 |
25 | android {
26 | namespace = "mini.android.sample"
27 |
28 | compileSdk = libs.versions.android.compileSdk.get().toInt()
29 | buildToolsVersion = libs.versions.android.buildTools.get()
30 |
31 | defaultConfig {
32 | applicationId = "mini.android.sample"
33 | minSdk = libs.versions.android.minSdk.get().toInt()
34 | targetSdk = libs.versions.android.targetSdk.get().toInt()
35 | multiDexEnabled = true
36 | testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
37 | }
38 |
39 | buildFeatures {
40 | compose = true
41 | viewBinding = true
42 | }
43 |
44 | composeOptions {
45 | kotlinCompilerExtensionVersion = libs.versions.compose.compiler.get()
46 | }
47 |
48 | buildTypes {
49 | release {
50 | isMinifyEnabled = false
51 | proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
52 | }
53 | }
54 |
55 | compileOptions {
56 | sourceCompatibility = JavaVersion.toVersion(libs.versions.java.sdk.get())
57 | targetCompatibility = JavaVersion.toVersion(libs.versions.java.sdk.get())
58 | }
59 |
60 | kotlinOptions {
61 | jvmTarget = libs.versions.java.sdk.get()
62 | }
63 |
64 | lint {
65 | abortOnError = false
66 | }
67 | }
68 |
69 | dependencies {
70 | implementation(project(":mini-android"))
71 | implementation(project(":mini-kodein-android"))
72 |
73 | // kapt(project(":mini-processor"))
74 | ksp(project(":mini-processor"))
75 |
76 | // Kotlin
77 | implementation(libs.kotlin.stdlib)
78 | implementation(libs.kotlin.reflect)
79 |
80 | // Coroutines
81 | implementation(libs.kotlinx.coroutines.core)
82 |
83 | // Support
84 | implementation(libs.bundles.androidx)
85 | implementation(libs.bundles.compose)
86 | implementation(libs.androidx.activity)
87 | implementation(libs.bundles.androidx.lifecycle)
88 |
89 | // Test
90 | testImplementation(libs.junit)
91 | androidTestImplementation(libs.androidx.test.runner)
92 | androidTestImplementation(libs.espresso)
93 | androidTestImplementation(libs.androidx.test.junit)
94 | }
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/pablo/development/android-sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.kts.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
18 |
19 |
20 |
21 |
28 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
43 |
44 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/app/src/main/kotlin/mini/android/sample/MainActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2024 HyperDevs
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package mini.android.sample
18 |
19 | import android.content.Intent
20 | import android.net.Uri
21 | import android.os.Bundle
22 | import android.widget.Button
23 | import androidx.activity.compose.setContent
24 | import androidx.activity.enableEdgeToEdge
25 | import androidx.appcompat.app.AppCompatActivity
26 | import androidx.compose.foundation.background
27 | import androidx.compose.foundation.layout.Arrangement
28 | import androidx.compose.foundation.layout.Box
29 | import androidx.compose.foundation.layout.Column
30 | import androidx.compose.foundation.layout.fillMaxSize
31 | import androidx.compose.foundation.layout.padding
32 | import androidx.compose.material3.Button
33 | import androidx.compose.material3.MaterialTheme
34 | import androidx.compose.material3.Scaffold
35 | import androidx.compose.material3.Text
36 | import androidx.compose.runtime.Composable
37 | import androidx.compose.runtime.remember
38 | import androidx.compose.ui.Alignment
39 | import androidx.compose.ui.Modifier
40 | import androidx.compose.ui.graphics.Color
41 | import androidx.compose.ui.platform.LocalContext
42 | import androidx.compose.ui.res.stringResource
43 | import androidx.compose.ui.tooling.preview.Preview
44 | import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
45 | import mini.android.sample.ui.theme.AppTheme
46 |
47 | class MainActivity : AppCompatActivity() {
48 |
49 | override fun onCreate(savedInstanceState: Bundle?) {
50 | super.onCreate(savedInstanceState)
51 |
52 | installSplashScreen()
53 | enableEdgeToEdge()
54 |
55 | setContent {
56 | AppTheme {
57 | MainScreen(
58 | onGoToStoreSampleClicked = {
59 | Intent(this, StoreSampleActivity::class.java).apply {
60 | startActivity(this)
61 | }
62 | },
63 | onGoToViewModelSampleClicked = {
64 | Intent(this, ViewModelSampleActivity::class.java).apply {
65 | startActivity(this)
66 | }
67 | }
68 | )
69 | }
70 | }
71 | }
72 | }
73 |
74 | @Composable
75 | private fun MainScreen(modifier: Modifier = Modifier,
76 | onGoToStoreSampleClicked: () -> Unit = {},
77 | onGoToViewModelSampleClicked: () -> Unit = {}) {
78 | Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
79 | MainContent(
80 | modifier = modifier
81 | .fillMaxSize()
82 | .padding(innerPadding),
83 | onGoToStoreSampleClicked = onGoToStoreSampleClicked,
84 | onGoToViewModelSampleClicked = onGoToViewModelSampleClicked
85 | )
86 | }
87 | }
88 |
89 | @Composable
90 | private fun MainContent(
91 | modifier: Modifier = Modifier,
92 | onGoToStoreSampleClicked: () -> Unit = {},
93 | onGoToViewModelSampleClicked: () -> Unit = {}
94 | ) {
95 | Column(
96 | modifier = modifier.fillMaxSize(),
97 | horizontalAlignment = Alignment.CenterHorizontally,
98 | verticalArrangement = Arrangement.Center
99 | ) {
100 | Button(onClick = onGoToStoreSampleClicked) {
101 | Text("Go to Store sample")
102 | }
103 | Button(onClick = onGoToViewModelSampleClicked) {
104 | Text("Go to ViewModel sample")
105 | }
106 | }
107 | }
108 |
109 | @Preview(showBackground = true)
110 | @Composable
111 | fun MainScreenPreview() {
112 | AppTheme {
113 | MainContent()
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/app/src/main/kotlin/mini/android/sample/SampleActions.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2024 HyperDevs
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package mini.android.sample
18 |
19 | import mini.Action
20 | import mini.Reducer
21 | import mini.SuspendingAction
22 | import java.io.Serializable
23 |
24 | data class MainState(
25 | val text: String = "0",
26 | val loading: Boolean = false
27 | ) : Serializable, mini.State
28 |
29 | @Action
30 | data class SetLoadingAction(val loading: Boolean)
31 |
32 | @Action
33 | data class SetTextAction(val text: String)
34 |
35 | @Action
36 | interface AnalyticsAction
37 |
38 | @Action
39 | class LongUseCaseAction(val userName: String) : AnalyticsAction, SuspendingAction
40 |
41 | /**
42 | * Use any name you like for suspending actions, or use reducer
43 | */
44 | typealias UseCase = Reducer
--------------------------------------------------------------------------------
/app/src/main/kotlin/mini/android/sample/SampleScreen.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2024 HyperDevs
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package mini.android.sample
18 |
19 | import androidx.compose.foundation.layout.Arrangement
20 | import androidx.compose.foundation.layout.Box
21 | import androidx.compose.foundation.layout.Column
22 | import androidx.compose.foundation.layout.fillMaxSize
23 | import androidx.compose.foundation.layout.fillMaxWidth
24 | import androidx.compose.foundation.layout.height
25 | import androidx.compose.foundation.layout.padding
26 | import androidx.compose.material3.Button
27 | import androidx.compose.material3.CircularProgressIndicator
28 | import androidx.compose.material3.Text
29 | import androidx.compose.runtime.Composable
30 | import androidx.compose.ui.Alignment
31 | import androidx.compose.ui.Modifier
32 | import androidx.compose.ui.text.style.TextAlign
33 | import androidx.compose.ui.unit.dp
34 |
35 | @Composable
36 | fun SampleScreen(
37 | modifier: Modifier = Modifier,
38 | text: String,
39 | isLoading: Boolean,
40 | onStartSampleClicked: () -> Unit
41 | ) {
42 | Column(
43 | modifier = modifier.fillMaxSize().padding(16.dp),
44 | horizontalAlignment = Alignment.CenterHorizontally,
45 | verticalArrangement = Arrangement.Center
46 | ) {
47 | Text(
48 | modifier = Modifier.fillMaxWidth(),
49 | textAlign = TextAlign.Center,
50 | text = text
51 | )
52 |
53 | Box(modifier = Modifier.fillMaxWidth().height(60.dp), contentAlignment = Alignment.Center) {
54 | if (!isLoading) {
55 | Button(onClick = onStartSampleClicked) {
56 | Text("Start sample")
57 | }
58 | }
59 |
60 | if (isLoading) {
61 | CircularProgressIndicator()
62 | }
63 | }
64 | }
65 | }
--------------------------------------------------------------------------------
/app/src/main/kotlin/mini/android/sample/StoreSampleActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2024 HyperDevs
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package mini.android.sample
18 |
19 | import android.os.Bundle
20 | import android.view.View
21 | import android.widget.Button
22 | import android.widget.ProgressBar
23 | import android.widget.TextView
24 | import android.widget.Toast
25 | import androidx.activity.compose.setContent
26 | import androidx.compose.foundation.layout.fillMaxSize
27 | import androidx.compose.foundation.layout.padding
28 | import androidx.compose.material3.Scaffold
29 | import androidx.compose.runtime.Composable
30 | import androidx.compose.runtime.LaunchedEffect
31 | import androidx.compose.runtime.collectAsState
32 | import androidx.compose.runtime.mutableStateOf
33 | import androidx.compose.runtime.remember
34 | import androidx.compose.ui.Modifier
35 | import kotlinx.coroutines.delay
36 | import kotlinx.coroutines.flow.map
37 | import kotlinx.coroutines.flow.onEach
38 | import kotlinx.coroutines.launch
39 | import mini.*
40 | import mini.android.FluxActivity
41 | import mini.android.sample.ui.theme.AppTheme
42 |
43 | private val dispatcher = Dispatcher()
44 |
45 | class MainStore : Store() {
46 |
47 | init {
48 | Mini.link(dispatcher, this).track()
49 | }
50 |
51 | @Reducer
52 | fun handleLoading(state: MainState, action: SetLoadingAction): MainState {
53 | return state.copy(loading = action.loading)
54 | }
55 |
56 | @Reducer
57 | fun handleSetTextAction(state: MainState, action: SetTextAction): MainState {
58 | return state.copy(text = action.text)
59 | }
60 |
61 | @Reducer
62 | fun handleAnalyticsAction(action: AnalyticsAction) {
63 | //Log to analytics
64 | }
65 |
66 | @Reducer
67 | fun handleAnyAction(action: Any) {
68 | //Log to analytics
69 | }
70 |
71 | @UseCase
72 | suspend fun useCase(action: LongUseCaseAction) {
73 | if (state.loading) return
74 | dispatcher.dispatch(SetLoadingAction(true))
75 | dispatcher.dispatch(SetTextAction("Loading from network..."))
76 | delay(5000)
77 | dispatcher.dispatch(SetTextAction("Hello From UseCase"))
78 | dispatcher.dispatch(SetLoadingAction(false))
79 | }
80 | }
81 |
82 | class StoreSampleActivity : FluxActivity() {
83 | private val mainStore: MainStore by lazy {
84 | MainStore()
85 | }
86 |
87 | override suspend fun whenCreated(savedInstanceState: Bundle?) {
88 | setContent {
89 | AppTheme {
90 | StoreSampleScreen()
91 | }
92 | }
93 | }
94 |
95 | @Composable
96 | private fun StoreSampleScreen() {
97 | val mainState = mainStore.flow().collectAsState(initial = MainState())
98 | val showToastState = mainStore.flow(hotStart = false).map { !it.loading }
99 | .collectAsState(initial = false)
100 |
101 | LaunchedEffect(showToastState.value) {
102 | if (showToastState.value) {
103 | Toast.makeText(
104 | this@StoreSampleActivity,
105 | "Finished loading",
106 | Toast.LENGTH_LONG
107 | ).show()
108 | }
109 | }
110 |
111 | Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
112 | SampleScreen(
113 | modifier = Modifier.padding(innerPadding),
114 | text = mainState.value.toString(),
115 | isLoading = mainState.value.loading,
116 | onStartSampleClicked = {
117 | launch {
118 | dispatcher.dispatch(LongUseCaseAction("HyperDevs"))
119 | }
120 | }
121 | )
122 | }
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/app/src/main/kotlin/mini/android/sample/ViewModelSampleActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2024 HyperDevs
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package mini.android.sample
18 |
19 | import android.os.Bundle
20 | import android.view.View
21 | import android.widget.Button
22 | import android.widget.ProgressBar
23 | import android.widget.TextView
24 | import android.widget.Toast
25 | import androidx.activity.compose.setContent
26 | import androidx.activity.viewModels
27 | import androidx.compose.foundation.layout.fillMaxSize
28 | import androidx.compose.foundation.layout.padding
29 | import androidx.compose.material3.Scaffold
30 | import androidx.compose.runtime.Composable
31 | import androidx.compose.runtime.LaunchedEffect
32 | import androidx.compose.runtime.collectAsState
33 | import androidx.compose.ui.Modifier
34 | import androidx.lifecycle.SavedStateHandle
35 | import kotlinx.coroutines.*
36 | import kotlinx.coroutines.flow.map
37 | import kotlinx.coroutines.flow.onEach
38 | import mini.*
39 | import mini.android.FluxActivity
40 | import mini.android.FluxStoreViewModel
41 | import mini.android.sample.ui.theme.AppTheme
42 |
43 | private val dispatcher = Dispatcher()
44 |
45 | class MainViewModelReducer : NestedStateContainer() {
46 |
47 | @Reducer
48 | fun handleLoading(state: MainState, action: SetLoadingAction): MainState {
49 | return state.copy(loading = action.loading)
50 | }
51 |
52 | @Reducer
53 | fun handleSetTextAction(state: MainState, action: SetTextAction): MainState {
54 | return state.copy(text = action.text)
55 | }
56 | }
57 |
58 | class MainStoreViewModel(savedStateHandle: SavedStateHandle) :
59 | FluxStoreViewModel(savedStateHandle) {
60 | private val reducerSlice = MainViewModelReducer().apply { parent = this@MainStoreViewModel }
61 |
62 | init {
63 | Mini.link(dispatcher, listOf(this, reducerSlice)).track()
64 | }
65 |
66 | override fun saveState(state: MainState, handle: SavedStateHandle) {
67 | println("State saved")
68 | handle.set("state", state)
69 | }
70 |
71 | override fun restoreState(handle: SavedStateHandle): MainState? {
72 | val restored = handle.get("state")
73 | println("State restored $restored")
74 | return restored
75 | }
76 |
77 | @UseCase
78 | suspend fun useCase(action: LongUseCaseAction) {
79 | if (state.loading) return
80 | dispatcher.dispatch(SetLoadingAction(true))
81 | delay(2000)
82 | dispatcher.dispatch(SetTextAction("${state.text.toInt() + 1}"))
83 | dispatcher.dispatch(SetLoadingAction(false))
84 | }
85 | }
86 |
87 | class ViewModelSampleActivity : FluxActivity() {
88 |
89 | private val viewModel: MainStoreViewModel by viewModels()
90 |
91 | override suspend fun whenCreated(savedInstanceState: Bundle?) {
92 | setContent {
93 | AppTheme {
94 | ViewModelSampleScreen()
95 | }
96 | }
97 | }
98 |
99 | @Composable
100 | private fun ViewModelSampleScreen() {
101 | val mainState = viewModel.flow().collectAsState(initial = MainState())
102 | val showToastState = viewModel.flow(hotStart = false).map { !it.loading }
103 | .collectAsState(initial = false)
104 |
105 | LaunchedEffect(showToastState.value) {
106 | if (showToastState.value) {
107 | Toast.makeText(
108 | this@ViewModelSampleActivity,
109 | "Finished loading",
110 | Toast.LENGTH_LONG
111 | ).show()
112 | }
113 | }
114 |
115 | Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
116 | SampleScreen(
117 | modifier = Modifier.padding(innerPadding),
118 | text = mainState.value.toString(),
119 | isLoading = mainState.value.loading,
120 | onStartSampleClicked = {
121 | launch {
122 | dispatcher.dispatch(LongUseCaseAction("HyperDevs"))
123 | }
124 | }
125 | )
126 | }
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/app/src/main/kotlin/mini/android/sample/ui/theme/Color.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2024 HyperDevs
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package mini.android.sample.ui.theme
18 |
19 | import androidx.compose.ui.graphics.Color
20 |
21 | val primaryLight = Color(0xFF3C6939)
22 | val onPrimaryLight = Color(0xFFFFFFFF)
23 | val primaryContainerLight = Color(0xFFBDF0B4)
24 | val onPrimaryContainerLight = Color(0xFF393838)
25 | val secondaryLight = Color(0xFF53634F)
26 | val onSecondaryLight = Color(0xFFFFFFFF)
27 | val secondaryContainerLight = Color(0xFFD6E8CE)
28 | val onSecondaryContainerLight = Color(0xFF393838)
29 | val tertiaryLight = Color(0xFF49672E)
30 | val onTertiaryLight = Color(0xFFFFFFFF)
31 | val tertiaryContainerLight = Color(0xFFCAEEA6)
32 | val onTertiaryContainerLight = Color(0xFF393838)
33 | val errorLight = Color(0xFFBA1A1A)
34 | val onErrorLight = Color(0xFFFFFFFF)
35 | val errorContainerLight = Color(0xFFFFDAD6)
36 | val onErrorContainerLight = Color(0xFF410002)
37 | val backgroundLight = Color(0xFFF7FBF1)
38 | val onBackgroundLight = Color(0xFF191D17)
39 | val surfaceLight = Color(0xFFF7FBF1)
40 | val onSurfaceLight = Color(0xFF191D17)
41 | val surfaceVariantLight = Color(0xFFDEE5D8)
42 | val onSurfaceVariantLight = Color(0xFF424940)
43 | val outlineLight = Color(0xFF72796F)
44 | val outlineVariantLight = Color(0xFFC2C8BD)
45 | val scrimLight = Color(0xFF393838)
46 | val inverseSurfaceLight = Color(0xFF2D322B)
47 | val inverseOnSurfaceLight = Color(0xFFEFF2E9)
48 | val inversePrimaryLight = Color(0xFFA1D399)
49 | val surfaceDimLight = Color(0xFFD8DBD2)
50 | val surfaceBrightLight = Color(0xFFF7FBF1)
51 | val surfaceContainerLowestLight = Color(0xFFFFFFFF)
52 | val surfaceContainerLowLight = Color(0xFFF1F5EB)
53 | val surfaceContainerLight = Color(0xFFECEFE6)
54 | val surfaceContainerHighLight = Color(0xFFE6E9E0)
55 | val surfaceContainerHighestLight = Color(0xFFE0E4DB)
56 |
57 | val primaryDark = Color(0xFFA1D399)
58 | val onPrimaryDark = Color(0xFF0B390F)
59 | val primaryContainerDark = Color(0xFF245023)
60 | val onPrimaryContainerDark = Color(0xFFBDF0B4)
61 | val secondaryDark = Color(0xFFBACCB3)
62 | val onSecondaryDark = Color(0xFF253423)
63 | val secondaryContainerDark = Color(0xFF3B4B38)
64 | val onSecondaryContainerDark = Color(0xFFD6E8CE)
65 | val tertiaryDark = Color(0xFFAED18D)
66 | val onTertiaryDark = Color(0xFF1C3703)
67 | val tertiaryContainerDark = Color(0xFF324E18)
68 | val onTertiaryContainerDark = Color(0xFFCAEEA6)
69 | val errorDark = Color(0xFFFFB4AB)
70 | val onErrorDark = Color(0xFF690005)
71 | val errorContainerDark = Color(0xFF93000A)
72 | val onErrorContainerDark = Color(0xFFFFDAD6)
73 | val backgroundDark = Color(0xFF393838)
74 | val onBackgroundDark = Color(0xFFE0E4DB)
75 | val surfaceDark = Color(0xFF393838)
76 | val onSurfaceDark = Color(0xFFE0E4DB)
77 | val surfaceVariantDark = Color(0xFF424940)
78 | val onSurfaceVariantDark = Color(0xFFC2C8BD)
79 | val outlineDark = Color(0xFF8C9388)
80 | val outlineVariantDark = Color(0xFF424940)
81 | val scrimDark = Color(0xFF393838)
82 | val inverseSurfaceDark = Color(0xFFE0E4DB)
83 | val inverseOnSurfaceDark = Color(0xFF2D322B)
84 | val inversePrimaryDark = Color(0xFF3C6939)
85 | val surfaceDimDark = Color(0xFF10140F)
86 | val surfaceBrightDark = Color(0xFF363A34)
87 | val surfaceContainerLowestDark = Color(0xFF0B0F0A)
88 | val surfaceContainerLowDark = Color(0xFF191D17)
89 | val surfaceContainerDark = Color(0xFF1D211B)
90 | val surfaceContainerHighDark = Color(0xFF272B25)
91 | val surfaceContainerHighestDark = Color(0xFF323630)
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/app/src/main/kotlin/mini/android/sample/ui/theme/Type.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2024 HyperDevs
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package mini.android.sample.ui.theme
18 |
19 | import androidx.compose.material3.Typography
20 |
21 | val AppTypography = Typography()
22 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
19 |
20 |
25 |
28 |
29 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
18 |
19 |
24 |
27 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_monochrome.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hyperdevs-team/mini-kotlin/ea00956349097f6ffdec7525f1c64dc48eab69b7/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hyperdevs-team/mini-kotlin/ea00956349097f6ffdec7525f1c64dc48eab69b7/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hyperdevs-team/mini-kotlin/ea00956349097f6ffdec7525f1c64dc48eab69b7/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hyperdevs-team/mini-kotlin/ea00956349097f6ffdec7525f1c64dc48eab69b7/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hyperdevs-team/mini-kotlin/ea00956349097f6ffdec7525f1c64dc48eab69b7/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hyperdevs-team/mini-kotlin/ea00956349097f6ffdec7525f1c64dc48eab69b7/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hyperdevs-team/mini-kotlin/ea00956349097f6ffdec7525f1c64dc48eab69b7/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hyperdevs-team/mini-kotlin/ea00956349097f6ffdec7525f1c64dc48eab69b7/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hyperdevs-team/mini-kotlin/ea00956349097f6ffdec7525f1c64dc48eab69b7/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hyperdevs-team/mini-kotlin/ea00956349097f6ffdec7525f1c64dc48eab69b7/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
19 |
20 |
21 | #393838
22 | #393838
23 | #8BC34A
24 | @color/white
25 |
26 | #ffffff
27 | #7dffffff
28 |
29 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
19 |
20 |
21 |
22 | 12sp
23 | 14sp
24 | 16sp
25 | 20sp
26 | 24sp
27 |
28 |
29 | 4dp
30 | 8dp
31 | 12dp
32 | 16dp
33 | 20dp
34 | 24dp
35 |
36 |
37 | 4dp
38 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
18 |
19 |
20 | Mini Sample
21 | Store Sample
22 | View Model Sample
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2024 HyperDevs
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | plugins {
18 | alias(libs.plugins.android.application) apply false
19 | alias(libs.plugins.android.library) apply false
20 |
21 | alias(libs.plugins.kotlin.jvm) apply false
22 | alias(libs.plugins.kotlin.android) apply false
23 | alias(libs.plugins.kotlin.kapt) apply false
24 | alias(libs.plugins.kotlin.ksp) apply false
25 |
26 | alias(libs.plugins.versions)
27 | }
28 |
29 | allprojects {
30 | group = "com.hyperdevs.mini"
31 | }
32 |
33 | tasks {
34 | val clean by registering(Delete::class) {
35 | delete(rootProject.layout.buildDirectory.asFile.get())
36 | }
37 | }
--------------------------------------------------------------------------------
/convention-plugins/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/convention-plugins/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2024 HyperDevs
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | plugins {
18 | `java-gradle-plugin`
19 | `kotlin-dsl`
20 | }
21 |
22 | dependencies {
23 | compileOnly(libs.android.gradle)
24 | implementation(libs.androidgitversion)
25 | }
26 |
27 | java {
28 | sourceCompatibility = JavaVersion.toVersion(libs.versions.java.sdk.get())
29 | targetCompatibility = JavaVersion.toVersion(libs.versions.java.sdk.get())
30 | }
31 |
32 | tasks.withType().configureEach {
33 | kotlinOptions {
34 | jvmTarget = libs.versions.java.sdk.get()
35 | }
36 | }
37 |
38 | gradlePlugin {
39 | plugins {
40 | register("androidApp") {
41 | id = "mini.android.plugins.androidApp"
42 | implementationClass = "mini.android.plugins.AndroidAppConventionPlugin"
43 | }
44 |
45 | register("androidLib") {
46 | id = "mini.android.plugins.androidLib"
47 | implementationClass = "mini.android.plugins.AndroidLibConventionPlugin"
48 | }
49 |
50 | register("javaLib") {
51 | id = "mini.android.plugins.javaLib"
52 | implementationClass = "mini.android.plugins.JavaLibConventionPlugin"
53 | }
54 | }
55 | }
--------------------------------------------------------------------------------
/convention-plugins/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2024 HyperDevs
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | @file:Suppress("UnstableApiUsage")
18 |
19 | dependencyResolutionManagement {
20 | repositories {
21 | google()
22 | mavenCentral()
23 | gradlePluginPortal()
24 | }
25 |
26 | versionCatalogs {
27 | create("libs") {
28 | from(files("../gradle/libs.versions.toml"))
29 | }
30 | }
31 | }
32 |
33 | rootProject.name = "convention-plugins"
--------------------------------------------------------------------------------
/convention-plugins/src/main/kotlin/mini/android/plugins/AndroidAppConventionPlugin.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2024 HyperDevs
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package mini.android.plugins
18 |
19 | import mini.android.plugins.extensions.applyAndroidAppVersioning
20 | import mini.android.plugins.extensions.applyAndroidLibPublishing
21 | import mini.android.plugins.extensions.applyVersioning
22 | import org.gradle.api.Plugin
23 | import org.gradle.api.Project
24 |
25 | class AndroidAppConventionPlugin : Plugin {
26 | override fun apply(target: Project) {
27 | with(target) {
28 | val (versionName, versionCode) = applyVersioning()
29 | applyAndroidAppVersioning(versionName, versionCode)
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/convention-plugins/src/main/kotlin/mini/android/plugins/AndroidLibConventionPlugin.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2024 HyperDevs
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package mini.android.plugins
18 |
19 | import mini.android.plugins.extensions.applyAndroidLibPublishing
20 | import mini.android.plugins.extensions.applyVersioning
21 | import org.gradle.api.Plugin
22 | import org.gradle.api.Project
23 |
24 | class AndroidLibConventionPlugin : Plugin {
25 | override fun apply(target: Project) {
26 | with(target) {
27 | val (versionName, _) = applyVersioning()
28 | applyAndroidLibPublishing(versionName)
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/convention-plugins/src/main/kotlin/mini/android/plugins/JavaLibConventionPlugin.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2024 HyperDevs
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package mini.android.plugins
18 |
19 | import mini.android.plugins.extensions.applyJavaLibPublishing
20 | import mini.android.plugins.extensions.applyVersioning
21 | import org.gradle.api.Plugin
22 | import org.gradle.api.Project
23 |
24 | class JavaLibConventionPlugin : Plugin {
25 | override fun apply(target: Project) {
26 | with(target) {
27 | val (versionName, _) = applyVersioning()
28 | applyJavaLibPublishing(versionName)
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/convention-plugins/src/main/kotlin/mini/android/plugins/extensions/MavenPomExtensions.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2024 HyperDevs
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package mini.android.plugins.extensions
18 |
19 | import org.gradle.api.publish.maven.internal.publication.DefaultMavenPom
20 |
21 | fun DefaultMavenPom.setMetadata(artifactName: String, artifactVersion: String) {
22 | name.set("Mini ($artifactName)")
23 | description.set("Mini is a minimal Flux architecture written in Kotlin that also adds a mix of useful features to build UIs fast.")
24 | url.set("https://github.com/hyperdevs-team/mini-kotlin/releases/tag/$artifactVersion")
25 | //version.set(miniVersion)
26 | inceptionYear.set("2017")
27 |
28 | licenses {
29 | license {
30 | name.set("The Apache License, Version 2.0")
31 | url.set("http://www.apache.org/licenses/LICENSE-2.0.txt")
32 | }
33 | }
34 |
35 | organization {
36 | name.set("HyperDevs")
37 | url.set("https://github.com/hyperdevs-team")
38 | }
39 |
40 | issueManagement {
41 | system.set("GitHub Issues")
42 | url.set("https://github.com/hyperdevs-team/mini-kotlin/issues")
43 | }
44 |
45 | scm {
46 | connection.set("scm:git:git@github.com:hyperdevs-team/mini-kotlin.git")
47 | url.set("https://github.com/hyperdevs-team/mini-kotlin.git")
48 | }
49 |
50 | developers {
51 | developer {
52 | name.set("Estefanía Sarasola Elvira")
53 | id.set("yamidragut")
54 | url.set("https://github.com/yamidragut")
55 | roles.set(listOf("Maintainer"))
56 | }
57 |
58 | developer {
59 | name.set("Sara Lucía Pérez")
60 | id.set("Babelia13")
61 | url.set("https://github.com/Babelia13")
62 | roles.set(listOf("Maintainer"))
63 | }
64 |
65 | developer {
66 | name.set("Adrián García")
67 | id.set("adriangl")
68 | url.set("https://github.com/adriangl")
69 | roles.set(listOf("Maintainer"))
70 | }
71 |
72 | developer {
73 | name.set("Francisco García Sierra")
74 | id.set("FrangSierra")
75 | url.set("https://github.com/FrangSierra")
76 | roles.set(listOf("Maintainer", "Initial Work"))
77 | }
78 |
79 | developer {
80 | name.set("Pablo Orgaz")
81 | id.set("pabloogc")
82 | url.set("https://github.com/pabloogc")
83 | roles.set(listOf("Initial Work"))
84 | }
85 | }
86 | }
--------------------------------------------------------------------------------
/convention-plugins/src/main/kotlin/mini/android/plugins/extensions/ProjectExtensions.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2024 HyperDevs
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package mini.android.plugins.extensions
18 |
19 | import com.android.build.api.dsl.ApplicationExtension
20 | import com.android.build.gradle.LibraryExtension
21 | import com.gladed.androidgitversion.AndroidGitVersionExtension
22 | import org.gradle.api.Project
23 | import org.gradle.api.plugins.JavaPluginExtension
24 | import org.gradle.api.publish.PublishingExtension
25 | import org.gradle.api.publish.maven.MavenPublication
26 | import org.gradle.api.publish.maven.internal.publication.DefaultMavenPom
27 | import org.gradle.kotlin.dsl.configure
28 |
29 | data class Version(val name: String, val code: Int)
30 |
31 | internal fun Project.applyVersioning(): Version {
32 | pluginManager.apply("com.gladed.androidgitversion")
33 | project.extensions.configure {
34 | codeFormat = "MNNPP"
35 | baseCode = 1
36 | }
37 |
38 | return Version(
39 | project.extensions.getByType(AndroidGitVersionExtension::class.java).name(),
40 | project.extensions.getByType(AndroidGitVersionExtension::class.java).code()
41 | )
42 | }
43 |
44 | internal fun Project.applyAndroidAppVersioning(versionName: String, versionCode: Int) {
45 | project.extensions.configure{
46 | defaultConfig {
47 | this.versionName = versionName
48 | this.versionCode = versionCode
49 | }
50 | }
51 | }
52 |
53 | internal fun Project.applyAndroidLibPublishing(versionName: String) {
54 | val publishingName = "release"
55 |
56 | pluginManager.apply("maven-publish")
57 |
58 | project.extensions.configure {
59 | publishing {
60 | singleVariant(publishingName) {
61 | withSourcesJar()
62 | withJavadocJar()
63 | }
64 | }
65 | }
66 |
67 | project.afterEvaluate {
68 | project.extensions.configure {
69 | publications {
70 | create(publishingName, MavenPublication::class.java) {
71 | from(components.getByName(publishingName))
72 |
73 | artifactId = project.name
74 | version = versionName
75 |
76 | (pom as DefaultMavenPom).setMetadata(
77 | project.name,
78 | versionName
79 | )
80 | }
81 | }
82 | }
83 | }
84 | }
85 |
86 | internal fun Project.applyJavaLibPublishing(versionName: String) {
87 | val publishingName = "maven"
88 |
89 | pluginManager.apply("java")
90 | pluginManager.apply("maven-publish")
91 |
92 | project.extensions.configure {
93 | withSourcesJar()
94 | withJavadocJar()
95 | }
96 |
97 | project.extensions.configure {
98 | publications {
99 | create(publishingName, MavenPublication::class.java) {
100 | from(components.getByName("java"))
101 |
102 | artifactId = project.name
103 | version = versionName
104 |
105 | (pom as DefaultMavenPom).setMetadata(
106 | project.name,
107 | versionName
108 | )
109 | }
110 | }
111 | }
112 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright 2021 HyperDevs
3 | #
4 | # Copyright 2020 BQ
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | # Project-wide Gradle settings.
20 | # IDE (e.g. Android Studio) users:
21 | # Gradle settings configured through the IDE *will take*
22 | # any settings specified in this file.
23 | # For more details on how to fn your build environment visit
24 | # http://www.gradle.org/docs/current/userguide/build_environment.html
25 | # Specifies the JVM arguments used for the daemon process.
26 | # The setting is particularly useful for tweaking memory settings.
27 | org.gradle.jvmargs=-Xmx1536m
28 | android.useAndroidX=true
29 | android.enableJetifier=false
30 | # When configured, Gradle will run in incubating parallel mode.
31 | # This option should only be used with decoupled projects. More details, visit
32 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
33 | # org.gradle.parallel=true
34 |
35 | # Some performance improvements
36 | org.gradle.parallel=true
37 | org.gradle.configureondemand=true
38 | org.gradle.caching=true
39 | org.gradle.daemon=true
40 | kapt.incremental.apt=true
41 | kapt.use.worker.api=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hyperdevs-team/mini-kotlin/ea00956349097f6ffdec7525f1c64dc48eab69b7/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/jitpack.yml:
--------------------------------------------------------------------------------
1 | jdk:
2 | - openjdk17
--------------------------------------------------------------------------------
/mini-android/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/mini-android/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2024 HyperDevs
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | plugins {
18 | alias(libs.plugins.android.library)
19 | alias(libs.plugins.kotlin.android)
20 | alias(libs.plugins.convention.androidLib)
21 | }
22 |
23 | android {
24 | namespace = "mini.android"
25 |
26 | compileSdk = libs.versions.android.compileSdk.get().toInt()
27 | buildToolsVersion = libs.versions.android.buildTools.get()
28 |
29 | defaultConfig {
30 | minSdk = libs.versions.android.minSdk.get().toInt()
31 | testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
32 | consumerProguardFiles("mini-android.pro")
33 | }
34 |
35 | buildTypes {
36 | release {
37 | isMinifyEnabled = false
38 | proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
39 | }
40 | }
41 |
42 | compileOptions {
43 | sourceCompatibility = JavaVersion.toVersion(libs.versions.java.sdk.get())
44 | targetCompatibility = JavaVersion.toVersion(libs.versions.java.sdk.get())
45 | }
46 | }
47 |
48 | tasks.withType().configureEach {
49 | kotlinOptions {
50 | jvmTarget = libs.versions.java.sdk.get()
51 | }
52 | }
53 |
54 | java {
55 | sourceCompatibility = JavaVersion.toVersion(libs.versions.java.sdk.get())
56 | targetCompatibility = JavaVersion.toVersion(libs.versions.java.sdk.get())
57 | }
58 |
59 | kotlin {
60 | jvmToolchain(libs.versions.java.sdk.get().toInt())
61 | }
62 |
63 | dependencies {
64 | api(project(":mini-common"))
65 |
66 | api(libs.kotlinx.coroutines.android)
67 | api(libs.androidx.appcompat)
68 | api(libs.androidx.activity)
69 | api(libs.androidx.fragment)
70 |
71 | api(libs.bundles.androidx.lifecycle)
72 |
73 | testImplementation(libs.junit)
74 | androidTestImplementation(libs.androidx.test.runner)
75 | androidTestImplementation(libs.espresso)
76 | }
77 |
78 |
--------------------------------------------------------------------------------
/mini-android/mini-android.pro:
--------------------------------------------------------------------------------
1 | # ViewModel's empty constructor is considered to be unused by proguard, so keep it
2 | -keepclassmembers,allowobfuscation class * extends androidx.lifecycle.ViewModel {
3 | ();
4 | }
5 | -keepclassmembers,allowobfuscation class * extends androidx.lifecycle.AndroidViewModel {
6 | (android.app.Application);
7 | }
--------------------------------------------------------------------------------
/mini-android/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.kts.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/mini-android/src/main/java/mini/android/FluxActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2021 HyperDevs
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package mini.android
18 |
19 | import android.os.Bundle
20 | import androidx.appcompat.app.AppCompatActivity
21 | import androidx.lifecycle.lifecycleScope
22 | import kotlinx.coroutines.CoroutineScope
23 | import kotlinx.coroutines.flow.Flow
24 | import kotlinx.coroutines.flow.launchIn
25 | import kotlinx.coroutines.launch
26 | import mini.CloseableTracker
27 | import mini.DefaultCloseableTracker
28 | import kotlin.coroutines.CoroutineContext
29 |
30 | abstract class FluxActivity : AppCompatActivity(),
31 | CloseableTracker by DefaultCloseableTracker(),
32 | CoroutineScope {
33 |
34 | override val coroutineContext: CoroutineContext
35 | get() = lifecycleScope.coroutineContext
36 |
37 | override fun onCreate(savedInstanceState: Bundle?) {
38 | super.onCreate(savedInstanceState)
39 | lifecycleScope.launch { whenCreated(savedInstanceState) }
40 | }
41 |
42 | override fun onResume() {
43 | super.onResume()
44 | lifecycleScope.launch { whenResumed() }
45 | }
46 |
47 | override fun onPause() {
48 | super.onPause()
49 | lifecycleScope.launch { whenPaused() }
50 | }
51 |
52 | override fun onStop() {
53 | super.onStop()
54 | lifecycleScope.launch { whenStopped() }
55 | }
56 |
57 | override fun onDestroy() {
58 | lifecycleScope.launch { whenDestroyed() }
59 | close()
60 | super.onDestroy()
61 | }
62 |
63 | fun Flow.launchInLifecycleScope() {
64 | launchIn(lifecycleScope)
65 | }
66 |
67 | protected open suspend fun whenCreated(savedInstanceState: Bundle?) = Unit
68 | protected open suspend fun whenResumed() = Unit
69 | protected open suspend fun whenPaused() = Unit
70 | protected open suspend fun whenStopped() = Unit
71 | protected open suspend fun whenDestroyed() = Unit
72 |
73 | }
--------------------------------------------------------------------------------
/mini-android/src/main/java/mini/android/FluxFragment.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2021 HyperDevs
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package mini.android
18 |
19 | import android.os.Bundle
20 | import androidx.fragment.app.Fragment
21 | import androidx.lifecycle.lifecycleScope
22 | import kotlinx.coroutines.CoroutineScope
23 | import kotlinx.coroutines.flow.Flow
24 | import kotlinx.coroutines.flow.launchIn
25 | import kotlinx.coroutines.launch
26 | import mini.CloseableTracker
27 | import mini.DefaultCloseableTracker
28 | import kotlin.coroutines.CoroutineContext
29 |
30 | abstract class FluxFragment : Fragment(),
31 | CloseableTracker by DefaultCloseableTracker(),
32 | CoroutineScope {
33 |
34 | override val coroutineContext: CoroutineContext
35 | get() = lifecycleScope.coroutineContext
36 |
37 | override fun onCreate(savedInstanceState: Bundle?) {
38 | super.onCreate(savedInstanceState)
39 | lifecycleScope.launch { whenCreated(savedInstanceState) }
40 | }
41 |
42 | override fun onResume() {
43 | super.onResume()
44 | lifecycleScope.launch { whenResumed() }
45 | }
46 |
47 | override fun onPause() {
48 | super.onPause()
49 | lifecycleScope.launch { whenPaused() }
50 | }
51 |
52 | override fun onStop() {
53 | super.onStop()
54 | lifecycleScope.launch { whenStopped() }
55 | }
56 |
57 | override fun onDestroy() {
58 | lifecycleScope.launch { whenDestroyed() }
59 | close()
60 | super.onDestroy()
61 | }
62 |
63 | fun Flow.launchOnUi() {
64 | launchIn(lifecycleScope)
65 | }
66 |
67 | protected open suspend fun whenCreated(savedInstanceState: Bundle?) = Unit
68 | protected open suspend fun whenResumed() = Unit
69 | protected open suspend fun whenPaused() = Unit
70 | protected open suspend fun whenStopped() = Unit
71 | protected open suspend fun whenDestroyed() = Unit
72 | }
--------------------------------------------------------------------------------
/mini-android/src/main/java/mini/android/FluxStoreViewModel.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2021 HyperDevs
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package mini.android
18 |
19 | import androidx.lifecycle.SavedStateHandle
20 | import androidx.lifecycle.ViewModel
21 | import mini.CloseableTracker
22 | import mini.DefaultCloseableTracker
23 | import mini.State
24 | import mini.StateContainer
25 | import mini.assertOnUiThread
26 | import java.io.Closeable
27 | import java.util.concurrent.CopyOnWriteArrayList
28 |
29 | abstract class FluxStoreViewModel(
30 | val savedStateHandle: SavedStateHandle) :
31 | ViewModel(),
32 | StateContainer,
33 | CloseableTracker by DefaultCloseableTracker() {
34 |
35 | class ViewModelSubscription internal constructor(private val vm: FluxStoreViewModel<*>,
36 | private val fn: Any) : Closeable {
37 | override fun close() {
38 | vm.listeners.remove(fn)
39 | }
40 | }
41 |
42 | private var _state: Any? = StateContainer.Companion.NoState
43 | private val listeners = CopyOnWriteArrayList<(S) -> Unit>()
44 |
45 | override val state: S
46 | get() {
47 | if (_state === StateContainer.Companion.NoState) {
48 | synchronized(this) {
49 | if (_state === StateContainer.Companion.NoState) {
50 | _state = restoreState(savedStateHandle) ?: initialState()
51 | }
52 | }
53 | }
54 | @Suppress("UNCHECKED_CAST")
55 | return _state as S
56 | }
57 |
58 | override fun setState(newState: S) {
59 | assertOnUiThread()
60 | performStateChange(newState)
61 | }
62 |
63 | private fun performStateChange(newState: S) {
64 | if (_state != newState) {
65 | _state = newState
66 | saveState(newState, savedStateHandle)
67 | listeners.forEach {
68 | it(newState)
69 | }
70 | }
71 | }
72 |
73 | /**
74 | * Persist the state, no-op by default.
75 | *
76 | * ```handle.set("state", state)```
77 | */
78 | open fun saveState(state: S, handle: SavedStateHandle) {
79 | //No-op
80 | }
81 |
82 | /**
83 | * Restore the state from the [SavedStateHandle] or null if nothing was saved.
84 | *
85 | * ```handle.get("state")```
86 | */
87 | open fun restoreState(handle: SavedStateHandle): S? {
88 | return null
89 | }
90 |
91 | override fun subscribe(hotStart: Boolean, fn: (S) -> Unit): Closeable {
92 | listeners.add(fn)
93 | if (hotStart) fn(state)
94 | return ViewModelSubscription(this, fn)
95 | }
96 |
97 | override fun onCleared() {
98 | super.onCleared()
99 | close()
100 | }
101 | }
--------------------------------------------------------------------------------
/mini-android/src/main/java/mini/android/FluxViewModel.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2021 HyperDevs
3 | *
4 | * Copyright 2020 BQ
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | package mini.android
20 |
21 | import androidx.annotation.CallSuper
22 | import androidx.lifecycle.ViewModel
23 | import mini.CloseableTracker
24 | import mini.DefaultCloseableTracker
25 |
26 | abstract class FluxViewModel : ViewModel(),
27 | CloseableTracker by DefaultCloseableTracker() {
28 |
29 | @CallSuper
30 | override fun onCleared() {
31 | super.onCleared()
32 | close()
33 | }
34 | }
--------------------------------------------------------------------------------
/mini-common/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/mini-common/build.gradle.kts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2024 HyperDevs
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | plugins {
18 | id("idea")
19 | alias(libs.plugins.kotlin.jvm)
20 | alias(libs.plugins.convention.javaLib)
21 | }
22 |
23 | dependencies {
24 | implementation(libs.kotlin.stdlib)
25 | implementation(libs.kotlin.reflect)
26 |
27 | // Optional Rx and Android bindings, one day these should be modules,
28 | // for now we compile against them but let user package library
29 | compileOnly(libs.android.library)
30 |
31 | compileOnly(libs.kotlinx.coroutines.core)
32 | testImplementation(libs.kotlinx.coroutines.core)
33 |
34 | testImplementation(libs.junit)
35 | testImplementation(libs.kluent)
36 | }
37 |
38 | tasks.withType().configureEach {
39 | kotlinOptions {
40 | jvmTarget = libs.versions.java.sdk.get()
41 | }
42 | }
43 |
44 | java {
45 | sourceCompatibility = JavaVersion.toVersion(libs.versions.java.sdk.get())
46 | targetCompatibility = JavaVersion.toVersion(libs.versions.java.sdk.get())
47 | }
48 |
49 | kotlin {
50 | jvmToolchain(libs.versions.java.sdk.get().toInt())
51 | }
52 |
53 | idea {
54 | module {
55 | val sourceFoldersToAdd = listOf(
56 | "build/generated/source/kapt/main",
57 | "build/generated/source/kaptKotlin/main",
58 | "build/generated/source/ksp/main"
59 | ).map { File(it) }
60 |
61 | sourceDirs.addAll(sourceFoldersToAdd)
62 | generatedSourceDirs.addAll(sourceFoldersToAdd)
63 | }
64 | }
65 |
66 |
--------------------------------------------------------------------------------
/mini-common/src/main/java/mini/AndroidInterop.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2021 HyperDevs
3 | *
4 | * Copyright 2020 BQ
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | package mini
20 |
21 | /**
22 | * Check if running on android device / emulator or jvm
23 | */
24 | internal val isAndroid by lazy {
25 | try {
26 | android.os.Build.VERSION.SDK_INT != 0
27 | } catch (e: Throwable) {
28 | false
29 | }
30 | }
31 |
32 | fun requireAndroid() {
33 | if (!isAndroid) {
34 | throw UnsupportedOperationException("This method can only be called from android environment")
35 | }
36 | }
--------------------------------------------------------------------------------
/mini-common/src/main/java/mini/Annotations.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2021 HyperDevs
3 | *
4 | * Copyright 2020 BQ
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | package mini
20 |
21 | import java.lang.annotation.Inherited
22 |
23 | const val DEFAULT_PRIORITY = 100
24 |
25 | /**
26 | * Mark a type as action for code generation. All actions must include this annotation
27 | * or dispatcher won't work properly.
28 | */
29 | @Target(AnnotationTarget.TYPE, AnnotationTarget.CLASS)
30 | @Retention(AnnotationRetention.RUNTIME)
31 | @Inherited
32 | annotation class Action
33 |
34 | /**
35 | * Mark a function declared in a [StateContainer] as a reducer function.
36 | *
37 | * Reducers function must have two parameters, the state that must have same time
38 | * as the [StateContainer] state, and the action being handled.
39 | *
40 | * If the reducer function is not pure, only the action parameter is allowed
41 | * and function should have no return.
42 | */
43 | @Target(AnnotationTarget.FUNCTION)
44 | @Retention(AnnotationRetention.RUNTIME)
45 | annotation class Reducer(val priority: Int = DEFAULT_PRIORITY)
46 |
47 |
--------------------------------------------------------------------------------
/mini-common/src/main/java/mini/CloseableTracker.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2021 HyperDevs
3 | *
4 | * Copyright 2020 BQ
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | package mini
20 |
21 | import java.io.Closeable
22 |
23 | interface CloseableTracker : Closeable {
24 | /**
25 | * Start tracking a disposable.
26 | */
27 | fun T.track(): T
28 | }
29 |
30 | class DefaultCloseableTracker : CloseableTracker {
31 | private val closeables = CompositeCloseable()
32 | override fun close() = closeables.close()
33 | override fun T.track(): T {
34 | closeables.add(this)
35 | return this
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/mini-common/src/main/java/mini/CompositeCloseable.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2021 HyperDevs
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package mini
18 |
19 | import java.io.Closeable
20 |
21 | /**
22 | * A collection of closeables.
23 | */
24 | class CompositeCloseable : Closeable {
25 | private val items = ArrayList()
26 |
27 | override fun close() {
28 | synchronized(this) {
29 | items.forEach { it.close() }
30 | items.clear()
31 | }
32 | }
33 |
34 | fun add(closeable: T): T {
35 | synchronized(this) {
36 | items.add(closeable)
37 | }
38 | return closeable
39 | }
40 | }
--------------------------------------------------------------------------------
/mini-common/src/main/java/mini/DiffAdapter.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2021 HyperDevs
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package mini
18 |
19 | import kotlin.reflect.KClass
20 |
21 | interface DiffAdapter {
22 |
23 | companion object {
24 | const val GENERATED_CLASS_SUFFIX = "DiffAdapter"
25 | }
26 |
27 | /**
28 | * Produce a json like diff of an object
29 | */
30 | fun diff(a: T, b: T, indent: String = " "): String?
31 | }
32 |
33 | class ListDiffAdapter> : DiffAdapter {
34 | companion object {
35 | val INSTANCE = ListDiffAdapter>()
36 | }
37 |
38 | override fun diff(a: T, b: T, indent: String): String? {
39 | val sb = StringBuilder()
40 | val aSize = a.size
41 | val bSize = b.size
42 | val range = 0..(kotlin.math.max(aSize, bSize))
43 | range.forEach { index ->
44 | val ai = a.getOrNull(index)
45 | val bi = b.getOrNull(index)
46 | val diff = diffObjects(ai, bi, indent)
47 | if (diff != null) {
48 | @Suppress("UNCHECKED_CAST")
49 | sb.append("\n$index: $diff")
50 | }
51 | }
52 | return "[${sb.toString().prependIndent(indent)}\n]"
53 | }
54 | }
55 |
56 | @Suppress("UNCHECKED_CAST")
57 | class MapDiffAdapter> : DiffAdapter {
58 |
59 | companion object {
60 | val INSTANCE = MapDiffAdapter