Browse Source

Merge pull request #6332 from nextcloud/enh/darkThemeOptimizations

Enh/dark theme optimizations
Tobias Kaminsky 4 years ago
parent
commit
3c609a329f
21 changed files with 106 additions and 103 deletions
  1. BIN
      screenshots/gplay/debug/com.nextcloud.client.FileDisplayActivityIT_showShares.png
  2. BIN
      screenshots/gplay/debug/com.owncloud.android.ui.activity.ManageAccountsActivityIT_open.png
  3. BIN
      screenshots/gplay/debug/com.owncloud.android.ui.fragment.OCFileListFragmentIT_createAndShowShareViaLink.png
  4. 1 1
      scripts/analysis/findbugs-results.txt
  5. 1 2
      src/main/java/com/owncloud/android/ui/activity/CommunityActivity.java
  6. 1 1
      src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java
  7. 6 5
      src/main/java/com/owncloud/android/ui/activity/FolderPickerActivity.java
  8. 2 2
      src/main/java/com/owncloud/android/ui/activity/PassCodeActivity.java
  9. 3 7
      src/main/java/com/owncloud/android/ui/activity/ReceiveExternalFilesActivity.java
  10. 1 2
      src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java
  11. 1 3
      src/main/java/com/owncloud/android/ui/activity/UploadFilesActivity.java
  12. 1 2
      src/main/java/com/owncloud/android/ui/adapter/NotificationListAdapter.java
  13. 1 1
      src/main/java/com/owncloud/android/ui/dialog/SendShareDialog.java
  14. 1 1
      src/main/java/com/owncloud/android/ui/dialog/SortingOrderDialogFragment.java
  15. 4 6
      src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java
  16. 2 8
      src/main/java/com/owncloud/android/ui/fragment/contactsbackup/ContactsBackupFragment.java
  17. 1 2
      src/main/java/com/owncloud/android/ui/preview/PreviewTextStringFragment.java
  18. 1 1
      src/main/java/com/owncloud/android/utils/MimeTypeUtil.java
  19. 79 57
      src/main/java/com/owncloud/android/utils/ThemeUtils.java
  20. 0 1
      src/main/res/values-night/colors.xml
  21. 0 1
      src/main/res/values/colors.xml

BIN
screenshots/gplay/debug/com.nextcloud.client.FileDisplayActivityIT_showShares.png


BIN
screenshots/gplay/debug/com.owncloud.android.ui.activity.ManageAccountsActivityIT_open.png


BIN
screenshots/gplay/debug/com.owncloud.android.ui.fragment.OCFileListFragmentIT_createAndShowShareViaLink.png


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

@@ -1 +1 @@
-340
+339

+ 1 - 2
src/main/java/com/owncloud/android/ui/activity/CommunityActivity.java

@@ -92,8 +92,7 @@ public class CommunityActivity extends FileActivity {
                                 getString(R.string.contributing_link)))));
 
         MaterialButton reportButton = findViewById(R.id.community_testing_report);
-        reportButton.setBackgroundColor(ThemeUtils.primaryColor(this,true));
-        reportButton.setTextColor(ThemeUtils.fontColor(this, false));
+        ThemeUtils.colorPrimaryButton(reportButton, this);
         reportButton.setOnClickListener(v -> DisplayUtils.startLinkIntent(this, R.string.report_issue_link));
     }
 

+ 1 - 1
src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java

@@ -703,7 +703,7 @@ public abstract class DrawerActivity extends ToolbarActivity
             mCheckedMenuItem = menuItemId;
             MenuItem currentItem = mNavigationView.getMenu().findItem(menuItemId);
             int drawerColor = getResources().getColor(R.color.drawer_text_color);
-            int activeColor = ThemeUtils.elementColor(this);
+            int activeColor = ThemeUtils.primaryColor(null, true, true, this);
 
             currentItem.setChecked(true);
 

+ 6 - 5
src/main/java/com/owncloud/android/ui/activity/FolderPickerActivity.java

