Skip to content

Commit f6d2be9

Browse files
committed
updated
1 parent 729d4fb commit f6d2be9

11 files changed

Lines changed: 327 additions & 23 deletions

File tree

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
package com.mifos.core.designsystem.component
2+
3+
import android.Manifest
4+
import androidx.compose.runtime.Composable
5+
import android.app.Activity
6+
import android.content.Intent
7+
import android.content.pm.PackageManager
8+
import android.net.Uri
9+
import android.os.Build
10+
import android.provider.Settings
11+
import androidx.activity.compose.rememberLauncherForActivityResult
12+
import androidx.activity.result.contract.ActivityResultContracts
13+
import androidx.compose.runtime.DisposableEffect
14+
import androidx.compose.runtime.getValue
15+
import androidx.compose.runtime.mutableStateOf
16+
import androidx.compose.runtime.remember
17+
import androidx.compose.runtime.setValue
18+
import androidx.compose.ui.platform.LocalContext
19+
import androidx.compose.ui.platform.LocalLifecycleOwner
20+
import androidx.core.app.ActivityCompat
21+
import androidx.core.content.ContextCompat
22+
import androidx.lifecycle.Lifecycle
23+
import androidx.lifecycle.LifecycleEventObserver
24+
25+
@Composable
26+
actual fun PermissionBox(
27+
requiredPermissions: List<String>,
28+
title: String,
29+
confirmButtonText: String,
30+
dismissButtonText: String,
31+
description: String?,
32+
onGranted: @Composable (() -> Unit)?
33+
) {
34+
val context = LocalContext.current
35+
val lifecycleOwner = LocalLifecycleOwner.current
36+
37+
var permissionGranted by remember {
38+
mutableStateOf(
39+
requiredPermissions.all {
40+
ContextCompat.checkSelfPermission(
41+
context,
42+
it,
43+
) == PackageManager.PERMISSION_GRANTED
44+
},
45+
)
46+
}
47+
48+
var shouldShowPermissionRationale =
49+
requiredPermissions.all {
50+
(context as? Activity)?.let { it1 ->
51+
ActivityCompat.shouldShowRequestPermissionRationale(
52+
it1, it,
53+
)
54+
} == true
55+
}
56+
57+
var shouldDirectUserToApplicationSettings by remember {
58+
mutableStateOf(false)
59+
}
60+
61+
val decideCurrentPermissionStatus: (Boolean, Boolean) -> String =
62+
{ granted, rationale ->
63+
if (granted) {
64+
"Granted"
65+
} else if (rationale) {
66+
"Rejected"
67+
} else {
68+
"Denied"
69+
}
70+
}
71+
72+
var currentPermissionStatus by remember {
73+
mutableStateOf(
74+
decideCurrentPermissionStatus(
75+
permissionGranted,
76+
shouldShowPermissionRationale,
77+
),
78+
)
79+
}
80+
81+
val multiplePermissionLauncher = rememberLauncherForActivityResult(
82+
contract = ActivityResultContracts.RequestMultiplePermissions(),
83+
onResult = { permissionResults ->
84+
val isGranted =
85+
requiredPermissions.all { permissionResults[it] == true }
86+
87+
permissionGranted = isGranted
88+
89+
if (!isGranted) {
90+
shouldShowPermissionRationale =
91+
requiredPermissions.all {
92+
(context as? Activity)?.let { it1 ->
93+
ActivityCompat.shouldShowRequestPermissionRationale(
94+
it1, it,
95+
)
96+
} == false
97+
}
98+
}
99+
shouldDirectUserToApplicationSettings =
100+
!shouldShowPermissionRationale && !permissionGranted
101+
currentPermissionStatus = decideCurrentPermissionStatus(
102+
permissionGranted,
103+
shouldShowPermissionRationale,
104+
)
105+
},
106+
)
107+
108+
DisposableEffect(
109+
key1 = lifecycleOwner,
110+
effect = {
111+
val observer = LifecycleEventObserver { _, event ->
112+
if (event == Lifecycle.Event.ON_START &&
113+
!permissionGranted &&
114+
!shouldShowPermissionRationale
115+
) {
116+
multiplePermissionLauncher.launch(requiredPermissions.toTypedArray())
117+
}
118+
}
119+
lifecycleOwner.lifecycle.addObserver(observer)
120+
onDispose {
121+
lifecycleOwner.lifecycle.removeObserver(observer)
122+
}
123+
},
124+
)
125+
126+
if (shouldShowPermissionRationale) {
127+
MifosDialogBox(
128+
showDialogState = true,
129+
onDismiss = { shouldShowPermissionRationale = false },
130+
title = title,
131+
message = description,
132+
confirmButtonText = confirmButtonText,
133+
onConfirm = {
134+
shouldShowPermissionRationale = false
135+
multiplePermissionLauncher.launch(requiredPermissions.toTypedArray())
136+
},
137+
dismissButtonText = dismissButtonText,
138+
)
139+
}
140+
141+
142+
if (shouldDirectUserToApplicationSettings) {
143+
Intent(
144+
Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
145+
Uri.fromParts("package", context.packageName, null),
146+
).also {
147+
context.startActivity(it)
148+
}
149+
}
150+
151+
if (permissionGranted) {
152+
onGranted?.invoke()
153+
}
154+
}
155+
156+
actual fun getRequiredPermissionsForExport(): List<String> {
157+
return if (Build.VERSION.SDK_INT >= 33) {
158+
listOf(Manifest.permission.READ_MEDIA_IMAGES)
159+
} else {
160+
listOf(
161+
Manifest.permission.READ_EXTERNAL_STORAGE,
162+
Manifest.permission.WRITE_EXTERNAL_STORAGE,
163+
)
164+
}
165+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.mifos.core.designsystem.component
2+
3+
import androidx.compose.runtime.Composable
4+
5+
@Composable
6+
expect fun PermissionBox(
7+
requiredPermissions: List<String>,
8+
title: String,
9+
confirmButtonText: String,
10+
dismissButtonText: String,
11+
description: String? = null,
12+
onGranted: @Composable (() -> Unit)? = null,
13+
)
14+
15+
expect fun getRequiredPermissionsForExport(): List<String>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.mifos.core.designsystem.component
2+
3+
import androidx.compose.runtime.Composable
4+
5+
@Composable
6+
actual fun PermissionBox(
7+
requiredPermissions: List<String>,
8+
title: String,
9+
confirmButtonText: String,
10+
dismissButtonText: String,
11+
description: String?,
12+
onGranted: @Composable (() -> Unit)?
13+
) {
14+
TODO("Not yet implemented")
15+
}
16+
17+
actual fun getRequiredPermissionsForExport(): List<String> {
18+
TODO("Not yet implemented")
19+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.mifos.core.designsystem.component
2+
3+
import androidx.compose.runtime.Composable
4+
5+
@Composable
6+
actual fun PermissionBox(
7+
requiredPermissions: List<String>,
8+
title: String,
9+
confirmButtonText: String,
10+
dismissButtonText: String,
11+
description: String?,
12+
onGranted: @Composable (() -> Unit)?
13+
) {
14+
TODO("Not yet implemented")
15+
}
16+
17+
actual fun getRequiredPermissionsForExport(): List<String> {
18+
TODO("Not yet implemented")
19+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package com.mifos.feature.report.reportDetail
2+
3+
import android.os.Environment
4+
import co.touchlab.kermit.Logger
5+
import com.mifos.core.model.objects.runreport.FullParameterListResponse
6+
import okio.FileSystem
7+
import okio.Path.Companion.toPath
8+
import okio.buffer
9+
import java.io.File
10+
11+
actual fun getFileHelper(reportName: String): FileHelper= AndroidFileHelper(reportName)
12+
13+
class AndroidFileHelper(private val reportName: String) : FileHelper {
14+
override suspend fun exportCsv(report: FullParameterListResponse): Boolean {
15+
return try {
16+
val timestamp = System.currentTimeMillis()
17+
val fileName = "$reportName-$timestamp.csv"
18+
19+
val downloadsDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
20+
val exportFolder = File(downloadsDir, "MifosReports") // Optional: subfolder
21+
22+
if (!exportFolder.exists()) {
23+
exportFolder.mkdirs()
24+
}
25+
26+
val filePath = File(exportFolder, fileName).absolutePath.toPath()
27+
28+
FileSystem.SYSTEM.sink(filePath).buffer().use { sink ->
29+
val headers = report.columnHeaders.joinToString(",") { it.columnName }
30+
sink.writeUtf8("$headers\n")
31+
report.data.forEach { row ->
32+
val line = row.row.joinToString(",")
33+
sink.writeUtf8("$line\n")
34+
}
35+
}
36+
true
37+
} catch (e: Exception) {
38+
Logger.e("Revanth"){
39+
e.toString()
40+
}
41+
false
42+
}
43+
}
44+
}

feature/report/src/commonMain/kotlin/com/mifos/feature/report/report/ReportScreen.kt

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ import androidx.compose.ui.unit.dp
4242
import androidx.lifecycle.compose.collectAsStateWithLifecycle
4343
import androidx.lifecycle.viewmodel.compose.viewModel
4444
import com.mifos.core.designsystem.component.MifosScaffold
45+
import com.mifos.core.designsystem.component.PermissionBox
46+
import com.mifos.core.designsystem.component.getRequiredPermissionsForExport
4547
import com.mifos.core.designsystem.icon.MifosIcons
4648
import com.mifos.core.model.objects.runreport.FullParameterListResponse
4749
import com.mifos.feature.report.reportDetail.ReportUiState
@@ -97,27 +99,20 @@ import org.jetbrains.compose.ui.tooling.preview.PreviewParameterProvider
9799
}
98100

99101
if (checkPermission) {
100-
// PermissionBox(
101-
// requiredPermissions = if (Build.VERSION.SDK_INT >= 33) {
102-
// listOf(Manifest.permission.READ_MEDIA_IMAGES)
103-
// } else {
104-
// listOf(
105-
// Manifest.permission.READ_EXTERNAL_STORAGE,
106-
// Manifest.permission.WRITE_EXTERNAL_STORAGE,
107-
// )
108-
// },
109-
// title = Res.string.feature_report_permission_required,
110-
// description = Res.string.feature_report_external_approve_permission_description,
111-
// confirmButtonText = Res.string.feature_report_proceed,
112-
// dismissButtonText = Res.string.feature_report_dismiss,
113-
// onGranted = {
114-
// LaunchedEffect(key1 = Unit) {
115-
// scope.launch {
116-
// exportReport()
117-
// }
118-
// }
119-
// },
120-
// )
102+
PermissionBox(
103+
requiredPermissions = getRequiredPermissionsForExport(),
104+
title = stringResource(Res.string.feature_report_permission_required),
105+
description = stringResource(Res.string.feature_report_external_approve_permission_description),
106+
confirmButtonText = stringResource(Res.string.feature_report_proceed),
107+
dismissButtonText = stringResource(Res.string.feature_report_dismiss),
108+
onGranted = {
109+
LaunchedEffect(key1 = Unit) {
110+
scope.launch {
111+
exportReport()
112+
}
113+
}
114+
},
115+
)
121116
}
122117

123118
MifosScaffold(
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.mifos.feature.report.reportDetail
2+
3+
import com.mifos.core.model.objects.runreport.FullParameterListResponse
4+
5+
interface FileHelper {
6+
suspend fun exportCsv(report: FullParameterListResponse): Boolean
7+
}
8+
9+
expect fun getFileHelper(reportName: String): FileHelper

feature/report/src/commonMain/kotlin/com/mifos/feature/report/reportDetail/ReportDetailScreen.kt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ internal fun ReportDetailScreen(
9393
val state by viewModel.reportDetailUiState.collectAsStateWithLifecycle()
9494
val reportParameterList by viewModel.reportParameterList.collectAsStateWithLifecycle()
9595
val reportDetail by viewModel.reportDetail.collectAsStateWithLifecycle()
96+
val reportUiState by viewModel.reportUiState.collectAsStateWithLifecycle()
9697
val reportOffices by viewModel.reportOffices.collectAsStateWithLifecycle()
9798
val reportProducts by viewModel.reportProducts.collectAsStateWithLifecycle()
9899
val runReportDetail by viewModel.runReport.collectAsStateWithLifecycle()
@@ -188,10 +189,12 @@ internal fun ReportDetailScreen(
188189

189190
if(showReportScreen){
190191
ReportScreen(
191-
state = ReportUiState.Initial,
192+
state = reportUiState,
192193
report = runReportDetail!!,
193194
onBackPressed = onBackPressed,
194-
exportReport = {}
195+
exportReport = {
196+
viewModel.exportCsv(runReportDetail!!)
197+
}
195198
)
196199
}
197200
else{

0 commit comments

Comments
 (0)