From ddefb384024d1542553483c041f8aa48e462b5a9 Mon Sep 17 00:00:00 2001 From: Caesar2011 Date: Thu, 5 Jul 2018 12:19:50 +0200 Subject: [PATCH 1/5] Refesh on error fixed --- .idea/misc.xml | 2 +- .idea/modules.xml | 2 +- .idea/vcs.xml | 1 - .../moddetails/ModDetailOverviewFragment.java | 10 ++++++++-- .../fuplanner/services/KVV/KVVModuleList.java | 20 ++++++++++++------- .../fuplanner/services/KVV/types/Modules.java | 8 +++++++- .../de/sebse/fuplanner/tools/AsyncQueue.java | 3 +++ 7 files changed, 33 insertions(+), 13 deletions(-) diff --git a/.idea/misc.xml b/.idea/misc.xml index 4e024a8..a8cce1b 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 bee9e70..62306f1 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -2,7 +2,7 @@ - + diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 8306744..35eb1dd 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -2,6 +2,5 @@ - \ No newline at end of file diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailOverviewFragment.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailOverviewFragment.java index 01cf213..a03c5b4 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailOverviewFragment.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailOverviewFragment.java @@ -94,8 +94,14 @@ public class ModDetailOverviewFragment extends Fragment { adapter.setModule(); if (pair.second) swipeLayout.setRefreshing(false); - }, error -> log.e(error)); - }, error -> log.e(error), forceRefresh); + }, error -> { + swipeLayout.setRefreshing(false); + log.e(error); + }); + }, error -> { + swipeLayout.setRefreshing(false); + log.e(error); + }, forceRefresh); } } diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModuleList.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModuleList.java index aa3a10d..7a3a377 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModuleList.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModuleList.java @@ -44,7 +44,9 @@ public class KVVModuleList extends HTTPService { super(context); this.token = token; try { - this.moduleList = Modules.load(context); + Modules modules = Modules.load(context); + if (modules.getUsername().equals(token.getUsername())) + this.moduleList = modules; } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { @@ -56,7 +58,9 @@ public class KVVModuleList extends HTTPService { public void getModuleList(final NetworkCallback callback, final NetworkErrorCallback errorCallback, boolean forceRefresh) { + log.d("getModuleList"); queueModuleDetails.add("list", () -> { + log.d("getModuleList start", forceRefresh); if (this.moduleList != null && !forceRefresh) { callback.onResponse(this.moduleList); queueModuleDetails.next("list"); @@ -66,7 +70,7 @@ public class KVVModuleList extends HTTPService { this.moduleList = success; callback.onResponse(this.moduleList); queueModuleDetails.next("list"); - }, errorCallback); + }, queueModuleDetails.check("list", errorCallback)); }); } @@ -77,7 +81,7 @@ public class KVVModuleList extends HTTPService { errorCallback.onError(new NetworkError(101101, 403, "No module list retrieved!")); return; } - Modules modules = new Modules(); + Modules modules = new Modules(token.getUsername()); try { JSONObject json = new JSONObject(body); JSONArray sites = json.getJSONArray("site_collection"); @@ -136,6 +140,7 @@ public class KVVModuleList extends HTTPService { AtomicReference lastError = new AtomicReference<>(null); final int items = 4; NetworkCallback successCb = success -> { + log.d("items-d", returns.get()); returns.getAndIncrement(); callback.onResponse(Pair.create(module, false)); if (returns.get() == items) { @@ -145,6 +150,7 @@ public class KVVModuleList extends HTTPService { } }; NetworkErrorCallback errorCb = error -> { + log.d("items-e", returns.get()); lastError.set(error); returns.getAndIncrement(); if (returns.get() == items) { @@ -182,7 +188,7 @@ public class KVVModuleList extends HTTPService { module.announcements = success; callback.onResponse(module); queueModuleDetails.next(module.getID()); - }, errorCallback); + }, queueModuleDetails.check(module.getID(), errorCallback)); }); } @@ -233,7 +239,7 @@ public class KVVModuleList extends HTTPService { module.assignments = success; callback.onResponse(module); queueModuleDetails.next(module.getID()); - }, errorCallback); + }, queueModuleDetails.check(module.getID(), errorCallback)); }); } @@ -297,7 +303,7 @@ public class KVVModuleList extends HTTPService { module.events = success; callback.onResponse(module); queueModuleDetails.next(module.getID()); - }, errorCallback); + }, queueModuleDetails.check(module.getID(), errorCallback)); }); } @@ -348,7 +354,7 @@ public class KVVModuleList extends HTTPService { module.gradebook = success; callback.onResponse(module); queueModuleDetails.next(module.getID()); - }, errorCallback); + }, queueModuleDetails.check(module.getID(), errorCallback)); }); } diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Modules.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Modules.java index 42b8e51..ee6ec2c 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Modules.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Modules.java @@ -26,10 +26,12 @@ import de.sebse.fuplanner.tools.logging.Logger; public class Modules implements Iterable, Serializable { private final SortedModuleList list; private String latestSemester = null; + private String username = null; private transient Logger log = new Logger(this); private static final String FILE_NAME = "ModuleListSaving"; - public Modules() { + public Modules(String username) { + this.username = username; this.list = new SortedModuleList(); } @@ -174,6 +176,10 @@ public class Modules implements Iterable, Serializable { context.deleteFile(FILE_NAME); } + public String getUsername() { + return username; + } + public class Module implements Serializable { public final String semester; public final HashSet lvNumber; diff --git a/app/src/main/java/de/sebse/fuplanner/tools/AsyncQueue.java b/app/src/main/java/de/sebse/fuplanner/tools/AsyncQueue.java index 2bc56c6..dc3d4d0 100644 --- a/app/src/main/java/de/sebse/fuplanner/tools/AsyncQueue.java +++ b/app/src/main/java/de/sebse/fuplanner/tools/AsyncQueue.java @@ -3,12 +3,14 @@ package de.sebse.fuplanner.tools; import java.util.HashMap; import java.util.LinkedList; +import de.sebse.fuplanner.tools.logging.Logger; import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkErrorCallback; public class AsyncQueue { private HashMap> mQueues = new HashMap<>(); private HashMap mRunnings = new HashMap<>(); + private Logger log = new Logger(this); public void add(String hash, AsyncQueueCallback callback) { if (isRunning(hash)) @@ -20,6 +22,7 @@ public class AsyncQueue { } public void next(String hash) { + log.d("next", hash); AsyncQueueCallback callback = getQueue(hash).pollFirst(); if (callback == null) setRunning(hash, false); From 35a60c7072ca4e88e136108eb03efad0e96ff5c3 Mon Sep 17 00:00:00 2001 From: Caesar2011 Date: Thu, 5 Jul 2018 23:35:44 +0200 Subject: [PATCH 2/5] Added Announcement detail page --- .idea/misc.xml | 2 +- .idea/modules.xml | 2 +- .idea/vcs.xml | 1 + app/build.gradle | 4 +- .../fuplanner/fragments/ModulesFragment.java | 5 - .../moddetails/ModDetailAnnounceAdapter.java | 108 ++++++++++++++++++ .../moddetails/ModDetailAnnounceFragment.java | 46 +++++++- .../fuplanner/tools/ui/StringViewHolder.java | 20 ++++ .../layout/fragment_mod_detail_announce.xml | 23 ++-- app/src/main/res/layout/list_all_string.xml | 15 +++ 10 files changed, 208 insertions(+), 18 deletions(-) create mode 100644 app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAnnounceAdapter.java create mode 100644 app/src/main/java/de/sebse/fuplanner/tools/ui/StringViewHolder.java create mode 100644 app/src/main/res/layout/list_all_string.xml diff --git a/.idea/misc.xml b/.idea/misc.xml index a8cce1b..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 35eb1dd..8306744 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -2,5 +2,6 @@ + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index c2b5fe0..5ce95fe 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -34,7 +34,7 @@ dependencies { }) implementation 'com.android.support:appcompat-v7:27.1.1' implementation 'com.android.support:design:27.1.1' - implementation 'com.android.support.constraint:constraint-layout:1.1.1' + implementation 'com.android.support.constraint:constraint-layout:1.1.2' implementation 'com.android.volley:volley:1.0.0' //noinspection GradleDependency implementation 'com.google.android.gms:play-services-auth:15.0.0' @@ -47,5 +47,7 @@ dependencies { implementation 'org.jetbrains:annotations-java5:15.0' implementation 'com.github.alamkanak:android-week-view:1.2.6' implementation 'com.ms-square:expandableTextView:0.1.4' + // https://github.com/bignerdranch/expandable-recycler-view + implementation 'com.bignerdranch.android:expandablerecyclerview:3.0.0-RC1' implementation files('libs/jericho-html-3.4.jar') } diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/ModulesFragment.java b/app/src/main/java/de/sebse/fuplanner/fragments/ModulesFragment.java index c4c23d6..8deaf4a 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/ModulesFragment.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/ModulesFragment.java @@ -45,7 +45,6 @@ public class ModulesFragment extends Fragment { public static ModulesFragment newInstance() { ModulesFragment fragment = new ModulesFragment(); Bundle args = new Bundle(); - /*args.putInt(ARG_COLUMN_COUNT, columnCount);*/ fragment.setArguments(args); return fragment; } @@ -53,10 +52,6 @@ public class ModulesFragment extends Fragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - - /*if (getArguments() != null) { - mColumnCount = getArguments().getInt(ARG_COLUMN_COUNT); - }*/ } @Override diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAnnounceAdapter.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAnnounceAdapter.java new file mode 100644 index 0000000..25a6bcb --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAnnounceAdapter.java @@ -0,0 +1,108 @@ +package de.sebse.fuplanner.fragments.moddetails; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseExpandableListAdapter; +import android.widget.TextView; + +import de.sebse.fuplanner.R; +import de.sebse.fuplanner.services.KVV.types.Announcement; +import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.tools.Conversion; +import de.sebse.fuplanner.tools.ui.ItemViewHolder; +import de.sebse.fuplanner.tools.ui.StringViewHolder; + +public class ModDetailAnnounceAdapter extends BaseExpandableListAdapter { + + private Modules.Module mModule = null; + + @Override + public String getChild(int groupPosition, int childPosititon) { + return this.getGroup(groupPosition).getBody(); + } + + @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 Announcement getGroup(int groupPosition) { + if (this.mModule != null && this.mModule.announcements != null) + return this.mModule.announcements.get(groupPosition); + else + return null; + } + + @Override + public int getGroupCount() { + if (this.mModule != null && this.mModule.announcements != null) + return this.mModule.announcements.size(); + else + return 0; + } + + @Override + public long getGroupId(int groupPosition) { + return groupPosition; + } + + @Override + public View getGroupView(int groupPosition, boolean isExpanded, + View convertView, ViewGroup parent) { + Announcement announce = 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(announce.getTitle()); + itemHolder.mSubLeft.setText(announce.getCreatedBy()); + itemHolder.mSubRight.setText(Conversion.getModifiedDateTime(announce.getCreatedOn())); + + return convertView; + } + + @Override + public boolean hasStableIds() { + return false; + } + + @Override + public boolean isChildSelectable(int groupPosition, int childPosition) { + return false; + } + + public void setModule(Modules.Module module) { + this.mModule = module; + this.setModule(); + } + + public void setModule() { + this.notifyDataSetChanged(); + } +} \ No newline at end of file diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAnnounceFragment.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAnnounceFragment.java index f0f0b6d..e08deb8 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAnnounceFragment.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAnnounceFragment.java @@ -1,14 +1,22 @@ package de.sebse.fuplanner.fragments.moddetails; +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 android.widget.ExpandableListView; +import de.sebse.fuplanner.MainActivity; import de.sebse.fuplanner.R; +import de.sebse.fuplanner.services.KVV.KVV; +import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.tools.logging.Logger; /** @@ -24,6 +32,8 @@ public class ModDetailAnnounceFragment extends Fragment { // TODO: Rename and change types of parameters private int mItemPos; private Logger log = new Logger(this); + private ModDetailAnnounceAdapter adapter; + private SwipeRefreshLayout swipeLayout; public ModDetailAnnounceFragment() { @@ -58,7 +68,41 @@ public class ModDetailAnnounceFragment extends Fragment { public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment - return inflater.inflate(R.layout.fragment_mod_detail_announce, container, false); + View view = inflater.inflate(R.layout.fragment_mod_detail_announce, container, false); + // Set the adapter + Context context = view.getContext(); + ExpandableListView expandableListView = view.findViewById(R.id.list); + //expandableListView.setLayoutManager(new LinearLayoutManager(context)); + adapter = new ModDetailAnnounceAdapter(); + expandableListView.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) { + KVV kvv = ((MainActivity) getActivity()).getKVV(); + kvv.getModuleList((Modules success) -> { + Modules.Module module = success.get(mItemPos); + adapter.setModule(module); + kvv.getModuleAnnouncements(module, success1 -> { + adapter.setModule(); + swipeLayout.setRefreshing(false); + }, error -> { + swipeLayout.setRefreshing(false); + log.e(error); + }); + }, error -> { + swipeLayout.setRefreshing(false); + log.e(error); + }, forceRefresh); + } } } diff --git a/app/src/main/java/de/sebse/fuplanner/tools/ui/StringViewHolder.java b/app/src/main/java/de/sebse/fuplanner/tools/ui/StringViewHolder.java new file mode 100644 index 0000000..65aa3c7 --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/tools/ui/StringViewHolder.java @@ -0,0 +1,20 @@ +package de.sebse.fuplanner.tools.ui; + +import android.view.View; +import android.widget.TextView; + +import de.sebse.fuplanner.R; + +public class StringViewHolder extends CustomViewHolder { + public final TextView mString; + + public StringViewHolder(View view) { + super(view); + mString = view.findViewById(R.id.string); + } + + @Override + public String toString() { + return super.toString() + " '" + mString.getText() + "'"; + } +} diff --git a/app/src/main/res/layout/fragment_mod_detail_announce.xml b/app/src/main/res/layout/fragment_mod_detail_announce.xml index 99b4da7..5ecf219 100644 --- a/app/src/main/res/layout/fragment_mod_detail_announce.xml +++ b/app/src/main/res/layout/fragment_mod_detail_announce.xml @@ -1,14 +1,19 @@ - - - - + - - \ No newline at end of file + android:layout_marginLeft="16dp" + android:layout_marginRight="16dp" + app:layoutManager="android.support.v7.widget.LinearLayoutManager" + tools:context=".fragments.moddetails.ModDetailAnnounceFragment" + tools:listitem="@layout/list_all_caption" /> + \ No newline at end of file diff --git a/app/src/main/res/layout/list_all_string.xml b/app/src/main/res/layout/list_all_string.xml new file mode 100644 index 0000000..ee17e94 --- /dev/null +++ b/app/src/main/res/layout/list_all_string.xml @@ -0,0 +1,15 @@ + + + + + \ No newline at end of file From 684a510738ff84aeca56d0c08a783b6ab373fb6a Mon Sep 17 00:00:00 2001 From: Caesar2011 Date: Fri, 6 Jul 2018 00:15:45 +0200 Subject: [PATCH 3/5] Sorted assignments --- .../fuplanner/services/KVV/KVVModuleList.java | 5 +- .../fuplanner/services/KVV/types/Modules.java | 3 +- .../sebse/fuplanner/tools/AssignmentList.java | 19 +++ .../sebse/fuplanner/tools/DateSortedList.java | 108 ++++++++++++++++++ .../de/sebse/fuplanner/tools/EventList.java | 85 +------------- 5 files changed, 136 insertions(+), 84 deletions(-) create mode 100644 app/src/main/java/de/sebse/fuplanner/tools/AssignmentList.java create mode 100644 app/src/main/java/de/sebse/fuplanner/tools/DateSortedList.java diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModuleList.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModuleList.java index 7a3a377..c2aece0 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModuleList.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModuleList.java @@ -23,6 +23,7 @@ import de.sebse.fuplanner.services.KVV.types.Gradebook; import de.sebse.fuplanner.services.KVV.types.Lecturer; import de.sebse.fuplanner.services.KVV.types.LoginToken; import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.tools.AssignmentList; import de.sebse.fuplanner.tools.AsyncQueue; import de.sebse.fuplanner.tools.EventList; import de.sebse.fuplanner.tools.Regex; @@ -243,14 +244,14 @@ public class KVVModuleList extends HTTPService { }); } - private void getAssignmentsUpgrade(String ID, final NetworkCallback> callback, final NetworkErrorCallback errorCallback) { + private void getAssignmentsUpgrade(String ID, final NetworkCallback callback, final NetworkErrorCallback errorCallback) { get(String.format("https://kvv.imp.fu-berlin.de/direct/assignment/site/%s.json", ID), token.getCookies(), response ->{ String body = response.getParsed(); if (body == null) { errorCallback.onError(new NetworkError(101301, 403, "No assignments retrieved!")); return; } - ArrayList assignments = new ArrayList<>(); + AssignmentList assignments = new AssignmentList(); try { JSONObject json = new JSONObject(body); JSONArray sites = json.getJSONArray("assignment_collection"); diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Modules.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Modules.java index ee6ec2c..7db9dcb 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Modules.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Modules.java @@ -13,6 +13,7 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; +import de.sebse.fuplanner.tools.AssignmentList; import de.sebse.fuplanner.tools.Compare; import de.sebse.fuplanner.tools.EventList; import de.sebse.fuplanner.tools.Regex; @@ -189,7 +190,7 @@ public class Modules implements Iterable, Serializable { public final String description; private final String ID; public ArrayList announcements; - public ArrayList assignments; + public AssignmentList assignments; public EventList events; public ArrayList gradebook; diff --git a/app/src/main/java/de/sebse/fuplanner/tools/AssignmentList.java b/app/src/main/java/de/sebse/fuplanner/tools/AssignmentList.java new file mode 100644 index 0000000..82292ac --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/tools/AssignmentList.java @@ -0,0 +1,19 @@ +package de.sebse.fuplanner.tools; + +import de.sebse.fuplanner.services.KVV.types.Assignment; +import de.sebse.fuplanner.tools.logging.Logger; + +public class AssignmentList extends DateSortedList { + + @Override + long getDateByItem(Assignment item) { + Logger log = new Logger(this); + log.d(item.getTitle(), Conversion.getModifiedDateTime(item.getDueDate())); + return item.getDueDate(); + } + + @Override + public boolean reversed() { + return true; + } +} diff --git a/app/src/main/java/de/sebse/fuplanner/tools/DateSortedList.java b/app/src/main/java/de/sebse/fuplanner/tools/DateSortedList.java new file mode 100644 index 0000000..2b5d020 --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/tools/DateSortedList.java @@ -0,0 +1,108 @@ +package de.sebse.fuplanner.tools; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collections; +import java.util.Iterator; + +import de.sebse.fuplanner.services.KVV.types.Event; + +public abstract class DateSortedList extends ArrayList { + private int split = -1; + + public T getPast(int index) { + if (split < 0) + sort(); + if (index >= split) + throw new ArrayIndexOutOfBoundsException(String.format("Index %d out of bounds! Only %d past events found!", index, split)); + if (reversed()) + index = sizePast() - index - 1; + return this.get(index); + } + + public T getUpcoming(int index) { + if (split < 0) + sort(); + index += split; + if (index >= this.size()) + throw new ArrayIndexOutOfBoundsException(String.format("Index %d out of bounds! Only %d upcoming events found!", index-split, this.size()-split)); + if (reversed()) + index = sizeUpcoming() - index - 1; + return this.get(index); + } + + @Override + public T get(int index) { + if (split < 0) + sort(); + if (reversed()) + index = size() - index - 1; + return super.get(index); + } + + public int sizePast() { + if (split < 0) + sort(); + return split; + } + + public int sizeUpcoming() { + if (split < 0) + sort(); + return this.size()-split; + } + + public boolean add(T event) { + split = -1; + return super.add(event); + } + + public void sort() { + + Collections.sort(this, ((e1, e2) -> Long.compare(getDateByItem(e1), getDateByItem(e2)))); + long now = System.currentTimeMillis(); + split = 0; + for (T event: this) { + if (getDateByItem(event) < now) + split++; + else + break; + } + } + + public Iterator getEventsOfMonth(int year, int month) { + if (split < 0) + sort(); + final int[] i = {0}; + Calendar minC = Calendar.getInstance(); + minC.set(year, month-1, 1, 0, 0); + Calendar maxC = Calendar.getInstance(); + maxC.set(year, month, 1, 0, 0); + for (; i[0] < this.size(); i[0]++) { + if (getDateByItem(this.get(i[0])) > minC.getTimeInMillis()) { + break; + } + } + return new Iterator() { + @Override + public boolean hasNext() { + return i[0] < DateSortedList.this.size() && getDateByItem(DateSortedList.this.get(i[0])) < maxC.getTimeInMillis(); + } + + @Override + public T next() { + if (hasNext()) { + return DateSortedList.this.get(i[0]++); + } else { + return null; + } + } + }; + } + + public boolean reversed() { + return false; + } + + abstract long getDateByItem(T item); +} diff --git a/app/src/main/java/de/sebse/fuplanner/tools/EventList.java b/app/src/main/java/de/sebse/fuplanner/tools/EventList.java index c233f0a..b7aabd2 100644 --- a/app/src/main/java/de/sebse/fuplanner/tools/EventList.java +++ b/app/src/main/java/de/sebse/fuplanner/tools/EventList.java @@ -1,88 +1,11 @@ package de.sebse.fuplanner.tools; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Collections; -import java.util.Iterator; - import de.sebse.fuplanner.services.KVV.types.Event; -public class EventList extends ArrayList { - private int split = 0; +public class EventList extends DateSortedList { - public Event getPast(int index) { - if (split < 0) - sort(); - if (index >= split) - throw new ArrayIndexOutOfBoundsException(String.format("Index %d out of bounds! Only %d past events found!", index, split)); - return this.get(index); - } - - public Event getUpcoming(int index) { - if (split < 0) - sort(); - index += split; - if (index >= this.size()) - throw new ArrayIndexOutOfBoundsException(String.format("Index %d out of bounds! Only %d upcoming events found!", index-split, this.size()-split)); - return this.get(index); - } - - public int sizePast() { - if (split < 0) - sort(); - return split; - } - - public int sizeUpcoming() { - if (split < 0) - sort(); - return this.size()-split; - } - - public boolean add(Event event) { - split = -1; - return super.add(event); - } - - public void sort() { - Collections.sort(this, ((e1, e2) -> Long.compare(e1.getEndDate(), e2.getEndDate()))); - long now = System.currentTimeMillis(); - split = 0; - for (Event event : this) { - if (event.getEndDate() < now) - split++; - else - break; - } - } - - public Iterator getEventsOfMonth(int year, int month) { - if (split < 0) - sort(); - final int[] i = {0}; - Calendar minC = Calendar.getInstance(); - minC.set(year, month-1, 1, 0, 0); - Calendar maxC = Calendar.getInstance(); - maxC.set(year, month, 1, 0, 0); - for (; i[0] < this.size(); i[0]++) { - if (this.get(i[0]).getEndDate() > minC.getTimeInMillis()) { - break; - } - } - return new Iterator() { - @Override - public boolean hasNext() { - return i[0] < EventList.this.size() && EventList.this.get(i[0]).getEndDate() < maxC.getTimeInMillis(); - } - - @Override - public Event next() { - if (hasNext()) { - return EventList.this.get(i[0]++); - } else { - return null; - } - } - }; + @Override + long getDateByItem(Event item) { + return item.getEndDate(); } } From 336bd55d9df26a77047b2db78447682e6e83d57a Mon Sep 17 00:00:00 2001 From: Caesar2011 Date: Fri, 6 Jul 2018 00:27:32 +0200 Subject: [PATCH 4/5] Added assignment page --- .../moddetails/ModDetailAdapter.java | 12 +- .../ModDetailAssignmentAdapter.java | 117 ++++++++++++++++++ .../ModDetailAssignmentFragment.java | 106 ++++++++++++++++ .../fuplanner/services/KVV/KVVModuleList.java | 2 - .../de/sebse/fuplanner/tools/AsyncQueue.java | 2 - 5 files changed, 230 insertions(+), 9 deletions(-) create mode 100644 app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentAdapter.java create mode 100644 app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentFragment.java diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAdapter.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAdapter.java index 79de3fa..7922e64 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAdapter.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAdapter.java @@ -17,25 +17,25 @@ class ModDetailAdapter extends FragmentStatePagerAdapter { super(fm); this.mContext = context; this.mItemPos = itemPosition; - log.d("constructor"); } // Returns total number of pages @Override public int getCount() { - return 2; + return 3; } // Returns the fragment to display for that page @Override public Fragment getItem(int position) { - log.d("getItem"); switch (position) { - case 0: // Fragment # 0 - This will show FirstFragment + case 0: return ModDetailOverviewFragment.newInstance(mItemPos); - case 1: // Fragment # 0 - This will show FirstFragment different title + case 1: return ModDetailAnnounceFragment.newInstance(mItemPos); + case 2: + return ModDetailAssignmentFragment.newInstance(mItemPos); default: return null; } @@ -49,6 +49,8 @@ class ModDetailAdapter extends FragmentStatePagerAdapter { return this.mContext.getResources().getString(R.string.overview); case 1: return this.mContext.getResources().getString(R.string.announcements); + case 2: + return this.mContext.getResources().getString(R.string.assignments); default: return ""; } diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentAdapter.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentAdapter.java new file mode 100644 index 0000000..9ecc73e --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentAdapter.java @@ -0,0 +1,117 @@ +package de.sebse.fuplanner.fragments.moddetails; + +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.KVV.types.Announcement; +import de.sebse.fuplanner.services.KVV.types.Assignment; +import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.tools.Conversion; +import de.sebse.fuplanner.tools.ui.ItemViewHolder; +import de.sebse.fuplanner.tools.ui.StringViewHolder; + +public class ModDetailAssignmentAdapter extends BaseExpandableListAdapter { + + private Modules.Module mModule = null; + + @Override + public String getChild(int groupPosition, int childPosititon) { + StringBuilder sb = new StringBuilder(); + for (String s : this.getGroup(groupPosition).getUrls()) + { + sb.append(s); + sb.append("\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 Assignment getGroup(int groupPosition) { + if (this.mModule != null && this.mModule.assignments != null) + return this.mModule.assignments.get(groupPosition); + else + return null; + } + + @Override + public int getGroupCount() { + if (this.mModule != null && this.mModule.assignments != null) + return this.mModule.assignments.size(); + else + return 0; + } + + @Override + public long getGroupId(int groupPosition) { + return groupPosition; + } + + @Override + public View getGroupView(int groupPosition, boolean isExpanded, + View convertView, ViewGroup parent) { + Assignment assignment = 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(assignment.getTitle()); + if(assignment.isOpen()) + itemHolder.mSubLeft.setText(itemHolder.mView.getResources().getText(R.string.open)); + else + itemHolder.mSubLeft.setText(itemHolder.mView.getResources().getText(R.string.close)); + itemHolder.mSubRight.setText(Conversion.getModifiedDateTime(assignment.getDueDate())); + + return convertView; + } + + @Override + public boolean hasStableIds() { + return false; + } + + @Override + public boolean isChildSelectable(int groupPosition, int childPosition) { + return false; + } + + public void setModule(Modules.Module module) { + this.mModule = module; + this.setModule(); + } + + public void setModule() { + this.notifyDataSetChanged(); + } +} \ No newline at end of file diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentFragment.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentFragment.java new file mode 100644 index 0000000..e876ea6 --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentFragment.java @@ -0,0 +1,106 @@ +package de.sebse.fuplanner.fragments.moddetails; + + +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.KVV.KVV; +import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.tools.logging.Logger; + +/** + * A simple {@link Fragment} subclass. + * Use the {@link ModDetailAssignmentFragment#newInstance} factory method to + * create an instance of this fragment. + */ +public class ModDetailAssignmentFragment extends Fragment { + // TODO: Rename parameter arguments, choose names that match + // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER + private static final String ARG_POSITION = "itemPosition"; + + // TODO: Rename and change types of parameters + private int mItemPos; + private Logger log = new Logger(this); + private ModDetailAssignmentAdapter adapter; + private SwipeRefreshLayout swipeLayout; + + + public ModDetailAssignmentFragment() { + // Required empty public constructor + } + + /** + * Use this factory method to create a new instance of + * this fragment using the provided parameters. + * + * @param itemPosition Item position in module list. + * @return A new instance of fragment ModDetailAnnounceFragment. + */ + // TODO: Rename and change types and number of parameters + public static ModDetailAssignmentFragment newInstance(int itemPosition) { + ModDetailAssignmentFragment fragment = new ModDetailAssignmentFragment(); + Bundle args = new Bundle(); + args.putInt(ARG_POSITION, itemPosition); + fragment.setArguments(args); + return fragment; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (getArguments() != null) { + mItemPos = getArguments().getInt(ARG_POSITION); + } + } + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + // Inflate the layout for this fragment + View view = inflater.inflate(R.layout.fragment_mod_detail_announce, container, false); + // Set the adapter + Context context = view.getContext(); + ExpandableListView expandableListView = view.findViewById(R.id.list); + //expandableListView.setLayoutManager(new LinearLayoutManager(context)); + adapter = new ModDetailAssignmentAdapter(); + expandableListView.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) { + KVV kvv = ((MainActivity) getActivity()).getKVV(); + kvv.getModuleList((Modules success) -> { + Modules.Module module = success.get(mItemPos); + adapter.setModule(module); + kvv.getModuleAssignments(module, success1 -> { + adapter.setModule(); + swipeLayout.setRefreshing(false); + }, error -> { + swipeLayout.setRefreshing(false); + log.e(error); + }); + }, error -> { + swipeLayout.setRefreshing(false); + log.e(error); + }, forceRefresh); + } + } + +} diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModuleList.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModuleList.java index c2aece0..28adaff 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModuleList.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModuleList.java @@ -141,7 +141,6 @@ public class KVVModuleList extends HTTPService { AtomicReference lastError = new AtomicReference<>(null); final int items = 4; NetworkCallback successCb = success -> { - log.d("items-d", returns.get()); returns.getAndIncrement(); callback.onResponse(Pair.create(module, false)); if (returns.get() == items) { @@ -151,7 +150,6 @@ public class KVVModuleList extends HTTPService { } }; NetworkErrorCallback errorCb = error -> { - log.d("items-e", returns.get()); lastError.set(error); returns.getAndIncrement(); if (returns.get() == items) { diff --git a/app/src/main/java/de/sebse/fuplanner/tools/AsyncQueue.java b/app/src/main/java/de/sebse/fuplanner/tools/AsyncQueue.java index dc3d4d0..a65cba8 100644 --- a/app/src/main/java/de/sebse/fuplanner/tools/AsyncQueue.java +++ b/app/src/main/java/de/sebse/fuplanner/tools/AsyncQueue.java @@ -10,7 +10,6 @@ import de.sebse.fuplanner.tools.network.NetworkErrorCallback; public class AsyncQueue { private HashMap> mQueues = new HashMap<>(); private HashMap mRunnings = new HashMap<>(); - private Logger log = new Logger(this); public void add(String hash, AsyncQueueCallback callback) { if (isRunning(hash)) @@ -22,7 +21,6 @@ public class AsyncQueue { } public void next(String hash) { - log.d("next", hash); AsyncQueueCallback callback = getQueue(hash).pollFirst(); if (callback == null) setRunning(hash, false); From d83f9279d8cff805313ca7a14809ba0344a42ca9 Mon Sep 17 00:00:00 2001 From: Caesar2011 Date: Sun, 8 Jul 2018 15:54:44 +0200 Subject: [PATCH 5/5] Offline login implemented --- .idea/misc.xml | 2 +- .idea/modules.xml | 2 +- .idea/vcs.xml | 1 - .../java/de/sebse/fuplanner/MainActivity.java | 106 +++++++++--------- .../fuplanner/fragments/LoginFragment.java | 97 ++++++++-------- .../de/sebse/fuplanner/services/KVV/KVV.java | 7 +- .../fuplanner/services/KVV/KVVModuleList.java | 47 +++++--- app/src/main/res/layout/fragment_login.xml | 11 +- app/src/main/res/values/strings.xml | 1 + build.gradle | 6 + 10 files changed, 162 insertions(+), 118 deletions(-) diff --git a/.idea/misc.xml b/.idea/misc.xml index 4e024a8..a8cce1b 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 bee9e70..62306f1 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -2,7 +2,7 @@ - + diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 8306744..35eb1dd 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -2,6 +2,5 @@ - \ 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 36df966..904ac8a 100644 --- a/app/src/main/java/de/sebse/fuplanner/MainActivity.java +++ b/app/src/main/java/de/sebse/fuplanner/MainActivity.java @@ -75,16 +75,16 @@ public class MainActivity extends AppCompatActivity getGoogleAuth().getLoginState(credentials -> { if (credentials == null || credentials.getUsername() == null || credentials.getPassword() == null) { MainActivity.this.getKVV().endUpdate(); - changeLoginState(null); + toLogoutState(); return; } MainActivity.this.getKVV().login(credentials.getUsername(), credentials.getPassword(), success -> { MainActivity.this.getKVV().endUpdate(); - changeLoginState(credentials); + toLoginState(credentials); }, error -> { log.e(error); MainActivity.this.getKVV().endUpdate(); - changeLoginState(null); + toLogoutState(); }); }); }); @@ -149,7 +149,7 @@ public class MainActivity extends AppCompatActivity if (credentials != null) { MainActivity.this.getGoogleAuth().deleteLoginState(credentials.getUsername(), credentials.getPassword()); } - MainActivity.this.changeLoginState(null); + MainActivity.this.toLogoutState(); }); break; } @@ -187,56 +187,60 @@ public class MainActivity extends AppCompatActivity return this.mKVV; } - private void changeLoginState(Credentials credentials) { - log.d("change login state"); + private void toLoginState(Credentials credentials) { if (credentials == null) { - log.d("null"); - FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); - fragmentTransaction.replace(R.id.fragcontainer, LoginFragment.newInstance()); - fragmentTransaction.commit(); - findViewById(R.id.app_bar_layout).setVisibility(View.VISIBLE); - - NavigationView navigationView = findViewById(R.id.nav_view); - View header = navigationView.getHeaderView(0); - header.findViewById(R.id.imageView).setVisibility(View.GONE); - header.findViewById(R.id.login_name).setVisibility(View.GONE); - header.findViewById(R.id.login_page).setVisibility(View.VISIBLE); - navigationView.getMenu().clear(); - navigationView.inflateMenu(R.menu.activity_main_drawer); - + toLogoutState(); } else { - log.d(credentials.getUsername()); - FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); - fragmentTransaction.replace(R.id.fragcontainer, ModulesFragment.newInstance()); - fragmentTransaction.commit(); - findViewById(R.id.app_bar_layout).setVisibility(View.VISIBLE); - - final NavigationView navigationView = findViewById(R.id.nav_view); - View header = navigationView.getHeaderView(0); - header.findViewById(R.id.imageView).setVisibility(View.VISIBLE); - header.findViewById(R.id.login_name).setVisibility(View.VISIBLE); - header.findViewById(R.id.login_page).setVisibility(View.GONE); - navigationView.getMenu().clear(); - navigationView.inflateMenu(R.menu.activity_main_drawer_login); - navigationView.setCheckedItem(R.id.nav_modules); - getKVV().getModuleList(success -> { - log.d("Modules.get", success.size()); - //SubMenu moduleMenu = navigationView.getMenu().findItem(R.id.nav_modules).getSubMenu(); - int i = 0; - for (Iterator it = success.latestSemesterIterator(); it.hasNext(); ) { - Modules.Module module = it.next(); - MenuItem menuItem = navigationView.getMenu().add(Menu.NONE, Menu.NONE, 101 + i, module.title); - final int finalI = i; - menuItem.setOnMenuItemClickListener(item -> { - onModulesFragmentInteraction(finalI); - return false; - }); - i++; - } - }, error -> log.d("Modules.error", error)); + toLoginState(credentials.getUsername()); } } + private void toLogoutState() { + FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); + fragmentTransaction.replace(R.id.fragcontainer, LoginFragment.newInstance()); + fragmentTransaction.commit(); + findViewById(R.id.app_bar_layout).setVisibility(View.VISIBLE); + + NavigationView navigationView = findViewById(R.id.nav_view); + View header = navigationView.getHeaderView(0); + header.findViewById(R.id.imageView).setVisibility(View.GONE); + header.findViewById(R.id.login_name).setVisibility(View.GONE); + header.findViewById(R.id.login_page).setVisibility(View.VISIBLE); + navigationView.getMenu().clear(); + navigationView.inflateMenu(R.menu.activity_main_drawer); + } + + private void toLoginState(String username) { + FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); + fragmentTransaction.replace(R.id.fragcontainer, ModulesFragment.newInstance()); + fragmentTransaction.commit(); + findViewById(R.id.app_bar_layout).setVisibility(View.VISIBLE); + + final NavigationView navigationView = findViewById(R.id.nav_view); + View header = navigationView.getHeaderView(0); + header.findViewById(R.id.imageView).setVisibility(View.VISIBLE); + header.findViewById(R.id.login_name).setVisibility(View.VISIBLE); + header.findViewById(R.id.login_page).setVisibility(View.GONE); + navigationView.getMenu().clear(); + navigationView.inflateMenu(R.menu.activity_main_drawer_login); + navigationView.setCheckedItem(R.id.nav_modules); + getKVV().getModuleList(success -> { + log.d("Modules.get", success.size()); + //SubMenu moduleMenu = navigationView.getMenu().findItem(R.id.nav_modules).getSubMenu(); + int i = 0; + for (Iterator it = success.latestSemesterIterator(); it.hasNext(); ) { + Modules.Module module = it.next(); + MenuItem menuItem = navigationView.getMenu().add(Menu.NONE, Menu.NONE, 101 + i, module.title); + final int finalI = i; + menuItem.setOnMenuItemClickListener(item -> { + onModulesFragmentInteraction(finalI); + return false; + }); + i++; + } + }, error -> log.e("Modules.error", error)); + } + @@ -248,8 +252,8 @@ public class MainActivity extends AppCompatActivity @Override - public void onLoginFragmentInteraction(Credentials credentials) { - changeLoginState(credentials); + public void onLoginFragmentInteraction(String username) { + toLoginState(username); } @Override diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/LoginFragment.java b/app/src/main/java/de/sebse/fuplanner/fragments/LoginFragment.java index 3a4d1ad..323e76b 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/LoginFragment.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/LoginFragment.java @@ -8,13 +8,17 @@ import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.Button; import android.widget.EditText; +import java.io.IOException; + import de.sebse.fuplanner.MainActivity; import de.sebse.fuplanner.R; import de.sebse.fuplanner.services.GoogleAuth.Credentials; import de.sebse.fuplanner.services.GoogleAuth.GoogleAuth; import de.sebse.fuplanner.services.KVV.KVV; +import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.tools.logging.Logger; /** @@ -26,11 +30,6 @@ import de.sebse.fuplanner.tools.logging.Logger; * create an instance of this fragment. */ public class LoginFragment extends Fragment { - // TODO: Rename parameter arguments, choose names that match - // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER - - // TODO: Rename and change types of parameters - private OnLoginFragmentInteractionListener mListener; private Logger log = new Logger(this); @@ -44,7 +43,6 @@ public class LoginFragment extends Fragment { * * @return A new instance of fragment LoginFragment. */ - // TODO: Rename and change types and number of parameters public static LoginFragment newInstance() { LoginFragment fragment = new LoginFragment(); Bundle args = new Bundle(); @@ -61,47 +59,57 @@ public class LoginFragment extends Fragment { public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment - View v = inflater.inflate(R.layout.fragment_login, container, false); - View btn_login = v.findViewById(R.id.btn_login); - if (btn_login != null) { - btn_login.setOnClickListener(view -> { - final ProgressDialog progressDialog = new ProgressDialog(LoginFragment.this.getContext(), - R.style.FUTheme_Dialog); - progressDialog.setIndeterminate(true); - progressDialog.setMessage("Authenticating..."); - progressDialog.show(); - - - EditText input_usr = ((View) view.getParent()).findViewById(R.id.input_username); - EditText input_pwd = ((View) view.getParent()).findViewById(R.id.input_password); - if (input_usr != null) { - if (input_pwd != null) { - if (LoginFragment.this.getActivity() == null) { - log.e("Login fragment has no activity!"); - return; - } - final String username = input_usr.getText().toString(); - final String password = input_pwd.getText().toString(); - final KVV kvv = ((MainActivity) LoginFragment.this.getActivity()).getKVV(); - final GoogleAuth gauth = ((MainActivity) LoginFragment.this.getActivity()).getGoogleAuth(); - kvv.login(username, password, success -> { - progressDialog.dismiss(); - log.d("success", success.toString()); - gauth.setLoginState(username, password); - if (LoginFragment.this.mListener != null) { - Credentials cred = new Credentials(username, password); - LoginFragment.this.mListener.onLoginFragmentInteraction(cred); - } - }, error -> { - progressDialog.dismiss(); - log.e("error", error); - }); - } + try { + Context context = getContext(); + if (context != null) { + Modules modules = Modules.load(context); + if (modules != null) { + Button offline_btn = v.findViewById(R.id.btn_offline); + offline_btn.setVisibility(View.VISIBLE); + offline_btn.setText(v.getResources().getString(R.string.enter_offline_mode, modules.getUsername())); + offline_btn.setOnClickListener(v1 -> mListener.onLoginFragmentInteraction(modules.getUsername())); } - }); + } + } catch (IOException e) { + e.printStackTrace(); + } catch (ClassNotFoundException e) { + e.printStackTrace(); } + View btn_login = v.findViewById(R.id.btn_login); + btn_login.setOnClickListener(view -> { + final ProgressDialog progressDialog = new ProgressDialog(LoginFragment.this.getContext(), + R.style.FUTheme_Dialog); + progressDialog.setIndeterminate(true); + progressDialog.setMessage("Authenticating..."); + progressDialog.show(); + + EditText input_usr = ((View) view.getParent()).findViewById(R.id.input_username); + EditText input_pwd = ((View) view.getParent()).findViewById(R.id.input_password); + if (input_usr != null) { + if (input_pwd != null) { + if (LoginFragment.this.getActivity() == null) { + log.e("Login fragment has no activity!"); + return; + } + String username = input_usr.getText().toString(); + String password = input_pwd.getText().toString(); + KVV kvv = ((MainActivity) getActivity()).getKVV(); + GoogleAuth gauth = ((MainActivity) getActivity()).getGoogleAuth(); + kvv.login(username, password, success -> { + progressDialog.dismiss(); + gauth.setLoginState(username, password); + if (mListener != null) + mListener.onLoginFragmentInteraction(username); + }, error -> { + progressDialog.dismiss(); + log.e("Error on KVV login!", error); + }); + } + } + }); + return v; } @@ -135,7 +143,6 @@ public class LoginFragment extends Fragment { * >Communicating with Other Fragments for more information. */ public interface OnLoginFragmentInteractionListener { - // TODO: Update argument type and name - void onLoginFragmentInteraction(Credentials credentials); + void onLoginFragmentInteraction(String username); } } diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVV.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVV.java index 4ac3eaf..d48d15c 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVV.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVV.java @@ -10,6 +10,7 @@ import java.util.HashMap; import de.sebse.fuplanner.services.KVV.types.LoginToken; import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.tools.logging.Logger; import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkErrorCallback; @@ -23,8 +24,10 @@ public class KVV { private boolean isUpdating; private ArrayList updatingList; private HashMap addons = new HashMap<>(); + private Logger log = new Logger(this); public KVV(Context context) { + log.d("new kvv"); this.context = context; this.isUpdating = false; this.updatingList = new ArrayList<>(); @@ -42,7 +45,7 @@ public class KVV { lastToken = null; KVVModuleList modules = (KVVModuleList) addons.get("modules"); if (modules != null) { - modules.deleteModules(this.context); + modules.deleteModulesOffline(this.context); } addons.clear(); } @@ -118,7 +121,7 @@ public class KVV { private NetworkCallback saveOnCallback(KVVModuleList modules, NetworkCallback callback){ return (success -> { try { - modules.saveModules(this.context); + modules.saveModulesOffline(this.context); } catch (IOException e) { e.printStackTrace(); } diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModuleList.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModuleList.java index 28adaff..da5a7fb 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModuleList.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModuleList.java @@ -46,7 +46,7 @@ public class KVVModuleList extends HTTPService { this.token = token; try { Modules modules = Modules.load(context); - if (modules.getUsername().equals(token.getUsername())) + if (token == null || modules.getUsername().equals(token.getUsername())) this.moduleList = modules; } catch (IOException e) { e.printStackTrace(); @@ -75,7 +75,11 @@ public class KVVModuleList extends HTTPService { }); } - public void getModuleListUpgrade(final NetworkCallback callback, final NetworkErrorCallback errorCallback) { + private void getModuleListUpgrade(final NetworkCallback callback, final NetworkErrorCallback errorCallback) { + if (token == null) { + errorCallback.onError(new NetworkError(101105, 500, "Currently running in offline mode!")); + return; + } get("https://kvv.imp.fu-berlin.de/direct/site.json", token.getCookies(), response -> { String body = response.getParsed(); if (body == null) { @@ -117,12 +121,12 @@ public class KVVModuleList extends HTTPService { }, error -> errorCallback.onError(new NetworkError(101104, error.networkResponse.statusCode, "Cannot get module list!"))); } - public void deleteModules(Context context) { + public void deleteModulesOffline(Context context) { if (this.moduleList != null) this.moduleList.delete(context); } - public void saveModules(Context context) throws IOException { + public void saveModulesOffline(Context context) throws IOException { if (this.moduleList != null) this.moduleList.save(context); } @@ -139,11 +143,11 @@ public class KVVModuleList extends HTTPService { public void getModuleDetails(Modules.Module module, final NetworkCallback> callback, final NetworkErrorCallback errorCallback, boolean forceRefresh) { AtomicInteger returns = new AtomicInteger(0); AtomicReference lastError = new AtomicReference<>(null); - final int items = 4; + final AtomicInteger items = new AtomicInteger(0); NetworkCallback successCb = success -> { returns.getAndIncrement(); callback.onResponse(Pair.create(module, false)); - if (returns.get() == items) { + if (returns.get() == items.get()) { callback.onResponse(Pair.create(module, true)); if (lastError.get() != null) errorCallback.onError(lastError.get()); @@ -152,7 +156,7 @@ public class KVVModuleList extends HTTPService { NetworkErrorCallback errorCb = error -> { lastError.set(error); returns.getAndIncrement(); - if (returns.get() == items) { + if (returns.get() == items.get()) { callback.onResponse(Pair.create(module, true)); if (lastError.get() != null) errorCallback.onError(lastError.get()); @@ -164,8 +168,7 @@ public class KVVModuleList extends HTTPService { () -> this.getAnnouncements(module, successCb, errorCb, forceRefresh), () -> this.getGradebook(module, successCb, errorCb, forceRefresh) }; - //noinspection ConstantConditions - if (methods.length != items) throw new AssertionError(); + items.set(methods.length); for (Runnable method: methods) { method.run(); } @@ -192,7 +195,10 @@ public class KVVModuleList extends HTTPService { } private void getAnnouncementsUpgrade(String ID, final NetworkCallback> callback, final NetworkErrorCallback errorCallback) { - //log.d("SITE GET URL", String.format("https://kvv.imp.fu-berlin.de/direct/announcement/site/%s.json?n=999999&d=999999999", ID)); + if (token == null) { + errorCallback.onError(new NetworkError(101204, 500, "Currently running in offline mode!")); + return; + } get(String.format("https://kvv.imp.fu-berlin.de/direct/announcement/site/%s.json?n=999999&d=999999999", ID), token.getCookies(), response -> { String body = response.getParsed(); if (body == null) { @@ -243,6 +249,10 @@ public class KVVModuleList extends HTTPService { } private void getAssignmentsUpgrade(String ID, final NetworkCallback callback, final NetworkErrorCallback errorCallback) { + if (token == null) { + errorCallback.onError(new NetworkError(101304, 500, "Currently running in offline mode!")); + return; + } get(String.format("https://kvv.imp.fu-berlin.de/direct/assignment/site/%s.json", ID), token.getCookies(), response ->{ String body = response.getParsed(); if (body == null) { @@ -277,7 +287,7 @@ public class KVVModuleList extends HTTPService { assignments.add(0, new Assignment(id, title, dueTime, gradebookItemName, gradeScale, urls)); } } catch (JSONException e) { - errorCallback.onError(new NetworkError(101306, 403, "Cannot parse announcements!")); + errorCallback.onError(new NetworkError(101302, 403, "Cannot parse announcements!")); return; } callback.onResponse(assignments); @@ -307,7 +317,10 @@ public class KVVModuleList extends HTTPService { } private void getEventsUpgrade(String ID, final NetworkCallback callback, final NetworkErrorCallback errorCallback) { - //https://kvv.imp.fu-berlin.de/direct/calendar/site/91c6e9cc-58eb-486d-ab99-a22a40997d1b.json + if (token == null) { + errorCallback.onError(new NetworkError(101404, 500, "Currently running in offline mode!")); + return; + } get(String.format("https://kvv.imp.fu-berlin.de/direct/calendar/site/%s.json", ID), token.getCookies(), response -> { String body = response.getParsed(); if (body == null) { @@ -358,6 +371,10 @@ public class KVVModuleList extends HTTPService { } private void getGradebookUpgrade(String ID, final NetworkCallback> callback, final NetworkErrorCallback errorCallback) { + if (token == null) { + errorCallback.onError(new NetworkError(101104, 500, "Currently running in offline mode!")); + return; + } get(String.format("https://kvv.imp.fu-berlin.de/direct/gradebook/site/%s.json", ID ), token.getCookies(), response ->{ String body = response.getParsed(); if (body == null) { @@ -370,22 +387,20 @@ public class KVVModuleList extends HTTPService { JSONArray sites = json.getJSONArray("assignments"); for (int i = 0; i < sites.length(); i++) { - //log.d("gradebook FOUND!", i); JSONObject site = sites.getJSONObject(i); String grade = site.optString("grade", null); String itemName = site.optString("itemName", null); double maxPoints = site.optDouble("points", -1); - //log.d("Gradebook:",itemName, grade, maxPoints); gradebook.add(0, new Gradebook(itemName, grade, maxPoints)); } }catch (JSONException e) { - errorCallback.onError(new NetworkError(101504, 403, "Cannot parse gradebook for announcements!")); + errorCallback.onError(new NetworkError(101502, 403, "Cannot parse gradebook for announcements!")); return; } callback.onResponse(gradebook); - }, error -> errorCallback.onError(new NetworkError(101505, error.networkResponse.statusCode, "Cannot get gradebook for assignments!"))); + }, error -> errorCallback.onError(new NetworkError(101503, error.networkResponse.statusCode, "Cannot get gradebook for assignments!"))); } diff --git a/app/src/main/res/layout/fragment_login.xml b/app/src/main/res/layout/fragment_login.xml index 323a10f..eb9b474 100644 --- a/app/src/main/res/layout/fragment_login.xml +++ b/app/src/main/res/layout/fragment_login.xml @@ -48,13 +48,22 @@ + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ec77120..c256c34 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -34,4 +34,5 @@ Hello blank fragment + Enter Offline Mode (%1$s) diff --git a/build.gradle b/build.gradle index ad6a928..be59a9b 100644 --- a/build.gradle +++ b/build.gradle @@ -18,6 +18,12 @@ allprojects { jcenter() google() } + + gradle.projectsEvaluated { + tasks.withType(JavaCompile) { + options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation" + } + } } task clean(type: Delete) {