diff --git a/OsmAnd/src/net/osmand/plus/auto/HistoryScreen.kt b/OsmAnd/src/net/osmand/plus/auto/HistoryScreen.kt index e29a1a39a9b..263d980d1b8 100644 --- a/OsmAnd/src/net/osmand/plus/auto/HistoryScreen.kt +++ b/OsmAnd/src/net/osmand/plus/auto/HistoryScreen.kt @@ -1,16 +1,23 @@ package net.osmand.plus.auto +import android.os.AsyncTask import android.text.SpannableString import android.text.Spanned import androidx.car.app.CarContext import androidx.car.app.constraints.ConstraintManager import androidx.car.app.model.* import androidx.core.graphics.drawable.IconCompat +import androidx.lifecycle.DefaultLifecycleObserver +import androidx.lifecycle.LifecycleOwner import net.osmand.data.LatLon import net.osmand.plus.R import net.osmand.plus.helpers.SearchHistoryHelper +import net.osmand.plus.helpers.SearchHistoryHelper.HistoryEntry import net.osmand.plus.search.QuickSearchHelper.SearchHistoryAPI import net.osmand.plus.search.listitems.QuickSearchListItem +import net.osmand.plus.track.data.GPXInfo +import net.osmand.plus.track.helpers.GPXDatabase.GpxDataItem +import net.osmand.plus.track.helpers.GpxDbHelper import net.osmand.search.core.ObjectType import net.osmand.search.core.SearchPhrase import net.osmand.search.core.SearchResult @@ -19,47 +26,38 @@ import net.osmand.util.MapUtils class HistoryScreen( carContext: CarContext, private val settingsAction: Action) : BaseOsmAndAndroidAutoScreen(carContext) { + private lateinit var updateItemsTask: HistoryScreen.UpdateHistoryItemsTask + private lateinit var searchItems: ArrayList + val gpxDbHelper: GpxDbHelper = app.gpxDbHelper + + init { + lifecycle.addObserver(object : DefaultLifecycleObserver { + override fun onCreate(owner: LifecycleOwner) { + super.onCreate(owner) + updateItemsTask = UpdateHistoryItemsTask() + updateItemsTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR) + } + }) + } + + private inner class UpdateHistoryItemsTask : AsyncTask() { + override fun doInBackground(vararg params: Unit?) { + prepareHistoryItems() + } + + override fun onPostExecute(result: Unit?) { + invalidate() + } + } + override fun onGetTemplate(): Template { - val listBuilder = ItemList.Builder() + val templateBuilder = ListTemplate.Builder() val app = app - val historyHelper = SearchHistoryHelper.getInstance(app) - val results = historyHelper.getHistoryEntries(true) - val location = app.mapViewTrackingUtilities.defaultLocation - val resultsSize = results.size - val limitedResults = results.subList(0, resultsSize.coerceAtMost(contentLimit - 1)) - for (result in limitedResults) { - val searchResult = - SearchHistoryAPI.createSearchResult(app, result, SearchPhrase.emptyPhrase()) - val listItem = QuickSearchListItem(app, searchResult) - val pointDescription = result.name - - val title = listItem.name - val icon = CarIcon.Builder( - IconCompat.createWithResource(app, pointDescription.itemIcon)).build() - val rowBuilder = Row.Builder() - .setTitle(title) - .setImage(icon) - .setOnClickListener { onClickHistoryItem(listItem) } - val dist = if (searchResult.location == null) { - 0.0 - } else { - rowBuilder.setMetadata( - Metadata.Builder().setPlace( - Place.Builder( - CarLocation.create( - result.lat, - result.lon)).build()).build()) - MapUtils.getDistance( - result.lat, result.lon, - location.latitude, location.longitude) - } - val address = SpannableString(" ") - val distanceSpan = DistanceSpan.create(TripHelper.getDistance(app, dist)) - address.setSpan(distanceSpan, 0, 1, Spanned.SPAN_INCLUSIVE_INCLUSIVE) - rowBuilder.addText(address) - listBuilder.addItem(rowBuilder.build()) - } + val isLoading = updateItemsTask.status != AsyncTask.Status.FINISHED + if (!isLoading) { + prepareList(templateBuilder) + } val actionStripBuilder = ActionStrip.Builder() actionStripBuilder.addAction( Action.Builder() @@ -69,23 +67,100 @@ class HistoryScreen( carContext, R.drawable.ic_action_search_dark)).build()) .setOnClickListener { openSearch() } .build()) - return ListTemplate.Builder() - .setSingleList(listBuilder.build()) + return templateBuilder + .setLoading(isLoading) .setTitle(app.getString(R.string.shared_string_history)) .setHeaderAction(Action.BACK) .setActionStrip(actionStripBuilder.build()) .build() } + private fun prepareHistoryItems() { + val historyHelper = SearchHistoryHelper.getInstance(app) + val results = historyHelper.getHistoryEntries(true) + val resultsSize = results.size + searchItems = ArrayList() + var limitedResults = results.subList(0, resultsSize.coerceAtMost(contentLimit - 1)) + for (result in limitedResults) { + val searchResult = + SearchHistoryAPI.createSearchResult(app, result, SearchPhrase.emptyPhrase()) + val listItem = QuickSearchListItem(app, searchResult) + if (listItem.searchResult.objectType == ObjectType.GPX_TRACK && listItem.searchResult.location == null) { + var gpxInfo = listItem.searchResult.relatedObject as GPXInfo + var gpxFile = gpxInfo.gpxFile + if (gpxFile == null) { + gpxInfo.file?.let { file -> + val item = gpxDbHelper.getItem(file) { + updateSearchResult( + listItem.searchResult, + it) + } + if (item != null) { + updateSearchResult(listItem.searchResult, item) + } + } + } else { + val analysis = gpxFile.getAnalysis(0) + listItem.searchResult.location = analysis?.latLonStart + } + } + searchItems.add(listItem) + } + } + + private fun updateSearchResult(searchResult: SearchResult, dataItem: GpxDataItem) { + searchResult.location = dataItem.analysis?.latLonStart + } + + private fun prepareList(templateBuilder: ListTemplate.Builder) { + val listBuilder = ItemList.Builder() + val location = app.mapViewTrackingUtilities.defaultLocation + for (item in searchItems) { + if (item.searchResult?.`object` is HistoryEntry) { + val result = item.searchResult?.`object` as HistoryEntry + val pointDescription = result.name + val title = item.name + val icon = CarIcon.Builder( + IconCompat.createWithResource(app, pointDescription.itemIcon)).build() + val rowBuilder = Row.Builder() + .setTitle(title) + .setImage(icon) + .setOnClickListener { onClickHistoryItem(item) } + val dist = if (item.searchResult.location == null) { + 0.0 + } else { + var startLocation = item.searchResult.location + rowBuilder.setMetadata( + Metadata.Builder().setPlace( + Place.Builder( + CarLocation.create( + startLocation.latitude, + startLocation.longitude)).build()).build()) + MapUtils.getDistance( + startLocation.latitude, startLocation.longitude, + location.latitude, location.longitude) + } + val address = SpannableString(" ") + val distanceSpan = DistanceSpan.create(TripHelper.getDistance(app, dist)) + address.setSpan(distanceSpan, 0, 1, Spanned.SPAN_INCLUSIVE_INCLUSIVE) + rowBuilder.addText(address) + listBuilder.addItem(rowBuilder.build()) + } + } + templateBuilder.setSingleList(listBuilder.build()) + } + override fun getConstraintLimitType(): Int { return ConstraintManager.CONTENT_LIMIT_TYPE_PLACE_LIST } private fun onClickHistoryItem(historyItem: QuickSearchListItem) { val result = SearchResult() - result.location = LatLon( - historyItem.searchResult.location.latitude, - historyItem.searchResult.location.longitude) + if (historyItem.searchResult.location != null) { + result.location = LatLon( + historyItem.searchResult.location.latitude, + historyItem.searchResult.location.longitude) + } result.objectType = ObjectType.RECENT_OBJ result.`object` = historyItem.searchResult.`object` openRoutePreview(settingsAction, result)