@@ -25,9 +25,7 @@ import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.res.ColorStateList;
 import android.content.res.Resources.NotFoundException;
-import android.graphics.PorterDuff;
 import android.os.Bundle;
 import android.os.Parcelable;
 import android.util.Log;
@@ -401,13 +399,16 @@ public class FolderPickerActivity extends FileActivity implements FileFragment.C
         mChooseBtn = findViewById(R.id.folder_picker_btn_choose);
 
         if (mChooseBtn != null) {
-            mChooseBtn.setBackgroundTintMode(PorterDuff.Mode.SRC_ATOP);
-            mChooseBtn.setBackgroundTintList(ColorStateList.valueOf(ThemeUtils.primaryColor(this, true)));
+            ThemeUtils.colorPrimaryButton(mChooseBtn, this);
             mChooseBtn.setOnClickListener(this);
         }
 
         if (mCancelBtn != null) {
-            mCancelBtn.setTextColor(ThemeUtils.primaryColor(this, true));
+            if (this instanceof FilePickerActivity) {
+                ThemeUtils.colorPrimaryButton(mCancelBtn, this);
+            } else {
+                mCancelBtn.setTextColor(ThemeUtils.primaryColor(this, true));
+            }
             mCancelBtn.setOnClickListener(this);
         }
     }

+ 2 - 2
src/main/java/com/owncloud/android/ui/activity/PassCodeActivity.java

@@ -95,10 +95,10 @@ public class PassCodeActivity extends AppCompatActivity implements Injectable {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.passcodelock);
 
-        int elementColor = ThemeUtils.elementColor(this);
+        int elementColor = ThemeUtils.primaryColor(this);
 
         mBCancel = findViewById(R.id.cancel);
-        mBCancel.setBackgroundColor(ThemeUtils.primaryColor(this));
+        ThemeUtils.colorPrimaryButton(mBCancel, this);
 
         mPassCodeHdr = findViewById(R.id.header);
         mPassCodeHdrExplanation = findViewById(R.id.explanation);

+ 3 - 7
src/main/java/com/owncloud/android/ui/activity/ReceiveExternalFilesActivity.java

@@ -765,19 +765,15 @@ public class ReceiveExternalFilesActivity extends FileActivity
                 mListView.setAdapter(sa);
             }
             MaterialButton btnChooseFolder = findViewById(R.id.uploader_choose_folder);
-            btnChooseFolder.setBackgroundTintMode(PorterDuff.Mode.SRC_ATOP);
-            btnChooseFolder.setBackgroundTintList(ColorStateList.valueOf(ThemeUtils.primaryColor(this, true)));
+            ThemeUtils.colorPrimaryButton(btnChooseFolder, this);
             btnChooseFolder.setOnClickListener(this);
-            btnChooseFolder.setTextColor(ThemeUtils.fontColor(this));
 
             if (mFile.canWrite()) {
                 btnChooseFolder.setEnabled(true);
-                btnChooseFolder.setBackgroundTintList(ColorStateList.valueOf(ThemeUtils.primaryColor(getAccount(),
-                                                                                                     true,
-                                                                                                     this)));
+                ThemeUtils.colorPrimaryButton(btnChooseFolder, this);
             } else {
                 btnChooseFolder.setEnabled(false);
-                btnChooseFolder.setBackgroundTintList(ColorStateList.valueOf(Color.GRAY));
+                btnChooseFolder.setBackgroundColor(Color.GRAY);
             }
 
             ThemeUtils.colorStatusBar(this);

+ 1 - 2
src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java

@@ -243,8 +243,7 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA
         adapter = new SyncedFolderAdapter(this, clock, gridWidth, this, lightVersion);
         syncedFolderProvider = new SyncedFolderProvider(getContentResolver(), preferences, clock);
         emptyContentIcon.setImageResource(R.drawable.nav_synced_folders);
