Skip to content

Commit

Permalink
135 fix widgets logic (#302)
Browse files Browse the repository at this point in the history
* Improve widget & preview layouts

* Small widget opens current day list page

* Widget logic
  • Loading branch information
phansier authored Oct 24, 2024
1 parent 439cb03 commit a146447
Show file tree
Hide file tree
Showing 14 changed files with 392 additions and 169 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,8 @@ enum class CoffeeType(
// icons from here: https://www.freepik.com/free-vector/list-different-types-coffee_951047.htm
// app logo is here: https://www.flaticon.com/free-icon/coffee-cup_766408
}

data class CoffeeTypeWithCount(
val coffee: CoffeeType,
val count: Int
)
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package ru.beryukhov.coffeegram.data

import androidx.annotation.VisibleForTesting

const val START_ACTIVITY_PATH = "/start-activity"
const val DAY_COFFEE_PATH = "/coffee"

@VisibleForTesting
fun Map<CoffeeType, Int>.withEmpty(): List<Pair<CoffeeType, Int>> {
/**
* Map contains only non-zero values
* This function creates a list with all CoffeeTypes and their counts according to data from the map
*/
fun Map<CoffeeType, Int>.withEmpty(): List<CoffeeTypeWithCount> {
@Suppress("DataClassShouldBeImmutable")
data class MutablePair(val ct: CoffeeType, var count: Int)

Expand All @@ -15,5 +16,5 @@ fun Map<CoffeeType, Int>.withEmpty(): List<Pair<CoffeeType, Int>> {
this.forEach { entry: Map.Entry<CoffeeType, Int> ->
emptyList.filter { it.ct == entry.key }.forEach { it.count = entry.value }
}
return emptyList.map { it.ct to it.count }
return emptyList.map { CoffeeTypeWithCount(it.ct, it.count) }
}
25 changes: 12 additions & 13 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -44,19 +44,18 @@
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />

<!--TODO fix widgets https://github.com/phansier/Coffeegram/issues/135-->
<!-- <receiver-->
<!-- android:name=".widget.WidgetReceiver"-->
<!-- android:enabled="true"-->
<!-- android:exported="false">-->
<!-- <intent-filter>-->
<!-- <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />-->
<!-- </intent-filter>-->

<!-- <meta-data-->
<!-- android:name="android.appwidget.provider"-->
<!-- android:resource="@xml/widget_info" />-->
<!-- </receiver>-->
<receiver
android:name=".widget.WidgetReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>

<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/widget_info" />
</receiver>
</application>

</manifest>
48 changes: 29 additions & 19 deletions app/src/main/java/ru/beryukhov/coffeegram/Application.kt
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package ru.beryukhov.coffeegram

import android.app.Application
import android.util.Log
import androidx.glance.appwidget.updateAll
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import org.koin.android.ext.android.get
import org.koin.android.ext.koin.androidContext
import org.koin.androidx.viewmodel.dsl.viewModel
import org.koin.core.context.startKoin
import org.koin.core.module.dsl.viewModel
import org.koin.dsl.module
import repository.CoffeeRepository
import repository.RoomCoffeeRepository
Expand All @@ -16,6 +20,7 @@ import ru.beryukhov.coffeegram.model.HeavyDaysCoffeesStore
import ru.beryukhov.coffeegram.model.NavigationStore
import ru.beryukhov.coffeegram.model.ThemeState
import ru.beryukhov.coffeegram.model.ThemeStore
import ru.beryukhov.coffeegram.pages.AppWidgetViewModelImpl
import ru.beryukhov.coffeegram.pages.CoffeeListViewModelImpl
import ru.beryukhov.coffeegram.pages.MapPageViewModelImpl
import ru.beryukhov.coffeegram.pages.TablePageViewModelImpl
Expand All @@ -25,24 +30,6 @@ import ru.beryukhov.coffeegram.store_lib.Storage
import ru.beryukhov.coffeegram.widget.FirstGlanceWidget

class Application : Application() {
private val appModule = module {
single<Storage<ThemeState>> {
// ThemeSharedPrefStorage(context = context)
// ThemeDataStorePrefStorage(context = context)
ThemeDataStoreProtoStorage(context = get())
}
single {
ThemeStore(get())
}
single<CoffeeRepository> { RoomCoffeeRepository(get()) }
single<CoffeeStorage> { CoffeeStorage(get()) }
single<DaysCoffeesStore> { HeavyDaysCoffeesStore(get()) }
// single<DaysCoffeesStore> { LightDaysCoffeesStore() }
single { NavigationStore() }
viewModel { CoffeeListViewModelImpl(daysCoffeesStore = get(), navigationStore = get()) }
viewModel { TablePageViewModelImpl(daysCoffeesStore = get(), navigationStore = get()) }
viewModel { MapPageViewModelImpl() }
}

override fun onCreate() {
super.onCreate()
Expand All @@ -57,6 +44,29 @@ class Application : Application() {
// or in a snapshot that has not yet been applied
GlobalScope.launch {
FirstGlanceWidget().updateAll(this@Application)
get<DaysCoffeesStore>().state.onEach {
Log.d("TEST||", "onCreate: $it")
FirstGlanceWidget().updateAll(this@Application) }.launchIn(this)
}
}
}

internal val appModule = module {
single<Storage<ThemeState>> {
// ThemeSharedPrefStorage(context = context)
// ThemeDataStorePrefStorage(context = context)
ThemeDataStoreProtoStorage(context = get())
}
single {
ThemeStore(get())
}
single<CoffeeRepository> { RoomCoffeeRepository(get()) }
single<CoffeeStorage> { CoffeeStorage(get()) }
single<DaysCoffeesStore> { HeavyDaysCoffeesStore(get()) }
// single<DaysCoffeesStore> { LightDaysCoffeesStore() }
single { NavigationStore() }
viewModel { CoffeeListViewModelImpl(daysCoffeesStore = get(), navigationStore = get()) }
viewModel { TablePageViewModelImpl(daysCoffeesStore = get(), navigationStore = get()) }
viewModel { MapPageViewModelImpl() }
viewModel { AppWidgetViewModelImpl(daysCoffeesStore = get()) }
}
21 changes: 19 additions & 2 deletions app/src/main/java/ru/beryukhov/coffeegram/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

package ru.beryukhov.coffeegram

import android.Manifest.permission.ACCESS_COARSE_LOCATION
Expand All @@ -19,12 +18,20 @@ import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.launch
import kotlinx.coroutines.tasks.await
import kotlinx.datetime.Clock
import kotlinx.datetime.TimeZone
import kotlinx.datetime.toLocalDateTime
import org.koin.compose.koinInject
import ru.beryukhov.coffeegram.animations.TransitionSlot
import ru.beryukhov.coffeegram.data.CoffeeType
import ru.beryukhov.coffeegram.data.DAY_COFFEE_PATH
import ru.beryukhov.coffeegram.data.DayCoffee
import ru.beryukhov.coffeegram.data.START_ACTIVITY_PATH
import ru.beryukhov.coffeegram.data.toDataMap
import ru.beryukhov.coffeegram.model.NavigationIntent
import ru.beryukhov.coffeegram.model.NavigationState.Companion.NAVIGATION_STATE_KEY
import ru.beryukhov.coffeegram.model.NavigationState.Companion.TODAYS_COFFEE_LIST
import ru.beryukhov.coffeegram.model.NavigationStore
import ru.beryukhov.coffeegram.pages.LandingPage

class MainActivity : ComponentActivity() {
Expand All @@ -39,6 +46,7 @@ class MainActivity : ComponentActivity() {
var doAnimationState by rememberSaveable {
mutableStateOf(true)
}
val navigationStore: NavigationStore = koinInject()
TransitionSlot(
doAnimation = doAnimationState,
StartPage = { modifier -> LandingPage(modifier = modifier) },
Expand All @@ -47,11 +55,20 @@ class MainActivity : ComponentActivity() {
modifier = modifier,
topPadding = topPadding,
startWearableActivity = ::startWearableActivity,
showMap = checkCoarseLocationPermission()
showMap = checkCoarseLocationPermission(),
navigationStore = navigationStore
)
},
) {
doAnimationState = false
if (intent.getStringExtra(NAVIGATION_STATE_KEY) == TODAYS_COFFEE_LIST) {
navigationStore.newIntent(
NavigationIntent.OpenCoffeeListPage(
dayOfMonth = Clock.System.now()
.toLocalDateTime(TimeZone.currentSystemDefault()).date.dayOfMonth
)
)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ class NavigationStore(val yearMonth: YearMonth = nowYM()) : InMemoryStore<Naviga
sealed interface NavigationIntent {
data class OpenCoffeeListPage(val dayOfMonth: Int) : NavigationIntent
data class SetYearMonth(val yearMonth: YearMonth) : NavigationIntent
object ReturnToTablePage : NavigationIntent
object ToSettingsPage : NavigationIntent
object ToMapPage : NavigationIntent
data object ReturnToTablePage : NavigationIntent
data object ToSettingsPage : NavigationIntent
data object ToMapPage : NavigationIntent
}

sealed interface NavigationState {
Expand All @@ -54,6 +54,10 @@ sealed interface NavigationState {

class TablePage(val yearMonth: YearMonth) : NavigationState
data class CoffeeListPage(val date: LocalDate) : NavigationState
object SettingsPage : NavigationState
object MapPage : NavigationState
data object SettingsPage : NavigationState
data object MapPage : NavigationState
companion object {
const val NAVIGATION_STATE_KEY = "NavigationState"
const val TODAYS_COFFEE_LIST = "TodaysCoffeeList"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package ru.beryukhov.coffeegram.pages

import android.util.Log
import androidx.lifecycle.ViewModel
import kotlinx.collections.immutable.PersistentList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toPersistentList
import kotlinx.datetime.Clock
import kotlinx.datetime.TimeZone
import kotlinx.datetime.todayIn
import ru.beryukhov.coffeegram.data.CoffeeType
import ru.beryukhov.coffeegram.data.CoffeeTypeWithCount
import ru.beryukhov.coffeegram.data.DayCoffee
import ru.beryukhov.coffeegram.model.DaysCoffeesIntent
import ru.beryukhov.coffeegram.model.DaysCoffeesState
import ru.beryukhov.coffeegram.model.DaysCoffeesStore

interface AppWidgetViewModel {
fun getCurrentDayCupsCount(): Int
fun getCurrentDayMostPopularWithCount(): CoffeeTypeWithCount
fun getCurrentDayList(): PersistentList<CoffeeTypeWithCount>

fun currentDayIncrement(coffeeType: CoffeeType)
fun currentDayDecrement(coffeeType: CoffeeType)
}

class AppWidgetViewModelStub : AppWidgetViewModel {
override fun getCurrentDayCupsCount(): Int = 0

override fun getCurrentDayMostPopularWithCount(): CoffeeTypeWithCount =
CoffeeTypeWithCount(CoffeeType.Cappuccino, 0)

override fun getCurrentDayList(): PersistentList<CoffeeTypeWithCount> =
persistentListOf(CoffeeTypeWithCount(CoffeeType.Cappuccino, 0))

override fun currentDayIncrement(coffeeType: CoffeeType) = Unit

override fun currentDayDecrement(coffeeType: CoffeeType) = Unit
}

class AppWidgetViewModelImpl(
private val daysCoffeesStore: DaysCoffeesStore,
) : ViewModel(), AppWidgetViewModel {

private fun getCurrentDay() = Clock.System.todayIn(TimeZone.currentSystemDefault())

override fun getCurrentDayCupsCount(): Int {
return getCurrentDayList().sumOf { it.count }
}

override fun getCurrentDayMostPopularWithCount(): CoffeeTypeWithCount {
return getCurrentDayList().first()
}

// coffee list does not contains 0 values and sorted by count
override fun getCurrentDayList(): PersistentList<CoffeeTypeWithCount> {
val dayCoffeeState: DaysCoffeesState = daysCoffeesStore.state.value
val dayCoffee = dayCoffeeState.value[getCurrentDay()] ?: DayCoffee()
val list = dayCoffee.coffeeCountMap.toList()
.sortedByDescending { it.second }
.map { CoffeeTypeWithCount(it.first, it.second) }
val emptyListMock = listOf(CoffeeTypeWithCount(CoffeeType.Cappuccino, 0))
return list.ifEmpty { emptyListMock }.toPersistentList()
}

override fun currentDayDecrement(coffeeType: CoffeeType) {
newIntent(
DaysCoffeesIntent.MinusCoffee(
localDate = getCurrentDay(),
coffeeType = coffeeType
)
)
}

override fun currentDayIncrement(coffeeType: CoffeeType) {
Log.d("TEST||", "currentDayIncrement: coffeeType = $coffeeType")
newIntent(
DaysCoffeesIntent.PlusCoffee(
localDate = getCurrentDay(),
coffeeType = coffeeType
)
)
}

private fun newIntent(intent: DaysCoffeesIntent) {
daysCoffeesStore.newIntent(intent)
}
}
18 changes: 4 additions & 14 deletions app/src/main/java/ru/beryukhov/coffeegram/pages/CoffeeListPage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import kotlinx.datetime.LocalDate
import org.koin.androidx.compose.koinViewModel
import ru.beryukhov.coffeegram.R
import ru.beryukhov.coffeegram.data.CoffeeType
import ru.beryukhov.coffeegram.model.DaysCoffeesIntent
import ru.beryukhov.coffeegram.data.CoffeeTypeWithCount
import ru.beryukhov.coffeegram.model.NavigationIntent
import ru.beryukhov.coffeegram.view.CoffeeTypeItem
import ru.beryukhov.date_time_utils.getFullMonthName
Expand Down Expand Up @@ -63,22 +63,12 @@ fun CoffeeListPage(
BackHandler { coffeeListViewModel.newIntent(NavigationIntent.ReturnToTablePage) }
val onPlusClick = remember(localDate, coffeeListViewModel) {
{ coffeeType: CoffeeType ->
coffeeListViewModel.newIntent(
DaysCoffeesIntent.PlusCoffee(
localDate,
coffeeType
)
)
coffeeListViewModel.incrementCoffee(localDate, coffeeType)
}
}
val onMinusClick = remember(localDate, coffeeListViewModel) {
{ coffeeType: CoffeeType ->
coffeeListViewModel.newIntent(
DaysCoffeesIntent.MinusCoffee(
localDate,
coffeeType
)
)
coffeeListViewModel.decrementCoffee(localDate, coffeeType)
}
}
CoffeeList(
Expand All @@ -91,7 +81,7 @@ fun CoffeeListPage(

@Composable
private fun CoffeeList(
coffeeItems: PersistentList<Pair<CoffeeType, Int>>,
coffeeItems: PersistentList<CoffeeTypeWithCount>,
onPlusClick: (coffeeType: CoffeeType) -> Unit,
modifier: Modifier = Modifier,
onMinusClick: (coffeeType: CoffeeType) -> Unit
Expand Down
Loading

0 comments on commit a146447

Please sign in to comment.