Bug fixing, Implemented Rescource, Event and Gradebook
This commit is contained in:
@@ -16,9 +16,9 @@ import java.util.List;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import de.sebse.fuplanner.R;
|
||||
import de.sebse.fuplanner.services.KVV.KVV;
|
||||
import de.sebse.fuplanner.services.KVV.types.Event;
|
||||
import de.sebse.fuplanner.services.KVV.types.Modules;
|
||||
import de.sebse.fuplanner.services.NewKVV.KVV;
|
||||
import de.sebse.fuplanner.services.NewKVV.types.Event;
|
||||
import de.sebse.fuplanner.services.NewKVV.types.Modules;
|
||||
import de.sebse.fuplanner.tools.UtilsDate;
|
||||
import de.sebse.fuplanner.tools.MainActivityListener;
|
||||
import de.sebse.fuplanner.tools.logging.Logger;
|
||||
@@ -59,24 +59,22 @@ public class ScheduleFragment extends Fragment implements MonthLoader.MonthChang
|
||||
}
|
||||
|
||||
public void invalidate(boolean forceRefresh) {
|
||||
if (mListener != null) {
|
||||
KVV kvv = mListener.getKVV();
|
||||
kvv.getModuleList((Modules success) -> {
|
||||
mModules = success;
|
||||
final int[] i = {0};
|
||||
for (Modules.Module module: mModules) {
|
||||
kvv.getModuleEvents(module, success1 -> {
|
||||
i[0]++;
|
||||
if (i[0] >= mModules.size()) {
|
||||
if (mWeekView != null) {
|
||||
mWeekView.invalidate();
|
||||
mWeekView.notifyDatasetChanged();
|
||||
}
|
||||
if (mListener == null) return;
|
||||
mListener.getNewKVV().modules().list().recv(modules -> {
|
||||
mModules = modules;
|
||||
final int[] i = {0};
|
||||
for (Modules.Module module: mModules) {
|
||||
mListener.getNewKVV().modules().events().recv(module, success1 -> {
|
||||
i[0]++;
|
||||
if (i[0] >= mModules.size()) {
|
||||
if (mWeekView != null) {
|
||||
mWeekView.invalidate();
|
||||
mWeekView.notifyDatasetChanged();
|
||||
}
|
||||
}, log::e, forceRefresh);
|
||||
}
|
||||
}, log::e, forceRefresh);
|
||||
}
|
||||
}
|
||||
}, log::e, forceRefresh);
|
||||
}
|
||||
}, log::e, forceRefresh);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -183,24 +181,21 @@ public class ScheduleFragment extends Fragment implements MonthLoader.MonthChang
|
||||
String moduleId = idParts[0];
|
||||
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getContext());
|
||||
|
||||
if (mListener != null) {
|
||||
KVV kvv = mListener.getKVV();
|
||||
kvv.getModuleList((Modules success) -> {
|
||||
Modules.Module module = success.get(moduleId);
|
||||
String moduleName = module.title;
|
||||
alertDialogBuilder
|
||||
.setTitle(event.getName())
|
||||
.setMessage(
|
||||
getResources().getString(R.string.module_name, moduleName) + "\n" +
|
||||
getResources().getString(R.string.location_name, event.getLocation()) + "\n" +
|
||||
getResources().getString(R.string.date_scale, UtilsDate.getModifiedTime(getContext(), event.getStartTime().getTimeInMillis()), UtilsDate.getModifiedTime(getContext(), event.getEndTime().getTimeInMillis()+1))
|
||||
)
|
||||
.setCancelable(true)
|
||||
.setNeutralButton(R.string.close, (dialog, id) -> dialog.cancel());
|
||||
if (mListener == null) return;
|
||||
mListener.getNewKVV().modules().list().find(moduleId, module -> {
|
||||
String moduleName = module.title;
|
||||
alertDialogBuilder
|
||||
.setTitle(event.getName())
|
||||
.setMessage(
|
||||
getResources().getString(R.string.module_name, moduleName) + "\n" +
|
||||
getResources().getString(R.string.location_name, event.getLocation()) + "\n" +
|
||||
getResources().getString(R.string.date_scale, UtilsDate.getModifiedTime(getContext(), event.getStartTime().getTimeInMillis()), UtilsDate.getModifiedTime(getContext(), event.getEndTime().getTimeInMillis()+1))
|
||||
)
|
||||
.setCancelable(true)
|
||||
.setNeutralButton(R.string.close, (dialog, id) -> dialog.cancel());
|
||||
|
||||
AlertDialog alertDialog = alertDialogBuilder.create();
|
||||
alertDialog.show();
|
||||
}, log::e);
|
||||
}
|
||||
AlertDialog alertDialog = alertDialogBuilder.create();
|
||||
alertDialog.show();
|
||||
}, log::e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import de.sebse.fuplanner.R;
|
||||
import de.sebse.fuplanner.services.KVV.Download;
|
||||
import de.sebse.fuplanner.services.NewKVV.Download;
|
||||
import de.sebse.fuplanner.services.NewKVV.types.Announcement;
|
||||
import de.sebse.fuplanner.services.NewKVV.types.Modules;
|
||||
import de.sebse.fuplanner.tools.Regex;
|
||||
|
||||
@@ -14,7 +14,7 @@ import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
import de.sebse.fuplanner.MainActivity;
|
||||
import de.sebse.fuplanner.R;
|
||||
import de.sebse.fuplanner.services.KVV.Download;
|
||||
import de.sebse.fuplanner.services.NewKVV.Download;
|
||||
import de.sebse.fuplanner.services.NewKVV.types.Modules;
|
||||
import de.sebse.fuplanner.tools.MainActivityListener;
|
||||
import de.sebse.fuplanner.tools.logging.Logger;
|
||||
|
||||
@@ -16,7 +16,7 @@ import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import de.sebse.fuplanner.R;
|
||||
import de.sebse.fuplanner.services.KVV.Download;
|
||||
import de.sebse.fuplanner.services.NewKVV.Download;
|
||||
import de.sebse.fuplanner.services.NewKVV.types.Assignment;
|
||||
import de.sebse.fuplanner.services.NewKVV.types.Modules;
|
||||
import de.sebse.fuplanner.tools.Regex;
|
||||
|
||||
@@ -14,7 +14,7 @@ import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
import de.sebse.fuplanner.MainActivity;
|
||||
import de.sebse.fuplanner.R;
|
||||
import de.sebse.fuplanner.services.KVV.Download;
|
||||
import de.sebse.fuplanner.services.NewKVV.Download;
|
||||
import de.sebse.fuplanner.services.NewKVV.types.Modules;
|
||||
import de.sebse.fuplanner.tools.MainActivityListener;
|
||||
import de.sebse.fuplanner.tools.logging.Logger;
|
||||
@@ -95,6 +95,7 @@ public class ModDetailAssignmentFragment extends Fragment implements Download.On
|
||||
|
||||
@Override
|
||||
public void request(String title, String url) {
|
||||
log.d(title, url, mListener);
|
||||
if (mListener == null)
|
||||
return;
|
||||
mListener.getNewKVV().modules().list().find(mItemPos, (Modules.Module module) -> {
|
||||
|
||||
@@ -14,10 +14,10 @@ import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import de.sebse.fuplanner.R;
|
||||
import de.sebse.fuplanner.services.KVV.types.Event;
|
||||
import de.sebse.fuplanner.services.KVV.types.EventList;
|
||||
import de.sebse.fuplanner.services.KVV.types.GroupedEvents;
|
||||
import de.sebse.fuplanner.services.KVV.types.Modules;
|
||||
import de.sebse.fuplanner.services.NewKVV.types.Event;
|
||||
import de.sebse.fuplanner.services.NewKVV.types.EventList;
|
||||
import de.sebse.fuplanner.services.NewKVV.types.GroupedEvents;
|
||||
import de.sebse.fuplanner.services.NewKVV.types.Modules;
|
||||
import de.sebse.fuplanner.tools.Triplet;
|
||||
import de.sebse.fuplanner.tools.UtilsDate;
|
||||
import de.sebse.fuplanner.tools.logging.Logger;
|
||||
|
||||
@@ -10,14 +10,11 @@ import java.util.ArrayList;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import de.sebse.fuplanner.R;
|
||||
import de.sebse.fuplanner.services.KVV.types.Event;
|
||||
import de.sebse.fuplanner.services.KVV.types.EventList;
|
||||
import de.sebse.fuplanner.services.KVV.types.GroupedEvents;
|
||||
import de.sebse.fuplanner.tools.Triplet;
|
||||
import de.sebse.fuplanner.services.NewKVV.types.Event;
|
||||
import de.sebse.fuplanner.services.NewKVV.types.EventList;
|
||||
import de.sebse.fuplanner.services.NewKVV.types.GroupedEvents;
|
||||
import de.sebse.fuplanner.tools.UtilsDate;
|
||||
import de.sebse.fuplanner.tools.ui.CustomViewHolder;
|
||||
import de.sebse.fuplanner.tools.ui.ItemViewHolder;
|
||||
import de.sebse.fuplanner.tools.ui.ListViewHolder;
|
||||
|
||||
class ModDetailEventAdapterInner extends RecyclerView.Adapter<ItemViewHolder> {
|
||||
private final ArrayList<Entry> mPositionalData;
|
||||
|
||||
@@ -8,14 +8,13 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
import de.sebse.fuplanner.MainActivity;
|
||||
import de.sebse.fuplanner.R;
|
||||
import de.sebse.fuplanner.services.KVV.KVV;
|
||||
import de.sebse.fuplanner.services.KVV.types.Modules;
|
||||
import de.sebse.fuplanner.tools.MainActivityListener;
|
||||
import de.sebse.fuplanner.tools.logging.Logger;
|
||||
|
||||
/**
|
||||
@@ -30,6 +29,7 @@ public class ModDetailEventFragment extends Fragment {
|
||||
private final Logger log = new Logger(this);
|
||||
private ModDetailEventAdapter adapter;
|
||||
private SwipeRefreshLayout swipeLayout;
|
||||
@Nullable private MainActivityListener mListener;
|
||||
|
||||
|
||||
public ModDetailEventFragment() {
|
||||
@@ -81,22 +81,31 @@ public class ModDetailEventFragment extends Fragment {
|
||||
}
|
||||
|
||||
private void refresh(boolean forceRefresh) {
|
||||
if (getActivity() != null) {
|
||||
KVV kvv = ((MainActivity) getActivity()).getKVV();
|
||||
kvv.getModule(mItemPos, (Modules.Module module) -> {
|
||||
adapter.setModule(module);
|
||||
kvv.getModuleEvents(module, success1 -> {
|
||||
adapter.setModule();
|
||||
swipeLayout.setRefreshing(false);
|
||||
}, error -> {
|
||||
swipeLayout.setRefreshing(false);
|
||||
log.e(error);
|
||||
}, forceRefresh);
|
||||
}, error -> {
|
||||
swipeLayout.setRefreshing(false);
|
||||
log.e(error);
|
||||
}, forceRefresh);
|
||||
}
|
||||
if (mListener == null)
|
||||
return;
|
||||
mListener.getNewKVV().modules().events().recv(mItemPos, success -> {
|
||||
adapter.setModule(success);
|
||||
swipeLayout.setRefreshing(false);
|
||||
}, error -> {
|
||||
swipeLayout.setRefreshing(false);
|
||||
log.e(error);
|
||||
}, forceRefresh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
if (context instanceof MainActivityListener) {
|
||||
this.mListener = ((MainActivityListener) context);
|
||||
} else
|
||||
throw new RuntimeException(context.toString() + " must implement MainActivityListener");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetach() {
|
||||
super.onDetach();
|
||||
if (this.mListener != null) {
|
||||
this.mListener = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
import de.sebse.fuplanner.R;
|
||||
import de.sebse.fuplanner.services.KVV.types.Modules;
|
||||
import de.sebse.fuplanner.services.NewKVV.types.Modules;
|
||||
import de.sebse.fuplanner.tools.MainActivityListener;
|
||||
import de.sebse.fuplanner.tools.logging.Logger;
|
||||
|
||||
@@ -72,7 +72,7 @@ public class ModDetailFragment extends Fragment implements ModDetailListener {
|
||||
}
|
||||
if (mListener != null) {
|
||||
mListener.onTitleTextChange(R.string.courses);
|
||||
mListener.getKVV().getModuleList(success -> {
|
||||
mListener.getNewKVV().modules().list().recv(success -> {
|
||||
Modules.Module module = success.get(mItemPos);
|
||||
if (mListener != null && module != null)
|
||||
mListener.onTitleTextChange(module.title);
|
||||
|
||||
@@ -12,8 +12,8 @@ import java.util.ArrayList;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import de.sebse.fuplanner.R;
|
||||
import de.sebse.fuplanner.services.KVV.types.Gradebook;
|
||||
import de.sebse.fuplanner.services.KVV.types.Modules;
|
||||
import de.sebse.fuplanner.services.NewKVV.types.Grade;
|
||||
import de.sebse.fuplanner.services.NewKVV.types.Modules;
|
||||
import de.sebse.fuplanner.tools.ui.StringViewHolder;
|
||||
|
||||
class ModDetailGradebookAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
||||
@@ -62,7 +62,7 @@ class ModDetailGradebookAdapter extends RecyclerView.Adapter<RecyclerView.ViewHo
|
||||
case TYPE_GRADE:
|
||||
view = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.list_moddetails_gradebook, parent, false);
|
||||
return new GradebookViewHolder(view);
|
||||
return new GradeViewHolder(view);
|
||||
default:
|
||||
//noinspection ConstantConditions
|
||||
return null;
|
||||
@@ -90,8 +90,8 @@ class ModDetailGradebookAdapter extends RecyclerView.Adapter<RecyclerView.ViewHo
|
||||
break;
|
||||
case TYPE_GRADE:
|
||||
int index = data.second / 1024;
|
||||
GradebookViewHolder i = (GradebookViewHolder) holder;
|
||||
Gradebook gradebook = mValue.gradebook.get(index);
|
||||
GradeViewHolder i = (GradeViewHolder) holder;
|
||||
Grade gradebook = mValue.gradebook.get(index);
|
||||
|
||||
i.mTitle.setText(gradebook.getItemName());
|
||||
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 mGradeMax;
|
||||
private final TextView mTitle;
|
||||
|
||||
GradebookViewHolder(View view) {
|
||||
GradeViewHolder(View view) {
|
||||
super(view);
|
||||
mTitle = view.findViewById(R.id.title);
|
||||
mGrade = view.findViewById(R.id.grade);
|
||||
|
||||
@@ -8,14 +8,13 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
import de.sebse.fuplanner.MainActivity;
|
||||
import de.sebse.fuplanner.R;
|
||||
import de.sebse.fuplanner.services.KVV.KVV;
|
||||
import de.sebse.fuplanner.services.KVV.types.Modules;
|
||||
import de.sebse.fuplanner.tools.MainActivityListener;
|
||||
import de.sebse.fuplanner.tools.logging.Logger;
|
||||
|
||||
/**
|
||||
@@ -30,6 +29,7 @@ public class ModDetailGradebookFragment extends Fragment {
|
||||
private final Logger log = new Logger(this);
|
||||
private ModDetailGradebookAdapter adapter;
|
||||
private SwipeRefreshLayout swipeLayout;
|
||||
@Nullable private MainActivityListener mListener;
|
||||
|
||||
|
||||
public ModDetailGradebookFragment() {
|
||||
@@ -81,22 +81,31 @@ public class ModDetailGradebookFragment extends Fragment {
|
||||
}
|
||||
|
||||
private void refresh(boolean forceRefresh) {
|
||||
if (getActivity() != null) {
|
||||
KVV kvv = ((MainActivity) getActivity()).getKVV();
|
||||
kvv.getModule(mItemPos, (Modules.Module module) -> {
|
||||
adapter.setModule(module);
|
||||
kvv.getModuleGradebook(module, success1 -> {
|
||||
adapter.setModule();
|
||||
swipeLayout.setRefreshing(false);
|
||||
}, error -> {
|
||||
swipeLayout.setRefreshing(false);
|
||||
log.e(error);
|
||||
}, forceRefresh);
|
||||
}, error -> {
|
||||
swipeLayout.setRefreshing(false);
|
||||
log.e(error);
|
||||
}, forceRefresh);
|
||||
}
|
||||
if (mListener == null)
|
||||
return;
|
||||
mListener.getNewKVV().modules().gradebook().recv(mItemPos, success -> {
|
||||
adapter.setModule(success);
|
||||
swipeLayout.setRefreshing(false);
|
||||
}, error -> {
|
||||
swipeLayout.setRefreshing(false);
|
||||
log.e(error);
|
||||
}, forceRefresh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
if (context instanceof MainActivityListener) {
|
||||
this.mListener = ((MainActivityListener) context);
|
||||
} else
|
||||
throw new RuntimeException(context.toString() + " must implement MainActivityListener");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetach() {
|
||||
super.onDetach();
|
||||
if (this.mListener != null) {
|
||||
this.mListener = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,10 +13,7 @@ import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
import de.sebse.fuplanner.MainActivity;
|
||||
import de.sebse.fuplanner.R;
|
||||
import de.sebse.fuplanner.services.KVV.KVV;
|
||||
import de.sebse.fuplanner.services.KVV.types.Modules;
|
||||
import de.sebse.fuplanner.tools.MainActivityListener;
|
||||
import de.sebse.fuplanner.tools.logging.Logger;
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@ package de.sebse.fuplanner.fragments.moddetails;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import de.sebse.fuplanner.services.KVV.types.Modules;
|
||||
import de.sebse.fuplanner.services.KVV.types.Resource;
|
||||
import de.sebse.fuplanner.services.NewKVV.types.Modules;
|
||||
import de.sebse.fuplanner.services.NewKVV.types.Resource;
|
||||
import de.sebse.fuplanner.tools.ui.treeview.TreeNode;
|
||||
import de.sebse.fuplanner.tools.ui.treeview.TreeViewAdapter;
|
||||
import de.sebse.fuplanner.tools.ui.treeview.TreeViewBinder;
|
||||
|
||||
@@ -11,16 +11,16 @@ import android.widget.ImageView;
|
||||
import java.util.Arrays;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
import de.sebse.fuplanner.MainActivity;
|
||||
import de.sebse.fuplanner.R;
|
||||
import de.sebse.fuplanner.services.KVV.Download;
|
||||
import de.sebse.fuplanner.services.KVV.KVV;
|
||||
import de.sebse.fuplanner.services.KVV.types.Modules;
|
||||
import de.sebse.fuplanner.services.KVV.types.Resource;
|
||||
import de.sebse.fuplanner.services.NewKVV.Download;
|
||||
import de.sebse.fuplanner.services.NewKVV.types.Modules;
|
||||
import de.sebse.fuplanner.services.NewKVV.types.Resource;
|
||||
import de.sebse.fuplanner.tools.MainActivityListener;
|
||||
import de.sebse.fuplanner.tools.logging.Logger;
|
||||
import de.sebse.fuplanner.tools.ui.treeview.DirectoryNodeBinder;
|
||||
@@ -40,8 +40,8 @@ public class ModDetailResourceFragment extends Fragment {
|
||||
private final Logger log = new Logger(this);
|
||||
private ModDetailResourceAdapter adapter;
|
||||
private SwipeRefreshLayout swipeLayout;
|
||||
private MainActivityListener context;
|
||||
private Download download;
|
||||
@Nullable private MainActivityListener mListener;
|
||||
|
||||
|
||||
public ModDetailResourceFragment() {
|
||||
@@ -88,10 +88,8 @@ public class ModDetailResourceFragment extends Fragment {
|
||||
if (!node.isLeaf()) {
|
||||
// Update and toggle the node.
|
||||
onToggle(!node.isExpand(), holder);
|
||||
} else if(node.getContent() instanceof Resource.File) { // if leaf is file
|
||||
KVV kvv = ModDetailResourceFragment.this.context.getKVV();
|
||||
kvv.getModule(mItemPos, (Modules.Module module) -> {
|
||||
|
||||
} else if (node.getContent() instanceof Resource.File && ModDetailResourceFragment.this.mListener != null) { // if leaf is file
|
||||
ModDetailResourceFragment.this.mListener.getNewKVV().modules().resources().recv(mItemPos, (Modules.Module module) -> {
|
||||
String folderName = "FU-"+module.title.replaceAll("[:*<>|/\"\\\\]", "-");
|
||||
Resource.File file = (Resource.File) node.getContent();
|
||||
getDownload().openDownloadDialog(file, folderName);
|
||||
@@ -120,14 +118,12 @@ public class ModDetailResourceFragment extends Fragment {
|
||||
return view;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
if (context instanceof MainActivityListener) {
|
||||
this.context = ((MainActivityListener) context);
|
||||
this.context.addRequestPermissionsResultListener(getDownload().getRequestPermissionsResultListener(), "ModDetailResourceFragment");
|
||||
this.mListener = ((MainActivityListener) context);
|
||||
this.mListener.addRequestPermissionsResultListener(getDownload().getRequestPermissionsResultListener(), "ModDetailResourceFragment");
|
||||
} else
|
||||
throw new RuntimeException(context.toString() + " must implement MainActivityListener");
|
||||
}
|
||||
@@ -135,26 +131,22 @@ public class ModDetailResourceFragment extends Fragment {
|
||||
@Override
|
||||
public void onDetach() {
|
||||
super.onDetach();
|
||||
this.context.removeRequestPermissionsResultListener("ModDetailResourceFragment");
|
||||
if (this.mListener != null) {
|
||||
this.mListener.removeRequestPermissionsResultListener("ModDetailResourceFragment");
|
||||
this.mListener = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void refresh(boolean forceRefresh) {
|
||||
if (getActivity() != null) {
|
||||
KVV kvv = ((MainActivity) getActivity()).getKVV();
|
||||
kvv.getModule(mItemPos, (Modules.Module module) -> {
|
||||
adapter.setModule(module);
|
||||
kvv.getModuleResources(module, success1 -> {
|
||||
adapter.setModule();
|
||||
swipeLayout.setRefreshing(false);
|
||||
}, error -> {
|
||||
swipeLayout.setRefreshing(false);
|
||||
log.e(error);
|
||||
}, forceRefresh);
|
||||
}, error -> {
|
||||
swipeLayout.setRefreshing(false);
|
||||
log.e(error);
|
||||
}, forceRefresh);
|
||||
}
|
||||
if (mListener == null)
|
||||
return;
|
||||
mListener.getNewKVV().modules().assignments().recv(mItemPos, success -> {
|
||||
adapter.setModule(success);
|
||||
swipeLayout.setRefreshing(false);
|
||||
}, error -> {
|
||||
swipeLayout.setRefreshing(false);
|
||||
log.e(error);
|
||||
}, forceRefresh);
|
||||
}
|
||||
|
||||
Download getDownload() {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -35,9 +35,6 @@ public class KVVLogin extends HTTPService {
|
||||
if (mLoginPending) {
|
||||
errorCallback.onError(new NetworkError(100160, -1, "Login already pending!"));
|
||||
}
|
||||
if (mToken != null) {
|
||||
errorCallback.onError(new NetworkError(100161, -1, "Already logged in!"));
|
||||
}
|
||||
mLoginPending = true;
|
||||
doLogin(username, password, token -> {
|
||||
testLoginToken(token, token2 -> {
|
||||
|
||||
@@ -12,7 +12,7 @@ public class KVVModules {
|
||||
private final KVVLogin mLogin;
|
||||
private final Context context;
|
||||
|
||||
public KVVModules(KVVLogin login, Context context) {
|
||||
KVVModules(KVVLogin login, Context context) {
|
||||
this.mLogin = login;
|
||||
this.context = context;
|
||||
}
|
||||
@@ -20,7 +20,7 @@ public class KVVModules {
|
||||
@NotNull
|
||||
public KVVModulesDetails details() {
|
||||
return (KVVModulesDetails) addAndGet("details", () -> {
|
||||
ModulesPart[] parts = {announcements(), assignments()};
|
||||
ModulesPart[] parts = {announcements(), assignments(), events(), gradebook(), resources()};
|
||||
return new KVVModulesDetails(mLogin, list(), context, parts);
|
||||
});
|
||||
}
|
||||
@@ -35,6 +35,21 @@ public class KVVModules {
|
||||
return (KVVModulesAssignments) addAndGet("assignments", () -> new KVVModulesAssignments(mLogin, list(), context));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public KVVModulesEvents events() {
|
||||
return (KVVModulesEvents) addAndGet("events", () -> new KVVModulesEvents(mLogin, list(), context));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public KVVModulesGradebook gradebook() {
|
||||
return (KVVModulesGradebook) addAndGet("gradebook", () -> new KVVModulesGradebook(mLogin, list(), context));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public KVVModulesResources resources() {
|
||||
return (KVVModulesResources) addAndGet("resources", () -> new KVVModulesResources(mLogin, list(), context));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public KVVModulesList list() {
|
||||
if (mList == null) {
|
||||
|
||||
@@ -75,6 +75,7 @@ public class KVVModulesAnnouncements extends ModulesPart<ArrayList<Announcement>
|
||||
announcements.add(new Announcement(id, title, text, createdBy, createdOn, urls));
|
||||
} catch (JSONException e) {
|
||||
log.e(new NetworkError(101205, 403, "Cannot parse announcements!"));
|
||||
log.e("ID:", i, "JSON:", sites);
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -75,6 +75,7 @@ public class KVVModulesAssignments extends ModulesPart<AssignmentList> {
|
||||
} catch (JSONException e) {
|
||||
log.e(new NetworkError(101305, 403, "Cannot parse assignments!"));
|
||||
e.printStackTrace();
|
||||
log.e("ID:", i, "JSON:", sites);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -84,6 +85,6 @@ public class KVVModulesAssignments extends ModulesPart<AssignmentList> {
|
||||
mLogin.testLoginToken(token -> callback.onResponse(assignments), errorCallback);
|
||||
else
|
||||
callback.onResponse(assignments);
|
||||
}, error -> errorCallback.onError(new NetworkError(101303, error.networkResponse.statusCode, "Cannot get announcements!")));
|
||||
}, error -> errorCallback.onError(new NetworkError(101303, error.networkResponse.statusCode, "Cannot get assignments!")));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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!")));
|
||||
}
|
||||
}
|
||||
@@ -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!")));
|
||||
}
|
||||
}
|
||||
@@ -179,9 +179,11 @@ public class KVVModulesList extends HTTPService {
|
||||
modules.addModule(semester, lvNumbers, title, lecturers, type, description, id);
|
||||
} catch (JSONException e) {
|
||||
log.e(new NetworkError(101103, 403, "Cannot parse module list!"));
|
||||
log.e("ID:", i, "JSON:", sites);
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchFieldException e) {
|
||||
log.e(new NetworkError(101106, 403, "Cannot parse module list!"));
|
||||
log.e("ID:", i, "JSON:", sites);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
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);
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
package de.sebse.fuplanner.services.NewKVV.types;
|
||||
|
||||
import com.google.android.gms.common.internal.Objects;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class Gradebook implements Serializable {
|
||||
public class Grade implements Serializable {
|
||||
private final String itemName;
|
||||
private final double grade;
|
||||
private final double maxPoints;
|
||||
|
||||
public Gradebook(String itemName, double points, double maxPoints) {
|
||||
public Grade(String itemName, double points, double maxPoints) {
|
||||
this.itemName = itemName;
|
||||
this.grade = points;
|
||||
this.maxPoints = maxPoints;
|
||||
@@ -31,4 +33,9 @@ public class Gradebook implements Serializable {
|
||||
"\nPoints: "+ getPoints()+
|
||||
"\nMax points: "+getMaxPoints();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(getItemName(), getPoints(), getMaxPoints());
|
||||
}
|
||||
}
|
||||
@@ -116,14 +116,14 @@ public class Modules implements Iterable<Modules.Module>, Serializable {
|
||||
@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;
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import de.sebse.fuplanner.R;
|
||||
import de.sebse.fuplanner.services.KVV.types.Resource;
|
||||
import de.sebse.fuplanner.services.NewKVV.types.Resource;
|
||||
|
||||
/**
|
||||
* Created by tlh on 2016/10/1 :)
|
||||
|
||||
@@ -4,7 +4,7 @@ import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import de.sebse.fuplanner.R;
|
||||
import de.sebse.fuplanner.services.KVV.types.Resource;
|
||||
import de.sebse.fuplanner.services.NewKVV.types.Resource;
|
||||
|
||||
/**
|
||||
* Created by tlh on 2016/10/1 :)
|
||||
|
||||
Reference in New Issue
Block a user