|
@@ -1,36 +1,39 @@
|
|
-/**
|
|
|
|
|
|
+/*
|
|
* ownCloud Android client application
|
|
* ownCloud Android client application
|
|
*
|
|
*
|
|
* @author Andy Scherzinger
|
|
* @author Andy Scherzinger
|
|
* Copyright (C) 2016 ownCloud Inc.
|
|
* Copyright (C) 2016 ownCloud Inc.
|
|
- * <p/>
|
|
|
|
|
|
+ *
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2,
|
|
* it under the terms of the GNU General Public License version 2,
|
|
* as published by the Free Software Foundation.
|
|
* as published by the Free Software Foundation.
|
|
- * <p/>
|
|
|
|
|
|
+ *
|
|
* This program is distributed in the hope that it will be useful,
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
* GNU General Public License for more details.
|
|
- * <p/>
|
|
|
|
|
|
+ *
|
|
* You should have received a copy of the GNU General Public License
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
*/
|
|
|
|
|
|
package com.owncloud.android.ui.adapter;
|
|
package com.owncloud.android.ui.adapter;
|
|
|
|
|
|
-import android.content.Context;
|
|
|
|
import android.content.Intent;
|
|
import android.content.Intent;
|
|
|
|
+import android.graphics.PorterDuff;
|
|
import android.graphics.Typeface;
|
|
import android.graphics.Typeface;
|
|
import android.graphics.drawable.PictureDrawable;
|
|
import android.graphics.drawable.PictureDrawable;
|
|
import android.net.Uri;
|
|
import android.net.Uri;
|
|
|
|
+import android.os.AsyncTask;
|
|
import android.support.annotation.NonNull;
|
|
import android.support.annotation.NonNull;
|
|
import android.support.v7.widget.RecyclerView;
|
|
import android.support.v7.widget.RecyclerView;
|
|
import android.text.TextUtils;
|
|
import android.text.TextUtils;
|
|
import android.view.LayoutInflater;
|
|
import android.view.LayoutInflater;
|
|
import android.view.View;
|
|
import android.view.View;
|
|
import android.view.ViewGroup;
|
|
import android.view.ViewGroup;
|
|
|
|
+import android.widget.Button;
|
|
import android.widget.ImageView;
|
|
import android.widget.ImageView;
|
|
|
|
+import android.widget.LinearLayout;
|
|
import android.widget.TextView;
|
|
import android.widget.TextView;
|
|
|
|
|
|
import com.bumptech.glide.GenericRequestBuilder;
|
|
import com.bumptech.glide.GenericRequestBuilder;
|
|
@@ -40,12 +43,25 @@ import com.bumptech.glide.load.model.StreamEncoder;
|
|
import com.bumptech.glide.load.resource.file.FileToStreamDecoder;
|
|
import com.bumptech.glide.load.resource.file.FileToStreamDecoder;
|
|
import com.caverock.androidsvg.SVG;
|
|
import com.caverock.androidsvg.SVG;
|
|
import com.owncloud.android.R;
|
|
import com.owncloud.android.R;
|
|
|
|
+import com.owncloud.android.lib.common.OwnCloudClient;
|
|
|
|
+import com.owncloud.android.lib.common.operations.RemoteOperation;
|
|
|
|
+import com.owncloud.android.lib.common.utils.Log_OC;
|
|
|
|
+import com.owncloud.android.lib.resources.notifications.models.Action;
|
|
import com.owncloud.android.lib.resources.notifications.models.Notification;
|
|
import com.owncloud.android.lib.resources.notifications.models.Notification;
|
|
|
|
+import com.owncloud.android.ui.activity.NotificationsActivity;
|
|
import com.owncloud.android.utils.DisplayUtils;
|
|
import com.owncloud.android.utils.DisplayUtils;
|
|
|
|
+import com.owncloud.android.utils.ThemeUtils;
|
|
import com.owncloud.android.utils.svg.SvgDecoder;
|
|
import com.owncloud.android.utils.svg.SvgDecoder;
|
|
import com.owncloud.android.utils.svg.SvgDrawableTranscoder;
|
|
import com.owncloud.android.utils.svg.SvgDrawableTranscoder;
|
|
import com.owncloud.android.utils.svg.SvgSoftwareLayerSetter;
|
|
import com.owncloud.android.utils.svg.SvgSoftwareLayerSetter;
|
|
|
|
|
|
|
|
+import org.apache.commons.httpclient.HttpMethod;
|
|
|
|
+import org.apache.commons.httpclient.HttpStatus;
|
|
|
|
+import org.apache.commons.httpclient.methods.DeleteMethod;
|
|
|
|
+import org.apache.commons.httpclient.methods.GetMethod;
|
|
|
|
+import org.apache.commons.httpclient.methods.PostMethod;
|
|
|
|
+
|
|
|
|
+import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.io.InputStream;
|
|
import java.util.ArrayList;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.List;
|
|
@@ -57,31 +73,36 @@ import butterknife.ButterKnife;
|
|
* This Adapter populates a RecyclerView with all notifications for an account within the app.
|
|
* This Adapter populates a RecyclerView with all notifications for an account within the app.
|
|
*/
|
|
*/
|
|
public class NotificationListAdapter extends RecyclerView.Adapter<NotificationListAdapter.NotificationViewHolder> {
|
|
public class NotificationListAdapter extends RecyclerView.Adapter<NotificationListAdapter.NotificationViewHolder> {
|
|
- private List<Notification> mValues;
|
|
|
|
- private Context context;
|
|
|
|
|
|
+ private static final String TAG = NotificationListAdapter.class.getSimpleName();
|
|
|
|
+
|
|
|
|
+ private List<Notification> notificationsList;
|
|
|
|
+ private OwnCloudClient client;
|
|
|
|
+ private NotificationsActivity notificationsActivity;
|
|
|
|
|
|
- public NotificationListAdapter(Context context) {
|
|
|
|
- this.mValues = new ArrayList<>();
|
|
|
|
- this.context = context;
|
|
|
|
|
|
+ public NotificationListAdapter(OwnCloudClient client, NotificationsActivity notificationsActivity) {
|
|
|
|
+ this.notificationsList = new ArrayList<>();
|
|
|
|
+ this.client = client;
|
|
|
|
+ this.notificationsActivity = notificationsActivity;
|
|
}
|
|
}
|
|
|
|
|
|
public void setNotificationItems(List<Notification> notificationItems) {
|
|
public void setNotificationItems(List<Notification> notificationItems) {
|
|
- mValues.clear();
|
|
|
|
- mValues.addAll(notificationItems);
|
|
|
|
|
|
+ notificationsList.clear();
|
|
|
|
+ notificationsList.addAll(notificationItems);
|
|
notifyDataSetChanged();
|
|
notifyDataSetChanged();
|
|
}
|
|
}
|
|
|
|
|
|
@NonNull
|
|
@NonNull
|
|
@Override
|
|
@Override
|
|
public NotificationViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
|
public NotificationViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
|
- View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.activity_list_item, parent, false);
|
|
|
|
|
|
+ View v = LayoutInflater.from(notificationsActivity).inflate(R.layout.notification_list_item, parent, false);
|
|
return new NotificationViewHolder(v);
|
|
return new NotificationViewHolder(v);
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
@Override
|
|
public void onBindViewHolder(@NonNull NotificationViewHolder holder, int position) {
|
|
public void onBindViewHolder(@NonNull NotificationViewHolder holder, int position) {
|
|
- Notification notification = mValues.get(position);
|
|
|
|
- holder.dateTime.setText(DisplayUtils.getRelativeTimestamp(context, notification.getDatetime().getTime()));
|
|
|
|
|
|
+ Notification notification = notificationsList.get(position);
|
|
|
|
+ holder.dateTime.setText(DisplayUtils.getRelativeTimestamp(notificationsActivity,
|
|
|
|
+ notification.getDatetime().getTime()));
|
|
|
|
|
|
String subject = notification.getSubject();
|
|
String subject = notification.getSubject();
|
|
if (!TextUtils.isEmpty(notification.getLink())) {
|
|
if (!TextUtils.isEmpty(notification.getLink())) {
|
|
@@ -95,14 +116,88 @@ public class NotificationListAdapter extends RecyclerView.Adapter<NotificationLi
|
|
|
|
|
|
// Todo set proper action icon (to be clarified how to pick)
|
|
// Todo set proper action icon (to be clarified how to pick)
|
|
if (!TextUtils.isEmpty(notification.getIcon())) {
|
|
if (!TextUtils.isEmpty(notification.getIcon())) {
|
|
- downloadIcon(notification.getIcon(), holder.activityIcon);
|
|
|
|
|
|
+ downloadIcon(notification.getIcon(), holder.icon);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // add action buttons
|
|
|
|
+ holder.buttons.removeAllViews();
|
|
|
|
+ Button button;
|
|
|
|
+ ExecuteActionTask executeActionTask = new ExecuteActionTask(holder);
|
|
|
|
+
|
|
|
|
+ for (Action action : notification.getActions()) {
|
|
|
|
+ button = new Button(notificationsActivity);
|
|
|
|
+ button.setText(action.label);
|
|
|
|
+ if (action.primary) {
|
|
|
|
+ button.getBackground().setColorFilter(ThemeUtils.primaryColor(notificationsActivity, true),
|
|
|
|
+ PorterDuff.Mode.SRC_ATOP);
|
|
|
|
+ button.setTextColor(ThemeUtils.fontColor(notificationsActivity));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ button.setOnClickListener(v -> executeActionTask.execute(action));
|
|
|
|
+
|
|
|
|
+ holder.buttons.addView(button);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private class ExecuteActionTask extends AsyncTask<Action, Void, Boolean> {
|
|
|
|
+
|
|
|
|
+ private NotificationViewHolder holder;
|
|
|
|
+
|
|
|
|
+ ExecuteActionTask(NotificationViewHolder holder) {
|
|
|
|
+ this.holder = holder;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ @Override
|
|
|
|
+ protected Boolean doInBackground(Action... actions) {
|
|
|
|
+ HttpMethod method;
|
|
|
|
+ Action action = actions[0];
|
|
|
|
+
|
|
|
|
+ switch (action.type) {
|
|
|
|
+ case "GET":
|
|
|
|
+ method = new GetMethod(action.link);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case "POST":
|
|
|
|
+ method = new PostMethod(action.link);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case "DELETE":
|
|
|
|
+ method = new DeleteMethod(action.link);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ // do nothing
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ method.setRequestHeader(RemoteOperation.OCS_API_HEADER, RemoteOperation.OCS_API_HEADER_VALUE);
|
|
|
|
+
|
|
|
|
+ int status;
|
|
|
|
+ try {
|
|
|
|
+ status = client.executeMethod(method);
|
|
|
|
+ } catch (IOException e) {
|
|
|
|
+ Log_OC.e(TAG, "Execution of notification action failed: " + e);
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return status == HttpStatus.SC_OK;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ protected void onPostExecute(Boolean success) {
|
|
|
|
+ if (success) {
|
|
|
|
+ int position = holder.getAdapterPosition();
|
|
|
|
+ notificationsList.remove(position);
|
|
|
|
+ notifyItemRemoved(position);
|
|
|
|
+ } else {
|
|
|
|
+ DisplayUtils.showSnackMessage(notificationsActivity, "Failed to execute action!");
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
private void downloadIcon(String icon, ImageView itemViewType) {
|
|
private void downloadIcon(String icon, ImageView itemViewType) {
|
|
- GenericRequestBuilder<Uri, InputStream, SVG, PictureDrawable> requestBuilder = Glide.with(context)
|
|
|
|
- .using(Glide.buildStreamModelLoader(Uri.class, context), InputStream.class)
|
|
|
|
|
|
+ GenericRequestBuilder<Uri, InputStream, SVG, PictureDrawable> requestBuilder = Glide.with(notificationsActivity)
|
|
|
|
+ .using(Glide.buildStreamModelLoader(Uri.class, notificationsActivity), InputStream.class)
|
|
.from(Uri.class)
|
|
.from(Uri.class)
|
|
.as(SVG.class)
|
|
.as(SVG.class)
|
|
.transcode(new SvgDrawableTranscoder(), PictureDrawable.class)
|
|
.transcode(new SvgDrawableTranscoder(), PictureDrawable.class)
|
|
@@ -112,7 +207,7 @@ public class NotificationListAdapter extends RecyclerView.Adapter<NotificationLi
|
|
.placeholder(R.drawable.ic_notification)
|
|
.placeholder(R.drawable.ic_notification)
|
|
.error(R.drawable.ic_notification)
|
|
.error(R.drawable.ic_notification)
|
|
.animate(android.R.anim.fade_in)
|
|
.animate(android.R.anim.fade_in)
|
|
- .listener(new SvgSoftwareLayerSetter<Uri>());
|
|
|
|
|
|
+ .listener(new SvgSoftwareLayerSetter<>());
|
|
|
|
|
|
|
|
|
|
Uri uri = Uri.parse(icon);
|
|
Uri uri = Uri.parse(icon);
|
|
@@ -123,23 +218,25 @@ public class NotificationListAdapter extends RecyclerView.Adapter<NotificationLi
|
|
}
|
|
}
|
|
|
|
|
|
private void openLink(String link) {
|
|
private void openLink(String link) {
|
|
- context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(link)));
|
|
|
|
|
|
+ notificationsActivity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(link)));
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
@Override
|
|
public int getItemCount() {
|
|
public int getItemCount() {
|
|
- return mValues.size();
|
|
|
|
|
|
+ return notificationsList.size();
|
|
}
|
|
}
|
|
|
|
|
|
static class NotificationViewHolder extends RecyclerView.ViewHolder {
|
|
static class NotificationViewHolder extends RecyclerView.ViewHolder {
|
|
- @BindView(R.id.activity_icon)
|
|
|
|
- public ImageView activityIcon;
|
|
|
|
- @BindView(R.id.activity_subject)
|
|
|
|
|
|
+ @BindView(R.id.notification_icon)
|
|
|
|
+ public ImageView icon;
|
|
|
|
+ @BindView(R.id.notification_subject)
|
|
public TextView subject;
|
|
public TextView subject;
|
|
- @BindView(R.id.activity_message)
|
|
|
|
|
|
+ @BindView(R.id.notification_message)
|
|
public TextView message;
|
|
public TextView message;
|
|
- @BindView(R.id.activity_datetime)
|
|
|
|
|
|
+ @BindView(R.id.notification_datetime)
|
|
public TextView dateTime;
|
|
public TextView dateTime;
|
|
|
|
+ @BindView(R.id.notification_buttons)
|
|
|
|
+ public LinearLayout buttons;
|
|
|
|
|
|
private NotificationViewHolder(View itemView) {
|
|
private NotificationViewHolder(View itemView) {
|
|
super(itemView);
|
|
super(itemView);
|