diff --git a/app/build.gradle b/app/build.gradle index a74f3ed..755a347 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -7,8 +7,8 @@ android { applicationId "de.sebse.fuplanner" minSdkVersion 15 targetSdkVersion 28 - versionCode 9 - versionName "1.2.1" + versionCode 10 + versionName "1.2.2" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes { @@ -32,7 +32,6 @@ dependencies { androidTestImplementation('androidx.test.espresso:espresso-core:3.1.0-beta02', { exclude group: 'com.android.support', module: 'support-annotations' }) - implementation 'androidx.appcompat:appcompat:1.0.0' implementation 'androidx.preference:preference:1.0.0' implementation 'com.google.android.material:material:1.0.0' implementation 'androidx.constraintlayout:constraintlayout:2.0.0-alpha2' @@ -42,7 +41,7 @@ dependencies { implementation 'androidx.legacy:legacy-support-v4:1.0.0' testImplementation 'junit:junit:4.12' implementation fileTree(include: ['*.jar'], dir: 'libs') - implementation 'androidx.appcompat:appcompat:1.0.0' + implementation 'androidx.appcompat:appcompat:1.0.2' implementation 'org.jbundle.util.osgi.wrapped:org.jbundle.util.osgi.wrapped.org.apache.http.client:4.1.2' implementation 'androidx.legacy:legacy-support-v4:1.0.0' implementation 'org.jetbrains:annotations-java5:15.0' diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailOverviewAdapter.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailOverviewAdapter.java index 1728f64..a009b2b 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailOverviewAdapter.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailOverviewAdapter.java @@ -231,6 +231,7 @@ class ModDetailOverviewAdapter extends RecyclerView.Adapter @Override protected void upgrade(final String ID, final NetworkCallback> callback, final NetworkErrorCallback errorCallback) { - if (!login.isInOnlineMode() || login.getLoginToken() == null) { + if (!mLogin.isInOnlineMode() || mLogin.getLoginToken() == null) { errorCallback.onError(new NetworkError(101204, 500, "Currently running in offline mode!")); return; } - super.get(String.format("https://kvv.imp.fu-berlin.de/direct/announcement/site/%s.json?n=999999&d=999999999", ID), login.getLoginToken().getCookies(), response -> { + super.get(String.format("https://kvv.imp.fu-berlin.de/direct/announcement/site/%s.json?n=999999&d=999999999", ID), mLogin.getLoginToken().getCookies(), response -> { String body = response.getParsed(); if (body == null) { errorCallback.onError(new NetworkError(101201, 403, "No announcements retrieved!")); return; } ArrayList announcements = new ArrayList<>(); + JSONArray sites; try { JSONObject json = new JSONObject(body); - JSONArray sites = json.getJSONArray("announcement_collection"); + sites = json.getJSONArray("announcement_collection"); + } catch (JSONException e) { + e.printStackTrace(); + errorCallback.onError(new NetworkError(101202, 403, "Cannot parse announcements!")); + return; + } - for (int i = 0; i < sites.length(); i++) { + for (int i = 0; i < sites.length(); i++) { + try { JSONObject site = sites.getJSONObject(i); String id = site.getString("announcementId"); String title = site.getString("title"); @@ -61,21 +68,21 @@ public class KVVModulesAnnouncements extends ModulesPart // Extract attachment links JSONArray attachments = site.getJSONArray("attachments"); ArrayList urls = new ArrayList<>(); - for (int j =0; j check if (announcements.size() == 0) - login.testLoginToken(token -> callback.onResponse(announcements), errorCallback); + mLogin.testLoginToken(token -> callback.onResponse(announcements), errorCallback); else callback.onResponse(announcements); }, error -> errorCallback.onError(new NetworkError(101203, error.networkResponse.statusCode, "Cannot get announcements!"))); diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesAssignments.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesAssignments.java index d8eaa2a..29a70b2 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesAssignments.java +++ b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesAssignments.java @@ -35,22 +35,29 @@ public class KVVModulesAssignments extends ModulesPart { @Override protected void upgrade(final String ID, final NetworkCallback callback, final NetworkErrorCallback errorCallback) { - if (!login.isInOnlineMode() || login.getLoginToken() == null) { + if (!mLogin.isInOnlineMode() || mLogin.getLoginToken() == 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), login.getLoginToken().getCookies(), response ->{ + get(String.format("https://kvv.imp.fu-berlin.de/direct/assignment/site/%s.json", ID), mLogin.getLoginToken().getCookies(), response -> { String body = response.getParsed(); if (body == null) { errorCallback.onError(new NetworkError(101301, 403, "No assignments retrieved!")); return; } AssignmentList assignments = new AssignmentList(); + JSONArray sites; try { JSONObject json = new JSONObject(body); - JSONArray sites = json.getJSONArray("assignment_collection"); + sites = json.getJSONArray("assignment_collection"); + } catch (JSONException e) { + e.printStackTrace(); + errorCallback.onError(new NetworkError(101302, 403, "Cannot parse assignments!")); + return; + } - for (int i = 0; i < sites.length(); i++) { + for (int i = 0; i < sites.length(); i++) { + try { JSONObject site = sites.getJSONObject(i); String id = site.getString("id"); String title = site.getString("title"); @@ -61,19 +68,20 @@ public class KVVModulesAssignments extends ModulesPart { String gradeScale = site.getString("gradeScale"); JSONArray attachments = site.getJSONArray("attachments"); ArrayList urls = new ArrayList<>(); - for (int j = 0; j check if (assignments.size() == 0) - login.testLoginToken(token -> callback.onResponse(assignments), errorCallback); + mLogin.testLoginToken(token -> callback.onResponse(assignments), errorCallback); else callback.onResponse(assignments); }, error -> errorCallback.onError(new NetworkError(101303, error.networkResponse.statusCode, "Cannot get announcements!"))); diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesList.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesList.java index 31f2946..810d5c4 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesList.java +++ b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesList.java @@ -136,11 +136,10 @@ public class KVVModulesList extends HTTPService { } private void upgrade(final NetworkCallback callback, final NetworkErrorCallback errorCallback) { - if (!mLogin.isInOnlineMode()) { + if (!mLogin.isInOnlineMode() || mLogin.getLoginToken() == null) { errorCallback.onError(new NetworkError(101105, 500, "Currently running in offline mode!")); return; } - // https://file.io/71sa2V get("https://kvv.imp.fu-berlin.de/direct/site.json", mLogin.getLoginToken().getCookies(), response -> { String body = response.getParsed(); if (body == null) { @@ -148,37 +147,43 @@ public class KVVModulesList extends HTTPService { return; } Modules modules = new Modules(mLogin.getLoginToken().getUsername()); + JSONArray sites; try { JSONObject json = new JSONObject(body); - JSONArray sites = json.getJSONArray("site_collection"); - - for (int i = 0; i < sites.length(); i++) { - JSONObject site = sites.getJSONObject(i); - String semester = site.getJSONObject("props").getString("term_eid"); - HashSet lvNumbers = new HashSet<>(); - for (MatchResult matchResult : Regex.allMatches("[0-9]+", site.getJSONObject("props").getString("kvv_lvnumbers"))) { - lvNumbers.add(matchResult.group()); - } - String title = site.getString("entityTitle"); - HashSet lecturers = new HashSet<>(); - for (String lecturer : site.getJSONObject("props").getString("kvv_lecturers").split("#")) { - if (lecturer.length() > 2) - lecturers.add(new Lecturer(lecturer)); - } - String type = site.getJSONObject("props").getString("kvv_coursetype"); - String description = site.getString("description"); - description = String.valueOf(ModulesPart.fromHtml(description)); - String id = site.getString("id"); - modules.addModule(semester, lvNumbers, title, lecturers, type, description, id); - } + sites = json.getJSONArray("site_collection"); } catch (JSONException e) { e.printStackTrace(); errorCallback.onError(new NetworkError(101102, 403, "Cannot parse module list!")); return; - } catch (NoSuchFieldException e) { - e.printStackTrace(); - errorCallback.onError(new NetworkError(101103, 403, "Cannot parse module list!")); - return; + } + for (int i = 0; i < sites.length(); i++) { + try { + JSONObject site = sites.getJSONObject(i); + String semester = site.getJSONObject("props").optString("term_eid", null); + HashSet lvNumbers = new HashSet<>(); + String kvv_lvnumbers = site.getJSONObject("props").optString("kvv_lvnumbers", null); + if (kvv_lvnumbers != null) for (MatchResult matchResult : Regex.allMatches("[0-9]+", kvv_lvnumbers)) { + lvNumbers.add(matchResult.group()); + } + String title = site.getString("entityTitle"); + HashSet lecturers = new HashSet<>(); + String kvv_lecturers = site.getJSONObject("props").optString("kvv_lecturers", null); + if (kvv_lecturers != null) for (String lecturer : kvv_lecturers.split("#")) { + if (lecturer.length() > 2) + lecturers.add(new Lecturer(lecturer)); + } + String type = site.getJSONObject("props").optString("kvv_coursetype", null); + String description = site.optString("description", ""); + description = String.valueOf(ModulesPart.fromHtml(description)); + String id = site.getString("id"); + modules.addModule(semester, lvNumbers, title, lecturers, type, description, id); + } catch (JSONException e) { + log.e(new NetworkError(101103, 403, "Cannot parse module list!")); + e.printStackTrace(); + } catch (NoSuchFieldException e) { + log.e(new NetworkError(101106, 403, "Cannot parse module list!")); + e.printStackTrace(); + } } // Empty module *may be* because token is invalid -> check if (modules.size() == 0) diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/ModulesPart.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/ModulesPart.java index 48d9833..f74ec97 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/ModulesPart.java +++ b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/ModulesPart.java @@ -11,7 +11,7 @@ import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkErrorCallback; abstract class ModulesPart extends Part { - private NewAsyncQueue queue = new NewAsyncQueue(); + private NewAsyncQueue mQueue = new NewAsyncQueue(); ModulesPart(KVVLogin login, KVVModulesList list, Context context) { super(login, list, context); @@ -19,28 +19,28 @@ abstract class ModulesPart extends Part { @Override protected void recv(final Modules.Module module, final NetworkCallback callback, final NetworkErrorCallback errorCallback, final boolean forceRefresh, final int retries) { - queue.add(() -> { + mQueue.add(() -> { if (getPart(module) != null && !forceRefresh) { callback.onResponse(module); - queue.next(); + mQueue.next(); return; } upgrade(module.getID(), success -> { if (setPart(module, success)) { - this.list.store(); + this.mList.store(); } callback.onResponse(module); - queue.next(); + mQueue.next(); }, error -> { if (retries >= 0 && (error.getHttpStatus() == 401 || error.getHttpStatus() == 403)) { - login.refreshLogin(success -> { + mLogin.refreshLogin(success -> { recv(module, callback, errorCallback, forceRefresh, retries-1); - queue.next(); + mQueue.next(); }, errorCallback); return; } errorCallback.onError(error); - queue.next(); + mQueue.next(); }); }); } diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/Part.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/Part.java index 12c13b6..294636c 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/Part.java +++ b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/Part.java @@ -3,20 +3,19 @@ package de.sebse.fuplanner.services.NewKVV; import android.content.Context; import de.sebse.fuplanner.services.NewKVV.types.Modules; -import de.sebse.fuplanner.tools.NewAsyncQueue; import de.sebse.fuplanner.tools.network.HTTPService; import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkErrorCallback; public abstract class Part extends HTTPService { static final int RETRY_COUNT = 1; - protected final KVVLogin login; - protected final KVVModulesList list; + protected final KVVLogin mLogin; + protected final KVVModulesList mList; Part(KVVLogin login, KVVModulesList list, Context context) { super(context); - this.login = login; - this.list = list; + this.mLogin = login; + this.mList = list; } public void recv(final String moduleID, final NetworkCallback callback, final NetworkErrorCallback errorCallback) { @@ -24,7 +23,7 @@ public abstract class Part extends HTTPService { } public void recv(final String moduleID, final NetworkCallback callback, final NetworkErrorCallback errorCallback, final boolean forceRefresh) { - list.find(moduleID, success -> recv(success, callback, errorCallback, forceRefresh, RETRY_COUNT), errorCallback); + mList.find(moduleID, success -> recv(success, callback, errorCallback, forceRefresh, RETRY_COUNT), errorCallback); } abstract protected void recv(final Modules.Module module, final NetworkCallback callback, final NetworkErrorCallback errorCallback, final boolean forceRefresh, final int retries); diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Modules.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Modules.java index 3b3dcc3..8994948 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Modules.java +++ b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Modules.java @@ -2,6 +2,8 @@ package de.sebse.fuplanner.services.NewKVV.types; import android.content.Context; +import org.jetbrains.annotations.NotNull; + import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; @@ -30,7 +32,7 @@ public class Modules implements Iterable, Serializable { this.list = new SortedListModule(); } - public void addModule(String semester, HashSet lvNumber, String title, HashSet lecturer, String type, String description, String ID) { + public void addModule(@Nullable String semester, HashSet lvNumber, String title, HashSet lecturer, String type, String description, String ID) { Module m = new Module(semester, lvNumber, title, lecturer, type, description, ID); this.list.add(m); } @@ -104,24 +106,19 @@ public class Modules implements Iterable, Serializable { } public class Module implements Serializable { - public final String semester; - final HashSet lvNumber; - public final String title; - final HashSet lecturer; - public final String type; - public final String description; - private final String ID; + @Nullable public final String semester; + @NotNull final HashSet lvNumber; + @NotNull public final String title; + @NotNull final HashSet lecturer; + @Nullable public final String type; + @Nullable public final String description; + @NotNull private final String ID; @Nullable public ArrayList announcements; @Nullable public AssignmentList assignments; @Nullable public EventList events; @Nullable public ArrayList gradebook; @Nullable public ArrayList resources; - /*private Module() { - this(null, null, null, null, null); - throw new AssertionError("Do not use this constructor!"); - }*/ - public float getGradebookPercent(){ float maxPoint = 0; float userPoint = 0; @@ -136,9 +133,11 @@ public class Modules implements Iterable, Serializable { return userPoint/maxPoint; } - private Module(String semester, HashSet lvNumber, String title, HashSet lecturer, String type, String description, String ID) { - semester = semester.replace("SS", "S"); - semester = semester.replaceAll("[0-9]{2}([0-9]{2})", "$1"); + private Module(@Nullable String semester, @NotNull HashSet lvNumber, @NotNull String title, @NotNull HashSet lecturer, @Nullable String type, @Nullable String description, @NotNull String ID) { + if (semester != null) { + semester = semester.replace("SS", "S"); + semester = semester.replaceAll("[0-9]{2}([0-9]{2})", "$1"); + } title = title.replaceAll("(.*?) (S[0-9]{2}|W[0-9/]{5})", "$1"); this.semester = semester; @@ -150,6 +149,7 @@ public class Modules implements Iterable, Serializable { this.ID = ID; } + @NonNull public String getID() { return ID; } diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/SortedListModule.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/SortedListModule.java index 13b1a83..a12ba34 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/SortedListModule.java +++ b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/SortedListModule.java @@ -63,6 +63,6 @@ public class SortedListModule extends SortedList @Override public boolean hasFilter(Modules.Module o1, String filter) { - return o1.semester.equals(filter); + return o1.semester != null && o1.semester.equals(filter); } }