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