Bimba.git

commit 9f03a19b03354a2f683dd5cba3d3f3547d4221da

Author: Adam Pioterek <adam.pioterek@protonmail.ch>

refresh stops on main activity

 app/src/main/java/ml/adamsprogs/bimba/MainActivity.kt | 85 ++++-
 app/src/main/java/ml/adamsprogs/bimba/MessageReceiver.kt | 5 
 app/src/main/java/ml/adamsprogs/bimba/NoDbActivity.kt | 20 
 app/src/main/java/ml/adamsprogs/bimba/TimetableDownloader.kt | 23 +
 app/src/main/res/layout/activity_main.xml | 53 ++-
 app/src/main/res/values-pl/strings.xml | 8 
 app/src/main/res/values/strings.xml | 9 


diff --git a/app/src/main/java/ml/adamsprogs/bimba/MainActivity.kt b/app/src/main/java/ml/adamsprogs/bimba/MainActivity.kt
index 4040505398c178bba2b0bde1bfc4ecbc381431dc..bfc9c3d3ae32ab816dbcf8aa000f8bfd6e43bd5f 100644
--- a/app/src/main/java/ml/adamsprogs/bimba/MainActivity.kt
+++ b/app/src/main/java/ml/adamsprogs/bimba/MainActivity.kt
@@ -4,55 +4,52 @@ import android.content.Intent
 import android.content.IntentFilter
 import android.os.*
 import android.support.design.widget.Snackbar
-import android.support.v7.app.AppCompatActivity
-import android.support.v7.app.AppCompatDelegate
+import android.support.v7.app.*
 import android.text.Html
 import android.view.View
 import com.arlib.floatingsearchview.FloatingSearchView
 import com.arlib.floatingsearchview.suggestions.model.SearchSuggestion
-import ml.adamsprogs.bimba.models.StopSuggestion
-import ml.adamsprogs.bimba.models.Timetable
+import ml.adamsprogs.bimba.models.*
 import kotlin.concurrent.thread
 import android.app.Activity
+import android.content.Context
+import android.support.v4.widget.SwipeRefreshLayout
+import android.util.Log
 import android.view.inputmethod.InputMethodManager
 
 
-class MainActivity : AppCompatActivity(), MessageReceiver.OnTimetableDownloadListener {
-    val listener = this
-    val receiver  = MessageReceiver()
-    lateinit var layout: View
+class MainActivity : AppCompatActivity(), MessageReceiver.OnTimetableDownloadListener, SwipeRefreshLayout.OnRefreshListener {
+    val context: Context = this
+    val receiver = MessageReceiver()
     lateinit var timetable: Timetable
     var stops: ArrayList<StopSuggestion>? = null
+    lateinit var swipeRefreshLayout: SwipeRefreshLayout
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
         setContentView(R.layout.activity_main)
         AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO)
 
-        layout = findViewById(R.id.main_layout)
-        val context = this
+        prepareSwipeLayout()
+
+        prepareOnDownloadListener()
+        startDownloaderService()
 
-        val filter = IntentFilter("ml.adamsprogs.bimba.timetableDownloaded")
-        filter.addCategory(Intent.CATEGORY_DEFAULT)
-        registerReceiver(receiver, filter)
-        receiver.addOnTimetableDownloadListener(listener)
-        startService(Intent(context, TimetableDownloader::class.java))
+        getStops()
 
-        timetable = Timetable(this)
-        stops = timetable.getStops()
         val searchView = findViewById(R.id.search_view) as FloatingSearchView
 
         searchView.setOnQueryChangeListener({ _, newQuery ->
             thread {
                 val newStops = stops!!.filter { deAccent(it.body.split("\n")[0]).contains(newQuery, true) }
-                runOnUiThread { searchView.swapSuggestions (newStops)}
+                runOnUiThread { searchView.swapSuggestions(newStops) }
             }
         })
 
         searchView.setOnSearchListener(object : FloatingSearchView.OnSearchListener {
             override fun onSuggestionClicked(searchSuggestion: SearchSuggestion) {
                 val imm = context.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
-                var view = context.currentFocus
+                var view = (context as MainActivity).currentFocus
                 if (view == null) {
                     view = View(context)
                 }
@@ -61,6 +58,7 @@                 intent = Intent(context, StopActivity::class.java)
                 intent.putExtra("stop", (searchSuggestion as StopSuggestion).id)
                 startActivity(intent)
             }
+
             override fun onSearchAction(query: String) {
             }
         })
@@ -70,19 +68,48 @@             val suggestion = item as StopSuggestion
             val text = suggestion.body.split("\n")
             val t = "<small><font color=\"#a0a0a0\">" + text[1] + "</font></small>"
             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
-                textView.text = Html.fromHtml(text[0]+"<br/>"+t, Html.FROM_HTML_MODE_LEGACY)
+                textView.text = Html.fromHtml(text[0] + "<br/>" + t, Html.FROM_HTML_MODE_LEGACY)
             } else {
                 @Suppress("DEPRECATION")
-                textView.text = Html.fromHtml(text[0]+"<br/>"+t)
+                textView.text = Html.fromHtml(text[0] + "<br/>" + t)
             }
         }
 
         //todo searchView.attachNavigationDrawerToMenuButton(mDrawerLayout)
     }
 
