Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions androidApp/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

<activity
android:exported="true"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustResize"
android:name=".MainActivity">
<intent-filter>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ data class ScheduledPaymentDetailsRoute(val paymentId: String) : NavKey
data class TransactionDetailsRoute(val transactionId: String) : NavKey

@Serializable
data class FinancialActionRoute(val tile: String, val body: String, val payload: Map<String, String>) : NavKey
data class FinancialActionRoute(val tile: String, val body: String, val actionId: String) : NavKey

@Serializable
data object TopSpendingCategoriesRoute : NavKey
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,23 @@ import androidx.navigation3.scene.DialogSceneStrategy
import com.spendoo.categories.api.AddTransactionRoute
import com.spendoo.categories.api.CategoriesFeatureApi
import com.spendoo.categories.api.CategoriesRoute
import com.spendoo.categories.api.CategoryOffersRoute
import com.spendoo.categories.api.EditTransactionRoute
import com.spendoo.categories.api.FinancialActionRoute
import com.spendoo.categories.api.ScheduledPaymentDetailsRoute
import com.spendoo.categories.api.ScheduledPaymentsRoute
import com.spendoo.categories.api.TopSpendingCategoriesRoute
import com.spendoo.categories.api.TransactionDetailsRoute
import com.spendoo.categories.presentation.screen.addTransactionBottomSheet.AddTransactionBottomSheet
import com.spendoo.categories.presentation.screen.categories.CategoriesScreen
import com.spendoo.categories.presentation.screen.categoryOffers.CategoryOffersScreen
import com.spendoo.categories.presentation.screen.editTransactionBottomSheet.EditTransactionBottomSheet
import com.spendoo.categories.presentation.screen.financialActionScreen.FinancialActionScreen
import com.spendoo.categories.presentation.screen.scheduledPaymentDetails.ScheduledPaymentDetailsScreen
import com.spendoo.categories.presentation.screen.scheduledPayments.ScheduledPaymentsScreen
import com.spendoo.categories.presentation.screen.transactionDetails.TransactionDetailsScreen
import com.spendoo.categories.presentation.screen.topSpendingCategories.TopSpendingCategoriesScreen
import com.spendoo.categories.presentation.screen.categoryOffers.CategoryOffersScreen
import com.spendoo.categories.presentation.screen.editTransactionBottomSheet.EditTransactionBottomSheet
import com.spendoo.categories.api.TopSpendingCategoriesRoute
import com.spendoo.categories.api.CategoryOffersRoute
import com.spendoo.categories.api.EditTransactionRoute
import com.spendoo.categories.presentation.screen.transactionDetails.TransactionDetailsScreen