-        emptyContentActionButton.setBackgroundColor(ThemeUtils.primaryColor(this));
-        emptyContentActionButton.setTextColor(ThemeUtils.fontColor(this));
+        ThemeUtils.colorPrimaryButton(emptyContentActionButton, this);
 
         final GridLayoutManager lm = new GridLayoutManager(this, gridWidth);
         adapter.setLayoutManager(lm);

+ 1 - 3
src/main/java/com/owncloud/android/ui/activity/UploadFilesActivity.java

@@ -178,9 +178,7 @@ public class UploadFilesActivity extends FileActivity implements LocalFileListFr
         cancelButton.setOnClickListener(this);
 
         MaterialButton uploadButton = findViewById(R.id.upload_files_btn_upload);
-        uploadButton.setBackgroundTintMode(PorterDuff.Mode.SRC_ATOP);
-        uploadButton.setBackgroundTintList(ColorStateList.valueOf(ThemeUtils.primaryColor(this, true)));
-        uploadButton.setTextColor(ThemeUtils.fontColor(this, false));
+        ThemeUtils.colorPrimaryButton(uploadButton, this);
         uploadButton.setOnClickListener(this);
 
         sortButton = findViewById(R.id.sort_button);

+ 1 - 2
src/main/java/com/owncloud/android/ui/adapter/NotificationListAdapter.java

