diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f2f3cf91..a48526cc 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -19,6 +19,26 @@ jobs: ref: ${{ github.head_ref }} submodules: "recursive" + - name: Cache Gradle + uses: actions/cache@v3 + with: + path: | + ~/.gradle/caches/modules-* + ~/.gradle/caches/jars-* + ~/.gradle/caches/build-cache-* + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }} + restore-keys: | + ${{ runner.os }}-gradle- + + - name: Install Kscript + run: | + curl -s "https://get.sdkman.io" | bash + source "$HOME/.sdkman/bin/sdkman-init.sh" + source android/version.properties + sdk install kotlin $kotlinVersion + sdk install kscript $kscriptVersion + echo $PATH >> $GITHUB_PATH + # To avoid code change in git when refreshing the "sample" project - name: Preserve the ArkanaKeys run: mv -f ./sample/ios/ArkanaKeys ../ diff --git a/.gitmodules b/.gitmodules index 117eab97..8b88b8ad 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,7 @@ [submodule "ios"] path = ios url = https://github.com/nimblehq/ios-templates.git +[submodule "android"] + path = android + url = git@github.com:nimblehq/android-templates.git + branch = feature/replace-hilt-with-koin diff --git a/android b/android new file mode 160000 index 00000000..5cb0ea45 --- /dev/null +++ b/android @@ -0,0 +1 @@ +Subproject commit 5cb0ea459a57f9363406c5dddc1de0800c5e43e4 diff --git a/android/.gitignore b/android/.gitignore deleted file mode 100644 index eb82db4a..00000000 --- a/android/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -# Google services -google-services.json - -# Keystore -config/release.keystore diff --git a/android/build.gradle.kts b/android/build.gradle.kts deleted file mode 100644 index b077b599..00000000 --- a/android/build.gradle.kts +++ /dev/null @@ -1,147 +0,0 @@ -import org.jetbrains.kotlin.konan.properties.loadProperties - -plugins { - id(Plugins.ANDROID_APPLICATION) - id(Plugins.KOVER) - kotlin(Plugins.ANDROID) -} - -val keystoreProperties = loadProperties("$rootDir/signing.properties") - -android { - namespace = "co.nimblehq.kmm.template" - compileSdk = Versions.ANDROID_COMPILE_SDK - defaultConfig { - applicationId = "co.nimblehq.kmm.template" - minSdk = Versions.ANDROID_MIN_SDK - targetSdk = Versions.ANDROID_TARGET_SDK - versionCode = Versions.ANDROID_VERSION_CODE - versionName = Versions.ANDROID_VERSION_NAME - } - buildFeatures { - compose = true - } - composeOptions { - kotlinCompilerExtensionVersion = Versions.COMPOSE_COMPILER - } - packaging { - resources { - excludes += "/META-INF/{AL2.0,LGPL2.1}" - } - } - signingConfigs { - create(BuildTypes.RELEASE) { - // Remember to edit signing.properties to have the correct info for release build. - storeFile = file("../config/release.keystore") - storePassword = keystoreProperties.getProperty("KEYSTORE_PASSWORD") - keyPassword = keystoreProperties.getProperty("KEY_PASSWORD") - keyAlias = keystoreProperties.getProperty("KEY_ALIAS") - } - - getByName(BuildTypes.DEBUG) { - storeFile = file("../config/debug.keystore") - //FIXME: Replace with your own password - storePassword = "oQ4mL1jY2uX7wD8q" - keyAlias = "debug-key-alias" - keyPassword = "oQ4mL1jY2uX7wD8q" - } - } - buildTypes { - getByName(BuildTypes.RELEASE) { - isMinifyEnabled = true - isDebuggable = false - isShrinkResources = true - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - signingConfig = signingConfigs[BuildTypes.RELEASE] - } - - getByName(BuildTypes.DEBUG) { - // For quickly testing build with proguard, enable this - isMinifyEnabled = false - signingConfig = signingConfigs[BuildTypes.DEBUG] - } - } - flavorDimensions += Flavors.DIMENSION_VERSION - productFlavors { - create(Flavors.STAGING) { - applicationIdSuffix = ".staging" - resValue("string", "app_name", "KMM Templates - Staging") - } - - create(Flavors.PRODUCTION) { - resValue("string", "app_name", "KMM Templates") - } - } - compileOptions { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 - } - kotlinOptions { - jvmTarget = JavaVersion.VERSION_17.toString() - } -} - -dependencies { - implementation(project(Modules.SHARED)) - - with(Dependencies.AndroidX) { - implementation(ACTIVITY_COMPOSE) - } - - with(Dependencies.Compose) { - implementation(UI) - implementation(UI_GRAPHICS) - implementation(MATERIAL) - implementation(NAVIGATION) - implementation(UI_TOOLING) - } - - with(Dependencies.Koin) { - implementation(CORE) - implementation(ANDROID) - implementation(COMPOSE) - } - - with(Dependencies.Log) { - implementation(TIMBER) - } - - with(Dependencies.Test) { - implementation(JUNIT) - implementation(COROUTINES) - } -} - -/* - * Kover configs - */ -dependencies { - kover(project(":shared")) -} - -koverReport { - defaults { - mergeWith("stagingDebug") - - val excludedFiles = listOf( - "io.mockative.*", - "*.BuildConfig", - "*.BuildKonfig", // BuildKonfig generated - "*.ComposableSingletons*", // Jetpack Compose generated - "*.*\$*Preview\$*", // Jetpack Compose Preview functions - "*.di.*", // Koin - "*.ui.preview.*", // Jetpack Compose Preview providers - "*.*Test", // Test files - "*.*Test*", // Test cases - "*.*Mock", // mockative @Mock generated - "*.test.*", // Test util package - "*.*\$\$serializer", // Kotlinx serializer - ) - - filters { - excludes { - classes(excludedFiles) - } - } - } -} diff --git a/android/src/debug/java/co/nimblehq/kmm/template/util/LogUtil.kt b/android/src/debug/java/co/nimblehq/kmm/template/util/LogUtil.kt deleted file mode 100644 index d6aa6e3b..00000000 --- a/android/src/debug/java/co/nimblehq/kmm/template/util/LogUtil.kt +++ /dev/null @@ -1,10 +0,0 @@ -package co.nimblehq.kmm.template.util - -import timber.log.Timber - -object LogUtil { - - fun setUpLogging() { - Timber.plant(Timber.DebugTree()) - } -} diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml deleted file mode 100644 index 44c41ed3..00000000 --- a/android/src/main/AndroidManifest.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - diff --git a/android/src/main/java/co/nimblehq/kmm/template/MainApplication.kt b/android/src/main/java/co/nimblehq/kmm/template/MainApplication.kt deleted file mode 100644 index ee71fa08..00000000 --- a/android/src/main/java/co/nimblehq/kmm/template/MainApplication.kt +++ /dev/null @@ -1,19 +0,0 @@ -package co.nimblehq.kmm.template - -import android.app.Application -import co.nimblehq.kmm.template.di.androidViewModelModule -import co.nimblehq.kmm.template.util.LogUtil -import co.nimblehq.kmm.template.di.initKoin -import org.koin.android.ext.koin.androidContext - -class MainApplication : Application() { - - override fun onCreate() { - super.onCreate() - LogUtil.setUpLogging() - initKoin { - androidContext(applicationContext) - modules(androidViewModelModule) - } - } -} diff --git a/android/src/main/java/co/nimblehq/kmm/template/di/ViewModelModule.kt b/android/src/main/java/co/nimblehq/kmm/template/di/ViewModelModule.kt deleted file mode 100644 index 69875337..00000000 --- a/android/src/main/java/co/nimblehq/kmm/template/di/ViewModelModule.kt +++ /dev/null @@ -1,8 +0,0 @@ -package co.nimblehq.kmm.template.di - -import org.koin.core.module.Module -import org.koin.dsl.module - -val androidViewModelModule: Module = module { - // TODO declare viewModel modules here -} diff --git a/android/src/main/java/co/nimblehq/kmm/template/lib/TypeAlias.kt b/android/src/main/java/co/nimblehq/kmm/template/lib/TypeAlias.kt deleted file mode 100644 index 5e6a53c9..00000000 --- a/android/src/main/java/co/nimblehq/kmm/template/lib/TypeAlias.kt +++ /dev/null @@ -1,3 +0,0 @@ -package co.nimblehq.kmm.template.lib - -typealias IsLoading = Boolean diff --git a/android/src/main/java/co/nimblehq/kmm/template/ui/base/BaseViewModel.kt b/android/src/main/java/co/nimblehq/kmm/template/ui/base/BaseViewModel.kt deleted file mode 100644 index 65ac5a84..00000000 --- a/android/src/main/java/co/nimblehq/kmm/template/ui/base/BaseViewModel.kt +++ /dev/null @@ -1,52 +0,0 @@ -package co.nimblehq.kmm.template.ui.base - -import androidx.compose.runtime.* -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import kotlinx.coroutines.flow.* -import kotlinx.coroutines.launch -import co.nimblehq.kmm.template.lib.IsLoading -import co.nimblehq.kmm.template.ui.navigation.AppDestination - -@Suppress("PropertyName") -abstract class BaseViewModel : ViewModel() { - - private var loadingCount: Int = 0 - - private val _isLoading = MutableStateFlow(false) - val isLoading: StateFlow = _isLoading - - protected val _error = MutableStateFlow(null) - val error: StateFlow = _error - - protected val _navigator = MutableSharedFlow() - val navigator: SharedFlow = _navigator - - /** - * To show loading manually, should call `hideLoading` after - */ - protected fun showLoading() { - if (loadingCount == 0) { - _isLoading.value = true - } - loadingCount++ - } - - /** - * To hide loading manually, should be called after `showLoading` - */ - protected fun hideLoading() { - loadingCount-- - if (loadingCount == 0) { - _isLoading.value = false - } - } - - protected fun Flow.injectLoading(): Flow = this - .onStart { showLoading() } - .onCompletion { hideLoading() } - - fun clearError() { - viewModelScope.launch { _error.emit(null) } - } -} diff --git a/android/src/main/java/co/nimblehq/kmm/template/ui/navigation/AppDestination.kt b/android/src/main/java/co/nimblehq/kmm/template/ui/navigation/AppDestination.kt deleted file mode 100644 index 22017549..00000000 --- a/android/src/main/java/co/nimblehq/kmm/template/ui/navigation/AppDestination.kt +++ /dev/null @@ -1,16 +0,0 @@ -package co.nimblehq.kmm.template.ui.navigation - -import androidx.navigation.NamedNavArgument - -sealed class AppDestination(val route: String = "") { - - open val arguments: List = emptyList() - - open var destination: String = route - - //====================================================// - - object Up : AppDestination() - - object Home : AppDestination("home") -} diff --git a/android/src/main/java/co/nimblehq/kmm/template/ui/navigation/AppNavigation.kt b/android/src/main/java/co/nimblehq/kmm/template/ui/navigation/AppNavigation.kt deleted file mode 100644 index 2b064b81..00000000 --- a/android/src/main/java/co/nimblehq/kmm/template/ui/navigation/AppNavigation.kt +++ /dev/null @@ -1,44 +0,0 @@ -package co.nimblehq.kmm.template.ui.navigation - -import androidx.compose.runtime.Composable -import androidx.navigation.* -import androidx.navigation.compose.* -import co.nimblehq.kmm.template.ui.screens.home.HomeScreen - -@Composable -fun AppNavigation( - navController: NavHostController = rememberNavController(), - startDestination: String = AppDestination.Home.destination -) { - NavHost( - navController = navController, - startDestination = startDestination - ) { - composable(AppDestination.Home) { - HomeScreen( - // TODO - // navigator = { destination -> navController.navigate(destination) } - ) - } - } -} - -private fun NavGraphBuilder.composable( - destination: AppDestination, - deepLinks: List = emptyList(), - content: @Composable (NavBackStackEntry) -> Unit -) { - composable( - route = destination.route, - arguments = destination.arguments, - deepLinks = deepLinks, - content = content - ) -} - -private fun NavHostController.navigate(destination: AppDestination) { - when (destination) { - is AppDestination.Up -> popBackStack() - else -> navigate(route = destination.destination) - } -} diff --git a/android/src/main/java/co/nimblehq/kmm/template/ui/screens/MainActivity.kt b/android/src/main/java/co/nimblehq/kmm/template/ui/screens/MainActivity.kt deleted file mode 100644 index 75d6bbc1..00000000 --- a/android/src/main/java/co/nimblehq/kmm/template/ui/screens/MainActivity.kt +++ /dev/null @@ -1,19 +0,0 @@ -package co.nimblehq.kmm.template.ui.screens - -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import co.nimblehq.kmm.template.ui.navigation.AppNavigation -import co.nimblehq.kmm.template.ui.theme.ComposeTheme - -class MainActivity : ComponentActivity() { - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContent { - ComposeTheme { - AppNavigation() - } - } - } -} diff --git a/android/src/main/java/co/nimblehq/kmm/template/ui/screens/home/HomeScreen.kt b/android/src/main/java/co/nimblehq/kmm/template/ui/screens/home/HomeScreen.kt deleted file mode 100644 index 800e2bc7..00000000 --- a/android/src/main/java/co/nimblehq/kmm/template/ui/screens/home/HomeScreen.kt +++ /dev/null @@ -1,27 +0,0 @@ -package co.nimblehq.kmm.template.ui.screens.home - -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.material.* -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview -import co.nimblehq.kmm.template.Greeting -import co.nimblehq.kmm.template.ui.theme.ComposeTheme - -@Composable -fun HomeScreen() { - Surface( - modifier = Modifier.fillMaxSize(), - color = MaterialTheme.colors.background - ) { - Text(text = Greeting().greet()) - } -} - -@Preview -@Composable -private fun HomeScreenPreview() { - ComposeTheme { - HomeScreen() - } -} diff --git a/android/src/main/java/co/nimblehq/kmm/template/ui/theme/AppColors.kt b/android/src/main/java/co/nimblehq/kmm/template/ui/theme/AppColors.kt deleted file mode 100644 index 37eca4df..00000000 --- a/android/src/main/java/co/nimblehq/kmm/template/ui/theme/AppColors.kt +++ /dev/null @@ -1,32 +0,0 @@ -package co.nimblehq.kmm.template.ui.theme - -import androidx.compose.material.* -import androidx.compose.runtime.staticCompositionLocalOf -import androidx.compose.ui.graphics.Color - -/** - * Extend final [Colors] class to provide more custom app colors. - */ -data class AppColors( - val themeColors: Colors, - - // Custom colors here -) - -internal val LightColorPalette = AppColors( - themeColors = lightColors( - primary = Color(0xFF6200EE), - primaryVariant = Color(0xFF3700B3), - secondary = Color(0xFF03DAC5) - ) -) - -internal val DarkColorPalette = AppColors( - themeColors = darkColors( - primary = Color(0xFFBB86FC), - primaryVariant = Color(0xFF3700B3), - secondary = Color(0xFF03DAC5) - ) -) - -internal val LocalColors = staticCompositionLocalOf { LightColorPalette } diff --git a/android/src/main/java/co/nimblehq/kmm/template/ui/theme/AppDimensions.kt b/android/src/main/java/co/nimblehq/kmm/template/ui/theme/AppDimensions.kt deleted file mode 100644 index 3875be76..00000000 --- a/android/src/main/java/co/nimblehq/kmm/template/ui/theme/AppDimensions.kt +++ /dev/null @@ -1,9 +0,0 @@ -package co.nimblehq.kmm.template.ui.theme - -import androidx.compose.runtime.staticCompositionLocalOf - -class AppDimensions { - // Custom dimensions here -} - -internal val LocalAppDimensions = staticCompositionLocalOf { AppDimensions() } diff --git a/android/src/main/java/co/nimblehq/kmm/template/ui/theme/AppStyles.kt b/android/src/main/java/co/nimblehq/kmm/template/ui/theme/AppStyles.kt deleted file mode 100644 index b6568d36..00000000 --- a/android/src/main/java/co/nimblehq/kmm/template/ui/theme/AppStyles.kt +++ /dev/null @@ -1,9 +0,0 @@ -package co.nimblehq.kmm.template.ui.theme - -import androidx.compose.runtime.staticCompositionLocalOf - -class AppStyles { - // Custom styles here -} - -internal val LocalAppStyles = staticCompositionLocalOf { AppStyles() } diff --git a/android/src/main/java/co/nimblehq/kmm/template/ui/theme/Theme.kt b/android/src/main/java/co/nimblehq/kmm/template/ui/theme/Theme.kt deleted file mode 100644 index ae5e06ad..00000000 --- a/android/src/main/java/co/nimblehq/kmm/template/ui/theme/Theme.kt +++ /dev/null @@ -1,84 +0,0 @@ -@file:Suppress("MatchingDeclarationName") -package co.nimblehq.kmm.template.ui.theme - -import androidx.compose.foundation.isSystemInDarkTheme -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.* -import androidx.compose.runtime.* -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.font.FontFamily -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp - -@Composable -fun ComposeTheme( - darkTheme: Boolean = isSystemInDarkTheme(), - content: @Composable () -> Unit -) { - val colors = if (darkTheme) { - DarkColorPalette - } else { - LightColorPalette - } - val dimensions = LocalAppDimensions.current - val styles = LocalAppStyles.current - - val typography = Typography( - body1 = TextStyle( - fontFamily = FontFamily.Default, - fontWeight = FontWeight.Normal, - fontSize = 16.sp - ) - ) - val shapes = Shapes( - small = RoundedCornerShape(4.dp), - medium = RoundedCornerShape(4.dp), - large = RoundedCornerShape(0.dp) - ) - - CompositionLocalProvider( - LocalColors provides colors, - LocalAppDimensions provides dimensions, - LocalAppStyles provides styles - ) { - MaterialTheme( - colors = colors.themeColors, - typography = typography, - shapes = shapes, - content = content - ) - } -} - -/** - * Alternate to [MaterialTheme] allowing us to add our own theme systems - * or to extend [MaterialTheme]'s types e.g. return our own [Colors] extension. - */ -object AppTheme { - - val colors: AppColors - @Composable - @ReadOnlyComposable - get() = LocalColors.current - - val typography: Typography - @Composable - @ReadOnlyComposable - get() = MaterialTheme.typography - - val shapes: Shapes - @Composable - @ReadOnlyComposable - get() = MaterialTheme.shapes - - val dimensions: AppDimensions - @Composable - @ReadOnlyComposable - get() = LocalAppDimensions.current - - val styles: AppStyles - @Composable - @ReadOnlyComposable - get() = LocalAppStyles.current -} diff --git a/android/src/main/res/values/styles.xml b/android/src/main/res/values/styles.xml deleted file mode 100644 index 676b4dda..00000000 --- a/android/src/main/res/values/styles.xml +++ /dev/null @@ -1,3 +0,0 @@ - -