Bimba.git

commit d7071235c2970d33f1debf61d8994e1fb2aa7bd3

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

refreshing timetable every 15s

 app/src/main/AndroidManifest.xml | 12 
  | 6 
 app/src/main/java/ml/adamsprogs/bimba/MessageReceiver.kt | 35 
  | 3 
  | 6 
  | 115 
 app/src/main/java/ml/adamsprogs/bimba/VmClient.kt | 31 
 app/src/main/java/ml/adamsprogs/bimba/models/DeparturesAdapter.kt | 47 
 app/src/main/java/ml/adamsprogs/bimba/models/Timetable.kt | 4 
 app/src/main/res/layout/activity_main.xml | 2 
 app/src/main/res/layout/activity_stop.xml | 2 
 app/src/main/res/layout/fragment_stop.xml | 2 
 app/src/main/res/menu/menu_stop.xml | 2 


diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 84217dda388216e606314352638831a0d2d80baa..d39599789d29518ca69c703776b72dba55903f21 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -11,18 +11,18 @@         android:icon="@drawable/logo"
         android:label="@string/app_name"
         android:supportsRtl="true"
         android:theme="@style/AppTheme">
-        <activity android:name=".MainActivity" />
+        <activity android:name=".activities.MainActivity" />
 
         <service
             android:name=".TimetableDownloader"
             android:exported="false" />
 
         <activity
-            android:name=".StopActivity"
+            android:name=".activities.StopActivity"
             android:label="@string/title_activity_stop"
             android:theme="@style/AppTheme" />
         <activity
-            android:name=".SplashActivity"
+            android:name=".activities.SplashActivity"
             android:theme="@style/SplashTheme">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
@@ -30,7 +30,11 @@
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
-        <activity android:name=".NoDbActivity" />
+        <activity android:name=".activities.NoDbActivity" />
+
+        <service
+            android:name=".VmClient"
+            android:exported="false"></service>
     </application>
 
 </manifest>
\ No newline at end of file




