Skip to content
This repository has been archived by the owner on Nov 5, 2024. It is now read-only.

Commit

Permalink
Merge pull request #1013 from mhss1/develop
Browse files Browse the repository at this point in the history
Added Wallet balance Widget
  • Loading branch information
ILIYANGERMANOV authored Jun 10, 2022
2 parents 9ec8a14 + 56a278a commit 9a36e93
Show file tree
Hide file tree
Showing 20 changed files with 444 additions and 2 deletions.
13 changes: 13 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,19 @@
android:name="android.appwidget.provider"
android:resource="@xml/add_transaction_widget_compact_info" />
</receiver>

<receiver
android:name=".ui.widget.WalletBalanceReceiver"
android:enabled="@bool/glance_appwidget_available"
android:label="@string/wallet_balance"
android:exported="true">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/wallet_balance_widget_info" />
</receiver>
</application>

</manifest>
20 changes: 20 additions & 0 deletions app/src/main/java/com/ivy/wallet/IvyAndroidApp.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ package com.ivy.wallet

import android.annotation.SuppressLint
import android.app.Application
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import androidx.annotation.StringRes
import androidx.hilt.work.HiltWorkerFactory
import androidx.work.Configuration
Expand Down Expand Up @@ -47,4 +51,20 @@ fun stringRes(
): String {
//I don't want strings.xml to handle something different than String at this point
return IvyAndroidApp.appContext.getString(id, *args)
}

fun refreshWidget(widgetReceiver: Class<out AppWidgetProvider>) {
val updateIntent = Intent(IvyAndroidApp.appContext, widgetReceiver)
updateIntent.action = AppWidgetManager.ACTION_APPWIDGET_UPDATE

val widgetManager = AppWidgetManager.getInstance(IvyAndroidApp.appContext)
val ids = widgetManager.getAppWidgetIds(
ComponentName(
IvyAndroidApp.appContext,
widgetReceiver
)
)
updateIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids)

IvyAndroidApp.appContext.sendBroadcast(updateIntent)
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@ import com.ivy.wallet.domain.deprecated.sync.uploader.TransactionUploader
import com.ivy.wallet.domain.event.AccountsUpdatedEvent
import com.ivy.wallet.io.persistence.SharedPrefs
import com.ivy.wallet.io.persistence.dao.*
import com.ivy.wallet.refreshWidget
import com.ivy.wallet.ui.EditTransaction
import com.ivy.wallet.ui.IvyWalletCtx
import com.ivy.wallet.ui.Main
import com.ivy.wallet.ui.loan.data.EditTransactionDisplayLoan
import com.ivy.wallet.ui.widget.WalletBalanceReceiver
import com.ivy.wallet.utils.*
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
Expand Down Expand Up @@ -536,6 +538,7 @@ class EditTransactionViewModel @Inject constructor(
}

transactionDao.save(loadedTransaction().toEntity())
refreshWidget(WalletBalanceReceiver::class.java)
}

