Bimba.git

commit 9dba115d62fda3ad59a77b837763327faef695b3

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

merging favourites

 app/src/main/java/ml/adamsprogs/bimba/activities/DashActivity.kt | 33 
 app/src/main/java/ml/adamsprogs/bimba/activities/StopActivity.kt | 2 
 app/src/main/java/ml/adamsprogs/bimba/models/FavouriteStorage.kt | 24 
 app/src/main/java/ml/adamsprogs/bimba/models/FavouritesAdapter.kt | 82 
 app/src/main/res/drawable/ic_merge.xml | 9 
 app/src/main/res/layout/activity_dash.xml | 31 
 app/src/main/res/layout/row_favourite.xml | 1 
 app/src/main/res/menu/menu_favourite_merge.xml | 10 
 app/src/main/res/values-pl/strings.xml | 3 
 app/src/main/res/values/colors.xml | 1 
 app/src/main/res/values/strings.xml | 2 


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 bb989fcd4ae56fb64aa5f59c10cdb7a95579b989..18315812aebef80b22dca777641dc3e7e92cebe9 100644
--- a/app/src/main/java/ml/adamsprogs/bimba/activities/DashActivity.kt
+++ b/app/src/main/java/ml/adamsprogs/bimba/activities/DashActivity.kt
@@ -14,8 +14,9 @@ import android.app.Activity
 import android.support.v4.widget.*
 import android.support.v7.widget.*
 import android.util.Log
+import android.view.Menu
+import android.view.MenuItem
 import android.view.inputmethod.InputMethodManager
-import android.widget.Toast
 import ml.adamsprogs.bimba.*
 
 //todo refresh every 15s
@@ -33,6 +34,9 @@     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
         setContentView(R.layout.activity_dash)
         AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO)
+        val toolbar = findViewById(R.id.toolbar) as Toolbar
+        setSupportActionBar(toolbar)
+        supportActionBar?.title = getString(R.string.merge_favourites)
 
         prepareSwipeLayout()
 