+    private fun getStops() {
+        timetable = Timetable(this)
+        stops = timetable.getStops()
+    }
+
+    private fun prepareOnDownloadListener() {
+        val filter = IntentFilter("ml.adamsprogs.bimba.timetableDownloaded")
+        filter.addCategory(Intent.CATEGORY_DEFAULT)
+        registerReceiver(receiver, filter)
+        receiver.addOnTimetableDownloadListener(context as MessageReceiver.OnTimetableDownloadListener)
+    }
+
+    private fun startDownloaderService() {
+        startService(Intent(context, TimetableDownloader::class.java))
+    }
+
+    private fun prepareSwipeLayout() {
+        swipeRefreshLayout = findViewById(R.id.swipeRefreshLayout) as SwipeRefreshLayout
+        swipeRefreshLayout.isEnabled = true
+        swipeRefreshLayout.setOnRefreshListener(this)
+        swipeRefreshLayout.setColorSchemeResources(R.color.colorAccent, R.color.colorPrimary)
+    }
+
+    override fun onRefresh() {
+        swipeRefreshLayout.isRefreshing = true
+        Log.i("Refresh", "Downloading")
+        startDownloaderService()
+    }
+
     override fun onDestroy() {
         super.onDestroy()
-        receiver.removeOnTimetableDownloadListener(listener)
+        receiver.removeOnTimetableDownloadListener(context as MessageReceiver.OnTimetableDownloadListener)
         unregisterReceiver(receiver)
     }
 
@@ -99,9 +126,19 @@         result = result.replace('ń', 'n')
         return result
     }
 
-    override fun onTimetableDownload() {
+    override fun onTimetableDownload(result: String?) {
+        Log.i("Refresh", "downloaded: $result")
+        val message: String
+        when (result) {
+            "downloaded" -> message = getString(R.string.timetable_downloaded)
+            "no connectivity" -> message = getString(R.string.no_connectivity)
+            "up-to-date" -> message = getString(R.string.timetable_up_to_date)
+            "validity failed" -> message = getString(R.string.validity_failed)
+            else -> message = getString(R.string.error_try_later)
+        }
         timetable.refresh()
         stops = timetable.getStops()
-        Snackbar.make(layout, getString(R.string.timetable_downloaded), Snackbar.LENGTH_LONG).show()
+        Snackbar.make(swipeRefreshLayout, message, Snackbar.LENGTH_LONG).show()
+        swipeRefreshLayout.isRefreshing = false
     }
 }




