Removed Old KVV
This commit is contained in:
@@ -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<de.sebse.fuplanner.services.NewKVV.types.Modules.Module> it = success.latestSemesterIterator(); it.hasNext(); ) {
|
||||
de.sebse.fuplanner.services.NewKVV.types.Modules.Module module = it.next();
|
||||
for (Iterator<de.sebse.fuplanner.services.KVV.types.Modules.Module> 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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<CustomViewHolder> {
|
||||
private static final String VALUE_LECTURE = "Class section - Lecture";
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 -> {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<RecyclerView.ViewHolder> {
|
||||
|
||||
@@ -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 -> {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 -> {
|
||||
|
||||
@@ -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("")){
|
||||
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", success1)){
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(success1));
|
||||
contextInterface.get().startActivity(intent);
|
||||
if (Regex.has("^http", success)){
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(success));
|
||||
context.startActivity(intent);
|
||||
}
|
||||
else {
|
||||
fileOpen(new File(success1));
|
||||
fileOpen(new File(success));
|
||||
}
|
||||
|
||||
}
|
||||
}, log::e, file.getTitle(), file.getUrl(), folderName, downloadNew);
|
||||
}
|
||||
}, 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;
|
||||
|
||||
@@ -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<LastTokenCallback> updatingList;
|
||||
private final HashMap<String, Object> 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;
|
||||
}
|
||||
|
||||
public void login(@NonNull String username, @NonNull String password, final NetworkCallback<LoginToken> 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);
|
||||
}
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void invalidate() {
|
||||
if (lastToken != null) {
|
||||
new KVVLogin(context).deleteOffline();
|
||||
lastToken = null;
|
||||
}
|
||||
addons.clear();
|
||||
this.isLoginPending = true;
|
||||
}
|
||||
|
||||
public void getModule(String id, final NetworkCallback<Modules.Module> callback, final NetworkErrorCallback error) {
|
||||
getModule(id, callback, error, false);
|
||||
}
|
||||
|
||||
public void getModule(String id, final NetworkCallback<Modules.Module> callback, final NetworkErrorCallback error, boolean forceRefresh) {
|
||||
getModulePart(modules -> modules.getModule(id, saveOnCallback(modules, callback, forceRefresh), errorOnCallback(error), forceRefresh));
|
||||
}
|
||||
|
||||
public void getModuleList(final NetworkCallback<Modules> callback, final NetworkErrorCallback error) {
|
||||
getModuleList(callback, error, false);
|
||||
}
|
||||
|
||||
public void getModuleList(final NetworkCallback<Modules> 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<Pair<Modules.Module, Boolean>> callback, final NetworkErrorCallback error) {
|
||||
getModuleDetails(module, callback, error, false);
|
||||
}
|
||||
|
||||
public void getModuleDetails(Modules.Module module, final NetworkCallback<Pair<Modules.Module, Boolean>> 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<Modules.Module> callback, final NetworkErrorCallback error) {
|
||||
getModuleAnnouncements(module, callback, error, false);
|
||||
}
|
||||
|
||||
public void getModuleAnnouncements(Modules.Module module, final NetworkCallback<Modules.Module> 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<Modules.Module> callback, final NetworkErrorCallback error) {
|
||||
getModuleAssignments(module, callback, error, false);
|
||||
}
|
||||
|
||||
public void getModuleAssignments(Modules.Module module, final NetworkCallback<Modules.Module> 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<Modules.Module> callback, final NetworkErrorCallback error) {
|
||||
getModuleEvents(module, callback, error, false);
|
||||
}
|
||||
|
||||
public void getModuleEvents(Modules.Module module, final NetworkCallback<Modules.Module> 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<Modules.Module> callback, final NetworkErrorCallback error) {
|
||||
getModuleGradebook(module, callback, error, false);
|
||||
}
|
||||
|
||||
public void getModuleGradebook(Modules.Module module, final NetworkCallback<Modules.Module> 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<Modules.Module> callback, final NetworkErrorCallback error) {
|
||||
getModuleResources(module, callback, error, false);
|
||||
}
|
||||
|
||||
public void getModuleResources(Modules.Module module, final NetworkCallback<Modules.Module> callback, final NetworkErrorCallback error, boolean forceRefresh) {
|
||||
getModulePart(modules -> modules.getResources(module, saveOnCallback(modules, callback, forceRefresh), errorOnCallback(error), forceRefresh));
|
||||
}
|
||||
|
||||
public void getResourceFile(final NetworkCallback<String> 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));
|
||||
});
|
||||
@NotNull
|
||||
public KVVModules modules() {
|
||||
return (KVVModules) addAndGet("module", () -> new KVVModules(account(), mContext));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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);
|
||||
|
||||
@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);
|
||||
}
|
||||
func.apply(modules);
|
||||
});
|
||||
return o;
|
||||
}
|
||||
|
||||
private<T> NetworkCallback<T> saveOnCallback(KVVModuleList modules, NetworkCallback<T> 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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<LoginToken> 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<LoginToken> 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);
|
||||
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<LoginToken> 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<LoginToken> 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<LoginToken> success, NetworkErrorCallback error) {
|
||||
mListener.getCredentials(credentials -> {
|
||||
doOnlineLogin(credentials.getUsername(), credentials.getPassword(), success, error);
|
||||
}, e -> {
|
||||
logout(false);
|
||||
error.onError(e);
|
||||
});
|
||||
} else {
|
||||
this.loginToken = null;
|
||||
login(username, password, callback, errorCallback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -320,5 +441,3 @@ class KVVLogin extends HTTPService {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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<Modules> 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<Modules> 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<String> 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<Lecturer> 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<Modules.Module> callback, final NetworkErrorCallback errorCallback, boolean forceRefresh) {
|
||||
this.getModuleList(success -> {
|
||||
callback.onResponse(success.get(id));
|
||||
}, errorCallback, forceRefresh);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void getModuleDetails(Modules.Module module, final NetworkCallback<Pair<Modules.Module, Boolean>> callback, final NetworkErrorCallback errorCallback, boolean forceRefresh) {
|
||||
AtomicInteger returns = new AtomicInteger(0);
|
||||
AtomicReference<NetworkError> lastError = new AtomicReference<>(null);
|
||||
final AtomicInteger items = new AtomicInteger(0);
|
||||
NetworkCallback<Modules.Module> 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<Modules.Module> 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<ArrayList<Announcement>> 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<Announcement> 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<String> urls = new ArrayList<>();
|
||||
for (int j =0; j<attachments.length(); j++){
|
||||
urls.add(attachments.getJSONObject(j).optString("url",null));
|
||||
}
|
||||
|
||||
announcements.add(new Announcement(id, title, text, createdBy, createdOn, urls));
|
||||
}
|
||||
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
errorCallback.onError(new NetworkError(101202, 403, "Cannot parse announcements!"));
|
||||
return;
|
||||
}
|
||||
// Empty announcements *may be* because token is invalid -> 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<Modules.Module> 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<AssignmentList> 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<String> urls = new ArrayList<>();
|
||||
for (int j = 0; j<attachments.length(); j++){
|
||||
urls.add(attachments.getJSONObject(j).getString("url"));
|
||||
}
|
||||
assignments.add(0, new Assignment(id, title, dueTime, gradebookItemName, gradeScale, urls, instructions));
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
errorCallback.onError(new NetworkError(101302, 403, "Cannot parse announcements!"));
|
||||
return;
|
||||
}
|
||||
// Empty assignments *may be* because token is invalid -> 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<Modules.Module> 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<EventList> 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<Modules.Module> 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<ArrayList<Gradebook>> 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> 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<Modules.Module> 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<ArrayList<Resource>> 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<Resource> 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<Resource> 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<String> 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<String> 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.sebse.fuplanner.services.NewKVV;
|
||||
package de.sebse.fuplanner.services.KVV;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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());
|
||||
@@ -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<ArrayList<Resource>> {
|
||||
|
||||
@Override
|
||||
protected boolean setPart(Modules.Module module, ArrayList<Resource> 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<ArrayList<Resource>> {
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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<T> extends Part<Modules.Module> {
|
||||
});
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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<LoginToken> 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!")));
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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<Modules.Module>, 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<String> lvNumber, String title, HashSet<Lecturer> lecturer, String type, String description, String ID) {
|
||||
public void addModule(@Nullable String semester, HashSet<String> lvNumber, String title, HashSet<Lecturer> 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<Modules.Module>, 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<Modules.Module>, Serializable {
|
||||
}
|
||||
|
||||
public class Module implements Serializable {
|
||||
public final String semester;
|
||||
final HashSet<String> lvNumber;
|
||||
public final String title;
|
||||
final HashSet<Lecturer> lecturer;
|
||||
public final String type;
|
||||
public final String description;
|
||||
private final String ID;
|
||||
@Nullable public final String semester;
|
||||
@NotNull final HashSet<String> lvNumber;
|
||||
@NotNull public final String title;
|
||||
@NotNull final HashSet<Lecturer> lecturer;
|
||||
@Nullable public final String type;
|
||||
@Nullable public final String description;
|
||||
@NotNull private final String ID;
|
||||
@Nullable public ArrayList<Announcement> announcements;
|
||||
@Nullable public AssignmentList assignments;
|
||||
@Nullable public EventList events;
|
||||
@Nullable public ArrayList<Gradebook> gradebook;
|
||||
@Nullable public ArrayList<Grade> gradebook;
|
||||
@Nullable public ArrayList<Resource> 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<Modules.Module>, Serializable {
|
||||
return userPoint/maxPoint;
|
||||
}
|
||||
|
||||
private Module(String semester, HashSet<String> lvNumber, String title, HashSet<Lecturer> lecturer, String type, String description, String ID) {
|
||||
private Module(@Nullable String semester, @NotNull HashSet<String> lvNumber, @NotNull String title, @NotNull HashSet<Lecturer> 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<Modules.Module>, Serializable {
|
||||
this.ID = ID;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String getID() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -63,6 +63,6 @@ public class SortedListModule extends SortedList<Modules.Module, String, String>
|
||||
|
||||
@Override
|
||||
public boolean hasFilter(Modules.Module o1, String filter) {
|
||||
return o1.semester.equals(filter);
|
||||
return o1.semester != null && o1.semester.equals(filter);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Integer> 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);
|
||||
}
|
||||
}
|
||||
@@ -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<String, Object> 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();
|
||||
}
|
||||
}
|
||||
@@ -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<LoginToken> 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<LoginToken> 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<LoginToken> 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<LoginToken> 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<LoginToken> 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<HashMap<String, String>> 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<String, String> 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<HashMap<String, String>> callback, final NetworkErrorCallback errorCallback) {
|
||||
HashMap<String, String> 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<String, String> 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<HashMap<String, String>> 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<String, String> 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<HashMap<String, String>> callback, final NetworkErrorCallback errorCallback) {
|
||||
HashMap<String, String> cookies = new HashMap<>();
|
||||
cookies.put("JSESSIONID", JSESSIONID);
|
||||
cookies.put("_idp_authn_lc_key", _idp_authn_lc_key);
|
||||
cookies.put("ROUTEID", ROUTEID);
|
||||
HashMap<String, String> 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<String, String> 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<HashMap<String, String>> callback, final NetworkErrorCallback errorCallback) {
|
||||
HashMap<String, String> 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<String, String> 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<HashMap<String, String>> callback, final NetworkErrorCallback errorCallback) {
|
||||
HashMap<String, String> cookies = new HashMap<>();
|
||||
cookies.put("JSESSIONID", JSESSIONID);
|
||||
HashMap<String, String> 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<String, String> 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<HashMap<String, String>> 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<String, String> getCookie(String cookies, String[] names) throws NoSuchFieldException {
|
||||
HashMap<String, String> result = new HashMap<>();
|
||||
for (String name: names) {
|
||||
result.put(name,this.getCookie(cookies, name));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -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<String> urls;
|
||||
|
||||
public Announcement(String id, String title, String body, String createdBy, long createdOn, ArrayList<String> urls) {
|
||||
|
||||
this.id = id;
|
||||
this.title = title;
|
||||
this.body = body;
|
||||
this.createdBy = createdBy;
|
||||
this.createdOn = createdOn;
|
||||
this.urls = urls;
|
||||
}
|
||||
|
||||
public ArrayList<String> 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());
|
||||
}
|
||||
}
|
||||
@@ -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<String> urls;
|
||||
private final String instructions;
|
||||
|
||||
public Assignment(String id, String title, long dueTime, String gradebookItemName, String gradeScale, ArrayList<String> 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<String> 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());
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package de.sebse.fuplanner.services.NewKVV.types;
|
||||
|
||||
import de.sebse.fuplanner.tools.DateSortedList;
|
||||
|
||||
public class AssignmentList extends DateSortedList<Assignment> {
|
||||
|
||||
@Override
|
||||
public long getDateByItem(Assignment item) {
|
||||
return item.getDueDate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean reversed() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package de.sebse.fuplanner.services.NewKVV.types;
|
||||
|
||||
import de.sebse.fuplanner.tools.DateSortedList;
|
||||
|
||||
public class EventList extends DateSortedList<Event> {
|
||||
|
||||
@Override
|
||||
public long getDateByItem(Event item) {
|
||||
return item.getEndDate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean reversed() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -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<Group> 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<Group> getGroups() {
|
||||
return Collections.unmodifiableList(arrayList);
|
||||
}
|
||||
|
||||
public class Group {
|
||||
private long firstDate;
|
||||
private long lastDate;
|
||||
private ArrayList<Long> 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<Long> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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<String, String> getCookies() {
|
||||
HashMap<String, String> 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<String, String> cookies = this.getCookies();
|
||||
for (String header: cookies.keySet()) {
|
||||
result.append(header).append("=").append(cookies.get(header)).append(";");
|
||||
}
|
||||
return result.substring(0, result.length()-1);
|
||||
}
|
||||
}
|
||||
@@ -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<Modules.Module>, 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<String> lvNumber, String title, HashSet<Lecturer> 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<Module> iterator() {
|
||||
return this.list.iterator();
|
||||
}
|
||||
|
||||
public Iterator<Module> 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<String> lvNumber;
|
||||
@NotNull public final String title;
|
||||
@NotNull final HashSet<Lecturer> lecturer;
|
||||
@Nullable public final String type;
|
||||
@Nullable public final String description;
|
||||
@NotNull private final String ID;
|
||||
@Nullable public ArrayList<Announcement> announcements;
|
||||
@Nullable public AssignmentList assignments;
|
||||
@Nullable public EventList events;
|
||||
@Nullable public ArrayList<Grade> gradebook;
|
||||
@Nullable public ArrayList<Resource> 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<String> lvNumber, @NotNull String title, @NotNull HashSet<Lecturer> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<Resource> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<Modules.Module, String, String> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
@@ -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 :)
|
||||
|
||||
@@ -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 :)
|
||||
|
||||
Reference in New Issue
Block a user