diff --git a/app/src/main/java/ml/adamsprogs/bimba/MainActivity.kt b/app/src/main/java/ml/adamsprogs/bimba/MainActivity.kt
deleted file mode 100644
index bfc9c3d3ae32ab816dbcf8aa000f8bfd6e43bd5f..0000000000000000000000000000000000000000
--- a/app/src/main/java/ml/adamsprogs/bimba/MainActivity.kt
+++ /dev/null
@@ -1,144 +0,0 @@
-package ml.adamsprogs.bimba
-
-import android.content.Intent
-import android.content.IntentFilter
-import android.os.*
-import android.support.design.widget.Snackbar
-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.*
-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, 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)
-
-        prepareSwipeLayout()
-
-        prepareOnDownloadListener()
-        startDownloaderService()
-
-        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) }
-            }
-        })
-
-        searchView.setOnSearchListener(object : FloatingSearchView.OnSearchListener {
-            override fun onSuggestionClicked(searchSuggestion: SearchSuggestion) {
-                val imm = context.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
-                var view = (context as MainActivity).currentFocus
-                if (view == null) {
-                    view = View(context)
-                }
-                imm.hideSoftInputFromWindow(view.windowToken, 0)
-                intent = Intent(context, StopActivity::class.java)
-                intent.putExtra("stop", (searchSuggestion as StopSuggestion).id)
-                startActivity(intent)
-            }
-
-            override fun onSearchAction(query: String) {
-            }
-        })
-
-        searchView.setOnBindSuggestionCallback { _, _, textView, item, _ ->
-            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)
-            } else {
-                @Suppress("DEPRECATION")
-                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(context as MessageReceiver.OnTimetableDownloadListener)
-        unregisterReceiver(receiver)
-    }
-
-    fun deAccent(str: String): String {
-        var result = str.replace('ę', 'e')
-        result = result.replace('ó', 'o')
-        result = result.replace('ą', 'a')
-        result = result.replace('ś', 's')
-        result = result.replace('ł', 'l')
-        result = result.replace('ż', 'ż')
-        result = result.replace('ź', 'ź')
-        result = result.replace('ć', 'ć')
-        result = result.replace('ń', 'n')
-        return result
-    }
-
-    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(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 0203994b9671acb43fbc21958b3f3800de22dd4a..bc53ddb2579afcedda4f27b10e3ba572a7c31ec5 100644
--- a/app/src/main/java/ml/adamsprogs/bimba/MessageReceiver.kt
+++ b/app/src/main/java/ml/adamsprogs/bimba/MessageReceiver.kt
@@ -3,14 +3,31 @@
 import android.content.BroadcastReceiver
 import android.content.Context
 import android.content.Intent
+import ml.adamsprogs.bimba.models.Departure
+import ml.adamsprogs.bimba.models.fromString
 
 class MessageReceiver: BroadcastReceiver() {
     val onTimetableDownloadListeners: HashSet<OnTimetableDownloadListener> = HashSet()
+    val onVmListeners: HashSet<OnVmListener> = HashSet()
 
     override fun onReceive(context: Context?, intent: Intent?) {
-        val result = intent?.getStringExtra("result")
-        for (listener in onTimetableDownloadListeners) {
-            listener.onTimetableDownload(result)
+        if (intent?.action == "ml.adamsprogs.bimba.timetableDownloaded") {
+            val result = intent.getStringExtra("result")
+            for (listener in onTimetableDownloadListeners) {
+                listener.onTimetableDownload(result)
+            }
+        }
+        if (intent?.action == "ml.adamsprogs.bimba.departuresCreated") {
+            val workdays = intent.getStringArrayListExtra("workdays").map { fromString(it)} as ArrayList<Departure>
+            val saturdays = intent.getStringArrayListExtra("saturdays").map { fromString(it)} as ArrayList<Departure>
+            val sundays = intent.getStringArrayListExtra("sundays").map { fromString(it)} as ArrayList<Departure>
+            val departures = HashMap<String, ArrayList<Departure>>()
+            departures["workdays"] = workdays
+            departures["saturdays"] = saturdays
+            departures["sundays"] = sundays
+            for (listener in onVmListeners) {
+                listener.onVm(departures)
+            }
         }
     }
 
@@ -22,7 +39,19 @@     fun removeOnTimetableDownloadListener(listener: OnTimetableDownloadListener) {
         onTimetableDownloadListeners.remove(listener)
     }
 
+    fun addOnVmListener(listener: OnVmListener) {
+        onVmListeners.add(listener)
+    }
+
+    fun removeOnVmListener(listener: OnVmListener) {
+        onVmListeners.remove(listener)
+    }
+
     interface OnTimetableDownloadListener {
         fun onTimetableDownload(result: String?)
+    }
+
+    interface OnVmListener {
+        fun onVm(departures: HashMap<String, ArrayList<Departure>>)
     }
 }
\ 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
deleted file mode 100644
index 8b31c19d7a91d7e5552a76bbb774cff692b123f1..0000000000000000000000000000000000000000
--- a/app/src/main/java/ml/adamsprogs/bimba/NoDbActivity.kt
+++ /dev/null
@@ -1,68 +0,0 @@
-package ml.adamsprogs.bimba
-
-import android.content.Intent
-import android.support.v7.app.AppCompatActivity
-import android.os.Bundle
-import android.content.IntentFilter
-import android.widget.TextView
-
-
-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)
-        setContentView(R.layout.activity_nodb)
-        var filter: IntentFilter
-        filter = IntentFilter("ml.adamsprogs.bimba.timetableDownloaded")
-        filter.addCategory(Intent.CATEGORY_DEFAULT)
-        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)
-            networkStateReceiver.addOnConnectivityChangeListener(this)
-        } else
-            downloadTimetable()
-    }
-
-    fun downloadTimetable() {
-        (findViewById(R.id.noDbCaption) as TextView).text = getString(R.string.no_db_downloading)
-        serviceRunning = true
-        intent = Intent(this, TimetableDownloader::class.java)
-        intent.putExtra("force", true)
-        startService(intent)
-    }
-
-    override fun onConnectivityChange(connected: Boolean) {
-        if (connected && !serviceRunning)
-            downloadTimetable()
-        /*if (!connected)
-            serviceRunning = false*/
-    }
-
-    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)
-        if (askedForNetwork)
-            unregisterReceiver(networkStateReceiver)
-    }
-}




diff --git a/app/src/main/java/ml/adamsprogs/bimba/SplashActivity.kt b/app/src/main/java/ml/adamsprogs/bimba/SplashActivity.kt
deleted file mode 100644
index 19f61cc3f8a4243ae8923ddc580b6b1085c5e2b0..0000000000000000000000000000000000000000
--- a/app/src/main/java/ml/adamsprogs/bimba/SplashActivity.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-package ml.adamsprogs.bimba
-
-import android.support.v7.app.AppCompatActivity
-import android.os.Bundle
-import android.content.Intent
-import ml.adamsprogs.bimba.models.Timetable
-
-
-class SplashActivity : AppCompatActivity() {
-
-    override fun onCreate(savedInstanceState: Bundle?) {
-        super.onCreate(savedInstanceState)
-        if(Timetable(this).isDatabaseHealthy())
-            startActivity(Intent(this, MainActivity::class.java))
-        else
-            startActivity(Intent(this, NoDbActivity::class.java))
-        finish()
-    }
-}




