فهرست منبع

also extract execute action task
ignore compound warning
renamed RemoteOperation

Signed-off-by: tobiasKaminsky <tobias@kaminsky.me>

tobiasKaminsky 6 سال پیش
والد
کامیت
6ca671ad85

+ 3 - 3
build.gradle

@@ -210,9 +210,9 @@ dependencies {
     // dependencies for app building
     implementation 'androidx.multidex:multidex:2.0.1'
 //    implementation project('nextcloud-android-library')
-    genericImplementation 'com.github.nextcloud:android-library:master-SNAPSHOT'
-    gplayImplementation 'com.github.nextcloud:android-library:master-SNAPSHOT'
-    versionDevImplementation 'com.github.nextcloud:android-library:master-SNAPSHOT'
+    genericImplementation 'com.github.nextcloud:android-library:deleteNotification-SNAPSHOT'
+    gplayImplementation 'com.github.nextcloud:android-library:deleteNotification-SNAPSHOT'
+    versionDevImplementation 'com.github.nextcloud:android-library:deleteNotification-SNAPSHOT'
     implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
     implementation 'androidx.legacy:legacy-support-v4:1.0.0'
     implementation 'com.google.android.material:material:1.0.0'

+ 52 - 3
src/main/java/com/owncloud/android/ui/activity/NotificationsActivity.java

@@ -28,6 +28,7 @@ import android.accounts.OperationCanceledException;
 import android.content.Intent;
 import android.graphics.PorterDuff;
 import android.os.Bundle;
+import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
 import android.widget.ImageView;
@@ -47,9 +48,11 @@ import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
 import com.owncloud.android.lib.common.operations.RemoteOperation;
 import com.owncloud.android.lib.common.operations.RemoteOperationResult;
 import com.owncloud.android.lib.common.utils.Log_OC;
-import com.owncloud.android.lib.resources.notifications.GetRemoteNotificationsOperation;
+import com.owncloud.android.lib.resources.notifications.GetNotificationsRemoteOperation;
 import com.owncloud.android.lib.resources.notifications.models.Notification;
 import com.owncloud.android.ui.adapter.NotificationListAdapter;
+import com.owncloud.android.ui.asynctasks.DeleteAllNotificationsTask;
+import com.owncloud.android.ui.notifications.NotificationsContract;
 import com.owncloud.android.utils.DisplayUtils;
 import com.owncloud.android.utils.PushUtils;
 import com.owncloud.android.utils.ThemeUtils;
@@ -68,7 +71,7 @@ import butterknife.Unbinder;
 /**
  * Activity displaying all server side stored notification items.
  */
-public class NotificationsActivity extends FileActivity {
+public class NotificationsActivity extends FileActivity implements NotificationsContract.View {
 
     private static final String TAG = NotificationsActivity.class.getSimpleName();
 
@@ -269,7 +272,7 @@ public class NotificationsActivity extends FileActivity {
                 recyclerView.setAdapter(adapter);
             }
 
-            RemoteOperation getRemoteNotificationOperation = new GetRemoteNotificationsOperation();
+            RemoteOperation getRemoteNotificationOperation = new GetNotificationsRemoteOperation();
             final RemoteOperationResult result = getRemoteNotificationOperation.execute(client);
 
             if (result.isSuccess() && result.getNotificationData() != null) {
@@ -305,6 +308,11 @@ public class NotificationsActivity extends FileActivity {
         });
     }
 
+    public boolean onCreateOptionsMenu(Menu menu) {
+        getMenuInflater().inflate(R.menu.notifications_actions_menu, menu);
+
+        return true;
+    }
 
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
@@ -319,6 +327,10 @@ public class NotificationsActivity extends FileActivity {
                 }
                 break;
 
+            case R.id.action_empty_notifications:
+                new DeleteAllNotificationsTask(client, this).execute();
+                break;
+
             default:
                 retval = super.onOptionsItemSelected(item);
                 break;
@@ -353,4 +365,41 @@ public class NotificationsActivity extends FileActivity {
 
         setDrawerMenuItemChecked(R.id.nav_notifications);
     }
+
+    @Override
+    public void onRemovedNotification(boolean isSuccess, NotificationListAdapter.NotificationViewHolder holder) {
+        if (isSuccess) {
+            adapter.removeNotification(holder);
+
+            if (adapter.getItemCount() == 0) {
+                setEmptyContent(noResultsHeadline, noResultsMessage);
+                swipeListRefreshLayout.setVisibility(View.GONE);
+                swipeEmptyListRefreshLayout.setVisibility(View.VISIBLE);
+            }
+        } else {
+            DisplayUtils.showSnackMessage(this, getString(R.string.remove_notification_failed));
+        }
+    }
+
+    @Override
+    public void onRemovedAllNotifications(boolean isSuccess) {
+        if (isSuccess) {
+            adapter.removeAllNotifications();
+            setEmptyContent(noResultsHeadline, noResultsMessage);
+            swipeListRefreshLayout.setVisibility(View.GONE);
+            swipeEmptyListRefreshLayout.setVisibility(View.VISIBLE);
+        } else {
+            DisplayUtils.showSnackMessage(this, getString(R.string.clear_notifications_failed));
+        }
+    }
+
+    @Override
+    public void onActionCallback(boolean isSuccess, NotificationListAdapter.NotificationViewHolder holder) {
+        if (isSuccess) {
+            adapter.removeNotification(holder);
+        } else {
+            adapter.setButtonEnabled(holder, true);
+            DisplayUtils.showSnackMessage(this, getString(R.string.notification_action_failed));
+        }
+    }
 }

+ 21 - 68
src/main/java/com/owncloud/android/ui/adapter/NotificationListAdapter.java

@@ -27,7 +27,6 @@ import android.graphics.PorterDuff;
 import android.graphics.Typeface;
 import android.graphics.drawable.PictureDrawable;
 import android.net.Uri;
-import android.os.AsyncTask;
 import android.text.Spannable;
 import android.text.SpannableStringBuilder;
 import android.text.TextUtils;
@@ -50,25 +49,18 @@ import com.caverock.androidsvg.SVG;
 import com.google.android.material.button.MaterialButton;
 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.RichObject;
 import com.owncloud.android.ui.activity.NotificationsActivity;
+import com.owncloud.android.ui.asynctasks.DeleteNotificationTask;
+import com.owncloud.android.ui.asynctasks.NotificationExecuteActionTask;
 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.SvgDrawableTranscoder;
 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.util.ArrayList;
 import java.util.List;
@@ -176,11 +168,14 @@ public class NotificationListAdapter extends RecyclerView.Adapter<NotificationLi
             button.setOnClickListener(v -> {
                 setButtonEnabled(holder, false);
 
-                new ExecuteActionTask(holder).execute(action);
+                new NotificationExecuteActionTask(client, holder, notificationsActivity).execute(action);
             });
 
             holder.buttons.addView(button);
         }
