Skip to content

Commit

Permalink
Feat: Migrate :core:designsystem to KMP (openMF#2290)
Browse files Browse the repository at this point in the history
* Directory restructure :core:designsystem to KMP

* Feat: Configure theme and color

* Updated components, theme, utils, colors

* Update files after ci-prepush run

* Fix issues related to stringResources and R class

* Update files after ci-prepush run

* Separate utils and utility

* Refactor: Remove explicit color, size, and typography definitions

* Remove mistakenly added file

* Refactor: Update typography, colors
  • Loading branch information
biplab1 authored Jan 30, 2025
1 parent 34b0b32 commit 5f77fdf
Show file tree
Hide file tree
Showing 70 changed files with 4,424 additions and 751 deletions.
69 changes: 46 additions & 23 deletions core/designsystem/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,38 +8,61 @@
* See https://github.com/openMF/android-client/blob/master/LICENSE.md
*/
plugins {
alias(libs.plugins.mifos.android.library)
alias(libs.plugins.mifos.android.library.compose)
alias(libs.plugins.mifos.android.library.jacoco)
alias(libs.plugins.mifos.kmp.library)
alias(libs.plugins.jetbrainsCompose)
alias(libs.plugins.compose.compiler)
alias(libs.plugins.roborazzi)
}

android {
namespace = "com.mifos.core.designsystem"

defaultConfig {
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
namespace = "com.mifos.core.designsystem"
}

dependencies {
lintPublish(projects.lint)
kotlin {
sourceSets {
androidMain.dependencies {
implementation(libs.androidx.compose.ui.tooling.preview)
implementation(libs.androidx.activity.compose)
}
androidInstrumentedTest.dependencies {
implementation(libs.androidx.compose.ui.test)
}
androidUnitTest.dependencies {
implementation(libs.androidx.compose.ui.test)
}
commonMain.dependencies {
implementation(libs.coil.kt.compose)
implementation(compose.runtime)
implementation(compose.foundation)
implementation(compose.material3)
implementation(compose.materialIconsExtended)
implementation(compose.ui)
implementation(compose.uiUtil)
implementation(compose.components.resources)
implementation(compose.components.uiToolingPreview)
api(libs.back.handler)
api(libs.window.size)
}

api(libs.androidx.compose.foundation)
api(libs.androidx.compose.foundation.layout)
api(libs.androidx.compose.material.iconsExtended)
api(libs.androidx.compose.material3)
api(libs.androidx.compose.runtime)
api(libs.androidx.compose.ui.util)
api(libs.androidx.activity.compose)
nativeMain.dependencies {
implementation(compose.runtime)
}

// coil
implementation(libs.coil.kt.compose)
jsMain.dependencies {
implementation(compose.runtime)
}

testImplementation(libs.androidx.compose.ui.test)
testImplementation(libs.androidx.compose.ui.test.manifest)
testImplementation(libs.hilt.android.testing)
testImplementation(projects.core.testing)

androidTestImplementation(libs.androidx.compose.ui.test)
androidTestImplementation(projects.core.testing)
wasmJsMain.dependencies {
implementation(compose.runtime)
}
}
}

compose.resources {
publicResClass = true
generateResClass = always
packageOfResClass = "core.designsystem.generated.resources"
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
*/
package com.mifos.core.designsystem.component

import DrawingState
import PathState
import android.view.MotionEvent
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.fillMaxSize
Expand All @@ -23,6 +21,7 @@ import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.input.pointer.pointerInteropFilter
import com.mifos.core.designsystem.utility.PathState

@ExperimentalComposeUiApi
@Composable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,24 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.compose.LocalLifecycleOwner

// TODO:: Support for compose multiplatform
@Suppress("LongMethod", "CyclomaticComplexMethod")
@Composable
fun PermissionBox(
title: String,
confirmButtonText: String,
dismissButtonText: String,
requiredPermissions: List<String>,
title: Int,
confirmButtonText: Int,
dismissButtonText: Int,
description: Int? = null,
modifier: Modifier = Modifier,
description: String? = null,
onGranted: @Composable (() -> Unit)? = null,
) {
val context = LocalContext.current
Expand All @@ -56,7 +60,8 @@ fun PermissionBox(
requiredPermissions.all {
(context as? Activity)?.let { it1 ->
ActivityCompat.shouldShowRequestPermissionRationale(
it1, it,
it1,
it,
)
} == true
}
Expand All @@ -66,10 +71,10 @@ fun PermissionBox(
}

val decideCurrentPermissionStatus: (Boolean, Boolean) -> String =
{ permissionGranted, shouldShowPermissionRationale ->
if (permissionGranted) {
{ granted, rationale ->
if (granted) {
"Granted"
} else if (shouldShowPermissionRationale) {
} else if (rationale) {
"Rejected"
} else {
"Denied"
Expand All @@ -85,62 +90,67 @@ fun PermissionBox(
)
}

val multiplePermissionLauncher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.RequestMultiplePermissions(),
onResult = { permissionResults ->
val isGranted =
requiredPermissions.all { permissionResults[it] ?: false }
val multiplePermissionLauncher =
rememberLauncherForActivityResult(
contract = ActivityResultContracts.RequestMultiplePermissions(),
onResult = { permissionResults ->
val isGranted =
requiredPermissions.all { permissionResults[it] ?: false }

permissionGranted = isGranted
permissionGranted = isGranted

if (!isGranted) {
shouldShowPermissionRationale =
requiredPermissions.all {
(context as? Activity)?.let { it1 ->
if (!isGranted) {
shouldShowPermissionRationale =
requiredPermissions.all {
ActivityCompat.shouldShowRequestPermissionRationale(
it1, it,
context as Activity,
it,
)
} == false
}
}
shouldDirectUserToApplicationSettings =
!shouldShowPermissionRationale &&
!permissionGranted
currentPermissionStatus =
decideCurrentPermissionStatus(
permissionGranted,
shouldShowPermissionRationale,
)
},
)

DisposableEffect(
key1 = lifecycleOwner,
effect = {
val observer =
LifecycleEventObserver { _, event ->
if (event == Lifecycle.Event.ON_START &&
!permissionGranted &&
!shouldShowPermissionRationale
) {
multiplePermissionLauncher.launch(requiredPermissions.toTypedArray())
}
}
lifecycleOwner.lifecycle.addObserver(observer)
onDispose {
lifecycleOwner.lifecycle.removeObserver(observer)
}
shouldDirectUserToApplicationSettings =
!shouldShowPermissionRationale && !permissionGranted
currentPermissionStatus = decideCurrentPermissionStatus(
permissionGranted,
shouldShowPermissionRationale,
)
},
)

DisposableEffect(key1 = lifecycleOwner, effect = {
val observer = LifecycleEventObserver { _, event ->
if (event == Lifecycle.Event.ON_START &&
!permissionGranted &&
!shouldShowPermissionRationale
) {
multiplePermissionLauncher.launch(requiredPermissions.toTypedArray())
}
}
lifecycleOwner.lifecycle.addObserver(observer)
onDispose {
lifecycleOwner.lifecycle.removeObserver(observer)
}
})

if (shouldShowPermissionRationale) {
MifosDialogBox(
showDialogState = shouldShowPermissionRationale,
onDismiss = { shouldShowPermissionRationale = false },
title = title,
message = description,
confirmButtonText = confirmButtonText,
onConfirm = {
shouldShowPermissionRationale = false
multiplePermissionLauncher.launch(requiredPermissions.toTypedArray())
},
dismissButtonText = dismissButtonText,
)
}
MifosDialogBox(
showDialogState = shouldShowPermissionRationale,
onDismiss = { shouldShowPermissionRationale = false },
title = title,
confirmButtonText = confirmButtonText,
onConfirm = {
shouldShowPermissionRationale = false
multiplePermissionLauncher.launch(requiredPermissions.toTypedArray())
},
dismissButtonText = dismissButtonText,
message = description,
modifier = modifier,
)

if (shouldDirectUserToApplicationSettings) {
Intent(
Expand All @@ -152,6 +162,8 @@ fun PermissionBox(
}

if (permissionGranted) {
onGranted?.invoke()
if (onGranted != null) {
onGranted()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright 2025 Mifos Initiative
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* See https://github.com/openMF/android-client/blob/master/LICENSE.md
*/
package com.mifos.core.designsystem.theme

import android.os.Build
import androidx.compose.material3.ColorScheme
import androidx.compose.material3.dynamicDarkColorScheme
import androidx.compose.material3.dynamicLightColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalContext

@Composable
actual fun colorScheme(useDarkTheme: Boolean, dynamicColor: Boolean): ColorScheme {
return when {
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
val context = LocalContext.current
if (useDarkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
}

useDarkTheme -> darkScheme
else -> lightScheme
}
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@
*
* See https://github.com/openMF/android-client/blob/master/LICENSE.md
*/
package com.mifos.core.designsystem.component

import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.snapshots.SnapshotStateList
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Path
import com.mifos.core.designsystem.utility.PathState

class DrawingState {
var usedColors: MutableState<Set<Color>> = mutableStateOf(setOf())
Expand All @@ -38,9 +41,3 @@ class DrawingState {
currentPath.value = Path()
}
}

data class PathState(
val path: Path,
val color: Color,
val stroke: Float,
)
Loading

0 comments on commit 5f77fdf

Please sign in to comment.