diff --git a/app/src/main/java/ml/adamsprogs/bimba/StopActivity.kt b/app/src/main/java/ml/adamsprogs/bimba/StopActivity.kt
deleted file mode 100644
index 5e222f87419a924e16dcb24c9a3a083865c658fb..0000000000000000000000000000000000000000
--- a/app/src/main/java/ml/adamsprogs/bimba/StopActivity.kt
+++ /dev/null
@@ -1,194 +0,0 @@
-package ml.adamsprogs.bimba
-
-import android.support.design.widget.*
-import android.support.v7.app.AppCompatActivity
-import android.support.v7.widget.Toolbar
-
-import android.support.v4.app.*
-import android.support.v4.view.ViewPager
-import android.os.Bundle
-import android.support.v4.content.res.ResourcesCompat
-import android.support.v4.view.PagerAdapter
-import android.view.*
-
-import ml.adamsprogs.bimba.models.*
-import android.support.v7.widget.*
-import java.util.*
-import kotlin.collections.ArrayList
-import kotlin.collections.HashMap
-
-
-class StopActivity : AppCompatActivity() { //todo refresh
-
-    private lateinit var stopId: String
-    private var timetableType = "departure"
-    private var sectionsPagerAdapter: SectionsPagerAdapter? = null
-    private var viewPager: ViewPager? = null
-    private lateinit var timetable: Timetable
-    private val today = Calendar.getInstance()
-    private lateinit var tabLayout: TabLayout
-
-    override fun onCreate(savedInstanceState: Bundle?) { //todo select current mode
-        super.onCreate(savedInstanceState)
-        setContentView(R.layout.activity_stop)
-        stopId = intent.getStringExtra("stop")
-
-        val toolbar = findViewById(R.id.toolbar) as Toolbar
-        setSupportActionBar(toolbar)
-
-        /*todo when Internet connection
-        exists -> download vm
-        else -> timetable
-         */
-        timetable = Timetable(this)
-        supportActionBar?.title = timetable.getStopName(stopId) ?: "Stop"
-
-        viewPager = findViewById(R.id.container) as ViewPager
-        tabLayout = findViewById(R.id.tabs) as TabLayout
-
-        sectionsPagerAdapter = SectionsPagerAdapter(supportFragmentManager, createDepartures())
-
-        viewPager!!.adapter = sectionsPagerAdapter
-        viewPager!!.addOnPageChangeListener(TabLayout.TabLayoutOnPageChangeListener(tabLayout))
-        tabLayout.addOnTabSelectedListener(TabLayout.ViewPagerOnTabSelectedListener(viewPager))
-
-        selectTodayPage()
-
-        val fab = findViewById(R.id.fab) as FloatingActionButton
-        fab.setOnClickListener { view ->
-            Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
-                    .setAction("Action", null).show()
-            //todo favourites
-        }
-    }
-
-    private fun createDepartures(): HashMap<String, ArrayList<Departure>> {
-        val departures = timetable.getStopDepartures(stopId)
-        val moreDepartures = timetable.getStopDepartures(stopId)
-        val rolledDepartures = HashMap<String, ArrayList<Departure>>()
-
-        for ((_, tomorrowDepartures) in moreDepartures!!) {
-            tomorrowDepartures.forEach{it.tomorrow = true}
-        }
-
-        for ((mode, _) in departures!!) {
-            rolledDepartures[mode] = (departures[mode] as ArrayList<Departure> +
-                    moreDepartures[mode] as ArrayList<Departure>) as ArrayList<Departure>
-            rolledDepartures[mode] = filterDepartures(rolledDepartures[mode])
-        }
-
-        return rolledDepartures
-    }
-
-    private fun filterDepartures(departures: List<Departure>?): ArrayList<Departure> {
-        val filtered = ArrayList<Departure>()
-        val lines = HashMap<String, Int>()
-        val now = Calendar.getInstance()
-        for (departure in departures!!) {
-            val time = Calendar.getInstance()
-            time.set(Calendar.HOUR_OF_DAY, Integer.parseInt(departure.time.split(":")[0]))
-            time.set(Calendar.MINUTE, Integer.parseInt(departure.time.split(":")[1]))
-            time.set(Calendar.SECOND, 0)
-            time.set(Calendar.MILLISECOND, 0)
-            if (departure.tomorrow)
-                time.add(Calendar.DAY_OF_MONTH, 1)
-            var lineExistedTimes = lines[departure.line]
-            if (now.before(time) && lineExistedTimes ?: 0 < 3) {
-                lineExistedTimes = (lineExistedTimes ?: 0) + 1
-                lines[departure.line] = lineExistedTimes
-                filtered.add(departure)
-            }
-        }
-        return filtered
-    }
-
-    private fun selectTodayPage() {
-        when (today.get(Calendar.DAY_OF_WEEK)) {
-            Calendar.SATURDAY -> tabLayout.getTabAt(1)?.select()
-            Calendar.SUNDAY -> tabLayout.getTabAt(2)?.select()
-            else -> tabLayout.getTabAt(0)?.select()
-        }
-    }
-
-    override fun onCreateOptionsMenu(menu: Menu): Boolean {
-        menuInflater.inflate(R.menu.menu_stop, menu)
-        return true
-    }
-
-    override fun onOptionsItemSelected(item: MenuItem): Boolean {
-        val id = item.itemId
-
-        if (id == R.id.action_change_type) {
-            if (timetableType == "departure") {
-                timetableType = "full"
-                item.icon = (ResourcesCompat.getDrawable(resources, R.drawable.ic_timetable_departure, this.theme))
-                sectionsPagerAdapter?.changeDepartures(timetable.getStopDepartures(stopId)!!)
-                sectionsPagerAdapter?.notifyDataSetChanged()
-            } else {
-                timetableType = "departure"
-                item.icon = (ResourcesCompat.getDrawable(resources, R.drawable.ic_timetable_full, this.theme))
-                sectionsPagerAdapter?.changeDepartures(createDepartures())
-                sectionsPagerAdapter?.notifyDataSetChanged()
-            }
-            return true
-        }
-
-        return super.onOptionsItemSelected(item)
-    }
-
-    class PlaceholderFragment : Fragment() {
-
-        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) as RecyclerView
-            val dividerItemDecoration = DividerItemDecoration(departuresList.context, layoutManager.orientation)
-            departuresList.addItemDecoration(dividerItemDecoration)
-            val adapter = DeparturesAdapter(activity, arguments.getStringArrayList("departures").map { fromString(it) })
-            departuresList.adapter = adapter
-            departuresList.layoutManager = layoutManager
-            return rootView
-        }
-
-        companion object {
-            private val ARG_SECTION_NUMBER = "section_number"
-
-            fun newInstance(sectionNumber: Int, stopId: String, departures: ArrayList<Departure>?): PlaceholderFragment {
-                val fragment = PlaceholderFragment()
-                val args = Bundle()
-                args.putInt(ARG_SECTION_NUMBER, sectionNumber)
-                args.putString("stop", stopId)
-                val d = ArrayList<String>()
-                departures?.mapTo(d) { it.toString() }
-                args.putStringArrayList("departures", d)
-                fragment.arguments = args
-                return fragment
-            }
-        }
-    }
-
-    inner class SectionsPagerAdapter(fm: FragmentManager, var departures: HashMap<String, ArrayList<Departure>>) : FragmentStatePagerAdapter(fm) {
-
-        override fun getItemPosition(obj: Any?): Int {
-            return PagerAdapter.POSITION_NONE
-        }
-
-        override fun getItem(position: Int): Fragment {
-            var mode: String? = null
-            when (position) {
-                0 -> mode = "workdays"
-                1 -> mode = "saturdays"
-                2 -> mode = "sundays"
-            }
-            return PlaceholderFragment.newInstance(position + 1, stopId, departures[mode])
-        }
-
-        fun changeDepartures(departures: HashMap<String, ArrayList<Departure>>) {
-            this.departures = departures
-        }
-
-        override fun getCount() = 3
-    }
-}




