mirror of
https://github.com/ev-map/EVMap.git
synced 2026-04-20 06:08:17 -04:00
rework favorites deletion undo logic to fix #304
This commit is contained in:
@@ -227,7 +227,7 @@ class FilterScreen(ctx: CarContext, val session: EVMapSession) : Screen(ctx) {
|
||||
CarToast.makeText(
|
||||
carContext,
|
||||
carContext.getString(
|
||||
R.string.deleted_filterprofile,
|
||||
R.string.deleted_item,
|
||||
it.name
|
||||
),
|
||||
CarToast.LENGTH_SHORT
|
||||
@@ -344,7 +344,7 @@ class EditFiltersScreen(ctx: CarContext) : Screen(ctx) {
|
||||
CarToast.makeText(
|
||||
carContext,
|
||||
carContext.getString(
|
||||
R.string.deleted_filterprofile,
|
||||
R.string.deleted_item,
|
||||
currentProfile.name
|
||||
),
|
||||
CarToast.LENGTH_SHORT
|
||||
|
||||
@@ -28,7 +28,6 @@ import net.vonforst.evmap.databinding.FragmentFavoritesBinding
|
||||
import net.vonforst.evmap.databinding.ItemFavoriteBinding
|
||||
import net.vonforst.evmap.location.FusionEngine
|
||||
import net.vonforst.evmap.location.LocationEngine
|
||||
import net.vonforst.evmap.model.Favorite
|
||||
import net.vonforst.evmap.model.FavoriteWithDetail
|
||||
import net.vonforst.evmap.utils.checkAnyLocationPermission
|
||||
import net.vonforst.evmap.viewmodel.FavoritesViewModel
|
||||
@@ -37,7 +36,6 @@ import net.vonforst.evmap.viewmodel.viewModelFactory
|
||||
class FavoritesFragment : Fragment() {
|
||||
private lateinit var binding: FragmentFavoritesBinding
|
||||
private lateinit var locationEngine: LocationEngine
|
||||
private var toDelete: Favorite? = null
|
||||
private var deleteSnackbar: Snackbar? = null
|
||||
private lateinit var adapter: FavoritesAdapter
|
||||
|
||||
@@ -113,6 +111,32 @@ class FavoritesFragment : Fragment() {
|
||||
binding.swipeRefresh.isRefreshing = false
|
||||
}
|
||||
}
|
||||
|
||||
vm.deletedFavorite.observe(viewLifecycleOwner) { fav ->
|
||||
if (fav == null) {
|
||||
deleteSnackbar?.dismiss()
|
||||
return@observe
|
||||
}
|
||||
val snackbar = Snackbar.make(
|
||||
requireView(),
|
||||
getString(
|
||||
R.string.deleted_item,
|
||||
fav.charger.name
|
||||
),
|
||||
Snackbar.LENGTH_LONG
|
||||
).setAction(R.string.undo) {
|
||||
vm.undoDeletion()
|
||||
}.addCallback(object : Snackbar.Callback() {
|
||||
override fun onDismissed(transientBottomBar: Snackbar?, event: Int) {
|
||||
// if undo was not clicked, actually delete
|
||||
if (event == DISMISS_EVENT_TIMEOUT || event == DISMISS_EVENT_SWIPE) {
|
||||
vm.deletedFavorite.value = null
|
||||
}
|
||||
}
|
||||
})
|
||||
deleteSnackbar = snackbar
|
||||
snackbar.show()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
@@ -127,41 +151,7 @@ class FavoritesFragment : Fragment() {
|
||||
}
|
||||
|
||||
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.favorite
|
||||
|
||||
view?.let {
|
||||
val snackbar = Snackbar.make(
|
||||
it,
|
||||
getString(R.string.deleted_filterprofile, fav.charger.name),
|
||||
Snackbar.LENGTH_LONG
|
||||
).setAction(R.string.undo) {
|
||||
toDelete = null
|
||||
adapter.notifyItemChanged(position)
|
||||
}.addCallback(object : Snackbar.Callback() {
|
||||
override fun onDismissed(transientBottomBar: Snackbar?, event: Int) {
|
||||
// if undo was not clicked, actually delete
|
||||
if (event == DISMISS_EVENT_TIMEOUT || event == DISMISS_EVENT_SWIPE) {
|
||||
actuallyDelete()
|
||||
}
|
||||
}
|
||||
})
|
||||
deleteSnackbar = snackbar
|
||||
snackbar.show()
|
||||
} ?: run {
|
||||
actuallyDelete()
|
||||
}
|
||||
}
|
||||
|
||||
private fun actuallyDelete() {
|
||||
toDelete?.let { vm.deleteFavorite(it) }
|
||||
toDelete = null
|
||||
vm.deleteFavoriteWithUndo(fav)
|
||||
}
|
||||
|
||||
private fun createTouchHelper(): ItemTouchHelper {
|
||||
|
||||
@@ -230,7 +230,7 @@ class FilterProfilesFragment : Fragment() {
|
||||
view?.let {
|
||||
val snackbar = Snackbar.make(
|
||||
it,
|
||||
getString(R.string.deleted_filterprofile, fp.name),
|
||||
getString(R.string.deleted_item, fp.name),
|
||||
Snackbar.LENGTH_LONG
|
||||
).setAction(R.string.undo) {
|
||||
toDelete = null
|
||||
|
||||
@@ -33,7 +33,7 @@ class FavoritesViewModel(application: Application) :
|
||||
MediatorLiveData<Map<Long, Resource<ChargeLocationStatus>>>().apply {
|
||||
addSource(favorites) { favorites ->
|
||||
if (favorites != null) {
|
||||
reloadAvailability()
|
||||
reloadAvailability(forceReload = false)
|
||||
} else {
|
||||
value = null
|
||||
}
|
||||
@@ -41,9 +41,10 @@ class FavoritesViewModel(application: Application) :
|
||||
}
|
||||
}
|
||||
|
||||
fun reloadAvailability(callback: (() -> Unit)? = null) {
|
||||
fun reloadAvailability(forceReload: Boolean = true, callback: (() -> Unit)? = null) {
|
||||
val favorites = favorites.value ?: return
|
||||
val chargers = favorites.map { it.charger }
|
||||
val previous = availability.value
|
||||
|
||||
viewModelScope.launch {
|
||||
val data = hashMapOf<Long, Resource<ChargeLocationStatus>>()
|
||||
@@ -54,8 +55,13 @@ class FavoritesViewModel(application: Application) :
|
||||
|
||||
chargers.map { charger ->
|
||||
async {
|
||||
data[charger.id] = availabilityRepo.getAvailability(charger)
|
||||
availability.value = data
|
||||
if (!forceReload && previous?.get(charger.id)?.status == Status.SUCCESS) {
|
||||
data[charger.id] = previous[charger.id]!!
|
||||
availability.value = data
|
||||
} else {
|
||||
data[charger.id] = availabilityRepo.getAvailability(charger)
|
||||
availability.value = data
|
||||
}
|
||||
}
|
||||
}.awaitAll()
|
||||
callback?.invoke()
|
||||
@@ -117,6 +123,24 @@ class FavoritesViewModel(application: Application) :
|
||||
}
|
||||
}
|
||||
|
||||
val deletedFavorite: MutableLiveData<FavoriteWithDetail?> by lazy {
|
||||
MutableLiveData<FavoriteWithDetail?>()
|
||||
}
|
||||
|
||||
fun deleteFavoriteWithUndo(fav: FavoriteWithDetail) {
|
||||
deletedFavorite.value = fav
|
||||
deleteFavorite(fav.favorite)
|
||||
}
|
||||
|
||||
fun undoDeletion() {
|
||||
deletedFavorite.value?.let {
|
||||
viewModelScope.launch {
|
||||
insertFavorite(it.charger)
|
||||
}
|
||||
deletedFavorite.value = null
|
||||
}
|
||||
}
|
||||
|
||||
fun deleteFavorite(fav: Favorite) {
|
||||
viewModelScope.launch {
|
||||
db.favoritesDao().delete(fav)
|
||||
|
||||
@@ -161,7 +161,7 @@
|
||||
<string name="donation_dialog_detail">EVMap ist kostenlos und Open Source. Über GitHub kann jeder zur Weiterentwicklung der App beitragen. Um die laufenden Kosten für die Datenquellen zu decken, freut sich der Entwickler über Spenden mit einem Betrag deiner Wahl.</string>
|
||||
<string name="chargeprice_donation_dialog_title">Du bist ein richtiger Sparfuchs!</string>
|
||||
<string name="chargeprice_donation_dialog_detail">Anscheinend nutzt du den Preisvergleich sehr gern. Mit einer Spende für EVMap kannst du helfen, die Kosten für den Datenzugriff zu decken.</string>
|
||||
<string name="deleted_filterprofile">„%s” gelöscht</string>
|
||||
<string name="deleted_item">„%s” gelöscht</string>
|
||||
<string name="undo">Rückgängig</string>
|
||||
<string name="rename">Umbenennen</string>
|
||||
<string name="charging_barrierfree">Ohne Vertrag / Registrierung nutzbar</string>
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
<string name="welcome_2_detail">Cela peut également être vu dans \"À propos\" → \"Foire aux questions\"</string>
|
||||
<string name="donation_dialog_title">Merci d\'utiliser EVMap</string>
|
||||
<string name="chargeprice_donation_dialog_title">Vous êtes un vrai chasseur de bonnes affaires !</string>
|
||||
<string name="deleted_filterprofile">\"%s\" supprimé</string>
|
||||
<string name="deleted_item">\"%s\" supprimé</string>
|
||||
<string name="undo">Annuler</string>
|
||||
<string name="rename">Renommer</string>
|
||||
<string name="verified">vérifié</string>
|
||||
|
||||
@@ -144,7 +144,7 @@
|
||||
<string name="save_profile_enter_name">Skriv inn navnet på filterprofilen:</string>
|
||||
<string name="filterprofiles_empty_state">Du har ikke noen lagrede filterprofiler</string>
|
||||
<string name="chargeprice_donation_dialog_title">Du er en sann gjerrigknark.</string>
|
||||
<string name="deleted_filterprofile">Slettet «%s»</string>
|
||||
<string name="deleted_item">Slettet «%s»</string>
|
||||
<string name="charging_barrierfree">Kan brukes uten registrering</string>
|
||||
<string name="welcome_1">Finn kjøretøyladere der du er</string>
|
||||
<string name="welcome_2">Hver laders farge samsvarer med dens høyeste ladeeffekt</string>
|
||||
|
||||
@@ -145,7 +145,7 @@
|
||||
<string name="donation_dialog_title">Bedankt om EVMap te gebruiken</string>
|
||||
<string name="chargeprice_donation_dialog_title">Jij bent een echte koopjeszoeker!</string>
|
||||
<string name="chargeprice_donation_dialog_detail">Blijkbaar maak je dankbaar gebruik van de prijsvergelijkingen. Met een donatie kan je de kosten voor deze data helpen dragen.</string>
|
||||
<string name="deleted_filterprofile">“%s” verwijderd</string>
|
||||
<string name="deleted_item">“%s” verwijderd</string>
|
||||
<string name="undo">Ongedaan maken</string>
|
||||
<string name="rename">Hernoem</string>
|
||||
<plurals name="charge_cards_compatible_num">
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<string name="welcome_2_detail">Também pode encontrar esta informação em \"Sobre\" → \"Perguntas frequentes\"</string>
|
||||
<string name="chargeprice_donation_dialog_title">Você é um verdadeiro caçador de pechinchas!</string>
|
||||
<string name="donation_dialog_title">Obrigado por usar o EVMap</string>
|
||||
<string name="deleted_filterprofile">“%s” removido</string>
|
||||
<string name="deleted_item">“%s” removido</string>
|
||||
<string name="undo">Refazer</string>
|
||||
<string name="rename">Renomear</string>
|
||||
<string name="chargeprice_donation_dialog_detail">Você faz grande uso da comparação de preços. Ajude a cobrir os custos de acesso à informação apoiando o EVMap com uma doação.</string>
|
||||
|
||||
@@ -160,7 +160,7 @@
|
||||
<string name="donation_dialog_detail">EVMap este libera si gratuita. Contributiile pe GitHub sunt apreciate. Pentru a acoperi costurile pentru acces la date, va rugam sa donati orice suma pentru dezvoltator.</string>
|
||||
<string name="chargeprice_donation_dialog_title">Stii sa cauti ofertele cele mai bune!</string>
|
||||
<string name="chargeprice_donation_dialog_detail">Stii sa folosesti optiunea de comparare preturi. Puteti ajuta pentru a acoperi costurile pentru accesul la aceste date donand pentru EVMap.</string>
|
||||
<string name="deleted_filterprofile">“%s” a fost sters</string>
|
||||
<string name="deleted_item">“%s” a fost sters</string>
|
||||
<string name="undo">Anuleaza</string>
|
||||
<string name="rename">Redenumeste</string>
|
||||
<string name="charging_barrierfree">Utilizabile fara inregistrare</string>
|
||||
|
||||
@@ -161,7 +161,7 @@
|
||||
<string name="donation_dialog_detail">EVMap is open source and free of charge. Code contributions on GitHub are much appreciated. To help cover the running costs for data access, please consider donating an amount of your choice to the developer.</string>
|
||||
<string name="chargeprice_donation_dialog_title">You\'re a real bargain hunter!</string>
|
||||
<string name="chargeprice_donation_dialog_detail">You make great use of the price comparison feature. Please help cover the costs for this data by supporting EVMap with a donation.</string>
|
||||
<string name="deleted_filterprofile">Deleted “%s”</string>
|
||||
<string name="deleted_item">Deleted “%s”</string>
|
||||
<string name="undo">Undo</string>
|
||||
<string name="rename">Rename</string>
|
||||
<string name="charging_barrierfree">Usable without registration</string>
|
||||
|
||||
Reference in New Issue
Block a user