if (closeScreen) {
Expand Down
97 changes: 97 additions & 0 deletions app/src/main/java/com/ivy/wallet/ui/widget/WalletBalanceWidget.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package com.ivy.wallet.ui.widget

import android.appwidget.AppWidgetManager
import android.content.Context
import androidx.compose.runtime.Composable
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.glance.appwidget.GlanceAppWidget
import androidx.glance.appwidget.GlanceAppWidgetManager
import androidx.glance.appwidget.GlanceAppWidgetReceiver
import androidx.glance.appwidget.state.updateAppWidgetState
import androidx.glance.currentState
import androidx.glance.state.PreferencesGlanceStateDefinition
import com.ivy.wallet.domain.action.account.AccountsAct
import com.ivy.wallet.domain.action.settings.SettingsAct
import com.ivy.wallet.domain.action.wallet.CalcIncomeExpenseAct
import com.ivy.wallet.domain.action.wallet.CalcWalletBalanceAct
import com.ivy.wallet.ui.IvyWalletCtx
import com.ivy.wallet.ui.onboarding.model.toCloseTimeRange
import com.ivy.wallet.utils.shortenAmount
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.launch
import javax.inject.Inject

class WalletBalanceWidget: GlanceAppWidget() {

@Composable
override fun Content() {
val prefs = currentState<Preferences>()
val balance = prefs[stringPreferencesKey("balance")] ?: "0.00"
val currency = prefs[stringPreferencesKey("currency")] ?: "USD"
val income = prefs[stringPreferencesKey("income")] ?: "0.00"
val expense = prefs[stringPreferencesKey("expense")] ?: "0.00"

WalletBalanceWidgetContent(balance, currency, income, expense)
}

}

@AndroidEntryPoint
class WalletBalanceReceiver : GlanceAppWidgetReceiver() {

override val glanceAppWidget: GlanceAppWidget = WalletBalanceWidget()
private val coroutineScope = MainScope()

@Inject
lateinit var walletBalanceAct: CalcWalletBalanceAct
@Inject
lateinit var settingsAct: SettingsAct
@Inject
lateinit var accountsAct: AccountsAct
@Inject
lateinit var calcIncomeExpenseAct: CalcIncomeExpenseAct
@Inject
lateinit var ivyContext: IvyWalletCtx

override fun onUpdate(
context: Context,
appWidgetManager: AppWidgetManager,
appWidgetIds: IntArray
) {
super.onUpdate(context, appWidgetManager, appWidgetIds)
updateData(context)
}

private fun updateData(context: Context) {
coroutineScope.launch {
val settings = settingsAct(Unit)
val currency = settings.baseCurrency
val balance = walletBalanceAct(CalcWalletBalanceAct.Input(baseCurrency = currency))
val accounts = accountsAct(Unit)
val period = ivyContext.selectedPeriod
val incomeExpense = calcIncomeExpenseAct(
CalcIncomeExpenseAct.Input(
baseCurrency = settings.baseCurrency,
accounts = accounts,
range = period.toRange(ivyContext.startDayOfMonth).toCloseTimeRange()
)
)

val glanceId =
GlanceAppWidgetManager(context).getGlanceIds(WalletBalanceWidget::class.java).firstOrNull()
glanceId?.let {
updateAppWidgetState(context, PreferencesGlanceStateDefinition, it) { pref ->
pref.toMutablePreferences().apply {
this[stringPreferencesKey("balance")] = shortenAmount(balance.toDouble())
this[stringPreferencesKey("currency")] = currency
this[stringPreferencesKey("income")] = shortenAmount(incomeExpense.income.toDouble())
this[stringPreferencesKey("expense")] = shortenAmount(incomeExpense.expense.toDouble())
}
}
glanceAppWidget.update(context, it)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.ivy.wallet.ui.widget

import android.content.Context
import android.content.Intent
import androidx.glance.GlanceId
import androidx.glance.action.ActionParameters
import androidx.glance.appwidget.action.ActionCallback
import com.ivy.wallet.domain.data.TransactionType
import com.ivy.wallet.ui.RootActivity

class WalletBalanceButtonsAction : ActionCallback {
override suspend fun onRun(context: Context, glanceId: GlanceId, parameters: ActionParameters) {
when (parameters[walletBtnActParam]) {
AddTransactionWidgetClick.ACTION_ADD_INCOME -> {
context.startActivity(
RootActivity.addTransactionStart(
context = context,
type = TransactionType.INCOME
).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
)
}
AddTransactionWidgetClick.ACTION_ADD_EXPENSE -> {
context.startActivity(
RootActivity.addTransactionStart(
context = context,
type = TransactionType.EXPENSE
).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
)
}
AddTransactionWidgetClick.ACTION_ADD_TRANSFER -> {
context.startActivity(
RootActivity.addTransactionStart(
context = context,
type = TransactionType.TRANSFER
).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
)
}
else -> return
}
}
}

class WalletBalanceWidgetClickAction: ActionCallback {
override suspend fun onRun(context: Context, glanceId: GlanceId, parameters: ActionParameters) {
context.startActivity(
RootActivity.getIntent(
context = context
).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
)
}
}

val walletBtnActParam = ActionParameters.Key<String>("wallet_balance_button_action")
Loading

0 comments on commit 9a36e93

Please sign in to comment.