diff --git a/app/src/main/java/ml/adamsprogs/bimba/VmClient.kt b/app/src/main/java/ml/adamsprogs/bimba/VmClient.kt
new file mode 100644
index 0000000000000000000000000000000000000000..ce9266da34b1b9f694a2546ad9f7ce3f8c910399
--- /dev/null
+++ b/app/src/main/java/ml/adamsprogs/bimba/VmClient.kt
@@ -0,0 +1,31 @@
+package ml.adamsprogs.bimba
+
+import android.app.IntentService
+import android.content.Intent
+import ml.adamsprogs.bimba.models.Departure
+
+import ml.adamsprogs.bimba.models.createDepartures
+
+class VmClient : IntentService("VmClient") {
+
+    override fun onHandleIntent(intent: Intent?) {
+        if (intent != null) {
+            val stopId = intent.getStringExtra("stopId")
+            if (!isNetworkAvailable(this)) {
+                sendResult(createDepartures(this, stopId))
+            } else {
+                //todo download vm
+            }
+        }
+    }
+
+    private fun sendResult(departures: HashMap<String, ArrayList<Departure>>) {
+        val broadcastIntent = Intent()
+        broadcastIntent.action = "ml.adamsprogs.bimba.departuresCreated"
+        broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT)
+        broadcastIntent.putStringArrayListExtra("workdays", departures["workdays"]?.map{it.toString()} as java.util.ArrayList<String>)
+        broadcastIntent.putStringArrayListExtra("saturdays", departures["saturdays"]?.map{it.toString()} as java.util.ArrayList<String>)
+        broadcastIntent.putStringArrayListExtra("sundays", departures["sundays"]?.map{it.toString()} as java.util.ArrayList<String>)
+        sendBroadcast(broadcastIntent)
+    }
+}