class CategoriesFeatureApiImpl : CategoriesFeatureApi {

override fun invoke(): (NavKey) -> NavEntry<NavKey> {
Expand All @@ -44,7 +45,7 @@ class CategoriesFeatureApiImpl : CategoriesFeatureApi {
FinancialActionScreen(
tile = route.tile,
body = route.body,
payload = route.payload
actionId = route.actionId
)
}
entry<TopSpendingCategoriesRoute> { TopSpendingCategoriesScreen() }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ import spendoo.designsystem.generated.resources.ok
fun FinancialActionScreen(
tile: String,
body: String,
payload: Map<String, String>,
actionId: String,
viewModel: FinancialActionViewModel =
koinViewModel(parameters = { parametersOf(tile, body, payload) })
koinViewModel(parameters = { parametersOf(tile, body, actionId) })
) {
val state by viewModel.state.collectAsStateWithLifecycle()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ import com.spendoo.designsystem.components.button.AppButtonState
data class FinancialActionUiState(
val tile: String = "",
val body: String = "",
val payload: Map<String, String> = emptyMap(),
val actionId: String = "",
val buttonState: AppButtonState = AppButtonState.Enabled
)
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import spendoo.designsystem.generated.resources.unknown_error
class FinancialActionViewModel(
private val navTile: String,
private val navBody: String,
private val navPayload: Map<String, String>,
private val navActionId: String,
private val budgetActionRepository: BudgetActionRepository
) : BaseViewModel<FinancialActionUiState>(FinancialActionUiState()),
FinancialActionInteractionListener {
Expand All @@ -21,7 +21,7 @@ class FinancialActionViewModel(
copy(
tile = navTile,
body = navBody,
payload = navPayload
actionId = navActionId
)
}
}
Expand All @@ -31,7 +31,7 @@ class FinancialActionViewModel(
}

override fun onExecute() {
val actionId = navPayload["actionId"] ?: return
val actionId = state.value.actionId
tryToCall(
onStart = {
updateState { copy(buttonState = AppButtonState.Loading) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,11 @@ enum class NotificationType {
USER_FOLLOW,
PAYMENT_REMINDER,
ALERT,
SYSTEM
SYSTEM;

companion object {
fun fromStringOrDefault(value: String?): NotificationType {
return entries.find { it.name.equals(value, ignoreCase = true) } ?: SYSTEM
}
}
}
70 changes: 63 additions & 7 deletions spendooApp/src/commonMain/kotlin/com/spendoo/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,24 @@ import com.mmk.kmpnotifier.push.PushListener
import com.mmk.kmpnotifier.push.firebase.addPushListener
import com.spendoo.appEntryPoint.EntryPoint
import com.spendoo.categories.api.FinancialActionRoute
import com.spendoo.categories.api.ScheduledPaymentsRoute
import com.spendoo.designsystem.navigation.effector.Effector
import com.spendoo.designsystem.theme.theme.SpendooTheme
import com.spendoo.goals.api.AchievementsRoute
import com.spendoo.goals.api.GoalsRoute
import com.spendoo.home.api.NotificationsRoute
import com.spendoo.identity.api.ProfileRoute
import com.spendoo.identity.domain.repository.AuthenticationRepository
import com.spendoo.identity.domain.repository.SettingsRepository
import com.spendoo.identity.domain.util.AppLanguage
import com.spendoo.identity.domain.util.AppLocalizer
import com.spendoo.identity.domain.util.AppTheme
import com.spendoo.notifications.domain.entity.NotificationType
import com.spendoo.statistics.api.StatisticsRoute
import com.spendoo.util.SetSystemBarsAppearance
import com.spendoo.util.toStringMap
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import org.koin.compose.koinInject

Expand Down Expand Up @@ -61,25 +69,39 @@ fun App(
body: String?,
data: PayloadData
) {
if (data.isEmpty()) {
KMPNotifier.localNotifier.notify {
this.title = title.orEmpty()
this.body = body.orEmpty()
}
} else {
val actionId = data["actionId"] as? String
if (actionId != null) {
coroutineScope.launch(exceptionHandler) {
effector.navigate(
FinancialActionRoute(
tile = title.orEmpty(),
body = body.orEmpty(),
payload = data.toStringMap()
actionId = actionId
),
forceNavigate = true
)
}
} else {
KMPNotifier.localNotifier.notify {
this.title = title.orEmpty()
this.body = body.orEmpty()
this.payloadData = data.toStringMap()
}
}
}
})


NotificationClickState.consumePendingPayload()?.let { data ->
handleNotificationClick(data, coroutineScope, exceptionHandler, effector)
}

coroutineScope.launch {
NotificationClickState.clickFlow.collect { data ->
NotificationClickState.consumePendingPayload()
handleNotificationClick(data, coroutineScope, exceptionHandler, effector)
}
}
}

val languageCode = if (currentLanguage == AppLanguage.DEFAULT) {
Expand All @@ -97,3 +119,37 @@ fun App(
}
)
}

private fun handleNotificationClick(
data: PayloadData,
coroutineScope: CoroutineScope,
exceptionHandler: CoroutineExceptionHandler,
effector: Effector
) {
val actionId = data["actionId"] as? String
coroutineScope.launch(exceptionHandler) {
if (actionId != null) {
effector.navigate(
FinancialActionRoute(
tile = (data["title"] as? String) ?: "Notification",
body = (data["body"] as? String).orEmpty(),
actionId = actionId
),
forceNavigate = true
)
} else {
val type = data["type"] as? String
val notificationType = NotificationType.fromStringOrDefault(type)
effector.navigate(
when (notificationType) {
NotificationType.ACHIEVEMENT -> AchievementsRoute
NotificationType.GOAL -> GoalsRoute
NotificationType.USER_FOLLOW -> ProfileRoute
NotificationType.PAYMENT_REMINDER -> ScheduledPaymentsRoute
NotificationType.ALERT -> StatisticsRoute()
NotificationType.SYSTEM -> NotificationsRoute
}, forceNavigate = true
)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.spendoo

import com.mmk.kmpnotifier.notification.PayloadData
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow

object NotificationClickState {
private var pendingPayload: PayloadData? = null
private val _clickFlow = MutableSharedFlow<PayloadData>(extraBufferCapacity = 1)
val clickFlow = _clickFlow.asSharedFlow()

fun onNotificationClicked(data: PayloadData) {
pendingPayload = data
_clickFlow.tryEmit(data)
}

fun consumePendingPayload(): PayloadData? {
val payload = pendingPayload
pendingPayload = null
return payload
}
}
8 changes: 8 additions & 0 deletions spendooApp/src/commonMain/kotlin/com/spendoo/initKoin.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.spendoo

import com.mmk.kmpnotifier.KMPNotifier
import com.mmk.kmpnotifier.notification.PayloadData
import com.spendoo.di.apiModule
import com.spendoo.di.appModule
import com.spendoo.di.featureModule
Expand All @@ -9,6 +11,12 @@ import org.koin.core.context.startKoin
import org.koin.dsl.KoinAppDeclaration

fun initKoin(config: KoinAppDeclaration? = null) {
KMPNotifier.addListener(object : KMPNotifier.Listener {
override fun onNotificationClicked(data: PayloadData) {
NotificationClickState.onNotificationClicked(data)
}
})

startKoin {
config?.invoke(this)

Expand Down
Loading