Skip to content

Commit cbc96b0

Browse files
committed
[Android] Fix WidgetUIViewModelTest and remove few context dependencies
Closes #10466
1 parent bc71c64 commit cbc96b0

File tree

5 files changed

+134
-107
lines changed

5 files changed

+134
-107
lines changed

app-android/calendar/src/main/java/de/tutao/calendar/widget/Agenda.kt

Lines changed: 26 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import androidx.glance.layout.padding
2929
import androidx.glance.preview.ExperimentalGlancePreviewApi
3030
import androidx.glance.preview.Preview
3131
import androidx.glance.state.GlanceStateDefinition
32+
import de.tutao.calendar.R
3233
import de.tutao.calendar.widget.component.ErrorBody
3334
import de.tutao.calendar.widget.component.LoadingSpinner
3435
import de.tutao.calendar.widget.component.ScrollableDaysList
@@ -38,6 +39,7 @@ import de.tutao.calendar.widget.data.WidgetUIData
3839
import de.tutao.calendar.widget.error.WidgetError
3940
import de.tutao.calendar.widget.error.WidgetErrorHandler
4041
import de.tutao.calendar.widget.error.WidgetErrorType
42+
import de.tutao.calendar.widget.model.BirthdayStrings
4143
import de.tutao.calendar.widget.model.WidgetUIViewModel
4244
import de.tutao.calendar.widget.model.openCalendarAgenda
4345
import de.tutao.calendar.widget.style.AppTheme
@@ -94,7 +96,9 @@ class Agenda : GlanceAppWidget() {
9496
LaunchedEffect(
9597
preferences[settingsPreferencesKey], preferences[lastSyncPreferencesKey]
9698
) {
97-
widgetUIViewModel.loadUIState(context, LocalDateTime.now())
99+
widgetUIViewModel.loadUIState(
100+
context.widgetDataStore, context.widgetCacheDataStore, LocalDateTime.now()
101+
)
98102
}
99103

100104
GlanceTheme(
@@ -118,8 +122,7 @@ class Agenda : GlanceAppWidget() {
118122
}
119123

120124
private suspend fun setupWidget(
121-
context: Context,
122-
appWidgetId: Int
125+
context: Context, appWidgetId: Int
123126
): Pair<WidgetUIViewModel, String?> {
124127
val db = AppDatabase.getDatabase(context, true)
125128
val remoteStorage = RemoteStorage(db)
@@ -133,15 +136,19 @@ class Agenda : GlanceAppWidget() {
133136
null
134137
}
135138

136-
val widgetUIViewModel =
137-
WidgetUIViewModel(
138-
context.widgetDataRepository,
139-
appWidgetId,
140-
nativeCredentialsFacade,
141-
crypto,
142-
sdk,
143-
Calendar.getInstance()
144-
)
139+
val birthdayStrings = BirthdayStrings(
140+
context.getString(R.string.birthdayEvent_title), context.getString(R.string.birthdayEventAge_title)
141+
)
142+
143+
val widgetUIViewModel = WidgetUIViewModel(
144+
context.widgetDataRepository,
145+
appWidgetId,
146+
nativeCredentialsFacade,
147+
crypto,
148+
sdk,
149+
Calendar.getInstance(),
150+
birthdayStrings
151+
)
145152
val userId = widgetUIViewModel.getLoggedInUser(context)
146153

147154
return Pair(widgetUIViewModel, userId)
@@ -155,11 +162,7 @@ class Agenda : GlanceAppWidget() {
155162
start = Dimensions.Spacing.LG.dp,
156163
end = Dimensions.Spacing.LG.dp,
157164
bottom = 0.dp
158-
)
159-
.background(GlanceTheme.colors.background)
160-
.fillMaxSize()
161-
.appWidgetBackground()
162-
.cornerRadius(20.dp),
165+
).background(GlanceTheme.colors.background).fillMaxSize().appWidgetBackground().cornerRadius(20.dp),
163166
) {
164167
if (data == null) { //
165168
return@Column LoadingSpinner()
@@ -286,8 +289,7 @@ class Agenda : GlanceAppWidget() {
286289
"00:00",
287290
isAllDay = true,
288291
startTimestamp = startOfTomorrow
289-
),
290-
UIEvent(
292+
), UIEvent(
291293
"previewCalendar",
292294
IdTupleCustom("", ""),
293295
"2196f3",
@@ -312,8 +314,7 @@ class Agenda : GlanceAppWidget() {
312314
"17:00",
313315
isAllDay = false,
314316
startTimestamp = afterTomorrow.toEpochMilli()
315-
),
316-
UIEvent(
317+
), UIEvent(
317318
"previewCalendar",
318319
IdTupleCustom("", ""),
319320
"2196f3",
@@ -372,8 +373,7 @@ class Agenda : GlanceAppWidget() {
372373
"17:00",
373374
isAllDay = false,
374375
startTimestamp = tomorrow.toEpochMilli()
375-
),
376-
UIEvent(
376+
), UIEvent(
377377
"previewCalendar",
378378
IdTupleCustom("", ""),
379379
"2196f3",
@@ -398,8 +398,7 @@ class Agenda : GlanceAppWidget() {
398398
"17:00",
399399
isAllDay = false,
400400
startTimestamp = afterTomorrow.toEpochMilli()
401-
),
402-
UIEvent(
401+
), UIEvent(
403402
"previewCalendar",
404403
IdTupleCustom("", ""),
405404
"2196f3",
@@ -448,8 +447,7 @@ class Agenda : GlanceAppWidget() {
448447
"17:00",
449448
isAllDay = false,
450449
startTimestamp = tomorrow.toEpochMilli()
451-
),
452-
UIEvent(
450+
), UIEvent(
453451
"previewCalendar",
454452
IdTupleCustom("", ""),
455453
"2196f3",
@@ -474,8 +472,7 @@ class Agenda : GlanceAppWidget() {
474472
"17:00",
475473
isAllDay = false,
476474
startTimestamp = afterTomorrow.toEpochMilli()
477-
),
478-
UIEvent(
475+
), UIEvent(
479476
"previewCalendar",
480477
IdTupleCustom("", ""),
481478
"2196f3",

app-android/calendar/src/main/java/de/tutao/calendar/widget/data/WidgetRepository.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import androidx.glance.appwidget.state.updateAppWidgetState
1111
import de.tutao.calendar.widget.WIDGET_CACHE_DATE_PREFIX
1212
import de.tutao.calendar.widget.WIDGET_LAST_SYNC_PREFIX
1313
import de.tutao.calendar.widget.WIDGET_SETTINGS_PREFIX
14-
import de.tutao.calendar.widget.widgetDataStore
1514
import de.tutao.tutasdk.CalendarRenderData
1615
import de.tutao.tutasdk.GeneratedId
1716
import de.tutao.tutasdk.LoggedInSdk
@@ -36,12 +35,12 @@ abstract class WidgetRepository() {
3635
throw NotImplementedError()
3736
}
3837

39-
suspend fun storeSettings(context: Context, widgetId: Int, settings: SettingsDao) {
38+
suspend fun storeSettings(widgetDataStore: DataStore<Preferences>, widgetId: Int, settings: SettingsDao) {
4039
val databaseWidgetIdentifier = "${WIDGET_SETTINGS_PREFIX}_$widgetId"
4140
val preferencesKey = stringPreferencesKey(databaseWidgetIdentifier)
4241
val serializedSettings = json.encodeToString(settings)
4342

44-
context.widgetDataStore.edit { preferences ->
43+
widgetDataStore.edit { preferences ->
4544
preferences[preferencesKey] = serializedSettings
4645
}
4746
}

app-android/calendar/src/main/java/de/tutao/calendar/widget/model/WidgetConfigViewModel.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ class WidgetConfigViewModel(
167167
try {
168168
repository.storeLastSyncInBatch(context, intArrayOf(widgetId), Date())
169169
repository.storeSettings(
170-
context,
170+
context.widgetDataStore,
171171
widgetId,
172172
SettingsDao(
173173
calendars = _selectedCalendars.value,

app-android/calendar/src/main/java/de/tutao/calendar/widget/model/WidgetUIViewModel.kt

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@ package de.tutao.calendar.widget.model
33
import android.content.Context
44
import android.content.Intent
55
import android.util.Log
6+
import androidx.datastore.core.DataStore
67
import androidx.datastore.core.IOException
8+
import androidx.datastore.preferences.core.Preferences
79
import androidx.glance.action.Action
810
import androidx.glance.appwidget.action.actionStartActivity
911
import androidx.lifecycle.ViewModel
1012
import de.tutao.calendar.MainActivity
11-
import de.tutao.calendar.R
1213
import de.tutao.calendar.widget.WidgetUpdateTrigger
1314
import de.tutao.calendar.widget.data.BirthdayEventDao
1415
import de.tutao.calendar.widget.data.LastSyncDao
@@ -18,7 +19,6 @@ import de.tutao.calendar.widget.data.WidgetRepository
1819
import de.tutao.calendar.widget.data.WidgetUIData
1920
import de.tutao.calendar.widget.error.WidgetError
2021
import de.tutao.calendar.widget.error.WidgetErrorType
21-
import de.tutao.calendar.widget.widgetCacheDataStore
2222
import de.tutao.calendar.widget.widgetDataStore
2323
import de.tutao.tutasdk.LoginException
2424
import de.tutao.tutasdk.Sdk
@@ -50,7 +50,8 @@ class WidgetUIViewModel(
5050
private val credentialsFacade: NativeCredentialsFacade,
5151
private val cryptoFacade: AndroidNativeCryptoFacade,
5252
private val sdk: Sdk?,
53-
private val calendar: Calendar
53+
private val calendar: Calendar,
54+
private val birthdayStrings: BirthdayStrings
5455
) : ViewModel() {
5556
private val _uiState = MutableStateFlow<WidgetUIData?>(null)
5657
val uiState: StateFlow<WidgetUIData?> = _uiState.asStateFlow()
@@ -62,7 +63,11 @@ class WidgetUIViewModel(
6263
private const val TAG = "WidgetUIViewModel"
6364
}
6465

65-
suspend fun loadUIState(context: Context, now: LocalDateTime): WidgetUIData? {
66+
suspend fun loadUIState(
67+
widgetDataStore: DataStore<Preferences>,
68+
widgetCacheDataStore: DataStore<Preferences>,
69+
now: LocalDateTime
70+
): WidgetUIData? {
6671
Log.i(TAG, "Init loadUIState")
6772
val allDayEvents: HashMap<Long, List<UIEvent>> = HashMap()
6873
val normalEvents: HashMap<Long, List<UIEvent>> = HashMap()
@@ -80,18 +85,18 @@ class WidgetUIViewModel(
8085
val calendars: List<String>
8186

8287
try {
83-
settings = repository.loadSettings(context.widgetDataStore, widgetId) ?: return WidgetUIData(
88+
settings = repository.loadSettings(widgetDataStore, widgetId) ?: return WidgetUIData(
8489
normalEvents,
8590
allDayEvents
8691
)
8792
Log.i(TAG, "Widget settings has ${settings.calendars.values.size} calendars")
8893
settings.calendars.entries.forEach { (calendarId, calendar) ->
8994
Log.d(TAG, "$calendarId - ${calendar.name}")
9095
}
91-
lastSync = repository.loadLastSync(context.widgetDataStore, widgetId)
96+
lastSync = repository.loadLastSync(widgetDataStore, widgetId)
9297
Log.i(TAG, "Widget last sync at $lastSync")
9398

94-
sdk?.let { sdk -> loadCalendars(context, sdk, settings) }
99+
sdk?.let { sdk -> loadCalendars(widgetDataStore, sdk, settings) }
95100
calendars = settings.calendars.keys.toList()
96101
} catch (e: Exception) {
97102
// We couldn't load widget settings, so we must show an error to User
@@ -128,7 +133,7 @@ class WidgetUIViewModel(
128133
val loggedInSdk = this.sdk.login(credentials.toSdkCredentials())
129134

130135
repository.loadEvents(
131-
context.widgetCacheDataStore,
136+
widgetCacheDataStore,
132137
widgetId,
133138
settings.userId,
134139
calendars,
@@ -144,7 +149,7 @@ class WidgetUIViewModel(
144149
"Missing credentials for user ${settings.userId} when trying to load widget content}", e
145150
)
146151
repository.loadEventsFromCache(
147-
context.widgetCacheDataStore,
152+
widgetCacheDataStore,
148153
widgetId,
149154
calendars,
150155
credentials,
@@ -153,7 +158,7 @@ class WidgetUIViewModel(
153158
} catch (e: Exception) {
154159
Log.e(TAG, "Unknown exception occurred", e)
155160
repository.loadEventsFromCache(
156-
context.widgetCacheDataStore,
161+
widgetCacheDataStore,
157162
widgetId,
158163
calendars,
159164
credentials,
@@ -162,7 +167,7 @@ class WidgetUIViewModel(
162167
}
163168
} else {
164169
repository.loadEventsFromCache(
165-
context.widgetCacheDataStore,
170+
widgetCacheDataStore,
166171
widgetId,
167172
calendars,
168173
credentials,
@@ -244,7 +249,7 @@ class WidgetUIViewModel(
244249
calendarId,
245250
it.eventDao.id,
246251
calendarColor = settings.calendars[calendarId]?.color ?: "2196f3",
247-
summary = buildBirthdayEventTitle(it, context),
252+
summary = buildBirthdayEventTitle(it),
248253
start.format(formatter),
249254
end.format(formatter),
250255
isAllDay = true,
@@ -288,15 +293,15 @@ class WidgetUIViewModel(
288293
return uiState.value
289294
}
290295

291-
private suspend fun loadCalendars(context: Context, sdk: Sdk, settings: SettingsDao) {
296+
private suspend fun loadCalendars(widgetDataStore: DataStore<Preferences>, sdk: Sdk, settings: SettingsDao) {
292297
try {
293298
Log.i(TAG, "Fetching new calendar data from server")
294299
val loadedCalendars = repository.loadCalendars(settings.userId, credentialsFacade, sdk)
295300
Log.i(TAG, "Successfully fetched ${loadedCalendars.size} calendars")
296301
for (key in loadedCalendars.keys) {
297302
settings.calendars[key]?.color = loadedCalendars[key]?.color ?: continue
298303
}
299-
repository.storeSettings(context, widgetId, settings)
304+
repository.storeSettings(widgetDataStore, widgetId, settings)
300305
Log.i(TAG, "Cached calendar data updated successfully!")
301306
} catch (e: LoginException.ApiCall) {
302307
// Failed to login into SDK, probably because of connection issues
@@ -310,12 +315,12 @@ class WidgetUIViewModel(
310315
}
311316
}
312317

313-
private fun buildBirthdayEventTitle(event: BirthdayEventDao, context: Context): String {
318+
private fun buildBirthdayEventTitle(event: BirthdayEventDao): String {
314319
if (event.contact.age == null) {
315-
return context.getString(R.string.birthdayEvent_title).replace("{name}", event.contact.name)
320+
return birthdayStrings.birthdayTitleTemplate.replace("{name}", event.contact.name)
316321
}
317322

318-
val age = context.getString(R.string.birthdayEventAge_title).replace(
323+
val age = birthdayStrings.birthdayAgeTemplate.replace(
319324
"{age}",
320325
event.contact.age.toString()
321326
)
@@ -371,4 +376,9 @@ fun openCalendarAgenda(
371376
}
372377

373378
return actionStartActivity(openCalendarAgenda)
374-
}
379+
}
380+
381+
data class BirthdayStrings(
382+
val birthdayTitleTemplate: String,
383+
val birthdayAgeTemplate: String
384+
)

0 commit comments

Comments
 (0)