Bug fixing, Implemented Rescource, Event and Gradebook

This commit is contained in:
Caesar2011
2018-11-09 20:11:40 +01:00
parent 0439c845a5
commit af9d2fed0e
28 changed files with 818 additions and 147 deletions

View File

@@ -16,9 +16,9 @@ import java.util.List;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import de.sebse.fuplanner.R; import de.sebse.fuplanner.R;
import de.sebse.fuplanner.services.KVV.KVV; import de.sebse.fuplanner.services.NewKVV.KVV;
import de.sebse.fuplanner.services.KVV.types.Event; import de.sebse.fuplanner.services.NewKVV.types.Event;
import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.services.NewKVV.types.Modules;
import de.sebse.fuplanner.tools.UtilsDate; import de.sebse.fuplanner.tools.UtilsDate;
import de.sebse.fuplanner.tools.MainActivityListener; import de.sebse.fuplanner.tools.MainActivityListener;
import de.sebse.fuplanner.tools.logging.Logger; import de.sebse.fuplanner.tools.logging.Logger;
@@ -59,13 +59,12 @@ public class ScheduleFragment extends Fragment implements MonthLoader.MonthChang
} }
public void invalidate(boolean forceRefresh) { public void invalidate(boolean forceRefresh) {
if (mListener != null) { if (mListener == null) return;
KVV kvv = mListener.getKVV(); mListener.getNewKVV().modules().list().recv(modules -> {
kvv.getModuleList((Modules success) -> { mModules = modules;
mModules = success;
final int[] i = {0}; final int[] i = {0};
for (Modules.Module module: mModules) { for (Modules.Module module: mModules) {
kvv.getModuleEvents(module, success1 -> { mListener.getNewKVV().modules().events().recv(module, success1 -> {
i[0]++; i[0]++;
if (i[0] >= mModules.size()) { if (i[0] >= mModules.size()) {
if (mWeekView != null) { if (mWeekView != null) {
@@ -77,7 +76,6 @@ public class ScheduleFragment extends Fragment implements MonthLoader.MonthChang
} }
}, log::e, forceRefresh); }, log::e, forceRefresh);
} }
}
@Override @Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
@@ -183,10 +181,8 @@ public class ScheduleFragment extends Fragment implements MonthLoader.MonthChang
String moduleId = idParts[0]; String moduleId = idParts[0];
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getContext()); AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getContext());
if (mListener != null) { if (mListener == null) return;
KVV kvv = mListener.getKVV(); mListener.getNewKVV().modules().list().find(moduleId, module -> {
kvv.getModuleList((Modules success) -> {
Modules.Module module = success.get(moduleId);
String moduleName = module.title; String moduleName = module.title;
alertDialogBuilder alertDialogBuilder
.setTitle(event.getName()) .setTitle(event.getName())
@@ -203,4 +199,3 @@ public class ScheduleFragment extends Fragment implements MonthLoader.MonthChang
}, log::e); }, log::e);
} }
} }
}

View File

@@ -16,7 +16,7 @@ import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import de.sebse.fuplanner.R; import de.sebse.fuplanner.R;
import de.sebse.fuplanner.services.KVV.Download; import de.sebse.fuplanner.services.NewKVV.Download;
import de.sebse.fuplanner.services.NewKVV.types.Announcement; import de.sebse.fuplanner.services.NewKVV.types.Announcement;
import de.sebse.fuplanner.services.NewKVV.types.Modules; import de.sebse.fuplanner.services.NewKVV.types.Modules;
import de.sebse.fuplanner.tools.Regex; import de.sebse.fuplanner.tools.Regex;

View File

@@ -14,7 +14,7 @@ import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import de.sebse.fuplanner.MainActivity; import de.sebse.fuplanner.MainActivity;
import de.sebse.fuplanner.R; import de.sebse.fuplanner.R;
import de.sebse.fuplanner.services.KVV.Download; import de.sebse.fuplanner.services.NewKVV.Download;
import de.sebse.fuplanner.services.NewKVV.types.Modules; import de.sebse.fuplanner.services.NewKVV.types.Modules;
import de.sebse.fuplanner.tools.MainActivityListener; import de.sebse.fuplanner.tools.MainActivityListener;
import de.sebse.fuplanner.tools.logging.Logger; import de.sebse.fuplanner.tools.logging.Logger;

View File

@@ -16,7 +16,7 @@ import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import de.sebse.fuplanner.R; import de.sebse.fuplanner.R;
import de.sebse.fuplanner.services.KVV.Download; import de.sebse.fuplanner.services.NewKVV.Download;
import de.sebse.fuplanner.services.NewKVV.types.Assignment; import de.sebse.fuplanner.services.NewKVV.types.Assignment;
import de.sebse.fuplanner.services.NewKVV.types.Modules; import de.sebse.fuplanner.services.NewKVV.types.Modules;
import de.sebse.fuplanner.tools.Regex; import de.sebse.fuplanner.tools.Regex;

View File

@@ -14,7 +14,7 @@ import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import de.sebse.fuplanner.MainActivity; import de.sebse.fuplanner.MainActivity;
import de.sebse.fuplanner.R; import de.sebse.fuplanner.R;
import de.sebse.fuplanner.services.KVV.Download; import de.sebse.fuplanner.services.NewKVV.Download;
import de.sebse.fuplanner.services.NewKVV.types.Modules; import de.sebse.fuplanner.services.NewKVV.types.Modules;
import de.sebse.fuplanner.tools.MainActivityListener; import de.sebse.fuplanner.tools.MainActivityListener;
import de.sebse.fuplanner.tools.logging.Logger; import de.sebse.fuplanner.tools.logging.Logger;
@@ -95,6 +95,7 @@ public class ModDetailAssignmentFragment extends Fragment implements Download.On
@Override @Override
public void request(String title, String url) { public void request(String title, String url) {
log.d(title, url, mListener);
if (mListener == null) if (mListener == null)
return; return;
mListener.getNewKVV().modules().list().find(mItemPos, (Modules.Module module) -> { mListener.getNewKVV().modules().list().find(mItemPos, (Modules.Module module) -> {

View File

@@ -14,10 +14,10 @@ import androidx.annotation.NonNull;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import de.sebse.fuplanner.R; import de.sebse.fuplanner.R;
import de.sebse.fuplanner.services.KVV.types.Event; import de.sebse.fuplanner.services.NewKVV.types.Event;
import de.sebse.fuplanner.services.KVV.types.EventList; import de.sebse.fuplanner.services.NewKVV.types.EventList;
import de.sebse.fuplanner.services.KVV.types.GroupedEvents; import de.sebse.fuplanner.services.NewKVV.types.GroupedEvents;
import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.services.NewKVV.types.Modules;
import de.sebse.fuplanner.tools.Triplet; import de.sebse.fuplanner.tools.Triplet;
import de.sebse.fuplanner.tools.UtilsDate; import de.sebse.fuplanner.tools.UtilsDate;
import de.sebse.fuplanner.tools.logging.Logger; import de.sebse.fuplanner.tools.logging.Logger;

View File

@@ -10,14 +10,11 @@ import java.util.ArrayList;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import de.sebse.fuplanner.R; import de.sebse.fuplanner.R;
import de.sebse.fuplanner.services.KVV.types.Event; import de.sebse.fuplanner.services.NewKVV.types.Event;
import de.sebse.fuplanner.services.KVV.types.EventList; import de.sebse.fuplanner.services.NewKVV.types.EventList;
import de.sebse.fuplanner.services.KVV.types.GroupedEvents; import de.sebse.fuplanner.services.NewKVV.types.GroupedEvents;
import de.sebse.fuplanner.tools.Triplet;
import de.sebse.fuplanner.tools.UtilsDate; import de.sebse.fuplanner.tools.UtilsDate;
import de.sebse.fuplanner.tools.ui.CustomViewHolder;
import de.sebse.fuplanner.tools.ui.ItemViewHolder; import de.sebse.fuplanner.tools.ui.ItemViewHolder;
import de.sebse.fuplanner.tools.ui.ListViewHolder;
class ModDetailEventAdapterInner extends RecyclerView.Adapter<ItemViewHolder> { class ModDetailEventAdapterInner extends RecyclerView.Adapter<ItemViewHolder> {
private final ArrayList<Entry> mPositionalData; private final ArrayList<Entry> mPositionalData;

View File

@@ -8,14 +8,13 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import de.sebse.fuplanner.MainActivity;
import de.sebse.fuplanner.R; import de.sebse.fuplanner.R;
import de.sebse.fuplanner.services.KVV.KVV; import de.sebse.fuplanner.tools.MainActivityListener;
import de.sebse.fuplanner.services.KVV.types.Modules;
import de.sebse.fuplanner.tools.logging.Logger; import de.sebse.fuplanner.tools.logging.Logger;
/** /**
@@ -30,6 +29,7 @@ public class ModDetailEventFragment extends Fragment {
private final Logger log = new Logger(this); private final Logger log = new Logger(this);
private ModDetailEventAdapter adapter; private ModDetailEventAdapter adapter;
private SwipeRefreshLayout swipeLayout; private SwipeRefreshLayout swipeLayout;
@Nullable private MainActivityListener mListener;
public ModDetailEventFragment() { public ModDetailEventFragment() {
@@ -81,22 +81,31 @@ public class ModDetailEventFragment extends Fragment {
} }
private void refresh(boolean forceRefresh) { private void refresh(boolean forceRefresh) {
if (getActivity() != null) { if (mListener == null)
KVV kvv = ((MainActivity) getActivity()).getKVV(); return;
kvv.getModule(mItemPos, (Modules.Module module) -> { mListener.getNewKVV().modules().events().recv(mItemPos, success -> {
adapter.setModule(module); adapter.setModule(success);
kvv.getModuleEvents(module, success1 -> {
adapter.setModule();
swipeLayout.setRefreshing(false); swipeLayout.setRefreshing(false);
}, error -> { }, error -> {
swipeLayout.setRefreshing(false); swipeLayout.setRefreshing(false);
log.e(error); log.e(error);
}, forceRefresh); }, forceRefresh);
}, error -> {
swipeLayout.setRefreshing(false);
log.e(error);
}, forceRefresh);
}
} }
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof MainActivityListener) {
this.mListener = ((MainActivityListener) context);
} else
throw new RuntimeException(context.toString() + " must implement MainActivityListener");
}
@Override
public void onDetach() {
super.onDetach();
if (this.mListener != null) {
this.mListener = null;
}
}
} }

View File

@@ -10,7 +10,7 @@ import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.viewpager.widget.ViewPager; import androidx.viewpager.widget.ViewPager;
import de.sebse.fuplanner.R; import de.sebse.fuplanner.R;
import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.services.NewKVV.types.Modules;
import de.sebse.fuplanner.tools.MainActivityListener; import de.sebse.fuplanner.tools.MainActivityListener;
import de.sebse.fuplanner.tools.logging.Logger; import de.sebse.fuplanner.tools.logging.Logger;
@@ -72,7 +72,7 @@ public class ModDetailFragment extends Fragment implements ModDetailListener {
} }
if (mListener != null) { if (mListener != null) {
mListener.onTitleTextChange(R.string.courses); mListener.onTitleTextChange(R.string.courses);
mListener.getKVV().getModuleList(success -> { mListener.getNewKVV().modules().list().recv(success -> {
Modules.Module module = success.get(mItemPos); Modules.Module module = success.get(mItemPos);
if (mListener != null && module != null) if (mListener != null && module != null)
mListener.onTitleTextChange(module.title); mListener.onTitleTextChange(module.title);

View File

@@ -12,8 +12,8 @@ import java.util.ArrayList;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import de.sebse.fuplanner.R; import de.sebse.fuplanner.R;
import de.sebse.fuplanner.services.KVV.types.Gradebook; import de.sebse.fuplanner.services.NewKVV.types.Grade;
import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.services.NewKVV.types.Modules;
import de.sebse.fuplanner.tools.ui.StringViewHolder; import de.sebse.fuplanner.tools.ui.StringViewHolder;
class ModDetailGradebookAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { class ModDetailGradebookAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
@@ -62,7 +62,7 @@ class ModDetailGradebookAdapter extends RecyclerView.Adapter<RecyclerView.ViewHo
case TYPE_GRADE: case TYPE_GRADE:
view = LayoutInflater.from(parent.getContext()) view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_moddetails_gradebook, parent, false); .inflate(R.layout.list_moddetails_gradebook, parent, false);
return new GradebookViewHolder(view); return new GradeViewHolder(view);
default: default:
//noinspection ConstantConditions //noinspection ConstantConditions
return null; return null;
@@ -90,8 +90,8 @@ class ModDetailGradebookAdapter extends RecyclerView.Adapter<RecyclerView.ViewHo
break; break;
case TYPE_GRADE: case TYPE_GRADE:
int index = data.second / 1024; int index = data.second / 1024;
GradebookViewHolder i = (GradebookViewHolder) holder; GradeViewHolder i = (GradeViewHolder) holder;
Gradebook gradebook = mValue.gradebook.get(index); Grade gradebook = mValue.gradebook.get(index);
i.mTitle.setText(gradebook.getItemName()); i.mTitle.setText(gradebook.getItemName());
i.mGrade.setText(String.valueOf(gradebook.getPoints())); i.mGrade.setText(String.valueOf(gradebook.getPoints()));
@@ -119,12 +119,12 @@ class ModDetailGradebookAdapter extends RecyclerView.Adapter<RecyclerView.ViewHo
private class GradebookViewHolder extends RecyclerView.ViewHolder { private class GradeViewHolder extends RecyclerView.ViewHolder {
private final TextView mGrade; private final TextView mGrade;
private final TextView mGradeMax; private final TextView mGradeMax;
private final TextView mTitle; private final TextView mTitle;
GradebookViewHolder(View view) { GradeViewHolder(View view) {
super(view); super(view);
mTitle = view.findViewById(R.id.title); mTitle = view.findViewById(R.id.title);
mGrade = view.findViewById(R.id.grade); mGrade = view.findViewById(R.id.grade);

View File

@@ -8,14 +8,13 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import de.sebse.fuplanner.MainActivity;
import de.sebse.fuplanner.R; import de.sebse.fuplanner.R;
import de.sebse.fuplanner.services.KVV.KVV; import de.sebse.fuplanner.tools.MainActivityListener;
import de.sebse.fuplanner.services.KVV.types.Modules;
import de.sebse.fuplanner.tools.logging.Logger; import de.sebse.fuplanner.tools.logging.Logger;
/** /**
@@ -30,6 +29,7 @@ public class ModDetailGradebookFragment extends Fragment {
private final Logger log = new Logger(this); private final Logger log = new Logger(this);
private ModDetailGradebookAdapter adapter; private ModDetailGradebookAdapter adapter;
private SwipeRefreshLayout swipeLayout; private SwipeRefreshLayout swipeLayout;
@Nullable private MainActivityListener mListener;
public ModDetailGradebookFragment() { public ModDetailGradebookFragment() {
@@ -81,22 +81,31 @@ public class ModDetailGradebookFragment extends Fragment {
} }
private void refresh(boolean forceRefresh) { private void refresh(boolean forceRefresh) {
if (getActivity() != null) { if (mListener == null)
KVV kvv = ((MainActivity) getActivity()).getKVV(); return;
kvv.getModule(mItemPos, (Modules.Module module) -> { mListener.getNewKVV().modules().gradebook().recv(mItemPos, success -> {
adapter.setModule(module); adapter.setModule(success);
kvv.getModuleGradebook(module, success1 -> {
adapter.setModule();
swipeLayout.setRefreshing(false); swipeLayout.setRefreshing(false);
}, error -> { }, error -> {
swipeLayout.setRefreshing(false); swipeLayout.setRefreshing(false);
log.e(error); log.e(error);
}, forceRefresh); }, forceRefresh);
}, error -> {
swipeLayout.setRefreshing(false);
log.e(error);
}, forceRefresh);
}
} }
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof MainActivityListener) {
this.mListener = ((MainActivityListener) context);
} else
throw new RuntimeException(context.toString() + " must implement MainActivityListener");
}
@Override
public void onDetach() {
super.onDetach();
if (this.mListener != null) {
this.mListener = null;
}
}
} }

View File

@@ -13,10 +13,7 @@ import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import de.sebse.fuplanner.MainActivity;
import de.sebse.fuplanner.R; import de.sebse.fuplanner.R;
import de.sebse.fuplanner.services.KVV.KVV;
import de.sebse.fuplanner.services.KVV.types.Modules;
import de.sebse.fuplanner.tools.MainActivityListener; import de.sebse.fuplanner.tools.MainActivityListener;
import de.sebse.fuplanner.tools.logging.Logger; import de.sebse.fuplanner.tools.logging.Logger;

View File

@@ -3,8 +3,8 @@ package de.sebse.fuplanner.fragments.moddetails;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.services.NewKVV.types.Modules;
import de.sebse.fuplanner.services.KVV.types.Resource; import de.sebse.fuplanner.services.NewKVV.types.Resource;
import de.sebse.fuplanner.tools.ui.treeview.TreeNode; import de.sebse.fuplanner.tools.ui.treeview.TreeNode;
import de.sebse.fuplanner.tools.ui.treeview.TreeViewAdapter; import de.sebse.fuplanner.tools.ui.treeview.TreeViewAdapter;
import de.sebse.fuplanner.tools.ui.treeview.TreeViewBinder; import de.sebse.fuplanner.tools.ui.treeview.TreeViewBinder;

View File

@@ -11,16 +11,16 @@ import android.widget.ImageView;
import java.util.Arrays; import java.util.Arrays;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import de.sebse.fuplanner.MainActivity; import de.sebse.fuplanner.MainActivity;
import de.sebse.fuplanner.R; import de.sebse.fuplanner.R;
import de.sebse.fuplanner.services.KVV.Download; import de.sebse.fuplanner.services.NewKVV.Download;
import de.sebse.fuplanner.services.KVV.KVV; import de.sebse.fuplanner.services.NewKVV.types.Modules;
import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.services.NewKVV.types.Resource;
import de.sebse.fuplanner.services.KVV.types.Resource;
import de.sebse.fuplanner.tools.MainActivityListener; import de.sebse.fuplanner.tools.MainActivityListener;
import de.sebse.fuplanner.tools.logging.Logger; import de.sebse.fuplanner.tools.logging.Logger;
import de.sebse.fuplanner.tools.ui.treeview.DirectoryNodeBinder; import de.sebse.fuplanner.tools.ui.treeview.DirectoryNodeBinder;
@@ -40,8 +40,8 @@ public class ModDetailResourceFragment extends Fragment {
private final Logger log = new Logger(this); private final Logger log = new Logger(this);
private ModDetailResourceAdapter adapter; private ModDetailResourceAdapter adapter;
private SwipeRefreshLayout swipeLayout; private SwipeRefreshLayout swipeLayout;
private MainActivityListener context;
private Download download; private Download download;
@Nullable private MainActivityListener mListener;
public ModDetailResourceFragment() { public ModDetailResourceFragment() {
@@ -88,10 +88,8 @@ public class ModDetailResourceFragment extends Fragment {
if (!node.isLeaf()) { if (!node.isLeaf()) {
// Update and toggle the node. // Update and toggle the node.
onToggle(!node.isExpand(), holder); onToggle(!node.isExpand(), holder);
} else if(node.getContent() instanceof Resource.File) { // if leaf is file } else if (node.getContent() instanceof Resource.File && ModDetailResourceFragment.this.mListener != null) { // if leaf is file
KVV kvv = ModDetailResourceFragment.this.context.getKVV(); ModDetailResourceFragment.this.mListener.getNewKVV().modules().resources().recv(mItemPos, (Modules.Module module) -> {
kvv.getModule(mItemPos, (Modules.Module module) -> {
String folderName = "FU-"+module.title.replaceAll("[:*<>|/\"\\\\]", "-"); String folderName = "FU-"+module.title.replaceAll("[:*<>|/\"\\\\]", "-");
Resource.File file = (Resource.File) node.getContent(); Resource.File file = (Resource.File) node.getContent();
getDownload().openDownloadDialog(file, folderName); getDownload().openDownloadDialog(file, folderName);
@@ -120,14 +118,12 @@ public class ModDetailResourceFragment extends Fragment {
return view; return view;
} }
@Override @Override
public void onAttach(Context context) { public void onAttach(Context context) {
super.onAttach(context); super.onAttach(context);
if (context instanceof MainActivityListener) { if (context instanceof MainActivityListener) {
this.context = ((MainActivityListener) context); this.mListener = ((MainActivityListener) context);
this.context.addRequestPermissionsResultListener(getDownload().getRequestPermissionsResultListener(), "ModDetailResourceFragment"); this.mListener.addRequestPermissionsResultListener(getDownload().getRequestPermissionsResultListener(), "ModDetailResourceFragment");
} else } else
throw new RuntimeException(context.toString() + " must implement MainActivityListener"); throw new RuntimeException(context.toString() + " must implement MainActivityListener");
} }
@@ -135,26 +131,22 @@ public class ModDetailResourceFragment extends Fragment {
@Override @Override
public void onDetach() { public void onDetach() {
super.onDetach(); super.onDetach();
this.context.removeRequestPermissionsResultListener("ModDetailResourceFragment"); if (this.mListener != null) {
this.mListener.removeRequestPermissionsResultListener("ModDetailResourceFragment");
this.mListener = null;
}
} }
private void refresh(boolean forceRefresh) { private void refresh(boolean forceRefresh) {
if (getActivity() != null) { if (mListener == null)
KVV kvv = ((MainActivity) getActivity()).getKVV(); return;
kvv.getModule(mItemPos, (Modules.Module module) -> { mListener.getNewKVV().modules().assignments().recv(mItemPos, success -> {
adapter.setModule(module); adapter.setModule(success);
kvv.getModuleResources(module, success1 -> {
adapter.setModule();
swipeLayout.setRefreshing(false); swipeLayout.setRefreshing(false);
}, error -> { }, error -> {
swipeLayout.setRefreshing(false); swipeLayout.setRefreshing(false);
log.e(error); log.e(error);
}, forceRefresh); }, forceRefresh);
}, error -> {
swipeLayout.setRefreshing(false);
log.e(error);
}, forceRefresh);
}
} }
Download getDownload() { Download getDownload() {

View File

@@ -0,0 +1,265 @@
package de.sebse.fuplanner.services.NewKVV;
import android.Manifest;
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.net.Uri;
import android.os.Environment;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.core.content.FileProvider;
import de.sebse.fuplanner.MainActivity;
import de.sebse.fuplanner.R;
import de.sebse.fuplanner.services.NewKVV.KVV;
import de.sebse.fuplanner.services.NewKVV.types.Resource;
import de.sebse.fuplanner.tools.Regex;
import de.sebse.fuplanner.tools.RequestPermissionsResultListener;
import de.sebse.fuplanner.tools.UtilsDate;
import de.sebse.fuplanner.tools.logging.Logger;
import static androidx.core.content.ContextCompat.checkSelfPermission;
public class Download {
private final ContextInterface contextInterface;
private final ActivityInterface activityInterface;
private RequestedDownload requestedDownload;
private Logger log = new Logger(this);
public Download(ContextInterface contextInterface, ActivityInterface activityInterface) {
this.contextInterface = contextInterface;
this.activityInterface = activityInterface;
}
public void openDownloadDialog(String title, String url, String folderName) {
openDownloadDialog(new Resource.File("", title, 0, url, true, "", ""), folderName);
}
public void openDownloadDialog(Resource.File file, String folderName) {
Context context = contextInterface.get();
if (context == null)
return;
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context);
File f = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOWNLOADS)+"/"+folderName+"/"+file.getTitle());
Resources resources = context.getResources();
String message = "";
if (file.getAuthor() != null && !file.getAuthor().isEmpty())
message += resources.getString(R.string.creator_name, file.getAuthor());
if (file.getModifiedDate() != 0) {
if (!message.isEmpty())
message += "\n";
message += resources.getString(R.string.last_modified_on, UtilsDate.getModifiedDateTime(context, file.getModifiedDate()));
}
alertDialogBuilder
.setTitle(file.getTitle())
.setMessage(message)
.setCancelable(true)
.setNeutralButton(R.string.close, (dialog, id) -> dialog.cancel());
// if already downloaded, show open button
if (f.exists()) {
alertDialogBuilder
.setPositiveButton(R.string.download_again, (dialog, id) -> download(file, folderName, true))
.setNegativeButton(R.string.openFile, (dialog, id) -> download(file, folderName, false));
} else {
alertDialogBuilder
.setPositiveButton(R.string.download, (dialog, id) -> download(file, folderName, true));
}
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
}
private void download(Resource.File file, String folderName, boolean downloadNew){
MainActivity activity = activityInterface.get();
if (activity == null) {
showDownloadError();
return;
}
if (checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
// Access granted
downloadOrOpen(file, folderName, downloadNew);
} else {
this.requestedDownload = new RequestedDownload(file, folderName, downloadNew);
ActivityCompat.requestPermissions(activity,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
1);
}
}
private void downloadOrOpen(Resource.File file, String folderName, boolean downloadNew) {
if (!isExternalStorageWritable()) {
return;
}
MainActivity activity = activityInterface.get();
if (activity == null) {
showDownloadError();
return;
}
activity.getNewKVV().modules().resources().file(file.getTitle(), file.getUrl(), folderName, success -> {
Context context = contextInterface.get();
if (success.equals("")) {
showDownloadError();
} else {
if (Regex.has("^http", success)){
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(success));
context.startActivity(intent);
}
else {
fileOpen(new File(success));
}
}
}, log::e, downloadNew);
}
private void showDownloadError() {
Context context = contextInterface.get();
if (context == null)
return;
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context);
alertDialogBuilder
.setTitle(R.string.ErrorFileDownload)
.setMessage(
R.string.ErrorFileDownloadText
)
.setCancelable(true)
.setNeutralButton(R.string.close, (dialog, id) -> dialog.cancel());
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
}
public RequestPermissionsResultListener getRequestPermissionsResultListener() {
return (requestCode, permissions, grantResults) -> {
if (requestedDownload == null) {
log.d("No request");
return;
}
if (activityInterface.get() == null) {
showDownloadError();
return;
}
ArrayList<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);
}
}

View File

@@ -35,9 +35,6 @@ public class KVVLogin extends HTTPService {
if (mLoginPending) { if (mLoginPending) {
errorCallback.onError(new NetworkError(100160, -1, "Login already pending!")); errorCallback.onError(new NetworkError(100160, -1, "Login already pending!"));
} }
if (mToken != null) {
errorCallback.onError(new NetworkError(100161, -1, "Already logged in!"));
}
mLoginPending = true; mLoginPending = true;
doLogin(username, password, token -> { doLogin(username, password, token -> {
testLoginToken(token, token2 -> { testLoginToken(token, token2 -> {

View File

@@ -12,7 +12,7 @@ public class KVVModules {
private final KVVLogin mLogin; private final KVVLogin mLogin;
private final Context context; private final Context context;
public KVVModules(KVVLogin login, Context context) { KVVModules(KVVLogin login, Context context) {
this.mLogin = login; this.mLogin = login;
this.context = context; this.context = context;
} }
@@ -20,7 +20,7 @@ public class KVVModules {
@NotNull @NotNull
public KVVModulesDetails details() { public KVVModulesDetails details() {
return (KVVModulesDetails) addAndGet("details", () -> { return (KVVModulesDetails) addAndGet("details", () -> {
ModulesPart[] parts = {announcements(), assignments()}; ModulesPart[] parts = {announcements(), assignments(), events(), gradebook(), resources()};
return new KVVModulesDetails(mLogin, list(), context, parts); return new KVVModulesDetails(mLogin, list(), context, parts);
}); });
} }
@@ -35,6 +35,21 @@ public class KVVModules {
return (KVVModulesAssignments) addAndGet("assignments", () -> new KVVModulesAssignments(mLogin, list(), context)); return (KVVModulesAssignments) addAndGet("assignments", () -> new KVVModulesAssignments(mLogin, list(), context));
} }
@NotNull
public KVVModulesEvents events() {
return (KVVModulesEvents) addAndGet("events", () -> new KVVModulesEvents(mLogin, list(), context));
}
@NotNull
public KVVModulesGradebook gradebook() {
return (KVVModulesGradebook) addAndGet("gradebook", () -> new KVVModulesGradebook(mLogin, list(), context));
}
@NotNull
public KVVModulesResources resources() {
return (KVVModulesResources) addAndGet("resources", () -> new KVVModulesResources(mLogin, list(), context));
}
@NotNull @NotNull
public KVVModulesList list() { public KVVModulesList list() {
if (mList == null) { if (mList == null) {

View File

@@ -75,6 +75,7 @@ public class KVVModulesAnnouncements extends ModulesPart<ArrayList<Announcement>
announcements.add(new Announcement(id, title, text, createdBy, createdOn, urls)); announcements.add(new Announcement(id, title, text, createdBy, createdOn, urls));
} catch (JSONException e) { } catch (JSONException e) {
log.e(new NetworkError(101205, 403, "Cannot parse announcements!")); log.e(new NetworkError(101205, 403, "Cannot parse announcements!"));
log.e("ID:", i, "JSON:", sites);
e.printStackTrace(); e.printStackTrace();
return; return;
} }

View File

@@ -75,6 +75,7 @@ public class KVVModulesAssignments extends ModulesPart<AssignmentList> {
} catch (JSONException e) { } catch (JSONException e) {
log.e(new NetworkError(101305, 403, "Cannot parse assignments!")); log.e(new NetworkError(101305, 403, "Cannot parse assignments!"));
e.printStackTrace(); e.printStackTrace();
log.e("ID:", i, "JSON:", sites);
return; return;
} }
} }
@@ -84,6 +85,6 @@ public class KVVModulesAssignments extends ModulesPart<AssignmentList> {
mLogin.testLoginToken(token -> callback.onResponse(assignments), errorCallback); mLogin.testLoginToken(token -> callback.onResponse(assignments), errorCallback);
else else
callback.onResponse(assignments); callback.onResponse(assignments);
}, error -> errorCallback.onError(new NetworkError(101303, error.networkResponse.statusCode, "Cannot get announcements!"))); }, error -> errorCallback.onError(new NetworkError(101303, error.networkResponse.statusCode, "Cannot get assignments!")));
} }
} }

View File

@@ -0,0 +1,83 @@
package de.sebse.fuplanner.services.NewKVV;
import android.content.Context;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import de.sebse.fuplanner.services.NewKVV.types.Event;
import de.sebse.fuplanner.services.NewKVV.types.EventList;
import de.sebse.fuplanner.services.NewKVV.types.Modules;
import de.sebse.fuplanner.tools.network.NetworkCallback;
import de.sebse.fuplanner.tools.network.NetworkError;
import de.sebse.fuplanner.tools.network.NetworkErrorCallback;
public class KVVModulesEvents extends ModulesPart<EventList> {
KVVModulesEvents(KVVLogin login, KVVModulesList list, Context context) {
super(login, list, context);
}
@Override
protected EventList getPart(Modules.Module module) {
return module.events;
}
@Override
protected boolean setPart(Modules.Module module, EventList part) {
boolean changed = module.events == null || module.events.hashCode() != part.hashCode();
module.events = part;
return changed;
}
@Override
protected void upgrade(final String ID, final NetworkCallback<EventList> callback, final NetworkErrorCallback errorCallback) {
if (!mLogin.isInOnlineMode() || mLogin.getLoginToken() == null) {
errorCallback.onError(new NetworkError(101404, 500, "Currently running in offline mode!"));
return;
}
get(String.format("https://kvv.imp.fu-berlin.de/direct/calendar/site/%s.json?detailed=true", ID), mLogin.getLoginToken().getCookies(), response -> {
String body = response.getParsed();
if (body == null) {
errorCallback.onError(new NetworkError(101401, 403, "No events retrieved!"));
return;
}
EventList events = new EventList();
JSONArray sites;
try {
JSONObject json = new JSONObject(body);
sites = json.getJSONArray("calendar_collection");
} catch (JSONException e) {
e.printStackTrace();
errorCallback.onError(new NetworkError(101402, 403, "Cannot parse events!"));
return;
}
for (int i = 0; i < sites.length(); i++) {
try {
JSONObject site = sites.getJSONObject(i);
String id = site.getString("eventId");
String type = site.getString("type");
String title = site.getString("title");
String siteId = site.getString("siteId");
long duration = site.getLong("duration");
long firstTime = site.getJSONObject("firstTime").getLong("time");
String location = site.getString("location");
events.add(new Event(id, type, title, duration, firstTime, siteId, location));
} catch (JSONException e) {
log.e(new NetworkError(101405, 403, "Cannot parse events!"));
e.printStackTrace();
log.e("ID:", i, "JSON:", sites);
return;
}
}
// Empty events *may be* because token is invalid -> check
if (events.size() == 0)
mLogin.testLoginToken(token -> callback.onResponse(events), errorCallback);
else
callback.onResponse(events);
}, error -> errorCallback.onError(new NetworkError(101403, error.networkResponse.statusCode, "Cannot get events!")));
}
}

View File

@@ -0,0 +1,76 @@
package de.sebse.fuplanner.services.NewKVV;
import android.content.Context;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import de.sebse.fuplanner.services.NewKVV.types.Grade;
import de.sebse.fuplanner.services.NewKVV.types.Modules;
import de.sebse.fuplanner.tools.network.NetworkCallback;
import de.sebse.fuplanner.tools.network.NetworkError;
import de.sebse.fuplanner.tools.network.NetworkErrorCallback;
public class KVVModulesGradebook extends ModulesPart<ArrayList<Grade>> {
KVVModulesGradebook(KVVLogin login, KVVModulesList list, Context context) {
super(login, list, context);
}
@Override
protected ArrayList<Grade> getPart(Modules.Module module) {
return module.gradebook;
}
@Override
protected boolean setPart(Modules.Module module, ArrayList<Grade> part) {
boolean changed = module.gradebook == null || module.gradebook.hashCode() != part.hashCode();
module.gradebook = part;
return changed;
}
@Override
protected void upgrade(final String ID, final NetworkCallback<ArrayList<Grade>> callback, final NetworkErrorCallback errorCallback) {
if (!mLogin.isInOnlineMode() || mLogin.getLoginToken() == null) {
errorCallback.onError(new NetworkError(101504, 500, "Currently running in offline mode!"));
return;
}
super.get(String.format("https://kvv.imp.fu-berlin.de/direct/gradebook/site/%s.json", ID), mLogin.getLoginToken().getCookies(), response -> {
String body = response.getParsed();
if (body == null) {
errorCallback.onError(new NetworkError(101501, 403, "No gradebook retrieved!"));
return;
}
ArrayList<Grade> gradebook = new ArrayList<>();
JSONArray sites;
try {
JSONObject json = new JSONObject(body);
sites = json.getJSONArray("assignments");
} catch (JSONException e) {
e.printStackTrace();
errorCallback.onError(new NetworkError(101502, 403, "Cannot parse gradebook!"));
return;
}
for (int i = 0; i < sites.length(); i++) {
try {
JSONObject site = sites.getJSONObject(i);
double grade = site.optDouble("grade", 0);
String itemName = site.optString("itemName", null);
double maxPoints = site.optDouble("points", -1);
gradebook.add(0, new Grade(itemName, grade, maxPoints));
} catch (JSONException e) {
log.e(new NetworkError(101505, 403, "Cannot parse gradebook!"));
log.e("ID:", i, "JSON:", sites);
e.printStackTrace();
return;
}
}
callback.onResponse(gradebook);
}, error -> errorCallback.onError(new NetworkError(101503, error.networkResponse.statusCode, "Cannot get gradebook!")));
}
}

View File

@@ -179,9 +179,11 @@ public class KVVModulesList extends HTTPService {
modules.addModule(semester, lvNumbers, title, lecturers, type, description, id); modules.addModule(semester, lvNumbers, title, lecturers, type, description, id);
} catch (JSONException e) { } catch (JSONException e) {
log.e(new NetworkError(101103, 403, "Cannot parse module list!")); log.e(new NetworkError(101103, 403, "Cannot parse module list!"));
log.e("ID:", i, "JSON:", sites);
e.printStackTrace(); e.printStackTrace();
} catch (NoSuchFieldException e) { } catch (NoSuchFieldException e) {
log.e(new NetworkError(101106, 403, "Cannot parse module list!")); log.e(new NetworkError(101106, 403, "Cannot parse module list!"));
log.e("ID:", i, "JSON:", sites);
e.printStackTrace(); e.printStackTrace();
} }
} }

View File

@@ -0,0 +1,220 @@
package de.sebse.fuplanner.services.NewKVV;
import android.content.Context;
import android.os.Environment;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import de.sebse.fuplanner.services.NewKVV.types.Modules;
import de.sebse.fuplanner.services.NewKVV.types.Resource;
import de.sebse.fuplanner.tools.Regex;
import de.sebse.fuplanner.tools.network.NetworkCallback;
import de.sebse.fuplanner.tools.network.NetworkError;
import de.sebse.fuplanner.tools.network.NetworkErrorCallback;
public class KVVModulesResources extends ModulesPart<ArrayList<Resource>> {
KVVModulesResources(KVVLogin login, KVVModulesList list, Context context) {
super(login, list, context);
}
@Override
protected ArrayList<Resource> getPart(Modules.Module module) {
return module.resources;
}
@Override
protected boolean setPart(Modules.Module module, ArrayList<Resource> part) {
boolean changed = module.assignments == null || module.assignments.hashCode() != part.hashCode();
module.resources = part;
return changed;
}
@Override
protected void upgrade(final String ID, final NetworkCallback<ArrayList<Resource>> callback, final NetworkErrorCallback errorCallback) {
if (!mLogin.isInOnlineMode() || mLogin.getLoginToken() == null) {
errorCallback.onError(new NetworkError(101604, 500, "Currently running in offline mode!"));
return;
}
get(String.format("https://kvv.imp.fu-berlin.de/direct/content/site/%s.json", ID), mLogin.getLoginToken().getCookies(), response -> {
String body = response.getParsed();
if (body == null) {
errorCallback.onError(new NetworkError(101601, 403, "No resources retrieved!"));
return;
}
ArrayList<Resource> resources = new ArrayList<>();
JSONArray sites;
try {
JSONObject json = new JSONObject(body);
sites = json.getJSONArray("content_collection");
} catch (JSONException e) {
e.printStackTrace();
errorCallback.onError(new NetworkError(101602, 403, "Cannot parse resources!"));
return;
}
for (int i = 0; i < sites.length(); i++) {
try {
JSONObject site = sites.getJSONObject(i);
String author = site.getString("author");
String title = site.getString("title");
long modifiedDate = site.getLong("modifiedDate");
String url = site.getString("url");
boolean visible = site.getBoolean("visible");
String type = site.getString("type");
String container = site.getString("container");
if (type.equals("collection")){
resources.add(new Resource.Folder(author, title, modifiedDate, url, visible, container));
}
else {
resources.add(new Resource.File(author, title, modifiedDate, url, visible, container, type));
}
} catch (JSONException e) {
log.e(new NetworkError(101605, 403, "Cannot parse resources!"));
e.printStackTrace();
log.e("ID:", i, "JSON:", sites);
return;
}
}
ArrayList<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 assignments *may be* because token is invalid -> check
if (root.size() == 0)
mLogin.testLoginToken(token -> callback.onResponse(root), errorCallback);
else
callback.onResponse(root);
}, error -> errorCallback.onError(new NetworkError(101603, error.networkResponse.statusCode, "Cannot get resources!")));
}
public void file(final String filename, final String url, final String modulename, final NetworkCallback<String> callback, final NetworkErrorCallback errorCallback, boolean forceRefresh) {
file(filename, url, modulename, callback, errorCallback, forceRefresh, RETRY_COUNT);
}
public void file(final String filename, final String url, final String modulename, final NetworkCallback<String> callback, final NetworkErrorCallback errorCallback, boolean forceRefresh, int retries) {
if (isExternalStorageReadable()){
File f = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOWNLOADS)+"/"+modulename+"/"+filename);
// check if file already downloaded -> do not download again
if (f.exists() && !forceRefresh) {
callback.onResponse(f.getPath());
return;
}
}
fileUpgrade(filename, url , modulename, callback, error -> {
if (retries >= 0 && (error.getHttpStatus() == 401 || error.getHttpStatus() == 403)) {
mLogin.refreshLogin(success -> {
file(filename, url, modulename, callback, errorCallback, forceRefresh, retries-1);
}, errorCallback);
return;
}
errorCallback.onError(error);
});
}
private void fileUpgrade(String filename, String url, String modulename, final NetworkCallback<String> callback, final NetworkErrorCallback errorCallback) {
if (!mLogin.isInOnlineMode() || mLogin.getLoginToken() == null) {
errorCallback.onError(new NetworkError(101604, 500, "Currently running in offline mode!"));
return;
}
get(url, mLogin.getLoginToken().getCookies(), response -> {
if (Regex.has("\\.[Uu][Rr][Ll]$", url)){
// Return redirected URL
String path = response.getHeaders().get("Location");
if (path == null){
path = "";
}
callback.onResponse(path);
} else if (response.getBytes() == null) {
errorCallback.onError(new NetworkError(101705, 403, "Cannot get file!"));
} else if (isExternalStorageWritable()) {
String path = saveFileInDownloads(filename, response.getBytes(), modulename);
callback.onResponse(path);
} else {
errorCallback.onError(new NetworkError(101704, 403, "External storage not writable!"));
}
}, error -> errorCallback.onError(new NetworkError(101702, error.networkResponse.statusCode, "Cannot get file!")));
}
/* Checks if external storage is available for read and write */
private boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
log.w("File system: Writing not possible!");
return false;
}
/* Checks if external storage is available to at least read */
private boolean isExternalStorageReadable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state) ||
Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
return true;
}
log.w("File system: Reading not possible!");
return false;
}
private String saveFileInDownloads(String filename, byte[] data, String moduleName) {
// Saves file in folder: DOWNLOADS/moduleName
File folder = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOWNLOADS), moduleName);
if (!folder.mkdir()) {
log.w( "Directory not created");
}
String path = "";
try {
// TODO check if enough storage space is available
FileOutputStream out = new FileOutputStream(folder.getPath()+"/"+filename);
out.write(data);
out.close();
path = folder.getPath()+"/"+filename;
} catch (Exception e) {
log.w("File not saved!");
e.printStackTrace();
}
return path;
}
}

View File

@@ -23,7 +23,11 @@ public abstract class Part<T> extends HTTPService {
} }
public void recv(final String moduleID, final NetworkCallback<T> callback, final NetworkErrorCallback errorCallback, final boolean forceRefresh) { public void recv(final String moduleID, final NetworkCallback<T> callback, final NetworkErrorCallback errorCallback, final boolean forceRefresh) {
mList.find(moduleID, success -> recv(success, callback, errorCallback, forceRefresh, RETRY_COUNT), errorCallback); mList.find(moduleID, success -> recv(success, callback, errorCallback, forceRefresh), errorCallback);
}
public void recv(final Modules.Module module, final NetworkCallback<T> callback, final NetworkErrorCallback errorCallback, final boolean forceRefresh) {
recv(module, callback, errorCallback, forceRefresh, RETRY_COUNT);
} }
abstract protected void recv(final Modules.Module module, final NetworkCallback<T> callback, final NetworkErrorCallback errorCallback, final boolean forceRefresh, final int retries); abstract protected void recv(final Modules.Module module, final NetworkCallback<T> callback, final NetworkErrorCallback errorCallback, final boolean forceRefresh, final int retries);

View File

@@ -1,13 +1,15 @@
package de.sebse.fuplanner.services.NewKVV.types; package de.sebse.fuplanner.services.NewKVV.types;
import com.google.android.gms.common.internal.Objects;
import java.io.Serializable; import java.io.Serializable;
public class Gradebook implements Serializable { public class Grade implements Serializable {
private final String itemName; private final String itemName;
private final double grade; private final double grade;
private final double maxPoints; private final double maxPoints;
public Gradebook(String itemName, double points, double maxPoints) { public Grade(String itemName, double points, double maxPoints) {
this.itemName = itemName; this.itemName = itemName;
this.grade = points; this.grade = points;
this.maxPoints = maxPoints; this.maxPoints = maxPoints;
@@ -31,4 +33,9 @@ public class Gradebook implements Serializable {
"\nPoints: "+ getPoints()+ "\nPoints: "+ getPoints()+
"\nMax points: "+getMaxPoints(); "\nMax points: "+getMaxPoints();
} }
@Override
public int hashCode() {
return Objects.hashCode(getItemName(), getPoints(), getMaxPoints());
}
} }

View File

@@ -116,14 +116,14 @@ public class Modules implements Iterable<Modules.Module>, Serializable {
@Nullable public ArrayList<Announcement> announcements; @Nullable public ArrayList<Announcement> announcements;
@Nullable public AssignmentList assignments; @Nullable public AssignmentList assignments;
@Nullable public EventList events; @Nullable public EventList events;
@Nullable public ArrayList<Gradebook> gradebook; @Nullable public ArrayList<Grade> gradebook;
@Nullable public ArrayList<Resource> resources; @Nullable public ArrayList<Resource> resources;
public float getGradebookPercent(){ public float getGradebookPercent(){
float maxPoint = 0; float maxPoint = 0;
float userPoint = 0; float userPoint = 0;
if (gradebook != null) { if (gradebook != null) {
for (Gradebook g : gradebook){ for (Grade g : gradebook){
maxPoint += g.getMaxPoints(); maxPoint += g.getMaxPoints();
userPoint += g.getPoints(); userPoint += g.getPoints();
} }

View File

@@ -5,7 +5,7 @@ import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import de.sebse.fuplanner.R; import de.sebse.fuplanner.R;
import de.sebse.fuplanner.services.KVV.types.Resource; import de.sebse.fuplanner.services.NewKVV.types.Resource;
/** /**
* Created by tlh on 2016/10/1 :) * Created by tlh on 2016/10/1 :)

View File

@@ -4,7 +4,7 @@ import android.view.View;
import android.widget.TextView; import android.widget.TextView;
import de.sebse.fuplanner.R; import de.sebse.fuplanner.R;
import de.sebse.fuplanner.services.KVV.types.Resource; import de.sebse.fuplanner.services.NewKVV.types.Resource;
/** /**
* Created by tlh on 2016/10/1 :) * Created by tlh on 2016/10/1 :)