diff --git a/app/src/google/java/net/vonforst/evmap/auto/MapScreen.kt b/app/src/google/java/net/vonforst/evmap/auto/MapScreen.kt index ed1fd4cc..d1f69fc4 100644 --- a/app/src/google/java/net/vonforst/evmap/auto/MapScreen.kt +++ b/app/src/google/java/net/vonforst/evmap/auto/MapScreen.kt @@ -268,12 +268,13 @@ class MapScreen(ctx: CarContext, val session: EVMapSession, val favorites: Boole try { // load chargers if (favorites) { - chargers = db.chargeLocationsDao().getAllChargeLocationsAsync().sortedBy { - distanceBetween( - location.latitude, location.longitude, - it.coordinates.lat, it.coordinates.lng - ) - } + chargers = + db.favoritesDao().getAllFavoritesAsync().map { it.charger }.sortedBy { + distanceBetween( + location.latitude, location.longitude, + it.coordinates.lat, it.coordinates.lng + ) + } } else { val response = api.getChargepointsRadius( referenceData, diff --git a/app/src/main/java/net/vonforst/evmap/adapter/FavoritesAdapter.kt b/app/src/main/java/net/vonforst/evmap/adapter/FavoritesAdapter.kt index 131c7cf6..8aada7a6 100644 --- a/app/src/main/java/net/vonforst/evmap/adapter/FavoritesAdapter.kt +++ b/app/src/main/java/net/vonforst/evmap/adapter/FavoritesAdapter.kt @@ -14,7 +14,7 @@ class FavoritesAdapter(val onDelete: (FavoritesViewModel.FavoritesListItem) -> U override fun getItemViewType(position: Int): Int = R.layout.item_favorite - override fun getItemId(position: Int): Long = getItem(position).charger.id + override fun getItemId(position: Int): Long = getItem(position).fav.favorite.favoriteId @SuppressLint("ClickableViewAccessibility") override fun bind( diff --git a/app/src/main/java/net/vonforst/evmap/api/goingelectric/GoingElectricApi.kt b/app/src/main/java/net/vonforst/evmap/api/goingelectric/GoingElectricApi.kt index 13bf3093..8c6eb2a8 100644 --- a/app/src/main/java/net/vonforst/evmap/api/goingelectric/GoingElectricApi.kt +++ b/app/src/main/java/net/vonforst/evmap/api/goingelectric/GoingElectricApi.kt @@ -326,7 +326,7 @@ class GoingElectricApiWrapper( } else { true } - }.map { it.convert(apikey) } + }.map { it.convert(apikey, false) } // apply clustering val useClustering = zoom < 13 @@ -350,7 +350,7 @@ class GoingElectricApiWrapper( return if (response.isSuccessful && response.body()!!.status == "ok" && response.body()!!.chargelocations.size == 1) { Resource.success( (response.body()!!.chargelocations[0] as GEChargeLocation).convert( - apikey + apikey, true ) ) } else { diff --git a/app/src/main/java/net/vonforst/evmap/api/goingelectric/GoingElectricModel.kt b/app/src/main/java/net/vonforst/evmap/api/goingelectric/GoingElectricModel.kt index 1a7b2449..27747c6d 100644 --- a/app/src/main/java/net/vonforst/evmap/api/goingelectric/GoingElectricModel.kt +++ b/app/src/main/java/net/vonforst/evmap/api/goingelectric/GoingElectricModel.kt @@ -29,7 +29,7 @@ data class GEChargeCardList( ) sealed class GEChargepointListItem { - abstract fun convert(apikey: String): ChargepointListItem + abstract fun convert(apikey: String, isDetailed: Boolean): ChargepointListItem } @JsonClass(generateAdapter = true) @@ -54,7 +54,7 @@ data class GEChargeLocation( val openinghours: GEOpeningHours?, val cost: GECost? ) : GEChargepointListItem() { - override fun convert(apikey: String) = ChargeLocation( + override fun convert(apikey: String, isDetailed: Boolean) = ChargeLocation( id, "goingelectric", name, @@ -76,7 +76,9 @@ data class GEChargeLocation( openinghours?.convert(), cost?.convert(), null, - ChargepriceData(address.country, network, chargepoints.map { it.type }) + ChargepriceData(address.country, network, chargepoints.map { it.type }), + Instant.now(), + isDetailed ) } @@ -161,7 +163,7 @@ data class GEChargeLocationCluster( val clusterCount: Int, val coordinates: GECoordinate ) : GEChargepointListItem() { - override fun convert(apikey: String) = + override fun convert(apikey: String, isDetailed: Boolean) = ChargeLocationCluster(clusterCount, coordinates.convert()) } diff --git a/app/src/main/java/net/vonforst/evmap/api/openchargemap/OpenChargeMapApi.kt b/app/src/main/java/net/vonforst/evmap/api/openchargemap/OpenChargeMapApi.kt index 46b471d0..a6613832 100644 --- a/app/src/main/java/net/vonforst/evmap/api/openchargemap/OpenChargeMapApi.kt +++ b/app/src/main/java/net/vonforst/evmap/api/openchargemap/OpenChargeMapApi.kt @@ -235,7 +235,7 @@ class OpenChargeMapApiWrapper( .filter { it.power == null || it.power >= (minPower ?: 0.0) } .filter { if (connectorsVal != null && !connectorsVal.all) it.connectionTypeId in connectorsVal.values.map { it.toLong() } else true } .sumOf { it.quantity ?: 1 } >= (minConnectors ?: 0) - }.map { it.convert(referenceData) }.distinct() as List + }.map { it.convert(referenceData, false) }.distinct() as List // apply clustering val useClustering = zoom < 13 @@ -256,7 +256,7 @@ class OpenChargeMapApiWrapper( try { val response = api.getChargepointDetail(id) if (response.isSuccessful && response.body()?.size == 1) { - return Resource.success(response.body()!![0].convert(referenceData)) + return Resource.success(response.body()!![0].convert(referenceData, true)) } else { return Resource.error(response.message(), null) } diff --git a/app/src/main/java/net/vonforst/evmap/api/openchargemap/OpenChargeMapModel.kt b/app/src/main/java/net/vonforst/evmap/api/openchargemap/OpenChargeMapModel.kt index 6bec6da5..cc2e4206 100644 --- a/app/src/main/java/net/vonforst/evmap/api/openchargemap/OpenChargeMapModel.kt +++ b/app/src/main/java/net/vonforst/evmap/api/openchargemap/OpenChargeMapModel.kt @@ -7,6 +7,7 @@ import com.squareup.moshi.JsonClass import kotlinx.parcelize.Parcelize import net.vonforst.evmap.max import net.vonforst.evmap.model.* +import java.time.Instant import java.time.ZonedDateTime // Unknown, Currently Available, Currently In Use, Operational @@ -44,7 +45,7 @@ data class OCMChargepoint( @Json(name = "UserComments") val userComments: List?, @Json(name = "DateLastStatusUpdate") val lastStatusUpdateDate: ZonedDateTime? ) { - fun convert(refData: OCMReferenceData) = ChargeLocation( + fun convert(refData: OCMReferenceData, isDetailed: Boolean) = ChargeLocation( id, "openchargemap", addressInfo.title, @@ -69,7 +70,9 @@ data class OCMChargepoint( ChargepriceData( addressInfo.countryISOCode(refData), operatorId?.toString(), - connections.map { "${it.connectionTypeId},${it.currentTypeId}" }) + connections.map { "${it.connectionTypeId},${it.currentTypeId}" }), + Instant.now(), + isDetailed ) private fun convertFaultReport(): FaultReport? { diff --git a/app/src/main/java/net/vonforst/evmap/fragment/FavoritesFragment.kt b/app/src/main/java/net/vonforst/evmap/fragment/FavoritesFragment.kt index 81368910..0d2ad67b 100644 --- a/app/src/main/java/net/vonforst/evmap/fragment/FavoritesFragment.kt +++ b/app/src/main/java/net/vonforst/evmap/fragment/FavoritesFragment.kt @@ -28,7 +28,8 @@ import net.vonforst.evmap.adapter.DataBindingAdapter import net.vonforst.evmap.adapter.FavoritesAdapter import net.vonforst.evmap.databinding.FragmentFavoritesBinding import net.vonforst.evmap.databinding.ItemFavoriteBinding -import net.vonforst.evmap.model.ChargeLocation +import net.vonforst.evmap.model.Favorite +import net.vonforst.evmap.model.FavoriteWithDetail import net.vonforst.evmap.utils.checkAnyLocationPermission import net.vonforst.evmap.viewmodel.FavoritesViewModel import net.vonforst.evmap.viewmodel.viewModelFactory @@ -36,7 +37,7 @@ import net.vonforst.evmap.viewmodel.viewModelFactory class FavoritesFragment : Fragment(), LostApiClient.ConnectionCallbacks { private lateinit var binding: FragmentFavoritesBinding private var locationClient: LostApiClient? = null - private var toDelete: ChargeLocation? = null + private var toDelete: Favorite? = null private var deleteSnackbar: Snackbar? = null private lateinit var adapter: FavoritesAdapter @@ -84,7 +85,7 @@ class FavoritesFragment : Fragment(), LostApiClient.ConnectionCallbacks { ) adapter = FavoritesAdapter(onDelete = { - delete(it.charger) + delete(it.fav) }).apply { onClickListener = { findNavController().navigate( @@ -132,18 +133,20 @@ class FavoritesFragment : Fragment(), LostApiClient.ConnectionCallbacks { } } - fun delete(fav: ChargeLocation) { - val position = vm.listData.value?.indexOfFirst { it.charger == fav } ?: return + fun delete(fav: FavoriteWithDetail) { + val position = + vm.listData.value?.indexOfFirst { it.fav.favorite.favoriteId == fav.favorite.favoriteId } + ?: return // if there is already a profile to delete, delete it now actuallyDelete() deleteSnackbar?.dismiss() - toDelete = fav + toDelete = fav.favorite view?.let { val snackbar = Snackbar.make( it, - getString(R.string.deleted_filterprofile, fav.name), + getString(R.string.deleted_filterprofile, fav.charger.name), Snackbar.LENGTH_LONG ).setAction(R.string.undo) { toDelete = null @@ -182,7 +185,7 @@ class FavoritesFragment : Fragment(), LostApiClient.ConnectionCallbacks { } override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { - val fav = vm.favorites.value?.find { it.id == viewHolder.itemId } + val fav = vm.favorites.value?.find { it.favorite.favoriteId == viewHolder.itemId } fav?.let { delete(it) } } diff --git a/app/src/main/java/net/vonforst/evmap/fragment/MapFragment.kt b/app/src/main/java/net/vonforst/evmap/fragment/MapFragment.kt index 8cf86ff0..14f944ad 100644 --- a/app/src/main/java/net/vonforst/evmap/fragment/MapFragment.kt +++ b/app/src/main/java/net/vonforst/evmap/fragment/MapFragment.kt @@ -499,9 +499,9 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac private fun toggleFavorite() { val favs = vm.favorites.value ?: return val charger = vm.chargerSparse.value ?: return - val isFav = favs.find { it.id == charger.id } != null - if (isFav) { - vm.deleteFavorite(charger) + val fav = favs.find { it.charger.id == charger.id } + if (fav != null) { + vm.deleteFavorite(fav.favorite) } else { vm.insertFavorite(charger) } @@ -511,7 +511,7 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac highlight = true, fault = charger.faultReport != null, multi = charger.isMulti(vm.filteredConnectors.value), - fav = !isFav + fav = fav == null ) ) } @@ -642,7 +642,7 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac highlight = false, fault = c.faultReport != null, multi = c.isMulti(vm.filteredConnectors.value), - fav = c.id in vm.favorites.value?.map { it.id } ?: emptyList() + fav = c.id in vm.favorites.value?.map { it.charger.id } ?: emptyList() ) ) } @@ -657,7 +657,7 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac highlight = true, fault = charger.faultReport != null, multi = charger.isMulti(vm.filteredConnectors.value), - fav = charger.id in vm.favorites.value?.map { it.id } ?: emptyList() + fav = charger.id in vm.favorites.value?.map { it.charger.id } ?: emptyList() ) ) animator.animateMarkerBounce(marker) @@ -671,7 +671,7 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac highlight = false, fault = c.faultReport != null, multi = c.isMulti(vm.filteredConnectors.value), - fav = c.id in vm.favorites.value?.map { it.id } ?: emptyList() + fav = c.id in vm.favorites.value?.map { it.charger.id } ?: emptyList() ) ) } @@ -681,7 +681,7 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac private fun updateFavoriteToggle() { val favs = vm.favorites.value ?: return val charger = vm.chargerSparse.value ?: return - if (favs.find { it.id == charger.id } != null) { + if (favs.find { it.charger.id == charger.id } != null) { favToggle.setIcon(R.drawable.ic_fav) } else { favToggle.setIcon(R.drawable.ic_fav_no) @@ -1023,7 +1023,7 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac highlight = charger == vm.chargerSparse.value, fault = charger.faultReport != null, multi = charger.isMulti(vm.filteredConnectors.value), - fav = charger.id in vm.favorites.value?.map { it.id } ?: emptyList() + fav = charger.id in vm.favorites.value?.map { it.charger.id } ?: emptyList() ) ) } @@ -1041,7 +1041,8 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac val highlight = charger == vm.chargerSparse.value val fault = charger.faultReport != null val multi = charger.isMulti(vm.filteredConnectors.value) - val fav = charger.id in vm.favorites.value?.map { it.id } ?: emptyList() + val fav = + charger.id in vm.favorites.value?.map { it.charger.id } ?: emptyList() animator.animateMarkerDisappear(marker, tint, highlight, fault, multi, fav) } else { animator.deleteMarker(marker) @@ -1057,7 +1058,7 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac val highlight = charger == vm.chargerSparse.value val fault = charger.faultReport != null val multi = charger.isMulti(vm.filteredConnectors.value) - val fav = charger.id in vm.favorites.value?.map { it.id } ?: emptyList() + val fav = charger.id in vm.favorites.value?.map { it.charger.id } ?: emptyList() val marker = map.addMarker( MarkerOptions() .position(LatLng(charger.coordinates.lat, charger.coordinates.lng)) diff --git a/app/src/main/java/net/vonforst/evmap/model/ChargersModel.kt b/app/src/main/java/net/vonforst/evmap/model/ChargersModel.kt index 0d02dc91..ac95723c 100644 --- a/app/src/main/java/net/vonforst/evmap/model/ChargersModel.kt +++ b/app/src/main/java/net/vonforst/evmap/model/ChargersModel.kt @@ -24,6 +24,14 @@ import kotlin.math.floor sealed class ChargepointListItem + +/** + * A whole charging site (potentially with multiple chargepoints). + * + * @param timeRetrieved Time when this information was retrieved from the data source + * @param isDetailed Whether this data includes all available details (for many data sources, + * API calls that return a list may only give a compact representation) + */ @Entity(primaryKeys = ["id", "dataSource"]) @Parcelize data class ChargeLocation( @@ -49,7 +57,9 @@ data class ChargeLocation( @Embedded val openinghours: OpeningHours?, @Embedded val cost: Cost?, val license: String?, - @Embedded(prefix = "chargeprice") val chargepriceData: ChargepriceData? + @Embedded(prefix = "chargeprice") val chargepriceData: ChargepriceData?, + val timeRetrieved: Instant, + val isDetailed: Boolean ) : ChargepointListItem(), Equatable, Parcelable { /** * maximum power available from this charger. diff --git a/app/src/main/java/net/vonforst/evmap/model/FavoritesModel.kt b/app/src/main/java/net/vonforst/evmap/model/FavoritesModel.kt new file mode 100644 index 00000000..a0e079ed --- /dev/null +++ b/app/src/main/java/net/vonforst/evmap/model/FavoritesModel.kt @@ -0,0 +1,28 @@ +package net.vonforst.evmap.model + +import androidx.room.Embedded +import androidx.room.Entity +import androidx.room.ForeignKey +import androidx.room.PrimaryKey + +@Entity( + foreignKeys = [ + ForeignKey( + entity = ChargeLocation::class, + parentColumns = arrayOf("id", "dataSource"), + childColumns = arrayOf("chargerId", "chargerDataSource"), + onDelete = ForeignKey.RESTRICT, + ) + ] +) +data class Favorite( + @PrimaryKey(autoGenerate = true) + val favoriteId: Long = 0, + val chargerId: Long, + val chargerDataSource: String +) + +data class FavoriteWithDetail( + @Embedded() val favorite: Favorite, + @Embedded val charger: ChargeLocation +) diff --git a/app/src/main/java/net/vonforst/evmap/storage/Database.kt b/app/src/main/java/net/vonforst/evmap/storage/Database.kt index 14823c97..b67a6494 100644 --- a/app/src/main/java/net/vonforst/evmap/storage/Database.kt +++ b/app/src/main/java/net/vonforst/evmap/storage/Database.kt @@ -20,6 +20,7 @@ import net.vonforst.evmap.model.* @Database( entities = [ ChargeLocation::class, + Favorite::class, BooleanFilterValue::class, MultipleChoiceFilterValue::class, SliderFilterValue::class, @@ -31,11 +32,12 @@ import net.vonforst.evmap.model.* OCMConnectionType::class, OCMCountry::class, OCMOperator::class - ], version = 14 + ], version = 16 ) @TypeConverters(Converters::class) abstract class AppDatabase : RoomDatabase() { abstract fun chargeLocationsDao(): ChargeLocationsDao + abstract fun favoritesDao(): FavoritesDao abstract fun filterValueDao(): FilterValueDao abstract fun filterProfileDao(): FilterProfileDao abstract fun recentAutocompletePlaceDao(): RecentAutocompletePlaceDao @@ -53,7 +55,7 @@ abstract class AppDatabase : RoomDatabase() { .addMigrations( MIGRATION_2, MIGRATION_3, MIGRATION_4, MIGRATION_5, MIGRATION_6, MIGRATION_7, MIGRATION_8, MIGRATION_9, MIGRATION_10, MIGRATION_11, - MIGRATION_12, MIGRATION_13, MIGRATION_14 + MIGRATION_12, MIGRATION_13, MIGRATION_14, MIGRATION_15, MIGRATION_16 ) .addCallback(object : Callback() { override fun onCreate(db: SupportSQLiteDatabase) { @@ -312,5 +314,37 @@ abstract class AppDatabase : RoomDatabase() { } } + + private val MIGRATION_15 = object : Migration(14, 15) { + @SuppressLint("Range") + override fun migrate(db: SupportSQLiteDatabase) { + try { + db.beginTransaction() + db.execSQL("CREATE TABLE IF NOT EXISTS `Favorite` (`favoriteId` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `chargerId` INTEGER NOT NULL, `chargerDataSource` TEXT NOT NULL, FOREIGN KEY(`chargerId`, `chargerDataSource`) REFERENCES `ChargeLocation`(`id`, `dataSource`) ON UPDATE NO ACTION ON DELETE RESTRICT )"); + + val cursor = db.query("SELECT * FROM `ChargeLocation`") + while (cursor.moveToNext()) { + val id = cursor.getLong(cursor.getColumnIndex("id")) + val dataSource = cursor.getString(cursor.getColumnIndex("dataSource")) + val values = ContentValues().apply { + put("chargerId", id) + put("chargerDataSource", dataSource) + } + db.insert("favorite", SQLiteDatabase.CONFLICT_ROLLBACK, values) + } + + db.setTransactionSuccessful() + } finally { + db.endTransaction() + } + } + } + + private val MIGRATION_16 = object : Migration(15, 16) { + override fun migrate(db: SupportSQLiteDatabase) { + db.execSQL("ALTER TABLE `ChargeLocation` ADD `timeRetrieved` INTEGER NOT NULL DEFAULT 0") + db.execSQL("ALTER TABLE `ChargeLocation` ADD `isDetailed` INTEGER NOT NULL DEFAULT 0") + } + } } } \ No newline at end of file diff --git a/app/src/main/java/net/vonforst/evmap/storage/FavoritesDao.kt b/app/src/main/java/net/vonforst/evmap/storage/FavoritesDao.kt new file mode 100644 index 00000000..e2c2c963 --- /dev/null +++ b/app/src/main/java/net/vonforst/evmap/storage/FavoritesDao.kt @@ -0,0 +1,29 @@ +package net.vonforst.evmap.storage + +import androidx.lifecycle.LiveData +import androidx.room.* +import net.vonforst.evmap.model.Favorite +import net.vonforst.evmap.model.FavoriteWithDetail + +@Dao +interface FavoritesDao { + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun insert(vararg favorites: Favorite) + + @Delete + suspend fun delete(vararg favorites: Favorite) + + @Query("SELECT * FROM favorite LEFT JOIN chargelocation ON favorite.chargerDataSource = chargelocation.dataSource AND favorite.chargerId = chargelocation.id") + fun getAllFavorites(): LiveData> + + @Query("SELECT * FROM favorite LEFT JOIN chargelocation ON favorite.chargerDataSource = chargelocation.dataSource AND favorite.chargerId = chargelocation.id") + suspend fun getAllFavoritesAsync(): List + + @Query("SELECT * FROM favorite LEFT JOIN chargelocation ON favorite.chargerDataSource = chargelocation.dataSource AND favorite.chargerId = chargelocation.id WHERE lat >= :lat1 AND lat <= :lat2 AND lng >= :lng1 AND lng <= :lng2") + suspend fun getFavoritesInBoundsAsync( + lat1: Double, + lat2: Double, + lng1: Double, + lng2: Double + ): List +} \ No newline at end of file diff --git a/app/src/main/java/net/vonforst/evmap/viewmodel/FavoritesViewModel.kt b/app/src/main/java/net/vonforst/evmap/viewmodel/FavoritesViewModel.kt index 186e7d6f..471d2f14 100644 --- a/app/src/main/java/net/vonforst/evmap/viewmodel/FavoritesViewModel.kt +++ b/app/src/main/java/net/vonforst/evmap/viewmodel/FavoritesViewModel.kt @@ -11,6 +11,8 @@ import net.vonforst.evmap.api.availability.ChargeLocationStatus import net.vonforst.evmap.api.availability.ChargepointStatus import net.vonforst.evmap.api.availability.getAvailability import net.vonforst.evmap.model.ChargeLocation +import net.vonforst.evmap.model.Favorite +import net.vonforst.evmap.model.FavoriteWithDetail import net.vonforst.evmap.storage.AppDatabase import net.vonforst.evmap.utils.distanceBetween @@ -18,8 +20,8 @@ class FavoritesViewModel(application: Application, geApiKey: String) : AndroidViewModel(application) { private var db = AppDatabase.getInstance(application) - val favorites: LiveData> by lazy { - db.chargeLocationsDao().getAllChargeLocations() + val favorites: LiveData> by lazy { + db.favoritesDao().getAllFavorites() } val location: MutableLiveData by lazy { @@ -28,8 +30,9 @@ class FavoritesViewModel(application: Application, geApiKey: String) : val availability: MediatorLiveData>> by lazy { MediatorLiveData>>().apply { - addSource(favorites) { chargers -> - if (chargers != null) { + addSource(favorites) { favorites -> + if (favorites != null) { + val chargers = favorites.map { it.charger } viewModelScope.launch { val data = hashMapOf>() chargers.forEach { charger -> @@ -54,9 +57,10 @@ class FavoritesViewModel(application: Application, geApiKey: String) : val listData: MediatorLiveData> by lazy { MediatorLiveData>().apply { val callback = { _: Any -> - listData.value = favorites.value?.map { charger -> + listData.value = favorites.value?.map { favorite -> + val charger = favorite.charger FavoritesListItem( - charger, + favorite, totalAvailable(charger.id), charger.chargepoints.sumBy { it.count }, location.value.let { loc -> @@ -78,11 +82,14 @@ class FavoritesViewModel(application: Application, geApiKey: String) : } data class FavoritesListItem( - val charger: ChargeLocation, + val fav: FavoriteWithDetail, val available: Resource>, val total: Int, val distance: Double? - ) : Equatable + ) : Equatable { + val charger + get() = fav.charger + } private fun totalAvailable(id: Long): Resource> { val availability = availability.value?.get(id) ?: return Resource.error(null, null) @@ -97,12 +104,14 @@ class FavoritesViewModel(application: Application, geApiKey: String) : fun insertFavorite(charger: ChargeLocation) { viewModelScope.launch { db.chargeLocationsDao().insert(charger) + db.favoritesDao() + .insert(Favorite(chargerId = charger.id, chargerDataSource = charger.dataSource)) } } - fun deleteFavorite(charger: ChargeLocation) { + fun deleteFavorite(fav: Favorite) { viewModelScope.launch { - db.chargeLocationsDao().delete(charger) + db.favoritesDao().delete(fav) } } } \ No newline at end of file diff --git a/app/src/main/java/net/vonforst/evmap/viewmodel/MapViewModel.kt b/app/src/main/java/net/vonforst/evmap/viewmodel/MapViewModel.kt index ca73ed32..6e059720 100644 --- a/app/src/main/java/net/vonforst/evmap/viewmodel/MapViewModel.kt +++ b/app/src/main/java/net/vonforst/evmap/viewmodel/MapViewModel.kt @@ -222,8 +222,8 @@ class MapViewModel(application: Application, private val state: SavedStateHandle } } - val favorites: LiveData> by lazy { - db.chargeLocationsDao().getAllChargeLocations() + val favorites: LiveData> by lazy { + db.favoritesDao().getAllFavorites() } val searchResult: MutableLiveData by lazy { @@ -279,12 +279,14 @@ class MapViewModel(application: Application, private val state: SavedStateHandle fun insertFavorite(charger: ChargeLocation) { viewModelScope.launch { db.chargeLocationsDao().insert(charger) + db.favoritesDao() + .insert(Favorite(chargerId = charger.id, chargerDataSource = charger.dataSource)) } } - fun deleteFavorite(charger: ChargeLocation) { + fun deleteFavorite(favorite: Favorite) { viewModelScope.launch { - db.chargeLocationsDao().delete(charger) + db.favoritesDao().delete(favorite) } } @@ -310,12 +312,12 @@ class MapViewModel(application: Application, private val state: SavedStateHandle if (filterStatus.value == FILTERS_FAVORITES) { // load favorites from local DB val b = mapPosition.bounds - var chargers = db.chargeLocationsDao().getChargeLocationsInBoundsAsync( + var chargers = db.favoritesDao().getFavoritesInBoundsAsync( b.southwest.latitude, b.northeast.latitude, b.southwest.longitude, b.northeast.longitude - ) as List + ).map { it.charger } as List val clusterDistance = getClusterDistance(mapPosition.zoom) clusterDistance?.let {