@@ -49,7 +53,10 @@         searchView.setOnFocusChangeListener(object : FloatingSearchView.OnFocusChangeListener {
             override fun onFocus() {
                 swipeRefreshLayout.isEnabled = false
                 favouritesList.visibility = View.GONE
-                //todo show suggestions
+                thread {
+                    val newStops = stops!!.filter { deAccent(it.body.split("\n")[0]).contains(deAccent(searchView.query), true) }
+                    runOnUiThread { searchView.swapSuggestions(newStops) }
+                }
             }
 
             override fun onFocusCleared() {
@@ -134,7 +141,6 @@     }
 
     override fun onRefresh() {
         swipeRefreshLayout.isRefreshing = true
-        Log.i("Refresh", "Downloading")
         startDownloaderService()
     }
 
@@ -146,7 +152,7 @@     }
 
     override fun onResume() {
         super.onResume()
-        favouritesList.adapter = FavouritesAdapter(context, favourites.favouritesList, this)
+        (favouritesList.adapter as FavouritesAdapter).favourites = favourites.favouritesList
         favouritesList.adapter.notifyDataSetChanged()
     }
 
@@ -154,6 +160,25 @@     override fun onDestroy() {
         super.onDestroy()
         receiver.removeOnTimetableDownloadListener(context as MessageReceiver.OnTimetableDownloadListener)
         unregisterReceiver(receiver)
+    }
+
+    override fun onCreateOptionsMenu(menu: Menu): Boolean {
+        menuInflater.inflate(R.menu.menu_favourite_merge, menu)
+        return true
+    }
+
+    override fun onOptionsItemSelected(item: MenuItem): Boolean {
+        val id = item.itemId
+
+        if (id == R.id.action_merge) {
+            val names = (favouritesList.adapter as FavouritesAdapter).selectedNames
+            favourites.merge(names)
+            (favouritesList.adapter as FavouritesAdapter).favourites = favourites.favouritesList
+            favouritesList.adapter.notifyDataSetChanged()
+            (favouritesList.adapter as FavouritesAdapter).stopSelecting(names[0])
+        }
+
+        return super.onOptionsItemSelected(item)
     }
 
     fun deAccent(str: String): String {




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 0186293dd268fc39efc0b8f660528ff32ca06a72..c9ff27e2028878e4a1d07fdc8da4fbf07b8cb0c8 100644
--- a/app/src/main/java/ml/adamsprogs/bimba/activities/StopActivity.kt
+++ b/app/src/main/java/ml/adamsprogs/bimba/activities/StopActivity.kt
@@ -77,7 +77,7 @@             Log.i("FAB", "Click")
             if (!favourites.has(stopSymbol)) {
                 Log.i("FAB", "Add")
                 val items = ArrayList<HashMap<String, String>>()
-                timetable.getLines(stopId)?.forEach {
+                timetable.getLines(stopId).forEach {
                     val o = HashMap<String, String>()
                     o["stop"] = stopId
                     o["line"] = it




diff --git a/app/src/main/java/ml/adamsprogs/bimba/models/FavouriteStorage.kt b/app/src/main/java/ml/adamsprogs/bimba/models/FavouriteStorage.kt
index 38b9d791c187ec18baa390442822d46c7216a61f..d6556e360d30fed602f6334c8e9c1c2b1ef488af 100644
--- a/app/src/main/java/ml/adamsprogs/bimba/models/FavouriteStorage.kt
+++ b/app/src/main/java/ml/adamsprogs/bimba/models/FavouriteStorage.kt
@@ -31,10 +31,6 @@             return favourites.values.toList()
         }
 
     init {
-        refresh()
-    }
-
-    fun refresh() {
         val favouritesString = preferences.getString("favourites", "{}")
         val favouritesMap = Gson().fromJson(favouritesString, JsonObject::class.java)
         for ((name, jsonTimetables) in favouritesMap.entrySet()) {
@@ -66,17 +62,12 @@         }
     }
 
     fun delete(name: String) {
-        Log.i("ROW", "Deleting $name")
-        Log.i("ROW", "$name is in favourites?: ${favourites.contains(name)}")
-        val b = favourites.remove(name)
-        Log.i("ROW", "deleted: $b")
+        favourites.remove(name)
         serialize()
     }
 
     fun delete(name: String, stop: String, line: String) {
-        Log.i("ROW", "delete $name, $stop, $line")
         favourites[name]?.delete(stop, line)
-        //todo check empty
         serialize()
     }
 
@@ -109,5 +100,18 @@         favourites[newName] = Favourite(newName, array)
         serialize()
 
         delete(name, stop, line)
+    }
+
+    fun merge(names: ArrayList<String>) {
+        if (names.size < 2 )
+            return
+        val newFavourite = Favourite(names[0], ArrayList<HashMap<String, String>>())
+        for (name in names) {
+            newFavourite.timetables.addAll(favourites[name]!!.timetables)
+            favourites.remove(name)
+        }
+        favourites[names[0]] = newFavourite
+
+        serialize()
     }
 }
\ No newline at end of file




diff --git a/app/src/main/java/ml/adamsprogs/bimba/models/FavouritesAdapter.kt b/app/src/main/java/ml/adamsprogs/bimba/models/FavouritesAdapter.kt
index d14bb6508bd8a86adf3dce0fd28b4422316df9aa..78c540a87e9d72773b8f849b3ddb092bcc2205a9 100644
--- a/app/src/main/java/ml/adamsprogs/bimba/models/FavouritesAdapter.kt
+++ b/app/src/main/java/ml/adamsprogs/bimba/models/FavouritesAdapter.kt
@@ -2,6 +2,8 @@ package ml.adamsprogs.bimba.models
 
 import android.app.Activity
 import android.content.Context
+import android.os.Build
+import android.support.v7.widget.CardView
 import android.support.v7.widget.PopupMenu
 import android.support.v7.widget.RecyclerView
 import android.view.View
@@ -12,10 +14,34 @@ import ml.adamsprogs.bimba.R
 import android.view.LayoutInflater
 import java.util.*
 import kotlin.concurrent.thread
-
+import android.util.TypedValue
+import kotlin.collections.ArrayList
 
+//todo list to storage
 class FavouritesAdapter(val context: Context, var favourites: List<Favourite>, val onMenuItemClickListener: FavouritesAdapter.OnMenuItemClickListener) :
         RecyclerView.Adapter<FavouritesAdapter.ViewHolder>() {
+
+    val isSelecting: Boolean
+        get() {
+            return selected.any { it }
+        }
+    val selected = ArrayList<Boolean>()
+    val selectedNames: ArrayList<String>
+        get() {
+            val l = ArrayList<String>()
+            for ((i, it) in selected.withIndex()) {
+                if (it)
+                    l.add(favourites[i].name)
+            }
+            return l
+        }
+
+    init {
+        favourites.forEach {
+            selected.add(false)
+        }
+    }
+
     override fun getItemCount(): Int {
         return favourites.size
     }
@@ -37,15 +63,20 @@                 if (nextDeparture.tomorrow)
                     departureTime.add(Calendar.DAY_OF_MONTH, 1)
                 val interval = ((departureTime.timeInMillis - now.timeInMillis) / (1000 * 60)).toString()
                 nextDepartureText = context.getString(R.string.departure_in, interval)
-                nextDepartureLineText =context.getString(R.string.departure_to_line, nextDeparture.line, nextDeparture.direction)
+                nextDepartureLineText = context.getString(R.string.departure_to_line, nextDeparture.line, nextDeparture.direction)
             } else {
                 nextDepartureText = context.getString(R.string.no_next_departure)
                 nextDepartureLineText = ""
             }
             (context as Activity).runOnUiThread {
+                holder?.root?.setOnLongClickListener {
+                    toggleSelected(it as CardView, position)
+                    true
+                }
                 holder?.timeTextView?.text = nextDepartureText
                 holder?.lineTextView?.text = nextDepartureLineText
                 holder?.moreButton?.setOnClickListener {
+                    unSelect(holder.root, position)
                     val popup = PopupMenu(context, it)
                     val inflater = popup.menuInflater
                     popup.setOnMenuItemClickListener {
@@ -62,6 +93,42 @@             }
         }
     }
 
+    fun toggleSelected(view: CardView, position: Int) {
+        if (selected[position])
+            unSelect(view, position)
+        else
+            select(view, position)
+    }
+
+    fun select(view: CardView, position: Int) {
+        @Suppress("DEPRECATION")
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
+            view.setCardBackgroundColor(context.resources.getColor(R.color.colorAccent, null))
+        else
+            view.setCardBackgroundColor(context.resources.getColor(R.color.colorAccent))
+        selected[position] = true
+        setSelecting()
+    }
+
+    fun unSelect(view: CardView, position: Int) {
+        val colour = TypedValue()
+        context.theme.resolveAttribute(R.attr.cardBackgroundColor, colour, true)
+        view.setCardBackgroundColor(colour.data)
+        selected[position] = false
+        setSelecting()
+    }
+
+    fun setSelecting() {
+        context as Activity
+        if (isSelecting) {
+            context.findViewById(R.id.search_view).visibility = View.INVISIBLE
+            context.findViewById(R.id.appbar).visibility = View.VISIBLE
+        } else {
+            context.findViewById(R.id.search_view).visibility = View.VISIBLE
+            context.findViewById(R.id.appbar).visibility = View.INVISIBLE
+        }
+    }
+
     override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): ViewHolder {
         val context = parent?.context
         val inflater = LayoutInflater.from(context)
@@ -71,7 +138,18 @@         val viewHolder = ViewHolder(rowView)
         return viewHolder
     }
 
+    fun stopSelecting(name: String) {
+        selected.clear()
+        favourites.forEach {
+            if (it.name == name)
+                selected.add(true)
+            else
+                selected.add(false)
+        }
+    }
+
     inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
+        val root = itemView.findViewById(R.id.favourite_card) as CardView
         val nameTextView = itemView.findViewById(R.id.favourite_name) as TextView
         val timeTextView = itemView.findViewById(R.id.favourite_time) as TextView
         val lineTextView = itemView.findViewById(R.id.favourite_line) as TextView




diff --git a/app/src/main/res/drawable/ic_merge.xml b/app/src/main/res/drawable/ic_merge.xml
new file mode 100644
index 0000000000000000000000000000000000000000..18a93f7c4dbc2e9ccf2a0c1748eb98f8c4fb09a0
--- /dev/null
+++ b/app/src/main/res/drawable/ic_merge.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportHeight="24.0"
+    android:viewportWidth="24.0">
+    <path
+        android:fillColor="#ffffffff"
+        android:pathData="M17,20.41L18.41,19 15,15.59 13.59,17 17,20.41zM7.5,8H11v5.59L5.59,19 7,20.41l6,-6V8h3.5L12,3.5 7.5,8z" />
+</vector>




diff --git a/app/src/main/res/layout/activity_dash.xml b/app/src/main/res/layout/activity_dash.xml
index f742d2c57060380e3d98edf399bdde2cd36d4001..3c9da371645392721c2ebe789e170204d8050d66 100644
--- a/app/src/main/res/layout/activity_dash.xml
+++ b/app/src/main/res/layout/activity_dash.xml
@@ -12,6 +12,25 @@         android:id="@+id/main_layout"
         android:layout_width="match_parent"
         android:layout_height="match_parent">
 
+        <android.support.design.widget.AppBarLayout
+            android:id="@+id/appbar"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:background="@color/colorAccentDark"
+            android:paddingTop="@dimen/appbar_padding_top"
+            android:theme="@style/AppTheme.AppBarOverlay"
+            android:visibility="invisible">
+
+            <android.support.v7.widget.Toolbar
+                android:id="@+id/toolbar"
+                android:layout_width="match_parent"
+                android:layout_height="?attr/actionBarSize"
+                android:layout_weight="1"
+                android:background="@color/colorAccentDark"
+                app:layout_scrollFlags="scroll|enterAlways"
+                app:popupTheme="@style/AppTheme.PopupOverlay" />
+        </android.support.design.widget.AppBarLayout>
+
         <com.arlib.floatingsearchview.FloatingSearchView
             android:id="@+id/search_view"
             android:layout_width="match_parent"
@@ -29,14 +48,14 @@
         <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_height="469dp"
+            android:layout_marginEnd="8dp"
             android:layout_marginStart="8dp"
+            android:layout_marginTop="100dp"
+            android:scrollbars="none"
             app:layout_constraintEnd_toEndOf="parent"
-            android:layout_marginEnd="8dp"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent"
             app:layout_constraintBottom_toBottomOf="parent"
             android:layout_marginBottom="8dp" />
 




diff --git a/app/src/main/res/layout/row_favourite.xml b/app/src/main/res/layout/row_favourite.xml
index 592c44f24f3d4825361c83d2e582d2108be3283f..2064150f864e7113664e5d804079bfa3f9a787a5 100644
--- a/app/src/main/res/layout/row_favourite.xml
+++ b/app/src/main/res/layout/row_favourite.xml
@@ -2,6 +2,7 @@ 
 <android.support.v7.widget.CardView 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/favourite_card"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:layout_margin="4dp"




diff --git a/app/src/main/res/menu/menu_favourite_merge.xml b/app/src/main/res/menu/menu_favourite_merge.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9342fb336b87d362d276538d787572c1e907dc59
--- /dev/null
+++ b/app/src/main/res/menu/menu_favourite_merge.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto">
+    <item
+        android:id="@+id/action_merge"
+        android:orderInCategory="100"
+        android:title="@string/action_merge"
+        android:icon="@drawable/ic_merge"
+        app:showAsAction="always" />
+</menu>
\ No newline at end of file




diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index 006fa03d80ecf874e108e69035e499dc0f773da7..19fdd7ec188945443a6e23bb7cfdd5f9536aba03 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -3,4 +3,5 @@ 
     <color name="colorPrimary">#4caf50</color>
     <color name="colorPrimaryDark">#087f23</color>
     <color name="colorAccent">#40c4ff</color>
+    <color name="colorAccentDark">#0094cc</color>
 </resources>
\ 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 2661da5259d90e15438ee399361b8406876d04db..4cb75f7401f3c1dd4edbd096fbe53e8728b2a17f 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -33,4 +33,6 @@     Edit ‘%1$s’
     <string name="favourite_element_delete_button" translatable="false">favourite element delete button</string>
     <string name="favourite_element_split_button" translatable="false">favourite element split button</string>
     <string name="no_next_departure">No next departure</string>
+    <string name="action_merge">Merge</string>
+    <string name="merge_favourites">Merge favourites</string>
 </resources>




diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml
index 74c9790a772cd65a8b68e69caaff597c87e3eeaa..f930b6bd9f6b1b5ae5302629fa927bce24834e8f 100644
--- a/app/src/main/res/values-pl/strings.xml
+++ b/app/src/main/res/values-pl/strings.xml
@@ -26,4 +26,7 @@     Zakończ
     <string name="favourite_edit">Edytuj ulubiony</string>
     <string name="edit_favourite_title">Edytuj „%1$s”</string>
     <string name="favourite_name">Nazwa ulubionego</string>
+    <string name="no_next_departure">Brak następnego odjazdu</string>
+    <string name="action_merge">Połącz</string>
+    <string name="merge_favourites">Połącz ulubione</string>
 </resources>
\ No newline at end of file