diff --git a/app/src/main/java/ml/adamsprogs/bimba/MessageReceiver.kt b/app/src/main/java/ml/adamsprogs/bimba/MessageReceiver.kt
index 4e2c81f4ef4cb432099ea2c7d7733b1ccc833583..0203994b9671acb43fbc21958b3f3800de22dd4a 100644
--- a/app/src/main/java/ml/adamsprogs/bimba/MessageReceiver.kt
+++ b/app/src/main/java/ml/adamsprogs/bimba/MessageReceiver.kt
@@ -8,8 +8,9 @@ class MessageReceiver: BroadcastReceiver() {
     val onTimetableDownloadListeners: HashSet<OnTimetableDownloadListener> = HashSet()
 
     override fun onReceive(context: Context?, intent: Intent?) {
+        val result = intent?.getStringExtra("result")
         for (listener in onTimetableDownloadListeners) {
-            listener.onTimetableDownload()
+            listener.onTimetableDownload(result)
         }
     }
 
@@ -22,6 +23,6 @@         onTimetableDownloadListeners.remove(listener)
     }
 
     interface OnTimetableDownloadListener {
-        fun onTimetableDownload()
+        fun onTimetableDownload(result: String?)
     }
 }
\ No newline at end of file




diff --git a/app/src/main/java/ml/adamsprogs/bimba/NoDbActivity.kt b/app/src/main/java/ml/adamsprogs/bimba/NoDbActivity.kt
index 177140d77dbe6c1a5c8a66e159318a03b6cd7ae1..8b31c19d7a91d7e5552a76bbb774cff692b123f1 100644
--- a/app/src/main/java/ml/adamsprogs/bimba/NoDbActivity.kt
+++ b/app/src/main/java/ml/adamsprogs/bimba/NoDbActivity.kt
@@ -11,6 +11,7 @@ class NoDbActivity : AppCompatActivity(), NetworkStateReceiver.OnConnectivityChangeListener, MessageReceiver.OnTimetableDownloadListener {
     val networkStateReceiver = NetworkStateReceiver()
     val timetableDownloadReceiver = MessageReceiver()
     var serviceRunning = false
+    var askedForNetwork = false
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
@@ -22,6 +23,7 @@         registerReceiver(timetableDownloadReceiver, filter)
         timetableDownloadReceiver.addOnTimetableDownloadListener(this)
 
         if (!isNetworkAvailable(this)) {
+            askedForNetwork = true
             (findViewById(R.id.noDbCaption) as TextView).text = getString(R.string.no_db_connect)
             filter = IntentFilter("android.net.conn.CONNECTIVITY_CHANGE")
             registerReceiver(networkStateReceiver, filter)
@@ -45,16 +47,22 @@         /*if (!connected)
             serviceRunning = false*/
     }
 
-    override fun onTimetableDownload() {
-        timetableDownloadReceiver.removeOnTimetableDownloadListener(this)
-        networkStateReceiver.removeOnConnectivityChangeListener(this)
-        startActivity(Intent(this, MainActivity::class.java))
-        finish()
+    override fun onTimetableDownload(result: String?) {
+        when (result) {
+            "downloaded" -> {
+                timetableDownloadReceiver.removeOnTimetableDownloadListener(this)
+                networkStateReceiver.removeOnConnectivityChangeListener(this)
+                startActivity(Intent(this, MainActivity::class.java))
+                finish()
+            }
+            else -> (findViewById(R.id.noDbCaption) as TextView).text = getString(R.string.error_try_later)
+        }
     }
 
     override fun onPause() {
         super.onPause()
         unregisterReceiver(timetableDownloadReceiver)
-        unregisterReceiver(networkStateReceiver)
+        if (askedForNetwork)
+            unregisterReceiver(networkStateReceiver)
     }
 }




diff --git a/app/src/main/java/ml/adamsprogs/bimba/TimetableDownloader.kt b/app/src/main/java/ml/adamsprogs/bimba/TimetableDownloader.kt
index b7187dcc8a173bb5893a41b4d6bbdbc31299adc7..f933bfbf80b424de1a383826236afad73e2cd5ec 100644
--- a/app/src/main/java/ml/adamsprogs/bimba/TimetableDownloader.kt
+++ b/app/src/main/java/ml/adamsprogs/bimba/TimetableDownloader.kt
@@ -23,8 +23,10 @@
         if (intent != null) {
             notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
             val prefs = this.getSharedPreferences("ml.adamsprogs.bimba.prefs", Context.MODE_PRIVATE)!!
-            if (!isNetworkAvailable(this))
+            if (!isNetworkAvailable(this)) {
+                sendResult("no connectivity")
                 return
+            }
             val metadataUrl = URL("https://adamsprogs.ml/w/_media/programmes/bimba/timetable.db.meta")
             var httpCon = metadataUrl.openConnection() as HttpURLConnection
             if (httpCon.responseCode != HttpURLConnection.HTTP_OK)
@@ -35,8 +37,10 @@             val lastModified = reader.readLine()
             val checksum = reader.readLine()
             size = Integer.parseInt(reader.readLine()) / 1024
             val currentLastModified = prefs.getString("timetableLastModified", "1979-10-12T00:00")
-            if (lastModified <= currentLastModified && !intent.getBooleanExtra("force", false))
+            if (lastModified <= currentLastModified && !intent.getBooleanExtra("force", false)) {
+                sendResult("up-to-date")
                 return
+            }
             Log.i("Downloader", "timetable is newer ($lastModified > $currentLastModified)")
 
             notify(0)
@@ -56,16 +60,22 @@                 file.renameTo(File("timetable.db"))
                 val prefsEditor = prefs.edit()
                 prefsEditor.putString("timetableLastModified", lastModified)
                 prefsEditor.apply()
-                val broadcastIntent = Intent()
-                broadcastIntent.action = "ml.adamsprogs.bimba.timetableDownloaded"
-                broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT)
-                sendBroadcast(broadcastIntent)
+                sendResult("downloaded")
             } else {
                 Log.i("Downloader", "downloaded but is wrong")
+                sendResult("validity failed")
             }
 
             cancelNotification()
         }
