Blackboard Resources (no links)
This commit is contained in:
@@ -24,6 +24,7 @@ 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;
|
||||||
|
import de.sebse.fuplanner.tools.ui.treeview.DocumentNodeBinder;
|
||||||
import de.sebse.fuplanner.tools.ui.treeview.FileNodeBinder;
|
import de.sebse.fuplanner.tools.ui.treeview.FileNodeBinder;
|
||||||
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;
|
||||||
@@ -81,7 +82,7 @@ public class ModDetailResourceFragment extends Fragment {
|
|||||||
RecyclerView recyclerView = view.findViewById(R.id.list);
|
RecyclerView recyclerView = view.findViewById(R.id.list);
|
||||||
recyclerView.setLayoutManager(new LinearLayoutManager(context));
|
recyclerView.setLayoutManager(new LinearLayoutManager(context));
|
||||||
|
|
||||||
adapter = new ModDetailResourceAdapter(Arrays.asList(new FileNodeBinder(), new DirectoryNodeBinder()));
|
adapter = new ModDetailResourceAdapter(Arrays.asList(new FileNodeBinder(), new DirectoryNodeBinder(), new DocumentNodeBinder()));
|
||||||
adapter.setOnTreeNodeListener(new TreeViewAdapter.OnTreeNodeListener() {
|
adapter.setOnTreeNodeListener(new TreeViewAdapter.OnTreeNodeListener() {
|
||||||
@Override
|
@Override
|
||||||
public boolean onClick(TreeNode node, RecyclerView.ViewHolder holder) {
|
public boolean onClick(TreeNode node, RecyclerView.ViewHolder holder) {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import java.io.UnsupportedEncodingException;
|
|||||||
import java.net.URLDecoder;
|
import java.net.URLDecoder;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
|
||||||
import de.sebse.fuplanner.services.kvv.types.Modules;
|
import de.sebse.fuplanner.services.kvv.types.Modules;
|
||||||
import de.sebse.fuplanner.services.kvv.types.Resource;
|
import de.sebse.fuplanner.services.kvv.types.Resource;
|
||||||
@@ -126,9 +127,82 @@ public class ModulesResources extends PartModules<ArrayList<Resource>> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void upgradeBB(String ID, NetworkCallback<ArrayList<Resource>> callback, NetworkErrorCallback errorCallback) {
|
protected void upgradeBB(String ID, NetworkCallback<ArrayList<Resource>> callback, NetworkErrorCallback errorCallback) {
|
||||||
callback.onResponse(new ArrayList<>());
|
if (!mLogin.isInOnlineMode() || mLogin.getLoginTokenBB() == null || !mLogin.getLoginTokenBB().isAvailable()) {
|
||||||
|
errorCallback.onError(new NetworkError(101614, 500, "Currently running in offline mode!"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
getRescourceFolder(String.format("https://lms.fu-berlin.de/learn/api/public/v1/courses/%s/contents/", ID), ID, false, callback, errorCallback);
|
||||||
|
//callback.onResponse(new ArrayList<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void getRescourceFolder(String url, String ID, boolean subRequest, NetworkCallback<ArrayList<Resource>> callback, NetworkErrorCallback errorCallback) {
|
||||||
|
if (mLogin.getLoginTokenBB() == null) {
|
||||||
|
errorCallback.onError(new NetworkError(101610, 500, "Cannot get resources!"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
get(url, mLogin.getLoginTokenBB().getCookies(), response -> {
|
||||||
|
String body = response.getParsed();
|
||||||
|
if (body == null) {
|
||||||
|
errorCallback.onError(new NetworkError(101611, 403, "No resources retrieved!"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ArrayList<Resource> resources = new ArrayList<>();
|
||||||
|
JSONArray sites;
|
||||||
|
try {
|
||||||
|
JSONObject json = new JSONObject(body);
|
||||||
|
sites = json.getJSONArray("results");
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
errorCallback.onError(new NetworkError(101612, 400, "Cannot parse resources!"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int[] latch = {sites.length()};
|
||||||
|
for (int i = 0; i < sites.length(); i++) {
|
||||||
|
try {
|
||||||
|
JSONObject resource = sites.getJSONObject(i);
|
||||||
|
String resid = resource.getString("id");
|
||||||
|
String title = resource.getString("title");
|
||||||
|
String created = resource.getString("created");
|
||||||
|
String content = resource.getJSONObject("contentHandler").getString("id");
|
||||||
|
long createdDate = UtilsDate.stringToMillis(created, "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
|
||||||
|
if (content.equals("resource/x-bb-folder")) {
|
||||||
|
Resource.Folder folder = new Resource.Folder("", title, createdDate, "", true, "");
|
||||||
|
resources.add(folder);
|
||||||
|
getRescourceFolder(String.format("https://lms.fu-berlin.de/learn/api/public/v1/courses/%s/contents/%s/children", ID, resid), ID, true, response1 -> {
|
||||||
|
for (Resource resource1 : response1) {
|
||||||
|
folder.add(resource1);
|
||||||
|
}
|
||||||
|
if (--latch[0] == 0) callback.onResponse(resources);
|
||||||
|
}, errorCallback);
|
||||||
|
} else {
|
||||||
|
String bodyText = resource.optString("body", "");
|
||||||
|
bodyText = String.valueOf(PartModules.fromHtml(bodyText));
|
||||||
|
resources.add(new Resource.Document("", title, createdDate, true, "", bodyText));
|
||||||
|
if (--latch[0] == 0) callback.onResponse(resources);
|
||||||
|
}
|
||||||
|
} catch (JSONException e) {
|
||||||
|
log.e(new NetworkError(101615, 400, "Cannot parse resources!"));
|
||||||
|
e.printStackTrace();
|
||||||
|
log.e("ID:", i, "JSON:", sites);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, error -> {
|
||||||
|
if (!subRequest || error.networkResponse.statusCode != 403) {
|
||||||
|
errorCallback.onError(new NetworkError(101613, error.networkResponse.statusCode, "Cannot get resources!"));
|
||||||
|
} else {
|
||||||
|
callback.onResponse(new ArrayList<>());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -62,6 +62,61 @@ public abstract class Resource implements Serializable {
|
|||||||
return Objects.hashCode(getAuthor(), getContainer(), getModifiedDate(), getTitle(), getUrl());
|
return Objects.hashCode(getAuthor(), getContainer(), getModifiedDate(), getTitle(), getUrl());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class Document extends Resource implements LayoutItemType {
|
||||||
|
private final ArrayList<String> urls;
|
||||||
|
private final String body;
|
||||||
|
|
||||||
|
public Document(String author, String title, long modifiedDate, boolean visible, String container, String body) {
|
||||||
|
super(author, title, modifiedDate, "", visible, container);
|
||||||
|
this.body = body;
|
||||||
|
this.urls = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Resource{" +
|
||||||
|
"author='" + author + '\'' +
|
||||||
|
", modifiedDate=" + modifiedDate +
|
||||||
|
", title='" + title + '\'' +
|
||||||
|
", urls='" + urls.size() + '\'' +
|
||||||
|
", body='" + body + '\'' +
|
||||||
|
", urls='" + body + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBody() {
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addUrl(String res){
|
||||||
|
urls.add(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUrl(int id){
|
||||||
|
return urls.get(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size(){
|
||||||
|
return urls.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TreeNode getTreeNode() {
|
||||||
|
return new TreeNode<>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @LayoutRes int getLayoutId() {
|
||||||
|
return R.layout.list_announcement_items;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hashCode(super.hashCode(), this.getClass().getSimpleName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class File extends Resource implements LayoutItemType {
|
public static class File extends Resource implements LayoutItemType {
|
||||||
private final String type;
|
private final String type;
|
||||||
|
|
||||||
@@ -91,6 +146,11 @@ public abstract class Resource implements Serializable {
|
|||||||
public @LayoutRes int getLayoutId() {
|
public @LayoutRes int getLayoutId() {
|
||||||
return R.layout.item_file;
|
return R.layout.item_file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hashCode(super.hashCode(), this.getClass().getSimpleName());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Folder extends Resource implements LayoutItemType {
|
public static class Folder extends Resource implements LayoutItemType {
|
||||||
@@ -138,6 +198,11 @@ public abstract class Resource implements Serializable {
|
|||||||
public @LayoutRes int getLayoutId() {
|
public @LayoutRes int getLayoutId() {
|
||||||
return R.layout.item_dir;
|
return R.layout.item_dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hashCode(super.hashCode(), this.getClass().getSimpleName());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,12 +64,12 @@ public class ExpandableCardView extends CardView {
|
|||||||
private int expandedHeight = 0;
|
private int expandedHeight = 0;
|
||||||
|
|
||||||
private OnExpandedListener listener;
|
private OnExpandedListener listener;
|
||||||
|
private final Logger log = new Logger(this);
|
||||||
|
|
||||||
private final OnClickListener defaultClickListener = v -> {
|
private final OnClickListener defaultClickListener = v -> {
|
||||||
if(isExpanded()) collapse();
|
if(isExpanded()) collapse();
|
||||||
else expand();
|
else expand();
|
||||||
};
|
};
|
||||||
private final Logger log = new Logger(this);
|
|
||||||
|
|
||||||
public ExpandableCardView(Context context) {
|
public ExpandableCardView(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
package de.sebse.fuplanner.tools.ui.treeview;
|
||||||
|
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.cunoraz.tagview.Tag;
|
||||||
|
import com.cunoraz.tagview.TagView;
|
||||||
|
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
import de.sebse.fuplanner.R;
|
||||||
|
import de.sebse.fuplanner.services.kvv.types.Resource;
|
||||||
|
import de.sebse.fuplanner.tools.logging.Logger;
|
||||||
|
import de.sebse.fuplanner.tools.ui.cardview.ExpandableCardView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by tlh on 2016/10/1 :)
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class DocumentNodeBinder extends TreeViewBinder<DocumentNodeBinder.ViewHolder> {
|
||||||
|
@Override
|
||||||
|
public ViewHolder provideViewHolder(View itemView) {
|
||||||
|
return new ViewHolder(itemView);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void bindView(ViewHolder holder, int position, TreeNode node) {
|
||||||
|
Resource.Document fileNode = (Resource.Document) node.getContent();
|
||||||
|
holder.title.setText(fileNode.getTitle());
|
||||||
|
holder.notes.setText(fileNode.getBody());
|
||||||
|
|
||||||
|
/*for (int i = 0, notesSize = fileNode.size(); i < notesSize; i++) {
|
||||||
|
String name = urlToName(fileNode.getUrl(i), i, holder.itemView.getResources());
|
||||||
|
Tag tag = new Tag(name);
|
||||||
|
tag.id = i;
|
||||||
|
tag.layoutColor = ContextCompat.getColor(holder.itemView.getContext(), R.color.colorFUBlue);
|
||||||
|
holder.mTagGroup.addTag(tag);
|
||||||
|
}
|
||||||
|
holder.mTagGroup.setOnTagClickListener((tag, i) -> {
|
||||||
|
String s = fileNode.getUrl(i);
|
||||||
|
if (s != null) {
|
||||||
|
String name = urlToName(s, i, holder.itemView.getResources());
|
||||||
|
requestInterface.request(name, s);
|
||||||
|
}
|
||||||
|
});*/
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getLayoutId() {
|
||||||
|
return R.layout.list_announcement_items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ViewHolder extends TreeViewBinder.ViewHolder {
|
||||||
|
final TextView title;
|
||||||
|
final TextView notes;
|
||||||
|
final ExpandableCardView card_view;
|
||||||
|
final TagView mTagGroup;
|
||||||
|
|
||||||
|
ViewHolder(View rootView) {
|
||||||
|
super(rootView);
|
||||||
|
this.card_view = rootView.findViewById(R.id.card_view);
|
||||||
|
this.title = this.card_view.getOuterView().findViewById(R.id.title);
|
||||||
|
this.notes = this.card_view.getInnerView().findViewById(R.id.notes);
|
||||||
|
this.mTagGroup = this.card_view.getInnerView().findViewById(R.id.tag_group);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,6 +13,7 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.recyclerview.widget.DiffUtil;
|
import androidx.recyclerview.widget.DiffUtil;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
import de.sebse.fuplanner.tools.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by tlh on 2016/10/1 :)
|
* Created by tlh on 2016/10/1 :)
|
||||||
@@ -88,32 +89,34 @@ public class TreeViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde
|
|||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, int position) {
|
public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, int position) {
|
||||||
holder.itemView.setPadding(displayNodes.get(position).getHeight() * padding, 3, 3, 3);
|
holder.itemView.setPadding(displayNodes.get(position).getHeight() * padding, 3, 3, 3);
|
||||||
holder.itemView.setOnClickListener(v -> {
|
if (!holder.itemView.hasOnClickListeners()) {
|
||||||
TreeNode selectedNode = displayNodes.get(holder.getLayoutPosition());
|
holder.itemView.setOnClickListener(v -> {
|
||||||
// Prevent multi-click during the short interval.
|
TreeNode selectedNode = displayNodes.get(holder.getLayoutPosition());
|
||||||
try {
|
// Prevent multi-click during the short interval.
|
||||||
long lastClickTime = (long) holder.itemView.getTag();
|
try {
|
||||||
if (System.currentTimeMillis() - lastClickTime < 500)
|
long lastClickTime = (long) holder.itemView.getTag();
|
||||||
return;
|
if (System.currentTimeMillis() - lastClickTime < 500)
|
||||||
} catch (Exception e) {
|
return;
|
||||||
|
} catch (Exception e) {
|
||||||
|
holder.itemView.setTag(System.currentTimeMillis());
|
||||||
|
}
|
||||||
holder.itemView.setTag(System.currentTimeMillis());
|
holder.itemView.setTag(System.currentTimeMillis());
|
||||||
}
|
|
||||||
holder.itemView.setTag(System.currentTimeMillis());
|
|
||||||
|
|
||||||
if (onTreeNodeListener != null && onTreeNodeListener.onClick(selectedNode, holder))
|
if (onTreeNodeListener != null && onTreeNodeListener.onClick(selectedNode, holder))
|
||||||
return;
|
return;
|
||||||
if (selectedNode.isLeaf())
|
if (selectedNode.isLeaf())
|
||||||
return;
|
return;
|
||||||
// This TreeNode was locked to click.
|
// This TreeNode was locked to click.
|
||||||
if (selectedNode.isLocked()) return;
|
if (selectedNode.isLocked()) return;
|
||||||
boolean isExpand = selectedNode.isExpand();
|
boolean isExpand = selectedNode.isExpand();
|
||||||
int positionStart = displayNodes.indexOf(selectedNode) + 1;
|
int positionStart = displayNodes.indexOf(selectedNode) + 1;
|
||||||
if (!isExpand) {
|
if (!isExpand) {
|
||||||
notifyItemRangeInserted(positionStart, addChildNodes(selectedNode, positionStart));
|
notifyItemRangeInserted(positionStart, addChildNodes(selectedNode, positionStart));
|
||||||
} else {
|
} else {
|
||||||
notifyItemRangeRemoved(positionStart, removeChildNodes(selectedNode, true));
|
notifyItemRangeRemoved(positionStart, removeChildNodes(selectedNode, true));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
for (TreeViewBinder viewBinder : viewBinders) {
|
for (TreeViewBinder viewBinder : viewBinders) {
|
||||||
if (viewBinder.getLayoutId() == displayNodes.get(position).getContent().getLayoutId())
|
if (viewBinder.getLayoutId() == displayNodes.get(position).getContent().getLayoutId())
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
<de.sebse.fuplanner.tools.ui.cardview.ExpandableCardView xmlns:android="http://schemas.android.com/apk/res/android"
|
<de.sebse.fuplanner.tools.ui.cardview.ExpandableCardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:card_view="http://schemas.android.com/tools"
|
xmlns:card_view="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/card_view"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_margin="@dimen/cardview_margin"
|
android:layout_margin="@dimen/cardview_margin"
|
||||||
|
|||||||
Reference in New Issue
Block a user