From b60336295e58412102bb634e8b9c2eda908d9ab2 Mon Sep 17 00:00:00 2001 From: Caesar2011 Date: Mon, 30 Jul 2018 00:59:18 +0200 Subject: [PATCH] Implemented Canteen Plan --- .idea/misc.xml | 2 +- .idea/modules.xml | 2 +- .idea/vcs.xml | 1 + .../java/de/sebse/fuplanner/MainActivity.java | 36 ++++- .../fuplanner/fragments/CanteensAdapter.java | 68 +++++++++ .../fuplanner/fragments/CanteensFragment.java | 110 ++++++++++++++ .../fragments/canteen/DaySwitcherAdapter.java | 47 ++++++ .../canteen/DaySwitcherFragment.java | 139 ++++++++++++++++++ .../canteen/DaySwitcherListener.java | 9 ++ .../fragments/canteen/MealAdapter.java | 116 +++++++++++++++ .../fragments/canteen/MealFragment.java | 128 ++++++++++++++++ .../services/Canteen/CanteenBrowser.java | 3 + .../services/Canteen/types/Canteen.java | 9 +- .../services/Canteen/types/Canteens.java | 11 +- .../fuplanner/services/Canteen/types/Day.java | 1 + .../tools/MainAcitivityListener.java | 4 + .../de/sebse/fuplanner/tools/SortedList.java | 8 + .../main/res/layout/fragment_modules_list.xml | 2 - app/src/main/res/values/strings.xml | 1 + datenschutz.md | 25 ++++ 20 files changed, 704 insertions(+), 18 deletions(-) create mode 100644 app/src/main/java/de/sebse/fuplanner/fragments/CanteensAdapter.java create mode 100644 app/src/main/java/de/sebse/fuplanner/fragments/CanteensFragment.java create mode 100644 app/src/main/java/de/sebse/fuplanner/fragments/canteen/DaySwitcherAdapter.java create mode 100644 app/src/main/java/de/sebse/fuplanner/fragments/canteen/DaySwitcherFragment.java create mode 100644 app/src/main/java/de/sebse/fuplanner/fragments/canteen/DaySwitcherListener.java create mode 100644 app/src/main/java/de/sebse/fuplanner/fragments/canteen/MealAdapter.java create mode 100644 app/src/main/java/de/sebse/fuplanner/fragments/canteen/MealFragment.java create mode 100644 datenschutz.md diff --git a/.idea/misc.xml b/.idea/misc.xml index 26dc4f5..4e024a8 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -25,5 +25,5 @@ - + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml index 62306f1..bee9e70 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -2,7 +2,7 @@ - + diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 94a25f7..8306744 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -1,6 +1,7 @@ + \ No newline at end of file diff --git a/app/src/main/java/de/sebse/fuplanner/MainActivity.java b/app/src/main/java/de/sebse/fuplanner/MainActivity.java index 2574d3f..83ec9ab 100644 --- a/app/src/main/java/de/sebse/fuplanner/MainActivity.java +++ b/app/src/main/java/de/sebse/fuplanner/MainActivity.java @@ -20,10 +20,12 @@ import android.widget.TextView; import java.util.Iterator; +import de.sebse.fuplanner.fragments.CanteensFragment; import de.sebse.fuplanner.fragments.LoginFragment; import de.sebse.fuplanner.fragments.ModulesFragment; import de.sebse.fuplanner.fragments.ScheduleFragment; import de.sebse.fuplanner.fragments.StartupFragment; +import de.sebse.fuplanner.fragments.canteen.DaySwitcherFragment; import de.sebse.fuplanner.fragments.moddetails.ModDetailFragment; import de.sebse.fuplanner.services.Canteen.CanteenBrowser; import de.sebse.fuplanner.services.Canteen.types.Canteen; @@ -38,7 +40,8 @@ public class MainActivity extends AppCompatActivity implements MainAcitivityListener, NavigationView.OnNavigationItemSelectedListener, LoginFragment.OnLoginFragmentInteractionListener, - ModulesFragment.OnModulesFragmentInteractionListener { + ModulesFragment.OnModulesFragmentInteractionListener, + CanteensFragment.OnCanteensFragmentInteractionListener { private static final int FRAGMENT_NONE = -1; private static final int FRAGMENT_STARTUP = 0; @@ -46,7 +49,8 @@ public class MainActivity extends AppCompatActivity private static final int FRAGMENT_MODULES_DETAILS = 2; private static final int FRAGMENT_LOGIN = 3; private static final int FRAGMENT_SCHEDULE = 4; - private static final int FRAGMENT_CANTEEN = 5; + private static final int FRAGMENT_CANTEENS = 5; + private static final int FRAGMENT_CANTEENS_DETAILS = 6; private static final String ARG_FRAGMENT_PAGE = "fragment_page"; private static final String ARG_FRAGMENT_STATUS = "fragment_status"; @@ -165,6 +169,9 @@ public class MainActivity extends AppCompatActivity case R.id.nav_schedule: changeFragment(FRAGMENT_SCHEDULE); break; + case R.id.nav_dining: + changeFragment(FRAGMENT_CANTEENS); + break; case R.id.nav_share: Intent sendIntent = new Intent(); sendIntent.setAction(Intent.ACTION_SEND); @@ -188,7 +195,6 @@ public class MainActivity extends AppCompatActivity int size = mNavigationView.getMenu().size(); for (int k = 0; k < size; k++) { - //mNavigationView.getMenu().getItem(k).setChecked(mNavigationView.getMenu().getItem(k).getOrder() == 101+itemPosition); mNavigationView.getMenu().getItem(k).setChecked(mNavigationView.getMenu().getItem(k) == item); } item.setChecked(true); @@ -291,6 +297,10 @@ public class MainActivity extends AppCompatActivity fragment = LoginFragment.newInstance(); } else if (newFragment == FRAGMENT_SCHEDULE) { fragment = ScheduleFragment.newInstance(); + } else if (newFragment == FRAGMENT_CANTEENS) { + fragment = CanteensFragment.newInstance(); + } else if (newFragment == FRAGMENT_CANTEENS_DETAILS) { + fragment = DaySwitcherFragment.newInstance(Integer.parseInt(newData)); } else { // FRAGMENT_STARTUP fragment = StartupFragment.newInstance(); } @@ -354,6 +364,17 @@ public class MainActivity extends AppCompatActivity } }, log::e); } + if (newFragment == FRAGMENT_CANTEENS_DETAILS) { + getCanteenBrowser().getCanteens(success -> { + int size = mNavigationView.getMenu().size(); + Canteen canteen = success.getCanteen(Integer.parseInt(newData)); + //noinspection ConstantConditions + String title = canteen == null ? null : canteen.getName(); + for (int k = 0; k < size; k++) { + mNavigationView.getMenu().getItem(k).setChecked(mNavigationView.getMenu().getItem(k).getTitle().equals(title)); + } + }, log::e); + } this.fragmentPage = newFragment; this.fragmentData = newData; @@ -382,9 +403,10 @@ public class MainActivity extends AppCompatActivity private void afterAnyMenuInflate() { getCanteenBrowser().getCanteens(success -> { int i = 0; - for (Canteen module : success) { - MenuItem menuItem = mNavigationView.getMenu().add(Menu.NONE, Menu.NONE, 201 + i, module.getName()); + for (Canteen canteen: success) { + MenuItem menuItem = mNavigationView.getMenu().add(Menu.NONE, Menu.NONE, 201 + i, canteen.getName()); menuItem.setOnMenuItemClickListener(item -> { + onCanteensFragmentInteraction(canteen.getId()); return false; }); i++; @@ -406,6 +428,10 @@ public class MainActivity extends AppCompatActivity changeFragment(FRAGMENT_MODULES_DETAILS, itemID); } + public void onCanteensFragmentInteraction(final int itemID) { + changeFragment(FRAGMENT_CANTEENS_DETAILS, String.valueOf(itemID)); + } + public void onTitleTextChange(String newTitle) { setTitle(newTitle); } diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/CanteensAdapter.java b/app/src/main/java/de/sebse/fuplanner/fragments/CanteensAdapter.java new file mode 100644 index 0000000..341a353 --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/fragments/CanteensAdapter.java @@ -0,0 +1,68 @@ +package de.sebse.fuplanner.fragments; + +import android.support.annotation.NonNull; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +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.services.KVV.types.Modules; +import de.sebse.fuplanner.tools.ui.ItemViewHolder; + +/** + * {@link RecyclerView.Adapter} that can display a {@link Modules.Module} and makes a call to the + * specified {@link OnCanteensFragmentInteractionListener}. + */ +public class CanteensAdapter extends RecyclerView.Adapter { + + private Canteens mValues; + private final OnCanteensFragmentInteractionListener mListener; + + CanteensAdapter(OnCanteensFragmentInteractionListener listener) { + mValues = null; + mListener = listener; + } + + public void setCanteens(Canteens canteens) { + mValues = canteens; + this.notifyDataSetChanged(); + } + + @NonNull + @Override + public ItemViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.list_all_items, parent, false); + return new ItemViewHolder(view); + } + + @Override + public void onBindViewHolder(@NonNull ItemViewHolder holder, int position) { + if (mValues == null) + return; + Canteen canteen = mValues.get(holder.getAdapterPosition()); + holder.mTitle.setText(canteen.getName()); + holder.mSubLeft.setText(canteen.getAddress()); + holder.mSubRight.setText(canteen.getCity()); + + holder.mView.setOnClickListener(v -> { + if (null != mListener) { + // Notify the active callbacks interface (the activity, if the + // fragment is attached to one) that an item has been selected. + mListener.onCanteensFragmentInteraction(canteen.getId()); + } + }); + } + + @Override + public int getItemCount() { + if (mValues != null) { + return mValues.size(); + } + return 0; + } +} diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/CanteensFragment.java b/app/src/main/java/de/sebse/fuplanner/fragments/CanteensFragment.java new file mode 100644 index 0000000..2314b8e --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/fragments/CanteensFragment.java @@ -0,0 +1,110 @@ +package de.sebse.fuplanner.fragments; + +import android.content.Context; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.Fragment; +import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import de.sebse.fuplanner.MainActivity; +import de.sebse.fuplanner.R; +import de.sebse.fuplanner.services.Canteen.CanteenBrowser; +import de.sebse.fuplanner.tools.MainAcitivityListener; +import de.sebse.fuplanner.tools.logging.Logger; + +/** + * A fragment representing a list of Items. + *

+ * Activities containing this fragment MUST implement the {@link OnCanteensFragmentInteractionListener} + * interface. + */ +public class CanteensFragment extends Fragment { + private OnCanteensFragmentInteractionListener mListener; + private Logger log = new Logger(this); + private CanteensAdapter adapter; + private SwipeRefreshLayout swipeLayout; + + /** + * Mandatory empty constructor for the fragment manager to instantiate the + * fragment (e.g. upon screen orientation changes). + */ + public CanteensFragment() { + } + + public static CanteensFragment newInstance() { + CanteensFragment fragment = new CanteensFragment(); + Bundle args = new Bundle(); + fragment.setArguments(args); + return fragment; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + + View view = inflater.inflate(R.layout.fragment_modules_list, container, false); + // Set the adapter + Context context = view.getContext(); + RecyclerView recyclerView = view.findViewById(R.id.list); + recyclerView.setLayoutManager(new LinearLayoutManager(context)); + adapter = new CanteensAdapter(mListener); + recyclerView.setAdapter(adapter); + + // Getting SwipeContainerLayout + swipeLayout = view.findViewById(R.id.swipe_container); + // Adding Listener + swipeLayout.setOnRefreshListener(() -> refresh(true)); + refresh(false); + + return view; + } + + private void refresh(boolean forceRefresh) { + if (getActivity() != null) { + CanteenBrowser browser = ((MainActivity) getActivity()).getCanteenBrowser(); + browser.getCanteens(success -> { + adapter.setCanteens(success); + swipeLayout.setRefreshing(false); + }, error -> { + log.e(error.toString()); + swipeLayout.setRefreshing(false); + }, forceRefresh); + } + } + + + @Override + public void onAttach(Context context) { + super.onAttach(context); + if (context instanceof OnCanteensFragmentInteractionListener) { + mListener = (OnCanteensFragmentInteractionListener) context; + } else { + throw new RuntimeException(context.toString() + + " must implement OnCanteensFragmentInteractionListener"); + } + if (context instanceof MainAcitivityListener) + ((MainAcitivityListener) context).onTitleTextChange(R.string.canteens); + else + throw new RuntimeException(context.toString() + "must implement MainActivityListener"); + } + + @Override + public void onDetach() { + super.onDetach(); + mListener = null; + } + + public interface OnCanteensFragmentInteractionListener { + void onCanteensFragmentInteraction(int id); + } +} diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/canteen/DaySwitcherAdapter.java b/app/src/main/java/de/sebse/fuplanner/fragments/canteen/DaySwitcherAdapter.java new file mode 100644 index 0000000..b8a54e1 --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/fragments/canteen/DaySwitcherAdapter.java @@ -0,0 +1,47 @@ +package de.sebse.fuplanner.fragments.canteen; + +import android.content.Context; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentStatePagerAdapter; + +import de.sebse.fuplanner.services.Canteen.types.Canteen; +import de.sebse.fuplanner.tools.DateUtils; +import de.sebse.fuplanner.tools.logging.Logger; + +class DaySwitcherAdapter extends FragmentStatePagerAdapter { + private Canteen mCanteen = null; + + DaySwitcherAdapter(FragmentManager fm) { + super(fm); + } + + public void setModule(Canteen canteen) { + mCanteen = canteen; + this.setModule(); + } + + public void setModule() { + this.notifyDataSetChanged(); + } + + + // Returns total number of pages + @Override + public int getCount() { + return mCanteen == null ? 0 : mCanteen.size(); + } + + // Returns the fragment to display for that page + @Override + public Fragment getItem(int position) { + return MealFragment.newInstance(mCanteen.getId(), position); + } + + // Returns the page title for the top indicator + @Override + public CharSequence getPageTitle(int position) { + return DateUtils.getModifiedDate(mCanteen.get(position).getCalendar().getTimeInMillis()); + } + +} diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/canteen/DaySwitcherFragment.java b/app/src/main/java/de/sebse/fuplanner/fragments/canteen/DaySwitcherFragment.java new file mode 100644 index 0000000..96b076a --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/fragments/canteen/DaySwitcherFragment.java @@ -0,0 +1,139 @@ +package de.sebse.fuplanner.fragments.canteen; + +import android.content.Context; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.Fragment; +import android.support.v4.view.ViewPager; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import de.sebse.fuplanner.MainActivity; +import de.sebse.fuplanner.R; +import de.sebse.fuplanner.services.Canteen.CanteenBrowser; +import de.sebse.fuplanner.services.Canteen.types.Canteen; +import de.sebse.fuplanner.tools.MainAcitivityListener; +import de.sebse.fuplanner.tools.logging.Logger; +import de.sebse.fuplanner.tools.network.NetworkCallback; +import de.sebse.fuplanner.tools.network.NetworkErrorCallback; + +/** + * A simple {@link Fragment} subclass. + * Activities that contain this fragment must implement the + * {@link MainAcitivityListener} interface + * to handle interaction events. + * Use the {@link DaySwitcherFragment#newInstance} factory method to + * create an instance of this fragment. + */ +public class DaySwitcherFragment extends Fragment implements DaySwitcherListener { + private static final String ARG_POSITION = "canteenId"; + + // Parameters + private int mCanteenId; + + private MainAcitivityListener mListener; + private Logger log = new Logger(this); + private ViewPager mViewPager; + private DaySwitcherAdapter adapterViewPager; + + public DaySwitcherFragment() { + // Required empty public constructor + } + + /** + * Use this factory method to create a new instance of + * this fragment using the provided parameters. + * + * @param canteenId Canteen id in canteens list. + * @return A new instance of fragment DaySwitcherFragment. + */ + public static Fragment newInstance(int canteenId) { + DaySwitcherFragment fragment = new DaySwitcherFragment(); + Bundle args = new Bundle(); + args.putInt(ARG_POSITION, canteenId); + fragment.setArguments(args); + return fragment; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (getArguments() != null) { + mCanteenId = getArguments().getInt(ARG_POSITION); + } + if (mListener != null) { + mListener.onTitleTextChange(R.string.canteens); + mListener.getCanteenBrowser().getCanteens(success -> { + Canteen canteen = success.getCanteen(mCanteenId); + if (mListener != null && canteen != null) + mListener.onTitleTextChange(canteen.getName()); + }, log::e); + } + } + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + // Inflate the layout for this fragment + View v = inflater.inflate(R.layout.fragment_mod_detail, container, false); + + mViewPager = v.findViewById(R.id.vpPager); + adapterViewPager = new DaySwitcherAdapter(getChildFragmentManager()); + mViewPager.setAdapter(adapterViewPager); + + refresh(false); + + return v; + } + + @Override + public void onAttach(Context context) { + super.onAttach(context); + if (context instanceof MainAcitivityListener) { + mListener = (MainAcitivityListener) context; + } else { + throw new RuntimeException(context.toString() + + " must implement MainActivityListener"); + } + } + + @Override + public void onDetach() { + super.onDetach(); + mListener = null; + } + + private void refresh(boolean forceRefresh) { + refresh(forceRefresh, null, null); + } + + private void refresh(boolean forceRefresh, NetworkCallback callback, NetworkErrorCallback errorCallback) { + if (getActivity() != null) { + CanteenBrowser browser = ((MainActivity) getActivity()).getCanteenBrowser(); + browser.getCanteens(canteens -> { + Canteen canteen = canteens.getCanteen(mCanteenId); + adapterViewPager.setModule(canteen); + browser.getCanteen(canteen, success -> { + adapterViewPager.setModule(); + if (callback != null) + callback.onResponse(success); + }, error -> { + log.e(error); + if (errorCallback != null) + errorCallback.onError(error); + }, forceRefresh); + }, error -> { + log.e(error); + if (errorCallback != null) + errorCallback.onError(error); + }, forceRefresh); + } + } + + @Override + public void onChildRefresh(NetworkCallback callback, NetworkErrorCallback errorCallback) { + refresh(true, callback, errorCallback); + } + +} diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/canteen/DaySwitcherListener.java b/app/src/main/java/de/sebse/fuplanner/fragments/canteen/DaySwitcherListener.java new file mode 100644 index 0000000..c80eb83 --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/fragments/canteen/DaySwitcherListener.java @@ -0,0 +1,9 @@ +package de.sebse.fuplanner.fragments.canteen; + +import de.sebse.fuplanner.services.Canteen.types.Canteen; +import de.sebse.fuplanner.tools.network.NetworkCallback; +import de.sebse.fuplanner.tools.network.NetworkErrorCallback; + +public interface DaySwitcherListener { + void onChildRefresh(NetworkCallback callback, NetworkErrorCallback errorCallback); +} diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/canteen/MealAdapter.java b/app/src/main/java/de/sebse/fuplanner/fragments/canteen/MealAdapter.java new file mode 100644 index 0000000..975c614 --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/fragments/canteen/MealAdapter.java @@ -0,0 +1,116 @@ +package de.sebse.fuplanner.fragments.canteen; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseExpandableListAdapter; + +import de.sebse.fuplanner.R; +import de.sebse.fuplanner.services.Canteen.types.Day; +import de.sebse.fuplanner.services.Canteen.types.Meal; +import de.sebse.fuplanner.services.KVV.types.Assignment; +import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.tools.DateUtils; +import de.sebse.fuplanner.tools.ui.ItemViewHolder; +import de.sebse.fuplanner.tools.ui.StringViewHolder; + +public class MealAdapter extends BaseExpandableListAdapter { + + private Day mDay = null; + + @Override + public String getChild(int groupPosition, int childPosititon) { + StringBuilder sb = new StringBuilder(); + sb.append("\n\n"); + for (String s : this.getGroup(groupPosition).getNotes()) + { + sb.append(s); + sb.append("\n\n"); + } + return sb.toString(); + } + + @Override + public long getChildId(int groupPosition, int childPosition) { + return childPosition; + } + + @Override + public View getChildView(int groupPosition, final int childPosition, + boolean isLastChild, View convertView, ViewGroup parent) { + + final String childText = getChild(groupPosition, childPosition); + + if (convertView == null) { + convertView = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.list_all_string, parent, false); + } + + StringViewHolder itemHolder = new StringViewHolder(convertView); + itemHolder.mString.setText(childText); + + return convertView; + } + + @Override + public int getChildrenCount(int groupPosition) { + return 1; + } + + @Override + public Meal getGroup(int groupPosition) { + if (this.mDay != null) + return this.mDay.get(groupPosition); + else + return null; + } + + @Override + public int getGroupCount() { + if (this.mDay != null) + return this.mDay.size(); + else + return 0; + } + + @Override + public long getGroupId(int groupPosition) { + return groupPosition; + } + + @Override + public View getGroupView(int groupPosition, boolean isExpanded, + View convertView, ViewGroup parent) { + Meal meal = getGroup(groupPosition); + if (convertView == null) { + convertView = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.list_all_items, parent, false); + } + + ItemViewHolder itemHolder = new ItemViewHolder(convertView); + itemHolder.mTitle.setText(meal.getName()); + itemHolder.mSubLeft.setText(meal.getCategory()); + itemHolder.mSubRight.setText(meal.getPriceStdnt()+"/"+meal.getPriceEmply()+"/"+meal.getPriceOther()); + + return convertView; + } + + @Override + public boolean hasStableIds() { + return false; + } + + @Override + public boolean isChildSelectable(int groupPosition, int childPosition) { + return false; + } + + public void setDay(Day day) { + this.mDay = day; + this.setDay(); + } + + public void setDay() { + this.notifyDataSetChanged(); + } +} \ No newline at end of file diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/canteen/MealFragment.java b/app/src/main/java/de/sebse/fuplanner/fragments/canteen/MealFragment.java new file mode 100644 index 0000000..e53daa3 --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/fragments/canteen/MealFragment.java @@ -0,0 +1,128 @@ +package de.sebse.fuplanner.fragments.canteen; + + +import android.content.Context; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.Fragment; +import android.support.v4.widget.SwipeRefreshLayout; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ExpandableListView; + +import de.sebse.fuplanner.MainActivity; +import de.sebse.fuplanner.R; +import de.sebse.fuplanner.services.Canteen.CanteenBrowser; +import de.sebse.fuplanner.services.Canteen.types.Canteen; +import de.sebse.fuplanner.services.Canteen.types.Day; +import de.sebse.fuplanner.tools.logging.Logger; + +/** + * A simple {@link Fragment} subclass. + * Use the {@link MealFragment#newInstance} factory method to + * create an instance of this fragment. + */ +public class MealFragment extends Fragment { + private static final String ARG_POSITION = "canteenId"; + private static final String ARG_DAY_ID = "dayPosition"; + + private int mCanteenId; + private int mDayPosition; + private Logger log = new Logger(this); + private MealAdapter adapter; + private SwipeRefreshLayout swipeLayout; + private DaySwitcherListener mListener; + + + public MealFragment() { + // Required empty public constructor + } + + /** + * Use this factory method to create a new instance of + * this fragment using the provided parameters. + * + * @param canteenId Item position in module list. + * @param dayPosition Item position in module list. + * @return A new instance of fragment ModDetailAnnounceFragment. + */ + public static MealFragment newInstance(int canteenId, int dayPosition) { + MealFragment fragment = new MealFragment(); + Bundle args = new Bundle(); + args.putInt(ARG_POSITION, canteenId); + args.putInt(ARG_DAY_ID, dayPosition); + fragment.setArguments(args); + return fragment; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (getArguments() != null) { + mCanteenId = getArguments().getInt(ARG_POSITION); + mDayPosition = getArguments().getInt(ARG_DAY_ID); + } + } + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + // Inflate the layout for this fragment + View view = inflater.inflate(R.layout.fragment_expandable_list_view, container, false); + // Set the adapter + ExpandableListView expandableListView = view.findViewById(R.id.list); + adapter = new MealAdapter(); + expandableListView.setAdapter(adapter); + + // Getting SwipeContainerLayout + swipeLayout = view.findViewById(R.id.swipe_container); + // Adding Listener + swipeLayout.setOnRefreshListener(() -> { + mListener.onChildRefresh(callback -> refresh(true), error -> refresh(true)); + }); + refresh(false); + + return view; + } + + @Override + public void onAttach(Context context) { + super.onAttach(context); + Fragment parentFragment = getParentFragment(); + if (parentFragment != null) { + if (parentFragment instanceof DaySwitcherListener) { + mListener = (DaySwitcherListener) parentFragment; + } else { + throw new RuntimeException(context.toString() + + " must implement DaySwitcherListener"); + } + } else log.w("No parent fragment!"); + } + + private void refresh(boolean forceRefresh) { + if (getActivity() != null) { + CanteenBrowser browser = ((MainActivity) getActivity()).getCanteenBrowser(); + browser.getCanteens(canteens -> { + Canteen canteen = canteens.getCanteen(mCanteenId); + browser.getCanteen(canteen, success -> { + Day day = success.get(mDayPosition); + adapter.setDay(day); + browser.getDay(day, success1 -> { + adapter.setDay(); + swipeLayout.setRefreshing(false); + }, error -> { + swipeLayout.setRefreshing(false); + log.e(error); + }, forceRefresh); + }, error -> { + swipeLayout.setRefreshing(false); + log.e(error); + }, forceRefresh); + }, error -> { + swipeLayout.setRefreshing(false); + log.e(error); + }, forceRefresh); + } + } +} 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 c7afe40..790fe3b 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 @@ -46,6 +46,7 @@ public class CanteenBrowser extends HTTPService { return; } this.upgradeCanteens(success -> { + log.d("updated canteen list"); if (this.canteens == null) this.canteens = success; else @@ -110,6 +111,7 @@ public class CanteenBrowser extends HTTPService { return; } this.upgradeCanteen(canteen, success -> { + log.d("updated canteen"); canteen.update(success); this.save(); callback.onResponse(canteen); @@ -157,6 +159,7 @@ public class CanteenBrowser extends HTTPService { return; } this.upgradeDay(day, success -> { + log.d("updated day"); day.update(success); this.save(); callback.onResponse(day); diff --git a/app/src/main/java/de/sebse/fuplanner/services/Canteen/types/Canteen.java b/app/src/main/java/de/sebse/fuplanner/services/Canteen/types/Canteen.java index f914eea..c948706 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/Canteen/types/Canteen.java +++ b/app/src/main/java/de/sebse/fuplanner/services/Canteen/types/Canteen.java @@ -34,7 +34,8 @@ public class Canteen implements Serializable, Iterable { addDay(day); } - private void addDay(@NonNull Day day) { + void addDay(@NonNull Day day) { + if (this.list.contains(day)) return; if (!day.isClosed()) { this.list.add(day); } @@ -58,12 +59,8 @@ public class Canteen implements Serializable, Iterable { } public void update(Canteen canteen) { - SortedListDay oldList = this.list; + // remove loaded meals when updating days of a canteen this.list = canteen.list; - for (Day oldDay: oldList) { - Day newDay = getDay(oldDay.getCalendar()); - if (newDay != null) newDay.update(oldDay); - } } @NonNull diff --git a/app/src/main/java/de/sebse/fuplanner/services/Canteen/types/Canteens.java b/app/src/main/java/de/sebse/fuplanner/services/Canteen/types/Canteens.java index d70dad1..2d86cad 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/Canteen/types/Canteens.java +++ b/app/src/main/java/de/sebse/fuplanner/services/Canteen/types/Canteens.java @@ -16,7 +16,7 @@ public class Canteens implements Serializable, Iterable { private static final String FILE_NAME = "CanteensSaving"; private SortedListCanteen list = new SortedListCanteen(); - private Canteen getCanteen(int id) { + public Canteen getCanteen(int id) { return this.list.getById(id); } @@ -26,10 +26,11 @@ public class Canteens implements Serializable, Iterable { } private void addCanteen(Canteen canteen) { + if (this.list.contains(canteen)) return; this.list.add(canteen); } - private int size() { + public int size() { return this.list.size(); } @@ -42,7 +43,11 @@ public class Canteens implements Serializable, Iterable { this.list = canteens.list; for (Canteen oldCanteen: oldList) { Canteen newCanteen = getCanteen(oldCanteen.getId()); - if (newCanteen != null) newCanteen.update(oldCanteen); + if (newCanteen != null) { + for (Day day: oldCanteen) { + newCanteen.addDay(day); + } + } } } diff --git a/app/src/main/java/de/sebse/fuplanner/services/Canteen/types/Day.java b/app/src/main/java/de/sebse/fuplanner/services/Canteen/types/Day.java index 4270ebd..9806a3a 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/Canteen/types/Day.java +++ b/app/src/main/java/de/sebse/fuplanner/services/Canteen/types/Day.java @@ -24,6 +24,7 @@ public class Day implements Serializable, Iterable { public void addMeal(int id, String name, String category, double priceStdnt, double priceEmply, double priceOther, String[] notes) { Meal meal = new Meal(id, name, category, priceStdnt, priceEmply, priceOther, notes); + if (this.list.contains(meal)) return; this.list.add(meal); } diff --git a/app/src/main/java/de/sebse/fuplanner/tools/MainAcitivityListener.java b/app/src/main/java/de/sebse/fuplanner/tools/MainAcitivityListener.java index 40facdd..9bdb11f 100644 --- a/app/src/main/java/de/sebse/fuplanner/tools/MainAcitivityListener.java +++ b/app/src/main/java/de/sebse/fuplanner/tools/MainAcitivityListener.java @@ -2,6 +2,8 @@ package de.sebse.fuplanner.tools; import android.support.annotation.StringRes; +import de.sebse.fuplanner.fragments.canteen.DaySwitcherFragment; +import de.sebse.fuplanner.services.Canteen.CanteenBrowser; import de.sebse.fuplanner.services.GoogleAuth.GoogleAuth; import de.sebse.fuplanner.services.KVV.KVV; @@ -17,4 +19,6 @@ public interface MainAcitivityListener { void loginTokenInvalid(boolean doPrecheck); void refreshFailed(boolean isFailed); + + CanteenBrowser getCanteenBrowser(); } diff --git a/app/src/main/java/de/sebse/fuplanner/tools/SortedList.java b/app/src/main/java/de/sebse/fuplanner/tools/SortedList.java index 1e57efe..6137cf1 100644 --- a/app/src/main/java/de/sebse/fuplanner/tools/SortedList.java +++ b/app/src/main/java/de/sebse/fuplanner/tools/SortedList.java @@ -45,6 +45,14 @@ public abstract class SortedList implements Iterable, Serializable { return internalList.size(); } + public boolean contains(T o1) { + for (T o2 : this.internalList) { + if (compare(o1, o2) == 0) + return true; + } + return false; + } + @NonNull @Override public Iterator iterator() { diff --git a/app/src/main/res/layout/fragment_modules_list.xml b/app/src/main/res/layout/fragment_modules_list.xml index d8ea530..546bc96 100644 --- a/app/src/main/res/layout/fragment_modules_list.xml +++ b/app/src/main/res/layout/fragment_modules_list.xml @@ -8,12 +8,10 @@ android:layout_width="match_parent" android:layout_height="match_parent"> \ 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 4d809c7..a0c701c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -44,4 +44,5 @@ https://play.google.com/store/apps/details?id=de.sebse.fuplanner Refresh Go to today + Canteens diff --git a/datenschutz.md b/datenschutz.md new file mode 100644 index 0000000..8d4dc66 --- /dev/null +++ b/datenschutz.md @@ -0,0 +1,25 @@ +# Informationen zur Datenverarbeitung + +Diese Datenschutzinformationen betreffen die Android-App _FUPlanner_. + +Im Folgenden klären wir auf, wie wir den gesetzlichen Aufklärungs- und Informationspflichen bestmöglich nachkommen. Wir erläutern, wie die App die Daten veratbeitet und welche Daten an Dienste gesendet werde. Die Anbindung an die Server von "KVV der FU-Berlin", + + + + + + +Der Schutz Ihrer Daten ist wichtig. In Folge dessen und um selbstverständlich allen uns obliegenden gesetzlichen Informations- und Aufklärungspflichten nachzukommen, informieren wir Sie nachfolgend darüber wie wir, die Anwaltskanzlei Diercks, welche diesen Blog betreibt, Ihre Daten verarbeiten und welche Rechte Ihnen hinsichtlich der Datenverarbeitung zustehen. Ferner klären wir Sie darüber auf, soweit wir – Stand 06.06.2018 – können, welche Daten bei der Nutzung unserer Facebook-Seite von uns bzw. Facebook verarbeitet werden. +Informationen zur Datenverarbeitung im Hinblick auf den Blog +Gegenstand des Datenschutzes + +Gegenstand des Datenschutzes sind personenbezogene Daten. Dies sind nach Art. 4 Nr. 1 DSGVO alle Informationen, die sich auf eine identifizierte oder identifizierbare Person beziehen. Hierunter fallen z.B. Angaben wie Namen, Post-Adressen, E-Mail-Adressen oder Telefonnummern, aber auch Nutzungsdaten wie Ihre IP-Adresse oder Inhaltsdaten wie die von Ihnen möglicherweise abgegebenen Kommentare unter Beiträgen oder die Nachrichten, die Sie uns über das Kontaktformular übersenden. +Umfang sowie Zwecke der Datenverarbeitung + +Im Folgenden klären wir Sie über den Umfang der Datenerhebung und -speicherung sowie deren Nutzung und über den Zweck der jeweiligen Datenerhebung im Rahmen der Nutzung dieser Webseite auf. (Im Folgenden „Datenverarbeitung“, verwendet im Sinne von Art. 4 Nr. 2 DSGVO) + +Die Nutzung unseres Blogs ist ohne die Angaben von personenbezogenen Daten möglich – naja, fast. Schließlich müssen wir Ihre IP-Adresse verarbeiten, um Ihnen dieses Blog im Internet anzeigen zu können (siehe im einzelnen dazu „Verarbeitung der IP-Adresse“). + +Wenn Sie allerdings unseren Blog nicht nur zum fröhlichen Lesevergnügen besuchen, nicht nur zu Informationszwecken besuchen, sondern vielleicht den Newsletter abonnieren, einen Artikel kommentieren, das Kontaktformular nutzen oder uns eine E-Mail-Adresse übersenden, dann, ja dann erhalten wir von Ihnen natürlich personenbezogene Daten (mehr dazu unter Kommentierung bzw. Kontaktaufnahme via E-Mail oder dem Kontaktformular). + +Bitte beachten Sie auch unsere Hinweise zu den Social PlugIns und zu Cookies. \ No newline at end of file