+    }
+
+    private fun sendResult(result: String) {
+        val broadcastIntent = Intent()
+        broadcastIntent.action = "ml.adamsprogs.bimba.timetableDownloaded"
+        broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT)
+        broadcastIntent.putExtra("result", result)
+        sendBroadcast(broadcastIntent)
     }
 
     private fun notify(progress: Int) {
@@ -100,7 +110,6 @@                 md.update(buf, 0, len)
                 out.write(buf, 0, len)
                 lenSum += len.toFloat() / 1024.0f
                 notify(lenSum.toInt())
-                Log.i("Downloader", "downloading $len B: $lenSum KiB")
             }
             out.close()
         } catch (e: Exception) {




diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 739666dc2ed00f729c50555a9a7681dd3ee1cce6..50db680552ef62dca20d5cf36e3e3e65aa3101db 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -1,21 +1,44 @@
 <?xml version="1.0" encoding="utf-8"?>
-<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<android.support.v4.widget.SwipeRefreshLayout 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/swipeRefreshLayout"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    tools:context="ml.adamsprogs.bimba.MainActivity"
-    android:id="@+id/main_layout">
-    <com.arlib.floatingsearchview.FloatingSearchView
-        android:id="@+id/search_view"
+    tools:context="ml.adamsprogs.bimba.MainActivity">
+
+    <android.support.constraint.ConstraintLayout
+        android:id="@+id/main_layout"
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        app:floatingSearch_searchBarMarginLeft="16dp"
-        app:floatingSearch_searchBarMarginTop="16dp"
-        app:floatingSearch_searchBarMarginRight="16dp"
-        app:floatingSearch_searchHint="Search..."
-        app:floatingSearch_suggestionsListAnimDuration="250"
-        app:floatingSearch_showSearchKey="false"
-        app:floatingSearch_leftActionMode="showHamburger"
-        app:floatingSearch_close_search_on_keyboard_dismiss="true"/>
-</android.support.constraint.ConstraintLayout>
+        android:layout_height="match_parent">
+
+        <com.arlib.floatingsearchview.FloatingSearchView
+            android:id="@+id/search_view"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            app:floatingSearch_close_search_on_keyboard_dismiss="true"
+            app:floatingSearch_leftActionMode="showHamburger"
+            app:floatingSearch_searchBarMarginLeft="16dp"
+            app:floatingSearch_searchBarMarginRight="16dp"
+            app:floatingSearch_searchBarMarginTop="16dp"
+            app:floatingSearch_searchHint="@string/search_placeholder"
+            app:floatingSearch_showSearchKey="false"
+            app:floatingSearch_suggestionsListAnimDuration="250" />
+
+
+        <android.support.v7.widget.RecyclerView
+            android:id="@+id/favouritesList"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:scrollbars="none"
+            android:layout_marginTop="128dp"
+            app:layout_constraintTop_toTopOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            android:layout_marginStart="8dp"
+            app:layout_constraintEnd_toEndOf="parent"
+            android:layout_marginEnd="8dp"
+            app:layout_constraintBottom_toBottomOf="parent"
+            android:layout_marginBottom="8dp" />
+
+    </android.support.constraint.ConstraintLayout>
+</android.support.v4.widget.SwipeRefreshLayout>
\ 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 a56f3fca135b861588ef4cdbc093a4017ccc9e19..54b6e3bedc3affa2cc01ff48b8811d78aa25f21a 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -11,8 +11,13 @@     departure type (timetable, VM)
     <string name="departure_in">In %1$s minutes</string>
     <string name="departure_to">→ %1$s</string>
     <string name="departure_at">At %1$s</string>
-    <string name="no_database_background">no database background</string>
+    <string name="no_database_background" translatable="false">no database background</string>
     <string name="no_db_connect">Connect to the Internet to download the timetable</string>
-    <string name="no_db_downloading">Timetable is being downloaded</string>
+    <string name="no_db_downloading">Timetable is being downloaded…</string>
     <string name="timetable_downloading">Downloading timetable</string>
+    <string name="search_placeholder">Search…</string>
+    <string name="no_connectivity">No connectivity – can’t update timetable</string>
+    <string name="timetable_up_to_date">Timetable is up-to-date</string>
+    <string name="validity_failed">Downloaded timetable is corrupted – can’t update</string>
+    <string name="error_try_later">Error. Try again later</string>
 </resources>




diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml
index 0d3d7bccd9c2fa4b602dfce5e810aa190f7ef38c..2e69341c19dd00da266a34b134c8f252a79be450 100644
--- a/app/src/main/res/values-pl/strings.xml
+++ b/app/src/main/res/values-pl/strings.xml
@@ -9,4 +9,12 @@     Typ
     <string name="departure_in">Za %1$s minut</string>
     <string name="departure_at">O %1$s</string>
     <string name="departure_to">→ %1$s</string>
+    <string name="no_db_connect">Połącz się z Internetem aby pobrać rozkład</string>
+    <string name="no_db_downloading">Pobieranie rozkładu…</string>
+    <string name="timetable_downloading">Pobieranie rozkładu…</string>
+    <string name="search_placeholder">Szukaj…</string>
+    <string name="timetable_up_to_date">Rozkład jest aktualny</string>
+    <string name="validity_failed">Pobrany rozkład jest uszkodzony – nie można zaktualizować</string>
+    <string name="no_connectivity">Brak połączenia z Internetem – nie można zaktualizować rozkładu</string>
+    <string name="error_try_later">Błąd. Spróbuj ponownie później</string>
 </resources>
\ No newline at end of file