diff --git a/app/src/main/java/ml/adamsprogs/bimba/activities/MainActivity.kt b/app/src/main/java/ml/adamsprogs/bimba/activities/MainActivity.kt
new file mode 100644
index 0000000000000000000000000000000000000000..c058e131c46d25dc808a521e0ec206937829d2d5
--- /dev/null
+++ b/app/src/main/java/ml/adamsprogs/bimba/activities/MainActivity.kt
@@ -0,0 +1,148 @@
+package ml.adamsprogs.bimba.activities
+
+import android.content.Intent
+import android.content.IntentFilter
+import android.os.*
+import android.support.design.widget.Snackbar
+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.*
+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
+import ml.adamsprogs.bimba.MessageReceiver
+import ml.adamsprogs.bimba.R
+import ml.adamsprogs.bimba.TimetableDownloader
+
+
+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)
+
+        prepareSwipeLayout()
+
+        prepareOnDownloadListener()
+        startDownloaderService()
+
+        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) }
+            }
+        })
+
+        searchView.setOnSearchListener(object : FloatingSearchView.OnSearchListener {
+            override fun onSuggestionClicked(searchSuggestion: SearchSuggestion) {
+                val imm = context.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
+                var view = (context as MainActivity).currentFocus
+                if (view == null) {
+                    view = View(context)
+                }
+                imm.hideSoftInputFromWindow(view.windowToken, 0)
+                intent = Intent(context, StopActivity::class.java)
+                intent.putExtra("stop", (searchSuggestion as StopSuggestion).id)
+                startActivity(intent)
+            }
+
+            override fun onSearchAction(query: String) {
+            }
+        })
+
+        searchView.setOnBindSuggestionCallback { _, _, textView, item, _ ->
+            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)
+            } else {
+                @Suppress("DEPRECATION")
+                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(context as MessageReceiver.OnTimetableDownloadListener)
+        unregisterReceiver(receiver)
+        timetable.close()
+    }
+
+    fun deAccent(str: String): String {
+        var result = str.replace('ę', 'e')
+        result = result.replace('ó', 'o')
+        result = result.replace('ą', 'a')
+        result = result.replace('ś', 's')
+        result = result.replace('ł', 'l')
+        result = result.replace('ż', 'ż')
+        result = result.replace('ź', 'ź')
+        result = result.replace('ć', 'ć')
+        result = result.replace('ń', 'n')
+        return result
+    }
+
+    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(swipeRefreshLayout, message, Snackbar.LENGTH_LONG).show()
+        swipeRefreshLayout.isRefreshing = false
+    }
+}




diff --git a/app/src/main/java/ml/adamsprogs/bimba/activities/NoDbActivity.kt b/app/src/main/java/ml/adamsprogs/bimba/activities/NoDbActivity.kt
new file mode 100644
index 0000000000000000000000000000000000000000..6e89218c7fd22a9565f0f86a86e19f5eac2a622f
--- /dev/null
+++ b/app/src/main/java/ml/adamsprogs/bimba/activities/NoDbActivity.kt
@@ -0,0 +1,69 @@
+package ml.adamsprogs.bimba.activities
+
+import android.content.Intent
+import android.support.v7.app.AppCompatActivity
+import android.os.Bundle
+import android.content.IntentFilter
+import android.widget.TextView
+import ml.adamsprogs.bimba.*
+
+
+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)
+        setContentView(R.layout.activity_nodb)
+        var filter: IntentFilter
+        filter = IntentFilter("ml.adamsprogs.bimba.timetableDownloaded")
+        filter.addCategory(Intent.CATEGORY_DEFAULT)
+        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)
+            networkStateReceiver.addOnConnectivityChangeListener(this)
+        } else
+            downloadTimetable()
+    }
+
+    fun downloadTimetable() {
+        (findViewById(R.id.noDbCaption) as TextView).text = getString(R.string.no_db_downloading)
+        serviceRunning = true
+        intent = Intent(this, TimetableDownloader::class.java)
+        intent.putExtra("force", true)
+        startService(intent)
+    }
+
+    override fun onConnectivityChange(connected: Boolean) {
+        if (connected && !serviceRunning)
+            downloadTimetable()
+        /*if (!connected)
+            serviceRunning = false*/
+    }
+
+    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)
+        if (askedForNetwork)
+            unregisterReceiver(networkStateReceiver)
+    }
+}




diff --git a/app/src/main/java/ml/adamsprogs/bimba/activities/SplashActivity.kt b/app/src/main/java/ml/adamsprogs/bimba/activities/SplashActivity.kt
new file mode 100644
index 0000000000000000000000000000000000000000..98a0fed99b714a63fb103c20389d8563598e7847
--- /dev/null
+++ b/app/src/main/java/ml/adamsprogs/bimba/activities/SplashActivity.kt
@@ -0,0 +1,21 @@
+package ml.adamsprogs.bimba.activities
+
+import android.support.v7.app.AppCompatActivity
+import android.os.Bundle
+import android.content.Intent
+import ml.adamsprogs.bimba.models.Timetable
+
+
+class SplashActivity : AppCompatActivity() {
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        val timetable = Timetable(this)
+        if(timetable.isDatabaseHealthy())
+            startActivity(Intent(this, MainActivity::class.java))
+        else
+            startActivity(Intent(this, NoDbActivity::class.java))
+        timetable.close()
+        finish()
+    }
+}




