ref: v3.7.0
app/src/main/java/xyz/apiote/bimba/czwek/departures/DeparturesViewModel.kt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
// SPDX-FileCopyrightText: Adam Evyčędo // // SPDX-License-Identifier: GPL-3.0-or-later package xyz.apiote.bimba.czwek.departures import android.app.Activity import android.content.Context import android.content.Intent import android.net.Uri import android.util.Log import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import kotlinx.coroutines.MainScope import kotlinx.coroutines.launch import xyz.apiote.bimba.czwek.api.Error import xyz.apiote.bimba.czwek.api.mapHttpError import xyz.apiote.bimba.czwek.repo.FeedInfo import xyz.apiote.bimba.czwek.repo.OfflineRepository import xyz.apiote.bimba.czwek.repo.OnlineRepository import xyz.apiote.bimba.czwek.repo.QrLocation import xyz.apiote.bimba.czwek.repo.StopDepartures import xyz.apiote.bimba.czwek.repo.TrafficResponseException import java.time.LocalDate import java.time.LocalTime class DeparturesViewModel : ViewModel() { private val _departures = MutableLiveData<StopDepartures>() val departures: LiveData<StopDepartures> = _departures private val _error = MutableLiveData<Error>() val error: LiveData<Error> = _error var requestedItemsNumber = 12 var allItemsRequested = false private var feed: FeedInfo? = null var openBottomSheet: DepartureBottomSheet? = null private lateinit var code: String val mutableLinesFilter = MutableLiveData<Map<String, Boolean>>() val linesFilter: LiveData<Map<String, Boolean>> = mutableLinesFilter var showingTerminusArrivals: String? = null // TODO observe in activity, maybe refreshing and not getting departures is enough var startTime: LocalTime = LocalTime.MIN var endTime: LocalTime = LocalTime.MAX // TODO observe in activity, refreshing is not enough var date: LocalDate? = null fun getDepartures(context: Context, date: LocalDate?, force: Boolean) { MainScope().launch { try { if (feed == null) { feed = getFeed(context) code = getCode(context, feed!!) } val repository = OnlineRepository() val stopDepartures = repository.getDepartures( feed!!.id, code, date, context, requestedItemsNumber ) stopDepartures?.let { if (stopDepartures.departures.isEmpty()) { val (string, image) = mapHttpError(44) throw TrafficResponseException(44, "", Error(44, string, image)) } _departures.value = it } } catch (e: TrafficResponseException) { if (!departures.isInitialized || force) { _error.value = e.error } Log.w("Departures", "$e") } } } private suspend fun getFeed(context: Context): FeedInfo { val intent = (context as Activity).intent val repository = OfflineRepository(context) var feeds = repository.getFeeds(context) if (feeds.isNullOrEmpty()) { feeds = OnlineRepository().getFeeds(context) if (feeds != null) { repository.saveFeedCache(context, feeds) } } repository.close() return when (intent.action) { Intent.ACTION_VIEW -> { val feed = feeds?.values?.find { it.qrHost == intent.data?.host } if (feed == null) { if (feeds?.values?.all { it.qrIn == QrLocation.UNKNOWN } == true) { return getFeedOld(intent.data?.host, feeds) ?: throw TrafficResponseException(41) } else { throw TrafficResponseException(41) } } else { return feed } } null -> { val feedID = intent.extras?.getString(DeparturesActivity.FEED_PARAM) feeds?.get(feedID) ?: throw TrafficResponseException(41) } else -> throw TrafficResponseException(41) } } // TODO [after removing FeedsResponseV1] remove this method private fun getFeedOld(host: String?, feeds: Map<String, FeedInfo?>): FeedInfo? { @Suppress("SpellCheckingInspection") return when (host) { "www.peka.poznan.pl" -> feeds["poznan_ztm"] "rj.metropoliaztm.pl" -> feeds["gzm_ztm"] else -> null } } private fun getCode(context: Context, feed: FeedInfo): String { val intent = (context as Activity).intent return when (intent.action) { Intent.ACTION_VIEW -> { when (feed.qrIn) { QrLocation.QUERY -> { intent.data?.getQueryParameter(feed.qrSelector) } QrLocation.PATH -> { feed.qrSelector.toRegex().find(intent.data?.path ?: "")?.value } QrLocation.UNKNOWN -> { getCodeOld(intent.data) } QrLocation.NONE -> { throw TrafficResponseException(41) } } ?: throw TrafficResponseException(41) } null -> intent?.extras?.getString(DeparturesActivity.CODE_PARAM) ?: throw TrafficResponseException(41) else -> throw TrafficResponseException(41) } } // TODO [after removing FeedsResponseV1] remove this method private fun getCodeOld(data: Uri?): String { @Suppress("SpellCheckingInspection") return when (data?.host) { "www.peka.poznan.pl" -> data.getQueryParameter("przystanek") ?: "" "rj.metropoliaztm.pl" -> data.lastPathSegment ?: "" else -> "" } } } |