From 49259439571b8705376901bd18ce52088d9f4ffc Mon Sep 17 00:00:00 2001 From: Sebastian Seedorf Date: Fri, 18 Oct 2019 01:49:10 +0200 Subject: [PATCH] Delete Canteens and Restore Canteen List to Default --- .../java/de/sebse/fuplanner/MainActivity.java | 41 ++++++--- .../fuplanner/fragments/CanteensAdapter.java | 91 ++++++++++++++++--- .../fuplanner/fragments/CanteensFragment.java | 44 +++++++++ .../services/canteen/CanteenBrowser.java | 27 ++++-- .../de/sebse/fuplanner/tools/Preferences.java | 34 +++++++ .../tools/ui/CanteensViewHolder.java | 18 ++++ .../main/res/drawable/ic_remove_circle.xml | 5 + .../res/drawable/ic_remove_circle_outline.xml | 5 + .../res/layout/list_canteens_btn_delete.xml | 19 ++++ .../main/res/layout/list_canteens_items.xml | 70 ++++++++++++++ app/src/main/res/menu/options_canteens.xml | 12 +++ app/src/main/res/values-de/strings.xml | 2 + app/src/main/res/values/preferences.xml | 17 ++-- app/src/main/res/values/strings.xml | 2 + 14 files changed, 352 insertions(+), 35 deletions(-) create mode 100644 app/src/main/java/de/sebse/fuplanner/tools/ui/CanteensViewHolder.java create mode 100644 app/src/main/res/drawable/ic_remove_circle.xml create mode 100644 app/src/main/res/drawable/ic_remove_circle_outline.xml create mode 100644 app/src/main/res/layout/list_canteens_btn_delete.xml create mode 100644 app/src/main/res/layout/list_canteens_items.xml create mode 100644 app/src/main/res/menu/options_canteens.xml diff --git a/app/src/main/java/de/sebse/fuplanner/MainActivity.java b/app/src/main/java/de/sebse/fuplanner/MainActivity.java index 9d7d28d..64b1e54 100644 --- a/app/src/main/java/de/sebse/fuplanner/MainActivity.java +++ b/app/src/main/java/de/sebse/fuplanner/MainActivity.java @@ -326,6 +326,9 @@ public class MainActivity extends AppCompatActivity if (mFragmentPage == FRAGMENT_SCHEDULE) { getMenuInflater().inflate(R.menu.options_schedule, menu); return true; + } else if (mFragmentPage == FRAGMENT_CANTEENS) { + getMenuInflater().inflate(R.menu.options_canteens, menu); + return true; } return false; } @@ -337,19 +340,35 @@ public class MainActivity extends AppCompatActivity // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); - //noinspection SimplifiableIfStatement - if (id == R.id.refresh) { - ScheduleFragment fragment = (ScheduleFragment) mFragmentManager.findFragmentByTag(String.valueOf(FRAGMENT_SCHEDULE)); - if (fragment != null && fragment.isVisible()) { - fragment.invalidate(true); + if (mFragmentPage == FRAGMENT_SCHEDULE) { + if (id == R.id.refresh) { + ScheduleFragment fragment = (ScheduleFragment) mFragmentManager.findFragmentByTag(String.valueOf(FRAGMENT_SCHEDULE)); + if (fragment != null && fragment.isVisible()) { + fragment.invalidate(true); + } + return true; + } else if (id == R.id.go_to_today) { + ScheduleFragment fragment = (ScheduleFragment) mFragmentManager.findFragmentByTag(String.valueOf(FRAGMENT_SCHEDULE)); + if (fragment != null && fragment.isVisible()) { + fragment.goToToday(); + } + return true; } - return true; - } else if (id == R.id.go_to_today) { - ScheduleFragment fragment = (ScheduleFragment) mFragmentManager.findFragmentByTag(String.valueOf(FRAGMENT_SCHEDULE)); - if (fragment != null && fragment.isVisible()) { - fragment.goToToday(); + } else if (mFragmentPage == FRAGMENT_CANTEENS) { + if (id == R.id.restore) { + CanteensFragment fragment = (CanteensFragment) mFragmentManager.findFragmentByTag(String.valueOf(FRAGMENT_CANTEENS)); + if (fragment != null && fragment.isVisible()) { + fragment.restoreDefaults(); + } + return true; + } + if (id == R.id.delete) { + CanteensFragment fragment = (CanteensFragment) mFragmentManager.findFragmentByTag(String.valueOf(FRAGMENT_CANTEENS)); + if (fragment != null && fragment.isVisible()) { + fragment.startDelete(); + } + return true; } - return true; } return super.onOptionsItemSelected(item); diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/CanteensAdapter.java b/app/src/main/java/de/sebse/fuplanner/fragments/CanteensAdapter.java index 729481f..51aa807 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/CanteensAdapter.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/CanteensAdapter.java @@ -7,12 +7,15 @@ import android.view.ViewGroup; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; + +import java.util.ArrayList; + import de.sebse.fuplanner.R; import de.sebse.fuplanner.fragments.CanteensFragment.OnCanteensFragmentInteractionListener; import de.sebse.fuplanner.services.canteen.types.Canteen; import de.sebse.fuplanner.services.canteen.types.Canteens; +import de.sebse.fuplanner.tools.ui.CanteensViewHolder; import de.sebse.fuplanner.tools.ui.CustomViewHolder; -import de.sebse.fuplanner.tools.ui.ItemViewHolder; import de.sebse.fuplanner.tools.ui.StringViewHolder; /** @@ -21,8 +24,14 @@ import de.sebse.fuplanner.tools.ui.StringViewHolder; */ class CanteensAdapter extends RecyclerView.Adapter { + private static final int TYPE_NO_LIST_AVAILABLE = 0; + private static final int TYPE_DELETE_BUTTON = 1; + private static final int TYPE_ENTRY = 2; private Canteens mValues; private final OnCanteensFragmentInteractionListener mListener; + private boolean mIsShowDeletion = false; + private ArrayList mDeleteCanteenIds = new ArrayList<>(); + private DeletionListener mDeletionListener; CanteensAdapter(OnCanteensFragmentInteractionListener listener) { mValues = null; @@ -37,27 +46,55 @@ class CanteensAdapter extends RecyclerView.Adapter { @NonNull @Override public CustomViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) { + if (viewType == TYPE_NO_LIST_AVAILABLE) { View view = LayoutInflater.from(parent.getContext()) .inflate(R.layout.list_all_no_items, parent, false); return new StringViewHolder(view); + } else if (viewType == TYPE_DELETE_BUTTON) { + View view = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.list_canteens_btn_delete, parent, false); + return new StringViewHolder(view); } View view = LayoutInflater.from(parent.getContext()) - .inflate(R.layout.list_all_items, parent, false); - return new ItemViewHolder(view); + .inflate(R.layout.list_canteens_items, parent, false); + return new CanteensViewHolder(view); } @Override public void onBindViewHolder(@NonNull CustomViewHolder holder, int position) { - if (holder instanceof StringViewHolder) { + int viewType = getItemViewType(position); + if (viewType == TYPE_NO_LIST_AVAILABLE) { ((StringViewHolder) holder).mString.setText(R.string.canteen_not_available); - } else if (holder instanceof ItemViewHolder) { + } else if (viewType == TYPE_DELETE_BUTTON) { + ((StringViewHolder) holder).mString.setOnClickListener(v -> endDeletion()); + } else { + if (mIsShowDeletion) { + position--; + } if (mValues == null) return; - Canteen canteen = mValues.get(holder.getAdapterPosition()); - ((ItemViewHolder) holder).mTitle.setText(canteen.getName()); - ((ItemViewHolder) holder).mSubLeft.setText(canteen.getAddress()); - ((ItemViewHolder) holder).mSubRight.setText(canteen.getCity()); + Canteen canteen = mValues.get(position); + ((CanteensViewHolder) holder).mTitle.setText(canteen.getName()); + ((CanteensViewHolder) holder).mSubLeft.setText(canteen.getAddress()); + ((CanteensViewHolder) holder).mSubRight.setText(canteen.getCity()); + ((CanteensViewHolder) holder).mRemoveIcon.setVisibility(mIsShowDeletion ? View.VISIBLE : View.GONE); + if (mDeleteCanteenIds.contains(canteen.getId())) { + ((CanteensViewHolder) holder).mRemoveIcon.setImageDrawable(holder.mView.getResources().getDrawable(R.drawable.ic_remove_circle)); + } else { + ((CanteensViewHolder) holder).mRemoveIcon.setImageDrawable(holder.mView.getResources().getDrawable(R.drawable.ic_remove_circle_outline)); + } + ((CanteensViewHolder) holder).mRemoveIcon.setOnClickListener(v -> { + if (mDeleteCanteenIds.contains(canteen.getId())) { + // Prevent calling remove with index + //noinspection SuspiciousMethodCalls + mDeleteCanteenIds.remove((Object) canteen.getId()); + } else { + mDeleteCanteenIds.add(canteen.getId()); + } + notifyDataSetChanged(); + }); + + holder.mView.setOnClickListener(v -> { if (null != mListener) { @@ -75,8 +112,40 @@ class CanteensAdapter extends RecyclerView.Adapter { return 1; } if (mValues != null) { - return mValues.size(); + return mIsShowDeletion ? mValues.size() + 1 : mValues.size(); } return 0; } + + @Override + public int getItemViewType(int position) { + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) { + return TYPE_NO_LIST_AVAILABLE; + } + return mIsShowDeletion && position == 0 ? TYPE_DELETE_BUTTON : TYPE_ENTRY; + } + + public void startDeletion(DeletionListener listener) { + mDeletionListener = listener; + if (mValues.size() > 0) { + mDeleteCanteenIds.clear(); + mIsShowDeletion = true; + notifyDataSetChanged(); + } + } + + public void endDeletion() { + int[] canteenIds = new int[mDeleteCanteenIds.size()]; + for (int i = 0; i < mDeleteCanteenIds.size(); i++) { + canteenIds[i] = mDeleteCanteenIds.get(i); + } + mDeletionListener.onDeletionFinished(canteenIds); + mDeleteCanteenIds.clear(); + mIsShowDeletion = false; + notifyDataSetChanged(); + } + + public interface DeletionListener { + void onDeletionFinished(int[] canteenIds); + } } diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/CanteensFragment.java b/app/src/main/java/de/sebse/fuplanner/fragments/CanteensFragment.java index 6612471..6d18a52 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/CanteensFragment.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/CanteensFragment.java @@ -11,10 +11,16 @@ import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; + import de.sebse.fuplanner.MainActivity; import de.sebse.fuplanner.R; import de.sebse.fuplanner.services.canteen.CanteenBrowser; import de.sebse.fuplanner.tools.MainActivityListener; +import de.sebse.fuplanner.tools.Preferences; import de.sebse.fuplanner.tools.logging.Logger; /** @@ -104,6 +110,44 @@ public class CanteensFragment extends Fragment { mMainActivityListener = null; } + public void restoreDefaults() { + Preferences.setArrayInt(requireContext(), R.string.pref_canteen_selection, null); + this.refresh(true); + } + + public void startDelete() { + log.d("start deletion"); + adapter.startDeletion(items -> { + int[] canteens = Preferences.getArrayInt(requireContext(), R.string.pref_canteen_selection); + if (canteens != null) { + ArrayList newList = new ArrayList<>(); + for (int canteen : canteens) { + boolean found = false; + for (int item : items) { + if (item == canteen) { + found = true; + break; + } + } + if (!found) { + newList.add(canteen); + } + } + int[] newCants = new int[newList.size()]; + for (int i = 0; i < newList.size(); i++) + newCants[i] = newList.get(i); + Preferences.setArrayInt(requireContext(), R.string.pref_canteen_selection, newCants); + } + this.refresh(true); + }); + /*int[] canteens = Preferences.getArrayInt(requireContext(), R.string.pref_canteen_selection); + int[] newCants = new int[canteens.length - 1]; + for (int i = 0; i < canteens.length - 1; i++) + newCants[i] = canteens[i]; + Preferences.setArrayInt(requireContext(), R.string.pref_canteen_selection, newCants); + this.refresh(true);*/ + } + public interface OnCanteensFragmentInteractionListener { void onCanteensFragmentInteraction(int id); } diff --git a/app/src/main/java/de/sebse/fuplanner/services/canteen/CanteenBrowser.java b/app/src/main/java/de/sebse/fuplanner/services/canteen/CanteenBrowser.java index 467ddcc..8d4a00b 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/canteen/CanteenBrowser.java +++ b/app/src/main/java/de/sebse/fuplanner/services/canteen/CanteenBrowser.java @@ -8,12 +8,15 @@ import org.json.JSONException; import org.json.JSONObject; import java.io.IOException; +import java.util.HashSet; +import de.sebse.fuplanner.R; import de.sebse.fuplanner.services.canteen.types.Canteen; import de.sebse.fuplanner.services.canteen.types.CanteenListener; import de.sebse.fuplanner.services.canteen.types.Canteens; import de.sebse.fuplanner.services.canteen.types.Day; import de.sebse.fuplanner.tools.AsyncQueue; +import de.sebse.fuplanner.tools.Preferences; import de.sebse.fuplanner.tools.network.HTTPService; import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkError; @@ -70,7 +73,22 @@ public class CanteenBrowser extends HTTPService { callback.onResponse(new Canteens()); return; } - get("https://openmensa.org/api/v2/canteens?near[lat]=52.449743&near[lng]=13.282245&near[dist]=7", null, response -> { + int[] visibleCanteens = Preferences.getArrayInt(context, R.string.pref_canteen_selection); + if (visibleCanteens == null) { + Preferences.setArrayInt(context, R.string.pref_canteen_selection, Canteens.availableCanteens); + visibleCanteens = Preferences.getArrayInt(context, R.string.pref_canteen_selection); + } + if (visibleCanteens == null || visibleCanteens.length == 0) { + callback.onResponse(new Canteens()); + return; + } + + StringBuilder ids = new StringBuilder(); + ids.append(visibleCanteens[0]); + for (int i = 1; i < visibleCanteens.length; i++) ids.append(",").append(visibleCanteens[i]); + + // "https://openmensa.org/api/v2/canteens?near[lat]=52.449743&near[lng]=13.282245&near[dist]=7" + get("https://openmensa.org/api/v2/canteens?ids=" + ids.toString(), null, response -> { String body = response.getParsed(); if (body == null) { errorCallback.onError(new NetworkError(201101, 403, "No canteen list retrieved!")); @@ -93,12 +111,7 @@ public class CanteenBrowser extends HTTPService { lat = coords.getDouble(0); lng = coords.getDouble(1); } - for (int cant : Canteens.availableCanteens) { - if (cant == id) { - canteens.addCanteen(id, name, city, address, lat, lng); - break; - } - } + canteens.addCanteen(id, name, city, address, lat, lng); } } catch (JSONException e) { e.printStackTrace(); diff --git a/app/src/main/java/de/sebse/fuplanner/tools/Preferences.java b/app/src/main/java/de/sebse/fuplanner/tools/Preferences.java index 1fb529c..b691414 100644 --- a/app/src/main/java/de/sebse/fuplanner/tools/Preferences.java +++ b/app/src/main/java/de/sebse/fuplanner/tools/Preferences.java @@ -1,6 +1,7 @@ package de.sebse.fuplanner.tools; import android.content.Context; +import android.content.SharedPreferences; import androidx.annotation.ArrayRes; import androidx.annotation.StringRes; @@ -39,4 +40,37 @@ public class Preferences { String string = context.getResources().getString(key); PreferenceManager.getDefaultSharedPreferences(context).edit().putBoolean(string, value).apply(); } + + public static int[] getArrayInt(Context context, @StringRes int key) { + String string = context.getResources().getString(key); + + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + if (!prefs.contains(string + "_size")) { + return null; + } + int size = prefs.getInt(string + "_size", 0); + int[] array = new int[size]; + for (int i = 0; i < size; i++) + array[i] = prefs.getInt(string + "_" + i, 0); + return array; + } + public static void setArrayInt(Context context, @StringRes int key, int[] value) { + String string = context.getResources().getString(key); + + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + SharedPreferences.Editor editor = prefs.edit(); + int oldSize = prefs.getInt(string + "_size", 0); + int newSize = 0; + if (value == null) { + editor.remove(string + "_size"); + } else { + newSize = value.length; + editor.putInt(string +"_size", newSize); + } + for (int i = 0; i < newSize; i++) + editor.putInt(string + "_" + i, value[i]); + for (int i = newSize; i < oldSize; i++) + editor.remove(string + "_" + i); + editor.apply(); + } } diff --git a/app/src/main/java/de/sebse/fuplanner/tools/ui/CanteensViewHolder.java b/app/src/main/java/de/sebse/fuplanner/tools/ui/CanteensViewHolder.java new file mode 100644 index 0000000..102ed2f --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/tools/ui/CanteensViewHolder.java @@ -0,0 +1,18 @@ +package de.sebse.fuplanner.tools.ui; + +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import de.sebse.fuplanner.R; + +public class CanteensViewHolder extends ItemViewHolder { + public final ImageView mRemoveIcon; + + public CanteensViewHolder(View view) { + super(view); + mRemoveIcon = view.findViewById(R.id.remove_icon); + } +} diff --git a/app/src/main/res/drawable/ic_remove_circle.xml b/app/src/main/res/drawable/ic_remove_circle.xml new file mode 100644 index 0000000..1f0cc00 --- /dev/null +++ b/app/src/main/res/drawable/ic_remove_circle.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_remove_circle_outline.xml b/app/src/main/res/drawable/ic_remove_circle_outline.xml new file mode 100644 index 0000000..98bef5e --- /dev/null +++ b/app/src/main/res/drawable/ic_remove_circle_outline.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/layout/list_canteens_btn_delete.xml b/app/src/main/res/layout/list_canteens_btn_delete.xml new file mode 100644 index 0000000..4655147 --- /dev/null +++ b/app/src/main/res/layout/list_canteens_btn_delete.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/app/src/main/res/layout/list_canteens_items.xml b/app/src/main/res/layout/list_canteens_items.xml new file mode 100644 index 0000000..5b7887f --- /dev/null +++ b/app/src/main/res/layout/list_canteens_items.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/options_canteens.xml b/app/src/main/res/menu/options_canteens.xml new file mode 100644 index 0000000..497ae58 --- /dev/null +++ b/app/src/main/res/menu/options_canteens.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 96c7f40..5d1fe95 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -115,4 +115,6 @@ Ein Netzwerkfehler ist aufgetreten: %s! App bewerten! Die Kantinenliste ist für Android 4 und darunter nicht verfügbar! + Einträge zurücksetzen + Einträge löschen \ No newline at end of file diff --git a/app/src/main/res/values/preferences.xml b/app/src/main/res/values/preferences.xml index 7786f35..011d100 100644 --- a/app/src/main/res/values/preferences.xml +++ b/app/src/main/res/values/preferences.xml @@ -1,5 +1,6 @@ + @string/pref_price_group @string/pref_price_group_default @@ -7,16 +8,20 @@ pref_price_group all - pref_last_visited_news - - pref_set_auto_sync_on_startup - - pref_shib_idp_session - @string/pref_sync_frequency @string/pref_sync_frequency_default pref_sync_frequency 6 + + + + pref_last_visited_news + + pref_set_auto_sync_on_startup + + pref_shib_idp_session + + pref_canteen_selection \ 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 cbeeba0..b57fafe 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -123,4 +123,6 @@ A network error occurred: %s! Rate the App! The canteen list is not available for Android 4 and below! + Restore Defaults + Delete Items