diff --git a/app/src/main/java/ml/adamsprogs/bimba/activities/StopActivity.kt b/app/src/main/java/ml/adamsprogs/bimba/activities/StopActivity.kt
new file mode 100644
index 0000000000000000000000000000000000000000..46594bcd3f3a2780eb383b1a3957acb401f6c61b
--- /dev/null
+++ b/app/src/main/java/ml/adamsprogs/bimba/activities/StopActivity.kt
@@ -0,0 +1,207 @@
+package ml.adamsprogs.bimba.activities
+
+import android.content.Intent
+import android.content.IntentFilter
+import android.support.design.widget.*
+import android.support.v7.app.AppCompatActivity
+import android.support.v7.widget.Toolbar
+
+import android.support.v4.app.*
+import android.support.v4.view.ViewPager
+import android.os.Bundle
+import android.support.v4.content.res.ResourcesCompat
+import android.support.v4.view.PagerAdapter
+import android.view.*
+
+import ml.adamsprogs.bimba.models.*
+import android.support.v7.widget.*
+import ml.adamsprogs.bimba.MessageReceiver
+import ml.adamsprogs.bimba.R
+import ml.adamsprogs.bimba.VmClient
+import java.util.*
+import kotlin.collections.ArrayList
+import kotlin.collections.HashMap
+
+
+class StopActivity : AppCompatActivity(), MessageReceiver.OnVmListener {
+
+    private lateinit var stopId: String
+    private var timetableType = "departure"
+    private var sectionsPagerAdapter: SectionsPagerAdapter? = null
+    private var viewPager: ViewPager? = null
+    private lateinit var timetable: Timetable
+    private val today = Calendar.getInstance()
+    private lateinit var tabLayout: TabLayout
+    private var timer = Timer()
+    private lateinit var timerTask:TimerTask
+    private val context = this
+    val receiver = MessageReceiver()
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        setContentView(R.layout.activity_stop)
+        stopId = intent.getStringExtra("stop")
+
+        val toolbar = findViewById(R.id.toolbar) as Toolbar
+        setSupportActionBar(toolbar)
+
+        createTimerTask()
+
+        prepareOnDownloadListener()
+
+        timetable = Timetable(this)
+        supportActionBar?.title = timetable.getStopName(stopId) ?: "Stop"
+
+        viewPager = findViewById(R.id.container) as ViewPager
+        tabLayout = findViewById(R.id.tabs) as TabLayout
+
+        sectionsPagerAdapter = SectionsPagerAdapter(supportFragmentManager, createDepartures(this, stopId))
+
+        viewPager!!.adapter = sectionsPagerAdapter
+        viewPager!!.addOnPageChangeListener(TabLayout.TabLayoutOnPageChangeListener(tabLayout))
+        tabLayout.addOnTabSelectedListener(TabLayout.ViewPagerOnTabSelectedListener(viewPager))
+
+        selectTodayPage()
+
+        scheduleRefresh()
+
+        val fab = findViewById(R.id.fab) as FloatingActionButton
+        fab.setOnClickListener { view ->
+            Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
+                    .setAction("Action", null).show()
+            //todo favourites
+        }
+    }
+
+    private fun createTimerTask() {
+        timerTask = object : TimerTask() {
+            override fun run() {
+                val vmIntent = Intent(context, VmClient::class.java)
+                vmIntent.putExtra("stopId", stopId)
+                startService(vmIntent)
+            }
+        }
+    }
+
+    private fun prepareOnDownloadListener() {
+        val filter = IntentFilter("ml.adamsprogs.bimba.departuresCreated")
+        filter.addCategory(Intent.CATEGORY_DEFAULT)
+        registerReceiver(receiver, filter)
+        receiver.addOnVmListener(context as MessageReceiver.OnVmListener)
+    }
+
+    override fun onVm(departures: HashMap<String, ArrayList<Departure>>) {
+        sectionsPagerAdapter?.departures = departures
+        sectionsPagerAdapter?.notifyDataSetChanged()
+    }
+
+    private fun selectTodayPage() {
+        when (today.get(Calendar.DAY_OF_WEEK)) {
+            Calendar.SATURDAY -> tabLayout.getTabAt(1)?.select()
+            Calendar.SUNDAY -> tabLayout.getTabAt(2)?.select()
+            else -> tabLayout.getTabAt(0)?.select()
+        }
+    }
+
+    private fun scheduleRefresh() {
+        timer.cancel()
+        timer = Timer()
+        createTimerTask()
+        timer.scheduleAtFixedRate(timerTask, 0, 15000)
+    }
+
+    override fun onCreateOptionsMenu(menu: Menu): Boolean {
+        menuInflater.inflate(R.menu.menu_stop, menu)
+        return true
+    }
+
+    override fun onOptionsItemSelected(item: MenuItem): Boolean {
+        val id = item.itemId
+
+        if (id == R.id.action_change_type) {
+            if (timetableType == "departure") {
+                timetableType = "full"
+                item.icon = (ResourcesCompat.getDrawable(resources, R.drawable.ic_timetable_departure, this.theme))
+                sectionsPagerAdapter?.departures = timetable.getStopDepartures(stopId)!!
+                sectionsPagerAdapter?.relativeTime = false
+                sectionsPagerAdapter?.notifyDataSetChanged()
+                timer.cancel()
+            } else {
+                timetableType = "departure"
+                item.icon = (ResourcesCompat.getDrawable(resources, R.drawable.ic_timetable_full, this.theme))
+                sectionsPagerAdapter?.departures = createDepartures(this, stopId)
+                sectionsPagerAdapter?.relativeTime = true
+                sectionsPagerAdapter?.notifyDataSetChanged()
+                scheduleRefresh()
+            }
+            return true
+        }
+
+        return super.onOptionsItemSelected(item)
+    }
+
+    override fun onDestroy() {
+        super.onDestroy()
+        receiver.removeOnVmListener(context as MessageReceiver.OnVmListener)
+        unregisterReceiver(receiver)
+        timer.cancel()
+        timetable.close()
+    }
+
+    class PlaceholderFragment : Fragment() {
+
+        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) as RecyclerView
+            val dividerItemDecoration = DividerItemDecoration(departuresList.context, layoutManager.orientation)
+            departuresList.addItemDecoration(dividerItemDecoration)
+            val adapter = DeparturesAdapter(activity, arguments.getStringArrayList("departures").map { fromString(it) },
+                    arguments["relativeTime"] as Boolean)
+            departuresList.adapter = adapter
+            departuresList.layoutManager = layoutManager
+            return rootView
+        }
+
+        companion object {
+            private val ARG_SECTION_NUMBER = "section_number"
+
+            fun newInstance(sectionNumber: Int, stopId: String, departures: ArrayList<Departure>?, relativeTime: Boolean):
+                    PlaceholderFragment {
+                val fragment = PlaceholderFragment()
+                val args = Bundle()
+                args.putInt(ARG_SECTION_NUMBER, sectionNumber)
+                args.putString("stop", stopId)
+                val d = ArrayList<String>()
+                departures?.mapTo(d) { it.toString() }
+                args.putStringArrayList("departures", d)
+                args.putBoolean("relativeTime", relativeTime)
+                fragment.arguments = args
+                return fragment
+            }
+        }
+    }
+
+    inner class SectionsPagerAdapter(fm: FragmentManager, var departures: HashMap<String, ArrayList<Departure>>) : FragmentStatePagerAdapter(fm) {
+
+        var relativeTime = true
+
+        override fun getItemPosition(obj: Any?): Int {
+            return PagerAdapter.POSITION_NONE
+        }
+
+        override fun getItem(position: Int): Fragment {
+            var mode: String? = null
+            when (position) {
+                0 -> mode = "workdays"
+                1 -> mode = "saturdays"
+                2 -> mode = "sundays"
+            }
+            return PlaceholderFragment.newInstance(position + 1, stopId, departures[mode], relativeTime)
+        }
+
+        override fun getCount() = 3
+    }
+}




