Author: Adam Pioterek <adam.pioterek@protonmail.ch>
offline timetable
%!v(PANIC=String method: strings: negative Repeat count)
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 249294c52d3e85f02f2c65f0a8458e1e26631220..58ac9e4d29069e199be5ffbd848d746b75ee26e6 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -27,7 +27,6 @@ <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> - <activity android:name=".activities.NoDbActivity" /> <activity android:name=".activities.EditFavouriteActivity" /> <activity android:name=".activities.SettingsActivity" diff --git a/app/src/main/java/ml/adamsprogs/bimba/MessageReceiver.kt b/app/src/main/java/ml/adamsprogs/bimba/MessageReceiver.kt index 81c6bc9779bdbb6cfa7ef4faa87f43af010795a1..c40abec7cc2d1edd1e714a8a4f24dbe6afb6d577 100644 --- a/app/src/main/java/ml/adamsprogs/bimba/MessageReceiver.kt +++ b/app/src/main/java/ml/adamsprogs/bimba/MessageReceiver.kt @@ -30,7 +30,7 @@ } } if (intent?.action == VmService.ACTION_READY) { val departures = intent.getStringArrayListExtra(VmService.EXTRA_DEPARTURES)?.map { Departure.fromString(it) }?.toSet() - val plateId = intent.getSerializableExtra(VmService.EXTRA_PLATE_ID) as Plate.ID + val plateId = intent.getSerializableExtra(VmService.EXTRA_PLATE_ID) as Plate.ID? val stopCode = intent.getSerializableExtra(VmService.EXTRA_STOP_CODE) as String for (listener in onVmListeners) { listener.onVm(departures, plateId, stopCode) @@ -59,6 +59,6 @@ fun onTimetableDownload(result: String?) } interface OnVmListener { - fun onVm(vmDepartures: Set<Departure>?, plateId: Plate.ID, stopCode: String) + fun onVm(vmDepartures: Set<Departure>?, plateId: Plate.ID?, stopCode: String) } } \ No newline at end of file diff --git a/app/src/main/java/ml/adamsprogs/bimba/NetworkStateReceiver.kt b/app/src/main/java/ml/adamsprogs/bimba/NetworkStateReceiver.kt index 70a3a1652bc188fb666fd3841247a52422388b1c..2acd1e1eb9dbb95db986e6907c6e07db549c9792 100644 --- a/app/src/main/java/ml/adamsprogs/bimba/NetworkStateReceiver.kt +++ b/app/src/main/java/ml/adamsprogs/bimba/NetworkStateReceiver.kt @@ -37,9 +37,14 @@ fun onConnectivityChange(connected: Boolean) } companion object { - fun isNetworkAvailable(context: Context): Boolean { - val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager - val activeNetworkInfo = connectivityManager.activeNetworkInfo + lateinit var manager: ConnectivityManager + + fun init(context: Context) { + manager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + } + + fun isNetworkAvailable(): Boolean { + val activeNetworkInfo = manager.activeNetworkInfo return activeNetworkInfo != null && activeNetworkInfo.isConnected } } diff --git a/app/src/main/java/ml/adamsprogs/bimba/ProviderProxy.kt b/app/src/main/java/ml/adamsprogs/bimba/ProviderProxy.kt index 0dcddcffc601cb437e27a01a15286715735d045b..da2601cf9bf8bcf25a49956282b825c3730daff1 100644 --- a/app/src/main/java/ml/adamsprogs/bimba/ProviderProxy.kt +++ b/app/src/main/java/ml/adamsprogs/bimba/ProviderProxy.kt @@ -1,14 +1,13 @@ package ml.adamsprogs.bimba -import android.annotation.SuppressLint import android.content.* import kotlinx.coroutines.experimental.android.UI import kotlinx.coroutines.experimental.* -import ml.adamsprogs.bimba.activities.StopActivity import ml.adamsprogs.bimba.datasources.* import ml.adamsprogs.bimba.models.* import ml.adamsprogs.bimba.models.suggestions.* import java.util.* +import kotlin.collections.HashMap //todo make singleton class ProviderProxy(context: Context? = null) { @@ -16,6 +15,7 @@ private val vmStopsClient = VmClient.getVmStopClient() private var timetable: Timetable = Timetable.getTimetable(context) private var suggestions = emptyList<GtfsSuggestion>() private val requests = HashMap<String, Request>() + var mode = if (timetable.isEmpty()) MODE_VM else MODE_FULL companion object { @@ -25,10 +25,11 @@ } fun getSuggestions(query: String = "", callback: (List<GtfsSuggestion>) -> Unit) { launch(UI) { - suggestions = withContext(DefaultDispatcher) { - getStopSuggestions(query) //+ getLineSuggestions(query) //todo<p:v+1> + bike stations, train stations, &c + val filtered = withContext(DefaultDispatcher) { + suggestions = getStopSuggestions(query) //+ getLineSuggestions(query) //todo<p:v+1> + bike stations, train stations, &c + filterSuggestions(query) } - callback(filterSuggestions(query)) + callback(filtered) } } @@ -65,14 +66,14 @@ } fun getSheds(name: String, callback: (Map<String, Set<String>>) -> Unit) { launch(UI) { - val vmSheds = withContext(DefaultDispatcher) { - vmStopsClient.getSheds(name) - } + val sheds = withContext(DefaultDispatcher) { + val vmSheds = vmStopsClient.getSheds(name) - val sheds = if (vmSheds.isEmpty() and !timetable.isEmpty()) { - timetable.getHeadlinesForStop(name) - } else { - vmSheds + if (vmSheds.isEmpty() and !timetable.isEmpty()) { + timetable.getHeadlinesForStop(name) + } else { + vmSheds + } } callback(sheds) @@ -91,7 +92,7 @@ requests[uuid] = Request(listener, stopSegments) return uuid } - fun subscribeForDepartures(stopCode: String, listener: StopActivity, context: StopActivity): String { + fun subscribeForDepartures(stopCode: String, listener: OnDeparturesReadyListener, context: Context): String { val intent = Intent(context, VmService::class.java) intent.putExtra("stop", stopCode) intent.action = "request" @@ -102,11 +103,35 @@ requests[uuid] = Request(listener, setOf(StopSegment(stopCode, null))) return uuid } - private fun constructSegmentDepartures(stopSegments: Set<StopSegment>): Set<Departure> { - if (timetable.isEmpty()) - return emptySet() - else - TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + private fun constructSegmentDepartures(stopSegments: Set<StopSegment>): Deferred<Map<String, List<Departure>>> { + return async { + if (timetable.isEmpty()) + emptyMap() + else { + timetable.getStopDeparturesBySegments(stopSegments) + } + } + } + + private fun filterDepartures(departures: Map<String, List<Departure>>): List<Departure> { + val now = Calendar.getInstance().secondsAfterMidnight() + val lines = HashMap<String, Int>() + val twoDayDepartures = (timetable.getServiceForToday()?.let { + departures[it] + } ?: emptyList()) + + (timetable.getServiceForTomorrow()?.let { service -> + departures[service]!!.map { it.copy().apply { tomorrow = true } } + } ?: emptyList()) + + return twoDayDepartures + .filter { it.timeTill(now) >= 0 } + .filter { + val existed = lines[it.line] ?: 0 + if (existed < 3) { + lines[it.line] = existed + 1 + true + } else false + } } fun unsubscribeFromDepartures(uuid: String, context: Context) { @@ -119,65 +144,55 @@ timetable = Timetable.getTimetable(context, true) mode = MODE_FULL } - fun getFullTimetable(stopCode: String): Map<Int, List<Departure>> { - val departures = if (timetable.isEmpty()) + fun getFullTimetable(stopCode: String): Map<String, List<Departure>> { + return if (timetable.isEmpty()) emptyMap() else timetable.getStopDepartures(stopCode) - return convertCalendarModes(departures) } - fun getFullTimetable(stopSegments: Set<StopSegment>): Map<Int, List<Departure>> { - val departures = if (timetable.isEmpty()) + fun getFullTimetable(stopSegments: Set<StopSegment>): Map<String, List<Departure>> { + return if (timetable.isEmpty()) emptyMap() else timetable.getStopDeparturesBySegments(stopSegments) - return convertCalendarModes(departures) - } - - @SuppressLint("UseSparseArrays") - private fun convertCalendarModes(raw: Map<String, List<Departure>>): Map<Int, List<Departure>> { - val sunday = timetable.getServiceFor(Calendar.SUNDAY) - val saturday = timetable.getServiceFor(Calendar.SATURDAY) - - val departures = HashMap<Int, List<Departure>>() - departures[StopActivity.MODE_WORKDAYS] = - try { - raw.filter { it.key != saturday && it.key != sunday }.toList()[0].second - } catch (e: IndexOutOfBoundsException) { - ArrayList<Departure>() - } - - departures[StopActivity.MODE_SATURDAYS] = raw[saturday] ?: ArrayList() - departures[StopActivity.MODE_SUNDAYS] = raw[sunday] ?: ArrayList() - - return departures } interface OnDeparturesReadyListener { - fun onDeparturesReady(departures: Set<Departure>, plateId: Plate.ID) + fun onDeparturesReady(departures: List<Departure>, plateId: Plate.ID?) } inner class Request(private val listener: OnDeparturesReadyListener, private val segments: Set<StopSegment>) : MessageReceiver.OnVmListener { private val receiver = MessageReceiver.getMessageReceiver() private val receivedPlates = HashSet<Plate.ID>() + private var cache: Deferred<Map<String, List<Departure>>>? = null + init { - receiver.addOnVmListener(this) + receiver.addOnVmListener(this@Request) + launch(UI) { + cache = constructSegmentDepartures(segments) + } } - override fun onVm(vmDepartures: Set<Departure>?, plateId: Plate.ID, stopCode: String) { - if (segments.any { plateId in it }) { - if (vmDepartures != null) { - listener.onDeparturesReady(vmDepartures, plateId) - if (plateId !in receivedPlates) - receivedPlates.add(plateId) + override fun onVm(vmDepartures: Set<Departure>?, plateId: Plate.ID?, stopCode: String) { + launch(UI) { + if (plateId == null) { + listener.onDeparturesReady(filterDepartures(cache!!.await()), null) } else { - receivedPlates.remove(plateId) - if (receivedPlates.isEmpty()) - listener.onDeparturesReady(constructSegmentDepartures(segments), plateId) + if (segments.any { plateId in it }) { + if (vmDepartures != null) { + listener.onDeparturesReady(vmDepartures.toList(), plateId) + if (plateId !in receivedPlates) + receivedPlates.add(plateId) + } else { + receivedPlates.remove(plateId) + if (receivedPlates.isEmpty()) + listener.onDeparturesReady(filterDepartures(cache!!.await()), null) + } + } } } } diff --git a/app/src/main/java/ml/adamsprogs/bimba/activities/DashActivity.kt b/app/src/main/java/ml/adamsprogs/bimba/activities/DashActivity.kt index 35d8e4cf583bf4dc49428fff87ec963d663ce135..6c66c23ee44a8cd848b46d5f53c4130f8624a468 100644 --- a/app/src/main/java/ml/adamsprogs/bimba/activities/DashActivity.kt +++ b/app/src/main/java/ml/adamsprogs/bimba/activities/DashActivity.kt @@ -59,6 +59,7 @@ setSupportActionBar(toolbar) providerProxy = ProviderProxy(this) timetable = Timetable.getTimetable() + NetworkStateReceiver.init(this) getSuggestions() @@ -75,7 +76,7 @@ //drawer.setCheckedItem(R.id.drawer_home) drawerView.setNavigationItemSelectedListener { item -> when (item.itemId) { R.id.drawer_refresh -> { - startDownloaderService() + startDownloaderService(true) } R.id.drawer_help -> { startActivity(Intent(context, HelpActivity::class.java)) @@ -235,7 +236,7 @@ favouritesList.itemAnimator = DefaultItemAnimator() favouritesList.layoutManager = layoutManager } - override fun onDeparturesReady(departures: Set<Departure>, plateId: Plate.ID) { + override fun onDeparturesReady(departures: List<Departure>, plateId: Plate.ID?) { favouritesList.adapter.notifyDataSetChanged() } @@ -253,8 +254,8 @@ registerReceiver(receiver, filter) receiver.addOnTimetableDownloadListener(context as MessageReceiver.OnTimetableDownloadListener) } - private fun startDownloaderService() { - if (getDefaultSharedPreferences(this).getBoolean("automatic timetable updates", false)) + private fun startDownloaderService(force: Boolean = false) { + if (getDefaultSharedPreferences(this).getBoolean("automatic timetable updates", false) or force) startService(Intent(context, TimetableDownloader::class.java)) } diff --git a/app/src/main/java/ml/adamsprogs/bimba/activities/NoDbActivity.kt b/app/src/main/java/ml/adamsprogs/bimba/activities/NoDbActivity.kt deleted file mode 100644 index 12157af53cd4f527780038c4c7495da4cb8c1c92..0000000000000000000000000000000000000000 --- a/app/src/main/java/ml/adamsprogs/bimba/activities/NoDbActivity.kt +++ /dev/null @@ -1,105 +0,0 @@ -package ml.adamsprogs.bimba.activities - -import android.content.Context -import android.content.Intent -import android.support.v7.app.AppCompatActivity -import android.os.Bundle -import android.content.IntentFilter -import ml.adamsprogs.bimba.* -import kotlinx.android.synthetic.main.activity_nodb.* -import ml.adamsprogs.bimba.datasources.TimetableDownloader -import ml.adamsprogs.bimba.models.Timetable - -class NoDbActivity : AppCompatActivity(), NetworkStateReceiver.OnConnectivityChangeListener, MessageReceiver.OnTimetableDownloadListener { - private val networkStateReceiver = NetworkStateReceiver() - private val timetableDownloadReceiver = MessageReceiver.getMessageReceiver() - private var serviceRunning = false - private var askedForNetwork = false - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.activity_nodb) - val editor = getSharedPreferences("ml.adamsprogs.bimba.prefs", Context.MODE_PRIVATE).edit() - editor.putString("etag", "") - editor.apply() - - var filter = IntentFilter(TimetableDownloader.ACTION_DOWNLOADED) - filter.addCategory(Intent.CATEGORY_DEFAULT) - registerReceiver(timetableDownloadReceiver, filter) - timetableDownloadReceiver.addOnTimetableDownloadListener(this) - - if (!NetworkStateReceiver.isNetworkAvailable(this)) { - askedForNetwork = true - no_db_caption.text = getString(R.string.no_db_connect) - filter = IntentFilter("android.net.conn.CONNECTIVITY_CHANGE") - registerReceiver(networkStateReceiver, filter) - networkStateReceiver.addOnConnectivityChangeListener(this) - } else - downloadTimetable() - - skip_button.setOnClickListener { - /* - val editor = getSharedPreferences("ml.adamsprogs.bimba.prefs", Context.MODE_PRIVATE).edit() - editor.putBoolean(Timetable.ONLY_ONLINE, true) - editor.apply()*/ - startActivity(Intent(this, DashActivity::class.java)) - finish() - } - } - - override fun onResume() { - super.onResume() - try { - val timetable = Timetable.getTimetable(this, true) - if (!timetable.isEmpty()) { - startActivity(Intent(this, DashActivity::class.java)) - finish() - } - } catch (e:Exception){} - var filter = IntentFilter(TimetableDownloader.ACTION_DOWNLOADED) - filter.addCategory(Intent.CATEGORY_DEFAULT) - registerReceiver(timetableDownloadReceiver, filter) - if (!NetworkStateReceiver.isNetworkAvailable(this)) { - askedForNetwork = true - no_db_caption.text = getString(R.string.no_db_connect) - filter = IntentFilter("android.net.conn.CONNECTIVITY_CHANGE") - registerReceiver(networkStateReceiver, filter) - networkStateReceiver.addOnConnectivityChangeListener(this) - } else if (!serviceRunning) - downloadTimetable() - } - - private fun downloadTimetable() { - no_db_caption.text = getString(R.string.no_db_downloading) - serviceRunning = true - intent = Intent(this, TimetableDownloader::class.java) - intent.putExtra(TimetableDownloader.EXTRA_FORCE, true) - startService(intent) - } - - override fun onConnectivityChange(connected: Boolean) { - if (connected && !serviceRunning) - downloadTimetable() - /*if (!connected) - serviceRunning = false*/ - } - - override fun onTimetableDownload(result: String?) { - when (result) { - TimetableDownloader.RESULT_FINISHED -> { - timetableDownloadReceiver.removeOnTimetableDownloadListener(this) - networkStateReceiver.removeOnConnectivityChangeListener(this) - startActivity(Intent(this, DashActivity::class.java)) - finish() - } - else -> no_db_caption.text = getString(R.string.error_try_later) - } - } - - override fun onPause() { - super.onPause() - unregisterReceiver(timetableDownloadReceiver) - if (askedForNetwork) - unregisterReceiver(networkStateReceiver) - } -} diff --git a/app/src/main/java/ml/adamsprogs/bimba/activities/StopActivity.kt b/app/src/main/java/ml/adamsprogs/bimba/activities/StopActivity.kt index e9e1c623ac6479d893b707dd64b4fc7bf1314e99..4fb95b7576a4f220f6a667fc0a1ed2dd38c493fa 100644 --- a/app/src/main/java/ml/adamsprogs/bimba/activities/StopActivity.kt +++ b/app/src/main/java/ml/adamsprogs/bimba/activities/StopActivity.kt @@ -4,8 +4,6 @@ import android.content.* import android.support.design.widget.* import android.os.Bundle import android.view.* -import android.support.v4.app.* -import android.support.v4.view.PagerAdapter import android.support.v4.content.res.ResourcesCompat import android.support.v7.app.AppCompatActivity import android.support.v7.widget.* @@ -19,8 +17,6 @@ import ml.adamsprogs.bimba.models.* import ml.adamsprogs.bimba.models.adapters.DeparturesAdapter class StopActivity : AppCompatActivity(), MessageReceiver.OnTimetableDownloadListener, ProviderProxy.OnDeparturesReadyListener { - - private var sectionsPagerAdapter: SectionsPagerAdapter? = null companion object { const val EXTRA_STOP_CODE = "stopCode" @@ -44,9 +40,10 @@ private var timetableType = "departure" private val context = this private val receiver = MessageReceiver.getMessageReceiver() private lateinit var providerProxy: ProviderProxy - private val departures = HashMap<Plate.ID, Set<Departure>>() - private val fullDepartures = HashMap<Int, List<Departure>>() + private val departures = HashMap<Plate.ID, List<Departure>>() + private val fullDepartures = HashMap<String, List<Departure>>() private lateinit var subscriptionId: String + private lateinit var adapter: DeparturesAdapter private lateinit var sourceType: String @@ -73,14 +70,19 @@ } showFab() - sectionsPagerAdapter = SectionsPagerAdapter(supportFragmentManager, null) + val layoutManager = LinearLayoutManager(this) + departuresList.addItemDecoration(DividerItemDecoration(departuresList.context, layoutManager.orientation)) + departuresList.adapter = DeparturesAdapter(this, emptyList(), true) + adapter = departuresList.adapter as DeparturesAdapter + departuresList.layoutManager = layoutManager - container.adapter = sectionsPagerAdapter - - container.addOnPageChangeListener(TabLayout.TabLayoutOnPageChangeListener(tabs)) - tabs.addOnTabSelectedListener(TabLayout.ViewPagerOnTabSelectedListener(container)) - - selectTodayPage() + departuresList.addOnScrollListener(object : RecyclerView.OnScrollListener() { + override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {} + override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { + updateFabVisibility(dy) + super.onScrolled(recyclerView, dx, dy) + } + }) prepareOnDownloadListener() subscribeForDepartures() @@ -136,26 +138,28 @@ } else favourite!!.subscribeForDepartures(this, context) } - override fun onDeparturesReady(departures: Set<Departure>, plateId: Plate.ID) { - this.departures[plateId] = HashSet() - (this.departures[plateId]as HashSet).addAll(departures) + override fun onDeparturesReady(departures: List<Departure>, plateId: Plate.ID?) { + if (plateId == null) { + this.departures.clear() + this.departures[Plate.ID.dummy] = departures + } else { + this.departures.remove(Plate.ID.dummy) + this.departures[plateId] = departures + } if (timetableType == TIMETABLE_TYPE_FULL) return refreshAdapter() } private fun refreshAdapter() { - if (timetableType == TIMETABLE_TYPE_FULL) - sectionsPagerAdapter!!.departures = fullDepartures - else { - val departures = HashMap<Int, List<Departure>>() + if (timetableType == TIMETABLE_TYPE_FULL) { + // todo adapter.departures = fullDepartures + } else { val now = Calendar.getInstance() - val tab = now.getMode() val seconds = now.secondsAfterMidnight() - departures[tab] = this.departures.flatMap { it.value }.sortedBy { it.timeTill(seconds) } - sectionsPagerAdapter!!.departures = departures + adapter.departures = this.departures.flatMap { it.value }.sortedBy { it.timeTill(seconds) } } - sectionsPagerAdapter!!.notifyDataSetChanged() + adapter.notifyDataSetChanged() } override fun onTimetableDownload(result: String?) { @@ -172,10 +176,6 @@ } providerProxy.refreshTimetable(this) } - private fun selectTodayPage() { - tabs.getTabAt(sectionsPagerAdapter!!.todayTab())!!.select() - } - override fun onCreateOptionsMenu(menu: Menu): Boolean { if (providerProxy.mode == ProviderProxy.MODE_FULL) menuInflater.inflate(R.menu.menu_stop, menu) @@ -189,7 +189,7 @@ if (id == R.id.action_change_type) { if (timetableType == TIMETABLE_TYPE_DEPARTURE) { timetableType = TIMETABLE_TYPE_FULL item.icon = (ResourcesCompat.getDrawable(resources, R.drawable.ic_timetable_departure, this.theme)) - sectionsPagerAdapter?.relativeTime = false + adapter.relativeTime = false if (fullDepartures.isEmpty()) if (sourceType == SOURCE_TYPE_STOP) fullDepartures.putAll(providerProxy.getFullTimetable(stopCode)) @@ -199,7 +199,7 @@ refreshAdapter() } else { timetableType = TIMETABLE_TYPE_DEPARTURE item.icon = (ResourcesCompat.getDrawable(resources, R.drawable.ic_timetable_full, this.theme)) - sectionsPagerAdapter?.relativeTime = true + adapter.relativeTime = true refreshAdapter() } return true @@ -216,74 +216,5 @@ providerProxy.unsubscribeFromDepartures(subscriptionId, this) else favourite!!.unsubscribeFromDepartures(subscriptionId, this) unregisterReceiver(receiver) - } - - inner class SectionsPagerAdapter(fm: FragmentManager, var departures: Map<Int, List<Departure>>?) : FragmentStatePagerAdapter(fm) { - var relativeTime = true - - override fun getItem(position: Int): Fragment { - if (departures == null) - return PlaceholderFragment.newInstance(null, relativeTime) { updateFabVisibility(it) } - if (departures!!.isEmpty()) - return PlaceholderFragment.newInstance(ArrayList(), relativeTime) { updateFabVisibility(it) } - val list: List<Departure> = departures!![position] ?: ArrayList() - return PlaceholderFragment.newInstance(list, relativeTime) { updateFabVisibility(it) } - } - - override fun getCount() = 3 - - override fun getItemPosition(obj: Any): Int { - return PagerAdapter.POSITION_NONE - } - - fun todayTab(): Int { - return Calendar.getInstance().getMode() - } - } - - class PlaceholderFragment : Fragment() { - lateinit var updater: (Int) -> Unit - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - val rootView = inflater.inflate(R.layout.fragment_stop, container, false) - - val layoutManager = LinearLayoutManager(activity) - val departuresList: RecyclerView = rootView.findViewById(R.id.departuresList) - val departures = arguments?.getStringArrayList("departures")?.map { Departure.fromString(it) } - if (departures != null && departures.isNotEmpty()) - departuresList.addItemDecoration(DividerItemDecoration(departuresList.context, layoutManager.orientation)) - - - departuresList.adapter = DeparturesAdapter(activity as Context, departures, - arguments?.get("relativeTime") as Boolean) - departuresList.layoutManager = layoutManager - - departuresList.addOnScrollListener(object : RecyclerView.OnScrollListener() { - override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {} - override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { - updater(dy) - super.onScrolled(recyclerView, dx, dy) - } - }) - return rootView - } - - companion object { - fun newInstance(departures: List<Departure>?, relativeTime: Boolean, updater: (Int) -> Unit): PlaceholderFragment { - val fragment = PlaceholderFragment() - fragment.updater = updater - val args = Bundle() - if (departures != null) { - if (departures.isNotEmpty()) { - val d = ArrayList<String>() - departures.mapTo(d) { it.toString() } - args.putStringArrayList("departures", d) - } else - args.putStringArrayList("departures", ArrayList<String>()) - } - args.putBoolean("relativeTime", relativeTime) - fragment.arguments = args - return fragment - } - } } } diff --git a/app/src/main/java/ml/adamsprogs/bimba/collections/FavouriteStorage.kt b/app/src/main/java/ml/adamsprogs/bimba/collections/FavouriteStorage.kt index 0f6675399ffa2dc686306220cb12ecc95d9b0cc2..2c772c3a6ebe559d74358439cc0db557ae01621e 100644 --- a/app/src/main/java/ml/adamsprogs/bimba/collections/FavouriteStorage.kt +++ b/app/src/main/java/ml/adamsprogs/bimba/collections/FavouriteStorage.kt @@ -114,7 +114,7 @@ fun merge(names: List, context: Context) { if (names.size < 2) return - val newCache = HashMap<Int, ArrayList<Departure>>() + val newCache = HashMap<String, ArrayList<Departure>>() names.forEach { favourites[it]!!.fullTimetable().forEach { if (newCache[it.key] == null) diff --git a/app/src/main/java/ml/adamsprogs/bimba/datasources/TimetableDownloader.kt b/app/src/main/java/ml/adamsprogs/bimba/datasources/TimetableDownloader.kt index 88cb8c58bb4adcab4ec092cfd9ecdd508ab369a3..65495c91d65aefb89125ea4037822a40cdb2369c 100644 --- a/app/src/main/java/ml/adamsprogs/bimba/datasources/TimetableDownloader.kt +++ b/app/src/main/java/ml/adamsprogs/bimba/datasources/TimetableDownloader.kt @@ -31,7 +31,7 @@ if (intent != null) { notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager val prefs = this.getSharedPreferences("ml.adamsprogs.bimba.prefs", Context.MODE_PRIVATE)!! - if (!NetworkStateReceiver.isNetworkAvailable(this)) { + if (!NetworkStateReceiver.isNetworkAvailable()) { sendResult(RESULT_NO_CONNECTIVITY) return } diff --git a/app/src/main/java/ml/adamsprogs/bimba/datasources/VmClient.kt b/app/src/main/java/ml/adamsprogs/bimba/datasources/VmClient.kt index 81820ca45a92a47eb8f3c126748eddcf2721644c..a795febdae7c43b37f01e3c5eea0da38bdef61df 100644 --- a/app/src/main/java/ml/adamsprogs/bimba/datasources/VmClient.kt +++ b/app/src/main/java/ml/adamsprogs/bimba/datasources/VmClient.kt @@ -2,6 +2,7 @@ package ml.adamsprogs.bimba.datasources import com.google.gson.* import kotlinx.coroutines.experimental.* +import ml.adamsprogs.bimba.NetworkStateReceiver import ml.adamsprogs.bimba.models.suggestions.* import okhttp3.* import java.io.IOException @@ -72,6 +73,9 @@ return names.map { StopSuggestion(it, "", "") } } suspend fun makeRequest(method: String, data: String): JsonObject { + if (!NetworkStateReceiver.isNetworkAvailable()) + return JsonObject() + val client = OkHttpClient() val url = "http://www.peka.poznan.pl/vm/method.vm?ts=${Calendar.getInstance().timeInMillis}" val body = RequestBody.create(MediaType.parse("application/x-www-form-urlencoded; charset=UTF-8"), diff --git a/app/src/main/java/ml/adamsprogs/bimba/datasources/VmService.kt b/app/src/main/java/ml/adamsprogs/bimba/datasources/VmService.kt index d9829c86ccecc42d4ab362ade5e6e9a36be5511b..06aa77db42b01d4c0e94ee094007eb064c51e9dd 100644 --- a/app/src/main/java/ml/adamsprogs/bimba/datasources/VmService.kt +++ b/app/src/main/java/ml/adamsprogs/bimba/datasources/VmService.kt @@ -113,7 +113,7 @@ } } private suspend fun downloadVM(stopCode: String) { - if (!NetworkStateReceiver.isNetworkAvailable(this)) { + if (!NetworkStateReceiver.isNetworkAvailable()) { vms[stopCode] = emptySet() sendResult(stopCode, null, null) return diff --git a/app/src/main/java/ml/adamsprogs/bimba/extensions.kt b/app/src/main/java/ml/adamsprogs/bimba/extensions.kt index e398189fe5652b37dd473d40edf9927cf620e31a..a349dc85e76661e7745d7245c11cf93a3d450e75 100644 --- a/app/src/main/java/ml/adamsprogs/bimba/extensions.kt +++ b/app/src/main/java/ml/adamsprogs/bimba/extensions.kt @@ -4,6 +4,7 @@ import android.annotation.SuppressLint import android.content.Context import android.graphics.drawable.Drawable import android.os.Build +import android.text.format.DateFormat import ml.adamsprogs.bimba.activities.StopActivity import java.io.* import java.text.SimpleDateFormat @@ -106,3 +107,23 @@ bytes = read(buffer) } return bytesCopied } + +internal fun Calendar.toNiceString(context: Context, withTime: Boolean = false): String { + val dateFormat = DateFormat.getMediumDateFormat(context) + val timeFormat = DateFormat.getTimeFormat(context) + val now = Calendar.getInstance() + val date = if (get(Calendar.YEAR) == now.get(Calendar.YEAR)) { + when { + get(Calendar.DAY_OF_YEAR) == now.get(Calendar.DAY_OF_YEAR) -> timeFormat.format(time) + now.apply { add(Calendar.DATE, -1) }.get(Calendar.DAY_OF_YEAR) == get(Calendar.DAY_OF_YEAR) -> "Yesterday" + else -> DateFormat.format("d MMM" as CharSequence, this.time) as String + } + } else + dateFormat.format(this.time) + + return if (withTime) { + val time = timeFormat.format(this.time) + "$date, $time" + } else + date +} \ No newline at end of file diff --git a/app/src/main/java/ml/adamsprogs/bimba/models/Departure.kt b/app/src/main/java/ml/adamsprogs/bimba/models/Departure.kt index 35aeba4e97ff3df8a71f5742d7b49f2fb8a2bb8e..9661f529ba9bd5d83a822b47ec43e022c1daa537 100644 --- a/app/src/main/java/ml/adamsprogs/bimba/models/Departure.kt +++ b/app/src/main/java/ml/adamsprogs/bimba/models/Departure.kt @@ -48,33 +48,6 @@ return rollDepartures(departures) }*/ - fun rollDepartures(departures: Map<Int, List<Departure>>): Map<Int, List<Departure>> { //todo<p:2> it'd be nice to roll from tomorrow's real mode (Fri->Sat, Sat->Sun, Sun->Mon) - val rolledDepartures = HashMap<Int, List<Departure>>() - departures.keys.forEach { - val (filtered, isFull) = filterDepartures(departures[it]!!) - if (isFull as Boolean) { - @Suppress("UNCHECKED_CAST") - rolledDepartures[it] = filtered as List<Departure> - } else { - val (filteredTomorrow, _) = filterDepartures(departures[it]!!, 0) - val departuresTomorrow = ArrayList<Departure>() - @Suppress("UNCHECKED_CAST") - (filteredTomorrow as List<Departure>).forEach { - val departure = it.copy() - departure.tomorrow = true - departuresTomorrow.add(departure) - } - val (result, _) = - @Suppress("UNCHECKED_CAST") - filterDepartures((filtered as List<Departure>) + departuresTomorrow) - val now = Calendar.getInstance().secondsAfterMidnight() - @Suppress("UNCHECKED_CAST") - rolledDepartures[it] = (result as List<Departure>).sortedBy { it.timeTill(now) } - } - } - return rolledDepartures - } - fun fromString(string: String): Departure { val array = string.split("|") if (array.size != 9) diff --git a/app/src/main/java/ml/adamsprogs/bimba/models/Favourite.kt b/app/src/main/java/ml/adamsprogs/bimba/models/Favourite.kt index 87df063adc773a421f92d0c37b6d34c110c8af90..ebfe9480bedde0b7c07472f0df0e8cb27b2e01e8 100644 --- a/app/src/main/java/ml/adamsprogs/bimba/models/Favourite.kt +++ b/app/src/main/java/ml/adamsprogs/bimba/models/Favourite.kt @@ -15,8 +15,8 @@ var name: String private set var segments: HashSet<StopSegment> private set - private var fullDepartures: Map<Int, List<Departure>> = HashMap() - private var cache: Set<Departure> = HashSet() + private var fullDepartures: Map<String, List<Departure>> = HashMap() + private var cache: List<Departure> = ArrayList() val size get() = segments.sumBy { @@ -39,17 +39,17 @@ val mapDir = File(parcel.readString()) val mapString = mapDir.readText() - val map = HashMap<Int, List<Departure>>() + val map = HashMap<String, List<Departure>>() mapString.safeSplit("%")!!.forEach { it -> val (k, v) = it.split("#") - map[k.toInt()] = v.split("&").map { Departure.fromString(it) } + map[k] = v.split("&").map { Departure.fromString(it) } } this.fullDepartures = map mapDir.delete() providerProxy = ProviderProxy() } - constructor(name: String, segments: HashSet<StopSegment>, cache: Map<Int, List<Departure>>, context: Context) { + constructor(name: String, segments: HashSet<StopSegment>, cache: Map<String, List<Departure>>, context: Context) { this.fullDepartures = cache this.name = name this.segments = segments @@ -121,14 +121,14 @@ else cache.sortedBy { it.time }[0] - fun fullTimetable(): Map<Int, List<Departure>> { + fun fullTimetable(): Map<String, List<Departure>> { if (fullDepartures.isEmpty()) fullDepartures = providerProxy.getFullTimetable(segments) return fullDepartures } private fun removeFromCache(plate: Plate.ID) { - val map = HashMap<Int, List<Departure>>() + val map = HashMap<String, List<Departure>>() fullDepartures fullDepartures.forEach { it -> map[it.key] = it.value.filter { plate.line != it.line || plate.headsign != it.headsign } @@ -141,7 +141,7 @@ this.listener = listener return providerProxy.subscribeForDepartures(segments, this, context) } - override fun onDeparturesReady(departures: Set<Departure>, plateId: Plate.ID) { + override fun onDeparturesReady(departures: List<Departure>, plateId: Plate.ID?) { cache = departures listener.onDeparturesReady(departures, plateId) } diff --git a/app/src/main/java/ml/adamsprogs/bimba/models/Plate.kt b/app/src/main/java/ml/adamsprogs/bimba/models/Plate.kt index 8fb050a63053bf54097da8d1048f746fe74bae98..d4f7d8cc0dd3dc9e147c63f4182cbc1e009c64e7 100644 --- a/app/src/main/java/ml/adamsprogs/bimba/models/Plate.kt +++ b/app/src/main/java/ml/adamsprogs/bimba/models/Plate.kt @@ -54,6 +54,8 @@ } data class ID(val line: String, val stop: String, val headsign: String) : Serializable { companion object { + val dummy = Plate.ID("", "", "") + fun fromString(string: String): ID { val (line, stop, headsign) = string.split("|") return ID(line, diff --git a/app/src/main/java/ml/adamsprogs/bimba/models/Timetable.kt b/app/src/main/java/ml/adamsprogs/bimba/models/Timetable.kt index f00bd5680b147a5006f477d30922a8ba5b6df40a..f6b9dcfe6915fa4e06b2980cf7d5a341d0e0a96a 100644 --- a/app/src/main/java/ml/adamsprogs/bimba/models/Timetable.kt +++ b/app/src/main/java/ml/adamsprogs/bimba/models/Timetable.kt @@ -3,9 +3,10 @@ import android.annotation.SuppressLint import android.content.Context import android.database.* -import android.database.sqlite.SQLiteCantOpenDatabaseException import android.database.sqlite.SQLiteDatabase import android.database.sqlite.SQLiteException +import android.util.SparseArray +import android.util.SparseBooleanArray import ml.adamsprogs.bimba.* import ml.adamsprogs.bimba.models.gtfs.* import ml.adamsprogs.bimba.models.suggestions.* @@ -41,7 +42,7 @@ val filesDir = context.getSecondaryExternalFilesDir() val dbFile = File(filesDir, "timetable.db") timetable.db = try { SQLiteDatabase.openDatabase(dbFile.path, null, SQLiteDatabase.OPEN_READONLY) - } catch(e: SQLiteException) { + } catch (e: SQLiteException) { null } this.timetable = timetable @@ -101,23 +102,27 @@ fun getHeadlinesForStop(stop: String): Map<String, Set<String>> { val headsigns = HashMap<String, HashSet<String>>() - var cursor = db!!.rawQuery("select stop_code from stops where stop_name = ?", + var cursor = db!!.rawQuery("select stop_id, stop_code from stops where stop_name = ?", arrayOf(stop)) - val stopCodes = ArrayList<String>() + val stopIds = ArrayList<String>() + val stopCodes = SparseArray<String>() while (cursor.moveToNext()) { - stopCodes.add(cursor.getString(0)) + cursor.getInt(0).let { + stopIds.add(it.toString()) + stopCodes.put(it, cursor.getString(1)) + } } cursor.close() - val where = stopCodes.joinToString(" or ", "where ") { "stop_code = ?" } + val where = stopIds.joinToString(" or ", "where ") { "stop_id = ?" } - cursor = db!!.rawQuery("select stop_code, route_id, trip_headsign " + + cursor = db!!.rawQuery("select stop_id, route_id, trip_headsign " + "from stop_times natural join trips " + - where, stopCodes.toTypedArray()) + where, stopIds.toTypedArray()) while (cursor.moveToNext()) { - val stopCode = cursor.getString(0) + val stopCode = stopCodes[cursor.getInt(0)] val route = cursor.getString(1) val headsign = cursor.getString(2) if (stopCode !in headsigns) @@ -193,14 +198,21 @@ return map } - fun getStopDeparturesBySegments(segments: Set<StopSegment>): Map<String, List<Departure>> { + fun getStopDeparturesBySegments(segments: Set<StopSegment>): Map<String, List<Departure>> { // todo optimisation!!! + val stopCodes = HashMap<String, Int>() + var cursor = db!!.rawQuery("select stop_id, stop_code from stops", emptyArray()) + while (cursor.moveToNext()) { + stopCodes[cursor.getString(1)] = cursor.getInt(0) + } + cursor.close() + val wheres = segments.flatMap { - it.plates?.map { - "(stop_code = ${it.stop} and route_id = '${it.line}' and trip_headsign = '${it.headsign}')" - } ?: listOf() + it.plates?.map { plate -> + "(stop_id = ${stopCodes[plate.stop]} and route_id = '${plate.line}' and trip_headsign = '${plate.headsign}')" + } ?: listOf("stop_id = ${stopCodes[it.stop]}") }.joinToString(" or ") - val cursor = db!!.rawQuery("select route_id, service_id, departure_time, " + + cursor = db!!.rawQuery("select route_id, service_id, departure_time, " + "wheelchair_accessible, stop_sequence, trip_id, trip_headsign, route_desc " + "from stop_times natural join trips natural join routes where $wheres", null) @@ -346,37 +358,38 @@ cursor.close() return validTill } - fun getServiceForToday(): String { - val today = JCalendar.getInstance().get(JCalendar.DAY_OF_WEEK) + fun getServiceForToday(): String? { + val today = JCalendar.getInstance() return getServiceFor(today) } - fun getServiceForTomorrow(): String { + fun getServiceForTomorrow(): String? { val tomorrow = JCalendar.getInstance() tomorrow.add(JCalendar.DAY_OF_MONTH, 1) - val tomorrowDoW = tomorrow.get(JCalendar.DAY_OF_WEEK) - return getServiceFor(tomorrowDoW) + return getServiceFor(tomorrow) } - fun getServiceFor(day: Int): String { - val dayColumn = arrayOf("monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday")[((day + 5) % 7)] - val cursor = db!!.rawQuery("select service_id from calendar where $dayColumn = 1", null) + private fun getServiceFor(day: JCalendar): String? { + val dayColumn = arrayOf("monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday")[((day.get(JCalendar.DAY_OF_WEEK) + 5) % 7)] + val cursor = db!!.rawQuery("select service_id from calendar where $dayColumn = 1 and start_date < ? and ? < end_date", arrayOf(day.toIsoDate(), day.toIsoDate())) - val service: Int - cursor.moveToNext() - try { - service = cursor.getInt(0) - cursor.close() - return service.toString() + cursor.moveToFirst() + return try { + cursor.getInt(0).let { + cursor.close() + it.toString() + } } catch (e: CursorIndexOutOfBoundsException) { - throw IllegalArgumentException() + cursor.close() + null } } - fun getPlatesForStop(stop: String): Set<Plate.ID> { + private fun getPlatesForStop(stop: String): Set<Plate.ID> { + val plates = HashSet<Plate.ID>() val cursor = db!!.rawQuery("select route_id, trip_headsign " + - "from stop_times natural join trips where stop_code = ? " + + "from stop_times natural join trips natural join stops where stop_code = ? " + "group by route_id, trip_headsign", arrayOf(stop)) while (cursor.moveToNext()) { @@ -440,6 +453,45 @@ } } return graphs + } + + fun getServiceDescription(service: String, context: Context): String { + val dayNames = SparseArray<String>() + dayNames.put(1, context.getString(R.string.Mon)) + dayNames.put(1, context.getString(R.string.Tue)) + dayNames.put(1, context.getString(R.string.Wed)) + dayNames.put(1, context.getString(R.string.Thu)) + dayNames.put(1, context.getString(R.string.Fri)) + dayNames.put(1, context.getString(R.string.Sat)) + dayNames.put(1, context.getString(R.string.Sun)) + + val cursor = db!!.rawQuery("select * from calendar where service_id = ?", arrayOf(service)) + val days = SparseBooleanArray() + for (i in 1..7) { + days.append(i, cursor.getString(i) == "1") + } + val description = ArrayList<String>() + var start = 0 + + for (i in 1..7) { + if (!days[i] and (start > 0)) { + when { + i - start == 1 -> description.add(dayNames[start]) + i - start == 2 -> description.add("${dayNames[start]}, ${dayNames[start + 1]}") + i - start > 2 -> description.add("${dayNames[start]}–${dayNames[i - 1]}") + } + start = 0 + } + if (days[i] and (start == 0)) + start = i + } + + val startDate = calendarFromIsoD(cursor.getString(8)).toNiceString(context) + val endDate = calendarFromIsoD(cursor.getString(9)).toNiceString(context) + + cursor.close() + + return "${description.joinToString { it }} ($startDate–$endDate)" } class TripGraph { diff --git a/app/src/main/java/ml/adamsprogs/bimba/models/adapters/DeparturesAdapter.kt b/app/src/main/java/ml/adamsprogs/bimba/models/adapters/DeparturesAdapter.kt index 13a2f5765c5ec92fd13aa9ec8f05681c5f3ce0ed..c8915edf9e1b3e8b8444f3661e989ce6f3dc2810 100644 --- a/app/src/main/java/ml/adamsprogs/bimba/models/adapters/DeparturesAdapter.kt +++ b/app/src/main/java/ml/adamsprogs/bimba/models/adapters/DeparturesAdapter.kt @@ -16,7 +16,7 @@ import ml.adamsprogs.bimba.models.Departure import ml.adamsprogs.bimba.rollTime import java.util.* -class DeparturesAdapter(val context: Context, private val departures: List<Departure>?, private val relativeTime: Boolean) : +class DeparturesAdapter(val context: Context, var departures: List<Departure>?, var relativeTime: Boolean) : RecyclerView.Adapter<DeparturesAdapter.ViewHolder>() { companion object { @@ -26,31 +26,32 @@ const val VIEW_TYPE_EMPTY: Int = 2 } override fun getItemCount(): Int { - if (departures == null || departures.isEmpty()) + if (departures == null || departures!!.isEmpty()) return 1 - return departures.size + return departures!!.size } override fun getItemViewType(position: Int): Int { return when { - departures == null -> VIEW_TYPE_EMPTY - departures.isEmpty() -> VIEW_TYPE_LOADING + departures == null -> VIEW_TYPE_LOADING //empty + departures!!.isEmpty() -> VIEW_TYPE_LOADING else -> VIEW_TYPE_CONTENT } } override fun onBindViewHolder(holder: ViewHolder, position: Int) { + // todo migotanie ikon if (departures == null) { return } val line = holder.lineTextView val time = holder.timeTextView val direction = holder.directionTextView - if (departures.isEmpty()) { + if (departures!!.isEmpty()) { time.text = context.getString(R.string.no_departures) return } - val departure = departures[position] + val departure = departures!![position] val now = Calendar.getInstance() val departureTime = Calendar.getInstance().rollTime(departure.time) if (departure.tomorrow) diff --git a/app/src/main/res/layout/activity_stop.xml b/app/src/main/res/layout/activity_stop.xml index cad4b10f71491458bd9cc388e9db098c409a41da..0aefb1bbdb0b77ef1893e948cfa161bb4e1bfb58 100644 --- a/app/src/main/res/layout/activity_stop.xml +++ b/app/src/main/res/layout/activity_stop.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" +<android.support.constraint.ConstraintLayout 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/stop_layout" @@ -7,6 +7,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" tools:context="ml.adamsprogs.bimba.activities.StopActivity"> + <android.support.design.widget.AppBarLayout android:id="@+id/appbar" @@ -27,36 +28,17 @@ app:title="@string/app_name"> </android.support.v7.widget.Toolbar> - <android.support.design.widget.TabLayout - android:id="@+id/tabs" - android:layout_width="match_parent" - android:layout_height="wrap_content"> - <android.support.design.widget.TabItem - android:id="@+id/tabItem" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/tab_workday_text" /> - - <android.support.design.widget.TabItem - android:id="@+id/tabItem4" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/tab_saturday_text" /> - - <android.support.design.widget.TabItem - android:id="@+id/tabItem5" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/tab_sunday_text" /> - </android.support.design.widget.TabLayout> </android.support.design.widget.AppBarLayout> - <android.support.v4.view.ViewPager - android:id="@+id/container" - android:layout_width="match_parent" - android:layout_height="match_parent" - app:layout_behavior="@string/appbar_scrolling_view_behavior" /> + <android.support.v7.widget.RecyclerView + android:id="@+id/departuresList" + android:layout_width="0dp" + android:layout_height="0dp" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/appbar" /> <android.support.design.widget.FloatingActionButton android:id="@+id/fab" @@ -64,6 +46,9 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="end|bottom" android:layout_margin="@dimen/fab_margin" + android:layout_marginBottom="16dp" + android:layout_marginEnd="16dp" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" app:srcCompat="@drawable/ic_favourite" /> - -</android.support.design.widget.CoordinatorLayout> +</android.support.constraint.ConstraintLayout> diff --git a/app/src/main/res/layout/fragment_stop.xml b/app/src/main/res/layout/fragment_stop.xml deleted file mode 100644 index 4cadd826bbf25470cfb9f7417b425acadc0c9722..0000000000000000000000000000000000000000 --- a/app/src/main/res/layout/fragment_stop.xml +++ /dev/null @@ -1,24 +0,0 @@ -<android.support.constraint.ConstraintLayout 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/constraintLayout" - android:layout_width="match_parent" - android:layout_height="match_parent" - tools:context="ml.adamsprogs.bimba.activities.StopActivity$PlaceholderFragment"> - - <!-- todo landscape version --> - <android.support.v7.widget.RecyclerView - android:id="@+id/departuresList" - android:layout_width="368dp" - android:layout_height="516dp" - android:layout_marginBottom="8dp" - android:layout_marginStart="8dp" - android:layout_marginTop="8dp" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="parent" - app:layout_constraintVertical_bias="0.485" - app:layout_constraintEnd_toEndOf="parent" - android:layout_marginEnd="8dp" /> - -</android.support.constraint.ConstraintLayout> \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 59bae428d441c18d3f8b73074d7e738ee2d1c448..fc6cb018421f5b01bd650be84078c6b1522df076 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -90,4 +90,12 @@ key_timetable_source_url <string name="title_timetable_source_url">Timetable source</string> <string name="title_activity_settings">Settings</string> <string name="settings">Settings</string> + + <string name="Mon">Mon</string> + <string name="Tue">Tue</string> + <string name="Wed">Wed</string> + <string name="Thu">Thu</string> + <string name="Fri">Fri</string> + <string name="Sat">Sat</string> + <string name="Sun">Sun</string> </resources> diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 74a1403bc6cf2643facca4506c5f1b23cd015a27..bc754c49306b35a193dcb649178a347de04d8599 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -73,4 +73,11 @@Quelle des Fahrplans <string name="title_activity_settings">Einstellungen</string> <string name="settings">Einstellungen</string> <string name="timetable_decompressing">Fahrplan wird entpackt</string> + <string name="Mon">Mo.</string> + <string name="Tue">Di.</string> + <string name="Wed">Mi.</string> + <string name="Thu">Do.</string> + <string name="Fri">Fr.</string> + <string name="Sat">Sa.</string> + <string name="Sun">So.</string> </resources> diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index e18d6d65bf573b10800637ce426adbf393ea9bda..2f555258b4a51b199fde26df685ba07788e5bc20 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -71,4 +71,11 @@Fonte dell’Orario <string name="title_activity_settings">Impostazioni</string> <string name="settings">Impostazioni</string> <string name="timetable_decompressing">Decomprimendo l’orario</string> + <string name="Mon">lun</string> + <string name="Tue">mar</string> + <string name="Wed">mer</string> + <string name="Thu">gio</string> + <string name="Fri">ven</string> + <string name="Sat">sab</string> + <string name="Sun">dom</string> </resources> diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 3693fadac99d212054a413ec878bf37f093d5c77..82150b353f9a2b6c74446ff0d4415c6b8b4a12db 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -74,4 +74,11 @@Bron van de dienstregeling <string name="title_activity_settings">Instellingen</string> <string name="settings">Instellingen</string> <string name="timetable_decompressing">Bezig met uitpakken van dienstregeling</string> + <string name="Mon">ma</string> + <string name="Tue">di</string> + <string name="Wed">wo</string> + <string name="Thu">do</string> + <string name="Fri">vr</string> + <string name="Sat">za</string> + <string name="Sun">zo</string> </resources> diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 15370f10365138c4426f4c71c7ab5af1bc7370b0..ce9634e0554f906aa47db97f48b47415abfe3742 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -73,4 +73,11 @@Źródło rozkładu <string name="title_activity_settings">Ustawienia</string> <string name="settings">Ustawienia</string> <string name="timetable_decompressing">Rozpakowywanie rozkładu</string> + <string name="Mon">pon.</string> + <string name="Tue">wt.</string> + <string name="Wed">śr.</string> + <string name="Thu">czw.</string> + <string name="Fri">pt.</string> + <string name="Sat">sob.</string> + <string name="Sun">niedz.</string> </resources> \ No newline at end of file