+
+        holder.dismiss.setOnClickListener(v -> new DeleteNotificationTask(client, notification, holder,
+                                                                          notificationsActivity).execute());
     }
 
     private SpannableStringBuilder makeSpecialPartsBold(Notification notification) {
@@ -211,67 +206,23 @@ public class NotificationListAdapter extends RecyclerView.Adapter<NotificationLi
         return ssb;
     }
 
-    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;
-            }
+    public void removeNotification(NotificationViewHolder holder) {
+        int position = holder.getAdapterPosition();
 
-            return status == HttpStatus.SC_OK || status == HttpStatus.SC_ACCEPTED;
+        if (position >= 0 && position < notificationsList.size()) {
+            notificationsList.remove(position);
+            notifyItemRemoved(position);
+            notifyItemRangeChanged(position, notificationsList.size());
         }
+    }
 
-        @Override
-        protected void onPostExecute(Boolean success) {
-            if (success) {
-                int position = holder.getAdapterPosition();
-
-                if (position >= 0 && position < notificationsList.size()) {
-                    notificationsList.remove(position);
-                    notifyItemRemoved(position);
-                }
-            } else {
-                setButtonEnabled(holder, true);
-                DisplayUtils.showSnackMessage(notificationsActivity, "Failed to execute action!");
-            }
-        }
+    public void removeAllNotifications() {
+        notificationsList.clear();
+        notifyDataSetChanged();
     }
 