diff --git a/app/src/main/java/ml/adamsprogs/bimba/models/DeparturesAdapter.kt b/app/src/main/java/ml/adamsprogs/bimba/models/DeparturesAdapter.kt
index e899fc8cb3079e7e3c13c5be30c5beb1f787383b..834fbf4f0583568d1b4b85e4879676aa49f70412 100644
--- a/app/src/main/java/ml/adamsprogs/bimba/models/DeparturesAdapter.kt
+++ b/app/src/main/java/ml/adamsprogs/bimba/models/DeparturesAdapter.kt
@@ -11,7 +11,50 @@ import ml.adamsprogs.bimba.R
 import android.view.LayoutInflater
 import java.util.*
 
-class DeparturesAdapter(val context: Context, val departures: List<Departure>) :
+fun filterDepartures(departures: List<Departure>?): ArrayList<Departure> {
+    val filtered = ArrayList<Departure>()
+    val lines = HashMap<String, Int>()
+    val now = Calendar.getInstance()
+    for (departure in departures!!) {
+        val time = Calendar.getInstance()
+        time.set(Calendar.HOUR_OF_DAY, Integer.parseInt(departure.time.split(":")[0]))
+        time.set(Calendar.MINUTE, Integer.parseInt(departure.time.split(":")[1]))
+        time.set(Calendar.SECOND, 0)
+        time.set(Calendar.MILLISECOND, 0)
+        if (departure.tomorrow)
+            time.add(Calendar.DAY_OF_MONTH, 1)
+        var lineExistedTimes = lines[departure.line]
+        if (now.before(time) && lineExistedTimes ?: 0 < 3) {
+            lineExistedTimes = (lineExistedTimes ?: 0) + 1
+            lines[departure.line] = lineExistedTimes
+            filtered.add(departure)
+        }
+    }
+    return filtered
+}
+
+fun createDepartures(context: Context, stopId: String): HashMap<String, ArrayList<Departure>> {
+    val timetable = Timetable(context)
+    val departures = timetable.getStopDepartures(stopId)
+    val moreDepartures = timetable.getStopDepartures(stopId)
+    val rolledDepartures = HashMap<String, ArrayList<Departure>>()
+
+    for ((_, tomorrowDepartures) in moreDepartures!!) {
+        tomorrowDepartures.forEach { it.tomorrow = true }
+    }
+
+    for ((mode, _) in departures!!) {
+        rolledDepartures[mode] = (departures[mode] as ArrayList<Departure> +
+                moreDepartures[mode] as ArrayList<Departure>) as ArrayList<Departure>
+        rolledDepartures[mode] = filterDepartures(rolledDepartures[mode])
+    }
+
+    timetable.close()
+
+    return rolledDepartures
+}
+
+class DeparturesAdapter(val context: Context, val departures: List<Departure>, val relativeTime: Boolean) :
         RecyclerView.Adapter<DeparturesAdapter.ViewHolder>() {
     override fun getItemCount(): Int {
         return departures.size
@@ -29,7 +72,7 @@
         val departureIn = (departureTime.timeInMillis - now.timeInMillis) / (1000 * 60)
         val timeString: String
 
-        if (departureIn > 60 || departureIn < 0)
+        if (departureIn > 60 || departureIn < 0 || !relativeTime)
             timeString = context.getString(R.string.departure_at, departure.time)
         else if (departureIn > 0)
             timeString = context.getString(R.string.departure_in, departureIn.toString())




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 9e08ecd35ab476075222b2f4fc731c6e8949fdba..05e2a6ee4a6096c3bcecfb53edf441d5cd1882ba 100644
--- a/app/src/main/java/ml/adamsprogs/bimba/models/Timetable.kt
+++ b/app/src/main/java/ml/adamsprogs/bimba/models/Timetable.kt
@@ -86,4 +86,8 @@         }
         cursor.close()
         return departures
     }
