Skip to content

Commit

Permalink
Refactor- [:feature:loan] Apply & Fix Detekt, Ktlint Rules (#2683)
Browse files Browse the repository at this point in the history
  • Loading branch information
niyajali authored Sep 1, 2024
1 parent f6a56b1 commit 6aad45e
Show file tree
Hide file tree
Showing 47 changed files with 1,552 additions and 700 deletions.
4 changes: 2 additions & 2 deletions config/detekt/detekt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ complexity:
ignoreOverloaded: false
CyclomaticComplexMethod:
active: true
threshold: 20
threshold: 25
ignoreSingleWhenExpression: false
ignoreSimpleWhenEntries: false
ignoreNestingFunctions: false
Expand All @@ -168,7 +168,7 @@ complexity:
threshold: 600
LongMethod:
active: true
threshold: 150 #60
threshold: 180 #60
LongParameterList:
active: true
# Updating Common values based on current scenario
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ fun MifosButton(
onClick: () -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
shape: Shape = ButtonDefaults. shape,
colors: ButtonColors = ButtonDefaults. buttonColors(),
elevation: ButtonElevation? = ButtonDefaults. buttonElevation(),
shape: Shape = ButtonDefaults.shape,
colors: ButtonColors = ButtonDefaults.buttonColors(),
elevation: ButtonElevation? = ButtonDefaults.buttonElevation(),
border: BorderStroke? = null,
contentPadding: PaddingValues = ButtonDefaults. ContentPadding,
contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
) {
Button(
Expand All @@ -60,6 +60,33 @@ fun MifosButton(
)
}

@Composable
fun MifosButton(
onClick: () -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
shape: Shape = ButtonDefaults.shape,
colors: ButtonColors = ButtonDefaults.buttonColors(),
elevation: ButtonElevation? = ButtonDefaults.buttonElevation(),
border: BorderStroke? = null,
contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
content: @Composable (RowScope.() -> Unit),
) {
Button(
modifier = modifier,
onClick = onClick,
enabled = enabled,
shape = shape,
colors = colors,
elevation = elevation,
border = border,
contentPadding = contentPadding,
interactionSource = interactionSource,
content = content,
)
}

@Composable
fun MifosTextButton(
text: String,
Expand Down
1 change: 1 addition & 0 deletions core/qrcode/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
22 changes: 22 additions & 0 deletions core/qrcode/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@

plugins {
alias(libs.plugins.mifos.android.library)
alias(libs.plugins.mifos.android.library.compose)
}

android {
namespace = "org.mifos.mobile.core.qrcode"
}

dependencies {
implementation(projects.core.model)

api(libs.zxing.core)
api(libs.squareup.retrofit.converter.gson)

//cameraX
implementation(libs.androidx.camera.camera2)
implementation(libs.androidx.camera.lifecycle)
implementation(libs.androidx.camera.view)
implementation(libs.androidx.camera.core)
}
111 changes: 111 additions & 0 deletions core/qrcode/src/main/kotlin/org/mifos/mobile/core/qr/BarcodeCamera.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package org.mifos.mobile.core.qr

import android.content.ContentValues.TAG
import android.content.Context
import android.util.Log
import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.camera.core.Camera
import androidx.camera.core.CameraSelector
import androidx.camera.core.ExperimentalGetImage
import androidx.camera.core.ImageAnalysis
import androidx.camera.core.ImageCapture
import androidx.camera.core.Preview
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.camera.view.PreviewView
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.viewinterop.AndroidView
import androidx.core.content.ContextCompat
import androidx.lifecycle.LifecycleOwner

@ExperimentalGetImage
class BarcodeCamera {

private var camera: Camera? = null

@Composable
fun BarcodeReaderCamera(
onBarcodeScanned: (String?) -> Unit,
isFlashOn: Boolean,
) {
LaunchedEffect(isFlashOn) {
toggleFlash(isOn = isFlashOn)
}

val lifecycleOwner = LocalLifecycleOwner.current

val imageCapture = remember {
ImageCapture.Builder().build()
}

AndroidView(
factory = { context ->
PreviewView(context).apply {
layoutParams =
LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
scaleType = PreviewView.ScaleType.FILL_START

startCamera(
context = context,
previewView = this,
imageCapture = imageCapture,
lifecycleOwner = lifecycleOwner,
onBarcodeScanned = onBarcodeScanned
)
}
}
)
}

private fun startCamera(
context: Context,
previewView: PreviewView,
lifecycleOwner: LifecycleOwner,
imageCapture: ImageCapture,
onBarcodeScanned: (String) -> Unit
) {
val cameraProviderFuture = ProcessCameraProvider.getInstance(context)

cameraProviderFuture.addListener(
{
val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()

val preview = Preview.Builder().build()
.also { it.setSurfaceProvider(previewView.surfaceProvider) }

val imageAnalysis = ImageAnalysis.Builder()
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.build()

imageAnalysis.setAnalyzer(
ContextCompat.getMainExecutor(context),
QrCodeAnalyzer(
onBarcodeScanned = onBarcodeScanned
)
)

val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA

try {
cameraProvider.unbindAll()
camera = cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, preview, imageCapture, imageAnalysis)
} catch (exc: Exception) {
Log.e(TAG, "Use case binding failed", exc)
}
},
ContextCompat.getMainExecutor(context)
)
}

private fun toggleFlash(
isOn: Boolean,
) {
camera?.cameraControl?.enableTorch(isOn)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package org.mifos.mobile.core.qr

import android.graphics.ImageFormat
import androidx.camera.core.ImageAnalysis
import androidx.camera.core.ImageProxy
import com.google.zxing.BarcodeFormat
import com.google.zxing.BinaryBitmap
import com.google.zxing.DecodeHintType
import com.google.zxing.MultiFormatReader
import com.google.zxing.PlanarYUVLuminanceSource
import com.google.zxing.common.HybridBinarizer
import java.nio.ByteBuffer

class QrCodeAnalyzer(
private val onBarcodeScanned: (String) -> Unit
) : ImageAnalysis.Analyzer {

private val supportedImageFormats = listOf(
ImageFormat.YUV_420_888,
ImageFormat.YUV_422_888,
ImageFormat.YUV_444_888,
)

override fun analyze(image: ImageProxy) {
if (image.format in supportedImageFormats) {
val bytes = image.planes.first().buffer.toByteArray()
val source = PlanarYUVLuminanceSource(
bytes,
image.width,
image.height,
0,
0,
image.width,
image.height,
false
)
val binaryBmp = BinaryBitmap(HybridBinarizer(source))
try {
val result = MultiFormatReader().apply {
setHints(
mapOf(
DecodeHintType.POSSIBLE_FORMATS to arrayListOf(
BarcodeFormat.QR_CODE
)
)
)
}.decode(binaryBmp)
onBarcodeScanned(result.text)
} catch (e: Exception) {
e.printStackTrace()
} finally {
image.close()
}
}
}

private fun ByteBuffer.toByteArray(): ByteArray {
rewind()
return ByteArray(remaining()).also {
get(it)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package org.mifos.mobile.core.qr

import android.graphics.Bitmap
import android.graphics.Color
import com.google.gson.Gson
import com.google.zxing.BarcodeFormat
import com.google.zxing.MultiFormatWriter
import com.google.zxing.common.BitMatrix
import org.mifos.mobile.core.model.entity.beneficiary.Beneficiary
import org.mifos.mobile.core.model.entity.templates.account.AccountType
import org.mifos.mobile.core.model.enums.AccountType as EnumsAccountType

object QrCodeGenerator {
private const val QR_CODE_SIZE = 200

/**
* Generate a QRCode which stores `str` in the form of [Bitmap]
* @param str Data which need to stored in QRCode
* @return Returns a [Bitmap] of QRCode or null if generation fails
*/
fun encodeAsBitmap(str: String?): Bitmap? {
if (str.isNullOrEmpty()) return null

return try {
val result = MultiFormatWriter().encode(
str,
BarcodeFormat.QR_CODE,
QR_CODE_SIZE,
QR_CODE_SIZE,
null,
)
createBitmapFromBitMatrix(result)
} catch (e: Exception) {
null
}
}

private fun createBitmapFromBitMatrix(matrix: BitMatrix): Bitmap {
val width = matrix.width
val height = matrix.height
val pixels = IntArray(width * height) { index ->
if (matrix[index % width, index / width]) Color.BLACK else Color.WHITE
}

return Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888).apply {
setPixels(pixels, 0, width, 0, 0, width, height)
}
}

/**
* Provides a string which contains json data for creating a [Beneficiary]
* @param accountNumber Account Number of client
* @param officeName Office Name of Client
* @param accountType [EnumsAccountType] i.e. SAVINGS or LOAN
* @return Returns a string with account details
*/
fun getAccountDetailsInString(
accountNumber: String?,
officeName: String?,
accountType: EnumsAccountType,
): String {
val payload = Beneficiary().apply {
this.accountNumber = accountNumber
this.accountType = AccountType().apply {
id = when (accountType) {
EnumsAccountType.SAVINGS -> 0
EnumsAccountType.LOAN -> 1
EnumsAccountType.SHARE -> -1
}
}
this.officeName = officeName
}

return Gson().toJson(payload)
}
}
20 changes: 10 additions & 10 deletions feature/loan/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
/*
* Copyright 2024 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/mobile-mobile/blob/master/LICENSE.md
*/
plugins {
alias(libs.plugins.mifos.android.feature)
alias(libs.plugins.mifos.android.library.compose)
Expand All @@ -8,14 +17,5 @@ android {
}

dependencies {
implementation(projects.core.ui)
implementation(projects.core.common)
implementation(projects.core.model)
implementation(projects.core.data)
implementation(projects.feature.qr)
implementation(libs.squareup.retrofit.converter.gson)
//
// testImplementation(libs.junit)
// androidTestImplementation(libs.androidx.test.ext.junit)
// androidTestImplementation(libs.espresso.core)
implementation(projects.core.qrcode)
}
9 changes: 9 additions & 0 deletions feature/loan/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2024 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/mobile-mobile/blob/master/LICENSE.md
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

</manifest>
Loading

0 comments on commit 6aad45e

Please sign in to comment.