From 3cdce73c5acc269eaa81c0151d0aea43be07dce5 Mon Sep 17 00:00:00 2001 From: Caesar2011 Date: Wed, 7 Nov 2018 03:30:38 +0100 Subject: [PATCH 01/17] Working Progress (not runnable) --- app/src/main/AndroidManifest.xml | 9 - .../java/de/sebse/fuplanner/MainActivity.java | 206 +++++---- .../moddetails/ModDetailAnnounceFragment.java | 4 +- .../ModDetailAssignmentFragment.java | 4 +- .../services/GoogleAuth/GoogleAuth.java | 2 + .../fuplanner/services/KVV/Download.java | 26 +- .../sebse/fuplanner/services/NewKVV/KVV.java | 47 ++ .../services/NewKVV/KVVListener.java | 14 + .../fuplanner/services/NewKVV/KVVLogin.java | 433 ++++++++++++++++++ .../fuplanner/services/NewKVV/KVVModules.java | 43 ++ .../NewKVV/KVVModulesAnnouncements.java | 88 ++++ .../services/NewKVV/KVVModulesList.java | 161 +++++++ .../services/NewKVV/ModulesPart.java | 75 +++ .../services/NewKVV/types/Announcement.java | 64 +++ .../services/NewKVV/types/Assignment.java | 53 +++ .../services/NewKVV/types/AssignmentList.java | 16 + .../services/NewKVV/types/Event.java | 114 +++++ .../services/NewKVV/types/EventList.java | 16 + .../services/NewKVV/types/Gradebook.java | 34 ++ .../services/NewKVV/types/GroupedEvents.java | 128 ++++++ .../services/NewKVV/types/Lecturer.java | 41 ++ .../services/NewKVV/types/LoginToken.java | 114 +++++ .../services/NewKVV/types/Modules.java | 168 +++++++ .../services/NewKVV/types/Resource.java | 134 ++++++ .../NewKVV/types/SortedListModule.java | 68 +++ .../fuplanner/tools/MainActivityListener.java | 2 - .../sebse/fuplanner/tools/NewAsyncQueue.java | 58 +++ app/src/main/res/layout/activity_main.xml | 1 + app/src/main/res/xml/provider_paths.xml | 4 - 29 files changed, 1989 insertions(+), 138 deletions(-) create mode 100644 app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVV.java create mode 100644 app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVListener.java create mode 100644 app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVLogin.java create mode 100644 app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModules.java create mode 100644 app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesAnnouncements.java create mode 100644 app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesList.java create mode 100644 app/src/main/java/de/sebse/fuplanner/services/NewKVV/ModulesPart.java create mode 100644 app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Announcement.java create mode 100644 app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Assignment.java create mode 100644 app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/AssignmentList.java create mode 100644 app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Event.java create mode 100644 app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/EventList.java create mode 100644 app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Gradebook.java create mode 100644 app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/GroupedEvents.java create mode 100644 app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Lecturer.java create mode 100644 app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/LoginToken.java create mode 100644 app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Modules.java create mode 100644 app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Resource.java create mode 100644 app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/SortedListModule.java create mode 100644 app/src/main/java/de/sebse/fuplanner/tools/NewAsyncQueue.java delete mode 100644 app/src/main/res/xml/provider_paths.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2115831..9948868 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -24,15 +24,6 @@ - - - \ 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 a4929d3..6108cc6 100644 --- a/app/src/main/java/de/sebse/fuplanner/MainActivity.java +++ b/app/src/main/java/de/sebse/fuplanner/MainActivity.java @@ -33,16 +33,20 @@ 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; +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.NewKVV.KVV; import de.sebse.fuplanner.services.KVV.types.LoginToken; -import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.services.NewKVV.KVVListener; import de.sebse.fuplanner.tools.MainActivityListener; import de.sebse.fuplanner.tools.RequestPermissionsResultListener; import de.sebse.fuplanner.tools.logging.Logger; +import de.sebse.fuplanner.tools.network.NetworkCallback; +import de.sebse.fuplanner.tools.network.NetworkError; +import de.sebse.fuplanner.tools.network.NetworkErrorCallback; public class MainActivity extends AppCompatActivity - implements MainActivityListener, + implements MainActivityListener, KVVListener, NavigationView.OnNavigationItemSelectedListener, LoginFragment.OnLoginFragmentInteractionListener, ModulesFragment.OnModulesFragmentInteractionListener, @@ -63,26 +67,25 @@ public class MainActivity extends AppCompatActivity private FragmentManager mFragmentManager; private GoogleAuth mGoogleAuth; - private KVV mKVV; + private de.sebse.fuplanner.services.KVV.KVV mKVV; + private KVV mNewKVV; private final Logger log = new Logger(this); private NavigationView mNavigationView; private int fragmentPage = FRAGMENT_NONE; - private int currentPage = FRAGMENT_NONE; private String fragmentData = ""; - private String currentData = ""; private CanteenBrowser mCanteenBrowser; - private boolean mOfflineMode = false; private HashMap permissionListeners = new HashMap<>(); + private boolean mOfflineBanner; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - int newFragmentPage = FRAGMENT_NONE; - String newFragmentData = ""; + int desiredPage = getDefaultFragmentAfterLogin(); + String desiredData = ""; if (savedInstanceState != null) { - newFragmentPage = savedInstanceState.getInt(ARG_FRAGMENT_PAGE, fragmentPage); - newFragmentData = savedInstanceState.getString(ARG_FRAGMENT_STATUS, fragmentData); + desiredPage = savedInstanceState.getInt(ARG_FRAGMENT_PAGE, desiredPage); + desiredData = savedInstanceState.getString(ARG_FRAGMENT_STATUS, desiredData); } setContentView(R.layout.activity_main); @@ -99,15 +102,9 @@ public class MainActivity extends AppCompatActivity mNavigationView.setNavigationItemSelectedListener(this); mFragmentManager = getSupportFragmentManager(); - LoginToken loginToken = getKVV().easyLogin(); - if (loginToken == null) { - checkAndDoLogin(); - } else { - if (newFragmentPage != FRAGMENT_LOGIN && newFragmentPage != FRAGMENT_STARTUP && newFragmentPage != FRAGMENT_NONE) - toLoginState(loginToken, newFragmentPage, newFragmentData); - else - toLoginState(loginToken, getDefaultFragmentAfterLogin(), ""); - } + getNewKVV().account().doOfflineLogin(); + updateNavigation(); + changeFragment(desiredPage, desiredData); } @Override @@ -123,7 +120,7 @@ public class MainActivity extends AppCompatActivity @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. - if (currentPage == FRAGMENT_SCHEDULE) { + if (fragmentPage == FRAGMENT_SCHEDULE) { getMenuInflater().inflate(R.menu.options_schedule, menu); return true; } @@ -180,13 +177,13 @@ public class MainActivity extends AppCompatActivity startActivity(sendIntent); break; case R.id.nav_logout: - this.getKVV().logout(); + getNewKVV().account().logout(true); this.getGoogleAuth().getLoginState(credentials -> { if (credentials != null) { this.getGoogleAuth().deleteLoginState(credentials.getUsername(), credentials.getPassword()); } - this.toLogoutState(); }); + this.toLogoutState(); break; } @@ -210,13 +207,14 @@ public class MainActivity extends AppCompatActivity @Override protected void onSaveInstanceState(Bundle savedInstanceState) { - Fragment fragment = mFragmentManager.findFragmentByTag(String.valueOf(fragmentPage)); - savedInstanceState.putInt(ARG_FRAGMENT_PAGE, fragmentPage); - savedInstanceState.putString(ARG_FRAGMENT_STATUS, fragmentData); - if (fragment instanceof ModDetailFragment) { - savedInstanceState.putString(ARG_FRAGMENT_STATUS, ((ModDetailFragment) fragment).getData()); - } else { - savedInstanceState.putString(ARG_FRAGMENT_STATUS, fragmentData); + if (fragmentPage != FRAGMENT_STARTUP && fragmentPage != FRAGMENT_NONE && fragmentPage != FRAGMENT_LOGIN) { + Fragment fragment = mFragmentManager.findFragmentByTag(String.valueOf(fragmentPage)); + savedInstanceState.putInt(ARG_FRAGMENT_PAGE, fragmentPage); + if (fragment instanceof ModDetailFragment) { + savedInstanceState.putString(ARG_FRAGMENT_STATUS, ((ModDetailFragment) fragment).getData()); + } else { + savedInstanceState.putString(ARG_FRAGMENT_STATUS, fragmentData); + } } super.onSaveInstanceState(savedInstanceState); } @@ -239,13 +237,21 @@ public class MainActivity extends AppCompatActivity return this.mGoogleAuth; } - public KVV getKVV() { + @Deprecated + public de.sebse.fuplanner.services.KVV.KVV getKVV() { if (this.mKVV == null) { - this.mKVV = new KVV(this); + this.mKVV = new de.sebse.fuplanner.services.KVV.KVV(this); } return this.mKVV; } + public KVV getNewKVV() { + if (this.mNewKVV == null) { + this.mNewKVV = new KVV(this, this); + } + return this.mNewKVV; + } + public CanteenBrowser getCanteenBrowser() { if (this.mCanteenBrowser == null) { this.mCanteenBrowser = new CanteenBrowser(this); @@ -254,23 +260,13 @@ public class MainActivity extends AppCompatActivity } private int getDefaultFragmentAfterLogin() { - return getDefaultFragmentAfterLogin(new String[1]); - } - - private int getDefaultFragmentAfterLogin(String[] id) { - if (fragmentPage == FRAGMENT_NONE){ - id[0] = ""; - return FRAGMENT_MODULES; - } - else { - id[0] = fragmentData; - return fragmentPage; - } + return FRAGMENT_MODULES; } private void toLogoutState() { - setOfflineBanner(true); + setOfflineBanner(false); setRefreshFailedBanner(false); + updateNavigation(); changeFragment(FRAGMENT_LOGIN); } @@ -283,14 +279,17 @@ public class MainActivity extends AppCompatActivity } private void toLoginState(String fullName, String email, int newFragment, String newData, boolean onlineMode) { - setOfflineBanner(onlineMode); - changeFragment(newFragment, newData); + setOfflineBanner(!onlineMode); + updateNavigation(); View header = mNavigationView.getHeaderView(0); ((TextView) header.findViewById(R.id.login_name)).setText(fullName); ((TextView) header.findViewById(R.id.login_mail)).setText(email); + + changeFragment(newFragment, newData); } + @Deprecated private void checkAndDoLogin() { changeFragment(FRAGMENT_STARTUP); getGoogleAuth().getLoginState(credentials -> { @@ -298,10 +297,9 @@ public class MainActivity extends AppCompatActivity toLogoutState(); return; } - String[] id = {""}; - int fragment = getDefaultFragmentAfterLogin(id); - this.getKVV().login(credentials.getUsername(), credentials.getPassword(), success -> toLoginState(success, fragment , id[0]), + int fragment = getDefaultFragmentAfterLogin(); + this.getKVV().login(credentials.getUsername(), credentials.getPassword(), success -> toLoginState(success, fragment, ""), error -> { log.e(error); toLogoutState(); @@ -355,56 +353,38 @@ public class MainActivity extends AppCompatActivity fragmentTransaction.commit(); if (newFragment == FRAGMENT_STARTUP) { - findViewById(R.id.app_bar_layout).setVisibility(View.GONE); + findViewById(R.id.app_bar_include).setVisibility(View.GONE); } else { - findViewById(R.id.app_bar_layout).setVisibility(View.VISIBLE); + findViewById(R.id.app_bar_include).setVisibility(View.VISIBLE); } - boolean isChangeLoginState = - ( - (newFragment == FRAGMENT_STARTUP || newFragment == FRAGMENT_LOGIN) && - (currentPage != FRAGMENT_STARTUP && currentPage != FRAGMENT_LOGIN) - ) || ( - (currentPage == FRAGMENT_STARTUP || currentPage == FRAGMENT_LOGIN || currentPage == FRAGMENT_NONE) && - (newFragment != FRAGMENT_STARTUP && newFragment != FRAGMENT_LOGIN && (getKVV().isLoggedIn() || mOfflineMode)) - ); + this.fragmentPage = newFragment; + this.fragmentData = newData; - if (newFragment != FRAGMENT_STARTUP && newFragment != FRAGMENT_NONE && newFragment != FRAGMENT_LOGIN) { - this.fragmentPage = newFragment; - this.fragmentData = newData; - } - this.currentPage = newFragment; - this.currentData = newData; invalidateOptionsMenu(); - if (isChangeLoginState) - refreshNavigation(); - else - setNavigationSelection(currentPage, currentData); + //TODO navigation selection } - private void setOfflineBanner(boolean onlineMode) { + private void setOfflineBanner(boolean visible) { View offline_header = findViewById(R.id.offline_msg); - if (onlineMode) - offline_header.setVisibility(View.GONE); - else - offline_header.setVisibility(View.VISIBLE); - mOfflineMode = !onlineMode; + offline_header.setVisibility(visible ? View.VISIBLE : View.GONE); + mOfflineBanner = visible; } private void setRefreshFailedBanner(boolean refreshFailed) { View viewNoConnection = findViewById(R.id.no_connection_msg); - if (!mOfflineMode && refreshFailed) + if (!mOfflineBanner && refreshFailed) viewNoConnection.setVisibility(View.VISIBLE); else viewNoConnection.setVisibility(View.GONE); } - private void setNavigationSelection(int fragment, String data) { + private void setNavigationSelection() { MenuItem item; - switch (fragment) { + switch (fragmentPage) { case FRAGMENT_MODULES_DETAILS: - getKVV().getModule(data, success -> { + getKVV().getModule(fragmentData, success -> { int size = mNavigationView.getMenu().size(); //noinspection ConstantConditions String title = success == null ? null : success.title; @@ -426,7 +406,7 @@ public class MainActivity extends AppCompatActivity case FRAGMENT_CANTEENS_DETAILS: getCanteenBrowser().getCanteens(success -> { int size = mNavigationView.getMenu().size(); - Canteen canteen = success.getCanteen(Integer.parseInt(data)); + Canteen canteen = success.getCanteen(Integer.parseInt(fragmentData)); //noinspection ConstantConditions String title = canteen == null ? null : canteen.getName(); for (int k = 0; k < size; k++) { @@ -466,10 +446,10 @@ public class MainActivity extends AppCompatActivity private void afterAnyMenuInflate(boolean isLoggedIn) { if (isLoggedIn) { - getKVV().getModuleList(success -> { + getNewKVV().modules().list().recv(success -> { int i = 0; - for (Iterator it = success.latestSemesterIterator(); it.hasNext(); ) { - Modules.Module module = it.next(); + for (Iterator it = success.latestSemesterIterator(); it.hasNext(); ) { + de.sebse.fuplanner.services.NewKVV.types.Modules.Module module = it.next(); MenuItem menuItem = mNavigationView.getMenu().add(Menu.NONE, Menu.NONE, 101 + i, module.title); menuItem.setOnMenuItemClickListener(item -> { onModulesFragmentInteraction(module.getID()); @@ -492,16 +472,30 @@ public class MainActivity extends AppCompatActivity }, log::e); } + private void updateNavigation() { + boolean isLoggedIn = getNewKVV().account().isLoggedIn(); + setNavigationHeader(isLoggedIn); + mNavigationView.getMenu().clear(); + if (isLoggedIn) + mNavigationView.inflateMenu(R.menu.activity_main_drawer_login); + else + mNavigationView.inflateMenu(R.menu.activity_main_drawer); + afterAnyMenuInflate(isLoggedIn); + setNavigationSelection(); + } + + + + @Override public void onLoginFragmentInteraction(LoginToken loginToken, boolean onlineMode) { - String[] id = {""}; - int fragment = getDefaultFragmentAfterLogin(id); - toLoginState(loginToken.getFullName(), loginToken.getEmail(), fragment, id[0], onlineMode); + int fragment = getDefaultFragmentAfterLogin(); + toLoginState(loginToken.getFullName(), loginToken.getEmail(), fragment, "", onlineMode); } @Override @@ -524,6 +518,7 @@ public class MainActivity extends AppCompatActivity setTitle(titleId); } + @Deprecated @Override public void loginTokenInvalid(boolean doLoginCheck) { if (doLoginCheck) { @@ -564,16 +559,33 @@ public class MainActivity extends AppCompatActivity Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); } + + + + + + + + + @Override - public void refreshNavigation() { - boolean isLoggedIn = getKVV().isLoggedIn() || mOfflineMode; - setNavigationHeader(isLoggedIn); - mNavigationView.getMenu().clear(); - if (isLoggedIn) - mNavigationView.inflateMenu(R.menu.activity_main_drawer_login); - else - mNavigationView.inflateMenu(R.menu.activity_main_drawer); - afterAnyMenuInflate(isLoggedIn); - setNavigationSelection(currentPage, currentData); + public void getCredentials(NetworkCallback callback, NetworkErrorCallback error) { + getGoogleAuth().getLoginState(credentials -> { + if (credentials == null || credentials.getUsername() == null || credentials.getPassword() == null) { + error.onError(new NetworkError(200100, 403, "No Google Login available!")); + } else { + callback.onResponse(credentials); + } + }); + } + + @Override + public void handleLogin(de.sebse.fuplanner.services.NewKVV.types.LoginToken token, boolean enteringOnlineMode) { + toLoginState(token.getUsername(), token.getEmail(), getDefaultFragmentAfterLogin(), "", enteringOnlineMode); + } + + @Override + public void handleLogout() { + toLogoutState(); } } 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 66ea74e..52f3713 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 @@ -117,9 +117,9 @@ public class ModDetailAnnounceFragment extends Fragment implements Download.OnDo super.onAttach(context); if (context instanceof MainActivityListener) { this.context = ((MainActivityListener) context); - this.context.addRequestPermissionsResultListener(getDownload().getRequestPermissionsResultListener(), "ModDetailResourceFragment"); + this.context.addRequestPermissionsResultListener(getDownload().getRequestPermissionsResultListener(), "ModDetailAnnounceFragment"); } else - throw new RuntimeException(context.toString() + " must implement MainActivityListener"); + throw new RuntimeException(context.toString() + " must implement ModDetailAnnounceFragment"); } @Override 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 index 48e6f52..a3225d9 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentFragment.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentFragment.java @@ -117,7 +117,7 @@ public class ModDetailAssignmentFragment extends Fragment implements Download.On super.onAttach(context); if (context instanceof MainActivityListener) { this.context = ((MainActivityListener) context); - this.context.addRequestPermissionsResultListener(getDownload().getRequestPermissionsResultListener(), "ModDetailResourceFragment"); + this.context.addRequestPermissionsResultListener(getDownload().getRequestPermissionsResultListener(), "ModDetailAssignmentFragment"); } else throw new RuntimeException(context.toString() + " must implement MainActivityListener"); } @@ -125,7 +125,7 @@ public class ModDetailAssignmentFragment extends Fragment implements Download.On @Override public void onDetach() { super.onDetach(); - this.context.removeRequestPermissionsResultListener("ModDetailResourceFragment"); + this.context.removeRequestPermissionsResultListener("ModDetailAssignmentFragment"); } Download getDownload() { diff --git a/app/src/main/java/de/sebse/fuplanner/services/GoogleAuth/GoogleAuth.java b/app/src/main/java/de/sebse/fuplanner/services/GoogleAuth/GoogleAuth.java index ead95a8..98074e8 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/GoogleAuth/GoogleAuth.java +++ b/app/src/main/java/de/sebse/fuplanner/services/GoogleAuth/GoogleAuth.java @@ -29,6 +29,7 @@ public class GoogleAuth { private static final String TAG = "GoogleAuth"; private final FragmentActivity activity; + private static final String FU_PLANNER_PROVIDER = "FUPlanner"; private CredentialsClient mCredentialsClient; private boolean mIsResolving; @Nullable @@ -61,6 +62,7 @@ public class GoogleAuth { connect(); CredentialRequest request = new CredentialRequest.Builder() .setPasswordLoginSupported(true) + .setAccountTypes(FU_PLANNER_PROVIDER) .build(); diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/Download.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/Download.java index 4c03d45..8fcfb83 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/Download.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/Download.java @@ -15,7 +15,6 @@ import java.util.Arrays; import androidx.annotation.Nullable; import androidx.core.app.ActivityCompat; -import androidx.core.content.FileProvider; import de.sebse.fuplanner.MainActivity; import de.sebse.fuplanner.R; import de.sebse.fuplanner.services.KVV.types.Resource; @@ -24,10 +23,7 @@ import de.sebse.fuplanner.tools.RequestPermissionsResultListener; import de.sebse.fuplanner.tools.UtilsDate; import de.sebse.fuplanner.tools.logging.Logger; -import static android.content.Intent.normalizeMimeType; -import static androidx.core.app.ActivityCompat.startActivityForResult; import static androidx.core.content.ContextCompat.checkSelfPermission; -import static androidx.core.content.ContextCompat.startActivity; public class Download { @@ -35,7 +31,6 @@ public class Download { private final ActivityInterface activityInterface; private RequestedDownload requestedDownload; private Logger log = new Logger(this); - static final int REQUEST_IMAGE_OPEN = 1; public Download(ContextInterface contextInterface, ActivityInterface activityInterface) { @@ -60,7 +55,7 @@ public class Download { if (file.getModifiedDate() != 0) { if (!message.isEmpty()) message += "\n"; - message += resources.getString(R.string.last_modified_on, UtilsDate.getModifiedDateTime(contextInterface.get(), file.getModifiedDate())); + resources.getString(R.string.last_modified_on, UtilsDate.getModifiedDateTime(contextInterface.get(), file.getModifiedDate())); } alertDialogBuilder @@ -186,17 +181,9 @@ public class Download { } private void fileOpen(File url){ + Uri uri = Uri.fromFile(url); - Uri uri = FileProvider.getUriForFile(contextInterface.get(), contextInterface.get().getApplicationContext().getPackageName() + ".my.provider", url); - - Intent intent; - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) { - intent = new Intent(Intent.ACTION_VIEW); - } else { - intent = new Intent(); - } - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + Intent intent = new Intent();//Intent.ACTION_VIEW // Check what kind of file you are trying to open, by comparing the url with extensions. // When the if condition is matched, plugin sets the correct intent (mime) type, // so Android knew what application to use to open the file @@ -235,18 +222,13 @@ public class Download { intent.setDataAndType(uri, "video/*"); } else { //if you want you can also define the intent type for any other file + //additionally use else clause below, to manage other unknown extensions //in this case, Android will show all applications installed on the device //so you can choose which application to use intent.setDataAndType(uri, "*/*"); } - //intent.addCategory(Intent.CATEGORY_OPENABLE); - // Only the system receives the ACTION_OPEN_DOCUMENT, so no need to test. - - - - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); contextInterface.get().startActivity(intent); diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVV.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVV.java new file mode 100644 index 0000000..ab63ebe --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVV.java @@ -0,0 +1,47 @@ +package de.sebse.fuplanner.services.NewKVV; + +import android.content.Context; + +import org.jetbrains.annotations.NotNull; + +import java.util.HashMap; + +public class KVV { + private final HashMap addons = new HashMap<>(); + private final KVVListener mListener; + private final Context mContext; + + public KVV(KVVListener listener, Context context) { + this.mListener = listener; + this.mContext = context; + } + + @NotNull + public KVVLogin account() { + return (KVVLogin) addAndGet("account", () -> new KVVLogin(mListener, mContext)); + } + + @NotNull + public KVVModules modules() { + return (KVVModules) addAndGet("module", () -> new KVVModules(account(), mContext)); + } + + + + + + + @NotNull + private Object addAndGet(@NotNull String addon, @NotNull ModuleCreatorInterface creatorInterface) { + Object o = addons.get(addon); + if (o == null) { + o = creatorInterface.create(); + addons.put(addon, o); + } + return o; + } + + private interface ModuleCreatorInterface { + @NotNull Object create(); + } +} diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVListener.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVListener.java new file mode 100644 index 0000000..2dd7a9b --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVListener.java @@ -0,0 +1,14 @@ +package de.sebse.fuplanner.services.NewKVV; + +import de.sebse.fuplanner.services.GoogleAuth.Credentials; +import de.sebse.fuplanner.services.NewKVV.types.LoginToken; +import de.sebse.fuplanner.tools.network.NetworkCallback; +import de.sebse.fuplanner.tools.network.NetworkErrorCallback; + +public interface KVVListener { + void getCredentials(NetworkCallback callback, NetworkErrorCallback error); + + void handleLogin(LoginToken token, boolean enteringOnlineMode); + + void handleLogout(); +} diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVLogin.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVLogin.java new file mode 100644 index 0000000..29d4b42 --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVLogin.java @@ -0,0 +1,433 @@ +package de.sebse.fuplanner.services.NewKVV; + +import android.content.Context; + + +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.HashMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import androidx.annotation.Nullable; +import de.sebse.fuplanner.services.NewKVV.types.LoginToken; +import de.sebse.fuplanner.tools.network.HTTPService; +import de.sebse.fuplanner.tools.network.NetworkCallback; +import de.sebse.fuplanner.tools.network.NetworkError; +import de.sebse.fuplanner.tools.network.NetworkErrorCallback; + +public class KVVLogin extends HTTPService { + private KVVListener mListener; + @Nullable private LoginToken mToken; + private boolean mLoginPending = false; + private boolean mOnlineMode = false; + + KVVLogin(KVVListener listener, Context context) { + super(context); + this.mListener = listener; + } + + public void doOnlineLogin(String username, String password, NetworkCallback callback, NetworkErrorCallback errorCallback) { + if (mLoginPending) { + errorCallback.onError(new NetworkError(100160, -1, "Login already pending!")); + } + if (mToken != null) { + errorCallback.onError(new NetworkError(100161, -1, "Already logged in!")); + } + mLoginPending = true; + doLogin(username, password, token -> { + testLoginToken(token2 -> { + setToken(token, true); + mLoginPending = false; + callback.onResponse(token); + }, error -> { + mLoginPending = false; + errorCallback.onError(error); + }); + }, error -> { + mLoginPending = false; + errorCallback.onError(error); + }); + } + + public boolean doOfflineLogin() { + if (mLoginPending || mToken != null) + return false; + mLoginPending = true; + boolean result = false; + try { + result = setToken(LoginToken.load(getContext()), false); + } catch (FileNotFoundException ignored) { + } catch (IOException e) { + e.printStackTrace(); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + mLoginPending = false; + return result; + } + + public boolean isOfflineStoredAvailable() { + try { + LoginToken.load(getContext()); + return true; + } catch (FileNotFoundException ignored) { + } catch (IOException e) { + e.printStackTrace(); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + return false; + } + + public boolean logout(boolean delete) { + if (mLoginPending) + return false; + if (mToken == null) + return true; + if (delete) + mToken.delete(getContext()); + mToken = null; + return handleCallbacks(); + } + + public boolean isLoginPending() { + return mLoginPending; + } + + public boolean isLoggedIn() { + return mToken != null; + } + + public boolean isInOfflineMode() { + return isLoggedIn() && !mOnlineMode; + } + + public boolean isInOnlineMode() { + return isLoggedIn() && mOnlineMode; + } + + public void testLoginToken(NetworkCallback callback, NetworkErrorCallback errorCallback) { + if (mToken == null) { + errorCallback.onError(new NetworkError(100173, -1, "Not logged in!")); + return; + } + get(String.format("https://kvv.imp.fu-berlin.de/direct/profile/%s.json", mToken.getUsername()), mToken.getCookies(), response -> { + String body = response.getParsed(); + if (body == null) { + errorCallback.onError(new NetworkError(100172, 403, "Testing login failed!")); + return; + } + try { + JSONObject json = new JSONObject(body); + String displayName = json.getString("displayName"); + String email = json.getString("email"); + mToken.setAdditionals(displayName, email); + callback.onResponse(mToken); + } catch (JSONException e) { + errorCallback.onError(new NetworkError(100171, 403, "Cannot parse profile!")); + } + }, error -> errorCallback.onError(new NetworkError(100170, error.networkResponse.statusCode, "Testing login failed!"))); + } + + @Nullable public LoginToken getLoginToken() { + return mToken; + } + + void refreshLogin(NetworkCallback success, NetworkErrorCallback error) { + mListener.getCredentials(credentials -> { + doOnlineLogin(credentials.getUsername(), credentials.getPassword(), success, error); + }, e -> { + logout(false); + error.onError(e); + }); + } + + + + private boolean handleCallbacks() { + if (mToken != null) { + mListener.handleLogin(mToken, false); + return true; + } else { + mListener.handleLogout(); + return false; + } + } + + private boolean setToken(@Nullable LoginToken token, boolean enteringOnlineMode) { + if (token == null) + return false; + mToken = token; + if (enteringOnlineMode) { + try { + mToken.save(getContext()); + } catch (IOException e) { + e.printStackTrace(); + } + } + mOnlineMode = !enteringOnlineMode; + return handleCallbacks(); + } + + + + + + + + + + + private void doLogin(String username, String password, NetworkCallback callback, NetworkErrorCallback error) { + startKVVSession(success -> { + String kvvJSESSIONID = success.get("JSESSIONID"); + getSAMLRequest(kvvJSESSIONID, success1 -> startIdentSession(success1.get("Location"), success11 -> { + String identJSESSIONID = success11.get("JSESSIONID"); + String ident_idp_authn_lc_key = success11.get("_idp_authn_lc_key"); + String identROUTEID = success11.get("ROUTEID"); + loginIdent(true, username, password, identJSESSIONID, ident_idp_authn_lc_key, identROUTEID, success111 -> loginIdent(false, username, password, identJSESSIONID, ident_idp_authn_lc_key, identROUTEID, success11112 -> { + String ident_idp_session = success11112.get("_idp_session"); + getSAMLResponse(identJSESSIONID, ident_idp_authn_lc_key, identROUTEID, ident_idp_session, success1111 -> loginKVV(success1111.get("RelayState"), success1111.get("SAMLResponse"), kvvJSESSIONID, success111112 -> { + LoginToken token = new LoginToken(username, success111112.get("shibsessionKey"), success111112.get("shibsessionName"), kvvJSESSIONID); + finishKVVlogin(token, success11111 -> callback.onResponse(token), error); + }, error), error); + }, error), error); + }, error), error); + }, error); + } + + /* + GET https://kvv.imp.fu-berlin.de/portal/login + -> JSESSIONID 5c10406f-588c-4c16-96e9-c80d115417de.tomcat1 + */ + private void startKVVSession(final NetworkCallback> callback, final NetworkErrorCallback errorCallback) { + get("https://kvv.imp.fu-berlin.de/portal/login", null, response -> { + String cookies = response.getHeaders().get("Set-Cookie"); + if (cookies==null) { + errorCallback.onError(new NetworkError(100101, -1, "Error on starting KVV session!")); + return; + } + HashMap object; + try { + object = getCookie(cookies, new String[]{"JSESSIONID"}); + } catch (NoSuchFieldException e) { + errorCallback.onError(new NetworkError(100102, -1, "Error on starting KVV session!")); + return; + } + callback.onResponse(object); + }, error -> errorCallback.onError(new NetworkError(100100, error.networkResponse.statusCode, "Error on starting KVV session!"))); + } + + /* + GET https://kvv.imp.fu-berlin.de/sakai-login-tool/container + <- JSESSIONID + -> (Location-Header) https://identity.fu-berlin.de/idp-fub/profile/SAML2/Redirect/SSO + ?SAMLRequest=fZLLb.....Q8yre3X1IHwkJKE0Mnpy/V9TH4A + &RelayState=ss:mem:7ea01e29157b8bd906f7002176.....0d1a505f2c8bf + */ + private void getSAMLRequest(String JSESSIONID, final NetworkCallback> callback, final NetworkErrorCallback errorCallback) { + HashMap cookies = new HashMap<>(); + cookies.put("JSESSIONID", JSESSIONID); + get("https://kvv.imp.fu-berlin.de/sakai-login-tool/container", cookies, response -> { + String location = response.getHeaders().get("Location"); + if (location==null) { + errorCallback.onError(new NetworkError(100111, -1, "Error on getting SAML request!")); + return; + } + HashMap object = new HashMap<>(); + object.put("Location", location); + callback.onResponse(object); + }, error -> errorCallback.onError(new NetworkError(100110, error.networkResponse.statusCode, "Error on getting SAML request!"))); + } + + /* + GET https://identity.fu-berlin.de/idp-fub/profile/SAML2/Redirect/SSO + ?SAMLRequest=fZLLbsIwEEV/JfI+cWJAUIsgpbAoEi2IpF10UznxUKw6dupxaPn7hkdb2LD29bkzRzNGUeuGZ63fmjV8toA++K61QX58SEnrDLcCFXIjakDuK55njwvOopg3znpbWU2CDBGcV9ZMrcG2BpeD26kKnteLlGy9b5BT+rHbRapuok0bluC0MpEEmm9VWVoNfhshWnpgM7pa5gUJZt0wyogD9h+iJBiv/P6aomQTbtqSdhNtlIYzZg1SOag8zfMlCeazlLyNqpHsy1gO2V1fVsNBMuqJoUyAJaxXDUaiiyG2MDfohfEpYXEyDJM4ZKxgCe/FPI5fSbA6L36vjFTm/bal8hRC/lAUq/C02gs4PK7VBchkfHDNj8Xuwv5trPhVTiY3BeOf4DG96DmVNvypA89nK6tVtQ8yre3X1IHwkJKE0Mnpy/V9TH4A + &RelayState=ss:mem:7ea01e29157b8bd906f7002176213b6db5e1f45ebb88716a9820d1a505f2c8bf + -> JSESSIONID C4B6A428BA1F50746235D03F5D107A57 + -> _idp_authn_lc_key 57a6ae26067f374cc3d0ccfc47e27b04b47752d2a3d4eb2782af0d3994535395 + -> ROUTEID .1 + */ + private void startIdentSession(String url, final NetworkCallback> callback, final NetworkErrorCallback errorCallback) { + get(url, null, response -> { + String cookies = response.getHeaders().get("Set-Cookie"); + if (cookies==null) { + errorCallback.onError(new NetworkError(100121, -1, "Error on starting Ident session!")); + return; + } + HashMap object; + try { + object = getCookie(cookies, new String[]{"JSESSIONID", "_idp_authn_lc_key", "ROUTEID"}); + } catch (NoSuchFieldException e) { + errorCallback.onError(new NetworkError(100122, -1, "Error on starting Ident session!")); + return; + } + callback.onResponse(object); + }, error -> errorCallback.onError(new NetworkError(100120, error.networkResponse.statusCode, "Error on starting Ident session!"))); + } + + /* + POST https://identity.fu-berlin.de/idp-fub/Authn/UserPassword + <- j_username seedorf96 + <- j_password neinhieristpatrick + <- (Header-"Content-Type") application/x-www-form-urlencoded + <- JSESSIONID + <- _idp_authn_lc_key + <- ROUTEID + -> _idp_session OTMuMTkzLjg1LjMz|LQ==|OGYxOWI4MjA2NTQ4YWUwYzJkOWM4Mjk4YzcwZDMwZmJiZjBmMTdmMzkyZGU2OWIwY2JkNmZlNjlmNTRmNzBlMQ==|wLlzQal7VqyntmG2vLNn06wt8wQ= + */ + private void loginIdent(final boolean first, String username, String password, String JSESSIONID, String _idp_authn_lc_key, String ROUTEID, final NetworkCallback> callback, final NetworkErrorCallback errorCallback) { + HashMap cookies = new HashMap<>(); + cookies.put("JSESSIONID", JSESSIONID); + cookies.put("_idp_authn_lc_key", _idp_authn_lc_key); + cookies.put("ROUTEID", ROUTEID); + HashMap body = new HashMap<>(); + body.put("j_username", username); + body.put("j_password", password); + post("https://identity.fu-berlin.de/idp-fub/Authn/UserPassword", cookies, body, response -> { + if (first) { + callback.onResponse(new HashMap<>()); + return; + } + + String cookies1 = response.getHeaders().get("Set-Cookie"); + if (cookies1 ==null) { + errorCallback.onError(new NetworkError(100131, -1, "Error on logging in to Identity Server!")); + return; + } + HashMap object; + try { + object = getCookie(cookies1, new String[]{"_idp_session"}); + } catch (NoSuchFieldException e) { + errorCallback.onError(new NetworkError(100132, -1, "Error on logging in to Identity Server!")); + return; + } + callback.onResponse(object); + }, error -> errorCallback.onError(new NetworkError(100130, error.networkResponse.statusCode, "Error on logging in to Identity Server!"))); + } + + /* + GET https://identity.fu-berlin.de/idp-fub/profile/SAML2/Redirect/SSO + <- JSESSIONID + <- _idp_authn_lc_key + <- ROUTEID + <- _idp_session + -> (BODY) RelayState 7ea01e29157b8bd906f7002176213b6db5e1f45ebb88716a9820d1a505f2c8bf + -> (BODY) SAMLResponse PD94bWwgdmVyc2lvbj0...........wvc2FtbDJwOlJlc3BvbnNlPg== + */ + private void getSAMLResponse(String JSESSIONID, String _idp_authn_lc_key, String ROUTEID, String _idp_session, final NetworkCallback> callback, final NetworkErrorCallback errorCallback) { + HashMap cookies = new HashMap<>(); + cookies.put("JSESSIONID", JSESSIONID); + cookies.put("_idp_authn_lc_key", _idp_authn_lc_key); + cookies.put("ROUTEID", ROUTEID); + cookies.put("_idp_session", _idp_session); + get("https://identity.fu-berlin.de/idp-fub/profile/SAML2/Redirect/SSO", cookies, response -> { + String body = response.getParsed(); + if (body == null) { + errorCallback.onError(new NetworkError(100143, -1, "Error on getting SAML response!")); + return; + } + + HashMap object = new HashMap<>(); + + Pattern pattern = Pattern.compile("ss:mem:([0-9a-f]+)"); + Matcher matcher = pattern.matcher(body); + if (!matcher.find()) { + errorCallback.onError(new NetworkError(100142, -1, "Error on getting SAML response!")); + return; + } + object.put("RelayState", "ss:mem:"+matcher.group(1)); + + pattern = Pattern.compile("name=\"SAMLResponse\" value=\"([0-9a-zA-Z+]+=*)"); + matcher = pattern.matcher(body); + if (!matcher.find()) { + errorCallback.onError(new NetworkError(100141, -1, "Error on getting SAML response!")); + return; + } + object.put("SAMLResponse", matcher.group(1)); + + callback.onResponse(object); + }, error -> errorCallback.onError(new NetworkError(100140, error.networkResponse.statusCode, "Error on getting SAML response!"))); + } + + + /* + POST https://kvv.imp.fu-berlin.de/Shibboleth.sso/SAML2/POST + <- RelayState 7ea01e29157b8bd906f7002176213b6db5e1f45ebb88716a9820d1a505f2c8bf + <- SAMLResponse PD94bWwgdmVyc2lvbj0...........wvc2FtbDJwOlJlc3BvbnNlPg== + <- JSESSIONID + -> _shibsession_64656661756c7468747470733a2f2f6b76762e696d702e66752d6265726c696e2e64652f73686962626f6c657468 + _b1912c5a03d733a80bd3fee772bf68d4 + */ + private void loginKVV(String RelayState, String SAMLResponse, String JSESSIONID, final NetworkCallback> callback, final NetworkErrorCallback errorCallback) { + HashMap cookies = new HashMap<>(); + cookies.put("JSESSIONID", JSESSIONID); + HashMap body = new HashMap<>(); + body.put("RelayState", RelayState); + body.put("SAMLResponse", SAMLResponse); + post("https://kvv.imp.fu-berlin.de/Shibboleth.sso/SAML2/POST", cookies, body, response -> { + String cookies1 = response.getHeaders().get("Set-Cookie"); + if (cookies1 ==null) { + errorCallback.onError(new NetworkError(100151, -1, "Error on starting KVV session!")); + return; + } + HashMap object = new HashMap<>(); + + + Pattern pattern = Pattern.compile("(_shibsession_[0-9a-f]+)=([^;]+);"); + Matcher matcher = pattern.matcher(cookies1); + if (!matcher.find()) { + errorCallback.onError(new NetworkError(100152, -1, "Error on starting Ident session!")); + } + object.put("shibsessionKey", matcher.group(1)); + object.put("shibsessionName", matcher.group(2)); + + callback.onResponse(object); + }, error -> errorCallback.onError(new NetworkError(100150, error.networkResponse.statusCode, "Error on starting Ident session!"))); + } + + + /* + GET https://kvv.imp.fu-berlin.de/sakai-login-tool/container + <- JSESSIONID + <- _shibsession_64656661756c7468747470733a2f2f6b76762e696d702e66752d6265726c696e2e64652f73686962626f6c657468 + _b1912c5a03d733a80bd3fee772bf68d4 + */ + private void finishKVVlogin(LoginToken loginToken, final NetworkCallback> callback, final NetworkErrorCallback errorCallback) { + get("https://kvv.imp.fu-berlin.de/sakai-login-tool/container", loginToken.getCookies(), response -> callback.onResponse(new HashMap<>()), error -> errorCallback.onError(new NetworkError(100160, error.networkResponse.statusCode, "Cannot finish login process!"))); + } + + + + + + + + + + + + + private String getCookie(String cookies, String name) throws NoSuchFieldException { + Pattern pattern = Pattern.compile(name+"=([^;]+);"); + Matcher matcher = pattern.matcher(cookies); + if (!matcher.find()) { + log.e("GETcookie failed", name); + log.e("GETcookie failed", cookies); + throw new NoSuchFieldException(); + } + return matcher.group(1); + } + + private HashMap getCookie(String cookies, String[] names) throws NoSuchFieldException { + HashMap result = new HashMap<>(); + for (String name: names) { + result.put(name,this.getCookie(cookies, name)); + } + return result; + } +} diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModules.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModules.java new file mode 100644 index 0000000..546a057 --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModules.java @@ -0,0 +1,43 @@ +package de.sebse.fuplanner.services.NewKVV; + +import android.content.Context; + +import org.jetbrains.annotations.NotNull; + +import java.util.HashMap; + +public class KVVModules { + private final HashMap addons = new HashMap<>(); + private final KVVLogin login; + private final Context context; + + public KVVModules(KVVLogin login, Context context) { + this.login = login; + this.context = context; + } + + @NotNull + public KVVModulesAnnouncements announcements() { + return (KVVModulesAnnouncements) addAndGet("announcements", () -> new KVVModulesAnnouncements(login, list(), context)); + } + + @NotNull + public KVVModulesList list() { + return (KVVModulesList) addAndGet("list", () -> new KVVModulesList(login, context)); + } + + + @NotNull + private Object addAndGet(@NotNull String addon, @NotNull ModuleCreatorInterface creatorInterface) { + Object o = addons.get(addon); + if (o == null) { + o = creatorInterface.create(); + addons.put(addon, o); + } + return o; + } + + private interface ModuleCreatorInterface { + @NotNull Object create(); + } +} diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesAnnouncements.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesAnnouncements.java new file mode 100644 index 0000000..90e60c2 --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesAnnouncements.java @@ -0,0 +1,88 @@ +package de.sebse.fuplanner.services.NewKVV; + +import android.content.Context; +import android.os.Build; +import android.text.Html; +import android.text.Spanned; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; + +import de.sebse.fuplanner.services.NewKVV.types.Announcement; +import de.sebse.fuplanner.services.NewKVV.types.Modules; +import de.sebse.fuplanner.tools.network.NetworkCallback; +import de.sebse.fuplanner.tools.network.NetworkError; +import de.sebse.fuplanner.tools.network.NetworkErrorCallback; + +class KVVModulesAnnouncements extends ModulesPart> { + + KVVModulesAnnouncements(KVVLogin login, KVVModulesList list, Context context) { + super(login, list, context); + } + + @Override + protected ArrayList getPart(Modules.Module module) { + return module.announcements; + } + + @Override + protected boolean setPart(Modules.Module module, ArrayList part) { + boolean changed = false; + if (module.announcements != null && module.announcements.hashCode() != part.hashCode()) + changed = true; + module.announcements = part; + return changed; + } + + @Override + protected void upgrade(final String ID, final NetworkCallback> callback, final NetworkErrorCallback errorCallback) { + if (!login.isInOnlineMode()) { + 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 -> { + String body = response.getParsed(); + if (body == null) { + errorCallback.onError(new NetworkError(101201, 403, "No announcements retrieved!")); + return; + } + ArrayList announcements = new ArrayList<>(); + try { + JSONObject json = new JSONObject(body); + JSONArray sites = json.getJSONArray("announcement_collection"); + + for (int i = 0; i < sites.length(); i++) { + JSONObject site = sites.getJSONObject(i); + String id = site.getString("announcementId"); + String title = site.getString("title"); + String text = site.getString("body"); + text = String.valueOf(fromHtml(text)); + String createdBy = site.getString("createdByDisplayName"); + long createdOn = site.getLong("createdOn"); + + // 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); + 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/KVVModulesList.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesList.java new file mode 100644 index 0000000..18947e0 --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesList.java @@ -0,0 +1,161 @@ +package de.sebse.fuplanner.services.NewKVV; + +import android.content.Context; + +import org.jetbrains.annotations.Nullable; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.HashSet; +import java.util.regex.MatchResult; + +import de.sebse.fuplanner.services.NewKVV.types.Lecturer; +import de.sebse.fuplanner.services.NewKVV.types.Modules; +import de.sebse.fuplanner.tools.NewAsyncQueue; +import de.sebse.fuplanner.tools.Regex; +import de.sebse.fuplanner.tools.network.HTTPService; +import de.sebse.fuplanner.tools.network.NetworkCallback; +import de.sebse.fuplanner.tools.network.NetworkError; +import de.sebse.fuplanner.tools.network.NetworkErrorCallback; + +import static de.sebse.fuplanner.services.NewKVV.ModulesPart.RETRY_COUNT; + +public class KVVModulesList extends HTTPService { + protected final KVVLogin login; + @Nullable private Modules modules; + private NewAsyncQueue queue = new NewAsyncQueue(); + + KVVModulesList(KVVLogin login, Context context) { + super(context); + this.login = login; + restore(); + } + + public void find(String moduleID, NetworkCallback moduleNetworkCallback, NetworkErrorCallback errorCallback) { + find(moduleID, moduleNetworkCallback, errorCallback, RETRY_COUNT); + } + + private void find(String moduleID, NetworkCallback moduleNetworkCallback, NetworkErrorCallback errorCallback, int retries) { + if (retries < 0) { + errorCallback.onError(new NetworkError(101107, -1, "Too many retries!")); + return; + } + if (this.modules != null) { + Modules.Module module = this.modules.get(moduleID); + if (module != null) { + moduleNetworkCallback.onResponse(module); + return; + } + } + recv(success -> find(moduleID, moduleNetworkCallback, errorCallback, retries - 1), errorCallback, true, RETRY_COUNT); + } + + void store() { + if (this.modules != null) { + try { + this.modules.save(getContext()); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + private void restore() { + try { + this.modules = Modules.load(getContext()); + } catch (FileNotFoundException ignored) { + } catch (IOException e) { + e.printStackTrace(); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + } + + public void recv(final NetworkCallback callback, final NetworkErrorCallback errorCallback) { + recv(callback, errorCallback, false, RETRY_COUNT); + } + + public void recv(final NetworkCallback callback, final NetworkErrorCallback errorCallback, boolean forceRefresh, final int retries) { + queue.add(() -> { + if (this.modules != null && !forceRefresh) { + callback.onResponse(this.modules); + queue.next(); + return; + } + this.upgrade(success -> { + if (this.modules == null) + this.modules = success; + else + this.modules.updateList(success); + callback.onResponse(this.modules); + queue.next(); + }, error -> { + if (retries > 0 && (error.getHttpStatus() == 401 || error.getHttpStatus() == 403)) { + login.refreshLogin(success -> { + recv(callback, errorCallback, forceRefresh, retries-1); + queue.next(); + }, errorCallback); + return; + } + errorCallback.onError(error); + queue.next(); + }); + }); + } + + private void upgrade(final NetworkCallback callback, final NetworkErrorCallback errorCallback) { + if (!login.isInOnlineMode()) { + 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", login.getLoginToken().getCookies(), response -> { + String body = response.getParsed(); + if (body == null) { + errorCallback.onError(new NetworkError(101101, 403, "No module list retrieved!")); + return; + } + Modules modules = new Modules(login.getLoginToken()); + 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); + } + } 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; + } + // Empty module *may be* because token is invalid -> check + if (modules.size() == 0) + login.testLoginToken(token -> callback.onResponse(modules), errorCallback); + else + callback.onResponse(modules); + }, error -> errorCallback.onError(new NetworkError(101104, error.networkResponse.statusCode, "Cannot get module list!"))); + } +} 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 new file mode 100644 index 0000000..17239ab --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/ModulesPart.java @@ -0,0 +1,75 @@ +package de.sebse.fuplanner.services.NewKVV; + +import android.content.Context; +import android.os.Build; +import android.text.Html; +import android.text.Spanned; + +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 ModulesPart extends HTTPService { + static final int RETRY_COUNT = 1; + protected final KVVLogin login; + protected final KVVModulesList list; + private NewAsyncQueue queue = new NewAsyncQueue(); + + ModulesPart(KVVLogin login, KVVModulesList list, Context context) { + super(context); + this.login = login; + this.list = list; + } + + public void recv(final String moduleID, final NetworkCallback callback, final NetworkErrorCallback errorCallback) { + recv(moduleID, callback, errorCallback, false); + } + + 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); + } + + private void recv(final Modules.Module module, final NetworkCallback callback, final NetworkErrorCallback errorCallback, final boolean forceRefresh, final int retries) { + queue.add(() -> { + if (getPart(module) != null && !forceRefresh) { + callback.onResponse(module); + queue.next(); + return; + } + upgrade(module.getID(), success -> { + if (setPart(module, success)) { + this.list.store(); + } + callback.onResponse(module); + queue.next(); + }, error -> { + if (retries >= 0 && (error.getHttpStatus() == 401 || error.getHttpStatus() == 403)) { + login.refreshLogin(success -> { + recv(module, callback, errorCallback, forceRefresh, retries-1); + queue.next(); + }, errorCallback); + return; + } + errorCallback.onError(error); + queue.next(); + }); + }); + } + + static Spanned fromHtml(String html){ + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + return Html.fromHtml(html, Html.FROM_HTML_MODE_LEGACY); + } else { + //noinspection deprecation + return Html.fromHtml(html); + } + } + + protected abstract T getPart(Modules.Module module); + + protected abstract boolean setPart(Modules.Module module, T part); + + protected abstract void upgrade(final String ID, final NetworkCallback callback, final NetworkErrorCallback errorCallback); +} diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Announcement.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Announcement.java new file mode 100644 index 0000000..f25a6b7 --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Announcement.java @@ -0,0 +1,64 @@ +package de.sebse.fuplanner.services.NewKVV.types; + +import com.google.android.gms.common.internal.Objects; + +import java.io.Serializable; +import java.util.ArrayList; + +public class Announcement implements Serializable { + private final String id; + private final String title; + private final String body; + private final String createdBy; + private final long createdOn; + private final ArrayList urls; + + public Announcement(String id, String title, String body, String createdBy, long createdOn, ArrayList urls) { + + this.id = id; + this.title = title; + this.body = body; + this.createdBy = createdBy; + this.createdOn = createdOn; + this.urls = urls; + } + + public ArrayList getUrls() { + return urls; + } + + private String getId() { + return id; + } + + public String getTitle() { + return title; + } + + public String getBody() { + return body; + } + + public String getCreatedBy() { + return createdBy; + } + + public long getCreatedOn() { + return createdOn; + } + + @Override + public String toString() { + return "ID: "+getId()+ + "\nTitle: "+getTitle()+ + "\nBody length: "+getBody().length()+ + "\nCreated by: "+getCreatedBy()+ + "\nCreated on: "+getCreatedOn()+ + "\nURLs: "+getUrls().toString(); + } + + @Override + public int hashCode() { + return Objects.hashCode(getId(), getBody(), getCreatedBy(), getCreatedOn(), getTitle(), getUrls()); + } +} diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Assignment.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Assignment.java new file mode 100644 index 0000000..4f366af --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Assignment.java @@ -0,0 +1,53 @@ +package de.sebse.fuplanner.services.NewKVV.types; + +import java.io.Serializable; +import java.util.ArrayList; + +public class Assignment implements Serializable { + private final String id; + private final String title; + private final long dueTime; + private final ArrayList urls; + private final String instructions; + + public Assignment(String id, String title, long dueTime, String gradebookItemName, String gradeScale, ArrayList urls, String instructions) {//, String grade + this.id = id; + this.title = title; + this.dueTime = dueTime; + this.urls = urls; + //this.grade = grade; + this.instructions = instructions; + } + + private String getId() { + return id; + } + + public String getTitle() { + return title; + } + + public boolean isOpen() { + return dueTime > System.currentTimeMillis(); + } + + public long getDueDate() { + return dueTime; + } + + public ArrayList getUrls() { + return urls; + } + + public String getInstructions() { + return instructions; + } + + @Override + public String toString() { + return "ID: "+getId()+ + "\nTitle: "+getTitle()+ + "\nDue date: "+getDueDate()+ + "\nInstructions: "+getInstructions().substring(0, Math.min(getInstructions().length(), 100)); + } +} diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/AssignmentList.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/AssignmentList.java new file mode 100644 index 0000000..969e03f --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/AssignmentList.java @@ -0,0 +1,16 @@ +package de.sebse.fuplanner.services.NewKVV.types; + +import de.sebse.fuplanner.tools.DateSortedList; + +public class AssignmentList extends DateSortedList { + + @Override + public long getDateByItem(Assignment item) { + return item.getDueDate(); + } + + @Override + public boolean reversed() { + return true; + } +} diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Event.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Event.java new file mode 100644 index 0000000..ee73985 --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Event.java @@ -0,0 +1,114 @@ +package de.sebse.fuplanner.services.NewKVV.types; + +import java.io.Serializable; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +import de.sebse.fuplanner.tools.ColorRGB; + +public class Event implements Serializable { + private final String siteId; + private final String id; + private final String type; + private final String title; + private final long duration; + private final long firstTime; + private final String location; + + public Event(String id, String type, String title, long duration, long firstTime, String siteId, String location) { + this.siteId = siteId; + this.id = id; + this.type = type; + this.title = title; + this.duration = duration; + this.firstTime = firstTime; + this.location = location + .replace(" Übungsraum", "") + .replace(" Konferenzraum", "") + .replace(" Seminarraum", ""); + } + + public String getId() { + return id; + } + + public String getTitle() { + return this.title; + } + + public String getType() { + return this.type; + } + + public long getStartDate() { + return this.firstTime; + } + + public long getEndDate() { + return this.firstTime+this.duration; + } + + public String getLocation() { + return location; + } + + public String getModuleId() { + return siteId; + } + + public ColorRGB getColor() { + MessageDigest digest; + try { + digest = MessageDigest.getInstance("SHA-256"); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + return null; + } + byte[] encodedHash; + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) { + encodedHash = digest.digest(siteId.getBytes(StandardCharsets.UTF_8)); + } else { + encodedHash = digest.digest(siteId.getBytes()); + } + int h = (0xff & encodedHash[0]) + (0xff & encodedHash[1]) * 255; + h = h * 360 / 0xffff; + //int s = 0xff & encodedHash[2]; + //s = s * 100 / 0xffff; + //int v = 0xff & encodedHash[3]; + //v = v * 100 / 0xffff; + + // range for more beautiful colors + h = h / 30 * 30; + int s = 100; + int v = 80; + + return hsvToRgb(h/360.0, s/100.0, v/100.0); + } + + private static ColorRGB hsvToRgb(double hue, double saturation, double value) { + int h = (int)(hue * 6); + double f = hue * 6 - h; + double p = value * (1 - saturation); + double q = value * (1 - f * saturation); + double t = value * (1 - (1 - f) * saturation); + + switch (h) { + case 0: return new ColorRGB(value, t, p); + case 1: return new ColorRGB(q, value, p); + case 2: return new ColorRGB(p, value, t); + case 3: return new ColorRGB(p, q, value); + case 4: return new ColorRGB(t, p, value); + case 5: return new ColorRGB(value, p, q); + default: throw new RuntimeException("Something went wrong when converting from HSV to RGB. Input was " + hue + ", " + saturation + ", " + value); + } + } + + @Override + public String toString() { + return "ID: "+getId()+ + "\nType: "+getType()+ + "\nStart Date: "+getStartDate()+ + "\nEnd date: "+getEndDate(); + } +} diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/EventList.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/EventList.java new file mode 100644 index 0000000..1c18424 --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/EventList.java @@ -0,0 +1,16 @@ +package de.sebse.fuplanner.services.NewKVV.types; + +import de.sebse.fuplanner.tools.DateSortedList; + +public class EventList extends DateSortedList { + + @Override + public long getDateByItem(Event item) { + return item.getEndDate(); + } + + @Override + public boolean reversed() { + return false; + } +} diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Gradebook.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Gradebook.java new file mode 100644 index 0000000..d97e368 --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Gradebook.java @@ -0,0 +1,34 @@ +package de.sebse.fuplanner.services.NewKVV.types; + +import java.io.Serializable; + +public class Gradebook implements Serializable { + private final String itemName; + private final double grade; + private final double maxPoints; + + public Gradebook(String itemName, double points, double maxPoints) { + this.itemName = itemName; + this.grade = points; + this.maxPoints = maxPoints; + } + + public double getMaxPoints() { + return maxPoints; + } + + public double getPoints() { + return grade; + } + + public String getItemName() { + return itemName; + } + + @Override + public String toString() { + return "Name: "+getItemName()+ + "\nPoints: "+ getPoints()+ + "\nMax points: "+getMaxPoints(); + } +} diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/GroupedEvents.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/GroupedEvents.java new file mode 100644 index 0000000..0911641 --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/GroupedEvents.java @@ -0,0 +1,128 @@ +package de.sebse.fuplanner.services.NewKVV.types; + + +import android.annotation.SuppressLint; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collections; +import java.util.List; + +import androidx.annotation.NonNull; +import de.sebse.fuplanner.tools.logging.Logger; + +public class GroupedEvents { + private ArrayList arrayList = new ArrayList<>(); + private Logger log = new Logger(this); + + public void add(Event event) { + Calendar calendar = Calendar.getInstance(); + calendar.setTimeInMillis(event.getStartDate()); + long dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK); + for (Group group : arrayList) { + if (group.add(event)) { + return; + } + } + arrayList.add(new Group(event)); + } + + public List getGroups() { + return Collections.unmodifiableList(arrayList); + } + + public class Group { + private long firstDate; + private long lastDate; + private ArrayList skippedDates; + + private int dayOfWeek; + private long startTime; + private long duration; + + private Group(Event event) { + Calendar calendar = Calendar.getInstance(); + calendar.setTimeInMillis(event.getStartDate()); + dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK); + startTime = calendar.get(Calendar.HOUR_OF_DAY)*3600000+calendar.get(Calendar.MINUTE)*60000+calendar.get(Calendar.SECOND)*1000+calendar.get(Calendar.MILLISECOND); + duration = event.getEndDate()-event.getStartDate(); + + skippedDates = new ArrayList<>(); + calendar.set(Calendar.HOUR_OF_DAY, 0); + calendar.set(Calendar.MINUTE, 0); + calendar.set(Calendar.SECOND, 0); + calendar.set(Calendar.MILLISECOND, 0); + firstDate = calendar.getTimeInMillis(); + lastDate = firstDate; + } + + private boolean add(Event event) { + Calendar calendar = Calendar.getInstance(); + calendar.setTimeInMillis(event.getStartDate()); + int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK); + int startTime = calendar.get(Calendar.HOUR_OF_DAY)*3600000+calendar.get(Calendar.MINUTE)*60000+calendar.get(Calendar.SECOND)*1000+calendar.get(Calendar.MILLISECOND); + long length = event.getEndDate()-event.getStartDate(); + if (this.dayOfWeek != dayOfWeek || this.startTime != startTime || this.duration != length) + return false; + calendar.set(Calendar.HOUR_OF_DAY, 0); + calendar.set(Calendar.MINUTE, 0); + calendar.set(Calendar.SECOND, 0); + calendar.set(Calendar.MILLISECOND, 0); + long date = calendar.getTimeInMillis(); + if (date < firstDate) { + firstDate = addDays(firstDate, -7); + while (firstDate > date) { + skippedDates.add(firstDate); + firstDate = addDays(firstDate, -7); + } + } else if (date > lastDate) { + lastDate = addDays(lastDate, 7); + while (lastDate < date) { + skippedDates.add(lastDate); + lastDate = addDays(lastDate, 7); + } + } else { + skippedDates.remove(date); + } + return true; + } + + private long addDays(long timeInMillis, int days) { + Calendar calendar = Calendar.getInstance(); + calendar.setTimeInMillis(timeInMillis); + calendar.add(Calendar.DAY_OF_YEAR, days); + return calendar.getTimeInMillis(); + } + + public long getFirstDate() { + return firstDate; + } + + public long getLastDate() { + return lastDate; + } + + public List getSkippedDates() { + return Collections.unmodifiableList(skippedDates); + } + + public int getDayOfWeek() { + return dayOfWeek; + } + + public long getStartTime() { + return startTime; + } + + public long getDuration() { + return duration; + } + + @SuppressLint("DefaultLocale") + @NonNull + @Override + public String toString() { + return String.format("%d - %d - %d - %s", dayOfWeek, startTime, duration, skippedDates); + } + } +} diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Lecturer.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Lecturer.java new file mode 100644 index 0000000..31a2163 --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Lecturer.java @@ -0,0 +1,41 @@ +package de.sebse.fuplanner.services.NewKVV.types; + +import java.io.Serializable; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class Lecturer implements Serializable { + private final String firstName; + private final String surname; + private final String mail; + + public Lecturer(String parsableString) throws NoSuchFieldException { + Pattern pattern = Pattern.compile("([^|]*)\\|([^|]*)\\|([^|]*)\\|\\|", Pattern.DOTALL); + Matcher matcher = pattern.matcher(parsableString); + if (!matcher.find()) { + throw new NoSuchFieldException(); + } + this.firstName = matcher.group(1); + this.surname = matcher.group(2); + this.mail = matcher.group(3); + } + + private String getFirstName() { + return firstName; + } + + private String getSurname() { + return surname; + } + + private String getMail() { + return mail; + } + + @Override + public String toString() { + return "First name: "+ getFirstName()+ + "\nSurname: "+getSurname()+ + "\nMail: "+getMail(); + } +} diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/LoginToken.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/LoginToken.java new file mode 100644 index 0000000..015c82d --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/LoginToken.java @@ -0,0 +1,114 @@ +package de.sebse.fuplanner.services.NewKVV.types; + +import android.content.Context; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.HashMap; + +import androidx.annotation.Nullable; + +/** + * Created by sebastian on 29.10.17. + */ + +public class LoginToken implements Serializable { + private static final String FILE_NAME = "LoginTokenSaveFile"; + + private final String username; + private final String shibsessionKey; + private final String shibsessionName; + private final String JSESSIONID; + @Nullable private String fullName; + @Nullable private String email; + + public LoginToken(String username, String shibsessionKey, String shibsessionName, String JSESSIONID) { + this.username = username; + this.shibsessionKey = shibsessionKey; + this.shibsessionName = shibsessionName; + this.JSESSIONID = JSESSIONID; + } + + @Nullable + public static LoginToken load(Context context) throws IOException, ClassNotFoundException { + FileInputStream fis; + try { + fis = context.openFileInput(FILE_NAME); + } catch (FileNotFoundException e) { + return null; + } + ObjectInputStream is = new ObjectInputStream(fis); + LoginToken loginToken = (LoginToken) is.readObject(); + is.close(); + fis.close(); + return loginToken; + } + + public void save(Context context) throws IOException { + FileOutputStream fos = context.openFileOutput(FILE_NAME, Context.MODE_PRIVATE); + ObjectOutputStream os = new ObjectOutputStream(fos); + os.writeObject(this); + os.close(); + fos.close(); + } + + public void delete(Context context) { + context.deleteFile(FILE_NAME); + } + + public void setAdditionals(String fullName, String email) { + this.fullName = fullName; + this.email = email; + } + + public String getUsername() { + return username; + } + + private String getShibsessionKey() { + return shibsessionKey; + } + + private String getShibsessionName() { + return shibsessionName; + } + + private String getJSESSIONID() { + return JSESSIONID; + } + + public String getFullName() { + return fullName; + } + + public String getEmail() { + return email; + } + + public HashMap getCookies() { + HashMap cookies = new HashMap<>(); + cookies.put("JSESSIONID", getJSESSIONID()); + cookies.put(getShibsessionKey(), getShibsessionName()); + cookies.put("pasystem_timezone_ok", "true"); + return cookies; + } + + public boolean isSameUser(LoginToken token) { + return token != null && this.getUsername().equals(token.getUsername()); + } + + @Override + public String toString() { + StringBuilder result = new StringBuilder(); + HashMap cookies = this.getCookies(); + for (String header: cookies.keySet()) { + result.append(header).append("=").append(cookies.get(header)).append(";"); + } + return result.substring(0, result.length()-1); + } +} 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 new file mode 100644 index 0000000..6c4c21d --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Modules.java @@ -0,0 +1,168 @@ +package de.sebse.fuplanner.services.NewKVV.types; + +import android.content.Context; + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +/** + * Created by sebastian on 29.10.17. + */ + +public class Modules implements Iterable, Serializable { + private SortedListModule list; + private final LoginToken token; + //private transient Logger log = new Logger(this); + private static final String FILE_NAME = "ModuleListSaveFile"; + + public Modules(LoginToken loginToken) { + this.token = loginToken; + this.list = new SortedListModule(); + } + + public void addModule(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); + } + + @NonNull + @Override + public String toString() { + return this.list.toString(); + } + + @NonNull + @Override + public Iterator iterator() { + return this.list.iterator(); + } + + public Iterator latestSemesterIterator() { + return this.list.filteredIterator(this.list.getLatestSemester()); + } + + public int size() { + return this.list.size(); + } + + public Module get(String id) { + return this.list.getById(id); + } + + public Module getByIndex(int index) { + return this.list.get(index); + } + + public static Modules load(Context context) throws IOException, ClassNotFoundException { + FileInputStream fis = context.openFileInput(FILE_NAME); + ObjectInputStream is = new ObjectInputStream(fis); + Modules modules = (Modules) is.readObject(); + is.close(); + fis.close(); + return modules; + } + + public void save(Context context) throws IOException { + FileOutputStream fos = context.openFileOutput(FILE_NAME, Context.MODE_PRIVATE); + ObjectOutputStream os = new ObjectOutputStream(fos); + os.writeObject(this); + os.close(); + fos.close(); + } + + public void delete(Context context) { + context.deleteFile(FILE_NAME); + } + + public LoginToken getToken() { + return token; + } + + public void updateList(Modules modules) { + SortedListModule old = this.list; + this.list = modules.list; + for (Module oldModule : old) { + Module newModule = this.list.getById(oldModule.getID()); + if (newModule != null) { + newModule.announcements = oldModule.announcements; + newModule.assignments = oldModule.assignments; + newModule.events = oldModule.events; + newModule.gradebook = oldModule.gradebook; + newModule.resources = oldModule.resources; + } + } + } + + 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 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; + if (gradebook != null) { + for (Gradebook g : gradebook){ + maxPoint += g.getMaxPoints(); + userPoint += g.getPoints(); + } + } + if (maxPoint == 0) + return 0; + 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"); + title = title.replaceAll("(.*?) (S[0-9]{2}|W[0-9/]{5})", "$1"); + + this.semester = semester; + this.lvNumber = lvNumber; + this.title = title; + this.lecturer = lecturer; + this.type = type; + this.description = description; + this.ID = ID; + } + + public String getID() { + return ID; + } + + @NonNull + @Override + public String toString() { + return "Semester: "+semester+ + "\nlvNumber: "+lvNumber.toString()+ + "\ntitle: "+title+ + "\nlecturer: "+lecturer.toString()+ + "\ntype: "+type+ + "\nID: "+ID; + } + } +} diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Resource.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Resource.java new file mode 100644 index 0000000..598cf69 --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Resource.java @@ -0,0 +1,134 @@ +package de.sebse.fuplanner.services.NewKVV.types; + +import java.io.Serializable; +import java.util.ArrayList; + +import androidx.annotation.LayoutRes; +import de.sebse.fuplanner.R; +import de.sebse.fuplanner.tools.ui.treeview.LayoutItemType; +import de.sebse.fuplanner.tools.ui.treeview.TreeNode; + + +public abstract class Resource implements Serializable { + + final String author; + final long modifiedDate; + final String title; + final String url; + private final boolean visible; + private final String container; + + + Resource(String author, String title, long modifiedDate, String url, boolean visible, String container) { + this.author = author; + this.title = title; + this.modifiedDate = modifiedDate; + this.url = url; + this.visible = visible; + this.container = container; + } + + public String getAuthor() { + return author; + } + + public long getModifiedDate() { + return modifiedDate; + } + + public String getTitle() { + return title; + } + + public String getUrl() { + return url; + } + + public String getContainer() { + return container; + } + + public boolean isVisible() { + return visible; + } + + public abstract TreeNode getTreeNode(); + + public static class File extends Resource implements LayoutItemType { + private final String type; + + public File(String author, String title, long modifiedDate, String url, boolean visible, String container, String type) { + super(author, title, modifiedDate, url, visible, container); + this.type = type; + } + + @Override + public String toString() { + return "Resource{" + + "author='" + author + '\'' + + ", modifiedDate=" + modifiedDate + + ", title='" + title + '\'' + + ", url='" + url + '\'' + + ", type='" + type + '\'' + + '}'; + } + + @Override + public TreeNode getTreeNode() { + return new TreeNode<>(this); + } + + @Override + public @LayoutRes int getLayoutId() { + return R.layout.item_file; + } + } + + public static class Folder extends Resource implements LayoutItemType { + + private final ArrayList children; + public Folder(String author, String title, long modifiedDate, String url, boolean visible, String container) { + super(author, title, modifiedDate, url, visible, container); + children = new ArrayList<>(); + } + + public void add(Resource res){ + children.add(res); + } + + public Resource get(int id){ + return children.get(id); + } + + public int size(){ + return children.size(); + } + + @Override + public String toString() { + return "Resource{" + + "author='" + author + '\'' + + ", modifiedDate=" + modifiedDate + + ", title='" + title + '\'' + + ", url='" + url + '\'' + + ", children='" + children + '\'' + + '}'; + } + + @Override + public TreeNode getTreeNode() { + TreeNode dir = new TreeNode<>(this); + for (Resource res: children) { + dir.addChild(res.getTreeNode()); + } + return dir; + } + + @Override + public @LayoutRes int getLayoutId() { + return R.layout.item_dir; + } + } +} + + 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 new file mode 100644 index 0000000..13b1a83 --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/SortedListModule.java @@ -0,0 +1,68 @@ +package de.sebse.fuplanner.services.NewKVV.types; + +import de.sebse.fuplanner.tools.Regex; +import de.sebse.fuplanner.tools.SortedList; + +public class SortedListModule extends SortedList { + private static final int LARGER = 1; + private static final int EQUAL = 0; + private static final int SMALLER = -1; + + @Override + public int compare(Modules.Module o1, Modules.Module o2) { + int semester; + try { + semester = -compareSemester(o1.semester, o2.semester); + } catch (NoSuchFieldException e) { + e.printStackTrace(); + semester = EQUAL; + } + if (semester != EQUAL) + return semester; + return o1.title.compareToIgnoreCase(o2.title); + } + + @Override + public void add(Modules.Module e) { + super.add(e); + } + + public String getLatestSemester() { + if (size() > 0) + //noinspection ConstantConditions + return this.get(0).semester; + else + return null; + } + + private static int compareSemester(String a, String b) throws NoSuchFieldException { + if (a == null && b == null) + return EQUAL; + if (a == null) + return SMALLER; + if (b == null) + return LARGER; + + String s1type = Regex.regex("^(S|WS) ", a); + int s1year = Integer.parseInt(Regex.regex("^(S|WS) ([0-9]{2})", a, 2)); + String s2type = Regex.regex("^(S|WS) ", b); + int s2year = Integer.parseInt(Regex.regex("^(S|WS) ([0-9]{2})", b, 2)); + + if (s1year == s2year) { + if (s1type.equals(s2type)) + return EQUAL; + return s1type.equals("S") ? SMALLER : LARGER; + } + return s1year < s2year ? SMALLER : LARGER; + } + + @Override + public boolean hasIdentifier(Modules.Module o1, String id) { + return o1.getID().equals(id); + } + + @Override + public boolean hasFilter(Modules.Module o1, String filter) { + return o1.semester.equals(filter); + } +} diff --git a/app/src/main/java/de/sebse/fuplanner/tools/MainActivityListener.java b/app/src/main/java/de/sebse/fuplanner/tools/MainActivityListener.java index 63f5306..c972745 100644 --- a/app/src/main/java/de/sebse/fuplanner/tools/MainActivityListener.java +++ b/app/src/main/java/de/sebse/fuplanner/tools/MainActivityListener.java @@ -28,6 +28,4 @@ public interface MainActivityListener { void addRequestPermissionsResultListener(RequestPermissionsResultListener listener, String id); void removeRequestPermissionsResultListener(String id); - - void refreshNavigation(); } diff --git a/app/src/main/java/de/sebse/fuplanner/tools/NewAsyncQueue.java b/app/src/main/java/de/sebse/fuplanner/tools/NewAsyncQueue.java new file mode 100644 index 0000000..8a39c91 --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/tools/NewAsyncQueue.java @@ -0,0 +1,58 @@ +package de.sebse.fuplanner.tools; + +import java.util.LinkedList; + +import de.sebse.fuplanner.tools.network.NetworkCallback; +import de.sebse.fuplanner.tools.network.NetworkErrorCallback; + +public class NewAsyncQueue { + private final LinkedList mQueue = new LinkedList<>(); + private boolean mIsRunning = false; + + public void add(AsyncQueueCallback callback) { + if (isRunning()) + getQueue().addLast(callback); + else { + setRunning(true); + callback.run(); + } + } + + public void next() { + AsyncQueueCallback callback = getQueue().pollFirst(); + if (callback == null) + setRunning(false); + else + callback.run(); + } + + public interface AsyncQueueCallback { + void run(); + } + + public NetworkErrorCallback check(NetworkErrorCallback value) { + return error -> { + value.onError(error); + next(); + }; + } + + public NetworkCallback check(NetworkCallback value) { + return success -> { + value.onResponse(success); + next(); + }; + } + + private boolean isRunning() { + return mIsRunning; + } + + private void setRunning(boolean value) { + mIsRunning = value; + } + + private LinkedList getQueue() { + return mQueue; + } +} diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 6b82597..e962ffb 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -10,6 +10,7 @@ diff --git a/app/src/main/res/xml/provider_paths.xml b/app/src/main/res/xml/provider_paths.xml deleted file mode 100644 index 4495c28..0000000 --- a/app/src/main/res/xml/provider_paths.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file From e46a184f357e4b380f320941bd4bccd055014d89 Mon Sep 17 00:00:00 2001 From: Caesar2011 Date: Wed, 7 Nov 2018 19:36:33 +0100 Subject: [PATCH 02/17] Updated LoginFragment and ModulesFragment (not runnable) --- .../java/de/sebse/fuplanner/MainActivity.java | 12 +- .../fuplanner/fragments/CanteensFragment.java | 4 +- .../fuplanner/fragments/LoginFragment.java | 109 +++++------------- .../fuplanner/fragments/ModulesAdapter.java | 2 +- .../fuplanner/fragments/ModulesFragment.java | 12 +- .../fuplanner/services/NewKVV/KVVLogin.java | 33 ++++-- .../services/NewKVV/KVVModulesList.java | 83 ++++++++----- .../services/NewKVV/types/LoginToken.java | 4 +- .../services/NewKVV/types/Modules.java | 10 +- .../fuplanner/tools/MainActivityListener.java | 2 + 10 files changed, 129 insertions(+), 142 deletions(-) diff --git a/app/src/main/java/de/sebse/fuplanner/MainActivity.java b/app/src/main/java/de/sebse/fuplanner/MainActivity.java index 6108cc6..b2cd54b 100644 --- a/app/src/main/java/de/sebse/fuplanner/MainActivity.java +++ b/app/src/main/java/de/sebse/fuplanner/MainActivity.java @@ -48,7 +48,6 @@ import de.sebse.fuplanner.tools.network.NetworkErrorCallback; public class MainActivity extends AppCompatActivity implements MainActivityListener, KVVListener, NavigationView.OnNavigationItemSelectedListener, - LoginFragment.OnLoginFragmentInteractionListener, ModulesFragment.OnModulesFragmentInteractionListener, CanteensFragment.OnCanteensFragmentInteractionListener { @@ -102,7 +101,10 @@ public class MainActivity extends AppCompatActivity mNavigationView.setNavigationItemSelectedListener(this); mFragmentManager = getSupportFragmentManager(); - getNewKVV().account().doOfflineLogin(); + if (!getNewKVV().account().restoreOnlineLogin()) { + desiredPage = FRAGMENT_LOGIN; + desiredData = ""; + } updateNavigation(); changeFragment(desiredPage, desiredData); } @@ -492,12 +494,6 @@ public class MainActivity extends AppCompatActivity - @Override - public void onLoginFragmentInteraction(LoginToken loginToken, boolean onlineMode) { - int fragment = getDefaultFragmentAfterLogin(); - toLoginState(loginToken.getFullName(), loginToken.getEmail(), fragment, "", onlineMode); - } - @Override public void onModulesFragmentInteraction(final String itemID) { changeFragment(FRAGMENT_MODULES_DETAILS, itemID); diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/CanteensFragment.java b/app/src/main/java/de/sebse/fuplanner/fragments/CanteensFragment.java index c7d206d..9eee7a8 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/CanteensFragment.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/CanteensFragment.java @@ -70,8 +70,8 @@ public class CanteensFragment extends Fragment { CanteenBrowser browser = ((MainActivity) getActivity()).getCanteenBrowser(); browser.getCanteens(success -> { adapter.setCanteens(success); - if (mMainActivityListener != null) - mMainActivityListener.refreshNavigation(); + //if (mMainActivityListener != null) + // mMainActivityListener.refreshNavigation(); swipeLayout.setRefreshing(false); }, error -> { log.e(error.toString()); 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 f063748..2bbbb92 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/LoginFragment.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/LoginFragment.java @@ -9,31 +9,21 @@ import android.view.ViewGroup; import android.widget.Button; import android.widget.EditText; -import java.io.IOException; - import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; -import de.sebse.fuplanner.MainActivity; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.GoogleAuth.GoogleAuth; -import de.sebse.fuplanner.services.KVV.KVV; -import de.sebse.fuplanner.services.KVV.types.LoginToken; -import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.tools.MainActivityListener; import de.sebse.fuplanner.tools.logging.Logger; /** * A simple {@link Fragment} subclass. - * Activities that contain this fragment must implement the - * {@link LoginFragment.OnLoginFragmentInteractionListener} interface - * to handle interaction events. * Use the {@link LoginFragment#newInstance} factory method to * create an instance of this fragment. */ public class LoginFragment extends Fragment { - private OnLoginFragmentInteractionListener mListener; private final Logger log = new Logger(this); - private MainActivityListener mActivityListener; + @Nullable private MainActivityListener mActivityListener; public LoginFragment() { // Required empty public constructor @@ -57,21 +47,11 @@ public class LoginFragment extends Fragment { Bundle savedInstanceState) { // Inflate the layout for this fragment View v = inflater.inflate(R.layout.fragment_login, container, false); - 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.getToken().getUsername())); - offline_btn.setOnClickListener(v1 -> mListener.onLoginFragmentInteraction(modules.getToken(), false)); - } - } - } catch (IOException e) { - e.printStackTrace(); - } catch (ClassNotFoundException e) { - e.printStackTrace(); + if (mActivityListener != null && mActivityListener.getNewKVV().modules().list().stored()) { + 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, mActivityListener.getNewKVV().modules().list().getUsername())); + offline_btn.setOnClickListener(v1 -> mActivityListener.getNewKVV().account().doOfflineLogin()); } View btn_login = v.findViewById(R.id.btn_login); @@ -84,40 +64,29 @@ public class LoginFragment extends Fragment { 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(); + + mActivityListener.getNewKVV().account().doOnlineLogin(username, password, success -> { + progressDialog.dismiss(); + mActivityListener.getGoogleAuth().setLoginState(username, password); + input_usr.setError(null); + input_pwd.setError(null); + }, error -> { + progressDialog.dismiss(); + // Invalid password + if (mActivityListener != null) { + if (error.getCode() == 100131) { + mActivityListener.showToast(R.string.invalid_credentials); + input_usr.setError(input_usr.getResources().getString(R.string.invalid_credentials)); + input_pwd.setError(input_pwd.getResources().getString(R.string.invalid_credentials)); + } else { + mActivityListener.showToast(v.getResources().getString(R.string.error_occurred_code, error.getCode())); } - 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) { - input_usr.setError(null); - input_pwd.setError(null); - mListener.onLoginFragmentInteraction(success, true); - } - }, error -> { - progressDialog.dismiss(); - // Invalid password - if (mActivityListener != null) { - if (error.getCode() == 100131) { - mActivityListener.showToast(R.string.invalid_credentials); - input_usr.setError(input_usr.getResources().getString(R.string.invalid_credentials)); - input_pwd.setError(input_pwd.getResources().getString(R.string.invalid_credentials)); - } else { - mActivityListener.showToast(v.getResources().getString(R.string.error_occurred_code, error.getCode())); - } - } - log.e("Error on KVV login!", error); - }); } - } + log.e("Error on KVV login!", error); + }); }); return v; @@ -128,12 +97,6 @@ public class LoginFragment extends Fragment { @Override public void onAttach(Context context) { super.onAttach(context); - if (context instanceof OnLoginFragmentInteractionListener) { - mListener = (OnLoginFragmentInteractionListener) context; - } else { - throw new RuntimeException(context.toString() - + " must implement OnLoginFragmentInteractionListener"); - } if (context instanceof MainActivityListener) { mActivityListener = (MainActivityListener) context; mActivityListener.onTitleTextChange(R.string.log_in); @@ -144,20 +107,6 @@ public class LoginFragment extends Fragment { @Override public void onDetach() { super.onDetach(); - mListener = null; - } - - /** - * This interface must be implemented by activities that contain this - * fragment to allow an interaction in this fragment to be communicated - * to the activity and potentially other fragments contained in that - * activity. - *

- * See the Android Training lesson Communicating with Other Fragments for more information. - */ - public interface OnLoginFragmentInteractionListener { - void onLoginFragmentInteraction(LoginToken loginToken, boolean onlineMode); + mActivityListener = null; } } diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/ModulesAdapter.java b/app/src/main/java/de/sebse/fuplanner/fragments/ModulesAdapter.java index 4b85503..5413117 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/ModulesAdapter.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/ModulesAdapter.java @@ -8,7 +8,7 @@ import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import de.sebse.fuplanner.R; import de.sebse.fuplanner.fragments.ModulesFragment.OnModulesFragmentInteractionListener; -import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.services.NewKVV.types.Modules; import de.sebse.fuplanner.tools.ui.ItemViewHolder; /** 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 6ebcf64..9e3afcf 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/ModulesFragment.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/ModulesFragment.java @@ -7,6 +7,7 @@ import android.view.View; import android.view.ViewGroup; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -28,7 +29,7 @@ public class ModulesFragment extends Fragment { private final Logger log = new Logger(this); private ModulesAdapter adapter; private SwipeRefreshLayout swipeLayout; - private MainActivityListener mMainActivityListener; + @Nullable private MainActivityListener mMainActivityListener; /** * Mandatory empty constructor for the fragment manager to instantiate the @@ -66,12 +67,11 @@ public class ModulesFragment extends Fragment { } private void refresh(boolean forceRefresh) { - if (getActivity() != null) { - KVV kvv = ((MainActivity) getActivity()).getKVV(); - kvv.getModuleList(success -> { + if (mMainActivityListener != null) { + mMainActivityListener.getNewKVV().modules().list().recv(success -> { adapter.setModules(success); - if (mMainActivityListener != null) - mMainActivityListener.refreshNavigation(); + //if (mMainActivityListener != null) + // mMainActivityListener.refreshNavigation(); swipeLayout.setRefreshing(false); }, error -> { log.e(error.toString()); diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVLogin.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVLogin.java index 29d4b42..3d89e7d 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVLogin.java +++ b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVLogin.java @@ -3,6 +3,7 @@ package de.sebse.fuplanner.services.NewKVV; import android.content.Context; +import org.jetbrains.annotations.NotNull; import org.json.JSONException; import org.json.JSONObject; @@ -39,10 +40,10 @@ public class KVVLogin extends HTTPService { } mLoginPending = true; doLogin(username, password, token -> { - testLoginToken(token2 -> { - setToken(token, true); + testLoginToken(token, token2 -> { + setToken(token2, true); mLoginPending = false; - callback.onResponse(token); + callback.onResponse(token2); }, error -> { mLoginPending = false; errorCallback.onError(error); @@ -53,13 +54,21 @@ public class KVVLogin extends HTTPService { }); } + public boolean restoreOnlineLogin() { + return restoreLogin(true); + } + public boolean doOfflineLogin() { + return restoreLogin(false); + } + + private boolean restoreLogin(boolean enteringOnlineMode) { if (mLoginPending || mToken != null) return false; mLoginPending = true; boolean result = false; try { - result = setToken(LoginToken.load(getContext()), false); + result = setToken(LoginToken.load(getContext()), enteringOnlineMode); } catch (FileNotFoundException ignored) { } catch (IOException e) { e.printStackTrace(); @@ -110,12 +119,16 @@ public class KVVLogin extends HTTPService { return isLoggedIn() && mOnlineMode; } - public void testLoginToken(NetworkCallback callback, NetworkErrorCallback errorCallback) { + void testLoginToken(NetworkCallback callback, NetworkErrorCallback errorCallback) { if (mToken == null) { errorCallback.onError(new NetworkError(100173, -1, "Not logged in!")); return; } - get(String.format("https://kvv.imp.fu-berlin.de/direct/profile/%s.json", mToken.getUsername()), mToken.getCookies(), response -> { + testLoginToken(mToken, callback, errorCallback); + } + + private void testLoginToken(@NotNull LoginToken token, NetworkCallback callback, NetworkErrorCallback errorCallback) { + get(String.format("https://kvv.imp.fu-berlin.de/direct/profile/%s.json", token.getUsername()), token.getCookies(), response -> { String body = response.getParsed(); if (body == null) { errorCallback.onError(new NetworkError(100172, 403, "Testing login failed!")); @@ -125,8 +138,8 @@ public class KVVLogin extends HTTPService { JSONObject json = new JSONObject(body); String displayName = json.getString("displayName"); String email = json.getString("email"); - mToken.setAdditionals(displayName, email); - callback.onResponse(mToken); + token.setAdditionals(displayName, email); + callback.onResponse(token); } catch (JSONException e) { errorCallback.onError(new NetworkError(100171, 403, "Cannot parse profile!")); } @@ -150,7 +163,7 @@ public class KVVLogin extends HTTPService { private boolean handleCallbacks() { if (mToken != null) { - mListener.handleLogin(mToken, false); + mListener.handleLogin(mToken, mOnlineMode); return true; } else { mListener.handleLogout(); @@ -169,7 +182,7 @@ public class KVVLogin extends HTTPService { e.printStackTrace(); } } - mOnlineMode = !enteringOnlineMode; + mOnlineMode = enteringOnlineMode; return handleCallbacks(); } 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 18947e0..d48f33b 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 @@ -24,27 +24,41 @@ import de.sebse.fuplanner.tools.network.NetworkErrorCallback; import static de.sebse.fuplanner.services.NewKVV.ModulesPart.RETRY_COUNT; public class KVVModulesList extends HTTPService { - protected final KVVLogin login; - @Nullable private Modules modules; - private NewAsyncQueue queue = new NewAsyncQueue(); + private final KVVLogin mLogin; + @Nullable private Modules mModules; + private NewAsyncQueue mQueue = new NewAsyncQueue(); KVVModulesList(KVVLogin login, Context context) { super(context); - this.login = login; + this.mLogin = login; restore(); } + public boolean stored() { + return mModules != null; + } + + @Nullable + public String getUsername() { + if (mModules != null) { + return mModules.getUsername(); + } + return null; + } + public void find(String moduleID, NetworkCallback moduleNetworkCallback, NetworkErrorCallback errorCallback) { find(moduleID, moduleNetworkCallback, errorCallback, RETRY_COUNT); } private void find(String moduleID, NetworkCallback moduleNetworkCallback, NetworkErrorCallback errorCallback, int retries) { + if (mModules != null && mLogin.getLoginToken() != null && mLogin.getLoginToken().isSameUser(mModules.getUsername())) + delete(); if (retries < 0) { errorCallback.onError(new NetworkError(101107, -1, "Too many retries!")); return; } - if (this.modules != null) { - Modules.Module module = this.modules.get(moduleID); + if (this.mModules != null) { + Modules.Module module = this.mModules.get(moduleID); if (module != null) { moduleNetworkCallback.onResponse(module); return; @@ -54,9 +68,9 @@ public class KVVModulesList extends HTTPService { } void store() { - if (this.modules != null) { + if (this.mModules != null) { try { - this.modules.save(getContext()); + this.mModules.save(getContext()); } catch (IOException e) { e.printStackTrace(); } @@ -65,7 +79,7 @@ public class KVVModulesList extends HTTPService { private void restore() { try { - this.modules = Modules.load(getContext()); + this.mModules = Modules.load(getContext()); } catch (FileNotFoundException ignored) { } catch (IOException e) { e.printStackTrace(); @@ -74,51 +88,64 @@ public class KVVModulesList extends HTTPService { } } - public void recv(final NetworkCallback callback, final NetworkErrorCallback errorCallback) { - recv(callback, errorCallback, false, RETRY_COUNT); + private void delete() { + if (this.mModules != null) { + this.mModules.delete(getContext()); + this.mModules = null; + } } - public void recv(final NetworkCallback callback, final NetworkErrorCallback errorCallback, boolean forceRefresh, final int retries) { - queue.add(() -> { - if (this.modules != null && !forceRefresh) { - callback.onResponse(this.modules); - queue.next(); + public void recv(final NetworkCallback callback, final NetworkErrorCallback errorCallback) { + recv(callback, errorCallback, false); + } + + public void recv(final NetworkCallback callback, final NetworkErrorCallback errorCallback, boolean forceRefresh) { + recv(callback, errorCallback, forceRefresh, RETRY_COUNT); + } + + private void recv(final NetworkCallback callback, final NetworkErrorCallback errorCallback, boolean forceRefresh, final int retries) { + if (mModules != null && mLogin.getLoginToken() != null && mLogin.getLoginToken().isSameUser(mModules.getUsername())) + delete(); + mQueue.add(() -> { + if (this.mModules != null && !forceRefresh) { + callback.onResponse(this.mModules); + mQueue.next(); return; } this.upgrade(success -> { - if (this.modules == null) - this.modules = success; + if (this.mModules == null) + this.mModules = success; else - this.modules.updateList(success); - callback.onResponse(this.modules); - queue.next(); + this.mModules.updateList(success); + callback.onResponse(this.mModules); + mQueue.next(); }, error -> { if (retries > 0 && (error.getHttpStatus() == 401 || error.getHttpStatus() == 403)) { - login.refreshLogin(success -> { + mLogin.refreshLogin(success -> { recv(callback, errorCallback, forceRefresh, retries-1); - queue.next(); + mQueue.next(); }, errorCallback); return; } errorCallback.onError(error); - queue.next(); + mQueue.next(); }); }); } private void upgrade(final NetworkCallback callback, final NetworkErrorCallback errorCallback) { - if (!login.isInOnlineMode()) { + if (!mLogin.isInOnlineMode()) { 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", login.getLoginToken().getCookies(), response -> { + get("https://kvv.imp.fu-berlin.de/direct/site.json", mLogin.getLoginToken().getCookies(), response -> { String body = response.getParsed(); if (body == null) { errorCallback.onError(new NetworkError(101101, 403, "No module list retrieved!")); return; } - Modules modules = new Modules(login.getLoginToken()); + Modules modules = new Modules(mLogin.getLoginToken().getUsername()); try { JSONObject json = new JSONObject(body); JSONArray sites = json.getJSONArray("site_collection"); @@ -153,7 +180,7 @@ public class KVVModulesList extends HTTPService { } // Empty module *may be* because token is invalid -> check if (modules.size() == 0) - login.testLoginToken(token -> callback.onResponse(modules), errorCallback); + mLogin.testLoginToken(token -> callback.onResponse(modules), errorCallback); else callback.onResponse(modules); }, error -> errorCallback.onError(new NetworkError(101104, error.networkResponse.statusCode, "Cannot get module list!"))); diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/LoginToken.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/LoginToken.java index 015c82d..99bac12 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/LoginToken.java +++ b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/LoginToken.java @@ -98,8 +98,8 @@ public class LoginToken implements Serializable { return cookies; } - public boolean isSameUser(LoginToken token) { - return token != null && this.getUsername().equals(token.getUsername()); + public boolean isSameUser(String username) { + return this.getUsername().equals(username); } @Override 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 6c4c21d..3b3dcc3 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 @@ -21,12 +21,12 @@ import androidx.annotation.Nullable; public class Modules implements Iterable, Serializable { private SortedListModule list; - private final LoginToken token; + private final String mUsername; //private transient Logger log = new Logger(this); private static final String FILE_NAME = "ModuleListSaveFile"; - public Modules(LoginToken loginToken) { - this.token = loginToken; + public Modules(String username) { + this.mUsername = username; this.list = new SortedListModule(); } @@ -84,8 +84,8 @@ public class Modules implements Iterable, Serializable { context.deleteFile(FILE_NAME); } - public LoginToken getToken() { - return token; + public String getUsername() { + return mUsername; } public void updateList(Modules modules) { diff --git a/app/src/main/java/de/sebse/fuplanner/tools/MainActivityListener.java b/app/src/main/java/de/sebse/fuplanner/tools/MainActivityListener.java index c972745..67ed120 100644 --- a/app/src/main/java/de/sebse/fuplanner/tools/MainActivityListener.java +++ b/app/src/main/java/de/sebse/fuplanner/tools/MainActivityListener.java @@ -17,6 +17,8 @@ public interface MainActivityListener { KVV getKVV(); + de.sebse.fuplanner.services.NewKVV.KVV getNewKVV(); + GoogleAuth getGoogleAuth(); void loginTokenInvalid(boolean doLoginCheck); From 57ce9ffa26b01775d873a25054619985f2adb449 Mon Sep 17 00:00:00 2001 From: Caesar2011 Date: Thu, 8 Nov 2018 00:22:31 +0100 Subject: [PATCH 03/17] Updated ModDetails: Overview, Assignments, Announcements (not runnable) --- .../java/de/sebse/fuplanner/MainActivity.java | 1 + .../moddetails/ModDetailAnnounceAdapter.java | 6 +- .../moddetails/ModDetailAnnounceFragment.java | 51 ++++++------ .../ModDetailAssignmentAdapter.java | 6 +- .../ModDetailAssignmentFragment.java | 49 +++++------ .../moddetails/ModDetailOverviewAdapter.java | 8 +- .../moddetails/ModDetailOverviewFragment.java | 42 ++++++---- .../fuplanner/services/NewKVV/KVVModules.java | 35 +++++--- .../NewKVV/KVVModulesAnnouncements.java | 11 +-- .../NewKVV/KVVModulesAssignments.java | 81 +++++++++++++++++++ .../services/NewKVV/KVVModulesDetails.java | 47 +++++++++++ .../services/NewKVV/KVVModulesList.java | 8 +- .../services/NewKVV/ModulesPart.java | 21 +---- .../sebse/fuplanner/services/NewKVV/Part.java | 31 +++++++ .../services/NewKVV/types/Assignment.java | 8 +- .../fuplanner/tools/MainActivityListener.java | 1 + 16 files changed, 285 insertions(+), 121 deletions(-) create mode 100644 app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesAssignments.java create mode 100644 app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesDetails.java create mode 100644 app/src/main/java/de/sebse/fuplanner/services/NewKVV/Part.java diff --git a/app/src/main/java/de/sebse/fuplanner/MainActivity.java b/app/src/main/java/de/sebse/fuplanner/MainActivity.java index b2cd54b..d1a1769 100644 --- a/app/src/main/java/de/sebse/fuplanner/MainActivity.java +++ b/app/src/main/java/de/sebse/fuplanner/MainActivity.java @@ -180,6 +180,7 @@ public class MainActivity extends AppCompatActivity break; case R.id.nav_logout: getNewKVV().account().logout(true); + getNewKVV().modules().list().delete(); this.getGoogleAuth().getLoginState(credentials -> { if (credentials != null) { this.getGoogleAuth().deleteLoginState(credentials.getUsername(), credentials.getPassword()); 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 index d35f26f..6e1c49b 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAnnounceAdapter.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAnnounceAdapter.java @@ -17,8 +17,8 @@ import androidx.core.content.ContextCompat; import androidx.recyclerview.widget.RecyclerView; import de.sebse.fuplanner.R; import de.sebse.fuplanner.services.KVV.Download; -import de.sebse.fuplanner.services.KVV.types.Announcement; -import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.services.NewKVV.types.Announcement; +import de.sebse.fuplanner.services.NewKVV.types.Modules; import de.sebse.fuplanner.tools.Regex; import de.sebse.fuplanner.tools.UtilsDate; import de.sebse.fuplanner.tools.logging.Logger; @@ -76,12 +76,10 @@ class ModDetailAnnounceAdapter extends RecyclerView.Adapter { tag.id = i; tag.layoutColor = ContextCompat.getColor(holder.mView.getContext(), R.color.colorFUBlue); holder.mTagGroup.addTag(tag); - log.d(notes.get(i)); } holder.mTagGroup.setOnTagClickListener((tag, i) -> { String s = notes.get(i); if (s != null) { - log.d("Download", s); String name = urlToName(s, i, holder.mView.getResources()); requestInterface.request(name, s); } 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 52f3713..4b4d34a 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 @@ -6,17 +6,16 @@ import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.ExpandableListView; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.RecyclerView; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import de.sebse.fuplanner.MainActivity; import de.sebse.fuplanner.R; import de.sebse.fuplanner.services.KVV.Download; -import de.sebse.fuplanner.services.KVV.KVV; -import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.services.NewKVV.types.Modules; import de.sebse.fuplanner.tools.MainActivityListener; import de.sebse.fuplanner.tools.logging.Logger; @@ -33,7 +32,7 @@ public class ModDetailAnnounceFragment extends Fragment implements Download.OnDo private ModDetailAnnounceAdapter adapter; private SwipeRefreshLayout swipeLayout; private Download download; - private MainActivityListener context; + @Nullable private MainActivityListener mListener; public ModDetailAnnounceFragment() { @@ -83,49 +82,45 @@ public class ModDetailAnnounceFragment extends Fragment implements Download.OnDo } private void refresh(boolean forceRefresh) { - if (getActivity() != null) { - KVV kvv = ((MainActivity) getActivity()).getKVV(); - kvv.getModule(mItemPos, (Modules.Module module) -> { - adapter.setModule(module); - kvv.getModuleAnnouncements(module, success1 -> { - adapter.setModule(); - swipeLayout.setRefreshing(false); - }, error -> { - swipeLayout.setRefreshing(false); - log.e(error); - }, forceRefresh); - }, error -> { - swipeLayout.setRefreshing(false); - log.e(error); - }, forceRefresh); - } + if (mListener == null) + return; + mListener.getNewKVV().modules().announcements().recv(mItemPos, success -> { + adapter.setModule(success); + swipeLayout.setRefreshing(false); + }, error -> { + swipeLayout.setRefreshing(false); + log.e(error); + }, forceRefresh); } @Override public void request(String title, String url) { - context.getKVV().getModule(mItemPos, (Modules.Module module) -> { - if (module == null) - return; + if (mListener == null) + return; + mListener.getNewKVV().modules().list().find(mItemPos, (Modules.Module module) -> { String folderName = "FU-"+module.title.replaceAll("[:*<>|/\"\\\\]", "-"); folderName += "/Assignment"; getDownload().openDownloadDialog(title, url, folderName); - }, log::e, false); + }, log::e); } @Override public void onAttach(Context context) { super.onAttach(context); if (context instanceof MainActivityListener) { - this.context = ((MainActivityListener) context); - this.context.addRequestPermissionsResultListener(getDownload().getRequestPermissionsResultListener(), "ModDetailAnnounceFragment"); + this.mListener = ((MainActivityListener) context); + this.mListener.addRequestPermissionsResultListener(getDownload().getRequestPermissionsResultListener(), "ModDetailAnnounceFragment"); } else - throw new RuntimeException(context.toString() + " must implement ModDetailAnnounceFragment"); + throw new RuntimeException(context.toString() + " must implement MainActivityListener"); } @Override public void onDetach() { super.onDetach(); - this.context.removeRequestPermissionsResultListener("ModDetailResourceFragment"); + if (this.mListener != null) { + this.mListener.removeRequestPermissionsResultListener("ModDetailAnnounceFragment"); + this.mListener = null; + } } Download getDownload() { 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 index e695666..fb33aa8 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentAdapter.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentAdapter.java @@ -17,8 +17,8 @@ import androidx.core.content.ContextCompat; import androidx.recyclerview.widget.RecyclerView; import de.sebse.fuplanner.R; import de.sebse.fuplanner.services.KVV.Download; -import de.sebse.fuplanner.services.KVV.types.Assignment; -import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.services.NewKVV.types.Assignment; +import de.sebse.fuplanner.services.NewKVV.types.Modules; import de.sebse.fuplanner.tools.Regex; import de.sebse.fuplanner.tools.UtilsDate; import de.sebse.fuplanner.tools.logging.Logger; @@ -76,12 +76,10 @@ class ModDetailAssignmentAdapter extends RecyclerView.Adapter tag.id = i; tag.layoutColor = ContextCompat.getColor(holder.mView.getContext(), R.color.colorFUBlue); holder.mTagGroup.addTag(tag); - log.d(notes.get(i)); } holder.mTagGroup.setOnTagClickListener((tag, i) -> { String s = notes.get(i); if (s != null) { - log.d("Download", s); String name = urlToName(s, i, holder.mView.getResources()); requestInterface.request(name, s); } 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 index a3225d9..5396532 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentFragment.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentFragment.java @@ -6,17 +6,16 @@ import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.ExpandableListView; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.RecyclerView; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import de.sebse.fuplanner.MainActivity; import de.sebse.fuplanner.R; import de.sebse.fuplanner.services.KVV.Download; -import de.sebse.fuplanner.services.KVV.KVV; -import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.services.NewKVV.types.Modules; import de.sebse.fuplanner.tools.MainActivityListener; import de.sebse.fuplanner.tools.logging.Logger; @@ -33,7 +32,7 @@ public class ModDetailAssignmentFragment extends Fragment implements Download.On private ModDetailAssignmentAdapter adapter; private SwipeRefreshLayout swipeLayout; private Download download; - private MainActivityListener context; + @Nullable private MainActivityListener mListener; public ModDetailAssignmentFragment() { @@ -83,41 +82,34 @@ public class ModDetailAssignmentFragment extends Fragment implements Download.On } private void refresh(boolean forceRefresh) { - if (getActivity() != null) { - KVV kvv = ((MainActivity) getActivity()).getKVV(); - kvv.getModule(mItemPos, (Modules.Module module) -> { - adapter.setModule(module); - kvv.getModuleAssignments(module, success1 -> { - adapter.setModule(); - swipeLayout.setRefreshing(false); - }, error -> { - swipeLayout.setRefreshing(false); - log.e(error); - }, forceRefresh); - }, error -> { - swipeLayout.setRefreshing(false); - log.e(error); - }, forceRefresh); - } + if (mListener == null) + return; + mListener.getNewKVV().modules().assignments().recv(mItemPos, success -> { + adapter.setModule(success); + swipeLayout.setRefreshing(false); + }, error -> { + swipeLayout.setRefreshing(false); + log.e(error); + }, forceRefresh); } @Override public void request(String title, String url) { - context.getKVV().getModule(mItemPos, (Modules.Module module) -> { - if (module == null) - return; + if (mListener == null) + return; + mListener.getNewKVV().modules().list().find(mItemPos, (Modules.Module module) -> { String folderName = "FU-"+module.title.replaceAll("[:*<>|/\"\\\\]", "-"); folderName += "/Assignment"; getDownload().openDownloadDialog(title, url, folderName); - }, log::e, false); + }, log::e); } @Override public void onAttach(Context context) { super.onAttach(context); if (context instanceof MainActivityListener) { - this.context = ((MainActivityListener) context); - this.context.addRequestPermissionsResultListener(getDownload().getRequestPermissionsResultListener(), "ModDetailAssignmentFragment"); + this.mListener = ((MainActivityListener) context); + this.mListener.addRequestPermissionsResultListener(getDownload().getRequestPermissionsResultListener(), "ModDetailAssignmentFragment"); } else throw new RuntimeException(context.toString() + " must implement MainActivityListener"); } @@ -125,7 +117,10 @@ public class ModDetailAssignmentFragment extends Fragment implements Download.On @Override public void onDetach() { super.onDetach(); - this.context.removeRequestPermissionsResultListener("ModDetailAssignmentFragment"); + if (this.mListener != null) { + this.mListener.removeRequestPermissionsResultListener("ModDetailAssignmentFragment"); + this.mListener = null; + } } Download getDownload() { 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 aca5eb7..1728f64 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 @@ -13,10 +13,10 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.recyclerview.widget.RecyclerView; 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.Event; -import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.services.NewKVV.types.Announcement; +import de.sebse.fuplanner.services.NewKVV.types.Assignment; +import de.sebse.fuplanner.services.NewKVV.types.Event; +import de.sebse.fuplanner.services.NewKVV.types.Modules; import de.sebse.fuplanner.tools.UtilsDate; import de.sebse.fuplanner.tools.logging.Logger; import de.sebse.fuplanner.tools.ui.CustomViewHolder; 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 ae8c7ec..df03414 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 @@ -17,6 +17,7 @@ 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.MainActivityListener; import de.sebse.fuplanner.tools.logging.Logger; /** @@ -31,7 +32,8 @@ public class ModDetailOverviewFragment extends Fragment { private final Logger log = new Logger(this); private ModDetailOverviewAdapter adapter; private SwipeRefreshLayout swipeLayout; - @Nullable private ModDetailListener mListener; + @Nullable private ModDetailListener mDetailListener; + @Nullable private MainActivityListener mListener; public ModDetailOverviewFragment() { @@ -70,7 +72,7 @@ public class ModDetailOverviewFragment extends Fragment { Context context = view.getContext(); RecyclerView recyclerView = view.findViewById(R.id.list); recyclerView.setLayoutManager(new LinearLayoutManager(context)); - adapter = new ModDetailOverviewAdapter(mListener); + adapter = new ModDetailOverviewAdapter(mDetailListener); recyclerView.setAdapter(adapter); // Getting SwipeContainerLayout @@ -82,19 +84,15 @@ public class ModDetailOverviewFragment extends Fragment { return view; } + + + private void refresh(boolean forceRefresh) { - if (getActivity() != null) { - KVV kvv = ((MainActivity) getActivity()).getKVV(); - kvv.getModule(mItemPos, (Modules.Module module) -> { - adapter.setModule(module); - kvv.getModuleDetails(module, pair -> { - adapter.setModule(); - if (pair.second) - swipeLayout.setRefreshing(false); - }, error -> { + if (mListener != null) { + mListener.getNewKVV().modules().details().recv(mItemPos, pair -> { + adapter.setModule(pair.first); + if (pair.second) swipeLayout.setRefreshing(false); - log.e(error); - }, forceRefresh); }, error -> { swipeLayout.setRefreshing(false); log.e(error); @@ -104,15 +102,27 @@ public class ModDetailOverviewFragment extends Fragment { @Override public void onAttach(Context context) { + super.onAttach(context); + if (context instanceof MainActivityListener) { + this.mListener = ((MainActivityListener) context); + } else + throw new RuntimeException(context.toString() + " must implement MainActivityListener"); + + super.onAttach(context); Fragment parentFragment = getParentFragment(); if (parentFragment != null) { if (parentFragment instanceof ModDetailListener) { - mListener = (ModDetailListener) parentFragment; + mDetailListener = (ModDetailListener) parentFragment; } else { - throw new RuntimeException(context.toString() - + " must implement ModDetailListener"); + throw new RuntimeException(context.toString() + " must implement ModDetailListener"); } } else log.w("No parent fragment!"); } + + @Override + public void onDetach() { + super.onDetach(); + this.mListener = null; + } } diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModules.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModules.java index 546a057..ecc6aad 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModules.java +++ b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModules.java @@ -7,37 +7,54 @@ import org.jetbrains.annotations.NotNull; import java.util.HashMap; public class KVVModules { - private final HashMap addons = new HashMap<>(); - private final KVVLogin login; + private final HashMap mAddons = new HashMap<>(); + private KVVModulesList mList = null; + private final KVVLogin mLogin; private final Context context; public KVVModules(KVVLogin login, Context context) { - this.login = login; + this.mLogin = login; this.context = context; } + @NotNull + public KVVModulesDetails details() { + return (KVVModulesDetails) addAndGet("details", () -> { + ModulesPart[] parts = {announcements(), assignments()}; + return new KVVModulesDetails(mLogin, list(), context, parts); + }); + } + @NotNull public KVVModulesAnnouncements announcements() { - return (KVVModulesAnnouncements) addAndGet("announcements", () -> new KVVModulesAnnouncements(login, list(), context)); + return (KVVModulesAnnouncements) addAndGet("announcements", () -> new KVVModulesAnnouncements(mLogin, list(), context)); + } + + @NotNull + public KVVModulesAssignments assignments() { + return (KVVModulesAssignments) addAndGet("assignments", () -> new KVVModulesAssignments(mLogin, list(), context)); } @NotNull public KVVModulesList list() { - return (KVVModulesList) addAndGet("list", () -> new KVVModulesList(login, context)); + if (mList == null) { + mList = new KVVModulesList(mLogin, context); + } + return mList; } @NotNull - private Object addAndGet(@NotNull String addon, @NotNull ModuleCreatorInterface creatorInterface) { - Object o = addons.get(addon); + private Part addAndGet(@NotNull String addon, @NotNull ModuleCreatorInterface creatorInterface) { + Part o = mAddons.get(addon); if (o == null) { o = creatorInterface.create(); - addons.put(addon, o); + mAddons.put(addon, o); } return o; } private interface ModuleCreatorInterface { - @NotNull Object create(); + @NotNull Part create(); } } diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesAnnouncements.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesAnnouncements.java index 90e60c2..ed0fa02 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesAnnouncements.java +++ b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesAnnouncements.java @@ -1,9 +1,6 @@ package de.sebse.fuplanner.services.NewKVV; import android.content.Context; -import android.os.Build; -import android.text.Html; -import android.text.Spanned; import org.json.JSONArray; import org.json.JSONException; @@ -17,7 +14,7 @@ import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkError; import de.sebse.fuplanner.tools.network.NetworkErrorCallback; -class KVVModulesAnnouncements extends ModulesPart> { +public class KVVModulesAnnouncements extends ModulesPart> { KVVModulesAnnouncements(KVVLogin login, KVVModulesList list, Context context) { super(login, list, context); @@ -30,16 +27,14 @@ class KVVModulesAnnouncements extends ModulesPart> { @Override protected boolean setPart(Modules.Module module, ArrayList part) { - boolean changed = false; - if (module.announcements != null && module.announcements.hashCode() != part.hashCode()) - changed = true; + boolean changed = module.announcements == null || module.announcements.hashCode() != part.hashCode(); module.announcements = part; return changed; } @Override protected void upgrade(final String ID, final NetworkCallback> callback, final NetworkErrorCallback errorCallback) { - if (!login.isInOnlineMode()) { + if (!login.isInOnlineMode() || login.getLoginToken() == null) { errorCallback.onError(new NetworkError(101204, 500, "Currently running in offline mode!")); return; } 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 new file mode 100644 index 0000000..d8eaa2a --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesAssignments.java @@ -0,0 +1,81 @@ +package de.sebse.fuplanner.services.NewKVV; + +import android.content.Context; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; + +import de.sebse.fuplanner.services.NewKVV.types.Assignment; +import de.sebse.fuplanner.services.NewKVV.types.AssignmentList; +import de.sebse.fuplanner.services.NewKVV.types.Modules; +import de.sebse.fuplanner.tools.network.NetworkCallback; +import de.sebse.fuplanner.tools.network.NetworkError; +import de.sebse.fuplanner.tools.network.NetworkErrorCallback; + +public class KVVModulesAssignments extends ModulesPart { + + KVVModulesAssignments(KVVLogin login, KVVModulesList list, Context context) { + super(login, list, context); + } + + @Override + protected AssignmentList getPart(Modules.Module module) { + return module.assignments; + } + + @Override + protected boolean setPart(Modules.Module module, AssignmentList part) { + boolean changed = module.assignments == null || module.assignments.hashCode() != part.hashCode(); + module.assignments = part; + return changed; + } + + @Override + protected void upgrade(final String ID, final NetworkCallback callback, final NetworkErrorCallback errorCallback) { + if (!login.isInOnlineMode() || login.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 ->{ + String body = response.getParsed(); + if (body == null) { + errorCallback.onError(new NetworkError(101301, 403, "No assignments retrieved!")); + return; + } + AssignmentList assignments = new AssignmentList(); + try { + JSONObject json = new JSONObject(body); + JSONArray sites = json.getJSONArray("assignment_collection"); + + for (int i = 0; i < sites.length(); i++) { + JSONObject site = sites.getJSONObject(i); + String id = site.getString("id"); + String title = site.getString("title"); + String instructions = site.getString("instructions"); + instructions = String.valueOf(fromHtml(instructions)); + long dueTime = site.getJSONObject("dueTime").getLong("time"); + String gradebookItemName = site.optString("gradebookItemName", null); + 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); + 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/KVVModulesDetails.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesDetails.java new file mode 100644 index 0000000..ac3e270 --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesDetails.java @@ -0,0 +1,47 @@ +package de.sebse.fuplanner.services.NewKVV; + +import android.content.Context; +import android.util.Pair; + +import java.util.concurrent.atomic.AtomicReference; + +import de.sebse.fuplanner.services.NewKVV.types.Modules; +import de.sebse.fuplanner.tools.network.NetworkCallback; +import de.sebse.fuplanner.tools.network.NetworkError; +import de.sebse.fuplanner.tools.network.NetworkErrorCallback; + +final public class KVVModulesDetails extends Part> { + private final ModulesPart[] parts; + + KVVModulesDetails(KVVLogin login, KVVModulesList list, Context context, ModulesPart[] parts) { + super(login, list, context); + this.parts = parts; + } + + @Override + protected void recv(final Modules.Module module, final NetworkCallback> callback, final NetworkErrorCallback errorCallback, final boolean forceRefresh, final int retries) { + final int[] returned = {0}; + AtomicReference lastError = new AtomicReference<>(null); + NetworkCallback successCb = success -> { + returned[0] += 1; + callback.onResponse(Pair.create(module, false)); + if (returned[0] == parts.length) { + callback.onResponse(Pair.create(module, true)); + if (lastError.get() != null) + errorCallback.onError(lastError.get()); + } + }; + NetworkErrorCallback errorCb = error -> { + lastError.set(error); + returned[0] += 1; + if (returned[0] == parts.length) { + callback.onResponse(Pair.create(module, true)); + if (lastError.get() != null) + errorCallback.onError(lastError.get()); + } + }; + for (ModulesPart part: parts) { + part.recv(module, successCb, errorCb, forceRefresh, RETRY_COUNT); + } + } +} 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 d48f33b..31f2946 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 @@ -51,7 +51,7 @@ public class KVVModulesList extends HTTPService { } private void find(String moduleID, NetworkCallback moduleNetworkCallback, NetworkErrorCallback errorCallback, int retries) { - if (mModules != null && mLogin.getLoginToken() != null && mLogin.getLoginToken().isSameUser(mModules.getUsername())) + if (mModules != null && mLogin.getLoginToken() != null && !mLogin.getLoginToken().isSameUser(mModules.getUsername())) delete(); if (retries < 0) { errorCallback.onError(new NetworkError(101107, -1, "Too many retries!")); @@ -68,6 +68,7 @@ public class KVVModulesList extends HTTPService { } void store() { + log.d("Save data"); if (this.mModules != null) { try { this.mModules.save(getContext()); @@ -88,7 +89,7 @@ public class KVVModulesList extends HTTPService { } } - private void delete() { + public void delete() { if (this.mModules != null) { this.mModules.delete(getContext()); this.mModules = null; @@ -104,7 +105,7 @@ public class KVVModulesList extends HTTPService { } private void recv(final NetworkCallback callback, final NetworkErrorCallback errorCallback, boolean forceRefresh, final int retries) { - if (mModules != null && mLogin.getLoginToken() != null && mLogin.getLoginToken().isSameUser(mModules.getUsername())) + if (mModules != null && mLogin.getLoginToken() != null && !mLogin.getLoginToken().isSameUser(mModules.getUsername())) delete(); mQueue.add(() -> { if (this.mModules != null && !forceRefresh) { @@ -117,6 +118,7 @@ public class KVVModulesList extends HTTPService { this.mModules = success; else this.mModules.updateList(success); + store(); callback.onResponse(this.mModules); mQueue.next(); }, error -> { 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 17239ab..48d9833 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 @@ -7,31 +7,18 @@ import android.text.Spanned; 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 ModulesPart extends HTTPService { - static final int RETRY_COUNT = 1; - protected final KVVLogin login; - protected final KVVModulesList list; +abstract class ModulesPart extends Part { private NewAsyncQueue queue = new NewAsyncQueue(); ModulesPart(KVVLogin login, KVVModulesList list, Context context) { - super(context); - this.login = login; - this.list = list; + super(login, list, context); } - public void recv(final String moduleID, final NetworkCallback callback, final NetworkErrorCallback errorCallback) { - recv(moduleID, callback, errorCallback, false); - } - - 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); - } - - private void recv(final Modules.Module module, final NetworkCallback callback, final NetworkErrorCallback errorCallback, final boolean forceRefresh, final int retries) { + @Override + protected void recv(final Modules.Module module, final NetworkCallback callback, final NetworkErrorCallback errorCallback, final boolean forceRefresh, final int retries) { queue.add(() -> { if (getPart(module) != null && !forceRefresh) { callback.onResponse(module); 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 new file mode 100644 index 0000000..12c13b6 --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/Part.java @@ -0,0 +1,31 @@ +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; + + Part(KVVLogin login, KVVModulesList list, Context context) { + super(context); + this.login = login; + this.list = list; + } + + public void recv(final String moduleID, final NetworkCallback callback, final NetworkErrorCallback errorCallback) { + recv(moduleID, callback, errorCallback, false); + } + + 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); + } + + 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/Assignment.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Assignment.java index 4f366af..cd6a824 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Assignment.java +++ b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Assignment.java @@ -1,5 +1,7 @@ package de.sebse.fuplanner.services.NewKVV.types; +import com.google.android.gms.common.internal.Objects; + import java.io.Serializable; import java.util.ArrayList; @@ -15,7 +17,6 @@ public class Assignment implements Serializable { this.title = title; this.dueTime = dueTime; this.urls = urls; - //this.grade = grade; this.instructions = instructions; } @@ -50,4 +51,9 @@ public class Assignment implements Serializable { "\nDue date: "+getDueDate()+ "\nInstructions: "+getInstructions().substring(0, Math.min(getInstructions().length(), 100)); } + + @Override + public int hashCode() { + return Objects.hashCode(getId(), getDueDate(), getInstructions(), getTitle(), getUrls()); + } } diff --git a/app/src/main/java/de/sebse/fuplanner/tools/MainActivityListener.java b/app/src/main/java/de/sebse/fuplanner/tools/MainActivityListener.java index 67ed120..ce8977c 100644 --- a/app/src/main/java/de/sebse/fuplanner/tools/MainActivityListener.java +++ b/app/src/main/java/de/sebse/fuplanner/tools/MainActivityListener.java @@ -15,6 +15,7 @@ public interface MainActivityListener { void showToast(@StringRes int msgStringRes); + @Deprecated KVV getKVV(); de.sebse.fuplanner.services.NewKVV.KVV getNewKVV(); From 518ae756b1f93d349bf4a919749fca7674006996 Mon Sep 17 00:00:00 2001 From: Caesar2011 Date: Thu, 8 Nov 2018 20:39:07 +0100 Subject: [PATCH 04/17] Re-added new download opener --- app/src/main/AndroidManifest.xml | 9 +++++++++ .../sebse/fuplanner/services/KVV/Download.java | 16 ++++++++++++---- app/src/main/res/xml/provider_paths.xml | 4 ++++ 3 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 app/src/main/res/xml/provider_paths.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 9948868..2115831 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -24,6 +24,15 @@ + + + \ No newline at end of file diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/Download.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/Download.java index 8fcfb83..dab0fd3 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/Download.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/Download.java @@ -15,6 +15,7 @@ import java.util.Arrays; import androidx.annotation.Nullable; import androidx.core.app.ActivityCompat; +import androidx.core.content.FileProvider; import de.sebse.fuplanner.MainActivity; import de.sebse.fuplanner.R; import de.sebse.fuplanner.services.KVV.types.Resource; @@ -55,7 +56,7 @@ public class Download { if (file.getModifiedDate() != 0) { if (!message.isEmpty()) message += "\n"; - resources.getString(R.string.last_modified_on, UtilsDate.getModifiedDateTime(contextInterface.get(), file.getModifiedDate())); + message += resources.getString(R.string.last_modified_on, UtilsDate.getModifiedDateTime(contextInterface.get(), file.getModifiedDate())); } alertDialogBuilder @@ -181,9 +182,17 @@ public class Download { } private void fileOpen(File url){ - Uri uri = Uri.fromFile(url); - Intent intent = new Intent();//Intent.ACTION_VIEW + Uri uri = FileProvider.getUriForFile(contextInterface.get(), contextInterface.get().getApplicationContext().getPackageName() + ".my.provider", url); + + Intent intent; + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) { + intent = new Intent(Intent.ACTION_VIEW); + } else { + intent = new Intent(); + } + intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); // Check what kind of file you are trying to open, by comparing the url with extensions. // When the if condition is matched, plugin sets the correct intent (mime) type, // so Android knew what application to use to open the file @@ -228,7 +237,6 @@ public class Download { //so you can choose which application to use intent.setDataAndType(uri, "*/*"); } - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); contextInterface.get().startActivity(intent); diff --git a/app/src/main/res/xml/provider_paths.xml b/app/src/main/res/xml/provider_paths.xml new file mode 100644 index 0000000..4495c28 --- /dev/null +++ b/app/src/main/res/xml/provider_paths.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file From 0439c845a5362c09aea5588a031e923f0183c10b Mon Sep 17 00:00:00 2001 From: Caesar2011 Date: Fri, 9 Nov 2018 01:17:59 +0100 Subject: [PATCH 05/17] Bug fixing, JSON parsing more robust --- app/build.gradle | 7 +-- .../moddetails/ModDetailOverviewAdapter.java | 1 + .../NewKVV/KVVModulesAnnouncements.java | 31 ++++++---- .../NewKVV/KVVModulesAssignments.java | 28 +++++---- .../services/NewKVV/KVVModulesList.java | 59 ++++++++++--------- .../services/NewKVV/ModulesPart.java | 16 ++--- .../sebse/fuplanner/services/NewKVV/Part.java | 11 ++-- .../services/NewKVV/types/Modules.java | 32 +++++----- .../NewKVV/types/SortedListModule.java | 2 +- 9 files changed, 103 insertions(+), 84 deletions(-) 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); } } From af9d2fed0e5980ae75de2cb1d2b4c15713970209 Mon Sep 17 00:00:00 2001 From: Caesar2011 Date: Fri, 9 Nov 2018 20:11:40 +0100 Subject: [PATCH 06/17] Bug fixing, Implemented Rescource, Event and Gradebook --- .../fuplanner/fragments/ScheduleFragment.java | 71 +++-- .../moddetails/ModDetailAnnounceAdapter.java | 2 +- .../moddetails/ModDetailAnnounceFragment.java | 2 +- .../ModDetailAssignmentAdapter.java | 2 +- .../ModDetailAssignmentFragment.java | 3 +- .../moddetails/ModDetailEventAdapter.java | 8 +- .../ModDetailEventAdapterInner.java | 9 +- .../moddetails/ModDetailEventFragment.java | 47 ++-- .../moddetails/ModDetailFragment.java | 4 +- .../moddetails/ModDetailGradebookAdapter.java | 14 +- .../ModDetailGradebookFragment.java | 47 ++-- .../moddetails/ModDetailOverviewFragment.java | 3 - .../moddetails/ModDetailResourceAdapter.java | 4 +- .../moddetails/ModDetailResourceFragment.java | 52 ++-- .../fuplanner/services/NewKVV/Download.java | 265 ++++++++++++++++++ .../fuplanner/services/NewKVV/KVVLogin.java | 3 - .../fuplanner/services/NewKVV/KVVModules.java | 19 +- .../NewKVV/KVVModulesAnnouncements.java | 1 + .../NewKVV/KVVModulesAssignments.java | 3 +- .../services/NewKVV/KVVModulesEvents.java | 83 ++++++ .../services/NewKVV/KVVModulesGradebook.java | 76 +++++ .../services/NewKVV/KVVModulesList.java | 2 + .../services/NewKVV/KVVModulesResources.java | 220 +++++++++++++++ .../sebse/fuplanner/services/NewKVV/Part.java | 6 +- .../types/{Gradebook.java => Grade.java} | 11 +- .../services/NewKVV/types/Modules.java | 4 +- .../ui/treeview/DirectoryNodeBinder.java | 2 +- .../tools/ui/treeview/FileNodeBinder.java | 2 +- 28 files changed, 818 insertions(+), 147 deletions(-) create mode 100644 app/src/main/java/de/sebse/fuplanner/services/NewKVV/Download.java create mode 100644 app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesEvents.java create mode 100644 app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesGradebook.java create mode 100644 app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesResources.java rename app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/{Gradebook.java => Grade.java} (69%) diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/ScheduleFragment.java b/app/src/main/java/de/sebse/fuplanner/fragments/ScheduleFragment.java index eaafe4a..c6439ca 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/ScheduleFragment.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/ScheduleFragment.java @@ -16,9 +16,9 @@ import java.util.List; import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.KVV.KVV; -import de.sebse.fuplanner.services.KVV.types.Event; -import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.services.NewKVV.KVV; +import de.sebse.fuplanner.services.NewKVV.types.Event; +import de.sebse.fuplanner.services.NewKVV.types.Modules; import de.sebse.fuplanner.tools.UtilsDate; import de.sebse.fuplanner.tools.MainActivityListener; import de.sebse.fuplanner.tools.logging.Logger; @@ -59,24 +59,22 @@ public class ScheduleFragment extends Fragment implements MonthLoader.MonthChang } public void invalidate(boolean forceRefresh) { - if (mListener != null) { - KVV kvv = mListener.getKVV(); - kvv.getModuleList((Modules success) -> { - mModules = success; - final int[] i = {0}; - for (Modules.Module module: mModules) { - kvv.getModuleEvents(module, success1 -> { - i[0]++; - if (i[0] >= mModules.size()) { - if (mWeekView != null) { - mWeekView.invalidate(); - mWeekView.notifyDatasetChanged(); - } + if (mListener == null) return; + mListener.getNewKVV().modules().list().recv(modules -> { + mModules = modules; + final int[] i = {0}; + for (Modules.Module module: mModules) { + mListener.getNewKVV().modules().events().recv(module, success1 -> { + i[0]++; + if (i[0] >= mModules.size()) { + if (mWeekView != null) { + mWeekView.invalidate(); + mWeekView.notifyDatasetChanged(); } - }, log::e, forceRefresh); - } - }, log::e, forceRefresh); - } + } + }, log::e, forceRefresh); + } + }, log::e, forceRefresh); } @Override @@ -183,24 +181,21 @@ public class ScheduleFragment extends Fragment implements MonthLoader.MonthChang String moduleId = idParts[0]; AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getContext()); - if (mListener != null) { - KVV kvv = mListener.getKVV(); - kvv.getModuleList((Modules success) -> { - Modules.Module module = success.get(moduleId); - String moduleName = module.title; - alertDialogBuilder - .setTitle(event.getName()) - .setMessage( - getResources().getString(R.string.module_name, moduleName) + "\n" + - getResources().getString(R.string.location_name, event.getLocation()) + "\n" + - getResources().getString(R.string.date_scale, UtilsDate.getModifiedTime(getContext(), event.getStartTime().getTimeInMillis()), UtilsDate.getModifiedTime(getContext(), event.getEndTime().getTimeInMillis()+1)) - ) - .setCancelable(true) - .setNeutralButton(R.string.close, (dialog, id) -> dialog.cancel()); + if (mListener == null) return; + mListener.getNewKVV().modules().list().find(moduleId, module -> { + String moduleName = module.title; + alertDialogBuilder + .setTitle(event.getName()) + .setMessage( + getResources().getString(R.string.module_name, moduleName) + "\n" + + getResources().getString(R.string.location_name, event.getLocation()) + "\n" + + getResources().getString(R.string.date_scale, UtilsDate.getModifiedTime(getContext(), event.getStartTime().getTimeInMillis()), UtilsDate.getModifiedTime(getContext(), event.getEndTime().getTimeInMillis()+1)) + ) + .setCancelable(true) + .setNeutralButton(R.string.close, (dialog, id) -> dialog.cancel()); - AlertDialog alertDialog = alertDialogBuilder.create(); - alertDialog.show(); - }, log::e); - } + AlertDialog alertDialog = alertDialogBuilder.create(); + alertDialog.show(); + }, log::e); } } 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 index 6e1c49b..2c09880 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAnnounceAdapter.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAnnounceAdapter.java @@ -16,7 +16,7 @@ import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; import androidx.recyclerview.widget.RecyclerView; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.KVV.Download; +import de.sebse.fuplanner.services.NewKVV.Download; import de.sebse.fuplanner.services.NewKVV.types.Announcement; import de.sebse.fuplanner.services.NewKVV.types.Modules; import de.sebse.fuplanner.tools.Regex; 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 4b4d34a..3c7dc6b 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 @@ -14,7 +14,7 @@ import androidx.recyclerview.widget.RecyclerView; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import de.sebse.fuplanner.MainActivity; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.KVV.Download; +import de.sebse.fuplanner.services.NewKVV.Download; import de.sebse.fuplanner.services.NewKVV.types.Modules; import de.sebse.fuplanner.tools.MainActivityListener; import de.sebse.fuplanner.tools.logging.Logger; 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 index fb33aa8..32f6379 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentAdapter.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentAdapter.java @@ -16,7 +16,7 @@ import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; import androidx.recyclerview.widget.RecyclerView; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.KVV.Download; +import de.sebse.fuplanner.services.NewKVV.Download; import de.sebse.fuplanner.services.NewKVV.types.Assignment; import de.sebse.fuplanner.services.NewKVV.types.Modules; import de.sebse.fuplanner.tools.Regex; 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 index 5396532..8a9dbb3 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentFragment.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentFragment.java @@ -14,7 +14,7 @@ import androidx.recyclerview.widget.RecyclerView; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import de.sebse.fuplanner.MainActivity; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.KVV.Download; +import de.sebse.fuplanner.services.NewKVV.Download; import de.sebse.fuplanner.services.NewKVV.types.Modules; import de.sebse.fuplanner.tools.MainActivityListener; import de.sebse.fuplanner.tools.logging.Logger; @@ -95,6 +95,7 @@ public class ModDetailAssignmentFragment extends Fragment implements Download.On @Override public void request(String title, String url) { + log.d(title, url, mListener); if (mListener == null) return; mListener.getNewKVV().modules().list().find(mItemPos, (Modules.Module module) -> { diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailEventAdapter.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailEventAdapter.java index a3ef881..c3b80d3 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailEventAdapter.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailEventAdapter.java @@ -14,10 +14,10 @@ import androidx.annotation.NonNull; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.KVV.types.Event; -import de.sebse.fuplanner.services.KVV.types.EventList; -import de.sebse.fuplanner.services.KVV.types.GroupedEvents; -import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.services.NewKVV.types.Event; +import de.sebse.fuplanner.services.NewKVV.types.EventList; +import de.sebse.fuplanner.services.NewKVV.types.GroupedEvents; +import de.sebse.fuplanner.services.NewKVV.types.Modules; import de.sebse.fuplanner.tools.Triplet; import de.sebse.fuplanner.tools.UtilsDate; import de.sebse.fuplanner.tools.logging.Logger; diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailEventAdapterInner.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailEventAdapterInner.java index b4e5551..9ab60d7 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailEventAdapterInner.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailEventAdapterInner.java @@ -10,14 +10,11 @@ import java.util.ArrayList; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.KVV.types.Event; -import de.sebse.fuplanner.services.KVV.types.EventList; -import de.sebse.fuplanner.services.KVV.types.GroupedEvents; -import de.sebse.fuplanner.tools.Triplet; +import de.sebse.fuplanner.services.NewKVV.types.Event; +import de.sebse.fuplanner.services.NewKVV.types.EventList; +import de.sebse.fuplanner.services.NewKVV.types.GroupedEvents; import de.sebse.fuplanner.tools.UtilsDate; -import de.sebse.fuplanner.tools.ui.CustomViewHolder; import de.sebse.fuplanner.tools.ui.ItemViewHolder; -import de.sebse.fuplanner.tools.ui.ListViewHolder; class ModDetailEventAdapterInner extends RecyclerView.Adapter { private final ArrayList mPositionalData; diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailEventFragment.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailEventFragment.java index 04fb784..759a27c 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailEventFragment.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailEventFragment.java @@ -8,14 +8,13 @@ import android.view.View; import android.view.ViewGroup; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; -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.MainActivityListener; import de.sebse.fuplanner.tools.logging.Logger; /** @@ -30,6 +29,7 @@ public class ModDetailEventFragment extends Fragment { private final Logger log = new Logger(this); private ModDetailEventAdapter adapter; private SwipeRefreshLayout swipeLayout; + @Nullable private MainActivityListener mListener; public ModDetailEventFragment() { @@ -81,22 +81,31 @@ public class ModDetailEventFragment extends Fragment { } private void refresh(boolean forceRefresh) { - if (getActivity() != null) { - KVV kvv = ((MainActivity) getActivity()).getKVV(); - kvv.getModule(mItemPos, (Modules.Module module) -> { - adapter.setModule(module); - kvv.getModuleEvents(module, success1 -> { - adapter.setModule(); - swipeLayout.setRefreshing(false); - }, error -> { - swipeLayout.setRefreshing(false); - log.e(error); - }, forceRefresh); - }, error -> { - swipeLayout.setRefreshing(false); - log.e(error); - }, forceRefresh); - } + if (mListener == null) + return; + mListener.getNewKVV().modules().events().recv(mItemPos, success -> { + adapter.setModule(success); + swipeLayout.setRefreshing(false); + }, error -> { + swipeLayout.setRefreshing(false); + log.e(error); + }, forceRefresh); } + @Override + public void onAttach(Context context) { + super.onAttach(context); + if (context instanceof MainActivityListener) { + this.mListener = ((MainActivityListener) context); + } else + throw new RuntimeException(context.toString() + " must implement MainActivityListener"); + } + + @Override + public void onDetach() { + super.onDetach(); + if (this.mListener != null) { + this.mListener = null; + } + } } diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailFragment.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailFragment.java index d1c2591..1502fac 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailFragment.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailFragment.java @@ -10,7 +10,7 @@ import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; import androidx.viewpager.widget.ViewPager; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.services.NewKVV.types.Modules; import de.sebse.fuplanner.tools.MainActivityListener; import de.sebse.fuplanner.tools.logging.Logger; @@ -72,7 +72,7 @@ public class ModDetailFragment extends Fragment implements ModDetailListener { } if (mListener != null) { mListener.onTitleTextChange(R.string.courses); - mListener.getKVV().getModuleList(success -> { + mListener.getNewKVV().modules().list().recv(success -> { Modules.Module module = success.get(mItemPos); if (mListener != null && module != null) mListener.onTitleTextChange(module.title); diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailGradebookAdapter.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailGradebookAdapter.java index 62a779d..3201f0d 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailGradebookAdapter.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailGradebookAdapter.java @@ -12,8 +12,8 @@ import java.util.ArrayList; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.KVV.types.Gradebook; -import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.services.NewKVV.types.Grade; +import de.sebse.fuplanner.services.NewKVV.types.Modules; import de.sebse.fuplanner.tools.ui.StringViewHolder; class ModDetailGradebookAdapter extends RecyclerView.Adapter { @@ -62,7 +62,7 @@ class ModDetailGradebookAdapter extends RecyclerView.Adapter { - adapter.setModule(module); - kvv.getModuleGradebook(module, success1 -> { - adapter.setModule(); - swipeLayout.setRefreshing(false); - }, error -> { - swipeLayout.setRefreshing(false); - log.e(error); - }, forceRefresh); - }, error -> { - swipeLayout.setRefreshing(false); - log.e(error); - }, forceRefresh); - } + if (mListener == null) + return; + mListener.getNewKVV().modules().gradebook().recv(mItemPos, success -> { + adapter.setModule(success); + swipeLayout.setRefreshing(false); + }, error -> { + swipeLayout.setRefreshing(false); + log.e(error); + }, forceRefresh); } + @Override + public void onAttach(Context context) { + super.onAttach(context); + if (context instanceof MainActivityListener) { + this.mListener = ((MainActivityListener) context); + } else + throw new RuntimeException(context.toString() + " must implement MainActivityListener"); + } + + @Override + public void onDetach() { + super.onDetach(); + if (this.mListener != null) { + this.mListener = null; + } + } } 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 df03414..9bce5b8 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 @@ -13,10 +13,7 @@ import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; -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.MainActivityListener; import de.sebse.fuplanner.tools.logging.Logger; diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailResourceAdapter.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailResourceAdapter.java index 8b5e570..c63e94d 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailResourceAdapter.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailResourceAdapter.java @@ -3,8 +3,8 @@ package de.sebse.fuplanner.fragments.moddetails; import java.util.ArrayList; import java.util.List; -import de.sebse.fuplanner.services.KVV.types.Modules; -import de.sebse.fuplanner.services.KVV.types.Resource; +import de.sebse.fuplanner.services.NewKVV.types.Modules; +import de.sebse.fuplanner.services.NewKVV.types.Resource; import de.sebse.fuplanner.tools.ui.treeview.TreeNode; import de.sebse.fuplanner.tools.ui.treeview.TreeViewAdapter; import de.sebse.fuplanner.tools.ui.treeview.TreeViewBinder; diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailResourceFragment.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailResourceFragment.java index 665ba28..b245d79 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailResourceFragment.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailResourceFragment.java @@ -11,16 +11,16 @@ import android.widget.ImageView; import java.util.Arrays; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import de.sebse.fuplanner.MainActivity; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.KVV.Download; -import de.sebse.fuplanner.services.KVV.KVV; -import de.sebse.fuplanner.services.KVV.types.Modules; -import de.sebse.fuplanner.services.KVV.types.Resource; +import de.sebse.fuplanner.services.NewKVV.Download; +import de.sebse.fuplanner.services.NewKVV.types.Modules; +import de.sebse.fuplanner.services.NewKVV.types.Resource; import de.sebse.fuplanner.tools.MainActivityListener; import de.sebse.fuplanner.tools.logging.Logger; import de.sebse.fuplanner.tools.ui.treeview.DirectoryNodeBinder; @@ -40,8 +40,8 @@ public class ModDetailResourceFragment extends Fragment { private final Logger log = new Logger(this); private ModDetailResourceAdapter adapter; private SwipeRefreshLayout swipeLayout; - private MainActivityListener context; private Download download; + @Nullable private MainActivityListener mListener; public ModDetailResourceFragment() { @@ -88,10 +88,8 @@ public class ModDetailResourceFragment extends Fragment { if (!node.isLeaf()) { // Update and toggle the node. onToggle(!node.isExpand(), holder); - } else if(node.getContent() instanceof Resource.File) { // if leaf is file - KVV kvv = ModDetailResourceFragment.this.context.getKVV(); - kvv.getModule(mItemPos, (Modules.Module module) -> { - + } else if (node.getContent() instanceof Resource.File && ModDetailResourceFragment.this.mListener != null) { // if leaf is file + ModDetailResourceFragment.this.mListener.getNewKVV().modules().resources().recv(mItemPos, (Modules.Module module) -> { String folderName = "FU-"+module.title.replaceAll("[:*<>|/\"\\\\]", "-"); Resource.File file = (Resource.File) node.getContent(); getDownload().openDownloadDialog(file, folderName); @@ -120,14 +118,12 @@ public class ModDetailResourceFragment extends Fragment { return view; } - - @Override public void onAttach(Context context) { super.onAttach(context); if (context instanceof MainActivityListener) { - this.context = ((MainActivityListener) context); - this.context.addRequestPermissionsResultListener(getDownload().getRequestPermissionsResultListener(), "ModDetailResourceFragment"); + this.mListener = ((MainActivityListener) context); + this.mListener.addRequestPermissionsResultListener(getDownload().getRequestPermissionsResultListener(), "ModDetailResourceFragment"); } else throw new RuntimeException(context.toString() + " must implement MainActivityListener"); } @@ -135,26 +131,22 @@ public class ModDetailResourceFragment extends Fragment { @Override public void onDetach() { super.onDetach(); - this.context.removeRequestPermissionsResultListener("ModDetailResourceFragment"); + if (this.mListener != null) { + this.mListener.removeRequestPermissionsResultListener("ModDetailResourceFragment"); + this.mListener = null; + } } private void refresh(boolean forceRefresh) { - if (getActivity() != null) { - KVV kvv = ((MainActivity) getActivity()).getKVV(); - kvv.getModule(mItemPos, (Modules.Module module) -> { - adapter.setModule(module); - kvv.getModuleResources(module, success1 -> { - adapter.setModule(); - swipeLayout.setRefreshing(false); - }, error -> { - swipeLayout.setRefreshing(false); - log.e(error); - }, forceRefresh); - }, error -> { - swipeLayout.setRefreshing(false); - log.e(error); - }, forceRefresh); - } + if (mListener == null) + return; + mListener.getNewKVV().modules().assignments().recv(mItemPos, success -> { + adapter.setModule(success); + swipeLayout.setRefreshing(false); + }, error -> { + swipeLayout.setRefreshing(false); + log.e(error); + }, forceRefresh); } Download getDownload() { diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/Download.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/Download.java new file mode 100644 index 0000000..9ba73e2 --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/Download.java @@ -0,0 +1,265 @@ +package de.sebse.fuplanner.services.NewKVV; + +import android.Manifest; +import android.app.AlertDialog; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.res.Resources; +import android.net.Uri; +import android.os.Environment; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; + +import androidx.annotation.Nullable; +import androidx.core.app.ActivityCompat; +import androidx.core.content.FileProvider; +import de.sebse.fuplanner.MainActivity; +import de.sebse.fuplanner.R; +import de.sebse.fuplanner.services.NewKVV.KVV; +import de.sebse.fuplanner.services.NewKVV.types.Resource; +import de.sebse.fuplanner.tools.Regex; +import de.sebse.fuplanner.tools.RequestPermissionsResultListener; +import de.sebse.fuplanner.tools.UtilsDate; +import de.sebse.fuplanner.tools.logging.Logger; + +import static androidx.core.content.ContextCompat.checkSelfPermission; + +public class Download { + + private final ContextInterface contextInterface; + private final ActivityInterface activityInterface; + private RequestedDownload requestedDownload; + private Logger log = new Logger(this); + + + public Download(ContextInterface contextInterface, ActivityInterface activityInterface) { + this.contextInterface = contextInterface; + this.activityInterface = activityInterface; + } + + public void openDownloadDialog(String title, String url, String folderName) { + openDownloadDialog(new Resource.File("", title, 0, url, true, "", ""), folderName); + } + + public void openDownloadDialog(Resource.File file, String folderName) { + Context context = contextInterface.get(); + if (context == null) + return; + AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context); + File f = new File(Environment.getExternalStoragePublicDirectory( + Environment.DIRECTORY_DOWNLOADS)+"/"+folderName+"/"+file.getTitle()); + Resources resources = context.getResources(); + String message = ""; + if (file.getAuthor() != null && !file.getAuthor().isEmpty()) + message += resources.getString(R.string.creator_name, file.getAuthor()); + if (file.getModifiedDate() != 0) { + if (!message.isEmpty()) + message += "\n"; + message += resources.getString(R.string.last_modified_on, UtilsDate.getModifiedDateTime(context, file.getModifiedDate())); + } + + alertDialogBuilder + .setTitle(file.getTitle()) + .setMessage(message) + .setCancelable(true) + .setNeutralButton(R.string.close, (dialog, id) -> dialog.cancel()); + // if already downloaded, show open button + if (f.exists()) { + alertDialogBuilder + .setPositiveButton(R.string.download_again, (dialog, id) -> download(file, folderName, true)) + .setNegativeButton(R.string.openFile, (dialog, id) -> download(file, folderName, false)); + } else { + alertDialogBuilder + .setPositiveButton(R.string.download, (dialog, id) -> download(file, folderName, true)); + } + AlertDialog alertDialog = alertDialogBuilder.create(); + alertDialog.show(); + } + + private void download(Resource.File file, String folderName, boolean downloadNew){ + MainActivity activity = activityInterface.get(); + if (activity == null) { + showDownloadError(); + return; + } + if (checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + // Access granted + downloadOrOpen(file, folderName, downloadNew); + } else { + this.requestedDownload = new RequestedDownload(file, folderName, downloadNew); + ActivityCompat.requestPermissions(activity, + new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, + 1); + } + } + + private void downloadOrOpen(Resource.File file, String folderName, boolean downloadNew) { + if (!isExternalStorageWritable()) { + return; + } + MainActivity activity = activityInterface.get(); + if (activity == null) { + showDownloadError(); + return; + } + activity.getNewKVV().modules().resources().file(file.getTitle(), file.getUrl(), folderName, success -> { + Context context = contextInterface.get(); + if (success.equals("")) { + showDownloadError(); + } else { + if (Regex.has("^http", success)){ + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(success)); + context.startActivity(intent); + } + else { + fileOpen(new File(success)); + } + + } + }, log::e, downloadNew); + } + + private void showDownloadError() { + Context context = contextInterface.get(); + if (context == null) + return; + AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context); + alertDialogBuilder + .setTitle(R.string.ErrorFileDownload) + .setMessage( + R.string.ErrorFileDownloadText + ) + .setCancelable(true) + .setNeutralButton(R.string.close, (dialog, id) -> dialog.cancel()); + AlertDialog alertDialog = alertDialogBuilder.create(); + alertDialog.show(); + } + + public RequestPermissionsResultListener getRequestPermissionsResultListener() { + return (requestCode, permissions, grantResults) -> { + if (requestedDownload == null) { + log.d("No request"); + return; + } + if (activityInterface.get() == null) { + showDownloadError(); + return; + } + ArrayList intList = new ArrayList<>(); + for (int i : grantResults) + { + intList.add(i); + } + log.d(requestCode, Arrays.asList(permissions), intList); + int pos = Arrays.asList(permissions).indexOf("android.permission.WRITE_EXTERNAL_STORAGE"); + if (pos != -1) { + if (grantResults[pos] != -1) { + downloadOrOpen(requestedDownload.file, requestedDownload.folderName, requestedDownload.downloadNew); + } else { + log.d(requestedDownload, pos, grantResults[pos]); + showDownloadError(); + } + requestedDownload = null; + } + }; + } + + private class RequestedDownload { + Resource.File file; + String folderName; + boolean downloadNew; + + RequestedDownload(Resource.File file, String folderName, boolean downloadNew) { + this.file = file; + this.folderName = folderName; + this.downloadNew = downloadNew; + } + } + + /* Checks if external storage is available for read and write */ + private boolean isExternalStorageWritable() { + String state = Environment.getExternalStorageState(); + if (Environment.MEDIA_MOUNTED.equals(state)) { + return true; + } + log.e("File system: Writing not possible"); + return false; + } + + private void fileOpen(File url){ + Uri uri = FileProvider.getUriForFile(contextInterface.get(), contextInterface.get().getApplicationContext().getPackageName() + ".my.provider", url); + + Intent intent; + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) { + intent = new Intent(Intent.ACTION_VIEW); + } else { + intent = new Intent(); + } + intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + // Check what kind of file you are trying to open, by comparing the url with extensions. + // When the if condition is matched, plugin sets the correct intent (mime) type, + // so Android knew what application to use to open the file + if (url.toString().contains(".doc") || url.toString().contains(".docx")) { + // Word document + intent.setDataAndType(uri, "application/msword"); + } else if(url.toString().contains(".pdf")) { + // PDF file + intent.setDataAndType(uri, "application/pdf"); + } else if(url.toString().contains(".ppt") || url.toString().contains(".pptx")) { + // Powerpoint file + intent.setDataAndType(uri, "application/vnd.ms-powerpoint"); + } else if(url.toString().contains(".xls") || url.toString().contains(".xlsx")) { + // Excel file + intent.setDataAndType(uri, "application/vnd.ms-excel"); + } else if(url.toString().contains(".zip") || url.toString().contains(".rar")) { + // ZIP file + intent.setDataAndType(uri, "application/zip"); + } else if(url.toString().contains(".rtf")) { + // RTF file + intent.setDataAndType(uri, "application/rtf"); + } else if(url.toString().contains(".wav") || url.toString().contains(".mp3")) { + // WAV audio file + intent.setDataAndType(uri, "audio/x-wav"); + } else if(url.toString().contains(".gif")) { + // GIF file + intent.setDataAndType(uri, "image/gif"); + } else if(url.toString().contains(".jpg") || url.toString().contains(".jpeg") || url.toString().contains(".png")) { + // JPG file + intent.setDataAndType(uri, "image/jpeg"); + } else if(url.toString().contains(".txt")) { + // Text file + intent.setDataAndType(uri, "text/plain"); + } else if(url.toString().contains(".3gp") || url.toString().contains(".mpg") || url.toString().contains(".mpeg") || url.toString().contains(".mpe") || url.toString().contains(".mp4") || url.toString().contains(".avi")) { + // Video files + intent.setDataAndType(uri, "video/*"); + } else { + //if you want you can also define the intent type for any other file + + //additionally use else clause below, to manage other unknown extensions + //in this case, Android will show all applications installed on the device + //so you can choose which application to use + intent.setDataAndType(uri, "*/*"); + } + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + contextInterface.get().startActivity(intent); + + } + + @FunctionalInterface + public interface ContextInterface { + @Nullable Context get(); + } + + @FunctionalInterface + public interface ActivityInterface { + @Nullable MainActivity get(); + } + + public interface OnDownloadRequestInterface { + void request(String title, String url); + } +} diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVLogin.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVLogin.java index 3d89e7d..96b13e1 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVLogin.java +++ b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVLogin.java @@ -35,9 +35,6 @@ public class KVVLogin extends HTTPService { if (mLoginPending) { errorCallback.onError(new NetworkError(100160, -1, "Login already pending!")); } - if (mToken != null) { - errorCallback.onError(new NetworkError(100161, -1, "Already logged in!")); - } mLoginPending = true; doLogin(username, password, token -> { testLoginToken(token, token2 -> { diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModules.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModules.java index ecc6aad..7adbe0b 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModules.java +++ b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModules.java @@ -12,7 +12,7 @@ public class KVVModules { private final KVVLogin mLogin; private final Context context; - public KVVModules(KVVLogin login, Context context) { + KVVModules(KVVLogin login, Context context) { this.mLogin = login; this.context = context; } @@ -20,7 +20,7 @@ public class KVVModules { @NotNull public KVVModulesDetails details() { return (KVVModulesDetails) addAndGet("details", () -> { - ModulesPart[] parts = {announcements(), assignments()}; + ModulesPart[] parts = {announcements(), assignments(), events(), gradebook(), resources()}; return new KVVModulesDetails(mLogin, list(), context, parts); }); } @@ -35,6 +35,21 @@ public class KVVModules { return (KVVModulesAssignments) addAndGet("assignments", () -> new KVVModulesAssignments(mLogin, list(), context)); } + @NotNull + public KVVModulesEvents events() { + return (KVVModulesEvents) addAndGet("events", () -> new KVVModulesEvents(mLogin, list(), context)); + } + + @NotNull + public KVVModulesGradebook gradebook() { + return (KVVModulesGradebook) addAndGet("gradebook", () -> new KVVModulesGradebook(mLogin, list(), context)); + } + + @NotNull + public KVVModulesResources resources() { + return (KVVModulesResources) addAndGet("resources", () -> new KVVModulesResources(mLogin, list(), context)); + } + @NotNull public KVVModulesList list() { if (mList == null) { diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesAnnouncements.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesAnnouncements.java index a719484..af57532 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesAnnouncements.java +++ b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesAnnouncements.java @@ -75,6 +75,7 @@ public class KVVModulesAnnouncements extends ModulesPart announcements.add(new Announcement(id, title, text, createdBy, createdOn, urls)); } catch (JSONException e) { log.e(new NetworkError(101205, 403, "Cannot parse announcements!")); + log.e("ID:", i, "JSON:", sites); e.printStackTrace(); return; } 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 29a70b2..0863e32 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 @@ -75,6 +75,7 @@ public class KVVModulesAssignments extends ModulesPart { } catch (JSONException e) { log.e(new NetworkError(101305, 403, "Cannot parse assignments!")); e.printStackTrace(); + log.e("ID:", i, "JSON:", sites); return; } } @@ -84,6 +85,6 @@ public class KVVModulesAssignments extends ModulesPart { mLogin.testLoginToken(token -> callback.onResponse(assignments), errorCallback); else callback.onResponse(assignments); - }, error -> errorCallback.onError(new NetworkError(101303, error.networkResponse.statusCode, "Cannot get announcements!"))); + }, error -> errorCallback.onError(new NetworkError(101303, error.networkResponse.statusCode, "Cannot get assignments!"))); } } diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesEvents.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesEvents.java new file mode 100644 index 0000000..4673090 --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesEvents.java @@ -0,0 +1,83 @@ +package de.sebse.fuplanner.services.NewKVV; + +import android.content.Context; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import de.sebse.fuplanner.services.NewKVV.types.Event; +import de.sebse.fuplanner.services.NewKVV.types.EventList; +import de.sebse.fuplanner.services.NewKVV.types.Modules; +import de.sebse.fuplanner.tools.network.NetworkCallback; +import de.sebse.fuplanner.tools.network.NetworkError; +import de.sebse.fuplanner.tools.network.NetworkErrorCallback; + +public class KVVModulesEvents extends ModulesPart { + + KVVModulesEvents(KVVLogin login, KVVModulesList list, Context context) { + super(login, list, context); + } + + @Override + protected EventList getPart(Modules.Module module) { + return module.events; + } + + @Override + protected boolean setPart(Modules.Module module, EventList part) { + boolean changed = module.events == null || module.events.hashCode() != part.hashCode(); + module.events = part; + return changed; + } + + @Override + protected void upgrade(final String ID, final NetworkCallback callback, final NetworkErrorCallback errorCallback) { + if (!mLogin.isInOnlineMode() || mLogin.getLoginToken() == 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?detailed=true", ID), mLogin.getLoginToken().getCookies(), response -> { + String body = response.getParsed(); + if (body == null) { + errorCallback.onError(new NetworkError(101401, 403, "No events retrieved!")); + return; + } + EventList events = new EventList(); + JSONArray sites; + try { + JSONObject json = new JSONObject(body); + sites = json.getJSONArray("calendar_collection"); + } catch (JSONException e) { + e.printStackTrace(); + errorCallback.onError(new NetworkError(101402, 403, "Cannot parse events!")); + return; + } + + for (int i = 0; i < sites.length(); i++) { + try { + JSONObject site = sites.getJSONObject(i); + String id = site.getString("eventId"); + String type = site.getString("type"); + String title = site.getString("title"); + String siteId = site.getString("siteId"); + long duration = site.getLong("duration"); + long firstTime = site.getJSONObject("firstTime").getLong("time"); + String location = site.getString("location"); + events.add(new Event(id, type, title, duration, firstTime, siteId, location)); + } catch (JSONException e) { + log.e(new NetworkError(101405, 403, "Cannot parse events!")); + e.printStackTrace(); + log.e("ID:", i, "JSON:", sites); + return; + } + } + + // Empty events *may be* because token is invalid -> check + if (events.size() == 0) + mLogin.testLoginToken(token -> callback.onResponse(events), errorCallback); + else + callback.onResponse(events); + }, error -> errorCallback.onError(new NetworkError(101403, error.networkResponse.statusCode, "Cannot get events!"))); + } +} diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesGradebook.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesGradebook.java new file mode 100644 index 0000000..08d461e --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesGradebook.java @@ -0,0 +1,76 @@ +package de.sebse.fuplanner.services.NewKVV; + +import android.content.Context; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; + +import de.sebse.fuplanner.services.NewKVV.types.Grade; +import de.sebse.fuplanner.services.NewKVV.types.Modules; +import de.sebse.fuplanner.tools.network.NetworkCallback; +import de.sebse.fuplanner.tools.network.NetworkError; +import de.sebse.fuplanner.tools.network.NetworkErrorCallback; + +public class KVVModulesGradebook extends ModulesPart> { + + KVVModulesGradebook(KVVLogin login, KVVModulesList list, Context context) { + super(login, list, context); + } + + @Override + protected ArrayList getPart(Modules.Module module) { + return module.gradebook; + } + + @Override + protected boolean setPart(Modules.Module module, ArrayList part) { + boolean changed = module.gradebook == null || module.gradebook.hashCode() != part.hashCode(); + module.gradebook = part; + return changed; + } + + @Override + protected void upgrade(final String ID, final NetworkCallback> callback, final NetworkErrorCallback errorCallback) { + if (!mLogin.isInOnlineMode() || mLogin.getLoginToken() == null) { + errorCallback.onError(new NetworkError(101504, 500, "Currently running in offline mode!")); + return; + } + super.get(String.format("https://kvv.imp.fu-berlin.de/direct/gradebook/site/%s.json", ID), mLogin.getLoginToken().getCookies(), response -> { + String body = response.getParsed(); + if (body == null) { + errorCallback.onError(new NetworkError(101501, 403, "No gradebook retrieved!")); + return; + } + ArrayList gradebook = new ArrayList<>(); + JSONArray sites; + try { + JSONObject json = new JSONObject(body); + sites = json.getJSONArray("assignments"); + } catch (JSONException e) { + e.printStackTrace(); + errorCallback.onError(new NetworkError(101502, 403, "Cannot parse gradebook!")); + return; + } + + for (int i = 0; i < sites.length(); i++) { + try { + JSONObject site = sites.getJSONObject(i); + double grade = site.optDouble("grade", 0); + String itemName = site.optString("itemName", null); + double maxPoints = site.optDouble("points", -1); + + gradebook.add(0, new Grade(itemName, grade, maxPoints)); + } catch (JSONException e) { + log.e(new NetworkError(101505, 403, "Cannot parse gradebook!")); + log.e("ID:", i, "JSON:", sites); + e.printStackTrace(); + return; + } + } + callback.onResponse(gradebook); + }, error -> errorCallback.onError(new NetworkError(101503, error.networkResponse.statusCode, "Cannot get gradebook!"))); + } +} 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 810d5c4..dbb52ff 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 @@ -179,9 +179,11 @@ public class KVVModulesList extends HTTPService { modules.addModule(semester, lvNumbers, title, lecturers, type, description, id); } catch (JSONException e) { log.e(new NetworkError(101103, 403, "Cannot parse module list!")); + log.e("ID:", i, "JSON:", sites); e.printStackTrace(); } catch (NoSuchFieldException e) { log.e(new NetworkError(101106, 403, "Cannot parse module list!")); + log.e("ID:", i, "JSON:", sites); e.printStackTrace(); } } diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesResources.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesResources.java new file mode 100644 index 0000000..1598a5b --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesResources.java @@ -0,0 +1,220 @@ +package de.sebse.fuplanner.services.NewKVV; + +import android.content.Context; +import android.os.Environment; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.File; +import java.io.FileOutputStream; +import java.util.ArrayList; + +import de.sebse.fuplanner.services.NewKVV.types.Modules; +import de.sebse.fuplanner.services.NewKVV.types.Resource; +import de.sebse.fuplanner.tools.Regex; +import de.sebse.fuplanner.tools.network.NetworkCallback; +import de.sebse.fuplanner.tools.network.NetworkError; +import de.sebse.fuplanner.tools.network.NetworkErrorCallback; + +public class KVVModulesResources extends ModulesPart> { + + KVVModulesResources(KVVLogin login, KVVModulesList list, Context context) { + super(login, list, context); + } + + @Override + protected ArrayList getPart(Modules.Module module) { + return module.resources; + } + + @Override + protected boolean setPart(Modules.Module module, ArrayList part) { + boolean changed = module.assignments == null || module.assignments.hashCode() != part.hashCode(); + module.resources = part; + return changed; + } + + @Override + protected void upgrade(final String ID, final NetworkCallback> callback, final NetworkErrorCallback errorCallback) { + if (!mLogin.isInOnlineMode() || mLogin.getLoginToken() == null) { + errorCallback.onError(new NetworkError(101604, 500, "Currently running in offline mode!")); + return; + } + get(String.format("https://kvv.imp.fu-berlin.de/direct/content/site/%s.json", ID), mLogin.getLoginToken().getCookies(), response -> { + String body = response.getParsed(); + if (body == null) { + errorCallback.onError(new NetworkError(101601, 403, "No resources retrieved!")); + return; + } + ArrayList resources = new ArrayList<>(); + JSONArray sites; + try { + JSONObject json = new JSONObject(body); + sites = json.getJSONArray("content_collection"); + } catch (JSONException e) { + e.printStackTrace(); + errorCallback.onError(new NetworkError(101602, 403, "Cannot parse resources!")); + return; + } + + for (int i = 0; i < sites.length(); i++) { + try { + JSONObject site = sites.getJSONObject(i); + String author = site.getString("author"); + String title = site.getString("title"); + long modifiedDate = site.getLong("modifiedDate"); + String url = site.getString("url"); + boolean visible = site.getBoolean("visible"); + String type = site.getString("type"); + String container = site.getString("container"); + if (type.equals("collection")){ + resources.add(new Resource.Folder(author, title, modifiedDate, url, visible, container)); + } + else { + resources.add(new Resource.File(author, title, modifiedDate, url, visible, container, type)); + } + } catch (JSONException e) { + log.e(new NetworkError(101605, 403, "Cannot parse resources!")); + e.printStackTrace(); + log.e("ID:", i, "JSON:", sites); + return; + } + } + + ArrayList root = new ArrayList<>(); + // Generate folder structure + for (Resource res: resources) { + if (!res.getContainer().equals("/content/group/")) { + if (res.getContainer().equals("/content/group/"+ID+"/")){ + // if file in root folder + root.add(res); + } else { + // in sub folder + for (Resource res2: resources) { + if (res2.getUrl().endsWith(res.getContainer()) && res2 instanceof Resource.Folder) { + // Append File/Folder to list + ((Resource.Folder) res2).add(res); + } + } + } + } + } + + // Empty assignments *may be* because token is invalid -> check + if (root.size() == 0) + mLogin.testLoginToken(token -> callback.onResponse(root), errorCallback); + else + callback.onResponse(root); + }, error -> errorCallback.onError(new NetworkError(101603, error.networkResponse.statusCode, "Cannot get resources!"))); + } + + + + + + + + + + + + public void file(final String filename, final String url, final String modulename, final NetworkCallback callback, final NetworkErrorCallback errorCallback, boolean forceRefresh) { + file(filename, url, modulename, callback, errorCallback, forceRefresh, RETRY_COUNT); + } + + public void file(final String filename, final String url, final String modulename, final NetworkCallback callback, final NetworkErrorCallback errorCallback, boolean forceRefresh, int retries) { + if (isExternalStorageReadable()){ + File f = new File(Environment.getExternalStoragePublicDirectory( + Environment.DIRECTORY_DOWNLOADS)+"/"+modulename+"/"+filename); + // check if file already downloaded -> do not download again + if (f.exists() && !forceRefresh) { + callback.onResponse(f.getPath()); + return; + } + } + fileUpgrade(filename, url , modulename, callback, error -> { + if (retries >= 0 && (error.getHttpStatus() == 401 || error.getHttpStatus() == 403)) { + mLogin.refreshLogin(success -> { + file(filename, url, modulename, callback, errorCallback, forceRefresh, retries-1); + }, errorCallback); + return; + } + errorCallback.onError(error); + }); + } + + private void fileUpgrade(String filename, String url, String modulename, final NetworkCallback callback, final NetworkErrorCallback errorCallback) { + if (!mLogin.isInOnlineMode() || mLogin.getLoginToken() == null) { + errorCallback.onError(new NetworkError(101604, 500, "Currently running in offline mode!")); + return; + } + get(url, mLogin.getLoginToken().getCookies(), response -> { + if (Regex.has("\\.[Uu][Rr][Ll]$", url)){ + // Return redirected URL + String path = response.getHeaders().get("Location"); + if (path == null){ + path = ""; + } + callback.onResponse(path); + } else if (response.getBytes() == null) { + errorCallback.onError(new NetworkError(101705, 403, "Cannot get file!")); + } else if (isExternalStorageWritable()) { + String path = saveFileInDownloads(filename, response.getBytes(), modulename); + callback.onResponse(path); + } else { + errorCallback.onError(new NetworkError(101704, 403, "External storage not writable!")); + } + }, error -> errorCallback.onError(new NetworkError(101702, error.networkResponse.statusCode, "Cannot get file!"))); + + + } + + + + + + + + /* Checks if external storage is available for read and write */ + private boolean isExternalStorageWritable() { + String state = Environment.getExternalStorageState(); + if (Environment.MEDIA_MOUNTED.equals(state)) { + return true; + } + log.w("File system: Writing not possible!"); + return false; + } + + /* Checks if external storage is available to at least read */ + private boolean isExternalStorageReadable() { + String state = Environment.getExternalStorageState(); + if (Environment.MEDIA_MOUNTED.equals(state) || + Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) { + return true; + } + log.w("File system: Reading not possible!"); + return false; + } + private String saveFileInDownloads(String filename, byte[] data, String moduleName) { + // Saves file in folder: DOWNLOADS/moduleName + File folder = new File(Environment.getExternalStoragePublicDirectory( + Environment.DIRECTORY_DOWNLOADS), moduleName); + if (!folder.mkdir()) { + log.w( "Directory not created"); + } + String path = ""; + try { + // TODO check if enough storage space is available + FileOutputStream out = new FileOutputStream(folder.getPath()+"/"+filename); + out.write(data); + out.close(); + path = folder.getPath()+"/"+filename; + } catch (Exception e) { + log.w("File not saved!"); + e.printStackTrace(); + } + return path; + } +} 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 294636c..0521a9f 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 @@ -23,7 +23,11 @@ public abstract class Part extends HTTPService { } public void recv(final String moduleID, final NetworkCallback callback, final NetworkErrorCallback errorCallback, final boolean forceRefresh) { - mList.find(moduleID, success -> recv(success, callback, errorCallback, forceRefresh, RETRY_COUNT), errorCallback); + mList.find(moduleID, success -> recv(success, callback, errorCallback, forceRefresh), errorCallback); + } + + public void recv(final Modules.Module module, final NetworkCallback callback, final NetworkErrorCallback errorCallback, final boolean forceRefresh) { + recv(module, callback, errorCallback, forceRefresh, RETRY_COUNT); } 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/Gradebook.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Grade.java similarity index 69% rename from app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Gradebook.java rename to app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Grade.java index d97e368..d102d84 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Gradebook.java +++ b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Grade.java @@ -1,13 +1,15 @@ package de.sebse.fuplanner.services.NewKVV.types; +import com.google.android.gms.common.internal.Objects; + import java.io.Serializable; -public class Gradebook implements Serializable { +public class Grade implements Serializable { private final String itemName; private final double grade; private final double maxPoints; - public Gradebook(String itemName, double points, double maxPoints) { + public Grade(String itemName, double points, double maxPoints) { this.itemName = itemName; this.grade = points; this.maxPoints = maxPoints; @@ -31,4 +33,9 @@ public class Gradebook implements Serializable { "\nPoints: "+ getPoints()+ "\nMax points: "+getMaxPoints(); } + + @Override + public int hashCode() { + return Objects.hashCode(getItemName(), getPoints(), getMaxPoints()); + } } 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 8994948..a746e45 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 @@ -116,14 +116,14 @@ public class Modules implements Iterable, Serializable { @Nullable public ArrayList announcements; @Nullable public AssignmentList assignments; @Nullable public EventList events; - @Nullable public ArrayList gradebook; + @Nullable public ArrayList gradebook; @Nullable public ArrayList resources; public float getGradebookPercent(){ float maxPoint = 0; float userPoint = 0; if (gradebook != null) { - for (Gradebook g : gradebook){ + for (Grade g : gradebook){ maxPoint += g.getMaxPoints(); userPoint += g.getPoints(); } diff --git a/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/DirectoryNodeBinder.java b/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/DirectoryNodeBinder.java index 9a2ac9c..9cae51b 100644 --- a/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/DirectoryNodeBinder.java +++ b/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/DirectoryNodeBinder.java @@ -5,7 +5,7 @@ import android.widget.ImageView; import android.widget.TextView; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.KVV.types.Resource; +import de.sebse.fuplanner.services.NewKVV.types.Resource; /** * Created by tlh on 2016/10/1 :) diff --git a/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/FileNodeBinder.java b/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/FileNodeBinder.java index f337b37..a89af39 100644 --- a/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/FileNodeBinder.java +++ b/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/FileNodeBinder.java @@ -4,7 +4,7 @@ import android.view.View; import android.widget.TextView; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.KVV.types.Resource; +import de.sebse.fuplanner.services.NewKVV.types.Resource; /** * Created by tlh on 2016/10/1 :) From 9b48f9b414af58666157e6f2367dcc0062bd1262 Mon Sep 17 00:00:00 2001 From: Caesar2011 Date: Fri, 9 Nov 2018 20:45:54 +0100 Subject: [PATCH 07/17] Removed Old KVV --- .../java/de/sebse/fuplanner/MainActivity.java | 60 +- .../fuplanner/fragments/CanteensAdapter.java | 1 - .../fuplanner/fragments/LoginFragment.java | 8 +- .../fuplanner/fragments/ModulesAdapter.java | 2 +- .../fuplanner/fragments/ModulesFragment.java | 4 +- .../fuplanner/fragments/ScheduleFragment.java | 11 +- .../moddetails/ModDetailAnnounceAdapter.java | 6 +- .../moddetails/ModDetailAnnounceFragment.java | 8 +- .../ModDetailAssignmentAdapter.java | 6 +- .../ModDetailAssignmentFragment.java | 8 +- .../moddetails/ModDetailEventAdapter.java | 13 +- .../ModDetailEventAdapterInner.java | 6 +- .../moddetails/ModDetailEventFragment.java | 2 +- .../moddetails/ModDetailFragment.java | 4 +- .../moddetails/ModDetailGradebookAdapter.java | 4 +- .../ModDetailGradebookFragment.java | 2 +- .../moddetails/ModDetailOverviewAdapter.java | 8 +- .../moddetails/ModDetailOverviewFragment.java | 2 +- .../moddetails/ModDetailResourceAdapter.java | 4 +- .../moddetails/ModDetailResourceFragment.java | 10 +- .../fuplanner/services/KVV/Download.java | 56 +- .../de/sebse/fuplanner/services/KVV/KVV.java | 224 +----- .../services/{NewKVV => KVV}/KVVListener.java | 4 +- .../fuplanner/services/KVV/KVVLogin.java | 191 +++++- .../fuplanner/services/KVV/KVVModuleList.java | 639 ------------------ .../services/{NewKVV => KVV}/KVVModules.java | 2 +- .../KVVModulesAnnouncements.java | 6 +- .../KVVModulesAssignments.java | 8 +- .../{NewKVV => KVV}/KVVModulesDetails.java | 4 +- .../{NewKVV => KVV}/KVVModulesEvents.java | 8 +- .../{NewKVV => KVV}/KVVModulesGradebook.java | 6 +- .../{NewKVV => KVV}/KVVModulesList.java | 9 +- .../{NewKVV => KVV}/KVVModulesResources.java | 12 +- .../services/KVV/LastTokenCallback.java | 11 - .../services/{NewKVV => KVV}/ModulesPart.java | 6 +- .../services/{NewKVV => KVV}/Part.java | 4 +- .../fuplanner/services/KVV/TestLogin.java | 38 -- .../services/KVV/types/Announcement.java | 7 + .../services/KVV/types/Assignment.java | 8 +- .../fuplanner/services/KVV/types/Event.java | 7 + .../services/{NewKVV => KVV}/types/Grade.java | 2 +- .../services/KVV/types/Gradebook.java | 34 - .../services/KVV/types/LoginToken.java | 22 +- .../fuplanner/services/KVV/types/Modules.java | 48 +- .../services/KVV/types/Resource.java | 7 + .../services/KVV/types/SortedListModule.java | 2 +- .../fuplanner/services/NewKVV/Download.java | 265 -------- .../sebse/fuplanner/services/NewKVV/KVV.java | 47 -- .../fuplanner/services/NewKVV/KVVLogin.java | 443 ------------ .../services/NewKVV/types/Announcement.java | 64 -- .../services/NewKVV/types/Assignment.java | 59 -- .../services/NewKVV/types/AssignmentList.java | 16 - .../services/NewKVV/types/Event.java | 114 ---- .../services/NewKVV/types/EventList.java | 16 - .../services/NewKVV/types/GroupedEvents.java | 128 ---- .../services/NewKVV/types/Lecturer.java | 41 -- .../services/NewKVV/types/LoginToken.java | 114 ---- .../services/NewKVV/types/Modules.java | 168 ----- .../services/NewKVV/types/Resource.java | 134 ---- .../NewKVV/types/SortedListModule.java | 68 -- .../fuplanner/tools/MainActivityListener.java | 5 - .../ui/treeview/DirectoryNodeBinder.java | 2 +- .../tools/ui/treeview/FileNodeBinder.java | 2 +- 63 files changed, 380 insertions(+), 2840 deletions(-) rename app/src/main/java/de/sebse/fuplanner/services/{NewKVV => KVV}/KVVListener.java (79%) delete mode 100644 app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModuleList.java rename app/src/main/java/de/sebse/fuplanner/services/{NewKVV => KVV}/KVVModules.java (98%) rename app/src/main/java/de/sebse/fuplanner/services/{NewKVV => KVV}/KVVModulesAnnouncements.java (95%) rename app/src/main/java/de/sebse/fuplanner/services/{NewKVV => KVV}/KVVModulesAssignments.java (94%) rename app/src/main/java/de/sebse/fuplanner/services/{NewKVV => KVV}/KVVModulesDetails.java (94%) rename app/src/main/java/de/sebse/fuplanner/services/{NewKVV => KVV}/KVVModulesEvents.java (93%) rename app/src/main/java/de/sebse/fuplanner/services/{NewKVV => KVV}/KVVModulesGradebook.java (94%) rename app/src/main/java/de/sebse/fuplanner/services/{NewKVV => KVV}/KVVModulesList.java (96%) rename app/src/main/java/de/sebse/fuplanner/services/{NewKVV => KVV}/KVVModulesResources.java (95%) delete mode 100644 app/src/main/java/de/sebse/fuplanner/services/KVV/LastTokenCallback.java rename app/src/main/java/de/sebse/fuplanner/services/{NewKVV => KVV}/ModulesPart.java (93%) rename app/src/main/java/de/sebse/fuplanner/services/{NewKVV => KVV}/Part.java (93%) delete mode 100644 app/src/main/java/de/sebse/fuplanner/services/KVV/TestLogin.java rename app/src/main/java/de/sebse/fuplanner/services/{NewKVV => KVV}/types/Grade.java (94%) delete mode 100644 app/src/main/java/de/sebse/fuplanner/services/KVV/types/Gradebook.java delete mode 100644 app/src/main/java/de/sebse/fuplanner/services/NewKVV/Download.java delete mode 100644 app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVV.java delete mode 100644 app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVLogin.java delete mode 100644 app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Announcement.java delete mode 100644 app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Assignment.java delete mode 100644 app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/AssignmentList.java delete mode 100644 app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Event.java delete mode 100644 app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/EventList.java delete mode 100644 app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/GroupedEvents.java delete mode 100644 app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Lecturer.java delete mode 100644 app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/LoginToken.java delete mode 100644 app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Modules.java delete mode 100644 app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Resource.java delete mode 100644 app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/SortedListModule.java diff --git a/app/src/main/java/de/sebse/fuplanner/MainActivity.java b/app/src/main/java/de/sebse/fuplanner/MainActivity.java index d1a1769..1ee0b22 100644 --- a/app/src/main/java/de/sebse/fuplanner/MainActivity.java +++ b/app/src/main/java/de/sebse/fuplanner/MainActivity.java @@ -35,9 +35,8 @@ import de.sebse.fuplanner.services.Canteen.CanteenBrowser; import de.sebse.fuplanner.services.Canteen.types.Canteen; import de.sebse.fuplanner.services.GoogleAuth.Credentials; import de.sebse.fuplanner.services.GoogleAuth.GoogleAuth; -import de.sebse.fuplanner.services.NewKVV.KVV; -import de.sebse.fuplanner.services.KVV.types.LoginToken; -import de.sebse.fuplanner.services.NewKVV.KVVListener; +import de.sebse.fuplanner.services.KVV.KVV; +import de.sebse.fuplanner.services.KVV.KVVListener; import de.sebse.fuplanner.tools.MainActivityListener; import de.sebse.fuplanner.tools.RequestPermissionsResultListener; import de.sebse.fuplanner.tools.logging.Logger; @@ -66,7 +65,6 @@ public class MainActivity extends AppCompatActivity private FragmentManager mFragmentManager; private GoogleAuth mGoogleAuth; - private de.sebse.fuplanner.services.KVV.KVV mKVV; private KVV mNewKVV; private final Logger log = new Logger(this); private NavigationView mNavigationView; @@ -101,7 +99,7 @@ public class MainActivity extends AppCompatActivity mNavigationView.setNavigationItemSelectedListener(this); mFragmentManager = getSupportFragmentManager(); - if (!getNewKVV().account().restoreOnlineLogin()) { + if (!getKVV().account().restoreOnlineLogin()) { desiredPage = FRAGMENT_LOGIN; desiredData = ""; } @@ -179,8 +177,8 @@ public class MainActivity extends AppCompatActivity startActivity(sendIntent); break; case R.id.nav_logout: - getNewKVV().account().logout(true); - getNewKVV().modules().list().delete(); + getKVV().account().logout(true); + getKVV().modules().list().delete(); this.getGoogleAuth().getLoginState(credentials -> { if (credentials != null) { this.getGoogleAuth().deleteLoginState(credentials.getUsername(), credentials.getPassword()); @@ -240,15 +238,15 @@ public class MainActivity extends AppCompatActivity return this.mGoogleAuth; } - @Deprecated + /*@Deprecated public de.sebse.fuplanner.services.KVV.KVV getKVV() { if (this.mKVV == null) { this.mKVV = new de.sebse.fuplanner.services.KVV.KVV(this); } return this.mKVV; - } + }*/ - public KVV getNewKVV() { + public KVV getKVV() { if (this.mNewKVV == null) { this.mNewKVV = new KVV(this, this); } @@ -273,14 +271,6 @@ public class MainActivity extends AppCompatActivity changeFragment(FRAGMENT_LOGIN); } - private void toLoginState(LoginToken loginToken, int newFragment, String newData) { - if (loginToken == null) { - toLogoutState(); - } else { - toLoginState(loginToken.getFullName(), loginToken.getEmail(), newFragment, newData, true); - } - } - private void toLoginState(String fullName, String email, int newFragment, String newData, boolean onlineMode) { setOfflineBanner(!onlineMode); updateNavigation(); @@ -292,24 +282,6 @@ public class MainActivity extends AppCompatActivity changeFragment(newFragment, newData); } - @Deprecated - private void checkAndDoLogin() { - changeFragment(FRAGMENT_STARTUP); - getGoogleAuth().getLoginState(credentials -> { - if (credentials == null || credentials.getUsername() == null || credentials.getPassword() == null) { - toLogoutState(); - return; - } - - int fragment = getDefaultFragmentAfterLogin(); - this.getKVV().login(credentials.getUsername(), credentials.getPassword(), success -> toLoginState(success, fragment, ""), - error -> { - log.e(error); - toLogoutState(); - }); - }); - } - private void changeFragment(int newFragment) { changeFragment(newFragment, ""); } @@ -387,7 +359,7 @@ public class MainActivity extends AppCompatActivity MenuItem item; switch (fragmentPage) { case FRAGMENT_MODULES_DETAILS: - getKVV().getModule(fragmentData, success -> { + getKVV().modules().list().find(fragmentData, success -> { int size = mNavigationView.getMenu().size(); //noinspection ConstantConditions String title = success == null ? null : success.title; @@ -449,10 +421,10 @@ public class MainActivity extends AppCompatActivity private void afterAnyMenuInflate(boolean isLoggedIn) { if (isLoggedIn) { - getNewKVV().modules().list().recv(success -> { + getKVV().modules().list().recv(success -> { int i = 0; - for (Iterator it = success.latestSemesterIterator(); it.hasNext(); ) { - de.sebse.fuplanner.services.NewKVV.types.Modules.Module module = it.next(); + for (Iterator it = success.latestSemesterIterator(); it.hasNext(); ) { + de.sebse.fuplanner.services.KVV.types.Modules.Module module = it.next(); MenuItem menuItem = mNavigationView.getMenu().add(Menu.NONE, Menu.NONE, 101 + i, module.title); menuItem.setOnMenuItemClickListener(item -> { onModulesFragmentInteraction(module.getID()); @@ -476,7 +448,7 @@ public class MainActivity extends AppCompatActivity } private void updateNavigation() { - boolean isLoggedIn = getNewKVV().account().isLoggedIn(); + boolean isLoggedIn = getKVV().account().isLoggedIn(); setNavigationHeader(isLoggedIn); mNavigationView.getMenu().clear(); if (isLoggedIn) @@ -515,7 +487,7 @@ public class MainActivity extends AppCompatActivity setTitle(titleId); } - @Deprecated + /*+++@Deprecated @Override public void loginTokenInvalid(boolean doLoginCheck) { if (doLoginCheck) { @@ -529,7 +501,7 @@ public class MainActivity extends AppCompatActivity getKVV().invalidate(); checkAndDoLogin(); } - } + }*/ @Override public void onRefreshCompleted(boolean isFailed) { @@ -577,7 +549,7 @@ public class MainActivity extends AppCompatActivity } @Override - public void handleLogin(de.sebse.fuplanner.services.NewKVV.types.LoginToken token, boolean enteringOnlineMode) { + public void handleLogin(de.sebse.fuplanner.services.KVV.types.LoginToken token, boolean enteringOnlineMode) { toLoginState(token.getUsername(), token.getEmail(), getDefaultFragmentAfterLogin(), "", enteringOnlineMode); } diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/CanteensAdapter.java b/app/src/main/java/de/sebse/fuplanner/fragments/CanteensAdapter.java index 41c6ba0..d9e1217 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/CanteensAdapter.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/CanteensAdapter.java @@ -10,7 +10,6 @@ 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; /** 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 2bbbb92..693e63f 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/LoginFragment.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/LoginFragment.java @@ -47,11 +47,11 @@ public class LoginFragment extends Fragment { Bundle savedInstanceState) { // Inflate the layout for this fragment View v = inflater.inflate(R.layout.fragment_login, container, false); - if (mActivityListener != null && mActivityListener.getNewKVV().modules().list().stored()) { + if (mActivityListener != null && mActivityListener.getKVV().modules().list().stored()) { 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, mActivityListener.getNewKVV().modules().list().getUsername())); - offline_btn.setOnClickListener(v1 -> mActivityListener.getNewKVV().account().doOfflineLogin()); + offline_btn.setText(v.getResources().getString(R.string.enter_offline_mode, mActivityListener.getKVV().modules().list().getUsername())); + offline_btn.setOnClickListener(v1 -> mActivityListener.getKVV().account().doOfflineLogin()); } View btn_login = v.findViewById(R.id.btn_login); @@ -68,7 +68,7 @@ public class LoginFragment extends Fragment { String username = input_usr.getText().toString(); String password = input_pwd.getText().toString(); - mActivityListener.getNewKVV().account().doOnlineLogin(username, password, success -> { + mActivityListener.getKVV().account().doOnlineLogin(username, password, success -> { progressDialog.dismiss(); mActivityListener.getGoogleAuth().setLoginState(username, password); input_usr.setError(null); diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/ModulesAdapter.java b/app/src/main/java/de/sebse/fuplanner/fragments/ModulesAdapter.java index 5413117..4b85503 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/ModulesAdapter.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/ModulesAdapter.java @@ -8,7 +8,7 @@ import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import de.sebse.fuplanner.R; import de.sebse.fuplanner.fragments.ModulesFragment.OnModulesFragmentInteractionListener; -import de.sebse.fuplanner.services.NewKVV.types.Modules; +import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.tools.ui.ItemViewHolder; /** 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 9e3afcf..809ab8a 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/ModulesFragment.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/ModulesFragment.java @@ -12,9 +12,7 @@ import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; -import de.sebse.fuplanner.MainActivity; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.KVV.KVV; import de.sebse.fuplanner.tools.MainActivityListener; import de.sebse.fuplanner.tools.logging.Logger; @@ -68,7 +66,7 @@ public class ModulesFragment extends Fragment { private void refresh(boolean forceRefresh) { if (mMainActivityListener != null) { - mMainActivityListener.getNewKVV().modules().list().recv(success -> { + mMainActivityListener.getKVV().modules().list().recv(success -> { adapter.setModules(success); //if (mMainActivityListener != null) // mMainActivityListener.refreshNavigation(); diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/ScheduleFragment.java b/app/src/main/java/de/sebse/fuplanner/fragments/ScheduleFragment.java index c6439ca..2dce81b 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/ScheduleFragment.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/ScheduleFragment.java @@ -16,9 +16,8 @@ import java.util.List; import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.NewKVV.KVV; -import de.sebse.fuplanner.services.NewKVV.types.Event; -import de.sebse.fuplanner.services.NewKVV.types.Modules; +import de.sebse.fuplanner.services.KVV.types.Event; +import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.tools.UtilsDate; import de.sebse.fuplanner.tools.MainActivityListener; import de.sebse.fuplanner.tools.logging.Logger; @@ -60,11 +59,11 @@ public class ScheduleFragment extends Fragment implements MonthLoader.MonthChang public void invalidate(boolean forceRefresh) { if (mListener == null) return; - mListener.getNewKVV().modules().list().recv(modules -> { + mListener.getKVV().modules().list().recv(modules -> { mModules = modules; final int[] i = {0}; for (Modules.Module module: mModules) { - mListener.getNewKVV().modules().events().recv(module, success1 -> { + mListener.getKVV().modules().events().recv(module, success1 -> { i[0]++; if (i[0] >= mModules.size()) { if (mWeekView != null) { @@ -182,7 +181,7 @@ public class ScheduleFragment extends Fragment implements MonthLoader.MonthChang AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getContext()); if (mListener == null) return; - mListener.getNewKVV().modules().list().find(moduleId, module -> { + mListener.getKVV().modules().list().find(moduleId, module -> { String moduleName = module.title; alertDialogBuilder .setTitle(event.getName()) 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 index 2c09880..e616571 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAnnounceAdapter.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAnnounceAdapter.java @@ -16,9 +16,9 @@ import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; import androidx.recyclerview.widget.RecyclerView; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.NewKVV.Download; -import de.sebse.fuplanner.services.NewKVV.types.Announcement; -import de.sebse.fuplanner.services.NewKVV.types.Modules; +import de.sebse.fuplanner.services.KVV.Download; +import de.sebse.fuplanner.services.KVV.types.Announcement; +import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.tools.Regex; import de.sebse.fuplanner.tools.UtilsDate; import de.sebse.fuplanner.tools.logging.Logger; 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 3c7dc6b..fb38cdf 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 @@ -14,8 +14,8 @@ import androidx.recyclerview.widget.RecyclerView; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import de.sebse.fuplanner.MainActivity; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.NewKVV.Download; -import de.sebse.fuplanner.services.NewKVV.types.Modules; +import de.sebse.fuplanner.services.KVV.Download; +import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.tools.MainActivityListener; import de.sebse.fuplanner.tools.logging.Logger; @@ -84,7 +84,7 @@ public class ModDetailAnnounceFragment extends Fragment implements Download.OnDo private void refresh(boolean forceRefresh) { if (mListener == null) return; - mListener.getNewKVV().modules().announcements().recv(mItemPos, success -> { + mListener.getKVV().modules().announcements().recv(mItemPos, success -> { adapter.setModule(success); swipeLayout.setRefreshing(false); }, error -> { @@ -97,7 +97,7 @@ public class ModDetailAnnounceFragment extends Fragment implements Download.OnDo public void request(String title, String url) { if (mListener == null) return; - mListener.getNewKVV().modules().list().find(mItemPos, (Modules.Module module) -> { + mListener.getKVV().modules().list().find(mItemPos, (Modules.Module module) -> { String folderName = "FU-"+module.title.replaceAll("[:*<>|/\"\\\\]", "-"); folderName += "/Assignment"; getDownload().openDownloadDialog(title, url, folderName); 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 index 32f6379..f3f74e2 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentAdapter.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentAdapter.java @@ -16,9 +16,9 @@ import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; import androidx.recyclerview.widget.RecyclerView; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.NewKVV.Download; -import de.sebse.fuplanner.services.NewKVV.types.Assignment; -import de.sebse.fuplanner.services.NewKVV.types.Modules; +import de.sebse.fuplanner.services.KVV.Download; +import de.sebse.fuplanner.services.KVV.types.Assignment; +import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.tools.Regex; import de.sebse.fuplanner.tools.UtilsDate; import de.sebse.fuplanner.tools.logging.Logger; 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 index 8a9dbb3..39fb185 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentFragment.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentFragment.java @@ -14,8 +14,8 @@ import androidx.recyclerview.widget.RecyclerView; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import de.sebse.fuplanner.MainActivity; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.NewKVV.Download; -import de.sebse.fuplanner.services.NewKVV.types.Modules; +import de.sebse.fuplanner.services.KVV.Download; +import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.tools.MainActivityListener; import de.sebse.fuplanner.tools.logging.Logger; @@ -84,7 +84,7 @@ public class ModDetailAssignmentFragment extends Fragment implements Download.On private void refresh(boolean forceRefresh) { if (mListener == null) return; - mListener.getNewKVV().modules().assignments().recv(mItemPos, success -> { + mListener.getKVV().modules().assignments().recv(mItemPos, success -> { adapter.setModule(success); swipeLayout.setRefreshing(false); }, error -> { @@ -98,7 +98,7 @@ public class ModDetailAssignmentFragment extends Fragment implements Download.On log.d(title, url, mListener); if (mListener == null) return; - mListener.getNewKVV().modules().list().find(mItemPos, (Modules.Module module) -> { + mListener.getKVV().modules().list().find(mItemPos, (Modules.Module module) -> { String folderName = "FU-"+module.title.replaceAll("[:*<>|/\"\\\\]", "-"); folderName += "/Assignment"; getDownload().openDownloadDialog(title, url, folderName); diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailEventAdapter.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailEventAdapter.java index c3b80d3..fd80dee 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailEventAdapter.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailEventAdapter.java @@ -1,7 +1,6 @@ package de.sebse.fuplanner.fragments.moddetails; import android.content.res.Resources; -import android.util.Pair; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -11,20 +10,16 @@ import java.util.LinkedHashMap; import java.util.Map; import androidx.annotation.NonNull; -import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.NewKVV.types.Event; -import de.sebse.fuplanner.services.NewKVV.types.EventList; -import de.sebse.fuplanner.services.NewKVV.types.GroupedEvents; -import de.sebse.fuplanner.services.NewKVV.types.Modules; +import de.sebse.fuplanner.services.KVV.types.Event; +import de.sebse.fuplanner.services.KVV.types.EventList; +import de.sebse.fuplanner.services.KVV.types.GroupedEvents; +import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.tools.Triplet; -import de.sebse.fuplanner.tools.UtilsDate; import de.sebse.fuplanner.tools.logging.Logger; import de.sebse.fuplanner.tools.ui.CustomViewHolder; -import de.sebse.fuplanner.tools.ui.ItemViewHolder; import de.sebse.fuplanner.tools.ui.ListViewHolder; -import de.sebse.fuplanner.tools.ui.StringViewHolder; class ModDetailEventAdapter extends RecyclerView.Adapter { private static final String VALUE_LECTURE = "Class section - Lecture"; diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailEventAdapterInner.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailEventAdapterInner.java index 9ab60d7..2ff1e72 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailEventAdapterInner.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailEventAdapterInner.java @@ -10,9 +10,9 @@ import java.util.ArrayList; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.NewKVV.types.Event; -import de.sebse.fuplanner.services.NewKVV.types.EventList; -import de.sebse.fuplanner.services.NewKVV.types.GroupedEvents; +import de.sebse.fuplanner.services.KVV.types.Event; +import de.sebse.fuplanner.services.KVV.types.EventList; +import de.sebse.fuplanner.services.KVV.types.GroupedEvents; import de.sebse.fuplanner.tools.UtilsDate; import de.sebse.fuplanner.tools.ui.ItemViewHolder; diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailEventFragment.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailEventFragment.java index 759a27c..c5346c5 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailEventFragment.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailEventFragment.java @@ -83,7 +83,7 @@ public class ModDetailEventFragment extends Fragment { private void refresh(boolean forceRefresh) { if (mListener == null) return; - mListener.getNewKVV().modules().events().recv(mItemPos, success -> { + mListener.getKVV().modules().events().recv(mItemPos, success -> { adapter.setModule(success); swipeLayout.setRefreshing(false); }, error -> { diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailFragment.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailFragment.java index 1502fac..b903da7 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailFragment.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailFragment.java @@ -10,7 +10,7 @@ import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; import androidx.viewpager.widget.ViewPager; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.NewKVV.types.Modules; +import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.tools.MainActivityListener; import de.sebse.fuplanner.tools.logging.Logger; @@ -72,7 +72,7 @@ public class ModDetailFragment extends Fragment implements ModDetailListener { } if (mListener != null) { mListener.onTitleTextChange(R.string.courses); - mListener.getNewKVV().modules().list().recv(success -> { + mListener.getKVV().modules().list().recv(success -> { Modules.Module module = success.get(mItemPos); if (mListener != null && module != null) mListener.onTitleTextChange(module.title); diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailGradebookAdapter.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailGradebookAdapter.java index 3201f0d..a5ef15b 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailGradebookAdapter.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailGradebookAdapter.java @@ -12,8 +12,8 @@ import java.util.ArrayList; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.NewKVV.types.Grade; -import de.sebse.fuplanner.services.NewKVV.types.Modules; +import de.sebse.fuplanner.services.KVV.types.Grade; +import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.tools.ui.StringViewHolder; class ModDetailGradebookAdapter extends RecyclerView.Adapter { diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailGradebookFragment.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailGradebookFragment.java index b6fa624..69ee5f8 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailGradebookFragment.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailGradebookFragment.java @@ -83,7 +83,7 @@ public class ModDetailGradebookFragment extends Fragment { private void refresh(boolean forceRefresh) { if (mListener == null) return; - mListener.getNewKVV().modules().gradebook().recv(mItemPos, success -> { + mListener.getKVV().modules().gradebook().recv(mItemPos, success -> { adapter.setModule(success); swipeLayout.setRefreshing(false); }, error -> { 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 a009b2b..8e95208 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 @@ -13,10 +13,10 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.recyclerview.widget.RecyclerView; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.NewKVV.types.Announcement; -import de.sebse.fuplanner.services.NewKVV.types.Assignment; -import de.sebse.fuplanner.services.NewKVV.types.Event; -import de.sebse.fuplanner.services.NewKVV.types.Modules; +import de.sebse.fuplanner.services.KVV.types.Announcement; +import de.sebse.fuplanner.services.KVV.types.Assignment; +import de.sebse.fuplanner.services.KVV.types.Event; +import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.tools.UtilsDate; import de.sebse.fuplanner.tools.logging.Logger; import de.sebse.fuplanner.tools.ui.CustomViewHolder; 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 9bce5b8..8519488 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 @@ -86,7 +86,7 @@ public class ModDetailOverviewFragment extends Fragment { private void refresh(boolean forceRefresh) { if (mListener != null) { - mListener.getNewKVV().modules().details().recv(mItemPos, pair -> { + mListener.getKVV().modules().details().recv(mItemPos, pair -> { adapter.setModule(pair.first); if (pair.second) swipeLayout.setRefreshing(false); diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailResourceAdapter.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailResourceAdapter.java index c63e94d..8b5e570 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailResourceAdapter.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailResourceAdapter.java @@ -3,8 +3,8 @@ package de.sebse.fuplanner.fragments.moddetails; import java.util.ArrayList; import java.util.List; -import de.sebse.fuplanner.services.NewKVV.types.Modules; -import de.sebse.fuplanner.services.NewKVV.types.Resource; +import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.services.KVV.types.Resource; import de.sebse.fuplanner.tools.ui.treeview.TreeNode; import de.sebse.fuplanner.tools.ui.treeview.TreeViewAdapter; import de.sebse.fuplanner.tools.ui.treeview.TreeViewBinder; diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailResourceFragment.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailResourceFragment.java index b245d79..50bf28e 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailResourceFragment.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailResourceFragment.java @@ -18,9 +18,9 @@ import androidx.recyclerview.widget.RecyclerView; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import de.sebse.fuplanner.MainActivity; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.NewKVV.Download; -import de.sebse.fuplanner.services.NewKVV.types.Modules; -import de.sebse.fuplanner.services.NewKVV.types.Resource; +import de.sebse.fuplanner.services.KVV.Download; +import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.services.KVV.types.Resource; import de.sebse.fuplanner.tools.MainActivityListener; import de.sebse.fuplanner.tools.logging.Logger; import de.sebse.fuplanner.tools.ui.treeview.DirectoryNodeBinder; @@ -89,7 +89,7 @@ public class ModDetailResourceFragment extends Fragment { // Update and toggle the node. onToggle(!node.isExpand(), holder); } else if (node.getContent() instanceof Resource.File && ModDetailResourceFragment.this.mListener != null) { // if leaf is file - ModDetailResourceFragment.this.mListener.getNewKVV().modules().resources().recv(mItemPos, (Modules.Module module) -> { + ModDetailResourceFragment.this.mListener.getKVV().modules().resources().recv(mItemPos, (Modules.Module module) -> { String folderName = "FU-"+module.title.replaceAll("[:*<>|/\"\\\\]", "-"); Resource.File file = (Resource.File) node.getContent(); getDownload().openDownloadDialog(file, folderName); @@ -140,7 +140,7 @@ public class ModDetailResourceFragment extends Fragment { private void refresh(boolean forceRefresh) { if (mListener == null) return; - mListener.getNewKVV().modules().assignments().recv(mItemPos, success -> { + mListener.getKVV().modules().assignments().recv(mItemPos, success -> { adapter.setModule(success); swipeLayout.setRefreshing(false); }, error -> { diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/Download.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/Download.java index dab0fd3..98b21e0 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/Download.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/Download.java @@ -44,19 +44,20 @@ public class Download { } public void openDownloadDialog(Resource.File file, String folderName) { - if (contextInterface.get() == null) + Context context = contextInterface.get(); + if (context == null) return; - AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(contextInterface.get()); + AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context); File f = new File(Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_DOWNLOADS)+"/"+folderName+"/"+file.getTitle()); - Resources resources = contextInterface.get().getResources(); + Resources resources = context.getResources(); String message = ""; if (file.getAuthor() != null && !file.getAuthor().isEmpty()) message += resources.getString(R.string.creator_name, file.getAuthor()); if (file.getModifiedDate() != 0) { if (!message.isEmpty()) message += "\n"; - message += resources.getString(R.string.last_modified_on, UtilsDate.getModifiedDateTime(contextInterface.get(), file.getModifiedDate())); + message += resources.getString(R.string.last_modified_on, UtilsDate.getModifiedDateTime(context, file.getModifiedDate())); } alertDialogBuilder @@ -78,40 +79,46 @@ public class Download { } private void download(Resource.File file, String folderName, boolean downloadNew){ - if (activityInterface.get() == null) { + MainActivity activity = activityInterface.get(); + if (activity == null) { showDownloadError(); return; } - if (checkSelfPermission(activityInterface.get(), android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + if (checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { // Access granted downloadOrOpen(file, folderName, downloadNew); } else { this.requestedDownload = new RequestedDownload(file, folderName, downloadNew); - ActivityCompat.requestPermissions(activityInterface.get(), + ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1); } } private void downloadOrOpen(Resource.File file, String folderName, boolean downloadNew) { - KVV kvv = activityInterface.get().getKVV(); - if(isExternalStorageWritable()){ - kvv.getResourceFile(success1 -> { - // Downloading file failed - if (success1.equals("")){ - showDownloadError(); - }else { - if (Regex.has("^http", success1)){ - Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(success1)); - contextInterface.get().startActivity(intent); - } - else { - fileOpen(new File(success1)); - } - - } - }, log::e, file.getTitle(), file.getUrl(), folderName, downloadNew); + if (!isExternalStorageWritable()) { + return; } + MainActivity activity = activityInterface.get(); + if (activity == null) { + showDownloadError(); + return; + } + activity.getKVV().modules().resources().file(file.getTitle(), file.getUrl(), folderName, success -> { + Context context = contextInterface.get(); + if (success.equals("")) { + showDownloadError(); + } else { + if (Regex.has("^http", success)){ + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(success)); + context.startActivity(intent); + } + else { + fileOpen(new File(success)); + } + + } + }, log::e, downloadNew); } private void showDownloadError() { @@ -182,7 +189,6 @@ public class Download { } private void fileOpen(File url){ - Uri uri = FileProvider.getUriForFile(contextInterface.get(), contextInterface.get().getApplicationContext().getPackageName() + ".my.provider", url); Intent intent; 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 4420c01..b8d5eff 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 @@ -1,219 +1,47 @@ package de.sebse.fuplanner.services.KVV; import android.content.Context; -import android.util.Pair; -import java.io.IOException; -import java.util.ArrayList; +import org.jetbrains.annotations.NotNull; + import java.util.HashMap; -import androidx.annotation.NonNull; -import de.sebse.fuplanner.services.KVV.types.LoginToken; -import de.sebse.fuplanner.services.KVV.types.Modules; -import de.sebse.fuplanner.tools.MainActivityListener; -import de.sebse.fuplanner.tools.logging.Logger; -import de.sebse.fuplanner.tools.network.NetworkCallback; -import de.sebse.fuplanner.tools.network.NetworkErrorCallback; - -/** - * Created by sebastian on 29.10.17. - */ - public class KVV { - private final Context context; - private LoginToken lastToken; - private boolean isLoginPending = true; - private final ArrayList updatingList; private final HashMap addons = new HashMap<>(); - private final MainActivityListener mListener; - private Logger log = new Logger(this); + private final KVVListener mListener; + private final Context mContext; - public KVV(Context context) { - mListener = (MainActivityListener) context; - this.context = context; - this.updatingList = new ArrayList<>(); + public KVV(KVVListener listener, Context context) { + this.mListener = listener; + this.mContext = context; } - public boolean isLoggedIn() { - return this.lastToken != null; + @NotNull + public KVVLogin account() { + return (KVVLogin) addAndGet("account", () -> new KVVLogin(mListener, mContext)); } - public LoginToken easyLogin() { - KVVLogin login = new KVVLogin(this.context); - lastToken = login.easyLogin(); - this.endUpdate(); - return lastToken; + @NotNull + public KVVModules modules() { + return (KVVModules) addAndGet("module", () -> new KVVModules(account(), mContext)); } - public void login(@NonNull String username, @NonNull String password, final NetworkCallback callback, NetworkErrorCallback error) { - KVVLogin login = new KVVLogin(this.context); - login.login(username, password, success -> { - lastToken = success; - this.endUpdate(); - try { - login.saveOffline(); - } catch (IOException e) { - e.printStackTrace(); - } - callback.onResponse(success); - }, error1 -> { - this.endUpdate(); - error.onError(error1); - }); - } - public void logout() { - KVVModuleList modules = (KVVModuleList) addons.get("modules"); - if (modules != null) { - modules.deleteModulesOffline(this.context); + + + + + @NotNull + private Object addAndGet(@NotNull String addon, @NotNull ModuleCreatorInterface creatorInterface) { + Object o = addons.get(addon); + if (o == null) { + o = creatorInterface.create(); + addons.put(addon, o); } - invalidate(); + return o; } - public void invalidate() { - if (lastToken != null) { - new KVVLogin(context).deleteOffline(); - lastToken = null; - } - addons.clear(); - this.isLoginPending = true; - } - - public void getModule(String id, final NetworkCallback callback, final NetworkErrorCallback error) { - getModule(id, callback, error, false); - } - - public void getModule(String id, final NetworkCallback callback, final NetworkErrorCallback error, boolean forceRefresh) { - getModulePart(modules -> modules.getModule(id, saveOnCallback(modules, callback, forceRefresh), errorOnCallback(error), forceRefresh)); - } - - public void getModuleList(final NetworkCallback callback, final NetworkErrorCallback error) { - getModuleList(callback, error, false); - } - - public void getModuleList(final NetworkCallback callback, final NetworkErrorCallback error, boolean forceRefresh) { - getModulePart(modules -> modules.getModuleList(saveOnCallback(modules, callback, forceRefresh), errorOnCallback(error), forceRefresh)); - } - - public void getModuleDetails(Modules.Module module, final NetworkCallback> callback, final NetworkErrorCallback error) { - getModuleDetails(module, callback, error, false); - } - - public void getModuleDetails(Modules.Module module, final NetworkCallback> callback, final NetworkErrorCallback error, boolean forceRefresh) { - getModulePart(modules -> modules.getModuleDetails(module, saveOnCallback(modules, callback, forceRefresh), errorOnCallback(error), forceRefresh)); - } - - public void getModuleAnnouncements(Modules.Module module, final NetworkCallback callback, final NetworkErrorCallback error) { - getModuleAnnouncements(module, callback, error, false); - } - - public void getModuleAnnouncements(Modules.Module module, final NetworkCallback callback, final NetworkErrorCallback error, boolean forceRefresh) { - getModulePart(modules -> modules.getAnnouncements(module, saveOnCallback(modules, callback, forceRefresh), errorOnCallback(error), forceRefresh)); - } - - public void getModuleAssignments(Modules.Module module, final NetworkCallback callback, final NetworkErrorCallback error) { - getModuleAssignments(module, callback, error, false); - } - - public void getModuleAssignments(Modules.Module module, final NetworkCallback callback, final NetworkErrorCallback error, boolean forceRefresh) { - getModulePart(modules -> modules.getAssignments(module, saveOnCallback(modules, callback, forceRefresh), errorOnCallback(error), forceRefresh)); - } - - public void getModuleEvents(Modules.Module module, final NetworkCallback callback, final NetworkErrorCallback error) { - getModuleEvents(module, callback, error, false); - } - - public void getModuleEvents(Modules.Module module, final NetworkCallback callback, final NetworkErrorCallback error, boolean forceRefresh) { - getModulePart(modules -> modules.getEvents(module, saveOnCallback(modules, callback, forceRefresh), errorOnCallback(error), forceRefresh)); - } - - public void getModuleGradebook(Modules.Module module, final NetworkCallback callback, final NetworkErrorCallback error) { - getModuleGradebook(module, callback, error, false); - } - - public void getModuleGradebook(Modules.Module module, final NetworkCallback callback, final NetworkErrorCallback error, boolean forceRefresh) { - getModulePart(modules -> modules.getGradebook(module, saveOnCallback(modules, callback, forceRefresh), errorOnCallback(error), forceRefresh)); - } - - public void getModuleResources(Modules.Module module, final NetworkCallback callback, final NetworkErrorCallback error) { - getModuleResources(module, callback, error, false); - } - - public void getModuleResources(Modules.Module module, final NetworkCallback callback, final NetworkErrorCallback error, boolean forceRefresh) { - getModulePart(modules -> modules.getResources(module, saveOnCallback(modules, callback, forceRefresh), errorOnCallback(error), forceRefresh)); - } - - public void getResourceFile(final NetworkCallback callback, final NetworkErrorCallback error, String filename, String url, String moduleName, boolean downloadNew){ - getModulePart(modules -> modules.getResourceFile(callback, errorOnCallback(error),filename, url, moduleName, downloadNew)); - } - - public void testLogin(BooleanFunction callback) { - getLastToken(lastToken -> { - TestLogin.testLogin(context, lastToken, success -> callback.apply(true), error -> callback.apply(false)); - }); - } - - - - - - private void getModulePart(ModListFunction func) { - this.getLastToken(token -> { - KVVModuleList modules = (KVVModuleList) addons.get("modules"); - if (modules == null) { - modules = new KVVModuleList(this.context, token); - addons.put("modules", modules); - } - func.apply(modules); - }); - } - - private NetworkCallback saveOnCallback(KVVModuleList modules, NetworkCallback callback, boolean forceRefresh){ - return (success -> { - try { - modules.saveModulesOffline(this.context); - } catch (IOException e) { - e.printStackTrace(); - } - if (forceRefresh) - mListener.onRefreshCompleted(false); - callback.onResponse(success); - }); - } - - private NetworkErrorCallback errorOnCallback(NetworkErrorCallback errorCallback){ - return (error -> { - if (error.getHttpStatus() == 401 || error.getHttpStatus() == 403) - mListener.loginTokenInvalid(true); - else - mListener.onRefreshCompleted(true); - log.e(error); - errorCallback.onError(error); - }); - } - - @FunctionalInterface - interface ModListFunction { - void apply(KVVModuleList mod); - } - - @FunctionalInterface - public interface BooleanFunction { - void apply(boolean isSuccess); - } - - private void getLastToken(LastTokenCallback lastTokenCallback) { - if (this.isLoginPending) { - this.updatingList.add(lastTokenCallback); - } else { - lastTokenCallback.onReceived(this.lastToken); - } - } - - private void endUpdate() { - this.isLoginPending = false; - for (LastTokenCallback s: this.updatingList) { - s.onReceived(this.lastToken); - } + private interface ModuleCreatorInterface { + @NotNull Object create(); } } diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVListener.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVListener.java similarity index 79% rename from app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVListener.java rename to app/src/main/java/de/sebse/fuplanner/services/KVV/KVVListener.java index 2dd7a9b..ef5f73c 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVListener.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVListener.java @@ -1,7 +1,7 @@ -package de.sebse.fuplanner.services.NewKVV; +package de.sebse.fuplanner.services.KVV; import de.sebse.fuplanner.services.GoogleAuth.Credentials; -import de.sebse.fuplanner.services.NewKVV.types.LoginToken; +import de.sebse.fuplanner.services.KVV.types.LoginToken; import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkErrorCallback; diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVLogin.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVLogin.java index 03604a7..2960911 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVLogin.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVLogin.java @@ -2,69 +2,190 @@ package de.sebse.fuplanner.services.KVV; import android.content.Context; + +import org.jetbrains.annotations.NotNull; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.FileNotFoundException; import java.io.IOException; import java.util.HashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; +import androidx.annotation.Nullable; import de.sebse.fuplanner.services.KVV.types.LoginToken; import de.sebse.fuplanner.tools.network.HTTPService; import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkError; import de.sebse.fuplanner.tools.network.NetworkErrorCallback; -import static de.sebse.fuplanner.services.KVV.TestLogin.testLogin; +public class KVVLogin extends HTTPService { + private KVVListener mListener; + @Nullable private LoginToken mToken; + private boolean mLoginPending = false; + private boolean mOnlineMode = false; -/** - * Created by sebastian on 24.10.17. - */ - -class KVVLogin extends HTTPService { - private LoginToken loginToken; - - KVVLogin(Context context) { + KVVLogin(KVVListener listener, Context context) { super(context); + this.mListener = listener; + } + + public void doOnlineLogin(String username, String password, NetworkCallback callback, NetworkErrorCallback errorCallback) { + if (mLoginPending) { + errorCallback.onError(new NetworkError(100160, -1, "Login already pending!")); + } + mLoginPending = true; + doLogin(username, password, token -> { + testLoginToken(token, token2 -> { + setToken(token2, true); + mLoginPending = false; + callback.onResponse(token2); + }, error -> { + mLoginPending = false; + errorCallback.onError(error); + }); + }, error -> { + mLoginPending = false; + errorCallback.onError(error); + }); + } + + public boolean restoreOnlineLogin() { + return restoreLogin(true); + } + + public boolean doOfflineLogin() { + return restoreLogin(false); + } + + private boolean restoreLogin(boolean enteringOnlineMode) { + if (mLoginPending || mToken != null) + return false; + mLoginPending = true; + boolean result = false; try { - this.loginToken = LoginToken.load(context); + result = setToken(LoginToken.load(getContext()), enteringOnlineMode); + } catch (FileNotFoundException ignored) { } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } + mLoginPending = false; + return result; } - LoginToken easyLogin() { - return this.loginToken; + public boolean isOfflineStoredAvailable() { + try { + LoginToken.load(getContext()); + return true; + } catch (FileNotFoundException ignored) { + } catch (IOException e) { + e.printStackTrace(); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + return false; } - void login(String username, String password, NetworkCallback callback, NetworkErrorCallback errorCallback) { - if (this.loginToken != null) { - if (this.loginToken.getUsername().equals(username)) { - testLogin(getContext(), this.loginToken, success -> callback.onResponse(this.loginToken), error -> { - this.loginToken = null; - login(username, password, callback, errorCallback); - }); - } else { - this.loginToken = null; - login(username, password, callback, errorCallback); + public boolean logout(boolean delete) { + if (mLoginPending) + return false; + if (mToken == null) + return true; + if (delete) + mToken.delete(getContext()); + mToken = null; + return handleCallbacks(); + } + + public boolean isLoginPending() { + return mLoginPending; + } + + public boolean isLoggedIn() { + return mToken != null; + } + + public boolean isInOfflineMode() { + return isLoggedIn() && !mOnlineMode; + } + + public boolean isInOnlineMode() { + return isLoggedIn() && mOnlineMode; + } + + void testLoginToken(NetworkCallback callback, NetworkErrorCallback errorCallback) { + if (mToken == null) { + errorCallback.onError(new NetworkError(100173, -1, "Not logged in!")); + return; + } + testLoginToken(mToken, callback, errorCallback); + } + + private void testLoginToken(@NotNull LoginToken token, NetworkCallback callback, NetworkErrorCallback errorCallback) { + get(String.format("https://kvv.imp.fu-berlin.de/direct/profile/%s.json", token.getUsername()), token.getCookies(), response -> { + String body = response.getParsed(); + if (body == null) { + errorCallback.onError(new NetworkError(100172, 403, "Testing login failed!")); + return; } + try { + JSONObject json = new JSONObject(body); + String displayName = json.getString("displayName"); + String email = json.getString("email"); + token.setAdditionals(displayName, email); + callback.onResponse(token); + } catch (JSONException e) { + errorCallback.onError(new NetworkError(100171, 403, "Cannot parse profile!")); + } + }, error -> errorCallback.onError(new NetworkError(100170, error.networkResponse.statusCode, "Testing login failed!"))); + } + + @Nullable public LoginToken getLoginToken() { + return mToken; + } + + void refreshLogin(NetworkCallback success, NetworkErrorCallback error) { + mListener.getCredentials(credentials -> { + doOnlineLogin(credentials.getUsername(), credentials.getPassword(), success, error); + }, e -> { + logout(false); + error.onError(e); + }); + } + + + + private boolean handleCallbacks() { + if (mToken != null) { + mListener.handleLogin(mToken, mOnlineMode); + return true; } else { - doLogin(username, password, token -> { - this.loginToken = token; - testLogin(getContext(), this.loginToken, success -> callback.onResponse(this.loginToken), errorCallback); - }, errorCallback); + mListener.handleLogout(); + return false; } } - void deleteOffline() { - if (this.loginToken != null) - this.loginToken.delete(getContext()); + private boolean setToken(@Nullable LoginToken token, boolean enteringOnlineMode) { + if (token == null) + return false; + mToken = token; + if (enteringOnlineMode) { + try { + mToken.save(getContext()); + } catch (IOException e) { + e.printStackTrace(); + } + } + mOnlineMode = enteringOnlineMode; + return handleCallbacks(); } - void saveOffline() throws IOException { - if (this.loginToken != null) - this.loginToken.save(getContext()); - } + + + @@ -220,7 +341,7 @@ class KVVLogin extends HTTPService { errorCallback.onError(new NetworkError(100143, -1, "Error on getting SAML response!")); return; } - + HashMap object = new HashMap<>(); Pattern pattern = Pattern.compile("ss:mem:([0-9a-f]+)"); @@ -320,5 +441,3 @@ class KVVLogin extends HTTPService { return result; } } - - 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 deleted file mode 100644 index 5f5443f..0000000 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModuleList.java +++ /dev/null @@ -1,639 +0,0 @@ -package de.sebse.fuplanner.services.KVV; - -import android.content.Context; -import android.os.Build; -import android.os.Environment; -import android.text.Html; -import android.text.Spanned; -import android.util.Pair; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; -import java.util.regex.MatchResult; - -import de.sebse.fuplanner.services.KVV.types.Announcement; -import de.sebse.fuplanner.services.KVV.types.Assignment; -import de.sebse.fuplanner.services.KVV.types.AssignmentList; -import de.sebse.fuplanner.services.KVV.types.Event; -import de.sebse.fuplanner.services.KVV.types.EventList; -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.services.KVV.types.Resource; -import de.sebse.fuplanner.tools.AsyncQueue; -import de.sebse.fuplanner.tools.Regex; -import de.sebse.fuplanner.tools.network.HTTPService; -import de.sebse.fuplanner.tools.network.NetworkCallback; -import de.sebse.fuplanner.tools.network.NetworkError; -import de.sebse.fuplanner.tools.network.NetworkErrorCallback; -import de.sebse.fuplanner.tools.network.Result; - -import static de.sebse.fuplanner.services.KVV.TestLogin.testLogin; - -/** - * Created by sebastian on 29.10.17. - */ - -class KVVModuleList extends HTTPService { - private final LoginToken token; - private Modules moduleList; - private final AsyncQueue queueModuleDetails = new AsyncQueue(); - - KVVModuleList(Context context, LoginToken token) { - super(context); - this.token = token; - try { - Modules modules = Modules.load(context); - if (token == null || token.isSameUser(modules.getToken())) - this.moduleList = modules; - } catch (IOException e) { - e.printStackTrace(); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } - } - - - - - void getModuleList(final NetworkCallback callback, final NetworkErrorCallback errorCallback, boolean forceRefresh) { - queueModuleDetails.add("list", () -> { - if (this.moduleList != null && !forceRefresh) { - callback.onResponse(this.moduleList); - queueModuleDetails.next("list"); - return; - } - this.getModuleListUpgrade(success -> { - if (this.moduleList == null) - this.moduleList = success; - else - this.moduleList.updateList(success); - callback.onResponse(this.moduleList); - queueModuleDetails.next("list"); - }, queueModuleDetails.check("list", 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) { - errorCallback.onError(new NetworkError(101101, 403, "No module list retrieved!")); - return; - } - Modules modules = new Modules(token); - 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(fromHtml(description)); - String id = site.getString("id"); - modules.addModule(semester, lvNumbers, title, lecturers, type, description, id); - } - } 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; - } - // Empty module *may be* because token is invalid -> check - if (modules.size() == 0) - testLogin(getContext(), token, token -> callback.onResponse(modules), errorCallback); - else - callback.onResponse(modules); - }, error -> errorCallback.onError(new NetworkError(101104, error.networkResponse.statusCode, "Cannot get module list!"))); - } - - void deleteModulesOffline(Context context) { - if (this.moduleList != null) - this.moduleList.delete(context); - } - - void saveModulesOffline(Context context) throws IOException { - if (this.moduleList != null) - this.moduleList.save(context); - } - - void getModule(String id, final NetworkCallback callback, final NetworkErrorCallback errorCallback, boolean forceRefresh) { - this.getModuleList(success -> { - callback.onResponse(success.get(id)); - }, errorCallback, forceRefresh); - } - - - - - - - void getModuleDetails(Modules.Module module, final NetworkCallback> callback, final NetworkErrorCallback errorCallback, boolean forceRefresh) { - AtomicInteger returns = new AtomicInteger(0); - AtomicReference lastError = new AtomicReference<>(null); - final AtomicInteger items = new AtomicInteger(0); - NetworkCallback successCb = success -> { - returns.getAndIncrement(); - callback.onResponse(Pair.create(module, false)); - if (returns.get() == items.get()) { - callback.onResponse(Pair.create(module, true)); - if (lastError.get() != null) - errorCallback.onError(lastError.get()); - } - }; - NetworkErrorCallback errorCb = error -> { - lastError.set(error); - returns.getAndIncrement(); - if (returns.get() == items.get()) { - callback.onResponse(Pair.create(module, true)); - if (lastError.get() != null) - errorCallback.onError(lastError.get()); - } - }; - Runnable[] methods = { - () -> this.getAssignments(module, successCb, errorCb, forceRefresh), - () -> this.getEvents(module, successCb, errorCb, forceRefresh), - () -> this.getAnnouncements(module, successCb, errorCb, forceRefresh), - () -> this.getGradebook(module, successCb, errorCb, forceRefresh), - () -> this.getResources(module, successCb, errorCb, forceRefresh) - }; - items.set(methods.length); - for (Runnable method: methods) { - method.run(); - } - } - - - - - - - void getAnnouncements(Modules.Module module, final NetworkCallback callback, final NetworkErrorCallback errorCallback, boolean forceRefresh) { - queueModuleDetails.add(module.getID(), () -> { - if (module.announcements != null && !forceRefresh) { - callback.onResponse(module); - queueModuleDetails.next(module.getID()); - return; - } - getAnnouncementsUpgrade(module.getID(), success -> { - module.announcements = success; - callback.onResponse(module); - queueModuleDetails.next(module.getID()); - }, queueModuleDetails.check(module.getID(), errorCallback)); - }); - } - - private void getAnnouncementsUpgrade(String ID, final NetworkCallback> callback, final NetworkErrorCallback errorCallback) { - 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) { - errorCallback.onError(new NetworkError(101201, 403, "No announcements retrieved!")); - return; - } - ArrayList announcements = new ArrayList<>(); - try { - JSONObject json = new JSONObject(body); - JSONArray sites = json.getJSONArray("announcement_collection"); - - for (int i = 0; i < sites.length(); i++) { - JSONObject site = sites.getJSONObject(i); - String id = site.getString("announcementId"); - String title = site.getString("title"); - String text = site.getString("body"); - text = String.valueOf(fromHtml(text)); - String createdBy = site.getString("createdByDisplayName"); - long createdOn = site.getLong("createdOn"); - - - - // Extract attachment links - JSONArray attachments = site.getJSONArray("attachments"); - ArrayList urls = new ArrayList<>(); - for (int j =0; j check - if (announcements.size() == 0) - testLogin(getContext(), token, token -> callback.onResponse(announcements), errorCallback); - else - callback.onResponse(announcements); - }, error -> errorCallback.onError(new NetworkError(101203, error.networkResponse.statusCode, "Cannot get announcements!"))); - } - - - - - - void getAssignments(Modules.Module module, final NetworkCallback callback, final NetworkErrorCallback errorCallback, boolean forceRefresh) { - queueModuleDetails.add(module.getID(), () -> { - if (module.assignments != null && !forceRefresh) { - callback.onResponse(module); - queueModuleDetails.next(module.getID()); - return; - } - getAssignmentsUpgrade(module.getID(), success -> { - module.assignments = success; - callback.onResponse(module); - queueModuleDetails.next(module.getID()); - }, queueModuleDetails.check(module.getID(), errorCallback)); - }); - } - - 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) { - errorCallback.onError(new NetworkError(101301, 403, "No assignments retrieved!")); - return; - } - AssignmentList assignments = new AssignmentList(); - try { - JSONObject json = new JSONObject(body); - JSONArray sites = json.getJSONArray("assignment_collection"); - - for (int i = 0; i < sites.length(); i++) { - JSONObject site = sites.getJSONObject(i); - String id = site.getString("id"); - String title = site.getString("title"); - String instructions = site.getString("instructions"); - instructions = String.valueOf(fromHtml(instructions)); - long dueTime = site.getJSONObject("dueTime").getLong("time"); - String gradebookItemName = site.optString("gradebookItemName", null); - String gradeScale = site.getString("gradeScale"); - JSONArray attachments = site.getJSONArray("attachments"); - ArrayList urls = new ArrayList<>(); - for (int j = 0; j check - if (assignments.size() == 0) - testLogin(getContext(), token, token -> callback.onResponse(assignments), errorCallback); - else - callback.onResponse(assignments); - }, error -> errorCallback.onError(new NetworkError(101303, error.networkResponse.statusCode, "Cannot get assignments!"))); - - - } - - - - - - - void getEvents(Modules.Module module, final NetworkCallback callback, final NetworkErrorCallback errorCallback, boolean forceRefresh) { - queueModuleDetails.add(module.getID(), () -> { - if (module.events != null && !forceRefresh) { - callback.onResponse(module); - queueModuleDetails.next(module.getID()); - return; - } - getEventsUpgrade(module.getID(), success -> { - module.events = success; - callback.onResponse(module); - queueModuleDetails.next(module.getID()); - }, queueModuleDetails.check(module.getID(), errorCallback)); - }); - } - - private void getEventsUpgrade(String ID, final NetworkCallback callback, final NetworkErrorCallback errorCallback) { - 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?detailed=true", ID), token.getCookies(), response -> { - String body = response.getParsed(); - if (body == null) { - errorCallback.onError(new NetworkError(101401, 403, "No calendar retrieved!")); - return; - } - EventList events = new EventList(); - try { - JSONObject json = new JSONObject(body); - JSONArray sites = json.getJSONArray("calendar_collection"); - - for (int i = 0; i < sites.length(); i++) { - JSONObject site = sites.getJSONObject(i); - String id = site.getString("eventId"); - String type = site.getString("type"); - String title = site.getString("title"); - String siteId = site.getString("siteId"); - long duration = site.getLong("duration"); - long firstTime = site.getJSONObject("firstTime").getLong("time"); - String location = site.getString("location"); - events.add(new Event(id, type, title, duration, firstTime, siteId, location)); - } - } catch (JSONException e) { - e.printStackTrace(); - errorCallback.onError(new NetworkError(101402, 403, "Cannot parse calendar entries!")); - return; - } - events.sort(); - // Empty events *may be* because token is invalid -> check - if (events.size() == 0) - testLogin(getContext(), token, token -> callback.onResponse(events), errorCallback); - else - callback.onResponse(events); - }, error -> errorCallback.onError(new NetworkError(101403, error.networkResponse.statusCode, "Cannot get calendar entries!"))); - } - - - - - - void getGradebook(Modules.Module module, final NetworkCallback callback, final NetworkErrorCallback errorCallback, boolean forceRefresh) { - queueModuleDetails.add(module.getID(), () -> { - if (module.gradebook != null && !forceRefresh) { - callback.onResponse(module); - queueModuleDetails.next(module.getID()); - return; - } - getGradebookUpgrade(module.getID(), success -> { - module.gradebook = success; - callback.onResponse(module); - queueModuleDetails.next(module.getID()); - }, queueModuleDetails.check(module.getID(), errorCallback)); - }); - } - - private void getGradebookUpgrade(String ID, final NetworkCallback> callback, final NetworkErrorCallback errorCallback) { - if (token == null) { - errorCallback.onError(new NetworkError(101504, 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) { - errorCallback.onError(new NetworkError(101501, 403, "No assignments retrieved!")); - return; - } - ArrayList gradebook = new ArrayList<>(); - try { - JSONObject json = new JSONObject(body); - JSONArray sites = json.getJSONArray("assignments"); - - for (int i = 0; i < sites.length(); i++) { - JSONObject site = sites.getJSONObject(i); - double grade = site.optDouble("grade", 0); - String itemName = site.optString("itemName", null); - double maxPoints = site.optDouble("points", -1); - - gradebook.add(0, new Gradebook(itemName, grade, maxPoints)); - } - - }catch (JSONException e) { - e.printStackTrace(); - errorCallback.onError(new NetworkError(101502, 403, "Cannot parse gradebook for announcements!")); - return; - } - callback.onResponse(gradebook); - }, error -> errorCallback.onError(new NetworkError(101503, error.networkResponse.statusCode, "Cannot get gradebook for assignments!"))); - - } - - public void getResources(Modules.Module module, final NetworkCallback callback, final NetworkErrorCallback errorCallback, boolean forceRefresh) { - queueModuleDetails.add(module.getID(), () -> { - if (module.resources != null && !forceRefresh) { - callback.onResponse(module); - queueModuleDetails.next(module.getID()); - return; - } - getResourcesUpgrade(module.getID(), success -> { - module.resources = success; - callback.onResponse(module); - queueModuleDetails.next(module.getID()); - }, queueModuleDetails.check(module.getID(), errorCallback)); - }); - } - - private void getResourcesUpgrade(String ID, final NetworkCallback> callback, final NetworkErrorCallback errorCallback) { - if (token == null) { - errorCallback.onError(new NetworkError(101604, 500, "Currently running in offline mode!")); - return; - } - get(String.format("https://kvv.imp.fu-berlin.de/direct/content/site/%s.json", ID ), token.getCookies(), response ->{ - String body = response.getParsed(); - if (body == null) { - errorCallback.onError(new NetworkError(101601, 403, "No resources retrieved!")); - return; - } - ArrayList resources = new ArrayList<>(); - try { - JSONObject json = new JSONObject(body); - JSONArray sites = json.getJSONArray("content_collection"); - - for (int i = 0; i < sites.length(); i++) { - JSONObject site = sites.getJSONObject(i); - String author = site.getString("author"); - String title = site.getString("title"); - long modifiedDate = site.getLong("modifiedDate"); - String url = site.getString("url"); - boolean visible = site.getBoolean("visible"); - String type = site.getString("type"); - String container = site.getString("container"); - if (type.equals("collection")){ - resources.add(new Resource.Folder(author, title, modifiedDate, url, visible, container)); - } - else { - resources.add(new Resource.File(author, title, modifiedDate, url, visible, container, type)); - } - - } - - } catch (JSONException e) { - e.printStackTrace(); - errorCallback.onError(new NetworkError(101602, 403, "Cannot parse resources!")); - return; - } - - ArrayList root = new ArrayList<>(); - // Generate folder structure - for (Resource res: resources) { - if (!res.getContainer().equals("/content/group/")) { - if (res.getContainer().equals("/content/group/"+ID+"/")){ - // if file in root folder - root.add(res); - } else { - // in sub folder - for (Resource res2: resources) { - if (res2.getUrl().endsWith(res.getContainer()) && res2 instanceof Resource.Folder) { - // Append File/Folder to list - ((Resource.Folder) res2).add(res); - } - } - } - } - } - - // Empty resources *may be* because token is invalid -> check - if (root.size() == 0) - testLogin(getContext(), token, token -> callback.onResponse(root), errorCallback); - else - callback.onResponse(root); - - }, error -> errorCallback.onError(new NetworkError(101603, error.networkResponse.statusCode, "Cannot get resources!"))); - - } - - void getResourceFile(final NetworkCallback callback, final NetworkErrorCallback errorCallback, String Filename, String url, String moduleName, boolean downloadNew) { - if (isExternalStorageReadable()){ - File f = new File(Environment.getExternalStoragePublicDirectory( - Environment.DIRECTORY_DOWNLOADS)+"/"+moduleName+"/"+Filename); - // check if file already downloaded -> do not download again - if (f.exists() && !downloadNew) { - callback.onResponse(f.getPath()); - return; - } - } - getResourceFileUpgrade(Filename, url , moduleName, callback, errorCallback); - } - - private void getResourceFileUpgrade(String filename, String url , String moduleName, final NetworkCallback callback, final NetworkErrorCallback errorCallback) { - if (token == null) { - errorCallback.onError(new NetworkError(101701, 500, "Currently running in offline mode!")); - return; - } - - get(url, token.getCookies(), response ->{ - - - if (Regex.has("\\.[Uu][Rr][Ll]$", url)){ - // Return redirected URL - String path = response.getHeaders().get("Location"); - if (path == null){ - path = ""; - } - callback.onResponse(path); - } else if (response.getBytes()==null){ - testLogin(getContext(), token, token -> { - if (isExternalStorageWritable()) { - // try to download file again - get(url, token.getCookies(), response2 -> { - String path = saveFileInDownloads(filename, response2, moduleName); - callback.onResponse(path); - }, error -> errorCallback.onError(new NetworkError(101705, error.networkResponse.statusCode, "Cannot get file!"))); - } else { - errorCallback.onError(new NetworkError(101703, 403, "External storage not writable!")); - } - }, errorCallback); - } else if (isExternalStorageWritable()) { - String path = saveFileInDownloads(filename, response, moduleName); - callback.onResponse(path); - } else { - errorCallback.onError(new NetworkError(101704, 403, "External storage not writable!")); - } - }, error -> errorCallback.onError(new NetworkError(101702, error.networkResponse.statusCode, "Cannot get file!"))); - - - } - - - - - - - - /* Checks if external storage is available for read and write */ - private boolean isExternalStorageWritable() { - String state = Environment.getExternalStorageState(); - if (Environment.MEDIA_MOUNTED.equals(state)) { - return true; - } - log.w("File system: Writing not possible!"); - return false; - } - - /* Checks if external storage is available to at least read */ - private boolean isExternalStorageReadable() { - String state = Environment.getExternalStorageState(); - if (Environment.MEDIA_MOUNTED.equals(state) || - Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) { - return true; - } - log.w("File system: Reading not possible!"); - return false; - } - private String saveFileInDownloads(String filename, Result fileResult, String moduleName) { - // Saves file in folder: DOWNLOADS/moduleName - File folder = new File(Environment.getExternalStoragePublicDirectory( - Environment.DIRECTORY_DOWNLOADS), moduleName); - if (!folder.mkdir()) { - log.w( "Directory not created"); - } - String path = ""; - try { - // TODO check if enough storage space is available - FileOutputStream out = new FileOutputStream(folder.getPath()+"/"+filename); - out.write(fileResult.getBytes()); - out.close(); - path = folder.getPath()+"/"+filename; - } catch (Exception e) { - log.w("File not saved!"); - e.printStackTrace(); - } - return path; - } - - @SuppressWarnings("deprecation") - public static Spanned fromHtml(String html){ - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - return Html.fromHtml(html, Html.FROM_HTML_MODE_LEGACY); - } else { - return Html.fromHtml(html); - } - } - - -} diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModules.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModules.java similarity index 98% rename from app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModules.java rename to app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModules.java index 7adbe0b..9ea60be 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModules.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModules.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.NewKVV; +package de.sebse.fuplanner.services.KVV; import android.content.Context; diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesAnnouncements.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesAnnouncements.java similarity index 95% rename from app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesAnnouncements.java rename to app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesAnnouncements.java index af57532..60a6368 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesAnnouncements.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesAnnouncements.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.NewKVV; +package de.sebse.fuplanner.services.KVV; import android.content.Context; @@ -8,8 +8,8 @@ import org.json.JSONObject; import java.util.ArrayList; -import de.sebse.fuplanner.services.NewKVV.types.Announcement; -import de.sebse.fuplanner.services.NewKVV.types.Modules; +import de.sebse.fuplanner.services.KVV.types.Announcement; +import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkError; import de.sebse.fuplanner.tools.network.NetworkErrorCallback; diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesAssignments.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesAssignments.java similarity index 94% rename from app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesAssignments.java rename to app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesAssignments.java index 0863e32..0db727c 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesAssignments.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesAssignments.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.NewKVV; +package de.sebse.fuplanner.services.KVV; import android.content.Context; @@ -8,9 +8,9 @@ import org.json.JSONObject; import java.util.ArrayList; -import de.sebse.fuplanner.services.NewKVV.types.Assignment; -import de.sebse.fuplanner.services.NewKVV.types.AssignmentList; -import de.sebse.fuplanner.services.NewKVV.types.Modules; +import de.sebse.fuplanner.services.KVV.types.Assignment; +import de.sebse.fuplanner.services.KVV.types.AssignmentList; +import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkError; import de.sebse.fuplanner.tools.network.NetworkErrorCallback; diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesDetails.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesDetails.java similarity index 94% rename from app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesDetails.java rename to app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesDetails.java index ac3e270..b110e86 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesDetails.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesDetails.java @@ -1,11 +1,11 @@ -package de.sebse.fuplanner.services.NewKVV; +package de.sebse.fuplanner.services.KVV; import android.content.Context; import android.util.Pair; import java.util.concurrent.atomic.AtomicReference; -import de.sebse.fuplanner.services.NewKVV.types.Modules; +import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkError; import de.sebse.fuplanner.tools.network.NetworkErrorCallback; diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesEvents.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesEvents.java similarity index 93% rename from app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesEvents.java rename to app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesEvents.java index 4673090..0ff9376 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesEvents.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesEvents.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.NewKVV; +package de.sebse.fuplanner.services.KVV; import android.content.Context; @@ -6,9 +6,9 @@ import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; -import de.sebse.fuplanner.services.NewKVV.types.Event; -import de.sebse.fuplanner.services.NewKVV.types.EventList; -import de.sebse.fuplanner.services.NewKVV.types.Modules; +import de.sebse.fuplanner.services.KVV.types.Event; +import de.sebse.fuplanner.services.KVV.types.EventList; +import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkError; import de.sebse.fuplanner.tools.network.NetworkErrorCallback; diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesGradebook.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesGradebook.java similarity index 94% rename from app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesGradebook.java rename to app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesGradebook.java index 08d461e..b9137db 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesGradebook.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesGradebook.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.NewKVV; +package de.sebse.fuplanner.services.KVV; import android.content.Context; @@ -8,8 +8,8 @@ import org.json.JSONObject; import java.util.ArrayList; -import de.sebse.fuplanner.services.NewKVV.types.Grade; -import de.sebse.fuplanner.services.NewKVV.types.Modules; +import de.sebse.fuplanner.services.KVV.types.Grade; +import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkError; import de.sebse.fuplanner.tools.network.NetworkErrorCallback; diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesList.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesList.java similarity index 96% rename from app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesList.java rename to app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesList.java index dbb52ff..99a7d9c 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesList.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesList.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.NewKVV; +package de.sebse.fuplanner.services.KVV; import android.content.Context; @@ -12,8 +12,8 @@ import java.io.IOException; import java.util.HashSet; import java.util.regex.MatchResult; -import de.sebse.fuplanner.services.NewKVV.types.Lecturer; -import de.sebse.fuplanner.services.NewKVV.types.Modules; +import de.sebse.fuplanner.services.KVV.types.Lecturer; +import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.tools.NewAsyncQueue; import de.sebse.fuplanner.tools.Regex; import de.sebse.fuplanner.tools.network.HTTPService; @@ -21,7 +21,7 @@ import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkError; import de.sebse.fuplanner.tools.network.NetworkErrorCallback; -import static de.sebse.fuplanner.services.NewKVV.ModulesPart.RETRY_COUNT; +import static de.sebse.fuplanner.services.KVV.ModulesPart.RETRY_COUNT; public class KVVModulesList extends HTTPService { private final KVVLogin mLogin; @@ -68,7 +68,6 @@ public class KVVModulesList extends HTTPService { } void store() { - log.d("Save data"); if (this.mModules != null) { try { this.mModules.save(getContext()); diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesResources.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesResources.java similarity index 95% rename from app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesResources.java rename to app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesResources.java index 1598a5b..70bf58d 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVModulesResources.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesResources.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.NewKVV; +package de.sebse.fuplanner.services.KVV; import android.content.Context; import android.os.Environment; @@ -11,8 +11,8 @@ import java.io.File; import java.io.FileOutputStream; import java.util.ArrayList; -import de.sebse.fuplanner.services.NewKVV.types.Modules; -import de.sebse.fuplanner.services.NewKVV.types.Resource; +import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.services.KVV.types.Resource; import de.sebse.fuplanner.tools.Regex; import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkError; @@ -31,7 +31,7 @@ public class KVVModulesResources extends ModulesPart> { @Override protected boolean setPart(Modules.Module module, ArrayList part) { - boolean changed = module.assignments == null || module.assignments.hashCode() != part.hashCode(); + boolean changed = module.resources == null || module.resources.hashCode() != part.hashCode(); module.resources = part; return changed; } @@ -102,8 +102,8 @@ public class KVVModulesResources extends ModulesPart> { } } - // Empty assignments *may be* because token is invalid -> check - if (root.size() == 0) + // Empty resources *may be* because token is invalid -> check + if (resources.size() == 0) mLogin.testLoginToken(token -> callback.onResponse(root), errorCallback); else callback.onResponse(root); diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/LastTokenCallback.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/LastTokenCallback.java deleted file mode 100644 index 9740b1e..0000000 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/LastTokenCallback.java +++ /dev/null @@ -1,11 +0,0 @@ -package de.sebse.fuplanner.services.KVV; - -import de.sebse.fuplanner.services.KVV.types.LoginToken; - -/** - * Created by sebastian on 31.01.18. - */ - -interface LastTokenCallback { - void onReceived(LoginToken token); -} diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/ModulesPart.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesPart.java similarity index 93% rename from app/src/main/java/de/sebse/fuplanner/services/NewKVV/ModulesPart.java rename to app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesPart.java index f74ec97..ac1d4ad 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/ModulesPart.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesPart.java @@ -1,11 +1,11 @@ -package de.sebse.fuplanner.services.NewKVV; +package de.sebse.fuplanner.services.KVV; import android.content.Context; import android.os.Build; import android.text.Html; import android.text.Spanned; -import de.sebse.fuplanner.services.NewKVV.types.Modules; +import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.tools.NewAsyncQueue; import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkErrorCallback; @@ -45,11 +45,11 @@ abstract class ModulesPart extends Part { }); } + @SuppressWarnings("deprecation") static Spanned fromHtml(String html){ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { return Html.fromHtml(html, Html.FROM_HTML_MODE_LEGACY); } else { - //noinspection deprecation return Html.fromHtml(html); } } diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/Part.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/Part.java similarity index 93% rename from app/src/main/java/de/sebse/fuplanner/services/NewKVV/Part.java rename to app/src/main/java/de/sebse/fuplanner/services/KVV/Part.java index 0521a9f..bb74ef5 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/Part.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/Part.java @@ -1,8 +1,8 @@ -package de.sebse.fuplanner.services.NewKVV; +package de.sebse.fuplanner.services.KVV; import android.content.Context; -import de.sebse.fuplanner.services.NewKVV.types.Modules; +import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.tools.network.HTTPService; import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkErrorCallback; diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/TestLogin.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/TestLogin.java deleted file mode 100644 index 48c9449..0000000 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/TestLogin.java +++ /dev/null @@ -1,38 +0,0 @@ -package de.sebse.fuplanner.services.KVV; - -import android.content.Context; - -import org.json.JSONException; -import org.json.JSONObject; - -import de.sebse.fuplanner.services.KVV.types.LoginToken; -import de.sebse.fuplanner.tools.network.HTTPService; -import de.sebse.fuplanner.tools.network.NetworkCallback; -import de.sebse.fuplanner.tools.network.NetworkError; -import de.sebse.fuplanner.tools.network.NetworkErrorCallback; - -final class TestLogin extends HTTPService { - - private TestLogin(Context context) { - super(context); - } - - static void testLogin(Context context, LoginToken loginToken, NetworkCallback callback, NetworkErrorCallback errorCallback) { - new TestLogin(context).get(String.format("https://kvv.imp.fu-berlin.de/direct/profile/%s.json", loginToken.getUsername()), loginToken.getCookies(), response -> { - String body = response.getParsed(); - if (body == null) { - errorCallback.onError(new NetworkError(100202, 403, "Testing login failed!")); - return; - } - try { - JSONObject json = new JSONObject(body); - String displayName = json.getString("displayName"); - String email = json.getString("email"); - loginToken.setAdditionals(displayName, email); - callback.onResponse(loginToken); - } catch (JSONException e) { - errorCallback.onError(new NetworkError(100201, 403, "Cannot parse profile!")); - } - }, error -> errorCallback.onError(new NetworkError(100200, error.networkResponse.statusCode, "Testing login failed!"))); - } -} diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Announcement.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Announcement.java index 4fb810e..72941a7 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Announcement.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Announcement.java @@ -1,5 +1,7 @@ package de.sebse.fuplanner.services.KVV.types; +import com.google.android.gms.common.internal.Objects; + import java.io.Serializable; import java.util.ArrayList; @@ -54,4 +56,9 @@ public class Announcement implements Serializable { "\nCreated on: "+getCreatedOn()+ "\nURLs: "+getUrls().toString(); } + + @Override + public int hashCode() { + return Objects.hashCode(getId(), getBody(), getCreatedBy(), getCreatedOn(), getTitle(), getUrls()); + } } diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Assignment.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Assignment.java index 6605b73..e24f57e 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Assignment.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Assignment.java @@ -1,5 +1,7 @@ package de.sebse.fuplanner.services.KVV.types; +import com.google.android.gms.common.internal.Objects; + import java.io.Serializable; import java.util.ArrayList; @@ -15,7 +17,6 @@ public class Assignment implements Serializable { this.title = title; this.dueTime = dueTime; this.urls = urls; - //this.grade = grade; this.instructions = instructions; } @@ -50,4 +51,9 @@ public class Assignment implements Serializable { "\nDue date: "+getDueDate()+ "\nInstructions: "+getInstructions().substring(0, Math.min(getInstructions().length(), 100)); } + + @Override + public int hashCode() { + return Objects.hashCode(getId(), getDueDate(), getInstructions(), getTitle(), getUrls()); + } } diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Event.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Event.java index 5b070b0..a88835d 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Event.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Event.java @@ -1,5 +1,7 @@ package de.sebse.fuplanner.services.KVV.types; +import com.google.android.gms.common.internal.Objects; + import java.io.Serializable; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; @@ -111,4 +113,9 @@ public class Event implements Serializable { "\nStart Date: "+getStartDate()+ "\nEnd date: "+getEndDate(); } + + @Override + public int hashCode() { + return Objects.hashCode(getId(), getType(), getStartDate(), getEndDate(), getTitle(), getLocation()); + } } diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Grade.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Grade.java similarity index 94% rename from app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Grade.java rename to app/src/main/java/de/sebse/fuplanner/services/KVV/types/Grade.java index d102d84..11ccd81 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Grade.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Grade.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.NewKVV.types; +package de.sebse.fuplanner.services.KVV.types; import com.google.android.gms.common.internal.Objects; diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Gradebook.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Gradebook.java deleted file mode 100644 index bf636cd..0000000 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Gradebook.java +++ /dev/null @@ -1,34 +0,0 @@ -package de.sebse.fuplanner.services.KVV.types; - -import java.io.Serializable; - -public class Gradebook implements Serializable { - private final String itemName; - private final double grade; - private final double maxPoints; - - public Gradebook(String itemName, double points, double maxPoints) { - this.itemName = itemName; - this.grade = points; - this.maxPoints = maxPoints; - } - - public double getMaxPoints() { - return maxPoints; - } - - public double getPoints() { - return grade; - } - - public String getItemName() { - return itemName; - } - - @Override - public String toString() { - return "Name: "+getItemName()+ - "\nPoints: "+ getPoints()+ - "\nMax points: "+getMaxPoints(); - } -} diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/LoginToken.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/LoginToken.java index 0bd58eb..8d5ce8f 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/LoginToken.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/LoginToken.java @@ -3,6 +3,7 @@ package de.sebse.fuplanner.services.KVV.types; import android.content.Context; import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; @@ -17,16 +18,14 @@ import androidx.annotation.Nullable; */ public class LoginToken implements Serializable { - private static final long EASY_LOGIN_TIME_MILLIS = 1000 * 60 * 60 * 300; - private static final String FILE_NAME = "LoginTokenSaving"; + private static final String FILE_NAME = "LoginTokenSaveFile"; private final String username; private final String shibsessionKey; private final String shibsessionName; private final String JSESSIONID; - private String fullName; - private String email; - private long saveDate = 0; + @Nullable private String fullName; + @Nullable private String email; public LoginToken(String username, String shibsessionKey, String shibsessionName, String JSESSIONID) { this.username = username; @@ -37,17 +36,20 @@ public class LoginToken implements Serializable { @Nullable public static LoginToken load(Context context) throws IOException, ClassNotFoundException { - FileInputStream fis = context.openFileInput(FILE_NAME); + FileInputStream fis; + try { + fis = context.openFileInput(FILE_NAME); + } catch (FileNotFoundException e) { + return null; + } ObjectInputStream is = new ObjectInputStream(fis); LoginToken loginToken = (LoginToken) is.readObject(); is.close(); fis.close(); - loginToken = (loginToken.saveDate > (System.currentTimeMillis() - EASY_LOGIN_TIME_MILLIS)) ? loginToken : null; return loginToken; } public void save(Context context) throws IOException { - saveDate = System.currentTimeMillis(); FileOutputStream fos = context.openFileOutput(FILE_NAME, Context.MODE_PRIVATE); ObjectOutputStream os = new ObjectOutputStream(fos); os.writeObject(this); @@ -96,8 +98,8 @@ public class LoginToken implements Serializable { return cookies; } - public boolean isSameUser(LoginToken token) { - return token != null && this.getUsername().equals(token.getUsername()); + public boolean isSameUser(String username) { + return this.getUsername().equals(username); } @Override 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 6c0f3d5..ec2652d 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 @@ -2,6 +2,8 @@ package de.sebse.fuplanner.services.KVV.types; import android.content.Context; +import org.jetbrains.annotations.NotNull; + import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; @@ -21,16 +23,16 @@ import androidx.annotation.Nullable; public class Modules implements Iterable, Serializable { private SortedListModule list; - private final LoginToken token; + private final String mUsername; //private transient Logger log = new Logger(this); - private static final String FILE_NAME = "ModuleListSaving"; + private static final String FILE_NAME = "ModuleListSaveFile"; - public Modules(LoginToken loginToken) { - this.token = loginToken; + public Modules(String username) { + this.mUsername = username; 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); } @@ -84,8 +86,8 @@ public class Modules implements Iterable, Serializable { context.deleteFile(FILE_NAME); } - public LoginToken getToken() { - return token; + public String getUsername() { + return mUsername; } public void updateList(Modules modules) { @@ -104,29 +106,24 @@ 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 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; if (gradebook != null) { - for (Gradebook g : gradebook){ + for (Grade g : gradebook){ maxPoint += g.getMaxPoints(); userPoint += g.getPoints(); } @@ -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/KVV/types/Resource.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Resource.java index 31ccb99..e4b1328 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Resource.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Resource.java @@ -1,5 +1,7 @@ package de.sebse.fuplanner.services.KVV.types; +import com.google.android.gms.common.internal.Objects; + import java.io.Serializable; import java.util.ArrayList; @@ -54,6 +56,11 @@ public abstract class Resource implements Serializable { public abstract TreeNode getTreeNode(); + @Override + public int hashCode() { + return Objects.hashCode(getAuthor(), getContainer(), getModifiedDate(), getTitle(), getUrl()); + } + public static class File extends Resource implements LayoutItemType { private final String type; diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/SortedListModule.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/SortedListModule.java index 412a208..bf306a5 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/SortedListModule.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/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); } } diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/Download.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/Download.java deleted file mode 100644 index 9ba73e2..0000000 --- a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/Download.java +++ /dev/null @@ -1,265 +0,0 @@ -package de.sebse.fuplanner.services.NewKVV; - -import android.Manifest; -import android.app.AlertDialog; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.res.Resources; -import android.net.Uri; -import android.os.Environment; - -import java.io.File; -import java.util.ArrayList; -import java.util.Arrays; - -import androidx.annotation.Nullable; -import androidx.core.app.ActivityCompat; -import androidx.core.content.FileProvider; -import de.sebse.fuplanner.MainActivity; -import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.NewKVV.KVV; -import de.sebse.fuplanner.services.NewKVV.types.Resource; -import de.sebse.fuplanner.tools.Regex; -import de.sebse.fuplanner.tools.RequestPermissionsResultListener; -import de.sebse.fuplanner.tools.UtilsDate; -import de.sebse.fuplanner.tools.logging.Logger; - -import static androidx.core.content.ContextCompat.checkSelfPermission; - -public class Download { - - private final ContextInterface contextInterface; - private final ActivityInterface activityInterface; - private RequestedDownload requestedDownload; - private Logger log = new Logger(this); - - - public Download(ContextInterface contextInterface, ActivityInterface activityInterface) { - this.contextInterface = contextInterface; - this.activityInterface = activityInterface; - } - - public void openDownloadDialog(String title, String url, String folderName) { - openDownloadDialog(new Resource.File("", title, 0, url, true, "", ""), folderName); - } - - public void openDownloadDialog(Resource.File file, String folderName) { - Context context = contextInterface.get(); - if (context == null) - return; - AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context); - File f = new File(Environment.getExternalStoragePublicDirectory( - Environment.DIRECTORY_DOWNLOADS)+"/"+folderName+"/"+file.getTitle()); - Resources resources = context.getResources(); - String message = ""; - if (file.getAuthor() != null && !file.getAuthor().isEmpty()) - message += resources.getString(R.string.creator_name, file.getAuthor()); - if (file.getModifiedDate() != 0) { - if (!message.isEmpty()) - message += "\n"; - message += resources.getString(R.string.last_modified_on, UtilsDate.getModifiedDateTime(context, file.getModifiedDate())); - } - - alertDialogBuilder - .setTitle(file.getTitle()) - .setMessage(message) - .setCancelable(true) - .setNeutralButton(R.string.close, (dialog, id) -> dialog.cancel()); - // if already downloaded, show open button - if (f.exists()) { - alertDialogBuilder - .setPositiveButton(R.string.download_again, (dialog, id) -> download(file, folderName, true)) - .setNegativeButton(R.string.openFile, (dialog, id) -> download(file, folderName, false)); - } else { - alertDialogBuilder - .setPositiveButton(R.string.download, (dialog, id) -> download(file, folderName, true)); - } - AlertDialog alertDialog = alertDialogBuilder.create(); - alertDialog.show(); - } - - private void download(Resource.File file, String folderName, boolean downloadNew){ - MainActivity activity = activityInterface.get(); - if (activity == null) { - showDownloadError(); - return; - } - if (checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { - // Access granted - downloadOrOpen(file, folderName, downloadNew); - } else { - this.requestedDownload = new RequestedDownload(file, folderName, downloadNew); - ActivityCompat.requestPermissions(activity, - new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, - 1); - } - } - - private void downloadOrOpen(Resource.File file, String folderName, boolean downloadNew) { - if (!isExternalStorageWritable()) { - return; - } - MainActivity activity = activityInterface.get(); - if (activity == null) { - showDownloadError(); - return; - } - activity.getNewKVV().modules().resources().file(file.getTitle(), file.getUrl(), folderName, success -> { - Context context = contextInterface.get(); - if (success.equals("")) { - showDownloadError(); - } else { - if (Regex.has("^http", success)){ - Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(success)); - context.startActivity(intent); - } - else { - fileOpen(new File(success)); - } - - } - }, log::e, downloadNew); - } - - private void showDownloadError() { - Context context = contextInterface.get(); - if (context == null) - return; - AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context); - alertDialogBuilder - .setTitle(R.string.ErrorFileDownload) - .setMessage( - R.string.ErrorFileDownloadText - ) - .setCancelable(true) - .setNeutralButton(R.string.close, (dialog, id) -> dialog.cancel()); - AlertDialog alertDialog = alertDialogBuilder.create(); - alertDialog.show(); - } - - public RequestPermissionsResultListener getRequestPermissionsResultListener() { - return (requestCode, permissions, grantResults) -> { - if (requestedDownload == null) { - log.d("No request"); - return; - } - if (activityInterface.get() == null) { - showDownloadError(); - return; - } - ArrayList intList = new ArrayList<>(); - for (int i : grantResults) - { - intList.add(i); - } - log.d(requestCode, Arrays.asList(permissions), intList); - int pos = Arrays.asList(permissions).indexOf("android.permission.WRITE_EXTERNAL_STORAGE"); - if (pos != -1) { - if (grantResults[pos] != -1) { - downloadOrOpen(requestedDownload.file, requestedDownload.folderName, requestedDownload.downloadNew); - } else { - log.d(requestedDownload, pos, grantResults[pos]); - showDownloadError(); - } - requestedDownload = null; - } - }; - } - - private class RequestedDownload { - Resource.File file; - String folderName; - boolean downloadNew; - - RequestedDownload(Resource.File file, String folderName, boolean downloadNew) { - this.file = file; - this.folderName = folderName; - this.downloadNew = downloadNew; - } - } - - /* Checks if external storage is available for read and write */ - private boolean isExternalStorageWritable() { - String state = Environment.getExternalStorageState(); - if (Environment.MEDIA_MOUNTED.equals(state)) { - return true; - } - log.e("File system: Writing not possible"); - return false; - } - - private void fileOpen(File url){ - Uri uri = FileProvider.getUriForFile(contextInterface.get(), contextInterface.get().getApplicationContext().getPackageName() + ".my.provider", url); - - Intent intent; - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) { - intent = new Intent(Intent.ACTION_VIEW); - } else { - intent = new Intent(); - } - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); - // Check what kind of file you are trying to open, by comparing the url with extensions. - // When the if condition is matched, plugin sets the correct intent (mime) type, - // so Android knew what application to use to open the file - if (url.toString().contains(".doc") || url.toString().contains(".docx")) { - // Word document - intent.setDataAndType(uri, "application/msword"); - } else if(url.toString().contains(".pdf")) { - // PDF file - intent.setDataAndType(uri, "application/pdf"); - } else if(url.toString().contains(".ppt") || url.toString().contains(".pptx")) { - // Powerpoint file - intent.setDataAndType(uri, "application/vnd.ms-powerpoint"); - } else if(url.toString().contains(".xls") || url.toString().contains(".xlsx")) { - // Excel file - intent.setDataAndType(uri, "application/vnd.ms-excel"); - } else if(url.toString().contains(".zip") || url.toString().contains(".rar")) { - // ZIP file - intent.setDataAndType(uri, "application/zip"); - } else if(url.toString().contains(".rtf")) { - // RTF file - intent.setDataAndType(uri, "application/rtf"); - } else if(url.toString().contains(".wav") || url.toString().contains(".mp3")) { - // WAV audio file - intent.setDataAndType(uri, "audio/x-wav"); - } else if(url.toString().contains(".gif")) { - // GIF file - intent.setDataAndType(uri, "image/gif"); - } else if(url.toString().contains(".jpg") || url.toString().contains(".jpeg") || url.toString().contains(".png")) { - // JPG file - intent.setDataAndType(uri, "image/jpeg"); - } else if(url.toString().contains(".txt")) { - // Text file - intent.setDataAndType(uri, "text/plain"); - } else if(url.toString().contains(".3gp") || url.toString().contains(".mpg") || url.toString().contains(".mpeg") || url.toString().contains(".mpe") || url.toString().contains(".mp4") || url.toString().contains(".avi")) { - // Video files - intent.setDataAndType(uri, "video/*"); - } else { - //if you want you can also define the intent type for any other file - - //additionally use else clause below, to manage other unknown extensions - //in this case, Android will show all applications installed on the device - //so you can choose which application to use - intent.setDataAndType(uri, "*/*"); - } - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - contextInterface.get().startActivity(intent); - - } - - @FunctionalInterface - public interface ContextInterface { - @Nullable Context get(); - } - - @FunctionalInterface - public interface ActivityInterface { - @Nullable MainActivity get(); - } - - public interface OnDownloadRequestInterface { - void request(String title, String url); - } -} diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVV.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVV.java deleted file mode 100644 index ab63ebe..0000000 --- a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVV.java +++ /dev/null @@ -1,47 +0,0 @@ -package de.sebse.fuplanner.services.NewKVV; - -import android.content.Context; - -import org.jetbrains.annotations.NotNull; - -import java.util.HashMap; - -public class KVV { - private final HashMap addons = new HashMap<>(); - private final KVVListener mListener; - private final Context mContext; - - public KVV(KVVListener listener, Context context) { - this.mListener = listener; - this.mContext = context; - } - - @NotNull - public KVVLogin account() { - return (KVVLogin) addAndGet("account", () -> new KVVLogin(mListener, mContext)); - } - - @NotNull - public KVVModules modules() { - return (KVVModules) addAndGet("module", () -> new KVVModules(account(), mContext)); - } - - - - - - - @NotNull - private Object addAndGet(@NotNull String addon, @NotNull ModuleCreatorInterface creatorInterface) { - Object o = addons.get(addon); - if (o == null) { - o = creatorInterface.create(); - addons.put(addon, o); - } - return o; - } - - private interface ModuleCreatorInterface { - @NotNull Object create(); - } -} diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVLogin.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVLogin.java deleted file mode 100644 index 96b13e1..0000000 --- a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/KVVLogin.java +++ /dev/null @@ -1,443 +0,0 @@ -package de.sebse.fuplanner.services.NewKVV; - -import android.content.Context; - - -import org.jetbrains.annotations.NotNull; -import org.json.JSONException; -import org.json.JSONObject; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.HashMap; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import androidx.annotation.Nullable; -import de.sebse.fuplanner.services.NewKVV.types.LoginToken; -import de.sebse.fuplanner.tools.network.HTTPService; -import de.sebse.fuplanner.tools.network.NetworkCallback; -import de.sebse.fuplanner.tools.network.NetworkError; -import de.sebse.fuplanner.tools.network.NetworkErrorCallback; - -public class KVVLogin extends HTTPService { - private KVVListener mListener; - @Nullable private LoginToken mToken; - private boolean mLoginPending = false; - private boolean mOnlineMode = false; - - KVVLogin(KVVListener listener, Context context) { - super(context); - this.mListener = listener; - } - - public void doOnlineLogin(String username, String password, NetworkCallback callback, NetworkErrorCallback errorCallback) { - if (mLoginPending) { - errorCallback.onError(new NetworkError(100160, -1, "Login already pending!")); - } - mLoginPending = true; - doLogin(username, password, token -> { - testLoginToken(token, token2 -> { - setToken(token2, true); - mLoginPending = false; - callback.onResponse(token2); - }, error -> { - mLoginPending = false; - errorCallback.onError(error); - }); - }, error -> { - mLoginPending = false; - errorCallback.onError(error); - }); - } - - public boolean restoreOnlineLogin() { - return restoreLogin(true); - } - - public boolean doOfflineLogin() { - return restoreLogin(false); - } - - private boolean restoreLogin(boolean enteringOnlineMode) { - if (mLoginPending || mToken != null) - return false; - mLoginPending = true; - boolean result = false; - try { - result = setToken(LoginToken.load(getContext()), enteringOnlineMode); - } catch (FileNotFoundException ignored) { - } catch (IOException e) { - e.printStackTrace(); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } - mLoginPending = false; - return result; - } - - public boolean isOfflineStoredAvailable() { - try { - LoginToken.load(getContext()); - return true; - } catch (FileNotFoundException ignored) { - } catch (IOException e) { - e.printStackTrace(); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } - return false; - } - - public boolean logout(boolean delete) { - if (mLoginPending) - return false; - if (mToken == null) - return true; - if (delete) - mToken.delete(getContext()); - mToken = null; - return handleCallbacks(); - } - - public boolean isLoginPending() { - return mLoginPending; - } - - public boolean isLoggedIn() { - return mToken != null; - } - - public boolean isInOfflineMode() { - return isLoggedIn() && !mOnlineMode; - } - - public boolean isInOnlineMode() { - return isLoggedIn() && mOnlineMode; - } - - void testLoginToken(NetworkCallback callback, NetworkErrorCallback errorCallback) { - if (mToken == null) { - errorCallback.onError(new NetworkError(100173, -1, "Not logged in!")); - return; - } - testLoginToken(mToken, callback, errorCallback); - } - - private void testLoginToken(@NotNull LoginToken token, NetworkCallback callback, NetworkErrorCallback errorCallback) { - get(String.format("https://kvv.imp.fu-berlin.de/direct/profile/%s.json", token.getUsername()), token.getCookies(), response -> { - String body = response.getParsed(); - if (body == null) { - errorCallback.onError(new NetworkError(100172, 403, "Testing login failed!")); - return; - } - try { - JSONObject json = new JSONObject(body); - String displayName = json.getString("displayName"); - String email = json.getString("email"); - token.setAdditionals(displayName, email); - callback.onResponse(token); - } catch (JSONException e) { - errorCallback.onError(new NetworkError(100171, 403, "Cannot parse profile!")); - } - }, error -> errorCallback.onError(new NetworkError(100170, error.networkResponse.statusCode, "Testing login failed!"))); - } - - @Nullable public LoginToken getLoginToken() { - return mToken; - } - - void refreshLogin(NetworkCallback success, NetworkErrorCallback error) { - mListener.getCredentials(credentials -> { - doOnlineLogin(credentials.getUsername(), credentials.getPassword(), success, error); - }, e -> { - logout(false); - error.onError(e); - }); - } - - - - private boolean handleCallbacks() { - if (mToken != null) { - mListener.handleLogin(mToken, mOnlineMode); - return true; - } else { - mListener.handleLogout(); - return false; - } - } - - private boolean setToken(@Nullable LoginToken token, boolean enteringOnlineMode) { - if (token == null) - return false; - mToken = token; - if (enteringOnlineMode) { - try { - mToken.save(getContext()); - } catch (IOException e) { - e.printStackTrace(); - } - } - mOnlineMode = enteringOnlineMode; - return handleCallbacks(); - } - - - - - - - - - - - private void doLogin(String username, String password, NetworkCallback callback, NetworkErrorCallback error) { - startKVVSession(success -> { - String kvvJSESSIONID = success.get("JSESSIONID"); - getSAMLRequest(kvvJSESSIONID, success1 -> startIdentSession(success1.get("Location"), success11 -> { - String identJSESSIONID = success11.get("JSESSIONID"); - String ident_idp_authn_lc_key = success11.get("_idp_authn_lc_key"); - String identROUTEID = success11.get("ROUTEID"); - loginIdent(true, username, password, identJSESSIONID, ident_idp_authn_lc_key, identROUTEID, success111 -> loginIdent(false, username, password, identJSESSIONID, ident_idp_authn_lc_key, identROUTEID, success11112 -> { - String ident_idp_session = success11112.get("_idp_session"); - getSAMLResponse(identJSESSIONID, ident_idp_authn_lc_key, identROUTEID, ident_idp_session, success1111 -> loginKVV(success1111.get("RelayState"), success1111.get("SAMLResponse"), kvvJSESSIONID, success111112 -> { - LoginToken token = new LoginToken(username, success111112.get("shibsessionKey"), success111112.get("shibsessionName"), kvvJSESSIONID); - finishKVVlogin(token, success11111 -> callback.onResponse(token), error); - }, error), error); - }, error), error); - }, error), error); - }, error); - } - - /* - GET https://kvv.imp.fu-berlin.de/portal/login - -> JSESSIONID 5c10406f-588c-4c16-96e9-c80d115417de.tomcat1 - */ - private void startKVVSession(final NetworkCallback> callback, final NetworkErrorCallback errorCallback) { - get("https://kvv.imp.fu-berlin.de/portal/login", null, response -> { - String cookies = response.getHeaders().get("Set-Cookie"); - if (cookies==null) { - errorCallback.onError(new NetworkError(100101, -1, "Error on starting KVV session!")); - return; - } - HashMap object; - try { - object = getCookie(cookies, new String[]{"JSESSIONID"}); - } catch (NoSuchFieldException e) { - errorCallback.onError(new NetworkError(100102, -1, "Error on starting KVV session!")); - return; - } - callback.onResponse(object); - }, error -> errorCallback.onError(new NetworkError(100100, error.networkResponse.statusCode, "Error on starting KVV session!"))); - } - - /* - GET https://kvv.imp.fu-berlin.de/sakai-login-tool/container - <- JSESSIONID - -> (Location-Header) https://identity.fu-berlin.de/idp-fub/profile/SAML2/Redirect/SSO - ?SAMLRequest=fZLLb.....Q8yre3X1IHwkJKE0Mnpy/V9TH4A - &RelayState=ss:mem:7ea01e29157b8bd906f7002176.....0d1a505f2c8bf - */ - private void getSAMLRequest(String JSESSIONID, final NetworkCallback> callback, final NetworkErrorCallback errorCallback) { - HashMap cookies = new HashMap<>(); - cookies.put("JSESSIONID", JSESSIONID); - get("https://kvv.imp.fu-berlin.de/sakai-login-tool/container", cookies, response -> { - String location = response.getHeaders().get("Location"); - if (location==null) { - errorCallback.onError(new NetworkError(100111, -1, "Error on getting SAML request!")); - return; - } - HashMap object = new HashMap<>(); - object.put("Location", location); - callback.onResponse(object); - }, error -> errorCallback.onError(new NetworkError(100110, error.networkResponse.statusCode, "Error on getting SAML request!"))); - } - - /* - GET https://identity.fu-berlin.de/idp-fub/profile/SAML2/Redirect/SSO - ?SAMLRequest=fZLLbsIwEEV/JfI+cWJAUIsgpbAoEi2IpF10UznxUKw6dupxaPn7hkdb2LD29bkzRzNGUeuGZ63fmjV8toA++K61QX58SEnrDLcCFXIjakDuK55njwvOopg3znpbWU2CDBGcV9ZMrcG2BpeD26kKnteLlGy9b5BT+rHbRapuok0bluC0MpEEmm9VWVoNfhshWnpgM7pa5gUJZt0wyogD9h+iJBiv/P6aomQTbtqSdhNtlIYzZg1SOag8zfMlCeazlLyNqpHsy1gO2V1fVsNBMuqJoUyAJaxXDUaiiyG2MDfohfEpYXEyDJM4ZKxgCe/FPI5fSbA6L36vjFTm/bal8hRC/lAUq/C02gs4PK7VBchkfHDNj8Xuwv5trPhVTiY3BeOf4DG96DmVNvypA89nK6tVtQ8yre3X1IHwkJKE0Mnpy/V9TH4A - &RelayState=ss:mem:7ea01e29157b8bd906f7002176213b6db5e1f45ebb88716a9820d1a505f2c8bf - -> JSESSIONID C4B6A428BA1F50746235D03F5D107A57 - -> _idp_authn_lc_key 57a6ae26067f374cc3d0ccfc47e27b04b47752d2a3d4eb2782af0d3994535395 - -> ROUTEID .1 - */ - private void startIdentSession(String url, final NetworkCallback> callback, final NetworkErrorCallback errorCallback) { - get(url, null, response -> { - String cookies = response.getHeaders().get("Set-Cookie"); - if (cookies==null) { - errorCallback.onError(new NetworkError(100121, -1, "Error on starting Ident session!")); - return; - } - HashMap object; - try { - object = getCookie(cookies, new String[]{"JSESSIONID", "_idp_authn_lc_key", "ROUTEID"}); - } catch (NoSuchFieldException e) { - errorCallback.onError(new NetworkError(100122, -1, "Error on starting Ident session!")); - return; - } - callback.onResponse(object); - }, error -> errorCallback.onError(new NetworkError(100120, error.networkResponse.statusCode, "Error on starting Ident session!"))); - } - - /* - POST https://identity.fu-berlin.de/idp-fub/Authn/UserPassword - <- j_username seedorf96 - <- j_password neinhieristpatrick - <- (Header-"Content-Type") application/x-www-form-urlencoded - <- JSESSIONID - <- _idp_authn_lc_key - <- ROUTEID - -> _idp_session OTMuMTkzLjg1LjMz|LQ==|OGYxOWI4MjA2NTQ4YWUwYzJkOWM4Mjk4YzcwZDMwZmJiZjBmMTdmMzkyZGU2OWIwY2JkNmZlNjlmNTRmNzBlMQ==|wLlzQal7VqyntmG2vLNn06wt8wQ= - */ - private void loginIdent(final boolean first, String username, String password, String JSESSIONID, String _idp_authn_lc_key, String ROUTEID, final NetworkCallback> callback, final NetworkErrorCallback errorCallback) { - HashMap cookies = new HashMap<>(); - cookies.put("JSESSIONID", JSESSIONID); - cookies.put("_idp_authn_lc_key", _idp_authn_lc_key); - cookies.put("ROUTEID", ROUTEID); - HashMap body = new HashMap<>(); - body.put("j_username", username); - body.put("j_password", password); - post("https://identity.fu-berlin.de/idp-fub/Authn/UserPassword", cookies, body, response -> { - if (first) { - callback.onResponse(new HashMap<>()); - return; - } - - String cookies1 = response.getHeaders().get("Set-Cookie"); - if (cookies1 ==null) { - errorCallback.onError(new NetworkError(100131, -1, "Error on logging in to Identity Server!")); - return; - } - HashMap object; - try { - object = getCookie(cookies1, new String[]{"_idp_session"}); - } catch (NoSuchFieldException e) { - errorCallback.onError(new NetworkError(100132, -1, "Error on logging in to Identity Server!")); - return; - } - callback.onResponse(object); - }, error -> errorCallback.onError(new NetworkError(100130, error.networkResponse.statusCode, "Error on logging in to Identity Server!"))); - } - - /* - GET https://identity.fu-berlin.de/idp-fub/profile/SAML2/Redirect/SSO - <- JSESSIONID - <- _idp_authn_lc_key - <- ROUTEID - <- _idp_session - -> (BODY) RelayState 7ea01e29157b8bd906f7002176213b6db5e1f45ebb88716a9820d1a505f2c8bf - -> (BODY) SAMLResponse PD94bWwgdmVyc2lvbj0...........wvc2FtbDJwOlJlc3BvbnNlPg== - */ - private void getSAMLResponse(String JSESSIONID, String _idp_authn_lc_key, String ROUTEID, String _idp_session, final NetworkCallback> callback, final NetworkErrorCallback errorCallback) { - HashMap cookies = new HashMap<>(); - cookies.put("JSESSIONID", JSESSIONID); - cookies.put("_idp_authn_lc_key", _idp_authn_lc_key); - cookies.put("ROUTEID", ROUTEID); - cookies.put("_idp_session", _idp_session); - get("https://identity.fu-berlin.de/idp-fub/profile/SAML2/Redirect/SSO", cookies, response -> { - String body = response.getParsed(); - if (body == null) { - errorCallback.onError(new NetworkError(100143, -1, "Error on getting SAML response!")); - return; - } - - HashMap object = new HashMap<>(); - - Pattern pattern = Pattern.compile("ss:mem:([0-9a-f]+)"); - Matcher matcher = pattern.matcher(body); - if (!matcher.find()) { - errorCallback.onError(new NetworkError(100142, -1, "Error on getting SAML response!")); - return; - } - object.put("RelayState", "ss:mem:"+matcher.group(1)); - - pattern = Pattern.compile("name=\"SAMLResponse\" value=\"([0-9a-zA-Z+]+=*)"); - matcher = pattern.matcher(body); - if (!matcher.find()) { - errorCallback.onError(new NetworkError(100141, -1, "Error on getting SAML response!")); - return; - } - object.put("SAMLResponse", matcher.group(1)); - - callback.onResponse(object); - }, error -> errorCallback.onError(new NetworkError(100140, error.networkResponse.statusCode, "Error on getting SAML response!"))); - } - - - /* - POST https://kvv.imp.fu-berlin.de/Shibboleth.sso/SAML2/POST - <- RelayState 7ea01e29157b8bd906f7002176213b6db5e1f45ebb88716a9820d1a505f2c8bf - <- SAMLResponse PD94bWwgdmVyc2lvbj0...........wvc2FtbDJwOlJlc3BvbnNlPg== - <- JSESSIONID - -> _shibsession_64656661756c7468747470733a2f2f6b76762e696d702e66752d6265726c696e2e64652f73686962626f6c657468 - _b1912c5a03d733a80bd3fee772bf68d4 - */ - private void loginKVV(String RelayState, String SAMLResponse, String JSESSIONID, final NetworkCallback> callback, final NetworkErrorCallback errorCallback) { - HashMap cookies = new HashMap<>(); - cookies.put("JSESSIONID", JSESSIONID); - HashMap body = new HashMap<>(); - body.put("RelayState", RelayState); - body.put("SAMLResponse", SAMLResponse); - post("https://kvv.imp.fu-berlin.de/Shibboleth.sso/SAML2/POST", cookies, body, response -> { - String cookies1 = response.getHeaders().get("Set-Cookie"); - if (cookies1 ==null) { - errorCallback.onError(new NetworkError(100151, -1, "Error on starting KVV session!")); - return; - } - HashMap object = new HashMap<>(); - - - Pattern pattern = Pattern.compile("(_shibsession_[0-9a-f]+)=([^;]+);"); - Matcher matcher = pattern.matcher(cookies1); - if (!matcher.find()) { - errorCallback.onError(new NetworkError(100152, -1, "Error on starting Ident session!")); - } - object.put("shibsessionKey", matcher.group(1)); - object.put("shibsessionName", matcher.group(2)); - - callback.onResponse(object); - }, error -> errorCallback.onError(new NetworkError(100150, error.networkResponse.statusCode, "Error on starting Ident session!"))); - } - - - /* - GET https://kvv.imp.fu-berlin.de/sakai-login-tool/container - <- JSESSIONID - <- _shibsession_64656661756c7468747470733a2f2f6b76762e696d702e66752d6265726c696e2e64652f73686962626f6c657468 - _b1912c5a03d733a80bd3fee772bf68d4 - */ - private void finishKVVlogin(LoginToken loginToken, final NetworkCallback> callback, final NetworkErrorCallback errorCallback) { - get("https://kvv.imp.fu-berlin.de/sakai-login-tool/container", loginToken.getCookies(), response -> callback.onResponse(new HashMap<>()), error -> errorCallback.onError(new NetworkError(100160, error.networkResponse.statusCode, "Cannot finish login process!"))); - } - - - - - - - - - - - - - private String getCookie(String cookies, String name) throws NoSuchFieldException { - Pattern pattern = Pattern.compile(name+"=([^;]+);"); - Matcher matcher = pattern.matcher(cookies); - if (!matcher.find()) { - log.e("GETcookie failed", name); - log.e("GETcookie failed", cookies); - throw new NoSuchFieldException(); - } - return matcher.group(1); - } - - private HashMap getCookie(String cookies, String[] names) throws NoSuchFieldException { - HashMap result = new HashMap<>(); - for (String name: names) { - result.put(name,this.getCookie(cookies, name)); - } - return result; - } -} diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Announcement.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Announcement.java deleted file mode 100644 index f25a6b7..0000000 --- a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Announcement.java +++ /dev/null @@ -1,64 +0,0 @@ -package de.sebse.fuplanner.services.NewKVV.types; - -import com.google.android.gms.common.internal.Objects; - -import java.io.Serializable; -import java.util.ArrayList; - -public class Announcement implements Serializable { - private final String id; - private final String title; - private final String body; - private final String createdBy; - private final long createdOn; - private final ArrayList urls; - - public Announcement(String id, String title, String body, String createdBy, long createdOn, ArrayList urls) { - - this.id = id; - this.title = title; - this.body = body; - this.createdBy = createdBy; - this.createdOn = createdOn; - this.urls = urls; - } - - public ArrayList getUrls() { - return urls; - } - - private String getId() { - return id; - } - - public String getTitle() { - return title; - } - - public String getBody() { - return body; - } - - public String getCreatedBy() { - return createdBy; - } - - public long getCreatedOn() { - return createdOn; - } - - @Override - public String toString() { - return "ID: "+getId()+ - "\nTitle: "+getTitle()+ - "\nBody length: "+getBody().length()+ - "\nCreated by: "+getCreatedBy()+ - "\nCreated on: "+getCreatedOn()+ - "\nURLs: "+getUrls().toString(); - } - - @Override - public int hashCode() { - return Objects.hashCode(getId(), getBody(), getCreatedBy(), getCreatedOn(), getTitle(), getUrls()); - } -} diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Assignment.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Assignment.java deleted file mode 100644 index cd6a824..0000000 --- a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Assignment.java +++ /dev/null @@ -1,59 +0,0 @@ -package de.sebse.fuplanner.services.NewKVV.types; - -import com.google.android.gms.common.internal.Objects; - -import java.io.Serializable; -import java.util.ArrayList; - -public class Assignment implements Serializable { - private final String id; - private final String title; - private final long dueTime; - private final ArrayList urls; - private final String instructions; - - public Assignment(String id, String title, long dueTime, String gradebookItemName, String gradeScale, ArrayList urls, String instructions) {//, String grade - this.id = id; - this.title = title; - this.dueTime = dueTime; - this.urls = urls; - this.instructions = instructions; - } - - private String getId() { - return id; - } - - public String getTitle() { - return title; - } - - public boolean isOpen() { - return dueTime > System.currentTimeMillis(); - } - - public long getDueDate() { - return dueTime; - } - - public ArrayList getUrls() { - return urls; - } - - public String getInstructions() { - return instructions; - } - - @Override - public String toString() { - return "ID: "+getId()+ - "\nTitle: "+getTitle()+ - "\nDue date: "+getDueDate()+ - "\nInstructions: "+getInstructions().substring(0, Math.min(getInstructions().length(), 100)); - } - - @Override - public int hashCode() { - return Objects.hashCode(getId(), getDueDate(), getInstructions(), getTitle(), getUrls()); - } -} diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/AssignmentList.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/AssignmentList.java deleted file mode 100644 index 969e03f..0000000 --- a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/AssignmentList.java +++ /dev/null @@ -1,16 +0,0 @@ -package de.sebse.fuplanner.services.NewKVV.types; - -import de.sebse.fuplanner.tools.DateSortedList; - -public class AssignmentList extends DateSortedList { - - @Override - public long getDateByItem(Assignment item) { - return item.getDueDate(); - } - - @Override - public boolean reversed() { - return true; - } -} diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Event.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Event.java deleted file mode 100644 index ee73985..0000000 --- a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Event.java +++ /dev/null @@ -1,114 +0,0 @@ -package de.sebse.fuplanner.services.NewKVV.types; - -import java.io.Serializable; -import java.nio.charset.StandardCharsets; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; - -import de.sebse.fuplanner.tools.ColorRGB; - -public class Event implements Serializable { - private final String siteId; - private final String id; - private final String type; - private final String title; - private final long duration; - private final long firstTime; - private final String location; - - public Event(String id, String type, String title, long duration, long firstTime, String siteId, String location) { - this.siteId = siteId; - this.id = id; - this.type = type; - this.title = title; - this.duration = duration; - this.firstTime = firstTime; - this.location = location - .replace(" Übungsraum", "") - .replace(" Konferenzraum", "") - .replace(" Seminarraum", ""); - } - - public String getId() { - return id; - } - - public String getTitle() { - return this.title; - } - - public String getType() { - return this.type; - } - - public long getStartDate() { - return this.firstTime; - } - - public long getEndDate() { - return this.firstTime+this.duration; - } - - public String getLocation() { - return location; - } - - public String getModuleId() { - return siteId; - } - - public ColorRGB getColor() { - MessageDigest digest; - try { - digest = MessageDigest.getInstance("SHA-256"); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - return null; - } - byte[] encodedHash; - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) { - encodedHash = digest.digest(siteId.getBytes(StandardCharsets.UTF_8)); - } else { - encodedHash = digest.digest(siteId.getBytes()); - } - int h = (0xff & encodedHash[0]) + (0xff & encodedHash[1]) * 255; - h = h * 360 / 0xffff; - //int s = 0xff & encodedHash[2]; - //s = s * 100 / 0xffff; - //int v = 0xff & encodedHash[3]; - //v = v * 100 / 0xffff; - - // range for more beautiful colors - h = h / 30 * 30; - int s = 100; - int v = 80; - - return hsvToRgb(h/360.0, s/100.0, v/100.0); - } - - private static ColorRGB hsvToRgb(double hue, double saturation, double value) { - int h = (int)(hue * 6); - double f = hue * 6 - h; - double p = value * (1 - saturation); - double q = value * (1 - f * saturation); - double t = value * (1 - (1 - f) * saturation); - - switch (h) { - case 0: return new ColorRGB(value, t, p); - case 1: return new ColorRGB(q, value, p); - case 2: return new ColorRGB(p, value, t); - case 3: return new ColorRGB(p, q, value); - case 4: return new ColorRGB(t, p, value); - case 5: return new ColorRGB(value, p, q); - default: throw new RuntimeException("Something went wrong when converting from HSV to RGB. Input was " + hue + ", " + saturation + ", " + value); - } - } - - @Override - public String toString() { - return "ID: "+getId()+ - "\nType: "+getType()+ - "\nStart Date: "+getStartDate()+ - "\nEnd date: "+getEndDate(); - } -} diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/EventList.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/EventList.java deleted file mode 100644 index 1c18424..0000000 --- a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/EventList.java +++ /dev/null @@ -1,16 +0,0 @@ -package de.sebse.fuplanner.services.NewKVV.types; - -import de.sebse.fuplanner.tools.DateSortedList; - -public class EventList extends DateSortedList { - - @Override - public long getDateByItem(Event item) { - return item.getEndDate(); - } - - @Override - public boolean reversed() { - return false; - } -} diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/GroupedEvents.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/GroupedEvents.java deleted file mode 100644 index 0911641..0000000 --- a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/GroupedEvents.java +++ /dev/null @@ -1,128 +0,0 @@ -package de.sebse.fuplanner.services.NewKVV.types; - - -import android.annotation.SuppressLint; - -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Collections; -import java.util.List; - -import androidx.annotation.NonNull; -import de.sebse.fuplanner.tools.logging.Logger; - -public class GroupedEvents { - private ArrayList arrayList = new ArrayList<>(); - private Logger log = new Logger(this); - - public void add(Event event) { - Calendar calendar = Calendar.getInstance(); - calendar.setTimeInMillis(event.getStartDate()); - long dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK); - for (Group group : arrayList) { - if (group.add(event)) { - return; - } - } - arrayList.add(new Group(event)); - } - - public List getGroups() { - return Collections.unmodifiableList(arrayList); - } - - public class Group { - private long firstDate; - private long lastDate; - private ArrayList skippedDates; - - private int dayOfWeek; - private long startTime; - private long duration; - - private Group(Event event) { - Calendar calendar = Calendar.getInstance(); - calendar.setTimeInMillis(event.getStartDate()); - dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK); - startTime = calendar.get(Calendar.HOUR_OF_DAY)*3600000+calendar.get(Calendar.MINUTE)*60000+calendar.get(Calendar.SECOND)*1000+calendar.get(Calendar.MILLISECOND); - duration = event.getEndDate()-event.getStartDate(); - - skippedDates = new ArrayList<>(); - calendar.set(Calendar.HOUR_OF_DAY, 0); - calendar.set(Calendar.MINUTE, 0); - calendar.set(Calendar.SECOND, 0); - calendar.set(Calendar.MILLISECOND, 0); - firstDate = calendar.getTimeInMillis(); - lastDate = firstDate; - } - - private boolean add(Event event) { - Calendar calendar = Calendar.getInstance(); - calendar.setTimeInMillis(event.getStartDate()); - int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK); - int startTime = calendar.get(Calendar.HOUR_OF_DAY)*3600000+calendar.get(Calendar.MINUTE)*60000+calendar.get(Calendar.SECOND)*1000+calendar.get(Calendar.MILLISECOND); - long length = event.getEndDate()-event.getStartDate(); - if (this.dayOfWeek != dayOfWeek || this.startTime != startTime || this.duration != length) - return false; - calendar.set(Calendar.HOUR_OF_DAY, 0); - calendar.set(Calendar.MINUTE, 0); - calendar.set(Calendar.SECOND, 0); - calendar.set(Calendar.MILLISECOND, 0); - long date = calendar.getTimeInMillis(); - if (date < firstDate) { - firstDate = addDays(firstDate, -7); - while (firstDate > date) { - skippedDates.add(firstDate); - firstDate = addDays(firstDate, -7); - } - } else if (date > lastDate) { - lastDate = addDays(lastDate, 7); - while (lastDate < date) { - skippedDates.add(lastDate); - lastDate = addDays(lastDate, 7); - } - } else { - skippedDates.remove(date); - } - return true; - } - - private long addDays(long timeInMillis, int days) { - Calendar calendar = Calendar.getInstance(); - calendar.setTimeInMillis(timeInMillis); - calendar.add(Calendar.DAY_OF_YEAR, days); - return calendar.getTimeInMillis(); - } - - public long getFirstDate() { - return firstDate; - } - - public long getLastDate() { - return lastDate; - } - - public List getSkippedDates() { - return Collections.unmodifiableList(skippedDates); - } - - public int getDayOfWeek() { - return dayOfWeek; - } - - public long getStartTime() { - return startTime; - } - - public long getDuration() { - return duration; - } - - @SuppressLint("DefaultLocale") - @NonNull - @Override - public String toString() { - return String.format("%d - %d - %d - %s", dayOfWeek, startTime, duration, skippedDates); - } - } -} diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Lecturer.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Lecturer.java deleted file mode 100644 index 31a2163..0000000 --- a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Lecturer.java +++ /dev/null @@ -1,41 +0,0 @@ -package de.sebse.fuplanner.services.NewKVV.types; - -import java.io.Serializable; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class Lecturer implements Serializable { - private final String firstName; - private final String surname; - private final String mail; - - public Lecturer(String parsableString) throws NoSuchFieldException { - Pattern pattern = Pattern.compile("([^|]*)\\|([^|]*)\\|([^|]*)\\|\\|", Pattern.DOTALL); - Matcher matcher = pattern.matcher(parsableString); - if (!matcher.find()) { - throw new NoSuchFieldException(); - } - this.firstName = matcher.group(1); - this.surname = matcher.group(2); - this.mail = matcher.group(3); - } - - private String getFirstName() { - return firstName; - } - - private String getSurname() { - return surname; - } - - private String getMail() { - return mail; - } - - @Override - public String toString() { - return "First name: "+ getFirstName()+ - "\nSurname: "+getSurname()+ - "\nMail: "+getMail(); - } -} diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/LoginToken.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/LoginToken.java deleted file mode 100644 index 99bac12..0000000 --- a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/LoginToken.java +++ /dev/null @@ -1,114 +0,0 @@ -package de.sebse.fuplanner.services.NewKVV.types; - -import android.content.Context; - -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; -import java.util.HashMap; - -import androidx.annotation.Nullable; - -/** - * Created by sebastian on 29.10.17. - */ - -public class LoginToken implements Serializable { - private static final String FILE_NAME = "LoginTokenSaveFile"; - - private final String username; - private final String shibsessionKey; - private final String shibsessionName; - private final String JSESSIONID; - @Nullable private String fullName; - @Nullable private String email; - - public LoginToken(String username, String shibsessionKey, String shibsessionName, String JSESSIONID) { - this.username = username; - this.shibsessionKey = shibsessionKey; - this.shibsessionName = shibsessionName; - this.JSESSIONID = JSESSIONID; - } - - @Nullable - public static LoginToken load(Context context) throws IOException, ClassNotFoundException { - FileInputStream fis; - try { - fis = context.openFileInput(FILE_NAME); - } catch (FileNotFoundException e) { - return null; - } - ObjectInputStream is = new ObjectInputStream(fis); - LoginToken loginToken = (LoginToken) is.readObject(); - is.close(); - fis.close(); - return loginToken; - } - - public void save(Context context) throws IOException { - FileOutputStream fos = context.openFileOutput(FILE_NAME, Context.MODE_PRIVATE); - ObjectOutputStream os = new ObjectOutputStream(fos); - os.writeObject(this); - os.close(); - fos.close(); - } - - public void delete(Context context) { - context.deleteFile(FILE_NAME); - } - - public void setAdditionals(String fullName, String email) { - this.fullName = fullName; - this.email = email; - } - - public String getUsername() { - return username; - } - - private String getShibsessionKey() { - return shibsessionKey; - } - - private String getShibsessionName() { - return shibsessionName; - } - - private String getJSESSIONID() { - return JSESSIONID; - } - - public String getFullName() { - return fullName; - } - - public String getEmail() { - return email; - } - - public HashMap getCookies() { - HashMap cookies = new HashMap<>(); - cookies.put("JSESSIONID", getJSESSIONID()); - cookies.put(getShibsessionKey(), getShibsessionName()); - cookies.put("pasystem_timezone_ok", "true"); - return cookies; - } - - public boolean isSameUser(String username) { - return this.getUsername().equals(username); - } - - @Override - public String toString() { - StringBuilder result = new StringBuilder(); - HashMap cookies = this.getCookies(); - for (String header: cookies.keySet()) { - result.append(header).append("=").append(cookies.get(header)).append(";"); - } - return result.substring(0, result.length()-1); - } -} 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 deleted file mode 100644 index a746e45..0000000 --- a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Modules.java +++ /dev/null @@ -1,168 +0,0 @@ -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; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Iterator; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -/** - * Created by sebastian on 29.10.17. - */ - -public class Modules implements Iterable, Serializable { - private SortedListModule list; - private final String mUsername; - //private transient Logger log = new Logger(this); - private static final String FILE_NAME = "ModuleListSaveFile"; - - public Modules(String username) { - this.mUsername = username; - this.list = new SortedListModule(); - } - - 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); - } - - @NonNull - @Override - public String toString() { - return this.list.toString(); - } - - @NonNull - @Override - public Iterator iterator() { - return this.list.iterator(); - } - - public Iterator latestSemesterIterator() { - return this.list.filteredIterator(this.list.getLatestSemester()); - } - - public int size() { - return this.list.size(); - } - - public Module get(String id) { - return this.list.getById(id); - } - - public Module getByIndex(int index) { - return this.list.get(index); - } - - public static Modules load(Context context) throws IOException, ClassNotFoundException { - FileInputStream fis = context.openFileInput(FILE_NAME); - ObjectInputStream is = new ObjectInputStream(fis); - Modules modules = (Modules) is.readObject(); - is.close(); - fis.close(); - return modules; - } - - public void save(Context context) throws IOException { - FileOutputStream fos = context.openFileOutput(FILE_NAME, Context.MODE_PRIVATE); - ObjectOutputStream os = new ObjectOutputStream(fos); - os.writeObject(this); - os.close(); - fos.close(); - } - - public void delete(Context context) { - context.deleteFile(FILE_NAME); - } - - public String getUsername() { - return mUsername; - } - - public void updateList(Modules modules) { - SortedListModule old = this.list; - this.list = modules.list; - for (Module oldModule : old) { - Module newModule = this.list.getById(oldModule.getID()); - if (newModule != null) { - newModule.announcements = oldModule.announcements; - newModule.assignments = oldModule.assignments; - newModule.events = oldModule.events; - newModule.gradebook = oldModule.gradebook; - newModule.resources = oldModule.resources; - } - } - } - - public class Module implements Serializable { - @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; - - public float getGradebookPercent(){ - float maxPoint = 0; - float userPoint = 0; - if (gradebook != null) { - for (Grade g : gradebook){ - maxPoint += g.getMaxPoints(); - userPoint += g.getPoints(); - } - } - if (maxPoint == 0) - return 0; - return userPoint/maxPoint; - } - - 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; - this.lvNumber = lvNumber; - this.title = title; - this.lecturer = lecturer; - this.type = type; - this.description = description; - this.ID = ID; - } - - @NonNull - public String getID() { - return ID; - } - - @NonNull - @Override - public String toString() { - return "Semester: "+semester+ - "\nlvNumber: "+lvNumber.toString()+ - "\ntitle: "+title+ - "\nlecturer: "+lecturer.toString()+ - "\ntype: "+type+ - "\nID: "+ID; - } - } -} diff --git a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Resource.java b/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Resource.java deleted file mode 100644 index 598cf69..0000000 --- a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/Resource.java +++ /dev/null @@ -1,134 +0,0 @@ -package de.sebse.fuplanner.services.NewKVV.types; - -import java.io.Serializable; -import java.util.ArrayList; - -import androidx.annotation.LayoutRes; -import de.sebse.fuplanner.R; -import de.sebse.fuplanner.tools.ui.treeview.LayoutItemType; -import de.sebse.fuplanner.tools.ui.treeview.TreeNode; - - -public abstract class Resource implements Serializable { - - final String author; - final long modifiedDate; - final String title; - final String url; - private final boolean visible; - private final String container; - - - Resource(String author, String title, long modifiedDate, String url, boolean visible, String container) { - this.author = author; - this.title = title; - this.modifiedDate = modifiedDate; - this.url = url; - this.visible = visible; - this.container = container; - } - - public String getAuthor() { - return author; - } - - public long getModifiedDate() { - return modifiedDate; - } - - public String getTitle() { - return title; - } - - public String getUrl() { - return url; - } - - public String getContainer() { - return container; - } - - public boolean isVisible() { - return visible; - } - - public abstract TreeNode getTreeNode(); - - public static class File extends Resource implements LayoutItemType { - private final String type; - - public File(String author, String title, long modifiedDate, String url, boolean visible, String container, String type) { - super(author, title, modifiedDate, url, visible, container); - this.type = type; - } - - @Override - public String toString() { - return "Resource{" + - "author='" + author + '\'' + - ", modifiedDate=" + modifiedDate + - ", title='" + title + '\'' + - ", url='" + url + '\'' + - ", type='" + type + '\'' + - '}'; - } - - @Override - public TreeNode getTreeNode() { - return new TreeNode<>(this); - } - - @Override - public @LayoutRes int getLayoutId() { - return R.layout.item_file; - } - } - - public static class Folder extends Resource implements LayoutItemType { - - private final ArrayList children; - public Folder(String author, String title, long modifiedDate, String url, boolean visible, String container) { - super(author, title, modifiedDate, url, visible, container); - children = new ArrayList<>(); - } - - public void add(Resource res){ - children.add(res); - } - - public Resource get(int id){ - return children.get(id); - } - - public int size(){ - return children.size(); - } - - @Override - public String toString() { - return "Resource{" + - "author='" + author + '\'' + - ", modifiedDate=" + modifiedDate + - ", title='" + title + '\'' + - ", url='" + url + '\'' + - ", children='" + children + '\'' + - '}'; - } - - @Override - public TreeNode getTreeNode() { - TreeNode dir = new TreeNode<>(this); - for (Resource res: children) { - dir.addChild(res.getTreeNode()); - } - return dir; - } - - @Override - public @LayoutRes int getLayoutId() { - return R.layout.item_dir; - } - } -} - - 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 deleted file mode 100644 index a12ba34..0000000 --- a/app/src/main/java/de/sebse/fuplanner/services/NewKVV/types/SortedListModule.java +++ /dev/null @@ -1,68 +0,0 @@ -package de.sebse.fuplanner.services.NewKVV.types; - -import de.sebse.fuplanner.tools.Regex; -import de.sebse.fuplanner.tools.SortedList; - -public class SortedListModule extends SortedList { - private static final int LARGER = 1; - private static final int EQUAL = 0; - private static final int SMALLER = -1; - - @Override - public int compare(Modules.Module o1, Modules.Module o2) { - int semester; - try { - semester = -compareSemester(o1.semester, o2.semester); - } catch (NoSuchFieldException e) { - e.printStackTrace(); - semester = EQUAL; - } - if (semester != EQUAL) - return semester; - return o1.title.compareToIgnoreCase(o2.title); - } - - @Override - public void add(Modules.Module e) { - super.add(e); - } - - public String getLatestSemester() { - if (size() > 0) - //noinspection ConstantConditions - return this.get(0).semester; - else - return null; - } - - private static int compareSemester(String a, String b) throws NoSuchFieldException { - if (a == null && b == null) - return EQUAL; - if (a == null) - return SMALLER; - if (b == null) - return LARGER; - - String s1type = Regex.regex("^(S|WS) ", a); - int s1year = Integer.parseInt(Regex.regex("^(S|WS) ([0-9]{2})", a, 2)); - String s2type = Regex.regex("^(S|WS) ", b); - int s2year = Integer.parseInt(Regex.regex("^(S|WS) ([0-9]{2})", b, 2)); - - if (s1year == s2year) { - if (s1type.equals(s2type)) - return EQUAL; - return s1type.equals("S") ? SMALLER : LARGER; - } - return s1year < s2year ? SMALLER : LARGER; - } - - @Override - public boolean hasIdentifier(Modules.Module o1, String id) { - return o1.getID().equals(id); - } - - @Override - public boolean hasFilter(Modules.Module o1, String filter) { - return o1.semester != null && o1.semester.equals(filter); - } -} diff --git a/app/src/main/java/de/sebse/fuplanner/tools/MainActivityListener.java b/app/src/main/java/de/sebse/fuplanner/tools/MainActivityListener.java index ce8977c..e41fe62 100644 --- a/app/src/main/java/de/sebse/fuplanner/tools/MainActivityListener.java +++ b/app/src/main/java/de/sebse/fuplanner/tools/MainActivityListener.java @@ -15,15 +15,10 @@ public interface MainActivityListener { void showToast(@StringRes int msgStringRes); - @Deprecated KVV getKVV(); - de.sebse.fuplanner.services.NewKVV.KVV getNewKVV(); - GoogleAuth getGoogleAuth(); - void loginTokenInvalid(boolean doLoginCheck); - void onRefreshCompleted(boolean isFailed); CanteenBrowser getCanteenBrowser(); diff --git a/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/DirectoryNodeBinder.java b/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/DirectoryNodeBinder.java index 9cae51b..9a2ac9c 100644 --- a/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/DirectoryNodeBinder.java +++ b/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/DirectoryNodeBinder.java @@ -5,7 +5,7 @@ import android.widget.ImageView; import android.widget.TextView; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.NewKVV.types.Resource; +import de.sebse.fuplanner.services.KVV.types.Resource; /** * Created by tlh on 2016/10/1 :) diff --git a/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/FileNodeBinder.java b/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/FileNodeBinder.java index a89af39..f337b37 100644 --- a/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/FileNodeBinder.java +++ b/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/FileNodeBinder.java @@ -4,7 +4,7 @@ import android.view.View; import android.widget.TextView; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.NewKVV.types.Resource; +import de.sebse.fuplanner.services.KVV.types.Resource; /** * Created by tlh on 2016/10/1 :) From cceb317457e77694c2b54d8dde789fef4a7ea4a4 Mon Sep 17 00:00:00 2001 From: Caesar2011 Date: Fri, 9 Nov 2018 21:17:21 +0100 Subject: [PATCH 08/17] Bug Fixes --- .../java/de/sebse/fuplanner/MainActivity.java | 32 +++++++------------ .../fuplanner/fragments/LoginFragment.java | 2 +- .../de/sebse/fuplanner/services/KVV/KVV.java | 2 +- .../fuplanner/services/KVV/KVVListener.java | 2 ++ .../fuplanner/services/KVV/KVVLogin.java | 7 ++-- .../fuplanner/services/KVV/KVVModules.java | 6 ++-- .../services/KVV/KVVModulesList.java | 5 ++- .../services/KVV/types/LoginToken.java | 7 ++-- .../fuplanner/services/KVV/types/Modules.java | 7 ++-- 9 files changed, 37 insertions(+), 33 deletions(-) diff --git a/app/src/main/java/de/sebse/fuplanner/MainActivity.java b/app/src/main/java/de/sebse/fuplanner/MainActivity.java index 1ee0b22..7e6cd53 100644 --- a/app/src/main/java/de/sebse/fuplanner/MainActivity.java +++ b/app/src/main/java/de/sebse/fuplanner/MainActivity.java @@ -37,6 +37,7 @@ 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.KVVListener; +import de.sebse.fuplanner.services.KVV.types.LoginToken; import de.sebse.fuplanner.tools.MainActivityListener; import de.sebse.fuplanner.tools.RequestPermissionsResultListener; import de.sebse.fuplanner.tools.logging.Logger; @@ -65,7 +66,7 @@ public class MainActivity extends AppCompatActivity private FragmentManager mFragmentManager; private GoogleAuth mGoogleAuth; - private KVV mNewKVV; + private KVV mKVV; private final Logger log = new Logger(this); private NavigationView mNavigationView; @@ -247,10 +248,10 @@ public class MainActivity extends AppCompatActivity }*/ public KVV getKVV() { - if (this.mNewKVV == null) { - this.mNewKVV = new KVV(this, this); + if (this.mKVV == null) { + this.mKVV = new KVV(this, this); } - return this.mNewKVV; + return this.mKVV; } public CanteenBrowser getCanteenBrowser() { @@ -487,22 +488,6 @@ public class MainActivity extends AppCompatActivity setTitle(titleId); } - /*+++@Deprecated - @Override - public void loginTokenInvalid(boolean doLoginCheck) { - if (doLoginCheck) { - getKVV().testLogin(isSuccess -> { - if (!isSuccess) { - getKVV().invalidate(); - checkAndDoLogin(); - } - }); - } else { - getKVV().invalidate(); - checkAndDoLogin(); - } - }*/ - @Override public void onRefreshCompleted(boolean isFailed) { setRefreshFailedBanner(isFailed); @@ -549,7 +534,7 @@ public class MainActivity extends AppCompatActivity } @Override - public void handleLogin(de.sebse.fuplanner.services.KVV.types.LoginToken token, boolean enteringOnlineMode) { + public void handleLogin(LoginToken token, boolean enteringOnlineMode) { toLoginState(token.getUsername(), token.getEmail(), getDefaultFragmentAfterLogin(), "", enteringOnlineMode); } @@ -557,4 +542,9 @@ public class MainActivity extends AppCompatActivity public void handleLogout() { toLogoutState(); } + + @Override + public void onModuleListChange() { + updateNavigation(); + } } 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 693e63f..a481e4f 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/LoginFragment.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/LoginFragment.java @@ -47,7 +47,7 @@ public class LoginFragment extends Fragment { Bundle savedInstanceState) { // Inflate the layout for this fragment View v = inflater.inflate(R.layout.fragment_login, container, false); - if (mActivityListener != null && mActivityListener.getKVV().modules().list().stored()) { + if (mActivityListener != null && mActivityListener.getKVV().account().isOfflineStoredAvailable()) { 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, mActivityListener.getKVV().modules().list().getUsername())); 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 b8d5eff..ae279d5 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 @@ -23,7 +23,7 @@ public class KVV { @NotNull public KVVModules modules() { - return (KVVModules) addAndGet("module", () -> new KVVModules(account(), mContext)); + return (KVVModules) addAndGet("module", () -> new KVVModules(account(), mListener, mContext)); } diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVListener.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVListener.java index ef5f73c..5304f33 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVListener.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVListener.java @@ -11,4 +11,6 @@ public interface KVVListener { void handleLogin(LoginToken token, boolean enteringOnlineMode); void handleLogout(); + + void onModuleListChange(); } diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVLogin.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVLogin.java index 2960911..945bf50 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVLogin.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVLogin.java @@ -78,8 +78,8 @@ public class KVVLogin extends HTTPService { public boolean isOfflineStoredAvailable() { try { - LoginToken.load(getContext()); - return true; + LoginToken load = LoginToken.load(getContext()); + return load != null; } catch (FileNotFoundException ignored) { } catch (IOException e) { e.printStackTrace(); @@ -171,6 +171,7 @@ public class KVVLogin extends HTTPService { private boolean setToken(@Nullable LoginToken token, boolean enteringOnlineMode) { if (token == null) return false; + boolean isOnlyRefresh = mToken != null; mToken = token; if (enteringOnlineMode) { try { @@ -180,7 +181,7 @@ public class KVVLogin extends HTTPService { } } mOnlineMode = enteringOnlineMode; - return handleCallbacks(); + return isOnlyRefresh || handleCallbacks(); } diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModules.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModules.java index 9ea60be..8f8e456 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModules.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModules.java @@ -10,10 +10,12 @@ public class KVVModules { private final HashMap mAddons = new HashMap<>(); private KVVModulesList mList = null; private final KVVLogin mLogin; + private KVVListener mListener; private final Context context; - KVVModules(KVVLogin login, Context context) { + KVVModules(KVVLogin login, KVVListener listener, Context context) { this.mLogin = login; + this.mListener = listener; this.context = context; } @@ -53,7 +55,7 @@ public class KVVModules { @NotNull public KVVModulesList list() { if (mList == null) { - mList = new KVVModulesList(mLogin, context); + mList = new KVVModulesList(mLogin, mListener, context); } return mList; } diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesList.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesList.java index 99a7d9c..50897da 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesList.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesList.java @@ -25,12 +25,14 @@ import static de.sebse.fuplanner.services.KVV.ModulesPart.RETRY_COUNT; public class KVVModulesList extends HTTPService { private final KVVLogin mLogin; + private final KVVListener mListener; @Nullable private Modules mModules; private NewAsyncQueue mQueue = new NewAsyncQueue(); - KVVModulesList(KVVLogin login, Context context) { + KVVModulesList(KVVLogin login, KVVListener listener, Context context) { super(context); this.mLogin = login; + this.mListener = listener; restore(); } @@ -117,6 +119,7 @@ public class KVVModulesList extends HTTPService { this.mModules = success; else this.mModules.updateList(success); + mListener.onModuleListChange(); store(); callback.onResponse(this.mModules); mQueue.next(); diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/LoginToken.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/LoginToken.java index 8d5ce8f..0ebfcfd 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/LoginToken.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/LoginToken.java @@ -18,7 +18,7 @@ import androidx.annotation.Nullable; */ public class LoginToken implements Serializable { - private static final String FILE_NAME = "LoginTokenSaveFile"; + private static final String FILE_NAME = "LoginTokenSaving"; private final String username; private final String shibsessionKey; @@ -43,7 +43,10 @@ public class LoginToken implements Serializable { return null; } ObjectInputStream is = new ObjectInputStream(fis); - LoginToken loginToken = (LoginToken) is.readObject(); + Object readObject = is.readObject(); + if (!(readObject instanceof LoginToken)) + return null; + LoginToken loginToken = (LoginToken) readObject; is.close(); fis.close(); return loginToken; 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 ec2652d..3d96419 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 @@ -25,7 +25,7 @@ public class Modules implements Iterable, Serializable { private SortedListModule list; private final String mUsername; //private transient Logger log = new Logger(this); - private static final String FILE_NAME = "ModuleListSaveFile"; + private static final String FILE_NAME = "ModuleListSaving"; public Modules(String username) { this.mUsername = username; @@ -68,7 +68,10 @@ public class Modules implements Iterable, Serializable { public static Modules load(Context context) throws IOException, ClassNotFoundException { FileInputStream fis = context.openFileInput(FILE_NAME); ObjectInputStream is = new ObjectInputStream(fis); - Modules modules = (Modules) is.readObject(); + Object readObject = is.readObject(); + if (!(readObject instanceof Modules)) + return null; + Modules modules = (Modules) readObject; is.close(); fis.close(); return modules; From 99933d5f8005e0224ee62945018df01c7a31b3ca Mon Sep 17 00:00:00 2001 From: Caesar2011 Date: Mon, 12 Nov 2018 18:40:15 +0100 Subject: [PATCH 09/17] Implemented Network Callback --- .../java/de/sebse/fuplanner/MainActivity.java | 11 ++++ .../fuplanner/services/KVV/KVVListener.java | 6 ++ .../fuplanner/services/KVV/KVVModules.java | 4 ++ .../sebse/fuplanner/tools/EventListener.java | 28 +++++++++ .../fuplanner/tools/MainActivityListener.java | 4 +- .../fuplanner/tools/network/HTTPService.java | 58 ++++++++++++++++--- 6 files changed, 101 insertions(+), 10 deletions(-) create mode 100644 app/src/main/java/de/sebse/fuplanner/tools/EventListener.java diff --git a/app/src/main/java/de/sebse/fuplanner/MainActivity.java b/app/src/main/java/de/sebse/fuplanner/MainActivity.java index 7e6cd53..52d61a7 100644 --- a/app/src/main/java/de/sebse/fuplanner/MainActivity.java +++ b/app/src/main/java/de/sebse/fuplanner/MainActivity.java @@ -8,6 +8,7 @@ import android.view.View; import android.widget.TextView; import android.widget.Toast; +import com.android.volley.NetworkResponse; import com.google.android.material.navigation.NavigationView; import java.util.HashMap; @@ -547,4 +548,14 @@ public class MainActivity extends AppCompatActivity public void onModuleListChange() { updateNavigation(); } + + @Override + public void onNetworkError(NetworkResponse networkResponse) { + setRefreshFailedBanner(true); + } + + @Override + public void onNetworkSuccess() { + setRefreshFailedBanner(false); + } } diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVListener.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVListener.java index 5304f33..df3b43f 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVListener.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVListener.java @@ -1,5 +1,7 @@ package de.sebse.fuplanner.services.KVV; +import com.android.volley.NetworkResponse; + import de.sebse.fuplanner.services.GoogleAuth.Credentials; import de.sebse.fuplanner.services.KVV.types.LoginToken; import de.sebse.fuplanner.tools.network.NetworkCallback; @@ -13,4 +15,8 @@ public interface KVVListener { void handleLogout(); void onModuleListChange(); + + void onNetworkError(NetworkResponse networkResponse); + + void onNetworkSuccess(); } diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModules.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModules.java index 8f8e456..52d0a52 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModules.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModules.java @@ -56,6 +56,8 @@ public class KVVModules { public KVVModulesList list() { if (mList == null) { mList = new KVVModulesList(mLogin, mListener, context); + mList.addErrorListener("KVVModules", error -> mListener.onNetworkError(error.networkResponse)); + mList.addSuccessListener("KVVModules", success -> mListener.onNetworkSuccess()); } return mList; } @@ -66,6 +68,8 @@ public class KVVModules { Part o = mAddons.get(addon); if (o == null) { o = creatorInterface.create(); + o.addErrorListener("KVVModules", error -> mListener.onNetworkError(error.networkResponse)); + o.addSuccessListener("KVVModules", success -> mListener.onNetworkSuccess()); mAddons.put(addon, o); } return o; diff --git a/app/src/main/java/de/sebse/fuplanner/tools/EventListener.java b/app/src/main/java/de/sebse/fuplanner/tools/EventListener.java new file mode 100644 index 0000000..7e1afd2 --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/tools/EventListener.java @@ -0,0 +1,28 @@ +package de.sebse.fuplanner.tools; + +import com.google.android.gms.common.util.Function; + +import java.util.HashMap; + +public class EventListener { + private HashMap> list = new HashMap<>(); + + public void add(String id,EventFunction listener) { + list.put(id, listener); + } + + public void remove(String id) { + list.remove(id); + } + + public void emit(T value) { + for (EventFunction listener : list.values()) { + listener.apply(value); + } + } + + @FunctionalInterface + public interface EventFunction { + void apply(T value); + } +} diff --git a/app/src/main/java/de/sebse/fuplanner/tools/MainActivityListener.java b/app/src/main/java/de/sebse/fuplanner/tools/MainActivityListener.java index e41fe62..3cc12d9 100644 --- a/app/src/main/java/de/sebse/fuplanner/tools/MainActivityListener.java +++ b/app/src/main/java/de/sebse/fuplanner/tools/MainActivityListener.java @@ -19,10 +19,10 @@ public interface MainActivityListener { GoogleAuth getGoogleAuth(); - void onRefreshCompleted(boolean isFailed); - CanteenBrowser getCanteenBrowser(); + void onRefreshCompleted(boolean isFailed); + void addRequestPermissionsResultListener(RequestPermissionsResultListener listener, String id); void removeRequestPermissionsResultListener(String id); diff --git a/app/src/main/java/de/sebse/fuplanner/tools/network/HTTPService.java b/app/src/main/java/de/sebse/fuplanner/tools/network/HTTPService.java index 088247a..96b9b00 100644 --- a/app/src/main/java/de/sebse/fuplanner/tools/network/HTTPService.java +++ b/app/src/main/java/de/sebse/fuplanner/tools/network/HTTPService.java @@ -10,6 +10,7 @@ import com.android.volley.Response; import com.android.volley.TimeoutError; import com.android.volley.VolleyError; import com.android.volley.toolbox.Volley; +import com.google.android.gms.common.util.Function; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; @@ -17,6 +18,7 @@ import java.util.HashMap; import java.util.Map; import androidx.annotation.Nullable; +import de.sebse.fuplanner.tools.EventListener; import de.sebse.fuplanner.tools.logging.Logger; /** @@ -27,35 +29,64 @@ public class HTTPService { private final RequestQueue requestQueue; private final Context mContext; protected Logger log = new Logger(this); + private EventListener errorResponseListener = new EventListener<>(); + private EventListener successResponseListener = new EventListener<>(); protected HTTPService(Context context) { this.mContext = context; requestQueue = Volley.newRequestQueue(context, new BetterHurlStack(false)); } + public void addErrorListener(String id, EventListener.EventFunction listener) { + errorResponseListener.add(id, listener); + } + + public void removeErrorListener(String id) { + errorResponseListener.remove(id); + } + + public void addSuccessListener(String id, EventListener.EventFunction listener) { + successResponseListener.add(id, listener); + } + + public void removeSuccessListener(String id) { + successResponseListener.remove(id); + } + protected void get(String url, @Nullable final HashMap cookies, Response.Listener response, Response.ErrorListener error) { HttpRequest request = new HttpRequest(Request.Method.GET, url, response, error) { @Override public void deliverError(VolleyError error) { if (error == null) { - super.deliverError(new VolleyError(new NetworkResponse(500, null, true, 0, null))); + deliver(new VolleyError(new NetworkResponse(500, null, true, 0, null))); } else if (error.networkResponse == null) { int statusCode; if (error instanceof TimeoutError) statusCode = 408; else statusCode = 500; - super.deliverError(new VolleyError(new NetworkResponse(statusCode, null, true, error.getNetworkTimeMs(), null))); + deliver(new VolleyError(new NetworkResponse(statusCode, null, true, error.getNetworkTimeMs(), null))); } else { final int status = error.networkResponse.statusCode; if (status == 302) { - super.deliverResponse(new Result(null, error.networkResponse.headers)); + deliverResponse(new Result(null, error.networkResponse.headers)); } else { - super.deliverError(error); + deliver(error); } } } + @Override + protected void deliverResponse(Result response) { + successResponseListener.emit(response); + super.deliverResponse(response); + } + + private void deliver(VolleyError error) { + errorResponseListener.emit(error); + super.deliverError(error); + } + public Map getHeaders() throws AuthFailureError { Map params = super.getHeaders(); if (cookies != null) { @@ -109,24 +140,35 @@ public class HTTPService { @Override public void deliverError(VolleyError error) { if (error == null) { - super.deliverError(new VolleyError(new NetworkResponse(500, null, true, 0, null))); + deliver(new VolleyError(new NetworkResponse(500, null, true, 0, null))); } else if (error.networkResponse == null) { int statusCode; if (error instanceof TimeoutError) statusCode = 408; else statusCode = 500; - super.deliverError(new VolleyError(new NetworkResponse(statusCode, null, true, error.getNetworkTimeMs(), null))); + deliver(new VolleyError(new NetworkResponse(statusCode, null, true, error.getNetworkTimeMs(), null))); } else { final int status = error.networkResponse.statusCode; if (status == 302) { - super.deliverResponse(new Result(null, error.networkResponse.headers)); + deliverResponse(new Result(null, error.networkResponse.headers)); } else { - super.deliverError(error); + deliver(error); } } } + private void deliver(VolleyError error) { + errorResponseListener.emit(error); + super.deliverError(error); + } + + @Override + protected void deliverResponse(Result response) { + successResponseListener.emit(response); + super.deliverResponse(response); + } + public Map getHeaders() throws AuthFailureError { Map params = super.getHeaders(); if (cookies != null) { From 6daa41cbcdb1c8d92a51ea1f99d2463ffb6f8f32 Mon Sep 17 00:00:00 2001 From: Caesar2011 Date: Tue, 13 Nov 2018 00:44:25 +0100 Subject: [PATCH 10/17] Massive Renaming and Name Shorting --- .../java/de/sebse/fuplanner/MainActivity.java | 24 +++--- .../moddetails/ModDetailAnnounceAdapter.java | 2 +- .../moddetails/ModDetailAnnounceFragment.java | 2 +- .../ModDetailAssignmentAdapter.java | 2 +- .../ModDetailAssignmentFragment.java | 2 +- .../moddetails/ModDetailResourceFragment.java | 2 +- .../de/sebse/fuplanner/services/KVV/KVV.java | 8 +- .../fuplanner/services/KVV/KVVListener.java | 8 +- .../fuplanner/services/KVV/KVVModules.java | 81 ------------------- .../KVV/{KVVLogin.java => Login.java} | 8 +- .../sebse/fuplanner/services/KVV/Modules.java | 81 +++++++++++++++++++ ...cements.java => ModulesAnnouncements.java} | 4 +- ...signments.java => ModulesAssignments.java} | 4 +- ...odulesDetails.java => ModulesDetails.java} | 6 +- ...VModulesEvents.java => ModulesEvents.java} | 4 +- ...esGradebook.java => ModulesGradebook.java} | 4 +- .../{KVVModulesList.java => ModulesList.java} | 10 +-- .../fuplanner/services/KVV/ModulesPart.java | 2 +- ...esResources.java => ModulesResources.java} | 4 +- .../de/sebse/fuplanner/services/KVV/Part.java | 6 +- .../services/KVV/{ => ui}/Download.java | 2 +- .../fuplanner/tools/MainActivityListener.java | 1 + 22 files changed, 129 insertions(+), 138 deletions(-) delete mode 100644 app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModules.java rename app/src/main/java/de/sebse/fuplanner/services/KVV/{KVVLogin.java => Login.java} (98%) create mode 100644 app/src/main/java/de/sebse/fuplanner/services/KVV/Modules.java rename app/src/main/java/de/sebse/fuplanner/services/KVV/{KVVModulesAnnouncements.java => ModulesAnnouncements.java} (95%) rename app/src/main/java/de/sebse/fuplanner/services/KVV/{KVVModulesAssignments.java => ModulesAssignments.java} (96%) rename app/src/main/java/de/sebse/fuplanner/services/KVV/{KVVModulesDetails.java => ModulesDetails.java} (88%) rename app/src/main/java/de/sebse/fuplanner/services/KVV/{KVVModulesEvents.java => ModulesEvents.java} (96%) rename app/src/main/java/de/sebse/fuplanner/services/KVV/{KVVModulesGradebook.java => ModulesGradebook.java} (95%) rename app/src/main/java/de/sebse/fuplanner/services/KVV/{KVVModulesList.java => ModulesList.java} (97%) rename app/src/main/java/de/sebse/fuplanner/services/KVV/{KVVModulesResources.java => ModulesResources.java} (98%) rename app/src/main/java/de/sebse/fuplanner/services/KVV/{ => ui}/Download.java (99%) diff --git a/app/src/main/java/de/sebse/fuplanner/MainActivity.java b/app/src/main/java/de/sebse/fuplanner/MainActivity.java index 52d61a7..a9aedd3 100644 --- a/app/src/main/java/de/sebse/fuplanner/MainActivity.java +++ b/app/src/main/java/de/sebse/fuplanner/MainActivity.java @@ -39,6 +39,7 @@ import de.sebse.fuplanner.services.GoogleAuth.GoogleAuth; import de.sebse.fuplanner.services.KVV.KVV; import de.sebse.fuplanner.services.KVV.KVVListener; import de.sebse.fuplanner.services.KVV.types.LoginToken; +import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.tools.MainActivityListener; import de.sebse.fuplanner.tools.RequestPermissionsResultListener; import de.sebse.fuplanner.tools.logging.Logger; @@ -273,7 +274,7 @@ public class MainActivity extends AppCompatActivity changeFragment(FRAGMENT_LOGIN); } - private void toLoginState(String fullName, String email, int newFragment, String newData, boolean onlineMode) { + private void toLoginState(String fullName, String email, int newFragment, boolean onlineMode) { setOfflineBanner(!onlineMode); updateNavigation(); @@ -281,7 +282,7 @@ public class MainActivity extends AppCompatActivity ((TextView) header.findViewById(R.id.login_name)).setText(fullName); ((TextView) header.findViewById(R.id.login_mail)).setText(email); - changeFragment(newFragment, newData); + changeFragment(newFragment); } private void changeFragment(int newFragment) { @@ -425,8 +426,8 @@ public class MainActivity extends AppCompatActivity if (isLoggedIn) { getKVV().modules().list().recv(success -> { int i = 0; - for (Iterator it = success.latestSemesterIterator(); it.hasNext(); ) { - de.sebse.fuplanner.services.KVV.types.Modules.Module module = it.next(); + for (Iterator it = success.latestSemesterIterator(); it.hasNext(); ) { + Modules.Module module = it.next(); MenuItem menuItem = mNavigationView.getMenu().add(Menu.NONE, Menu.NONE, 101 + i, module.title); menuItem.setOnMenuItemClickListener(item -> { onModulesFragmentInteraction(module.getID()); @@ -535,12 +536,12 @@ public class MainActivity extends AppCompatActivity } @Override - public void handleLogin(LoginToken token, boolean enteringOnlineMode) { - toLoginState(token.getUsername(), token.getEmail(), getDefaultFragmentAfterLogin(), "", enteringOnlineMode); + public void onLogin(LoginToken token, boolean enteringOnlineMode) { + toLoginState(token.getUsername(), token.getEmail(), getDefaultFragmentAfterLogin(), enteringOnlineMode); } @Override - public void handleLogout() { + public void onLogout() { toLogoutState(); } @@ -550,12 +551,7 @@ public class MainActivity extends AppCompatActivity } @Override - public void onNetworkError(NetworkResponse networkResponse) { - setRefreshFailedBanner(true); - } - - @Override - public void onNetworkSuccess() { - setRefreshFailedBanner(false); + public void onNetworkResponse(NetworkResponse error) { + setRefreshFailedBanner(error != null); } } 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 index e616571..b5a37f0 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAnnounceAdapter.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAnnounceAdapter.java @@ -16,7 +16,7 @@ import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; import androidx.recyclerview.widget.RecyclerView; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.KVV.Download; +import de.sebse.fuplanner.services.KVV.ui.Download; import de.sebse.fuplanner.services.KVV.types.Announcement; import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.tools.Regex; 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 fb38cdf..9a203b8 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 @@ -14,7 +14,7 @@ import androidx.recyclerview.widget.RecyclerView; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import de.sebse.fuplanner.MainActivity; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.KVV.Download; +import de.sebse.fuplanner.services.KVV.ui.Download; import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.tools.MainActivityListener; import de.sebse.fuplanner.tools.logging.Logger; 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 index f3f74e2..34c49fd 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentAdapter.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentAdapter.java @@ -16,7 +16,7 @@ import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; import androidx.recyclerview.widget.RecyclerView; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.KVV.Download; +import de.sebse.fuplanner.services.KVV.ui.Download; import de.sebse.fuplanner.services.KVV.types.Assignment; import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.tools.Regex; 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 index 39fb185..8706804 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentFragment.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailAssignmentFragment.java @@ -14,7 +14,7 @@ import androidx.recyclerview.widget.RecyclerView; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import de.sebse.fuplanner.MainActivity; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.KVV.Download; +import de.sebse.fuplanner.services.KVV.ui.Download; import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.tools.MainActivityListener; import de.sebse.fuplanner.tools.logging.Logger; diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailResourceFragment.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailResourceFragment.java index 50bf28e..ed73214 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailResourceFragment.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModDetailResourceFragment.java @@ -18,7 +18,7 @@ import androidx.recyclerview.widget.RecyclerView; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import de.sebse.fuplanner.MainActivity; import de.sebse.fuplanner.R; -import de.sebse.fuplanner.services.KVV.Download; +import de.sebse.fuplanner.services.KVV.ui.Download; import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.services.KVV.types.Resource; import de.sebse.fuplanner.tools.MainActivityListener; 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 ae279d5..076947f 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 @@ -17,13 +17,13 @@ public class KVV { } @NotNull - public KVVLogin account() { - return (KVVLogin) addAndGet("account", () -> new KVVLogin(mListener, mContext)); + public Login account() { + return (Login) addAndGet("account", () -> new Login(mListener, mContext)); } @NotNull - public KVVModules modules() { - return (KVVModules) addAndGet("module", () -> new KVVModules(account(), mListener, mContext)); + public Modules modules() { + return (Modules) addAndGet("module", () -> new Modules(account(), mListener, mContext)); } diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVListener.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVListener.java index df3b43f..72ffbce 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVListener.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVListener.java @@ -10,13 +10,11 @@ import de.sebse.fuplanner.tools.network.NetworkErrorCallback; public interface KVVListener { void getCredentials(NetworkCallback callback, NetworkErrorCallback error); - void handleLogin(LoginToken token, boolean enteringOnlineMode); + void onLogin(LoginToken token, boolean enteringOnlineMode); - void handleLogout(); + void onLogout(); void onModuleListChange(); - void onNetworkError(NetworkResponse networkResponse); - - void onNetworkSuccess(); + void onNetworkResponse(NetworkResponse error); } diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModules.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModules.java deleted file mode 100644 index 52d0a52..0000000 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModules.java +++ /dev/null @@ -1,81 +0,0 @@ -package de.sebse.fuplanner.services.KVV; - -import android.content.Context; - -import org.jetbrains.annotations.NotNull; - -import java.util.HashMap; - -public class KVVModules { - private final HashMap mAddons = new HashMap<>(); - private KVVModulesList mList = null; - private final KVVLogin mLogin; - private KVVListener mListener; - private final Context context; - - KVVModules(KVVLogin login, KVVListener listener, Context context) { - this.mLogin = login; - this.mListener = listener; - this.context = context; - } - - @NotNull - public KVVModulesDetails details() { - return (KVVModulesDetails) addAndGet("details", () -> { - ModulesPart[] parts = {announcements(), assignments(), events(), gradebook(), resources()}; - return new KVVModulesDetails(mLogin, list(), context, parts); - }); - } - - @NotNull - public KVVModulesAnnouncements announcements() { - return (KVVModulesAnnouncements) addAndGet("announcements", () -> new KVVModulesAnnouncements(mLogin, list(), context)); - } - - @NotNull - public KVVModulesAssignments assignments() { - return (KVVModulesAssignments) addAndGet("assignments", () -> new KVVModulesAssignments(mLogin, list(), context)); - } - - @NotNull - public KVVModulesEvents events() { - return (KVVModulesEvents) addAndGet("events", () -> new KVVModulesEvents(mLogin, list(), context)); - } - - @NotNull - public KVVModulesGradebook gradebook() { - return (KVVModulesGradebook) addAndGet("gradebook", () -> new KVVModulesGradebook(mLogin, list(), context)); - } - - @NotNull - public KVVModulesResources resources() { - return (KVVModulesResources) addAndGet("resources", () -> new KVVModulesResources(mLogin, list(), context)); - } - - @NotNull - public KVVModulesList list() { - if (mList == null) { - mList = new KVVModulesList(mLogin, mListener, context); - mList.addErrorListener("KVVModules", error -> mListener.onNetworkError(error.networkResponse)); - mList.addSuccessListener("KVVModules", success -> mListener.onNetworkSuccess()); - } - return mList; - } - - - @NotNull - private Part addAndGet(@NotNull String addon, @NotNull ModuleCreatorInterface creatorInterface) { - Part o = mAddons.get(addon); - if (o == null) { - o = creatorInterface.create(); - o.addErrorListener("KVVModules", error -> mListener.onNetworkError(error.networkResponse)); - o.addSuccessListener("KVVModules", success -> mListener.onNetworkSuccess()); - mAddons.put(addon, o); - } - return o; - } - - private interface ModuleCreatorInterface { - @NotNull Part create(); - } -} diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVLogin.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/Login.java similarity index 98% rename from app/src/main/java/de/sebse/fuplanner/services/KVV/KVVLogin.java rename to app/src/main/java/de/sebse/fuplanner/services/KVV/Login.java index 945bf50..b10473e 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVLogin.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/Login.java @@ -20,13 +20,13 @@ import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkError; import de.sebse.fuplanner.tools.network.NetworkErrorCallback; -public class KVVLogin extends HTTPService { +public class Login extends HTTPService { private KVVListener mListener; @Nullable private LoginToken mToken; private boolean mLoginPending = false; private boolean mOnlineMode = false; - KVVLogin(KVVListener listener, Context context) { + Login(KVVListener listener, Context context) { super(context); this.mListener = listener; } @@ -160,10 +160,10 @@ public class KVVLogin extends HTTPService { private boolean handleCallbacks() { if (mToken != null) { - mListener.handleLogin(mToken, mOnlineMode); + mListener.onLogin(mToken, mOnlineMode); return true; } else { - mListener.handleLogout(); + mListener.onLogout(); return false; } } diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/Modules.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/Modules.java new file mode 100644 index 0000000..50d67ba --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/Modules.java @@ -0,0 +1,81 @@ +package de.sebse.fuplanner.services.KVV; + +import android.content.Context; + +import org.jetbrains.annotations.NotNull; + +import java.util.HashMap; + +public class Modules { + private final HashMap mAddons = new HashMap<>(); + private ModulesList mList = null; + private final Login mLogin; + private KVVListener mListener; + private final Context context; + + Modules(Login login, KVVListener listener, Context context) { + this.mLogin = login; + this.mListener = listener; + this.context = context; + } + + @NotNull + public ModulesDetails details() { + return (ModulesDetails) addAndGet("details", () -> { + ModulesPart[] parts = {announcements(), assignments(), events(), gradebook(), resources()}; + return new ModulesDetails(mLogin, list(), context, parts); + }); + } + + @NotNull + public ModulesAnnouncements announcements() { + return (ModulesAnnouncements) addAndGet("announcements", () -> new ModulesAnnouncements(mLogin, list(), context)); + } + + @NotNull + public ModulesAssignments assignments() { + return (ModulesAssignments) addAndGet("assignments", () -> new ModulesAssignments(mLogin, list(), context)); + } + + @NotNull + public ModulesEvents events() { + return (ModulesEvents) addAndGet("events", () -> new ModulesEvents(mLogin, list(), context)); + } + + @NotNull + public ModulesGradebook gradebook() { + return (ModulesGradebook) addAndGet("gradebook", () -> new ModulesGradebook(mLogin, list(), context)); + } + + @NotNull + public ModulesResources resources() { + return (ModulesResources) addAndGet("resources", () -> new ModulesResources(mLogin, list(), context)); + } + + @NotNull + public ModulesList list() { + if (mList == null) { + mList = new ModulesList(mLogin, mListener, context); + mList.addErrorListener("Modules", error -> mListener.onNetworkResponse(error.networkResponse)); + mList.addSuccessListener("Modules", success -> mListener.onNetworkResponse(null)); + } + return mList; + } + + + @NotNull + private Part addAndGet(@NotNull String addon, @NotNull ModuleCreatorInterface creatorInterface) { + Part o = mAddons.get(addon); + if (o == null) { + o = creatorInterface.create(); + o.addErrorListener("Modules", error -> mListener.onNetworkResponse(error.networkResponse)); + o.addSuccessListener("Modules", success -> mListener.onNetworkResponse(null)); + mAddons.put(addon, o); + } + return o; + } + + private interface ModuleCreatorInterface { + @NotNull Part create(); + } +} diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesAnnouncements.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesAnnouncements.java similarity index 95% rename from app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesAnnouncements.java rename to app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesAnnouncements.java index 60a6368..72adc75 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesAnnouncements.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesAnnouncements.java @@ -14,9 +14,9 @@ import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkError; import de.sebse.fuplanner.tools.network.NetworkErrorCallback; -public class KVVModulesAnnouncements extends ModulesPart> { +public class ModulesAnnouncements extends ModulesPart> { - KVVModulesAnnouncements(KVVLogin login, KVVModulesList list, Context context) { + ModulesAnnouncements(Login login, ModulesList list, Context context) { super(login, list, context); } diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesAssignments.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesAssignments.java similarity index 96% rename from app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesAssignments.java rename to app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesAssignments.java index 0db727c..93d3aa2 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesAssignments.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesAssignments.java @@ -15,9 +15,9 @@ import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkError; import de.sebse.fuplanner.tools.network.NetworkErrorCallback; -public class KVVModulesAssignments extends ModulesPart { +public class ModulesAssignments extends ModulesPart { - KVVModulesAssignments(KVVLogin login, KVVModulesList list, Context context) { + ModulesAssignments(Login login, ModulesList list, Context context) { super(login, list, context); } diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesDetails.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesDetails.java similarity index 88% rename from app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesDetails.java rename to app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesDetails.java index b110e86..9ae2559 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesDetails.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesDetails.java @@ -10,10 +10,10 @@ import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkError; import de.sebse.fuplanner.tools.network.NetworkErrorCallback; -final public class KVVModulesDetails extends Part> { +final public class ModulesDetails extends Part> { private final ModulesPart[] parts; - KVVModulesDetails(KVVLogin login, KVVModulesList list, Context context, ModulesPart[] parts) { + ModulesDetails(Login login, ModulesList list, Context context, ModulesPart[] parts) { super(login, list, context); this.parts = parts; } @@ -40,7 +40,7 @@ final public class KVVModulesDetails extends Part> errorCallback.onError(lastError.get()); } }; - for (ModulesPart part: parts) { + for (ModulesPart part: parts) { part.recv(module, successCb, errorCb, forceRefresh, RETRY_COUNT); } } diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesEvents.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesEvents.java similarity index 96% rename from app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesEvents.java rename to app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesEvents.java index 0ff9376..50617f9 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesEvents.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesEvents.java @@ -13,9 +13,9 @@ import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkError; import de.sebse.fuplanner.tools.network.NetworkErrorCallback; -public class KVVModulesEvents extends ModulesPart { +public class ModulesEvents extends ModulesPart { - KVVModulesEvents(KVVLogin login, KVVModulesList list, Context context) { + ModulesEvents(Login login, ModulesList list, Context context) { super(login, list, context); } diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesGradebook.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesGradebook.java similarity index 95% rename from app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesGradebook.java rename to app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesGradebook.java index b9137db..4784a91 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesGradebook.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesGradebook.java @@ -14,9 +14,9 @@ import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkError; import de.sebse.fuplanner.tools.network.NetworkErrorCallback; -public class KVVModulesGradebook extends ModulesPart> { +public class ModulesGradebook extends ModulesPart> { - KVVModulesGradebook(KVVLogin login, KVVModulesList list, Context context) { + ModulesGradebook(Login login, ModulesList list, Context context) { super(login, list, context); } diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesList.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesList.java similarity index 97% rename from app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesList.java rename to app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesList.java index 50897da..ddc1e91 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesList.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesList.java @@ -23,23 +23,19 @@ import de.sebse.fuplanner.tools.network.NetworkErrorCallback; import static de.sebse.fuplanner.services.KVV.ModulesPart.RETRY_COUNT; -public class KVVModulesList extends HTTPService { - private final KVVLogin mLogin; +public class ModulesList extends HTTPService { + private final Login mLogin; private final KVVListener mListener; @Nullable private Modules mModules; private NewAsyncQueue mQueue = new NewAsyncQueue(); - KVVModulesList(KVVLogin login, KVVListener listener, Context context) { + ModulesList(Login login, KVVListener listener, Context context) { super(context); this.mLogin = login; this.mListener = listener; restore(); } - public boolean stored() { - return mModules != null; - } - @Nullable public String getUsername() { if (mModules != null) { diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesPart.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesPart.java index ac1d4ad..81f13c6 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesPart.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesPart.java @@ -13,7 +13,7 @@ import de.sebse.fuplanner.tools.network.NetworkErrorCallback; abstract class ModulesPart extends Part { private NewAsyncQueue mQueue = new NewAsyncQueue(); - ModulesPart(KVVLogin login, KVVModulesList list, Context context) { + ModulesPart(Login login, ModulesList list, Context context) { super(login, list, context); } diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesResources.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesResources.java similarity index 98% rename from app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesResources.java rename to app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesResources.java index 70bf58d..2c0545a 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVModulesResources.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesResources.java @@ -18,9 +18,9 @@ import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkError; import de.sebse.fuplanner.tools.network.NetworkErrorCallback; -public class KVVModulesResources extends ModulesPart> { +public class ModulesResources extends ModulesPart> { - KVVModulesResources(KVVLogin login, KVVModulesList list, Context context) { + ModulesResources(Login login, ModulesList list, Context context) { super(login, list, context); } diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/Part.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/Part.java index bb74ef5..686a484 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/Part.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/Part.java @@ -9,10 +9,10 @@ import de.sebse.fuplanner.tools.network.NetworkErrorCallback; public abstract class Part extends HTTPService { static final int RETRY_COUNT = 1; - protected final KVVLogin mLogin; - protected final KVVModulesList mList; + protected final Login mLogin; + protected final ModulesList mList; - Part(KVVLogin login, KVVModulesList list, Context context) { + Part(Login login, ModulesList list, Context context) { super(context); this.mLogin = login; this.mList = list; diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/Download.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/ui/Download.java similarity index 99% rename from app/src/main/java/de/sebse/fuplanner/services/KVV/Download.java rename to app/src/main/java/de/sebse/fuplanner/services/KVV/ui/Download.java index 98b21e0..8cd8ff8 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/Download.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/ui/Download.java @@ -1,4 +1,4 @@ -package de.sebse.fuplanner.services.KVV; +package de.sebse.fuplanner.services.KVV.ui; import android.Manifest; import android.app.AlertDialog; diff --git a/app/src/main/java/de/sebse/fuplanner/tools/MainActivityListener.java b/app/src/main/java/de/sebse/fuplanner/tools/MainActivityListener.java index 3cc12d9..5f6800c 100644 --- a/app/src/main/java/de/sebse/fuplanner/tools/MainActivityListener.java +++ b/app/src/main/java/de/sebse/fuplanner/tools/MainActivityListener.java @@ -21,6 +21,7 @@ public interface MainActivityListener { CanteenBrowser getCanteenBrowser(); + @Deprecated void onRefreshCompleted(boolean isFailed); void addRequestPermissionsResultListener(RequestPermissionsResultListener listener, String id); From a879a085b4b3ec55de8259626526117f930aaf9a Mon Sep 17 00:00:00 2001 From: Caesar2011 Date: Tue, 13 Nov 2018 01:39:12 +0100 Subject: [PATCH 11/17] Fixed Warnings --- .../tools/ui/treeview/TreeViewAdapter.java | 68 +++++++++---------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/TreeViewAdapter.java b/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/TreeViewAdapter.java index 69e5862..ffe2a813 100644 --- a/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/TreeViewAdapter.java +++ b/app/src/main/java/de/sebse/fuplanner/tools/ui/treeview/TreeViewAdapter.java @@ -17,6 +17,7 @@ import androidx.recyclerview.widget.RecyclerView; /** * Created by tlh on 2016/10/1 :) */ +@SuppressWarnings("unused") public class TreeViewAdapter extends RecyclerView.Adapter { private static final String KEY_IS_EXPAND = "IS_EXPAND"; private final List viewBinders; @@ -42,7 +43,7 @@ public class TreeViewAdapter extends RecyclerView.Adapter nodes) { - for (TreeNode node : nodes) { + for (TreeNode node : nodes) { displayNodes.add(node); if (!node.isLeaf() && node.isExpand()) findDisplayNodes(node.getChildList()); @@ -54,8 +55,9 @@ public class TreeViewAdapter extends RecyclerView.Adapter payloads) { - if (payloads != null && !payloads.isEmpty()) { + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position, @NonNull List payloads) { + if (!payloads.isEmpty()) { Bundle b = (Bundle) payloads.get(0); for (String key : b.keySet()) { switch (key) { @@ -84,44 +86,42 @@ public class TreeViewAdapter extends RecyclerView.Adapter { + TreeNode selectedNode = displayNodes.get(holder.getLayoutPosition()); + // Prevent multi-click during the short interval. + try { + long lastClickTime = (long) holder.itemView.getTag(); + if (System.currentTimeMillis() - lastClickTime < 500) + return; + } catch (Exception e) { holder.itemView.setTag(System.currentTimeMillis()); + } + holder.itemView.setTag(System.currentTimeMillis()); - if (onTreeNodeListener != null && onTreeNodeListener.onClick(selectedNode, holder)) - return; - if (selectedNode.isLeaf()) - return; - // This TreeNode was locked to click. - if (selectedNode.isLocked()) return; - boolean isExpand = selectedNode.isExpand(); - int positionStart = displayNodes.indexOf(selectedNode) + 1; - if (!isExpand) { - notifyItemRangeInserted(positionStart, addChildNodes(selectedNode, positionStart)); - } else { - notifyItemRangeRemoved(positionStart, removeChildNodes(selectedNode, true)); - } + if (onTreeNodeListener != null && onTreeNodeListener.onClick(selectedNode, holder)) + return; + if (selectedNode.isLeaf()) + return; + // This TreeNode was locked to click. + if (selectedNode.isLocked()) return; + boolean isExpand = selectedNode.isExpand(); + int positionStart = displayNodes.indexOf(selectedNode) + 1; + if (!isExpand) { + notifyItemRangeInserted(positionStart, addChildNodes(selectedNode, positionStart)); + } else { + notifyItemRangeRemoved(positionStart, removeChildNodes(selectedNode, true)); } }); for (TreeViewBinder viewBinder : viewBinders) { if (viewBinder.getLayoutId() == displayNodes.get(position).getContent().getLayoutId()) + //noinspection unchecked viewBinder.bindView(holder, position, displayNodes.get(position)); } } - private int addChildNodes(TreeNode pNode, int startIndex) { + private int addChildNodes(TreeNode pNode, int startIndex) { List childList = pNode.getChildList(); int addChildCount = 0; for (TreeNode treeNode : childList) { @@ -139,7 +139,7 @@ public class TreeViewAdapter extends RecyclerView.Adapter pNode, boolean shouldToggle) { if (pNode.isLeaf()) return 0; List childList = pNode.getChildList(); @@ -287,7 +287,7 @@ public class TreeViewAdapter extends RecyclerView.Adapter pNode) { List temp = backupDisplayNodes(); if (pNode.isRoot()) { List roots = new ArrayList<>(); @@ -301,7 +301,7 @@ public class TreeViewAdapter extends RecyclerView.Adapter parent = pNode.getParent(); if (parent == null) return; List childList = parent.getChildList(); From 9668fe889eb407e5fe05e61d1d4f87af8e96693a Mon Sep 17 00:00:00 2001 From: Caesar2011 Date: Tue, 13 Nov 2018 16:20:19 +0100 Subject: [PATCH 12/17] Rename and Bug Fixes --- .../java/de/sebse/fuplanner/services/KVV/Modules.java | 2 +- .../fuplanner/services/KVV/ModulesAnnouncements.java | 2 +- .../sebse/fuplanner/services/KVV/ModulesAssignments.java | 2 +- .../de/sebse/fuplanner/services/KVV/ModulesDetails.java | 6 +++--- .../de/sebse/fuplanner/services/KVV/ModulesEvents.java | 2 +- .../sebse/fuplanner/services/KVV/ModulesGradebook.java | 2 +- .../de/sebse/fuplanner/services/KVV/ModulesList.java | 4 ++-- .../sebse/fuplanner/services/KVV/ModulesResources.java | 2 +- .../services/KVV/{ModulesPart.java => PartModules.java} | 9 ++++++--- 9 files changed, 17 insertions(+), 14 deletions(-) rename app/src/main/java/de/sebse/fuplanner/services/KVV/{ModulesPart.java => PartModules.java} (88%) diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/Modules.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/Modules.java index 50d67ba..eba21a5 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/Modules.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/Modules.java @@ -22,7 +22,7 @@ public class Modules { @NotNull public ModulesDetails details() { return (ModulesDetails) addAndGet("details", () -> { - ModulesPart[] parts = {announcements(), assignments(), events(), gradebook(), resources()}; + PartModules[] parts = {announcements(), assignments(), events(), gradebook(), resources()}; return new ModulesDetails(mLogin, list(), context, parts); }); } diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesAnnouncements.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesAnnouncements.java index 72adc75..b13df13 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesAnnouncements.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesAnnouncements.java @@ -14,7 +14,7 @@ import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkError; import de.sebse.fuplanner.tools.network.NetworkErrorCallback; -public class ModulesAnnouncements extends ModulesPart> { +public class ModulesAnnouncements extends PartModules> { ModulesAnnouncements(Login login, ModulesList list, Context context) { super(login, list, context); diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesAssignments.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesAssignments.java index 93d3aa2..357be2c 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesAssignments.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesAssignments.java @@ -15,7 +15,7 @@ import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkError; import de.sebse.fuplanner.tools.network.NetworkErrorCallback; -public class ModulesAssignments extends ModulesPart { +public class ModulesAssignments extends PartModules { ModulesAssignments(Login login, ModulesList list, Context context) { super(login, list, context); diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesDetails.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesDetails.java index 9ae2559..a08fda4 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesDetails.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesDetails.java @@ -11,9 +11,9 @@ import de.sebse.fuplanner.tools.network.NetworkError; import de.sebse.fuplanner.tools.network.NetworkErrorCallback; final public class ModulesDetails extends Part> { - private final ModulesPart[] parts; + private final PartModules[] parts; - ModulesDetails(Login login, ModulesList list, Context context, ModulesPart[] parts) { + ModulesDetails(Login login, ModulesList list, Context context, PartModules[] parts) { super(login, list, context); this.parts = parts; } @@ -40,7 +40,7 @@ final public class ModulesDetails extends Part> { errorCallback.onError(lastError.get()); } }; - for (ModulesPart part: parts) { + for (PartModules part: parts) { part.recv(module, successCb, errorCb, forceRefresh, RETRY_COUNT); } } diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesEvents.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesEvents.java index 50617f9..66ba5c1 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesEvents.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesEvents.java @@ -13,7 +13,7 @@ import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkError; import de.sebse.fuplanner.tools.network.NetworkErrorCallback; -public class ModulesEvents extends ModulesPart { +public class ModulesEvents extends PartModules { ModulesEvents(Login login, ModulesList list, Context context) { super(login, list, context); diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesGradebook.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesGradebook.java index 4784a91..d346289 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesGradebook.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesGradebook.java @@ -14,7 +14,7 @@ import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkError; import de.sebse.fuplanner.tools.network.NetworkErrorCallback; -public class ModulesGradebook extends ModulesPart> { +public class ModulesGradebook extends PartModules> { ModulesGradebook(Login login, ModulesList list, Context context) { super(login, list, context); diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesList.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesList.java index ddc1e91..bd98552 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesList.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesList.java @@ -21,7 +21,7 @@ import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkError; import de.sebse.fuplanner.tools.network.NetworkErrorCallback; -import static de.sebse.fuplanner.services.KVV.ModulesPart.RETRY_COUNT; +import static de.sebse.fuplanner.services.KVV.PartModules.RETRY_COUNT; public class ModulesList extends HTTPService { private final Login mLogin; @@ -172,7 +172,7 @@ public class ModulesList extends HTTPService { } String type = site.getJSONObject("props").optString("kvv_coursetype", null); String description = site.optString("description", ""); - description = String.valueOf(ModulesPart.fromHtml(description)); + description = String.valueOf(PartModules.fromHtml(description)); String id = site.getString("id"); modules.addModule(semester, lvNumbers, title, lecturers, type, description, id); } catch (JSONException e) { diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesResources.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesResources.java index 2c0545a..f26869c 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesResources.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesResources.java @@ -18,7 +18,7 @@ import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkError; import de.sebse.fuplanner.tools.network.NetworkErrorCallback; -public class ModulesResources extends ModulesPart> { +public class ModulesResources extends PartModules> { ModulesResources(Login login, ModulesList list, Context context) { super(login, list, context); diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesPart.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/PartModules.java similarity index 88% rename from app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesPart.java rename to app/src/main/java/de/sebse/fuplanner/services/KVV/PartModules.java index 81f13c6..64cb4b8 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesPart.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/PartModules.java @@ -10,10 +10,10 @@ import de.sebse.fuplanner.tools.NewAsyncQueue; import de.sebse.fuplanner.tools.network.NetworkCallback; import de.sebse.fuplanner.tools.network.NetworkErrorCallback; -abstract class ModulesPart extends Part { +abstract class PartModules extends Part { private NewAsyncQueue mQueue = new NewAsyncQueue(); - ModulesPart(Login login, ModulesList list, Context context) { + PartModules(Login login, ModulesList list, Context context) { super(login, list, context); } @@ -36,7 +36,10 @@ abstract class ModulesPart extends Part { mLogin.refreshLogin(success -> { recv(module, callback, errorCallback, forceRefresh, retries-1); mQueue.next(); - }, errorCallback); + }, error2 -> { + errorCallback.onError(error2); + mQueue.next(); + }); return; } errorCallback.onError(error); From 07fbd7f74e2c08fd190c668458148b4aefd24c66 Mon Sep 17 00:00:00 2001 From: Caesar2011 Date: Tue, 13 Nov 2018 17:58:42 +0100 Subject: [PATCH 13/17] Even more CardView and new Semester Class, updated Module List --- .../java/de/sebse/fuplanner/MainActivity.java | 2 +- .../fuplanner/fragments/ModulesAdapter.java | 95 ++++++++++++++----- .../fuplanner/services/KVV/ModulesList.java | 4 +- .../services/KVV/types/Lecturer.java | 24 ++++- .../fuplanner/services/KVV/types/Modules.java | 15 ++- .../services/KVV/types/Semester.java | 53 +++++++++++ .../services/KVV/types/SortedListModule.java | 21 ++-- app/src/main/res/layout/list_all_items.xml | 91 +++++++++--------- app/src/main/res/values-de/strings.xml | 2 + app/src/main/res/values/strings.xml | 2 + 10 files changed, 217 insertions(+), 92 deletions(-) create mode 100644 app/src/main/java/de/sebse/fuplanner/services/KVV/types/Semester.java diff --git a/app/src/main/java/de/sebse/fuplanner/MainActivity.java b/app/src/main/java/de/sebse/fuplanner/MainActivity.java index a9aedd3..f033de4 100644 --- a/app/src/main/java/de/sebse/fuplanner/MainActivity.java +++ b/app/src/main/java/de/sebse/fuplanner/MainActivity.java @@ -537,7 +537,7 @@ public class MainActivity extends AppCompatActivity @Override public void onLogin(LoginToken token, boolean enteringOnlineMode) { - toLoginState(token.getUsername(), token.getEmail(), getDefaultFragmentAfterLogin(), enteringOnlineMode); + toLoginState(token.getFullName(), token.getEmail(), getDefaultFragmentAfterLogin(), enteringOnlineMode); } @Override diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/ModulesAdapter.java b/app/src/main/java/de/sebse/fuplanner/fragments/ModulesAdapter.java index 4b85503..c1e32c9 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/ModulesAdapter.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/ModulesAdapter.java @@ -1,66 +1,115 @@ package de.sebse.fuplanner.fragments; +import android.util.Pair; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import java.util.ArrayList; + import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import de.sebse.fuplanner.R; import de.sebse.fuplanner.fragments.ModulesFragment.OnModulesFragmentInteractionListener; +import de.sebse.fuplanner.services.KVV.types.Lecturer; import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.services.KVV.types.Semester; +import de.sebse.fuplanner.tools.ui.CustomViewHolder; import de.sebse.fuplanner.tools.ui.ItemViewHolder; +import de.sebse.fuplanner.tools.ui.StringViewHolder; /** * {@link RecyclerView.Adapter} that can display a {@link Modules.Module} and makes a call to the * specified {@link OnModulesFragmentInteractionListener}. */ -class ModulesAdapter extends RecyclerView.Adapter { +class ModulesAdapter extends RecyclerView.Adapter { + + private static final int TYPE_HEADER = 0; + private static final int TYPE_ITEM = 2; private Modules mValues; private final OnModulesFragmentInteractionListener mListener; + private final ArrayList> mPositionalData; ModulesAdapter(OnModulesFragmentInteractionListener listener) { mValues = null; mListener = listener; + mPositionalData = new ArrayList<>(); } public void setModules(Modules modules) { mValues = modules; + mPositionalData.clear(); + Semester lastSemester = null; + for (Modules.Module module : mValues) { + Semester semester = module.semester; + if (semester == null) + continue; + if (!semester.equals(lastSemester)) { + mPositionalData.add(new Pair<>(TYPE_HEADER, semester)); + lastSemester = semester; + } + mPositionalData.add(new Pair<>(TYPE_ITEM, module)); + } this.notifyDataSetChanged(); } + @Override + public int getItemViewType(int position) { + return mPositionalData.get(position).first; + } + @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); + public CustomViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + if (viewType == TYPE_HEADER) { + View view = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.list_all_caption, parent, false); + return new StringViewHolder(view); + } else { + 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; - Modules.Module module = mValues.getByIndex(holder.getAdapterPosition()); - holder.mTitle.setText(module.title); - holder.mSubLeft.setText(module.semester); - holder.mSubRight.setText(module.type); - - 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.onModulesFragmentInteraction(module.getID()); + public void onBindViewHolder(@NonNull CustomViewHolder holder, int position) { + Pair pair = mPositionalData.get(holder.getAdapterPosition()); + if (pair.first == TYPE_HEADER) { + StringViewHolder sHolder = (StringViewHolder) holder; + String localizedSemester; + Semester semester = (Semester) pair.second; + if (semester.getType() == Semester.SEM_WS) + localizedSemester = holder.mView.getResources().getString(R.string.winter_semester, semester.getYear(), semester.getYear()+1); + else + localizedSemester = holder.mView.getResources().getString(R.string.summer_semester, semester.getYear()); + sHolder.mString.setText(localizedSemester); + } else if (pair.first == TYPE_ITEM) { + ItemViewHolder iHolder = (ItemViewHolder) holder; + Modules.Module module = ((Modules.Module) pair.second); + iHolder.mTitle.setText(module.title); + StringBuilder lecturers = new StringBuilder(); + for (Lecturer lecturer : module.lecturer) { + if (!lecturer.isResponsible()) + continue; + if (lecturers.length() > 0) + lecturers.append(", "); + lecturers.append(lecturer.getNameShort()); } - }); + iHolder.mSubLeft.setText(lecturers); + iHolder.mSubRight.setText(module.type); + + iHolder.mView.setOnClickListener(v -> { + if (mListener != null) { + mListener.onModulesFragmentInteraction(module.getID()); + } + }); + } } @Override public int getItemCount() { - if (mValues != null) { - return mValues.size(); - } - return 0; + return mPositionalData.size(); } } diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesList.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesList.java index bd98552..5af11f7 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesList.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesList.java @@ -14,6 +14,7 @@ import java.util.regex.MatchResult; import de.sebse.fuplanner.services.KVV.types.Lecturer; import de.sebse.fuplanner.services.KVV.types.Modules; +import de.sebse.fuplanner.services.KVV.types.Semester; import de.sebse.fuplanner.tools.NewAsyncQueue; import de.sebse.fuplanner.tools.Regex; import de.sebse.fuplanner.tools.network.HTTPService; @@ -157,7 +158,8 @@ public class ModulesList extends HTTPService { for (int i = 0; i < sites.length(); i++) { try { JSONObject site = sites.getJSONObject(i); - String semester = site.getJSONObject("props").optString("term_eid", null); + String semester_string = site.getJSONObject("props").optString("term_eid", null); + Semester semester = new Semester(semester_string); 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)) { diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Lecturer.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Lecturer.java index bad72f5..c84737a 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Lecturer.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Lecturer.java @@ -4,13 +4,16 @@ import java.io.Serializable; import java.util.regex.Matcher; import java.util.regex.Pattern; +import de.sebse.fuplanner.tools.logging.Logger; + public class Lecturer implements Serializable { private final String firstName; private final String surname; private final String mail; + private final boolean isResponsible; public Lecturer(String parsableString) throws NoSuchFieldException { - Pattern pattern = Pattern.compile("([^|]*)\\|([^|]*)\\|([^|]*)\\|\\|", Pattern.DOTALL); + Pattern pattern = Pattern.compile("([^|]*)\\|([^|]*)\\|([^|]*)\\|\\|([^|]*)", Pattern.DOTALL); Matcher matcher = pattern.matcher(parsableString); if (!matcher.find()) { throw new NoSuchFieldException(); @@ -18,20 +21,33 @@ public class Lecturer implements Serializable { this.firstName = matcher.group(1); this.surname = matcher.group(2); this.mail = matcher.group(3); + this.isResponsible = matcher.group(4).equals("true"); } - private String getFirstName() { + public String getFirstName() { return firstName; } - private String getSurname() { + public String getSurname() { return surname; } - private String getMail() { + public String getMail() { return mail; } + public boolean isResponsible() { + return isResponsible; + } + + public String getName() { + return getFirstName() + " " + getSurname(); + } + + public String getNameShort() { + return getFirstName().substring(0, 1) + ". " + getSurname(); + } + @Override public String toString() { return "First name: "+ getFirstName()+ 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 3d96419..1b87e7d 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 @@ -10,6 +10,7 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; +import java.nio.channels.SeekableByteChannel; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; @@ -32,7 +33,7 @@ public class Modules implements Iterable, Serializable { this.list = new SortedListModule(); } - public void addModule(@Nullable String semester, HashSet lvNumber, String title, HashSet lecturer, String type, String description, String ID) { + public void addModule(@Nullable Semester 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); } @@ -109,10 +110,11 @@ public class Modules implements Iterable, Serializable { } public class Module implements Serializable { - @Nullable public final String semester; + @Nullable public final Semester semester; @NotNull final HashSet lvNumber; @NotNull public final String title; - @NotNull final HashSet lecturer; + @NotNull + public final HashSet lecturer; @Nullable public final String type; @Nullable public final String description; @NotNull private final String ID; @@ -136,11 +138,8 @@ public class Modules implements Iterable, Serializable { return userPoint/maxPoint; } - 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"); - } + private Module(@Nullable Semester semester, @NotNull HashSet lvNumber, @NotNull String title, @NotNull HashSet lecturer, @Nullable String type, @Nullable String description, @NotNull String ID) { + title = title.replaceAll("(.*?) (S[0-9]{2}|W[0-9/]{5})", "$1"); this.semester = semester; diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Semester.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Semester.java new file mode 100644 index 0000000..1e81d70 --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Semester.java @@ -0,0 +1,53 @@ +package de.sebse.fuplanner.services.KVV.types; + +import androidx.annotation.Nullable; +import de.sebse.fuplanner.tools.Regex; + +public class Semester { + public static final int SEM_WS = 1; + public static final int SEM_SS = 2; + private int type; + private int year; + + public Semester(int type, int year) { + this.type = type; + this.year = year; + } + + public Semester(String semester_string) throws NoSuchFieldException { + /*Semester sem = null; + if (semester != null) { + sem = new Semester(semester) + semester = semester.replace("SS", "S"); + semester = semester.replaceAll("[0-9]{2}([0-9]{2})", "$1"); + }*/ + + + /*String s1type = Regex.regex("^(S|WS) ", a); + int s1year = Integer.parseInt(Regex.regex("^(S|WS) ([0-9]{2})", a, 2)); + String s2type = Regex.regex("^(S|WS) ", b); + int s2year = Integer.parseInt(Regex.regex("^(S|WS) ([0-9]{2})", b, 2));*/ + + String type = Regex.regex("^(SS|WS) ", semester_string); + String year = Regex.regex("^(SS|WS) ([0-9]{2})", semester_string, 2); + this.type = type.equals("SS") ? SEM_SS : SEM_WS; + this.year = Integer.parseInt(year); + } + + public int getType() { + return type; + } + + public int getYear() { + return year; + } + + @Override + public boolean equals(@Nullable Object obj) { + if (obj instanceof Semester) { + Semester other = (Semester) obj; + return other.type == type && other.year == year; + } + return false; + } +} diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/SortedListModule.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/SortedListModule.java index bf306a5..b3b480e 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/SortedListModule.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/SortedListModule.java @@ -1,9 +1,10 @@ package de.sebse.fuplanner.services.KVV.types; +import androidx.annotation.Nullable; import de.sebse.fuplanner.tools.Regex; import de.sebse.fuplanner.tools.SortedList; -public class SortedListModule extends SortedList { +public class SortedListModule extends SortedList { private static final int LARGER = 1; private static final int EQUAL = 0; private static final int SMALLER = -1; @@ -27,7 +28,7 @@ public class SortedListModule extends SortedList super.add(e); } - public String getLatestSemester() { + public Semester getLatestSemester() { if (size() > 0) //noinspection ConstantConditions return this.get(0).semester; @@ -35,7 +36,7 @@ public class SortedListModule extends SortedList return null; } - private static int compareSemester(String a, String b) throws NoSuchFieldException { + private static int compareSemester(@Nullable Semester a, @Nullable Semester b) throws NoSuchFieldException { if (a == null && b == null) return EQUAL; if (a == null) @@ -43,17 +44,13 @@ public class SortedListModule extends SortedList if (b == null) return LARGER; - String s1type = Regex.regex("^(S|WS) ", a); - int s1year = Integer.parseInt(Regex.regex("^(S|WS) ([0-9]{2})", a, 2)); - String s2type = Regex.regex("^(S|WS) ", b); - int s2year = Integer.parseInt(Regex.regex("^(S|WS) ([0-9]{2})", b, 2)); - if (s1year == s2year) { - if (s1type.equals(s2type)) + if (a.getYear() == b.getYear()) { + if (a.getType() == b.getType()) return EQUAL; - return s1type.equals("S") ? SMALLER : LARGER; + return a.getType() == Semester.SEM_SS ? SMALLER : LARGER; } - return s1year < s2year ? SMALLER : LARGER; + return a.getYear() < b.getYear() ? SMALLER : LARGER; } @Override @@ -62,7 +59,7 @@ public class SortedListModule extends SortedList } @Override - public boolean hasFilter(Modules.Module o1, String filter) { + public boolean hasFilter(Modules.Module o1, Semester filter) { return o1.semester != null && o1.semester.equals(filter); } } diff --git a/app/src/main/res/layout/list_all_items.xml b/app/src/main/res/layout/list_all_items.xml index 05fa9b9..09d8e47 100644 --- a/app/src/main/res/layout/list_all_items.xml +++ b/app/src/main/res/layout/list_all_items.xml @@ -1,51 +1,56 @@ - - - + + android:orientation="horizontal" + android:padding="5dip" > + - + - + - - \ No newline at end of file + + + \ No newline at end of file diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 4221c85..01149c9 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -76,4 +76,6 @@ Klausur Andere Abgabe + Wintersemester %1$d/%2$d + Sommersemester %1$d \ 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 5500875..289dce6 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -84,4 +84,6 @@ Exam Other Deadline + Winter Semester %1$d/%2$d + Summer Semester %1$d From 4f8fa937a7d6384c4e47a284191fd2b1271979fc Mon Sep 17 00:00:00 2001 From: Caesar2011 Date: Tue, 13 Nov 2018 21:28:42 +0100 Subject: [PATCH 14/17] Added Lecturers to Overview and List --- .../java/de/sebse/fuplanner/MainActivity.java | 40 ++++++++++++----- .../fuplanner/fragments/ModulesAdapter.java | 2 +- .../moddetails/ModDetailOverviewAdapter.java | 29 ++++++++++++ .../fragments/moddetails/ModulePart.java | 1 + .../fuplanner/services/KVV/ModulesList.java | 3 +- .../services/KVV/types/Lecturer.java | 2 - .../fuplanner/services/KVV/types/Modules.java | 10 ++--- .../services/KVV/types/SortedListModule.java | 1 - .../sebse/fuplanner/tools/EventListener.java | 2 - .../fuplanner/tools/network/HTTPService.java | 1 - .../tools/ui/AnnouncementViewHolder.java | 1 - .../fuplanner/tools/ui/ListViewHolder.java | 2 - .../fuplanner/tools/ui/MailViewHolder.java | 26 +++++++++++ app/src/main/res/drawable/ic_mail.xml | 9 ++++ app/src/main/res/layout/list_all_mails.xml | 45 +++++++++++++++++++ app/src/main/res/values-de/strings.xml | 2 + app/src/main/res/values/strings.xml | 2 + 17 files changed, 150 insertions(+), 28 deletions(-) create mode 100644 app/src/main/java/de/sebse/fuplanner/tools/ui/MailViewHolder.java create mode 100644 app/src/main/res/drawable/ic_mail.xml create mode 100644 app/src/main/res/layout/list_all_mails.xml diff --git a/app/src/main/java/de/sebse/fuplanner/MainActivity.java b/app/src/main/java/de/sebse/fuplanner/MainActivity.java index f033de4..1a59f34 100644 --- a/app/src/main/java/de/sebse/fuplanner/MainActivity.java +++ b/app/src/main/java/de/sebse/fuplanner/MainActivity.java @@ -41,6 +41,7 @@ import de.sebse.fuplanner.services.KVV.KVVListener; import de.sebse.fuplanner.services.KVV.types.LoginToken; import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.tools.MainActivityListener; +import de.sebse.fuplanner.tools.NewAsyncQueue; import de.sebse.fuplanner.tools.RequestPermissionsResultListener; import de.sebse.fuplanner.tools.logging.Logger; import de.sebse.fuplanner.tools.network.NetworkCallback; @@ -77,6 +78,7 @@ public class MainActivity extends AppCompatActivity private CanteenBrowser mCanteenBrowser; private HashMap permissionListeners = new HashMap<>(); private boolean mOfflineBanner; + private NewAsyncQueue mQueue = new NewAsyncQueue(); @Override protected void onCreate(Bundle savedInstanceState) { @@ -422,7 +424,9 @@ public class MainActivity extends AppCompatActivity }); } - private void afterAnyMenuInflate(boolean isLoggedIn) { + private void afterAnyMenuInflate(boolean isLoggedIn, Runnable done) { + int MAX_COUNT = 2; + final int[] count = {0}; if (isLoggedIn) { getKVV().modules().list().recv(success -> { int i = 0; @@ -435,7 +439,11 @@ public class MainActivity extends AppCompatActivity }); i++; } - }, log::e); + if (++count[0] == MAX_COUNT) done.run(); + }, msg -> { + if (++count[0] == MAX_COUNT) done.run(); + log.e(msg); + }); } getCanteenBrowser().getCanteens(success -> { int i = 0; @@ -447,19 +455,27 @@ public class MainActivity extends AppCompatActivity }); i++; } - }, log::e); + if (++count[0] == MAX_COUNT) done.run(); + }, msg -> { + if (++count[0] == MAX_COUNT) done.run(); + log.e(msg); + }); } private void updateNavigation() { - boolean isLoggedIn = getKVV().account().isLoggedIn(); - setNavigationHeader(isLoggedIn); - mNavigationView.getMenu().clear(); - if (isLoggedIn) - mNavigationView.inflateMenu(R.menu.activity_main_drawer_login); - else - mNavigationView.inflateMenu(R.menu.activity_main_drawer); - afterAnyMenuInflate(isLoggedIn); - setNavigationSelection(); + mQueue.add(() -> { + boolean isLoggedIn = getKVV().account().isLoggedIn(); + setNavigationHeader(isLoggedIn); + mNavigationView.getMenu().clear(); + if (isLoggedIn) + mNavigationView.inflateMenu(R.menu.activity_main_drawer_login); + else + mNavigationView.inflateMenu(R.menu.activity_main_drawer); + afterAnyMenuInflate(isLoggedIn, () -> { + setNavigationSelection(); + mQueue.next(); + }); + }); } diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/ModulesAdapter.java b/app/src/main/java/de/sebse/fuplanner/fragments/ModulesAdapter.java index c1e32c9..3d770ea 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/ModulesAdapter.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/ModulesAdapter.java @@ -90,7 +90,7 @@ class ModulesAdapter extends RecyclerView.Adapter { Modules.Module module = ((Modules.Module) pair.second); iHolder.mTitle.setText(module.title); StringBuilder lecturers = new StringBuilder(); - for (Lecturer lecturer : module.lecturer) { + for (Lecturer lecturer: module.lecturer) { if (!lecturer.isResponsible()) continue; if (lecturers.length() > 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 8e95208..2edf8e0 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 @@ -16,11 +16,13 @@ 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.Event; +import de.sebse.fuplanner.services.KVV.types.Lecturer; import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.tools.UtilsDate; import de.sebse.fuplanner.tools.logging.Logger; import de.sebse.fuplanner.tools.ui.CustomViewHolder; import de.sebse.fuplanner.tools.ui.ItemViewHolder; +import de.sebse.fuplanner.tools.ui.MailViewHolder; import de.sebse.fuplanner.tools.ui.StringViewHolder; class ModDetailOverviewAdapter extends RecyclerView.Adapter { @@ -30,6 +32,7 @@ class ModDetailOverviewAdapter extends RecyclerView.Adapter(TYPE_HEADER, ModulePart.DESCRIPTION)); mPositionalData.add(new Pair<>(TYPE_DESCRIPTION, null)); + mPositionalData.add(new Pair<>(TYPE_HEADER, ModulePart.LECTURERS)); + for (int i = 0; i < mValue.lecturer.size(); i++) { + mPositionalData.add(new Pair<>(TYPE_MAIL, ModulePart.LECTURERS+1024*i)); + } mPositionalData.add(new Pair<>(TYPE_HEADER, ModulePart.ANNOUNCEMENT)); addPositionalListData(getAnnounceCount(), ModulePart.ANNOUNCEMENT); mPositionalData.add(new Pair<>(TYPE_HEADER, ModulePart.ASSIGNMENT)); @@ -90,6 +97,10 @@ class ModDetailOverviewAdapter extends RecyclerView.Adapter { + if (mListener != null) mListener.gotoFragmentPart(section, index); + });*/ + break; + } case TYPE_SHOW_MORE: CustomViewHolder c = (CustomViewHolder) holder; c.mView.setOnClickListener(view -> { diff --git a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModulePart.java b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModulePart.java index 1b6c693..bb25f62 100644 --- a/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModulePart.java +++ b/app/src/main/java/de/sebse/fuplanner/fragments/moddetails/ModulePart.java @@ -8,6 +8,7 @@ class ModulePart { static final int EVENT = 4; static final int GRADEBOOK = 5; static final int RESOURCES = 6; + static final int LECTURERS = 7; private static final int[] pages = new int[]{OVERVIEW, ANNOUNCEMENT, ASSIGNMENT, GRADEBOOK, RESOURCES, EVENT}; static int getPageCount() { diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesList.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesList.java index 5af11f7..c9f5129 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesList.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesList.java @@ -10,6 +10,7 @@ import org.json.JSONObject; import java.io.FileNotFoundException; import java.io.IOException; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.regex.MatchResult; import de.sebse.fuplanner.services.KVV.types.Lecturer; @@ -166,7 +167,7 @@ public class ModulesList extends HTTPService { lvNumbers.add(matchResult.group()); } String title = site.getString("entityTitle"); - HashSet lecturers = new HashSet<>(); + LinkedHashSet lecturers = new LinkedHashSet<>(); String kvv_lecturers = site.getJSONObject("props").optString("kvv_lecturers", null); if (kvv_lecturers != null) for (String lecturer : kvv_lecturers.split("#")) { if (lecturer.length() > 2) diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Lecturer.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Lecturer.java index c84737a..6ceb2b6 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Lecturer.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Lecturer.java @@ -4,8 +4,6 @@ import java.io.Serializable; import java.util.regex.Matcher; import java.util.regex.Pattern; -import de.sebse.fuplanner.tools.logging.Logger; - public class Lecturer implements Serializable { private final String firstName; private final String surname; 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 1b87e7d..9e5b6d7 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 @@ -10,10 +10,10 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; -import java.nio.channels.SeekableByteChannel; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; +import java.util.LinkedHashSet; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -33,7 +33,7 @@ public class Modules implements Iterable, Serializable { this.list = new SortedListModule(); } - public void addModule(@Nullable Semester semester, HashSet lvNumber, String title, HashSet lecturer, String type, String description, String ID) { + public void addModule(@Nullable Semester semester, HashSet lvNumber, String title, LinkedHashSet lecturer, String type, String description, String ID) { Module m = new Module(semester, lvNumber, title, lecturer, type, description, ID); this.list.add(m); } @@ -114,7 +114,7 @@ public class Modules implements Iterable, Serializable { @NotNull final HashSet lvNumber; @NotNull public final String title; @NotNull - public final HashSet lecturer; + public final ArrayList lecturer; @Nullable public final String type; @Nullable public final String description; @NotNull private final String ID; @@ -138,14 +138,14 @@ public class Modules implements Iterable, Serializable { return userPoint/maxPoint; } - private Module(@Nullable Semester semester, @NotNull HashSet lvNumber, @NotNull String title, @NotNull HashSet lecturer, @Nullable String type, @Nullable String description, @NotNull String ID) { + private Module(@Nullable Semester semester, @NotNull HashSet lvNumber, @NotNull String title, @NotNull LinkedHashSet lecturer, @Nullable String type, @Nullable String description, @NotNull String ID) { title = title.replaceAll("(.*?) (S[0-9]{2}|W[0-9/]{5})", "$1"); this.semester = semester; this.lvNumber = lvNumber; this.title = title; - this.lecturer = lecturer; + this.lecturer = new ArrayList<>(lecturer); this.type = type; this.description = description; this.ID = ID; diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/SortedListModule.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/SortedListModule.java index b3b480e..5c226f4 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/SortedListModule.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/SortedListModule.java @@ -1,7 +1,6 @@ package de.sebse.fuplanner.services.KVV.types; import androidx.annotation.Nullable; -import de.sebse.fuplanner.tools.Regex; import de.sebse.fuplanner.tools.SortedList; public class SortedListModule extends SortedList { diff --git a/app/src/main/java/de/sebse/fuplanner/tools/EventListener.java b/app/src/main/java/de/sebse/fuplanner/tools/EventListener.java index 7e1afd2..42bbbcf 100644 --- a/app/src/main/java/de/sebse/fuplanner/tools/EventListener.java +++ b/app/src/main/java/de/sebse/fuplanner/tools/EventListener.java @@ -1,7 +1,5 @@ package de.sebse.fuplanner.tools; -import com.google.android.gms.common.util.Function; - import java.util.HashMap; public class EventListener { diff --git a/app/src/main/java/de/sebse/fuplanner/tools/network/HTTPService.java b/app/src/main/java/de/sebse/fuplanner/tools/network/HTTPService.java index 96b9b00..ea82635 100644 --- a/app/src/main/java/de/sebse/fuplanner/tools/network/HTTPService.java +++ b/app/src/main/java/de/sebse/fuplanner/tools/network/HTTPService.java @@ -10,7 +10,6 @@ import com.android.volley.Response; import com.android.volley.TimeoutError; import com.android.volley.VolleyError; import com.android.volley.toolbox.Volley; -import com.google.android.gms.common.util.Function; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; diff --git a/app/src/main/java/de/sebse/fuplanner/tools/ui/AnnouncementViewHolder.java b/app/src/main/java/de/sebse/fuplanner/tools/ui/AnnouncementViewHolder.java index 91694b7..d8ae17b 100644 --- a/app/src/main/java/de/sebse/fuplanner/tools/ui/AnnouncementViewHolder.java +++ b/app/src/main/java/de/sebse/fuplanner/tools/ui/AnnouncementViewHolder.java @@ -1,7 +1,6 @@ package de.sebse.fuplanner.tools.ui; import android.view.View; -import android.widget.ImageView; import android.widget.TextView; import com.cunoraz.tagview.TagView; diff --git a/app/src/main/java/de/sebse/fuplanner/tools/ui/ListViewHolder.java b/app/src/main/java/de/sebse/fuplanner/tools/ui/ListViewHolder.java index 9c7534f..8e04b95 100644 --- a/app/src/main/java/de/sebse/fuplanner/tools/ui/ListViewHolder.java +++ b/app/src/main/java/de/sebse/fuplanner/tools/ui/ListViewHolder.java @@ -1,8 +1,6 @@ package de.sebse.fuplanner.tools.ui; import android.view.View; -import android.widget.ListView; -import android.widget.TextView; import androidx.recyclerview.widget.RecyclerView; import de.sebse.fuplanner.R; diff --git a/app/src/main/java/de/sebse/fuplanner/tools/ui/MailViewHolder.java b/app/src/main/java/de/sebse/fuplanner/tools/ui/MailViewHolder.java new file mode 100644 index 0000000..c24b47e --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/tools/ui/MailViewHolder.java @@ -0,0 +1,26 @@ +package de.sebse.fuplanner.tools.ui; + +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.recyclerview.widget.RecyclerView; +import de.sebse.fuplanner.R; + +public class MailViewHolder extends StringViewHolder { + public final TextView mTitle; + public final TextView mSubLeft; + public final ImageView mIcon; + + public MailViewHolder(View view) { + super(view); + mTitle = view.findViewById(R.id.title); + mSubLeft = view.findViewById(R.id.sub_left); + mIcon = view.findViewById(R.id.icon); + } + + @Override + public String toString() { + return super.toString() + " '" + mTitle.getText() + "' '" + mSubLeft.getText() + "'"; + } +} diff --git a/app/src/main/res/drawable/ic_mail.xml b/app/src/main/res/drawable/ic_mail.xml new file mode 100644 index 0000000..6701eb8 --- /dev/null +++ b/app/src/main/res/drawable/ic_mail.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/list_all_mails.xml b/app/src/main/res/layout/list_all_mails.xml new file mode 100644 index 0000000..ce391c3 --- /dev/null +++ b/app/src/main/res/layout/list_all_mails.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 01149c9..5d99002 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -78,4 +78,6 @@ Abgabe Wintersemester %1$d/%2$d Sommersemester %1$d + Dozenten + Mail Icon \ 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 289dce6..a69e4ea 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -86,4 +86,6 @@ Deadline Winter Semester %1$d/%2$d Summer Semester %1$d + Lecturers + Mail Icon From 6c146ad3d94249a5f2720cc708233ff0fcabd8e8 Mon Sep 17 00:00:00 2001 From: Caesar2011 Date: Tue, 13 Nov 2018 22:18:14 +0100 Subject: [PATCH 15/17] =?UTF-8?q?E-Mail=20Intent=20eingef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../moddetails/ModDetailOverviewAdapter.java | 15 +++++++++++---- app/src/main/res/values-de/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + 3 files changed, 13 insertions(+), 4 deletions(-) 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 2edf8e0..8b14a70 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 @@ -1,5 +1,7 @@ package de.sebse.fuplanner.fragments.moddetails; +import android.content.Intent; +import android.net.Uri; import android.util.Pair; import android.view.LayoutInflater; import android.view.View; @@ -205,10 +207,15 @@ class ModDetailOverviewAdapter extends RecyclerView.Adapter { - if (mListener != null) mListener.gotoFragmentPart(section, index); - });*/ + m.mIcon.setOnClickListener(view -> { + String defaultText = m.mView.getResources().getString(R.string.mail_default_text, + lecturer.getName()); + Intent emailIntent = new Intent(Intent.ACTION_SENDTO); + emailIntent.setData(Uri.parse("mailto:"+lecturer.getMail())); + emailIntent.putExtra(Intent.EXTRA_SUBJECT, mValue.title); + emailIntent.putExtra(Intent.EXTRA_TEXT, defaultText); + m.mView.getContext().startActivity(Intent.createChooser(emailIntent, mValue.title)); + }); break; } case TYPE_SHOW_MORE: diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 5d99002..bc69be7 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -80,4 +80,5 @@ Sommersemester %1$d Dozenten Mail Icon + Hallo %1$s, \n\nMit freundlichen Grüßen\n\nGesendet von der FUPlanner Android App \ 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 a69e4ea..e0f053e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -88,4 +88,5 @@ Summer Semester %1$d Lecturers Mail Icon + Dear %1$s, \n\nYours sincerely\n\nSend by FUPlanner Android App From 460713c0dbe5d24fc69cf27753e03aa4eb86b004 Mon Sep 17 00:00:00 2001 From: Caesar2011 Date: Tue, 13 Nov 2018 23:53:59 +0100 Subject: [PATCH 16/17] Bug Fixes --- app/src/main/java/de/sebse/fuplanner/MainActivity.java | 3 +-- .../java/de/sebse/fuplanner/services/KVV/types/Semester.java | 4 +++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/de/sebse/fuplanner/MainActivity.java b/app/src/main/java/de/sebse/fuplanner/MainActivity.java index 1a59f34..5dfd535 100644 --- a/app/src/main/java/de/sebse/fuplanner/MainActivity.java +++ b/app/src/main/java/de/sebse/fuplanner/MainActivity.java @@ -189,7 +189,6 @@ public class MainActivity extends AppCompatActivity this.getGoogleAuth().deleteLoginState(credentials.getUsername(), credentials.getPassword()); } }); - this.toLogoutState(); break; } @@ -425,7 +424,7 @@ public class MainActivity extends AppCompatActivity } private void afterAnyMenuInflate(boolean isLoggedIn, Runnable done) { - int MAX_COUNT = 2; + int MAX_COUNT = isLoggedIn ? 2 : 1; final int[] count = {0}; if (isLoggedIn) { getKVV().modules().list().recv(success -> { diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Semester.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Semester.java index 1e81d70..76605aa 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Semester.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/types/Semester.java @@ -1,9 +1,11 @@ package de.sebse.fuplanner.services.KVV.types; +import java.io.Serializable; + import androidx.annotation.Nullable; import de.sebse.fuplanner.tools.Regex; -public class Semester { +public class Semester implements Serializable { public static final int SEM_WS = 1; public static final int SEM_SS = 2; private int type; From 342d81f5c464640cdb2110a63ef2c3d4b3819eac Mon Sep 17 00:00:00 2001 From: Caesar2011 Date: Wed, 14 Nov 2018 01:24:12 +0100 Subject: [PATCH 17/17] Fixed Offline Mode --- app/src/main/java/de/sebse/fuplanner/MainActivity.java | 4 +--- .../java/de/sebse/fuplanner/services/KVV/KVVListener.java | 2 +- .../main/java/de/sebse/fuplanner/services/KVV/Login.java | 6 +++--- .../java/de/sebse/fuplanner/services/KVV/Modules.java | 8 ++++---- .../java/de/sebse/fuplanner/services/KVV/ModulesList.java | 5 ++++- .../java/de/sebse/fuplanner/services/KVV/PartModules.java | 4 ++-- app/src/main/res/values-de/strings.xml | 2 +- app/src/main/res/values/strings.xml | 2 +- 8 files changed, 17 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/de/sebse/fuplanner/MainActivity.java b/app/src/main/java/de/sebse/fuplanner/MainActivity.java index 5dfd535..c0bf213 100644 --- a/app/src/main/java/de/sebse/fuplanner/MainActivity.java +++ b/app/src/main/java/de/sebse/fuplanner/MainActivity.java @@ -341,7 +341,6 @@ public class MainActivity extends AppCompatActivity this.fragmentData = newData; invalidateOptionsMenu(); - //TODO navigation selection } private void setOfflineBanner(boolean visible) { @@ -356,7 +355,6 @@ public class MainActivity extends AppCompatActivity viewNoConnection.setVisibility(View.VISIBLE); else viewNoConnection.setVisibility(View.GONE); - } private void setNavigationSelection() { @@ -566,7 +564,7 @@ public class MainActivity extends AppCompatActivity } @Override - public void onNetworkResponse(NetworkResponse error) { + public void onKVVNetworkResponse(NetworkResponse error) { setRefreshFailedBanner(error != null); } } diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVListener.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVListener.java index 72ffbce..402899f 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVListener.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/KVVListener.java @@ -16,5 +16,5 @@ public interface KVVListener { void onModuleListChange(); - void onNetworkResponse(NetworkResponse error); + void onKVVNetworkResponse(NetworkResponse error); } diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/Login.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/Login.java index b10473e..5f6d21d 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/Login.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/Login.java @@ -31,7 +31,7 @@ public class Login extends HTTPService { this.mListener = listener; } - public void doOnlineLogin(String username, String password, NetworkCallback callback, NetworkErrorCallback errorCallback) { + public void doOnlineLogin(@NotNull String username, @NotNull String password, NetworkCallback callback, NetworkErrorCallback errorCallback) { if (mLoginPending) { errorCallback.onError(new NetworkError(100160, -1, "Login already pending!")); } @@ -116,7 +116,7 @@ public class Login extends HTTPService { return isLoggedIn() && mOnlineMode; } - void testLoginToken(NetworkCallback callback, NetworkErrorCallback errorCallback) { + void testLoginToken(@NotNull NetworkCallback callback, @NotNull NetworkErrorCallback errorCallback) { if (mToken == null) { errorCallback.onError(new NetworkError(100173, -1, "Not logged in!")); return; @@ -124,7 +124,7 @@ public class Login extends HTTPService { testLoginToken(mToken, callback, errorCallback); } - private void testLoginToken(@NotNull LoginToken token, NetworkCallback callback, NetworkErrorCallback errorCallback) { + private void testLoginToken(@NotNull LoginToken token, @NotNull NetworkCallback callback, @NotNull NetworkErrorCallback errorCallback) { get(String.format("https://kvv.imp.fu-berlin.de/direct/profile/%s.json", token.getUsername()), token.getCookies(), response -> { String body = response.getParsed(); if (body == null) { diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/Modules.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/Modules.java index eba21a5..8c8b54a 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/Modules.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/Modules.java @@ -56,8 +56,8 @@ public class Modules { public ModulesList list() { if (mList == null) { mList = new ModulesList(mLogin, mListener, context); - mList.addErrorListener("Modules", error -> mListener.onNetworkResponse(error.networkResponse)); - mList.addSuccessListener("Modules", success -> mListener.onNetworkResponse(null)); + mList.addErrorListener("Modules", error -> mListener.onKVVNetworkResponse(error.networkResponse)); + mList.addSuccessListener("Modules", success -> mListener.onKVVNetworkResponse(null)); } return mList; } @@ -68,8 +68,8 @@ public class Modules { Part o = mAddons.get(addon); if (o == null) { o = creatorInterface.create(); - o.addErrorListener("Modules", error -> mListener.onNetworkResponse(error.networkResponse)); - o.addSuccessListener("Modules", success -> mListener.onNetworkResponse(null)); + o.addErrorListener("Modules", error -> mListener.onKVVNetworkResponse(error.networkResponse)); + o.addSuccessListener("Modules", success -> mListener.onKVVNetworkResponse(null)); mAddons.put(addon, o); } return o; diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesList.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesList.java index c9f5129..cc5b8f9 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesList.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/ModulesList.java @@ -126,7 +126,10 @@ public class ModulesList extends HTTPService { mLogin.refreshLogin(success -> { recv(callback, errorCallback, forceRefresh, retries-1); mQueue.next(); - }, errorCallback); + }, error1 -> { + errorCallback.onError(error1); + mQueue.next(); + }); return; } errorCallback.onError(error); diff --git a/app/src/main/java/de/sebse/fuplanner/services/KVV/PartModules.java b/app/src/main/java/de/sebse/fuplanner/services/KVV/PartModules.java index 64cb4b8..0301135 100644 --- a/app/src/main/java/de/sebse/fuplanner/services/KVV/PartModules.java +++ b/app/src/main/java/de/sebse/fuplanner/services/KVV/PartModules.java @@ -36,8 +36,8 @@ abstract class PartModules extends Part { mLogin.refreshLogin(success -> { recv(module, callback, errorCallback, forceRefresh, retries-1); mQueue.next(); - }, error2 -> { - errorCallback.onError(error2); + }, error1 -> { + errorCallback.onError(error1); mQueue.next(); }); return; diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index bc69be7..08af5f2 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -80,5 +80,5 @@ Sommersemester %1$d Dozenten Mail Icon - Hallo %1$s, \n\nMit freundlichen Grüßen\n\nGesendet von der FUPlanner Android App + Hallo %1$s, \n\n\n\nMit freundlichen Grüßen\n\n\n\nGesendet von der FUPlanner Android App \ 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 e0f053e..9528137 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -88,5 +88,5 @@ Summer Semester %1$d Lecturers Mail Icon - Dear %1$s, \n\nYours sincerely\n\nSend by FUPlanner Android App + Dear %1$s, \n\n\n\nYours sincerely\n\n\n\nSend by FUPlanner Android App