+
+    fun close() {
+        db?.close()
+    }
 }




diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 50db680552ef62dca20d5cf36e3e3e65aa3101db..f8601b3ceeeacd90fea031f2d262ae969d0b8d68 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -5,7 +5,7 @@     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">
+    tools:context="ml.adamsprogs.bimba.activities.MainActivity">
 
     <android.support.constraint.ConstraintLayout
         android:id="@+id/main_layout"




diff --git a/app/src/main/res/layout/activity_stop.xml b/app/src/main/res/layout/activity_stop.xml
index 072d70cd1e87f953e74d7d4434544967ed4ea652..86a729521afcd4b934b2a58541fba5bba648d932 100644
--- a/app/src/main/res/layout/activity_stop.xml
+++ b/app/src/main/res/layout/activity_stop.xml
@@ -7,7 +7,7 @@     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:fitsSystemWindows="true"
     android:animateLayoutChanges="true"
-    tools:context="ml.adamsprogs.bimba.StopActivity">
+    tools:context="ml.adamsprogs.bimba.activities.StopActivity">
 
     <android.support.design.widget.AppBarLayout
         android:id="@+id/appbar"




diff --git a/app/src/main/res/layout/fragment_stop.xml b/app/src/main/res/layout/fragment_stop.xml
index e8ba3100581354aadfbc60adb32a8cfe0da82c3f..0e24c01dde58f17ff54d130b461c68c002d28298 100644
--- a/app/src/main/res/layout/fragment_stop.xml
+++ b/app/src/main/res/layout/fragment_stop.xml
@@ -4,7 +4,7 @@     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.StopActivity$PlaceholderFragment">
+    tools:context="ml.adamsprogs.bimba.activities.StopActivity$PlaceholderFragment">
 
     <android.support.v7.widget.RecyclerView
         android:id="@+id/departuresList"




diff --git a/app/src/main/res/menu/menu_stop.xml b/app/src/main/res/menu/menu_stop.xml
index b6a44d35ffee8bde31c57b994a4b54b58eeca51a..f5eeafa161d8425f01c97b62b4816477ecc797e0 100644
--- a/app/src/main/res/menu/menu_stop.xml
+++ b/app/src/main/res/menu/menu_stop.xml
@@ -1,7 +1,7 @@
 <menu 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"
-    tools:context="ml.adamsprogs.bimba.StopActivity">
+    tools:context="ml.adamsprogs.bimba.activities.StopActivity">
     <item
         android:id="@+id/action_change_type"
         android:orderInCategory="100"