Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mirego-base-setup 4 of X: Styling #43

Merged
merged 25 commits into from
Nov 27, 2023
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 34 additions & 1 deletion androidApp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,15 @@ android {
namespace = "com.mirego.kmp.boilerplate"
compileSdk = 34
defaultConfig {
minSdk = 21
minSdk = 28
targetSdk = 34

applicationId = "com.mirego.kmp.boilerplate"
versionCode = 1
versionName = "0.1"

val translationFilePath = "${project.rootDir}/shared/src/commonMain/resources/translations/translation.en.json"
buildConfigField("String", "KWORD_TRANSLATION_FILE_PATH", "\"$translationFilePath\"")
}
buildTypes {
debug {
Expand All @@ -38,6 +41,9 @@ android {
buildFeatures {
compose = true
}
androidResources {
generateLocaleConfig = true
}
composeOptions {
kotlinCompilerExtensionVersion = libs.versions.androidComposeCompiler.get()
}
Expand All @@ -46,16 +52,43 @@ android {
// See https://github.com/Kotlin/kotlinx.coroutines#avoiding-including-the-debug-infrastructure-in-the-resulting-apk
resources.excludes += "DebugProbesKt.bin"
}

sourceSets {
getByName("main") {
resources.srcDirs("../shared/src/commonMain/resources")
}
}

flavorDimensions += "environment"

productFlavors {
create("ci") {
dimension = "environment"
applicationIdSuffix = ".ci"
}

create("store") {
dimension = "environment"
}
}
}

dependencies {
implementation(project(":shared"))

implementation(libs.android.splash)
implementation(libs.androidx.appcompat)
implementation(libs.androidx.activity.compose)

implementation(platform(libs.androidx.compose.bom))
implementation(libs.accompanist.systemuicontroller)
implementation(libs.accompanist.placeholder.material)
implementation(libs.androidx.compose.ui)
implementation(libs.androidx.compose.ui.tooling)
implementation(libs.androidx.compose.material)
implementation(libs.koin.android)
implementation(libs.koin.androidx.compose)
implementation(libs.koin.androidx.compose.navigation)
implementation(libs.trikot.viewmodels.databinding)
implementation(libs.trikot.vmd.compose)
}
4 changes: 3 additions & 1 deletion androidApp/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,18 @@
<uses-permission android:name="android.permission.INTERNET" />

<application
android:name=".app.AndroidApplication"
android:allowBackup="true"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name="com.mirego.kmp.boilerplate.MainActivity"
android:name="com.mirego.kmp.boilerplate.app.MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>
23 changes: 0 additions & 23 deletions androidApp/src/main/java/com/mirego/kmp/boilerplate/Greeting.kt

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.mirego.kmp.boilerplate.app

import android.app.Application
import android.content.res.Configuration
import com.mirego.kmp.boilerplate.app.bootstrap.AndroidBootstrap
import com.mirego.kmp.boilerplate.bootstrap.Bootstrapper

class AndroidApplication : Application() {
private lateinit var bootstrap: AndroidBootstrap
val bootstrapper = Bootstrapper()

override fun onCreate() {
super.onCreate()
bootstrap = AndroidBootstrap(this)
bootstrapper.initDependencies(bootstrap)
}

override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
bootstrap.appInformation.updateLocale()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.mirego.kmp.boilerplate.app

import android.os.Bundle
import androidx.activity.compose.setContent
import androidx.appcompat.app.AppCompatActivity
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.core.view.WindowCompat
import com.mirego.kmp.boilerplate.app.ui.application.ApplicationView
import com.mirego.kmp.boilerplate.bootstrap.Bootstrapper
import com.mirego.kmp.boilerplate.trikot.viewmodels.declarative.compose.getInitialViewModel
import com.mirego.kmp.boilerplate.viewmodel.application.ApplicationViewModel

class MainActivity : AppCompatActivity() {
private val bootstrapper: Bootstrapper
get() = (applicationContext as AndroidApplication).bootstrapper

private val viewModel: ApplicationViewModel by lazy {
getInitialViewModel {
bootstrapper.applicationViewModel()
}
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
installSplashScreen()
WindowCompat.setDecorFitsSystemWindows(window, false)
setContent {
ApplicationView(applicationViewModel = viewModel)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.mirego.kmp.boilerplate.app.bootstrap

import android.content.Context
import com.mirego.kmp.boilerplate.BuildConfig
import com.mirego.kmp.boilerplate.app.resources.AndroidImageProvider
import com.mirego.kmp.boilerplate.bootstrap.AppEnvironment
import com.mirego.kmp.boilerplate.bootstrap.Bootstrap
import com.mirego.trikot.kword.android.AndroidKWord
import com.mirego.trikot.viewmodels.declarative.configuration.DefaultTextStyleProvider
import com.mirego.trikot.viewmodels.declarative.configuration.TrikotViewModelDeclarative
import java.util.*

class AndroidBootstrap(context: Context) : Bootstrap {

override val appInformation = AppInformationImpl(context)

override val environment = when (BuildConfig.FLAVOR.lowercase()) {
"ci" -> AppEnvironment.DEV
"store" -> AppEnvironment.PRODUCTION
else -> AppEnvironment.PRODUCTION
}

init {
if (Locale.getDefault().language.lowercase() == "fr") {
AndroidKWord.setCurrentLanguageCode("fr")
} else {
AndroidKWord.setCurrentLanguageCode("en")
}

TrikotViewModelDeclarative.initialize(
imageProvider = AndroidImageProvider(),
textStyleProvider = DefaultTextStyleProvider()
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.mirego.kmp.boilerplate.app.bootstrap

import android.content.Context
import com.mirego.kmp.boilerplate.BuildConfig
import com.mirego.kmp.boilerplate.bootstrap.AppInformation
import com.mirego.kmp.boilerplate.model.Language
import com.mirego.kmp.boilerplate.model.Locale
import com.mirego.kmp.boilerplate.utils.ConcreteFlow
import com.mirego.kmp.boilerplate.utils.wrap
import kotlinx.coroutines.flow.MutableStateFlow

class AppInformationImpl(context: Context) : AppInformation {
private val internalLocale = MutableStateFlow(currentLocale())
override fun locale(): ConcreteFlow<Locale> = internalLocale.wrap()

fun updateLocale() {
internalLocale.value = currentLocale()
}

private fun currentLocale() = Locale(
if (java.util.Locale.getDefault().language.lowercase() == "fr") Language.FRENCH else Language.ENGLISH,
java.util.Locale.getDefault().country
)

override val versionNumber: String = "${BuildConfig.VERSION_NAME}.${BuildConfig.VERSION_CODE}"
override val diskCachePath: String = context.cacheDir.toString()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.mirego.kmp.boilerplate.app.resources

import android.content.Context
import com.mirego.kmp.boilerplate.R
import com.mirego.kmp.boilerplate.viewmodel.common.SharedImageResource
import com.mirego.trikot.viewmodels.declarative.configuration.VMDImageProvider
import com.mirego.trikot.viewmodels.declarative.properties.VMDImageResource

class AndroidImageProvider : VMDImageProvider {
override fun resourceIdForResource(resource: VMDImageResource, context: Context) = when(resource) {
is SharedImageResource -> when(resource) {
SharedImageResource.emptyPageIcon -> R.drawable.baseline_question_mark_24
SharedImageResource.errorPageIcon -> R.drawable.baseline_warning_24
SharedImageResource.imagePlaceholder -> R.drawable.baseline_image_24
}
else -> null
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.mirego.kmp.boilerplate.app.ui.application

import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.tooling.preview.Preview
import com.mirego.kmp.boilerplate.app.ui.preview.PreviewProvider
import com.mirego.kmp.boilerplate.app.ui.root.RootView
import com.mirego.kmp.boilerplate.app.ui.theme.Theme
import com.mirego.kmp.boilerplate.viewmodel.application.ApplicationViewModel
import com.mirego.trikot.viewmodels.declarative.compose.extensions.observeAsState

@Composable
fun ApplicationView(applicationViewModel: ApplicationViewModel) {
val viewModel: ApplicationViewModel by applicationViewModel.observeAsState()
Theme {
RootView(rootViewModel = viewModel.rootViewModel)
}
}

@Preview
@Composable
fun PreviewApplicationView() {
PreviewProvider {
ApplicationView(applicationViewModel = it.createApplication())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.mirego.kmp.boilerplate.app.ui.common

import androidx.compose.ui.unit.dp

object Const {
val padding = 16.dp
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.mirego.kmp.boilerplate.app.ui.common

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.mirego.kmp.boilerplate.app.ui.common.Const.padding
import com.mirego.kmp.boilerplate.app.ui.preview.PreviewProvider
import com.mirego.kmp.boilerplate.app.ui.projects.ProjectsView
import com.mirego.kmp.boilerplate.app.ui.theme.TextSize
import com.mirego.kmp.boilerplate.app.ui.theme.TextWeight
import com.mirego.kmp.boilerplate.app.ui.theme.style
import com.mirego.kmp.boilerplate.usecase.preview.PreviewState
import com.mirego.kmp.boilerplate.viewmodel.common.EmptyViewModel
import com.mirego.trikot.viewmodels.declarative.compose.extensions.observeAsState
import com.mirego.trikot.viewmodels.declarative.compose.viewmodel.VMDImage
import com.mirego.trikot.viewmodels.declarative.compose.viewmodel.VMDText

@Composable
fun EmptyContentView(emptyViewModel: EmptyViewModel, modifier: Modifier = Modifier) {
val viewModel: EmptyViewModel by emptyViewModel.observeAsState()
Column(
modifier = modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally
) {
VMDImage(
modifier = Modifier.size(55.dp),
viewModel = viewModel.icon,
colorFilter = ColorFilter.tint(Color.White)
)

VMDText(
modifier = Modifier.padding(top = padding * 2),
viewModel = viewModel.title,
color = Color.White,
style = style(TextSize.LARGE_TITLE, TextWeight.REGULAR),
maxLines = 1
)

VMDText(
modifier = Modifier.padding(top = padding),
viewModel = viewModel.message,
color = Color.White,
style = style(TextSize.BODY, TextWeight.REGULAR),
textAlign = TextAlign.Center
)
}
}

@Preview
@Composable
fun PreviewEmptyContentView() {
PreviewProvider {
ProjectsView(projectsViewModel = it.createProjects(previewState = PreviewState.Data.Empty))
}
}
Loading
Loading