@@ -163,8 +163,7 @@ public class NotificationListAdapter extends RecyclerView.Adapter<NotificationLi
             int primaryColor = ThemeUtils.primaryColor(notificationsActivity);
 
             if (action.primary) {
-                button.setBackgroundColor(primaryColor);
-                button.setTextColor(ThemeUtils.fontColor(notificationsActivity));
+                ThemeUtils.colorPrimaryButton(button, notificationsActivity);
                 button.setTypeface(button.getTypeface(), Typeface.BOLD);
             } else {
                 button.setBackgroundColor(resources.getColor(R.color.grey_200));

+ 1 - 1
src/main/java/com/owncloud/android/ui/dialog/SendShareDialog.java

@@ -194,7 +194,7 @@ public class SendShareDialog extends BottomSheetDialogFragment {
     }
 
     private void themeShareButtonImage(ImageView shareImageView) {
-        shareImageView.getBackground().setColorFilter(ThemeUtils.elementColor(getContext()), PorterDuff.Mode.SRC_IN);
+        shareImageView.getBackground().setColorFilter(ThemeUtils.primaryColor(getContext()), PorterDuff.Mode.SRC_IN);
         shareImageView.getDrawable().mutate().setColorFilter(ThemeUtils.fontColor(getContext()),
                 PorterDuff.Mode.SRC_IN);
     }

+ 1 - 1
src/main/java/com/owncloud/android/ui/dialog/SortingOrderDialogFragment.java

@@ -130,7 +130,7 @@ public class SortingOrderDialogFragment extends DialogFragment {
      * tints the icon reflecting the actual sorting choice in the apps primary color.
      */
     private void setupActiveOrderSelection() {
-        final int color = ThemeUtils.elementColor(getContext());
+        final int color = ThemeUtils.primaryColor(null, true, true, getContext());
         for (View view: mTaggedViews) {
             if (!((FileSortOrder) view.getTag()).name.equals(mCurrentSortOrderName)) {
                 continue;

+ 4 - 6
src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java

@@ -293,8 +293,7 @@ public class OCFileListFragment extends ExtendedListFragment implements
         mFabMain = requireActivity().findViewById(R.id.fab_main);
 
         if (mFabMain != null) { // is not available in FolderPickerActivity
-            ThemeUtils.tintFloatingActionButton(mFabMain, requireContext());
-            ThemeUtils.drawableFloatingActionButton(mFabMain, R.drawable.ic_plus, requireContext());
+            ThemeUtils.colorFloatingActionButton(mFabMain, R.drawable.ic_plus, requireContext());
         }
 
         Log_OC.i(TAG, "onCreateView() end");
@@ -1770,7 +1769,7 @@ public class OCFileListFragment extends ExtendedListFragment implements
             getActivity().runOnUiThread(() -> {
                 if (visible) {
                     mFabMain.show();
-                    ThemeUtils.tintFloatingActionButton(mFabMain, requireContext());
+                    ThemeUtils.colorFloatingActionButton(mFabMain, requireContext());
                 } else {
                     mFabMain.hide();
                 }
@@ -1820,11 +1819,10 @@ public class OCFileListFragment extends ExtendedListFragment implements
             getActivity().runOnUiThread(() -> {
                 if (enabled) {
                     mFabMain.setEnabled(true);
-                    ThemeUtils.tintFloatingActionButton(mFabMain, requireContext());
+                    ThemeUtils.colorFloatingActionButton(mFabMain, requireContext());
                 } else {
                     mFabMain.setEnabled(false);
-                    mFabMain.setBackgroundTintList(ColorStateList.valueOf(Color.GRAY));
-                    mFabMain.setRippleColor(Color.GRAY);
+                    ThemeUtils.colorFloatingActionButton(mFabMain, requireContext(), Color.GRAY);
                 }
             });
         }

+ 2 - 8
src/main/java/com/owncloud/android/ui/fragment/contactsbackup/ContactsBackupFragment.java

@@ -184,14 +184,8 @@ public class ContactsBackupFragment extends FileFragment implements DatePickerDi
             calendarPickerOpen = true;
         }
 
-        int primaryColor = ThemeUtils.primaryColor(getContext());
-        int fontColor = ThemeUtils.fontColor(getContext());
-
-        backupNow.setBackgroundColor(primaryColor);
-        backupNow.setTextColor(fontColor);
-
-        contactsDatePickerBtn.setBackgroundColor(primaryColor);
-        contactsDatePickerBtn.setTextColor(fontColor);
+        ThemeUtils.colorPrimaryButton(backupNow, getContext());
+        ThemeUtils.colorPrimaryButton(contactsDatePickerBtn, getContext());
 
         return view;
     }

+ 1 - 2
src/main/java/com/owncloud/android/ui/preview/PreviewTextStringFragment.java

@@ -113,8 +113,7 @@ public class PreviewTextStringFragment extends PreviewTextFragment {
             fabMain.setVisibility(View.VISIBLE);
             fabMain.setEnabled(true);
             fabMain.setOnClickListener(v -> edit());
-            ThemeUtils.tintFloatingActionButton(fabMain, requireContext());
-            ThemeUtils.drawableFloatingActionButton(fabMain, R.drawable.ic_edit, requireContext());
+            ThemeUtils.colorFloatingActionButton(fabMain, R.drawable.ic_edit, requireContext());
         }
 
         return view;

+ 1 - 1
src/main/java/com/owncloud/android/utils/MimeTypeUtil.java

@@ -177,7 +177,7 @@ public final class MimeTypeUtil {
             drawableId = R.drawable.folder;
         }
 
-        return ThemeUtils.tintDrawable(drawableId, ThemeUtils.elementColor(account, context, true));
+        return ThemeUtils.tintDrawable(drawableId, ThemeUtils.primaryColor(account, true, context));
     }
 
     public static Drawable getDefaultFolderIcon(Context context) {

+ 79 - 57
src/main/java/com/owncloud/android/utils/ThemeUtils.java

@@ -38,6 +38,7 @@ import android.text.style.ForegroundColorSpan;
 import android.view.MenuItem;
 import android.view.View;
 import android.view.Window;
+import android.widget.Button;
 import android.widget.EditText;
 import android.widget.ImageButton;
 import android.widget.ImageView;
@@ -118,7 +119,15 @@ public final class ThemeUtils {
         OCCapability capability = getCapability(account, context);
 
         try {
-            return adjustLightness(-0.2f, Color.parseColor(capability.getServerColor()), -1f);
+            return calculateDarkColor(Color.parseColor(capability.getServerColor()), context);
+        } catch (Exception e) {
+            return context.getResources().getColor(R.color.primary_dark);
+        }
+    }
+
+    public static int calculateDarkColor(int color, Context context){
+        try {
+            return adjustLightness(-0.2f, color, -1f);
         } catch (Exception e) {
             return context.getResources().getColor(R.color.primary_dark);
         }
@@ -133,6 +142,24 @@ public final class ThemeUtils {
     }
 
     public static int primaryColor(Account account, boolean replaceEdgeColors, Context context) {
+        return primaryColor(account, replaceEdgeColors, false, context);
+    }
+
+    /**
+     * return the primary color defined in the server-side theming respecting Android dark/light theming and edge case
+     * scenarios including drawer menu.
+     *
+     * @param account                          the Nextcloud user
+     * @param replaceEdgeColors                flag if edge case color scenarios should be handled
+     * @param replaceEdgeColorsByInvertedColor flag in edge case handling should be done via color inversion
+     *                                         (black/white)
+     * @param context                          the context (needed to load client-side colors)
+     * @return the color
+     */
+    public static int primaryColor(Account account,
+                                   boolean replaceEdgeColors,
+                                   boolean replaceEdgeColorsByInvertedColor,
+                                   Context context) {
         if (context == null) {
             return Color.GRAY;
         }
@@ -142,13 +169,21 @@ public final class ThemeUtils {
             if (replaceEdgeColors) {
                 if (isDarkModeActive(context)) {
                     if (Color.BLACK == color) {
-                        return getNeutralGrey(context);
+                        if (replaceEdgeColorsByInvertedColor) {
+                            return Color.WHITE;
+                        } else {
+                            return getNeutralGrey(context);
+                        }
                     } else {
                         return color;
                     }
                 } else {
                     if (Color.WHITE == color) {
-                        return getNeutralGrey(context);
+                        if (replaceEdgeColorsByInvertedColor) {
+                            return Color.BLACK;
+                        } else {
+                            return getNeutralGrey(context);
+                        }
                     } else {
                         return color;
                     }
@@ -165,51 +200,6 @@ public final class ThemeUtils {
         return darkTheme(context) ? context.getResources().getColor(R.color.fg_contrast) : Color.GRAY;
     }
 
-    public static int elementColor(Context context) {
-        return elementColor(null, context, false);
-    }
-
-    @NextcloudServer(max = 12)
-    public static int elementColor(Account account, Context context, boolean replaceEdgeColors) {
-        OCCapability capability = getCapability(account, context);
-
-        try {
-            return Color.parseColor(capability.getServerElementColor());
-        } catch (Exception e) {
-            int color;
-
-            try {
-                color = Color.parseColor(capability.getServerColor());
-            } catch (Exception e1) {
-                color = context.getResources().getColor(R.color.primary);
-            }
-
-            if (replaceEdgeColors) {
-                if (isDarkModeActive(context)) {
-                    if (Color.BLACK == color) {
-                        return getNeutralGrey(context);
-                    } else {
-                        return color;
-                    }
-                } else {
-                    if (Color.WHITE == color) {
-                        return getNeutralGrey(context);
-                    } else {
-                        return color;
-                    }
-                }
-            } else {
-                float[] hsl = colorToHSL(color);
-
-                if (hsl[INDEX_LUMINATION] > LUMINATION_THRESHOLD) {
-                    return context.getResources().getColor(R.color.element_fallback_color);
-                } else {
-                    return color;
-                }
-            }
-        }
-    }
-
     public static boolean themingEnabled(Context context) {
         return getCapability(context).getServerColor() != null && !getCapability(context).getServerColor().isEmpty();
     }
@@ -409,6 +399,21 @@ public final class ThemeUtils {
         return hsl;
     }
 
+    public static void colorPrimaryButton(Button button, Context context) {
+        int primaryColor = ThemeUtils.primaryColor(null, true, false, context);
+        int fontColor = ThemeUtils.fontColor(context, false);
+
+        button.setBackgroundColor(primaryColor);
+
+        if (Color.BLACK == primaryColor) {
+            button.setTextColor(Color.WHITE);
+        } else if (Color.WHITE == primaryColor) {
+            button.setTextColor(Color.BLACK);
+        } else {
+            button.setTextColor(fontColor);
+        }
+    }
+
     /**
      * sets the tinting of the given ImageButton's icon to color_accent.
      *
@@ -420,10 +425,10 @@ public final class ThemeUtils {
         }
     }
 
-    public static void colorEditText(EditText editText, int elementColor) {
+    public static void colorEditText(EditText editText, int color) {
         if (editText != null) {
-            editText.setTextColor(elementColor);
-            editText.getBackground().setColorFilter(elementColor, PorterDuff.Mode.SRC_ATOP);
+            editText.setTextColor(color);
+            editText.getBackground().setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
         }
     }
 
@@ -680,14 +685,31 @@ public final class ThemeUtils {
         return String.format("#%06X", 0xFFFFFF & color);
     }
 
-    public static void tintFloatingActionButton(FloatingActionButton button, Context context) {
-        button.setBackgroundTintList(ColorStateList.valueOf(ThemeUtils.primaryColor(context)));
-        button.setRippleColor(ThemeUtils.primaryDarkColor(context));
+    public static void colorFloatingActionButton(FloatingActionButton button, @DrawableRes int drawable,
+                                                 Context context) {
+        int primaryColor = ThemeUtils.primaryColor(null, true, false, context);
+        colorFloatingActionButton(button, context, primaryColor);
+
+        if (Color.BLACK == primaryColor) {
+            button.setImageDrawable(ThemeUtils.tintDrawable(drawable, Color.WHITE));
+        } else if (Color.WHITE == primaryColor) {
+            button.setImageDrawable(ThemeUtils.tintDrawable(drawable, Color.BLACK));
+        } else {
+            button.setImageDrawable(ThemeUtils.tintDrawable(drawable, ThemeUtils.fontColor(context, false)));
+        }
+    }
+
+    public static void colorFloatingActionButton(FloatingActionButton button, Context context) {
+        colorFloatingActionButton(button, context, ThemeUtils.primaryColor(null, true, false, context));
+    }
+
+    public static void colorFloatingActionButton(FloatingActionButton button, Context context, int primaryColor) {
+        colorFloatingActionButton(button, primaryColor, calculateDarkColor(primaryColor, context));
     }
 
-    public static void drawableFloatingActionButton(FloatingActionButton button, @DrawableRes int
-        drawable, Context context) {
-        button.setImageDrawable(ThemeUtils.tintDrawable(drawable, ThemeUtils.fontColor(context)));
+    public static void colorFloatingActionButton(FloatingActionButton button, int backgroundColor, int rippleColor) {
+        button.setBackgroundTintList(ColorStateList.valueOf(backgroundColor));
+        button.setRippleColor(rippleColor);
     }
 
     private static OCCapability getCapability(Context context) {

+ 0 - 1
src/main/res/values-night/colors.xml

@@ -43,7 +43,6 @@
     <color name="switch_thumb_color_unchecked">#2a2a2a</color>
     <color name="switch_track_color_unchecked">#B3FFFFFF</color>
     <color name="drawer_active_item_background">@color/white</color>
-    <color name="element_fallback_color">#EDEDED</color>
 
     <!-- App bar -->
     <color name="appbar">#1E1E1E</color>

+ 0 - 1
src/main/res/values/colors.xml

@@ -37,7 +37,6 @@
 
     <!-- Colors -->
     <color name="standard_grey">#757575</color>
-    <color name="element_fallback_color">#555555</color>
     <color name="grey_200">#EEEEEE</color>
     <color name="grey_db">#dbdbdb</color>
     <color name="actionbar_shadow">#222222</color>