瀏覽代碼

Merge pull request #6561 from nextcloud/notificationButtonStyling

Make button text non-all-caps for consistent styling
Andy Scherzinger 4 年之前
父節點
當前提交
ef1aaead0c

二進制
screenshots/gplay/debug/com.owncloud.android.ui.activity.NotificationsActivityIT_empty.png


二進制
screenshots/gplay/debug/com.owncloud.android.ui.activity.NotificationsActivityIT_error.png


二進制
screenshots/gplay/debug/com.owncloud.android.ui.activity.NotificationsActivityIT_loading.png


二進制
screenshots/gplay/debug/com.owncloud.android.ui.activity.NotificationsActivityIT_showNotifications.png


+ 1 - 1
scripts/analysis/lint-results.txt

@@ -1,2 +1,2 @@
 DO NOT TOUCH; GENERATED BY DRONE
-      <span class="mdl-layout-title">Lint Report: 83 warnings</span>
+      <span class="mdl-layout-title">Lint Report: 81 warnings</span>

+ 12 - 5
scripts/androidScreenshotTest

@@ -8,13 +8,14 @@ if [ $# -lt 2 ]; then
     exit
 fi
 
-sed -i s'#<bool name="is_beta">false</bool>#<bool name="is_beta">true</bool>#'g src/main/res/values/setup.xml
-
-emulator -writable-system -avd uiComparison -no-snapshot -gpu swiftshader_indirect -no-audio -skin 500x833 &
-
 cd src/androidTest/java
 
-class=$(find | grep $2 | grep java | head -n1|sed s'/\//\./'g | sed s'#^\.\.##' | sed s'#\.java##')
+class=$(find | grep $2 | grep -E "java$|kt$" | head -n1|sed s'/\//\./'g | sed s'#^\.\.##' | sed s'#\.java##'| sed s'#\.kt##')
+
+if [[ -z $class ]]; then
+    echo "Class not found!"
+    exit 1
+fi
 
 cd ../../../
 
@@ -28,6 +29,12 @@ if [ -e $3 ] ; then
     method=""
 else
     method="#$3"
+
+    # check if method exists
+    if [[ $(grep -c $3 $(find | grep $2 | grep -E "java$|kt$" | head -n1)) -eq 0 ]]; then
+        echo "Method not found!"
+        exit 1
+    fi
 fi
 
 ./gradlew gplayDebugExecuteScreenshotTests $record \

+ 131 - 0
src/androidTest/java/com/owncloud/android/ui/activity/NotificationsActivityIT.kt

@@ -0,0 +1,131 @@
+/*
+ *
+ * Nextcloud Android client application
+ *
+ * @author Tobias Kaminsky
+ * Copyright (C) 2020 Tobias Kaminsky
+ * Copyright (C) 2020 Nextcloud GmbH
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+package com.owncloud.android.ui.activity
+
+import androidx.test.espresso.intent.rule.IntentsTestRule
+import com.facebook.testing.screenshot.Screenshot
+import com.owncloud.android.AbstractIT
+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.utils.ScreenshotTest
+import org.junit.Rule
+import org.junit.Test
+import java.util.GregorianCalendar
+
+class NotificationsActivityIT : AbstractIT() {
+    @get:Rule
+    var activityRule = IntentsTestRule(NotificationsActivity::class.java, true, false)
+
+    @Test
+    @ScreenshotTest
+    fun loading() {
+        val sut: NotificationsActivity = activityRule.launchActivity(null)
+
+        Screenshot.snapActivity(sut).record()
+    }
+
+    @Test
+    @ScreenshotTest
+    fun empty() {
+        val sut: NotificationsActivity = activityRule.launchActivity(null)
+
+        sut.runOnUiThread { sut.populateList(ArrayList<Notification>()) }
+
+        shortSleep()
+
+        Screenshot.snapActivity(sut).record()
+    }
+
+    @Test
+    @ScreenshotTest
+    fun showNotifications() {
+        val sut: NotificationsActivity = activityRule.launchActivity(null)
+
+        val date = GregorianCalendar()
+        date.set(2005, 4, 17, 10, 35, 30)
+
+        val notifications = ArrayList<Notification>()
+        notifications.add(
+            Notification(
+                1,
+                "files",
+                "user",
+                date.time,
+                "objectType",
+                "objectId",
+                "App recommendation: Tasks",
+                "SubjectRich",
+                HashMap<String, RichObject>(),
+                "Sync tasks from various devices with your Nextcloud and edit them online.",
+                "MessageRich",
+                HashMap<String, RichObject>(),
+                "link",
+                "icon",
+                ArrayList<Action>()
+            )
+        )
+
+        val actions = ArrayList<Action>()
+        actions.add(Action("Send usage", "link", "url", true))
+        actions.add(Action("Not now", "link", "url", false))
+
+        notifications.add(
+            Notification(
+                1,
+                "files",
+                "user",
+                date.time,
+                "objectType",
+                "objectId",
+                "Help improve Nextcloud",
+                "SubjectRich",
+                HashMap<String, RichObject>(),
+                "Do you want to help us to improve Nextcloud" +
+                    " by providing some anonymize data about your setup and usage?",
+                "MessageRich",
+                HashMap<String, RichObject>(),
+                "link",
+                "icon",
+                actions
+            )
+        )
+
+        sut.runOnUiThread { sut.populateList(notifications) }
+
+        shortSleep()
+
+        Screenshot.snapActivity(sut).record()
+    }
+
+    @Test
+    @ScreenshotTest
+    fun error() {
+        val sut: NotificationsActivity = activityRule.launchActivity(null)
+
+        shortSleep()
+
+        sut.runOnUiThread { sut.setEmptyContent("Error", "Error! Please try again later!") }
+
+        Screenshot.snapActivity(sut).record()
+    }
+}

+ 16 - 14
src/main/java/com/owncloud/android/ui/activity/NotificationsActivity.java

@@ -60,6 +60,7 @@ import java.util.List;
 
 import javax.inject.Inject;
 
+import androidx.annotation.VisibleForTesting;
 import androidx.recyclerview.widget.LinearLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
@@ -239,7 +240,7 @@ public class NotificationsActivity extends FileActivity implements Notifications
     private void setupContent() {
         emptyContentIcon.setImageResource(R.drawable.ic_notification);
         emptyContentProgressBar.getIndeterminateDrawable().setColorFilter(ThemeUtils.primaryAccentColor(this),
-                PorterDuff.Mode.SRC_IN);
+                                                                          PorterDuff.Mode.SRC_IN);
         setLoadingMessage();
 
         LinearLayoutManager layoutManager = new LinearLayoutManager(this);
@@ -249,8 +250,18 @@ public class NotificationsActivity extends FileActivity implements Notifications
         fetchAndSetData();
     }
 
-    private void populateList(List<Notification> notifications) {
+    @VisibleForTesting
+    public void populateList(List<Notification> notifications) {
         adapter.setNotificationItems(notifications);
+
+        if (notifications.size() > 0) {
+            swipeEmptyListRefreshLayout.setVisibility(View.GONE);
+            swipeListRefreshLayout.setVisibility(View.VISIBLE);
+        } else {
+            setEmptyContent(noResultsHeadline, noResultsMessage);
+            swipeListRefreshLayout.setVisibility(View.GONE);
+            swipeEmptyListRefreshLayout.setVisibility(View.VISIBLE);
+        }
     }
 
     private void fetchAndSetData() {
@@ -275,17 +286,7 @@ public class NotificationsActivity extends FileActivity implements Notifications
             if (result.isSuccess() && result.getNotificationData() != null) {
                 final List<Notification> notifications = result.getNotificationData();
 
-                runOnUiThread(() -> {
-                    populateList(notifications);
-                    if (notifications.size() > 0) {
-                        swipeEmptyListRefreshLayout.setVisibility(View.GONE);
-                        swipeListRefreshLayout.setVisibility(View.VISIBLE);
-                    } else {
-                        setEmptyContent(noResultsHeadline, noResultsMessage);
-                        swipeListRefreshLayout.setVisibility(View.GONE);
-                        swipeEmptyListRefreshLayout.setVisibility(View.VISIBLE);
-                    }
-                });
+                runOnUiThread(() -> populateList(notifications));
             } else {
                 Log_OC.d(TAG, result.getLogMessage());
                 // show error
@@ -344,7 +345,8 @@ public class NotificationsActivity extends FileActivity implements Notifications
         emptyContentProgressBar.setVisibility(View.VISIBLE);
     }
 
-    private void setEmptyContent(String headline, String message) {
+    @VisibleForTesting
+    public void setEmptyContent(String headline, String message) {
         if (emptyContentContainer != null && emptyContentMessage != null) {
             emptyContentHeadline.setText(headline);
             emptyContentMessage.setText(message);

+ 19 - 8
src/main/java/com/owncloud/android/ui/adapter/NotificationListAdapter.java

@@ -20,8 +20,10 @@
 package com.owncloud.android.ui.adapter;
 
 import android.content.Intent;
-import android.content.res.ColorStateList;
+import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.graphics.Color;
+import android.graphics.PorterDuff;
 import android.graphics.Typeface;
 import android.graphics.drawable.PictureDrawable;
 import android.net.Uri;
@@ -136,11 +138,17 @@ public class NotificationListAdapter extends RecyclerView.Adapter<NotificationLi
 
         holder.message.setText(notification.getMessage());
 
-        // Todo set proper action icon (to be clarified how to pick)
         if (!TextUtils.isEmpty(notification.getIcon())) {
             downloadIcon(notification.getIcon(), holder.icon);
         }
 
+        int nightModeFlag = notificationsActivity.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
+            if (Configuration.UI_MODE_NIGHT_YES == nightModeFlag) {
+                holder.icon.setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_IN);
+            } else {
+                holder.icon.setColorFilter(Color.BLACK, PorterDuff.Mode.SRC_IN);
+            }
+
         setButtons(holder, notification);
 
         holder.dismiss.setOnClickListener(v -> new DeleteNotificationTask(client, notification, holder,
@@ -154,8 +162,13 @@ public class NotificationListAdapter extends RecyclerView.Adapter<NotificationLi
 
         Resources resources = notificationsActivity.getResources();
         LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
-                                                                         ViewGroup.LayoutParams.WRAP_CONTENT);
-        params.setMargins(20, 0, 20, 0);
+                                                                         LinearLayout.LayoutParams.WRAP_CONTENT);
+        params.setMargins(
+            resources.getDimensionPixelOffset(R.dimen.standard_half_margin),
+            0,
+            resources.getDimensionPixelOffset(R.dimen.standard_half_margin),
+            0
+        );
 
         for (Action action : notification.getActions()) {
             button = new MaterialButton(notificationsActivity);
@@ -164,21 +177,19 @@ public class NotificationListAdapter extends RecyclerView.Adapter<NotificationLi
 
             if (action.primary) {
                 ThemeUtils.colorPrimaryButton(button, notificationsActivity);
-                button.setTypeface(button.getTypeface(), Typeface.BOLD);
             } else {
                 button.setBackgroundColor(resources.getColor(R.color.grey_200));
                 button.setTextColor(primaryColor);
-                button.setTypeface(button.getTypeface(), Typeface.BOLD);
             }
 
+            button.setAllCaps(false);
+
             button.setText(action.label);
             button.setCornerRadiusResource(R.dimen.button_corner_radius);
 
             button.setLayoutParams(params);
             button.setGravity(Gravity.CENTER);
 
-            button.setPadding(40, 40, 40, 40);
-
             button.setOnClickListener(v -> {
                 setButtonEnabled(holder, false);
 

+ 4 - 4
src/main/java/com/owncloud/android/ui/preview/PreviewImageFragment.java

@@ -655,13 +655,13 @@ public class PreviewImageFragment extends FileFragment implements Injectable {
     }
 
     private LayerDrawable generateCheckerboardLayeredDrawable(LoadImage result, Bitmap bitmap) {
-        Resources r = getResources();
+        Resources resources = getResources();
         Drawable[] layers = new Drawable[2];
-        layers[0] = r.getDrawable(R.color.bg_default);
+        layers[0] = ResourcesCompat.getDrawable(resources, R.color.bg_default, null);
         Drawable bitmapDrawable;
 
         if (MIME_TYPE_PNG.equalsIgnoreCase(result.ocFile.getMimeType())) {
-            bitmapDrawable = new BitmapDrawable(getResources(), bitmap);
+            bitmapDrawable = new BitmapDrawable(resources, bitmap);
         } else if (MIME_TYPE_SVG.equalsIgnoreCase(result.ocFile.getMimeType())) {
             bitmapDrawable = result.drawable;
         } else if (MIME_TYPE_GIF.equalsIgnoreCase(result.ocFile.getMimeType())) {
@@ -671,7 +671,7 @@ public class PreviewImageFragment extends FileFragment implements Injectable {
                 bitmapDrawable = result.drawable;
             }
         } else {
-            bitmapDrawable = new BitmapDrawable(getResources(), bitmap);
+            bitmapDrawable = new BitmapDrawable(resources, bitmap);
         }
 
         layers[1] = bitmapDrawable;

+ 0 - 24
src/main/res/drawable/round_bgnd_icons.xml

@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-    Nextcloud Android client application
-
-    @author Andy Scherzinger
-    Copyright (C) 2019 Andy Scherzinger
-
-    This program is free software: you can redistribute it and/or modify
-    it under the terms of the GNU Affero 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 Affero General Public License for more details.
-
-    You should have received a copy of the GNU Affero General Public License
-    along with this program. If not, see <http://www.gnu.org/licenses/>.
--->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
-       android:shape="oval">
-    <solid android:color="#ffffff"/>
-</shape>

+ 0 - 1
src/main/res/layout/notification_list_item.xml

@@ -38,7 +38,6 @@
         android:layout_marginEnd="@dimen/notification_icon_layout_right_end_margin"
         android:padding="2dp"
         android:alpha="0.5"
-        android:background="@drawable/round_bgnd_icons"
         android:contentDescription="@string/notification_icon"
         android:src="@drawable/ic_notification" />
 

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

@@ -61,13 +61,11 @@
     <string name="prefs_value_theme_system">Follow system</string>
     <string name="prefs_theme_title">Theme</string>
 
-
     <string name="recommend_subject">Try %1$s on your device!</string>
     <string name="recommend_text">I want to invite you to use %1$s on your device.\nDownload here: %2$s</string>
     <string name="recommend_urls">%1$s or %2$s</string>
 
     <string name="auth_host_url">Server address https://…</string>
-    <string name="auth_username">Username</string>
     <string name="sync_string_files">Files</string>
     <string name="uploader_btn_upload_text">Upload</string>
     <string name="uploader_btn_alternative_text">Choose</string>