-    private void setButtonEnabled(NotificationViewHolder holder, boolean enabled) {
+
+    public void setButtonEnabled(NotificationViewHolder holder, boolean enabled) {
         for (int i = 0; i < holder.buttons.getChildCount(); i++) {
             holder.buttons.getChildAt(i).setEnabled(enabled);
         }
@@ -310,7 +261,7 @@ public class NotificationListAdapter extends RecyclerView.Adapter<NotificationLi
         return notificationsList.size();
     }
 
-    static class NotificationViewHolder extends RecyclerView.ViewHolder {
+    public static class NotificationViewHolder extends RecyclerView.ViewHolder {
         @BindView(R.id.notification_icon)
         public ImageView icon;
         @BindView(R.id.notification_subject)
@@ -321,6 +272,8 @@ public class NotificationListAdapter extends RecyclerView.Adapter<NotificationLi
         public TextView dateTime;
         @BindView(R.id.notification_buttons)
         public LinearLayout buttons;
+        @BindView(R.id.notification_dismiss)
+        public ImageView dismiss;
 
         private NotificationViewHolder(View itemView) {
             super(itemView);

+ 54 - 0
src/main/java/com/owncloud/android/ui/asynctasks/DeleteAllNotificationsTask.java

@@ -0,0 +1,54 @@
+/*
+ * Nextcloud Android client application
+ *
+ * @author Tobias Kaminsky
+ * Copyright (C) 2019 Tobias Kaminsky
+ * Copyright (C) 2019 Nextcloud GmbH
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package com.owncloud.android.ui.asynctasks;
+
+import android.os.AsyncTask;
+
+import com.owncloud.android.lib.common.OwnCloudClient;
+import com.owncloud.android.lib.common.operations.RemoteOperationResult;
+import com.owncloud.android.lib.resources.notifications.DeleteAllNotificationsRemoteOperation;
+import com.owncloud.android.lib.resources.notifications.models.Action;
+import com.owncloud.android.ui.activity.NotificationsActivity;
+import com.owncloud.android.ui.notifications.NotificationsContract;
+
+public class DeleteAllNotificationsTask extends AsyncTask<Action, Void, Boolean> {
+    private OwnCloudClient client;
+    private NotificationsContract.View notificationsActivity;
+
+    public DeleteAllNotificationsTask(OwnCloudClient client, NotificationsActivity notificationsActivity) {
+        this.client = client;
+        this.notificationsActivity = notificationsActivity;
+    }
+
+    @Override
+    protected Boolean doInBackground(Action... actions) {
+
+        RemoteOperationResult result = new DeleteAllNotificationsRemoteOperation().execute(client);
+
+        return result.isSuccess();
+    }
+
+    @Override
+    protected void onPostExecute(Boolean success) {
+        notificationsActivity.onRemovedAllNotifications(success);
+    }
+}

+ 63 - 0
src/main/java/com/owncloud/android/ui/asynctasks/DeleteNotificationTask.java

@@ -0,0 +1,63 @@
+/*
+ * Nextcloud Android client application
+ *
+ * @author Tobias Kaminsky
+ * Copyright (C) 2019 Tobias Kaminsky
+ * Copyright (C) 2019 Nextcloud GmbH
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package com.owncloud.android.ui.asynctasks;
+
+import android.os.AsyncTask;
+
+import com.owncloud.android.lib.common.OwnCloudClient;
+import com.owncloud.android.lib.common.operations.RemoteOperationResult;
+import com.owncloud.android.lib.resources.notifications.DeleteNotificationRemoteOperation;
+import com.owncloud.android.lib.resources.notifications.models.Action;
+import com.owncloud.android.lib.resources.notifications.models.Notification;
+import com.owncloud.android.ui.activity.NotificationsActivity;
+import com.owncloud.android.ui.adapter.NotificationListAdapter;
+import com.owncloud.android.ui.notifications.NotificationsContract;
+
+public class DeleteNotificationTask extends AsyncTask<Action, Void, Boolean> {
+    private Notification notification;
+    private NotificationListAdapter.NotificationViewHolder holder;
+    private OwnCloudClient client;
+    private NotificationsContract.View notificationsActivity;
+
+    public DeleteNotificationTask(OwnCloudClient client, Notification notification,
+                                  NotificationListAdapter.NotificationViewHolder holder,
+                                  NotificationsActivity notificationsActivity) {
+        this.client = client;
+        this.notification = notification;
+        this.holder = holder;
+        this.notificationsActivity = notificationsActivity;
+    }
+
+    @Override
+    protected Boolean doInBackground(Action... actions) {
+
+        RemoteOperationResult result = new DeleteNotificationRemoteOperation(notification.notificationId)
+            .execute(client);
+
+        return result.isSuccess();
+    }
+
+    @Override
+    protected void onPostExecute(Boolean success) {
+        notificationsActivity.onRemovedNotification(success, holder);
+    }
+}

+ 73 - 0
src/main/java/com/owncloud/android/ui/asynctasks/NotificationExecuteActionTask.java

@@ -0,0 +1,73 @@
+package com.owncloud.android.ui.asynctasks;
+
+import android.os.AsyncTask;
+
+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.ui.activity.NotificationsActivity;
+import com.owncloud.android.ui.adapter.NotificationListAdapter;
+
+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;
+
+public class NotificationExecuteActionTask extends AsyncTask<Action, Void, Boolean> {
+
+    private NotificationListAdapter.NotificationViewHolder holder;
+    private OwnCloudClient client;
+    private NotificationsActivity notificationsActivity;
+
+    public NotificationExecuteActionTask(OwnCloudClient client, NotificationListAdapter.NotificationViewHolder holder,
+                                         NotificationsActivity notificationsActivity) {
+        this.client = client;
+        this.holder = holder;
+        this.notificationsActivity = notificationsActivity;
+    }
+
+    @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(this, "Execution of notification action failed: " + e);
+            return false;
+        }
+
+        return status == HttpStatus.SC_OK || status == HttpStatus.SC_ACCEPTED;
+    }
+
+    @Override
+    protected void onPostExecute(Boolean isSuccess) {
+        notificationsActivity.onActionCallback(isSuccess, holder);
+    }
+}

+ 35 - 0
src/main/java/com/owncloud/android/ui/notifications/NotificationsContract.java

@@ -0,0 +1,35 @@
+/*
+ * Nextcloud Android client application
+ *
+ * @author Tobias Kaminsky
+ * Copyright (C) 2019 Tobias Kaminsky
+ * Copyright (C) 2019 Nextcloud GmbH
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package com.owncloud.android.ui.notifications;
+
+import com.owncloud.android.ui.adapter.NotificationListAdapter;
+
+public interface NotificationsContract {
+
+    interface View {
+        void onRemovedNotification(boolean isSuccess, NotificationListAdapter.NotificationViewHolder holder);
+
+        void onRemovedAllNotifications(boolean isSuccess);
+
+        void onActionCallback(boolean isSuccess, NotificationListAdapter.NotificationViewHolder holder);
+    }
+}

+ 26 - 12
src/main/res/layout/notification_list_item.xml

@@ -5,22 +5,21 @@
   @author Tobias Kaminsky
   Copyright (C) 2018 Tobias Kaminsky
   Copyright (C) 2018 Nextcloud GmbH.
- 
+
   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
- 
+
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   GNU General Public License for more details.
- 
+
   You should have received a copy of the GNU General Public License
   along with this program. If not, see <https://www.gnu.org/licenses/>.
 -->
-<RelativeLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
@@ -28,7 +27,8 @@
     android:paddingTop="@dimen/standard_padding"
     android:paddingRight="@dimen/standard_padding"
     android:paddingBottom="@dimen/standard_padding"
-    android:paddingLeft="@dimen/standard_padding">
+    android:paddingLeft="@dimen/standard_padding"
+    tools:ignore="UseCompoundDrawables">
 
     <ImageView
         android:id="@+id/notification_icon"
@@ -49,13 +49,27 @@
         android:layout_toRightOf="@id/notification_icon"
         android:layout_toEndOf="@id/notification_icon">
 
-        <TextView
-            android:id="@+id/notification_subject"
+        <LinearLayout
             android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:ellipsize="end"
-            tools:text="@string/placeholder_filename"
-            android:textAppearance="?android:attr/textAppearanceListItem"/>
+            android:layout_height="match_parent"
+            android:orientation="horizontal">
+
+            <TextView
+                android:id="@+id/notification_subject"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:ellipsize="end"
+                android:textAppearance="?android:attr/textAppearanceListItem"
+                tools:text="@string/placeholder_filename" />
+
+            <ImageView
+                android:id="@+id/notification_dismiss"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:src="@drawable/ic_close"
+                android:contentDescription="@string/dismiss_notification_description" />
+        </LinearLayout>
 
         <TextView
             android:id="@+id/notification_message"

+ 32 - 0
src/main/res/menu/notifications_actions_menu.xml

@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ Nextcloud Android client application
+
+  @author Tobias Kaminsky
+  Copyright (C) 2019 Tobias Kaminsky
+  Copyright (C) 2019 Nextcloud GmbH.
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program. If not, see <https://www.gnu.org/licenses/>.
+-->
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    tools:ignore="AppCompatResource">
+
+    <item
+        android:id="@+id/action_empty_notifications"
+        android:contentDescription="@string/action_empty_notifications"
+        android:orderInCategory="1"
+        android:title="@string/action_empty_notifications"
+        app:showAsAction="never" />
+</menu>

+ 3 - 3
src/main/res/menu/trashbin_actions_menu.xml

@@ -5,17 +5,17 @@
   @author Tobias Kaminsky
   Copyright (C) 2018 Tobias Kaminsky
   Copyright (C) 2018 Nextcloud GmbH.
- 
+
   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
- 
+
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   GNU General Public License for more details.
- 
+
   You should have received a copy of the GNU General Public License
   along with this program. If not, see <https://www.gnu.org/licenses/>.
 -->

+ 5 - 0
src/main/res/values/strings.xml

@@ -855,4 +855,9 @@
     <string name="upload_local_storage_not_copied">File could not be copied to local storage</string>
     <string name="host_not_available">Server not available</string>
     <string name="delete_entries">Delete entries</string>
+    <string name="dismiss_notification_description">Dismiss notification</string>
+    <string name="action_empty_notifications">Clear all notifications</string>
+    <string name="clear_notifications_failed">Failed to clear notifications!</string>
+    <string name="remove_notification_failed">Failed to remove notification!</string>
+    <string name="notification_action_failed">Failed to execute action!</string>
 </resources>