Add "Monitoring for devices" card to Overview

This commit introduces a new card to the Overview screen that informs the user that the app is actively monitoring for devices when there are profiles configured but no devices are currently connected.
This commit is contained in:
darken
2025-09-29 14:14:09 +02:00
parent e2014a26fc
commit 69ce7e18f5
5 changed files with 89 additions and 4 deletions
@@ -12,6 +12,7 @@ import eu.darken.capod.common.lists.modular.ModularAdapter
import eu.darken.capod.common.lists.modular.mods.DataBinderMod import eu.darken.capod.common.lists.modular.mods.DataBinderMod
import eu.darken.capod.common.lists.modular.mods.TypedVHCreatorMod import eu.darken.capod.common.lists.modular.mods.TypedVHCreatorMod
import eu.darken.capod.main.ui.overview.cards.BluetoothDisabledVH import eu.darken.capod.main.ui.overview.cards.BluetoothDisabledVH
import eu.darken.capod.main.ui.overview.cards.MonitoringActiveVH
import eu.darken.capod.main.ui.overview.cards.NoProfilesVH import eu.darken.capod.main.ui.overview.cards.NoProfilesVH
import eu.darken.capod.main.ui.overview.cards.PermissionCardVH import eu.darken.capod.main.ui.overview.cards.PermissionCardVH
import eu.darken.capod.main.ui.overview.cards.UnmatchedDevicesCardVH import eu.darken.capod.main.ui.overview.cards.UnmatchedDevicesCardVH
@@ -33,6 +34,7 @@ class OverviewAdapter @Inject constructor() :
modules.add(TypedVHCreatorMod({ data[it] is SinglePodsCardVH.Item }) { SinglePodsCardVH(it) }) modules.add(TypedVHCreatorMod({ data[it] is SinglePodsCardVH.Item }) { SinglePodsCardVH(it) })
modules.add(TypedVHCreatorMod({ data[it] is NoProfilesVH.Item }) { NoProfilesVH(it) }) modules.add(TypedVHCreatorMod({ data[it] is NoProfilesVH.Item }) { NoProfilesVH(it) })
modules.add(TypedVHCreatorMod({ data[it] is BluetoothDisabledVH.Item }) { BluetoothDisabledVH(it) }) modules.add(TypedVHCreatorMod({ data[it] is BluetoothDisabledVH.Item }) { BluetoothDisabledVH(it) })
modules.add(TypedVHCreatorMod({ data[it] is MonitoringActiveVH.Item }) { MonitoringActiveVH(it) })
modules.add(TypedVHCreatorMod({ data[it] is UnmatchedDevicesCardVH.Item }) { UnmatchedDevicesCardVH(it) }) modules.add(TypedVHCreatorMod({ data[it] is UnmatchedDevicesCardVH.Item }) { UnmatchedDevicesCardVH(it) })
modules.add(TypedVHCreatorMod({ data[it] is UnknownPodDeviceCardVH.Item }) { UnknownPodDeviceCardVH(it) }) modules.add(TypedVHCreatorMod({ data[it] is UnknownPodDeviceCardVH.Item }) { UnknownPodDeviceCardVH(it) })
} }
@@ -42,7 +44,7 @@ class OverviewAdapter @Inject constructor() :
abstract class BaseVH<D : Item, B : ViewBinding>( abstract class BaseVH<D : Item, B : ViewBinding>(
@LayoutRes layoutId: Int, @LayoutRes layoutId: Int,
parent: ViewGroup parent: ViewGroup
) : ModularAdapter.VH(layoutId, parent), BindableVH<D, B> ) : VH(layoutId, parent), BindableVH<D, B>
interface Item : DifferItem interface Item : DifferItem
@@ -15,11 +15,11 @@ import eu.darken.capod.common.livedata.SingleLiveEvent
import eu.darken.capod.common.permissions.Permission import eu.darken.capod.common.permissions.Permission
import eu.darken.capod.common.uix.ViewModel3 import eu.darken.capod.common.uix.ViewModel3
import eu.darken.capod.common.upgrade.UpgradeRepo import eu.darken.capod.common.upgrade.UpgradeRepo
import eu.darken.capod.profiles.core.DeviceProfilesRepo
import eu.darken.capod.main.core.GeneralSettings import eu.darken.capod.main.core.GeneralSettings
import eu.darken.capod.main.core.MonitorMode import eu.darken.capod.main.core.MonitorMode
import eu.darken.capod.main.core.PermissionTool import eu.darken.capod.main.core.PermissionTool
import eu.darken.capod.main.ui.overview.cards.BluetoothDisabledVH import eu.darken.capod.main.ui.overview.cards.BluetoothDisabledVH
import eu.darken.capod.main.ui.overview.cards.MonitoringActiveVH
import eu.darken.capod.main.ui.overview.cards.NoProfilesVH import eu.darken.capod.main.ui.overview.cards.NoProfilesVH
import eu.darken.capod.main.ui.overview.cards.PermissionCardVH import eu.darken.capod.main.ui.overview.cards.PermissionCardVH
import eu.darken.capod.main.ui.overview.cards.UnmatchedDevicesCardVH import eu.darken.capod.main.ui.overview.cards.UnmatchedDevicesCardVH
@@ -31,6 +31,7 @@ import eu.darken.capod.monitor.core.worker.MonitorControl
import eu.darken.capod.pods.core.DualPodDevice import eu.darken.capod.pods.core.DualPodDevice
import eu.darken.capod.pods.core.PodDevice import eu.darken.capod.pods.core.PodDevice
import eu.darken.capod.pods.core.SinglePodDevice import eu.darken.capod.pods.core.SinglePodDevice
import eu.darken.capod.profiles.core.DeviceProfilesRepo
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.catch
@@ -176,7 +177,11 @@ class OverviewFragmentVM @Inject constructor(
) )
} }
}.run { items.addAll(this) } }.run { items.addAll(this) }
if (profiles.isNotEmpty() && devices.isEmpty()) {
items.add(MonitoringActiveVH.Item)
}
// Add unmatched devices section if any exist // Add unmatched devices section if any exist
if (unmatchedDevices.isNotEmpty()) { if (unmatchedDevices.isNotEmpty()) {
items.add(UnmatchedDevicesCardVH.Item( items.add(UnmatchedDevicesCardVH.Item(
@@ -0,0 +1,33 @@
package eu.darken.capod.main.ui.overview.cards
import android.view.ViewGroup
import eu.darken.capod.R
import eu.darken.capod.common.lists.binding
import eu.darken.capod.common.lists.differ.DifferItem
import eu.darken.capod.databinding.OverviewMonitoringActiveItemBinding
import eu.darken.capod.main.ui.overview.OverviewAdapter
class MonitoringActiveVH(parent: ViewGroup) :
OverviewAdapter.BaseVH<MonitoringActiveVH.Item, OverviewMonitoringActiveItemBinding>(
R.layout.overview_monitoring_active_item,
parent
) {
override val viewBinding = lazy {
OverviewMonitoringActiveItemBinding.bind(itemView)
}
override val onBindData: OverviewMonitoringActiveItemBinding.(
item: Item,
payloads: List<Any>
) -> Unit = binding(payload = true) { item ->
// No actions needed for this card - it's purely informational
}
object Item : OverviewAdapter.Item {
override val stableId: Long = Item::class.hashCode().toLong()
override val payloadProvider: ((DifferItem, DifferItem) -> DifferItem?)
get() = { old, new -> if (new::class.isInstance(old)) new else null }
}
}
@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/card"
style="@style/MyCardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:context=".main.ui.MainActivity">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.textview.MaterialTextView
android:id="@+id/monitoring_label"
style="@style/TextAppearance.Material3.TitleMedium"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="16dp"
android:text="@string/overview_monitoring_active_label"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/monitoring_description"
style="@style/TextAppearance.Material3.BodyMedium"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="4dp"
android:layout_marginBottom="16dp"
android:text="@string/overview_monitoring_active_description"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/monitoring_label" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
+3 -1
View File
@@ -140,7 +140,7 @@
<string name="onboarding_body4">You can upgrade to CAPod Pro to gain extra features and support development.</string> <string name="onboarding_body4">You can upgrade to CAPod Pro to gain extra features and support development.</string>
<!-- Strings from app-common --> <!-- Strings from app-common -->
<string name="app_name">CAPod</string> <string name="app_name">CAPod</string>
<string name="app_name_pro">CAPod Pro</string> <string name="app_name_pro">CAPod Pro</string>
<string name="app_name_foss">CAPod FOSS</string> <string name="app_name_foss">CAPod FOSS</string>
@@ -153,6 +153,8 @@
<string name="overview_nomaindevice_description">Configure your device to start monitoring battery levels and enable additional features.</string> <string name="overview_nomaindevice_description">Configure your device to start monitoring battery levels and enable additional features.</string>
<string name="overview_bluetooth_disabled_label">Bluetooth is disabled</string> <string name="overview_bluetooth_disabled_label">Bluetooth is disabled</string>
<string name="overview_bluetooth_disabled_description">Bluetooth is disabled, enable it ;)</string> <string name="overview_bluetooth_disabled_description">Bluetooth is disabled, enable it ;)</string>
<string name="overview_monitoring_active_label">Monitoring for devices</string>
<string name="overview_monitoring_active_description">Make sure your device is nearby and active.</string>
<string name="overview_unmatched_devices_label">Unmatched devices</string> <string name="overview_unmatched_devices_label">Unmatched devices</string>
<string name="overview_unmatched_devices_count_single">1 device without matching profile</string> <string name="overview_unmatched_devices_count_single">1 device without matching profile</string>
<string name="overview_unmatched_devices_count_plural">%d devices without matching profile</string> <string name="overview_unmatched_devices_count_plural">%d devices without matching profile</string>