Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/stefan-niedermann/nextcloud-deck.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNiedermann IT-Dienstleistungen <stefan-niedermann@users.noreply.github.com>2023-02-12 00:34:16 +0300
committerGitHub <noreply@github.com>2023-02-12 00:34:16 +0300
commit23a8635d0a76edeeb2aa02eff296590b7695e80c (patch)
treeb3ad6fd319782ebb5e590f2f5a53e2e24e9d7b3f /app/src/main/java/it/niedermann
parenta70b7edcba351e45f97e26f840a1744fb64fb2d8 (diff)
feat(theming): Integrate android-common Nextcloud library for unified M3 theming (#1431)
* refactor(branding): Use android-common to apply branding * refactor(branding): Rename BrandingUtil to ViewThemeUtils * refactor(branding): Move DeckViewThemeUtils to own class * refactor(branding): Apply theming to NavigationView * refactor(branding): Roll out android-common based theming * refactor(branding): Change terminology from "branding" to "theming" * refactor(branding): Get rid of DeckColorUtil Signed-off-by: Stefan Niedermann <info@niedermann.it>
Diffstat (limited to 'app/src/main/java/it/niedermann')
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/DeckApplication.java19
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/MainActivity.java63
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/PickStackActivity.java37
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/PushNotificationActivity.java25
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/about/AboutActivity.java5
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/about/AboutFragmentLicenseTab.java18
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/accountswitcher/AccountSwitcherDialog.java6
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/archivedcards/ArchivedCardsAdapter.java2
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/board/DeleteBoardDialogFragment.java2
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/board/EditBoardDialogFragment.java18
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/board/accesscontrol/AccessControlAdapter.java53
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/board/accesscontrol/AccessControlDialogFragment.java17
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/board/managelabels/EditLabelDialogFragment.java13
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/board/managelabels/ManageLabelsAdapter.java23
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/board/managelabels/ManageLabelsDialogFragment.java18
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/Branded.java9
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedDialogFragment.java19
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedPreferenceCategory.java44
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedSnackbar.java46
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedSwitchPreference.java104
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandingUtil.java119
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/AbstractCardViewHolder.java9
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/CardAdapter.java20
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/CompactCardViewHolder.java6
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/DefaultCardViewHolder.java6
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/EditActivity.java25
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/EditCardViewModel.java12
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/NewCardDialog.java9
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/assignee/CardAssigneeDialog.java2
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/AttachmentViewHolder.java14
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/CardAttachmentAdapter.java12
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/CardAttachmentsFragment.java29
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/DefaultAttachmentViewHolder.java10
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/DeleteAttachmentDialogFragment.java2
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/ImageAttachmentViewHolder.java4
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/CardCommentsAdapter.java11
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/CardCommentsEditDialogFragment.java13
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/CardCommentsFragment.java13
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/ItemCommentViewHolder.java8
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/details/CardDetailsFragment.java53
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterDialogFragment.java19
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/movecard/MoveCardDialogFragment.java21
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/settings/SettingsFragment.java26
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/sharetarget/ShareProgressDialogFragment.java17
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/stack/DeleteStackDialogFragment.java2
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/stack/EditStackDialogFragment.java13
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/stack/StackFragment.java6
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/takephoto/TakePhotoActivity.java8
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/DeckViewThemeUtils.java120
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/DeleteAlertDialogBuilder.java (renamed from app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/DeleteAlertDialogBuilder.java)8
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/ThemeUtils.java81
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/Themed.java9
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/ThemedDatePickerDialog.java (renamed from app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedDatePickerDialog.java)34
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/ThemedDialogFragment.java19
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/ThemedPreferenceCategory.java43
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/ThemedSnackbar.java31
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/ThemedSwitchPreference.java89
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/ThemedTimePickerDialog.java (renamed from app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedTimePickerDialog.java)26
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/upcomingcards/UpcomingCardsAdapter.java11
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/widget/singlecard/SelectCardForWidgetActivity.java6
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/util/DeckColorUtil.java63
61 files changed, 752 insertions, 818 deletions
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/DeckApplication.java b/app/src/main/java/it/niedermann/nextcloud/deck/DeckApplication.java
index 99c3d2aa6..9902e011d 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/DeckApplication.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/DeckApplication.java
@@ -5,7 +5,6 @@ import static androidx.lifecycle.Transformations.distinctUntilChanged;
import android.app.Application;
import android.content.Context;
-import android.content.res.Configuration;
import android.os.StrictMode;
import androidx.annotation.ColorInt;
@@ -14,6 +13,7 @@ import androidx.core.content.ContextCompat;
import androidx.lifecycle.LiveData;
import androidx.preference.PreferenceManager;
+import com.nextcloud.android.common.ui.util.PlatformThemeUtil;
import com.nextcloud.android.sso.helper.SingleAccountHelper;
import it.niedermann.android.sharedpreferences.SharedPreferenceIntLiveData;
@@ -39,7 +39,7 @@ public class DeckApplication extends Application {
PREF_KEY_THEME = getString(R.string.pref_key_dark_theme);
PREF_KEY_DEBUGGING = getString(R.string.pref_key_debugging);
- setAppTheme(getAppTheme(this));
+ setAppTheme(getAppThemeSetting(this));
DeckLog.enablePersistentLogs(isPersistentLoggingEnabled(this));
final var sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
currentAccountColor$ = distinctUntilChanged(new SharedPreferenceIntLiveData(sharedPreferences,
@@ -91,7 +91,7 @@ public class DeckApplication extends Application {
setDefaultNightMode(setting);
}
- public static int getAppTheme(@NonNull Context context) {
+ public static int getAppThemeSetting(@NonNull Context context) {
final var prefs = PreferenceManager.getDefaultSharedPreferences(context);
String mode;
try {
@@ -102,20 +102,13 @@ public class DeckApplication extends Application {
return Integer.parseInt(mode);
}
- public static boolean isDarkThemeActive(@NonNull Context context, int darkModeSetting) {
+ public static boolean isDarkTheme(@NonNull Context context) {
+ final var darkModeSetting = getAppThemeSetting(context);
return darkModeSetting == Integer.parseInt(context.getString(R.string.pref_value_theme_system_default))
- ? isDarkThemeActive(context)
+ ? PlatformThemeUtil.isDarkMode(context)
: darkModeSetting == Integer.parseInt(context.getString(R.string.pref_value_theme_dark));
}
- public static boolean isDarkThemeActive(@NonNull Context context) {
- return (context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES;
- }
-
- public static boolean isDarkTheme(@NonNull Context context) {
- return isDarkThemeActive(context, getAppTheme(context));
- }
-
// --------------------------------------
// Current account / board / stack states
// --------------------------------------
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/MainActivity.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/MainActivity.java
index bc35f5692..db6815685 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/MainActivity.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/MainActivity.java
@@ -11,13 +11,8 @@ import static it.niedermann.nextcloud.deck.DeckApplication.saveCurrentAccount;
import static it.niedermann.nextcloud.deck.DeckApplication.saveCurrentBoardId;
import static it.niedermann.nextcloud.deck.DeckApplication.saveCurrentStackId;
import static it.niedermann.nextcloud.deck.persistence.sync.adapters.db.util.LiveDataHelper.observeOnce;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.applyBrandToExtendedFAB;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.applyBrandToPrimaryTabLayout;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.clearBrandColors;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.getSecondaryForegroundColorDependingOnTheme;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.saveBrandColors;
-import static it.niedermann.nextcloud.deck.util.DeckColorUtil.contrastRatioIsSufficient;
-import static it.niedermann.nextcloud.deck.util.DeckColorUtil.contrastRatioIsSufficientBigAreas;
+import static it.niedermann.nextcloud.deck.ui.theme.ThemeUtils.clearBrandColors;
+import static it.niedermann.nextcloud.deck.ui.theme.ThemeUtils.saveBrandColors;
import static it.niedermann.nextcloud.deck.util.DrawerMenuUtil.MENU_ID_ABOUT;
import static it.niedermann.nextcloud.deck.util.DrawerMenuUtil.MENU_ID_ADD_BOARD;
import static it.niedermann.nextcloud.deck.util.DrawerMenuUtil.MENU_ID_ARCHIVED_BOARDS;
@@ -32,7 +27,6 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.sqlite.SQLiteConstraintException;
-import android.graphics.Color;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkRequest;
@@ -87,6 +81,7 @@ import java.util.Objects;
import it.niedermann.android.crosstabdnd.CrossTabDragAndDrop;
import it.niedermann.android.tablayouthelper.TabLayoutHelper;
import it.niedermann.android.tablayouthelper.TabTitleGenerator;
+import it.niedermann.android.util.ColorUtil;
import it.niedermann.nextcloud.deck.DeckApplication;
import it.niedermann.nextcloud.deck.DeckLog;
import it.niedermann.nextcloud.deck.R;
@@ -112,8 +107,6 @@ import it.niedermann.nextcloud.deck.ui.board.ArchiveBoardListener;
import it.niedermann.nextcloud.deck.ui.board.DeleteBoardListener;
import it.niedermann.nextcloud.deck.ui.board.EditBoardDialogFragment;
import it.niedermann.nextcloud.deck.ui.board.EditBoardListener;
-import it.niedermann.nextcloud.deck.ui.branding.BrandedSnackbar;
-import it.niedermann.nextcloud.deck.ui.branding.BrandingUtil;
import it.niedermann.nextcloud.deck.ui.card.CardAdapter;
import it.niedermann.nextcloud.deck.ui.card.CreateCardListener;
import it.niedermann.nextcloud.deck.ui.card.NewCardDialog;
@@ -130,6 +123,8 @@ import it.niedermann.nextcloud.deck.ui.stack.EditStackListener;
import it.niedermann.nextcloud.deck.ui.stack.OnScrollListener;
import it.niedermann.nextcloud.deck.ui.stack.StackAdapter;
import it.niedermann.nextcloud.deck.ui.stack.StackFragment;
+import it.niedermann.nextcloud.deck.ui.theme.ThemeUtils;
+import it.niedermann.nextcloud.deck.ui.theme.ThemedSnackbar;
import it.niedermann.nextcloud.deck.ui.upcomingcards.UpcomingCardsActivity;
import it.niedermann.nextcloud.deck.util.CustomAppGlideModule;
import it.niedermann.nextcloud.deck.util.DrawerMenuUtil;
@@ -196,7 +191,7 @@ public class MainActivity extends AppCompatActivity implements DeleteStackListen
Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler(this));
setTheme(R.style.AppTheme);
- colorAccent = BrandingUtil.getAttribute(this, R.attr.colorAccent);
+ colorAccent = ContextCompat.getColor(this, R.color.accent);
binding = ActivityMainBinding.inflate(getLayoutInflater());
headerBinding = NavHeaderMainBinding.bind(binding.navigationView.getHeaderView(0));
@@ -218,8 +213,8 @@ public class MainActivity extends AppCompatActivity implements DeleteStackListen
binding.navigationView.setNavigationItemSelectedListener(this);
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
- DeckApplication.readCurrentAccountColor().observe(this, this::applyAccountBranding);
- DeckApplication.readCurrentBoardColor().observe(this, this::applyBoardBranding);
+ DeckApplication.readCurrentAccountColor().observe(this, this::applyAccountTheme);
+ DeckApplication.readCurrentBoardColor().observe(this, this::applyBoardTheme);
binding.filterText.addTextChangedListener(new TextWatcher() {
@Override
@@ -452,17 +447,25 @@ public class MainActivity extends AppCompatActivity implements DeleteStackListen
binding.accountSwitcher.setOnClickListener((v) -> AccountSwitcherDialog.newInstance().show(getSupportFragmentManager(), AccountSwitcherDialog.class.getSimpleName()));
}
- private void applyBoardBranding(@ColorInt int mainColor) {
- applyBrandToPrimaryTabLayout(mainColor, binding.stackTitles);
- applyBrandToExtendedFAB(mainColor, binding.fab);
- // TODO We assume, that the background of the spinner is always white
- binding.swipeRefreshLayout.setColorSchemeColors(contrastRatioIsSufficient(Color.WHITE, mainColor) ? mainColor : DeckApplication.isDarkTheme(this) ? Color.DKGRAY : colorAccent);
- DrawableCompat.setTint(binding.filterIndicator.getDrawable(), getSecondaryForegroundColorDependingOnTheme(this, mainColor));
+ private void applyBoardTheme(@ColorInt int color) {
+ final var utils = ThemeUtils.of(color, this);
+ final var scheme = ThemeUtils.createScheme(color, this);
+
+ utils.deck.themeTabLayout(binding.stackTitles);
+ utils.deck.themeExtendedFAB(binding.fab);
+ utils.androidx.themeSwipeRefreshLayout(binding.swipeRefreshLayout);
+ utils.platform.colorEditText(binding.filterText);
+
+ DrawableCompat.setTint(binding.filterIndicator.getDrawable(), scheme.getOnPrimaryContainer());
}
- private void applyAccountBranding(@ColorInt int accountColor) {
+ private void applyAccountTheme(@ColorInt int accountColor) {
+ final var utils = ThemeUtils.of(accountColor, this);
+
+ utils.deck.colorNavigationView(binding.navigationView);
+
headerBinding.headerView.setBackgroundColor(accountColor);
- @ColorInt final int headerTextColor = contrastRatioIsSufficientBigAreas(accountColor, Color.WHITE) ? Color.WHITE : Color.BLACK;
+ @ColorInt final int headerTextColor = ColorUtil.INSTANCE.getForegroundColorForBackgroundColor(accountColor);
headerBinding.appName.setTextColor(headerTextColor);
DrawableCompat.setTint(headerBinding.logo.getDrawable(), headerTextColor);
DrawableCompat.setTint(headerBinding.copyDebugLogs.getDrawable(), headerTextColor);
@@ -497,7 +500,7 @@ public class MainActivity extends AppCompatActivity implements DeleteStackListen
@Override
public void onError(Throwable error) {
IResponseCallback.super.onError(error);
- runOnUiThread(() -> BrandedSnackbar.make(binding.coordinatorLayout, Objects.requireNonNull(error.getLocalizedMessage()), Snackbar.LENGTH_LONG)
+ runOnUiThread(() -> ThemedSnackbar.make(binding.coordinatorLayout, Objects.requireNonNull(error.getLocalizedMessage()), Snackbar.LENGTH_LONG)
.setAction(R.string.simple_more, v -> ExceptionDialogFragment.newInstance(error, mainViewModel.getCurrentAccount()).show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName()))
.setAnchorView(binding.fab)
.show());
@@ -548,7 +551,7 @@ public class MainActivity extends AppCompatActivity implements DeleteStackListen
@Override
public void onError(Throwable throwable) {
IResponseCallback.super.onError(throwable);
- runOnUiThread(() -> BrandedSnackbar.make(binding.coordinatorLayout, R.string.synchronization_failed, Snackbar.LENGTH_LONG)
+ runOnUiThread(() -> ThemedSnackbar.make(binding.coordinatorLayout, R.string.synchronization_failed, Snackbar.LENGTH_LONG)
.setAction(R.string.simple_more, v -> ExceptionDialogFragment.newInstance(throwable, mainViewModel.getCurrentAccount()).show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName()))
.setAnchorView(binding.fab)
.show());
@@ -857,14 +860,14 @@ public class MainActivity extends AppCompatActivity implements DeleteStackListen
if (!response.isMaintenanceEnabled()) {
if (response.getDeckVersion().isSupported()) {
runOnUiThread(() -> {
- final var importSnackbar = BrandedSnackbar.make(binding.coordinatorLayout, R.string.account_is_getting_imported, Snackbar.LENGTH_INDEFINITE)
+ final var importSnackbar = ThemedSnackbar.make(binding.coordinatorLayout, R.string.account_is_getting_imported, Snackbar.LENGTH_INDEFINITE)
.setAnchorView(binding.fab);
importSnackbar.show();
importSyncManager.synchronize(new ResponseCallback<>(createdAccount) {
@Override
public void onResponse(Boolean syncSuccess) {
importSnackbar.dismiss();
- runOnUiThread(() -> BrandedSnackbar.make(binding.coordinatorLayout, getString(R.string.account_imported), Snackbar.LENGTH_LONG)
+ runOnUiThread(() -> ThemedSnackbar.make(binding.coordinatorLayout, getString(R.string.account_imported), Snackbar.LENGTH_LONG)
.setAnchorView(binding.fab)
.setAction(R.string.simple_switch, (a) -> {
createdAccount.setColor(response.getColor());
@@ -932,7 +935,7 @@ public class MainActivity extends AppCompatActivity implements DeleteStackListen
IResponseCallback.super.onError(error);
if (error instanceof SQLiteConstraintException) {
DeckLog.warn("Account already added");
- BrandedSnackbar.make(binding.coordinatorLayout, R.string.account_already_added, Snackbar.LENGTH_LONG)
+ ThemedSnackbar.make(binding.coordinatorLayout, R.string.account_already_added, Snackbar.LENGTH_LONG)
.setAnchorView(binding.fab)
.show();
} else {
@@ -1116,7 +1119,7 @@ public class MainActivity extends AppCompatActivity implements DeleteStackListen
/**
- * Displays a {@link BrandedSnackbar} for an exception of a failed sync, but only if the cause wasn't maintenance mode (this should be handled by a TextView instead of a snackbar).
+ * Displays a {@link ThemedSnackbar} for an exception of a failed sync, but only if the cause wasn't maintenance mode (this should be handled by a TextView instead of a snackbar).
*
* @param throwable the cause of the failed sync
*/
@@ -1125,7 +1128,7 @@ public class MainActivity extends AppCompatActivity implements DeleteStackListen
if (!(throwable instanceof NextcloudHttpRequestFailedException) || ((NextcloudHttpRequestFailedException) throwable).getStatusCode() != HttpURLConnection.HTTP_UNAVAILABLE) {
runOnUiThread(() -> {
if (binding != null) { // Can be null in case the activity has been destroyed before the synchronization process has been finished
- BrandedSnackbar.make(binding.coordinatorLayout, R.string.synchronization_failed, Snackbar.LENGTH_LONG)
+ ThemedSnackbar.make(binding.coordinatorLayout, R.string.synchronization_failed, Snackbar.LENGTH_LONG)
.setAction(R.string.simple_more, v -> ExceptionDialogFragment.newInstance(throwable, mainViewModel.getCurrentAccount()).show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName()))
.setAnchorView(binding.fab)
.show();
@@ -1159,7 +1162,7 @@ public class MainActivity extends AppCompatActivity implements DeleteStackListen
.setMultiChoiceItems(animals, checkedItems, (dialog, which, isChecked) -> checkedItems[0] = isChecked)
.setPositiveButton(R.string.simple_clone, (dialog, which) -> {
binding.drawerLayout.closeDrawer(GravityCompat.START);
- final var snackbar = BrandedSnackbar.make(binding.coordinatorLayout, getString(R.string.cloning_board, board.getTitle()), Snackbar.LENGTH_INDEFINITE)
+ final var snackbar = ThemedSnackbar.make(binding.coordinatorLayout, getString(R.string.cloning_board, board.getTitle()), Snackbar.LENGTH_INDEFINITE)
.setAnchorView(binding.fab);
snackbar.show();
mainViewModel.cloneBoard(board.getAccountId(), board.getLocalId(), board.getAccountId(), board.getColor(), checkedItems[0], new IResponseCallback<>() {
@@ -1168,7 +1171,7 @@ public class MainActivity extends AppCompatActivity implements DeleteStackListen
runOnUiThread(() -> {
snackbar.dismiss();
setCurrentBoard(response.getBoard());
- BrandedSnackbar.make(binding.coordinatorLayout, getString(R.string.successfully_cloned_board, response.getBoard().getTitle()), Snackbar.LENGTH_LONG)
+ ThemedSnackbar.make(binding.coordinatorLayout, getString(R.string.successfully_cloned_board, response.getBoard().getTitle()), Snackbar.LENGTH_LONG)
.setAction(R.string.edit, v -> EditBoardDialogFragment.newInstance(response.getLocalId()).show(getSupportFragmentManager(), EditBoardDialogFragment.class.getSimpleName()))
.setAnchorView(binding.fab)
.show();
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/PickStackActivity.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/PickStackActivity.java
index 1d54ec015..358f17bbf 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/PickStackActivity.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/PickStackActivity.java
@@ -1,44 +1,35 @@
package it.niedermann.nextcloud.deck.ui;
import static androidx.lifecycle.Transformations.switchMap;
-import static it.niedermann.nextcloud.deck.DeckApplication.isDarkTheme;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.getSecondaryForegroundColorDependingOnTheme;
-import static it.niedermann.nextcloud.deck.util.DeckColorUtil.contrastRatioIsSufficientBigAreas;
-import android.content.res.ColorStateList;
-import android.graphics.Color;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
-import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
-import androidx.core.graphics.drawable.DrawableCompat;
import androidx.lifecycle.ViewModelProvider;
import java.util.List;
-import it.niedermann.android.util.ColorUtil;
-import it.niedermann.nextcloud.deck.DeckLog;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.api.IResponseCallback;
import it.niedermann.nextcloud.deck.databinding.ActivityPickStackBinding;
import it.niedermann.nextcloud.deck.model.Account;
import it.niedermann.nextcloud.deck.model.Board;
import it.niedermann.nextcloud.deck.model.Stack;
-import it.niedermann.nextcloud.deck.ui.branding.Branded;
-import it.niedermann.nextcloud.deck.ui.branding.BrandingUtil;
import it.niedermann.nextcloud.deck.ui.exception.ExceptionDialogFragment;
import it.niedermann.nextcloud.deck.ui.exception.ExceptionHandler;
import it.niedermann.nextcloud.deck.ui.pickstack.PickStackFragment;
import it.niedermann.nextcloud.deck.ui.pickstack.PickStackListener;
import it.niedermann.nextcloud.deck.ui.pickstack.PickStackViewModel;
+import it.niedermann.nextcloud.deck.ui.theme.ThemeUtils;
+import it.niedermann.nextcloud.deck.ui.theme.Themed;
-public abstract class PickStackActivity extends AppCompatActivity implements Branded, PickStackListener {
+public abstract class PickStackActivity extends AppCompatActivity implements Themed, PickStackListener {
private ActivityPickStackBinding binding;
private PickStackViewModel viewModel;
@@ -93,7 +84,7 @@ public abstract class PickStackActivity extends AppCompatActivity implements Bra
}
});
});
- viewModel.submitButtonEnabled().observe(this, (enabled) -> binding.submit.setEnabled(enabled));
+ viewModel.submitButtonEnabled().observe(this, enabled -> binding.submit.setEnabled(enabled));
if (requireContent()) {
viewModel.setContentIsSatisfied(false);
binding.inputWrapper.setVisibility(View.VISIBLE);
@@ -127,25 +118,19 @@ public abstract class PickStackActivity extends AppCompatActivity implements Bra
@Override
public void onStackPicked(@NonNull Account account, @Nullable Board board, @Nullable Stack stack) {
viewModel.setSelected(account, board, stack);
- applyBrand(board == null
+ applyTheme(board == null
? ContextCompat.getColor(this, R.color.accent)
: board.getColor()
);
}
@Override
- public void applyBrand(int mainColor) {
- try {
- @ColorInt final int finalMainColor = contrastRatioIsSufficientBigAreas(mainColor, ContextCompat.getColor(this, R.color.primary))
- ? mainColor
- : isDarkTheme(this) ? Color.WHITE : Color.BLACK;
- DrawableCompat.setTintList(binding.submit.getBackground(), ColorStateList.valueOf(finalMainColor));
- binding.submit.setTextColor(ColorUtil.INSTANCE.getForegroundColorForBackgroundColor(finalMainColor));
- binding.cancel.setTextColor(getSecondaryForegroundColorDependingOnTheme(this, mainColor));
- BrandingUtil.applyBrandToEditTextInputLayout(mainColor, binding.inputWrapper);
- } catch (Throwable t) {
- DeckLog.logError(t);
- }
+ public void applyTheme(int color) {
+ final var utils = ThemeUtils.of(color, this);
+
+ utils.material.colorMaterialButtonText(binding.cancel);
+ utils.material.colorMaterialButtonPrimaryFilled(binding.submit);
+ utils.material.colorTextInputLayout(binding.inputWrapper);
}
abstract protected void onSubmit(Account account, long boardLocalId, long stackId, @NonNull IResponseCallback<Void> callback);
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/PushNotificationActivity.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/PushNotificationActivity.java
index f76187a04..3b2332e7e 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/PushNotificationActivity.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/PushNotificationActivity.java
@@ -1,10 +1,7 @@
package it.niedermann.nextcloud.deck.ui;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.getSecondaryForegroundColorDependingOnTheme;
-
import android.annotation.SuppressLint;
import android.content.Intent;
-import android.graphics.PorterDuff;
import android.net.Uri;
import android.view.View;
@@ -15,8 +12,8 @@ import androidx.lifecycle.ViewModelProvider;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import java.util.stream.Stream;
-import it.niedermann.android.util.ColorUtil;
import it.niedermann.nextcloud.deck.DeckLog;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.databinding.ActivityPushNotificationBinding;
@@ -24,6 +21,7 @@ import it.niedermann.nextcloud.deck.model.Account;
import it.niedermann.nextcloud.deck.ui.card.EditActivity;
import it.niedermann.nextcloud.deck.ui.exception.ExceptionDialogFragment;
import it.niedermann.nextcloud.deck.ui.exception.ExceptionHandler;
+import it.niedermann.nextcloud.deck.ui.theme.ThemeUtils;
/**
* Warning: Do not move this class to another package or folder!
@@ -54,7 +52,7 @@ public class PushNotificationActivity extends AppCompatActivity {
setSupportActionBar(binding.toolbar);
binding.progress.setIndeterminate(true);
- viewModel.getAccount().observe(this, this::applyBrandToSubmitButton);
+ viewModel.getAccount().observe(this, this::applyThemeToSubmitButton);
executor.submit(() -> viewModel.getCardInformation(intent.getExtras(), new PushNotificationViewModel.PushNotificationCallback() {
@Override
public void onResponse(@NonNull PushNotificationViewModel.CardInformation cardInformation) {
@@ -123,16 +121,11 @@ public class PushNotificationActivity extends AppCompatActivity {
// TODO implement Branded interface
// TODO apply branding based on board color
- public void applyBrandToSubmitButton(@ColorInt int mainColor) {
- try {
- binding.progress.getProgressDrawable().setColorFilter(
- getSecondaryForegroundColorDependingOnTheme(this, mainColor), PorterDuff.Mode.SRC_IN);
- binding.submit.setBackgroundColor(mainColor);
- binding.submit.setTextColor(ColorUtil.INSTANCE.getForegroundColorForBackgroundColor(mainColor));
- binding.showError.setBackgroundColor(mainColor);
- binding.showError.setTextColor(ColorUtil.INSTANCE.getForegroundColorForBackgroundColor(mainColor));
- } catch (Throwable t) {
- DeckLog.logError(t);
- }
+ public void applyThemeToSubmitButton(@ColorInt int color) {
+ final var utils = ThemeUtils.of(color, this);
+
+ utils.platform.themeHorizontalProgressBar(binding.progress);
+ Stream.of(binding.submit, binding.showError)
+ .forEach(utils.material::colorMaterialButtonPrimaryFilled);
}
}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/about/AboutActivity.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/about/AboutActivity.java
index 552e9b5fd..cfb43c382 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/about/AboutActivity.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/about/AboutActivity.java
@@ -1,7 +1,5 @@
package it.niedermann.nextcloud.deck.ui.about;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.applyBrandToPrimaryTabLayout;
-
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
@@ -20,6 +18,7 @@ import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.databinding.ActivityAboutBinding;
import it.niedermann.nextcloud.deck.model.Account;
import it.niedermann.nextcloud.deck.ui.exception.ExceptionHandler;
+import it.niedermann.nextcloud.deck.ui.theme.ThemeUtils;
public class AboutActivity extends AppCompatActivity {
private static final String BUNDLE_KEY_ACCOUNT = "account";
@@ -39,7 +38,7 @@ public class AboutActivity extends AppCompatActivity {
binding = ActivityAboutBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
- DeckApplication.readCurrentAccountColor().observe(this, (mainColor) -> applyBrandToPrimaryTabLayout(mainColor, binding.tabLayout));
+ DeckApplication.readCurrentAccountColor().observe(this, color -> ThemeUtils.of(color, this).deck.themeTabLayout(binding.tabLayout));
setSupportActionBar(binding.toolbar);
binding.viewPager.setAdapter(new TabsPagerAdapter(this, (Account) getIntent().getSerializableExtra(BUNDLE_KEY_ACCOUNT)));
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/about/AboutFragmentLicenseTab.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/about/AboutFragmentLicenseTab.java
index 39a30ec2e..dafc54bee 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/about/AboutFragmentLicenseTab.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/about/AboutFragmentLicenseTab.java
@@ -1,29 +1,22 @@
package it.niedermann.nextcloud.deck.ui.about;
-import static it.niedermann.nextcloud.deck.DeckApplication.isDarkTheme;
-import static it.niedermann.nextcloud.deck.util.DeckColorUtil.contrastRatioIsSufficientBigAreas;
import static it.niedermann.nextcloud.deck.util.SpannableUtil.setTextWithURL;
import android.content.Intent;
-import android.content.res.ColorStateList;
-import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.core.content.ContextCompat;
-import androidx.core.graphics.drawable.DrawableCompat;
import androidx.fragment.app.Fragment;
-import it.niedermann.android.util.ColorUtil;
import it.niedermann.nextcloud.deck.DeckApplication;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.databinding.FragmentAboutLicenseTabBinding;
+import it.niedermann.nextcloud.deck.ui.theme.ThemeUtils;
public class AboutFragmentLicenseTab extends Fragment {
@@ -41,13 +34,8 @@ public class AboutFragmentLicenseTab extends Fragment {
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
- DeckApplication.readCurrentAccountColor().observe(getViewLifecycleOwner(), (mainColor) -> {
- @ColorInt final int finalMainColor = contrastRatioIsSufficientBigAreas(mainColor, ContextCompat.getColor(requireContext(), R.color.primary))
- ? mainColor
- : isDarkTheme(requireContext()) ? Color.WHITE : Color.BLACK;
- DrawableCompat.setTintList(binding.aboutAppLicenseButton.getBackground(), ColorStateList.valueOf(finalMainColor));
- binding.aboutAppLicenseButton.setTextColor(ColorUtil.INSTANCE.getForegroundColorForBackgroundColor(finalMainColor));
- });
+ DeckApplication.readCurrentAccountColor().observe(getViewLifecycleOwner(), color ->
+ ThemeUtils.of(color, requireContext()).material.colorMaterialButtonPrimaryFilled(binding.aboutAppLicenseButton));
}
@Override
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/accountswitcher/AccountSwitcherDialog.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/accountswitcher/AccountSwitcherDialog.java
index 12150641a..1f0098c4f 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/accountswitcher/AccountSwitcherDialog.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/accountswitcher/AccountSwitcherDialog.java
@@ -70,7 +70,7 @@ public class AccountSwitcherDialog extends DialogFragment {
adapter.setAccounts(accounts.stream().filter(account ->
!Objects.equals(account.getId(), viewModel.getCurrentAccount().getId())).collect(Collectors.toList())));
- observeOnce(DeckApplication.readCurrentBoardColor(), requireActivity(), this::applyBrand);
+ observeOnce(DeckApplication.readCurrentBoardColor(), requireActivity(), this::applyTheme);
binding.accountsList.setAdapter(adapter);
@@ -108,7 +108,7 @@ public class AccountSwitcherDialog extends DialogFragment {
return new AccountSwitcherDialog();
}
- private void applyBrand(int mainColor) {
-// applyBrandToLayerDrawable((LayerDrawable) binding.check.getDrawable(), R.id.area, mainColor);
+ private void applyTheme(int color) {
+// applyThemeToLayerDrawable((LayerDrawable) binding.check.getDrawable(), R.id.area, mainColor);
}
}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/archivedcards/ArchivedCardsAdapter.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/archivedcards/ArchivedCardsAdapter.java
index 45212f287..ea1ff4d89 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/archivedcards/ArchivedCardsAdapter.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/archivedcards/ArchivedCardsAdapter.java
@@ -26,7 +26,7 @@ public class ArchivedCardsAdapter extends CardAdapter {
@Override
public void onBindViewHolder(@NonNull AbstractCardViewHolder viewHolder, int position) {
- viewHolder.bind(cardList.get(position), mainViewModel.getCurrentAccount(), mainViewModel.getCurrentBoardRemoteId(), false, R.menu.archived_card_menu, this, counterMaxValue, mainColor);
+ viewHolder.bind(cardList.get(position), mainViewModel.getCurrentAccount(), mainViewModel.getCurrentBoardRemoteId(), false, R.menu.archived_card_menu, this, counterMaxValue, scheme);
}
@Override
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/DeleteBoardDialogFragment.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/DeleteBoardDialogFragment.java
index b81c6471e..94e658954 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/DeleteBoardDialogFragment.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/DeleteBoardDialogFragment.java
@@ -9,7 +9,7 @@ import androidx.fragment.app.DialogFragment;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.model.Board;
-import it.niedermann.nextcloud.deck.ui.branding.DeleteAlertDialogBuilder;
+import it.niedermann.nextcloud.deck.ui.theme.DeleteAlertDialogBuilder;
public class DeleteBoardDialogFragment extends DialogFragment {
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/EditBoardDialogFragment.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/EditBoardDialogFragment.java
index 894f0d835..9e05fbd80 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/EditBoardDialogFragment.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/EditBoardDialogFragment.java
@@ -1,7 +1,5 @@
package it.niedermann.nextcloud.deck.ui.board;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.applyBrandToEditTextInputLayout;
-
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
@@ -24,6 +22,7 @@ import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.databinding.DialogTextColorInputBinding;
import it.niedermann.nextcloud.deck.model.full.FullBoard;
import it.niedermann.nextcloud.deck.ui.MainViewModel;
+import it.niedermann.nextcloud.deck.ui.theme.ThemeUtils;
public class EditBoardDialogFragment extends DialogFragment {
@@ -64,14 +63,17 @@ public class EditBoardDialogFragment extends DialogFragment {
this.editBoardListener.onUpdateBoard(fullBoard);
});
final var viewModel = new ViewModelProvider(requireActivity()).get(MainViewModel.class);
- viewModel.getFullBoardById(viewModel.getCurrentAccount().getId(), args.getLong(KEY_BOARD_ID)).observe(EditBoardDialogFragment.this, (FullBoard fb) -> {
- if (fb.board != null) {
- this.fullBoard = fb;
- String title = this.fullBoard.getBoard().getTitle();
+
+ viewModel.getFullBoardById(viewModel.getCurrentAccount().getId(), args.getLong(KEY_BOARD_ID)).observe(EditBoardDialogFragment.this, fullBoard -> {
+ if (fullBoard.board != null) {
+ this.fullBoard = fullBoard;
+ final var utils = ThemeUtils.of(fullBoard.getBoard().getColor(), requireContext());
+
+ final String title = this.fullBoard.getBoard().getTitle();
binding.input.setText(title);
binding.input.setSelection(title.length());
- applyBrandToEditTextInputLayout(fb.getBoard().getColor(), binding.inputWrapper);
- binding.colorChooser.selectColor(fullBoard.getBoard().getColor());
+ binding.colorChooser.selectColor(this.fullBoard.getBoard().getColor());
+ utils.material.colorTextInputLayout(binding.inputWrapper);
}
});
} else {
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/accesscontrol/AccessControlAdapter.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/accesscontrol/AccessControlAdapter.java
index e120c665c..c97a1e4ba 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/accesscontrol/AccessControlAdapter.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/accesscontrol/AccessControlAdapter.java
@@ -1,17 +1,12 @@
package it.niedermann.nextcloud.deck.ui.board.accesscontrol;
import android.content.Context;
-import android.content.res.ColorStateList;
-import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
-import androidx.appcompat.widget.SwitchCompat;
import androidx.core.content.ContextCompat;
-import androidx.core.graphics.drawable.DrawableCompat;
import androidx.recyclerview.widget.RecyclerView;
import java.util.LinkedList;
@@ -24,34 +19,34 @@ import it.niedermann.nextcloud.deck.databinding.ItemAccessControlOwnerBinding;
import it.niedermann.nextcloud.deck.model.AccessControl;
import it.niedermann.nextcloud.deck.model.Account;
import it.niedermann.nextcloud.deck.model.enums.DBStatus;
-import it.niedermann.nextcloud.deck.ui.branding.Branded;
+import it.niedermann.nextcloud.deck.ui.theme.ThemeUtils;
+import it.niedermann.nextcloud.deck.ui.theme.Themed;
import it.niedermann.nextcloud.deck.util.ViewUtil;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.getSecondaryForegroundColorDependingOnTheme;
-
-public class AccessControlAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements Branded {
+public class AccessControlAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements Themed {
public static final long HEADER_ITEM_LOCAL_ID = -1L;
private static final int TYPE_HEADER = 0;
private static final int TYPE_ITEM = 1;
- private int mainColor;
+ @NonNull
+ private ThemeUtils utils;
@NonNull
- private Account account;
+ private final Account account;
@NonNull
- private List<AccessControl> accessControls = new LinkedList<>();
+ private final List<AccessControl> accessControls = new LinkedList<>();
@NonNull
- private AccessControlChangedListener accessControlChangedListener;
+ private final AccessControlChangedListener accessControlChangedListener;
@NonNull
- private Context context;
+ private final Context context;
private boolean hasManagePermission = false;
AccessControlAdapter(@NonNull Account account, @NonNull AccessControlChangedListener accessControlChangedListener, @NonNull Context context) {
this.account = account;
this.accessControlChangedListener = accessControlChangedListener;
this.context = context;
- this.mainColor = ContextCompat.getColor(context, R.color.primary);
+ this.utils = ThemeUtils.of(ContextCompat.getColor(context, R.color.primary), context);
setHasStableIds(true);
}
@@ -123,10 +118,10 @@ public class AccessControlAdapter extends RecyclerView.Adapter<RecyclerView.View
});
if (hasManagePermission) {
- brandSwitch(context, acHolder.binding.permissionEdit, mainColor);
- brandSwitch(context, acHolder.binding.permissionManage, mainColor);
+ utils.androidx.colorSwitchCompat(acHolder.binding.permissionEdit);
+ utils.androidx.colorSwitchCompat(acHolder.binding.permissionManage);
}
- brandSwitch(context, acHolder.binding.permissionShare, mainColor);
+ utils.androidx.colorSwitchCompat(acHolder.binding.permissionShare);
break;
}
}
@@ -157,26 +152,8 @@ public class AccessControlAdapter extends RecyclerView.Adapter<RecyclerView.View
}
@Override
- public void applyBrand(int mainColor) {
- this.mainColor = getSecondaryForegroundColorDependingOnTheme(context, mainColor);
+ public void applyTheme(int color) {
+ this.utils = ThemeUtils.of(color, context);
notifyDataSetChanged();
}
-
- /**
- * Helper method to apply branding to a {@link SwitchCompat}
- */
- private static void brandSwitch(@NonNull Context context, @NonNull SwitchCompat switchCompat, @ColorInt int mainColor) {
- final int finalMainColor = getSecondaryForegroundColorDependingOnTheme(context, mainColor);
- DrawableCompat.setTintList(switchCompat.getThumbDrawable(), new ColorStateList(
- new int[][]{new int[]{android.R.attr.state_checked}, new int[]{}},
- new int[]{finalMainColor, ContextCompat.getColor(context, R.color.fg_secondary)}
- ));
- final int trackColor = ContextCompat.getColor(context, R.color.fg_secondary);
- final int lightTrackColor = Color.argb(77, Color.red(trackColor), Color.green(trackColor), Color.blue(trackColor));
- final int lightTrackColorChecked = Color.argb(77, Color.red(finalMainColor), Color.green(finalMainColor), Color.blue(finalMainColor));
- DrawableCompat.setTintList(switchCompat.getTrackDrawable(), new ColorStateList(
- new int[][]{new int[]{android.R.attr.state_checked}, new int[]{}},
- new int[]{lightTrackColorChecked, lightTrackColor}
- ));
- }
}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/accesscontrol/AccessControlDialogFragment.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/accesscontrol/AccessControlDialogFragment.java
index 74c0ad2a3..7aa0dc199 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/accesscontrol/AccessControlDialogFragment.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/accesscontrol/AccessControlDialogFragment.java
@@ -1,7 +1,6 @@
package it.niedermann.nextcloud.deck.ui.board.accesscontrol;
import static it.niedermann.nextcloud.deck.ui.board.accesscontrol.AccessControlAdapter.HEADER_ITEM_LOCAL_ID;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.applyBrandToEditTextInputLayout;
import android.app.Dialog;
import android.content.Context;
@@ -29,9 +28,10 @@ import it.niedermann.nextcloud.deck.model.User;
import it.niedermann.nextcloud.deck.model.full.FullBoard;
import it.niedermann.nextcloud.deck.persistence.sync.SyncManager;
import it.niedermann.nextcloud.deck.ui.MainViewModel;
-import it.niedermann.nextcloud.deck.ui.branding.BrandedSnackbar;
import it.niedermann.nextcloud.deck.ui.card.UserAutoCompleteAdapter;
import it.niedermann.nextcloud.deck.ui.exception.ExceptionDialogFragment;
+import it.niedermann.nextcloud.deck.ui.theme.ThemeUtils;
+import it.niedermann.nextcloud.deck.ui.theme.ThemedSnackbar;
public class AccessControlDialogFragment extends DialogFragment implements AccessControlChangedListener, OnItemClickListener {
@@ -84,7 +84,7 @@ public class AccessControlDialogFragment extends DialogFragment implements Acces
binding.people.setAdapter(userAutoCompleteAdapter);
binding.people.setOnItemClickListener(this);
});
- applyBrand(fullBoard.getBoard().getColor());
+ applyTheme(fullBoard.getBoard().getColor());
} else {
// Happens when someone revokes his own access → board gets deleted locally → LiveData fires, but no board
// see https://github.com/stefan-niedermann/nextcloud-deck/issues/410
@@ -132,7 +132,7 @@ public class AccessControlDialogFragment extends DialogFragment implements Acces
public void onError(Throwable throwable) {
if (!SyncManager.ignoreExceptionOnVoidError(throwable)) {
IResponseCallback.super.onError(throwable);
- requireActivity().runOnUiThread(() -> BrandedSnackbar.make(requireView(), getString(R.string.error_revoking_ac, ac.getUser().getDisplayname()), Snackbar.LENGTH_LONG)
+ requireActivity().runOnUiThread(() -> ThemedSnackbar.make(requireView(), getString(R.string.error_revoking_ac, ac.getUser().getDisplayname()), Snackbar.LENGTH_LONG)
.setAction(R.string.simple_more, v -> ExceptionDialogFragment.newInstance(throwable, viewModel.getCurrentAccount()).show(getChildFragmentManager(), ExceptionDialogFragment.class.getSimpleName()))
.show());
}
@@ -166,9 +166,12 @@ public class AccessControlDialogFragment extends DialogFragment implements Acces
userAutoCompleteAdapter.exclude(user);
}
- public void applyBrand(@ColorInt int mainColor) {
- applyBrandToEditTextInputLayout(mainColor, binding.peopleWrapper);
- this.adapter.applyBrand(mainColor);
+ public void applyTheme(@ColorInt int color) {
+ final var utils = ThemeUtils.of(color, requireContext());
+
+ utils.material.colorTextInputLayout(binding.peopleWrapper);
+
+ this.adapter.applyTheme(color);
}
public static DialogFragment newInstance(long boardLocalId) {
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/managelabels/EditLabelDialogFragment.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/managelabels/EditLabelDialogFragment.java
index 1b8c1e0b1..4eef71eb8 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/managelabels/EditLabelDialogFragment.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/managelabels/EditLabelDialogFragment.java
@@ -1,7 +1,5 @@
package it.niedermann.nextcloud.deck.ui.board.managelabels;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.applyBrandToEditTextInputLayout;
-
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
@@ -14,9 +12,10 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.databinding.DialogTextColorInputBinding;
import it.niedermann.nextcloud.deck.model.Label;
-import it.niedermann.nextcloud.deck.ui.branding.BrandedDialogFragment;
+import it.niedermann.nextcloud.deck.ui.theme.ThemeUtils;
+import it.niedermann.nextcloud.deck.ui.theme.ThemedDialogFragment;
-public class EditLabelDialogFragment extends BrandedDialogFragment {
+public class EditLabelDialogFragment extends ThemedDialogFragment {
private DialogTextColorInputBinding binding;
@@ -90,7 +89,9 @@ public class EditLabelDialogFragment extends BrandedDialogFragment {
}
@Override
- public void applyBrand(int mainColor) {
- applyBrandToEditTextInputLayout(mainColor, binding.inputWrapper);
+ public void applyTheme(int color) {
+ final var utils = ThemeUtils.of(color, requireContext());
+
+ utils.material.colorTextInputLayout(binding.inputWrapper);
}
} \ No newline at end of file
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/managelabels/ManageLabelsAdapter.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/managelabels/ManageLabelsAdapter.java
index d6b097d89..ca5126250 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/managelabels/ManageLabelsAdapter.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/managelabels/ManageLabelsAdapter.java
@@ -5,35 +5,24 @@ import android.view.LayoutInflater;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
-import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView;
import java.util.LinkedList;
import java.util.List;
import java.util.NoSuchElementException;
-import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.databinding.ItemManageLabelBinding;
import it.niedermann.nextcloud.deck.model.Label;
-import it.niedermann.nextcloud.deck.ui.branding.Branded;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.getSecondaryForegroundColorDependingOnTheme;
-
-public class ManageLabelsAdapter extends RecyclerView.Adapter<ManageLabelsViewHolder> implements Branded {
-
- private int mainColor;
+public class ManageLabelsAdapter extends RecyclerView.Adapter<ManageLabelsViewHolder> {
@NonNull
- private ManageLabelListener listener;
+ private final ManageLabelListener listener;
@NonNull
- private List<Label> labels = new LinkedList<>();
- @NonNull
- private Context context;
+ private final List<Label> labels = new LinkedList<>();
ManageLabelsAdapter(@NonNull ManageLabelListener listener, @NonNull Context context) {
this.listener = listener;
- this.context = context;
- this.mainColor = ContextCompat.getColor(context, R.color.primary);
setHasStableIds(true);
}
@@ -73,10 +62,4 @@ public class ManageLabelsAdapter extends RecyclerView.Adapter<ManageLabelsViewHo
this.labels.addAll(labels);
notifyDataSetChanged();
}
-
- @Override
- public void applyBrand(int mainColor) {
- this.mainColor = getSecondaryForegroundColorDependingOnTheme(context, mainColor);
- notifyDataSetChanged();
- }
}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/managelabels/ManageLabelsDialogFragment.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/managelabels/ManageLabelsDialogFragment.java
index 53cbe09b9..ca3547ae7 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/managelabels/ManageLabelsDialogFragment.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/board/managelabels/ManageLabelsDialogFragment.java
@@ -1,8 +1,5 @@
package it.niedermann.nextcloud.deck.ui.board.managelabels;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.applyBrandToEditTextInputLayout;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.applyBrandToFAB;
-
import android.app.Dialog;
import android.content.Context;
import android.database.sqlite.SQLiteConstraintException;
@@ -27,10 +24,11 @@ import it.niedermann.nextcloud.deck.databinding.DialogBoardManageLabelsBinding;
import it.niedermann.nextcloud.deck.model.Label;
import it.niedermann.nextcloud.deck.persistence.sync.SyncManager;
import it.niedermann.nextcloud.deck.ui.MainViewModel;
-import it.niedermann.nextcloud.deck.ui.branding.BrandedDialogFragment;
-import it.niedermann.nextcloud.deck.ui.branding.DeleteAlertDialogBuilder;
+import it.niedermann.nextcloud.deck.ui.theme.DeleteAlertDialogBuilder;
+import it.niedermann.nextcloud.deck.ui.theme.ThemeUtils;
+import it.niedermann.nextcloud.deck.ui.theme.ThemedDialogFragment;
-public class ManageLabelsDialogFragment extends BrandedDialogFragment implements ManageLabelListener, EditLabelListener {
+public class ManageLabelsDialogFragment extends ThemedDialogFragment implements ManageLabelListener, EditLabelListener {
private MainViewModel viewModel;
private DialogBoardManageLabelsBinding binding;
@@ -119,9 +117,11 @@ public class ManageLabelsDialogFragment extends BrandedDialogFragment implements
}
@Override
- public void applyBrand(int mainColor) {
- applyBrandToFAB(mainColor, binding.fab);
- applyBrandToEditTextInputLayout(mainColor, binding.addLabelTitleWrapper);
+ public void applyTheme(int color) {
+ final var utils = ThemeUtils.of(color, requireContext());
+
+ utils.material.themeFAB(binding.fab);
+ utils.material.colorTextInputLayout(binding.addLabelTitleWrapper);
}
public static DialogFragment newInstance(long boardLocalId) {
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/Branded.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/Branded.java
deleted file mode 100644
index 99ad9c074..000000000
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/Branded.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package it.niedermann.nextcloud.deck.ui.branding;
-
-import androidx.annotation.ColorInt;
-import androidx.annotation.UiThread;
-
-public interface Branded {
- @UiThread
- void applyBrand(@ColorInt int mainColor);
-} \ No newline at end of file
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedDialogFragment.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedDialogFragment.java
deleted file mode 100644
index 4b35351b4..000000000
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedDialogFragment.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package it.niedermann.nextcloud.deck.ui.branding;
-
-import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.readBrandMainColor;
-
-import androidx.annotation.Nullable;
-import androidx.fragment.app.DialogFragment;
-
-public abstract class BrandedDialogFragment extends DialogFragment implements Branded {
-
- @Override
- public void onStart() {
- super.onStart();
-
- @Nullable final var context = getContext();
- if (context != null) {
- applyBrand(readBrandMainColor(context));
- }
- }
-}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedPreferenceCategory.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedPreferenceCategory.java
deleted file mode 100644
index eeac7579b..000000000
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedPreferenceCategory.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package it.niedermann.nextcloud.deck.ui.branding;
-
-import static it.niedermann.nextcloud.deck.DeckApplication.readCurrentAccountColor;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.getSecondaryForegroundColorDependingOnTheme;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.widget.TextView;
-
-import androidx.annotation.ColorInt;
-import androidx.annotation.Nullable;
-import androidx.preference.PreferenceCategory;
-import androidx.preference.PreferenceViewHolder;
-
-public class BrandedPreferenceCategory extends PreferenceCategory {
-
- @Override
- public void onBindViewHolder(PreferenceViewHolder holder) {
- super.onBindViewHolder(holder);
-
- final var view = holder.itemView.findViewById(android.R.id.title);
- @Nullable final Context context = getContext();
- if (context != null && view instanceof TextView) {
- @ColorInt final int mainColor = getSecondaryForegroundColorDependingOnTheme(context, readCurrentAccountColor(context));
- ((TextView) view).setTextColor(mainColor);
- }
- }
-
- public BrandedPreferenceCategory(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- }
-
- public BrandedPreferenceCategory(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- }
-
- public BrandedPreferenceCategory(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public BrandedPreferenceCategory(Context context) {
- super(context);
- }
-}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedSnackbar.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedSnackbar.java
deleted file mode 100644
index adc4ea65f..000000000
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedSnackbar.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package it.niedermann.nextcloud.deck.ui.branding;
-
-import static it.niedermann.nextcloud.deck.DeckApplication.isDarkTheme;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.getAttribute;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.readBrandMainColor;
-import static it.niedermann.nextcloud.deck.util.DeckColorUtil.contrastRatioIsSufficient;
-
-import android.graphics.Color;
-import android.view.View;
-
-import androidx.annotation.ColorInt;
-import androidx.annotation.NonNull;
-import androidx.annotation.StringRes;
-
-import com.google.android.material.snackbar.BaseTransientBottomBar;
-import com.google.android.material.snackbar.Snackbar;
-
-import it.niedermann.nextcloud.deck.R;
-
-public class BrandedSnackbar {
-
- @NonNull
- public static Snackbar make(@NonNull View view, @NonNull CharSequence text, @BaseTransientBottomBar.Duration int duration) {
- final var snackbar = Snackbar.make(view, text, duration);
-
- @ColorInt final int backgroundColor = getAttribute(view.getContext(), R.attr.colorSurfaceInverse);
- @ColorInt final int color = readBrandMainColor(view.getContext());
-
- if (contrastRatioIsSufficient(backgroundColor, color)) {
- snackbar.setActionTextColor(color);
- } else {
- if (isDarkTheme(view.getContext())) {
- snackbar.setActionTextColor(Color.BLACK);
- } else {
- snackbar.setActionTextColor(Color.WHITE);
- }
- }
-
- return snackbar;
- }
-
- @NonNull
- public static Snackbar make(@NonNull View view, @StringRes int resId, @BaseTransientBottomBar.Duration int duration) {
- return make(view, view.getResources().getText(resId), duration);
- }
-} \ No newline at end of file
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedSwitchPreference.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedSwitchPreference.java
deleted file mode 100644
index 3c1558df5..000000000
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedSwitchPreference.java
+++ /dev/null
@@ -1,104 +0,0 @@
-package it.niedermann.nextcloud.deck.ui.branding;
-
-import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.getSecondaryForegroundColorDependingOnTheme;
-
-import android.content.Context;
-import android.content.res.ColorStateList;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Switch;
-
-import androidx.annotation.ColorInt;
-import androidx.annotation.Nullable;
-import androidx.core.graphics.drawable.DrawableCompat;
-import androidx.preference.PreferenceViewHolder;
-import androidx.preference.SwitchPreference;
-
-import it.niedermann.nextcloud.deck.R;
-
-public class BrandedSwitchPreference extends SwitchPreference implements Branded {
-
- @ColorInt
- private Integer mainColor = null;
-
- @Nullable
- private Switch switchView;
-
- public BrandedSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- }
-
- public BrandedSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- }
-
- public BrandedSwitchPreference(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public BrandedSwitchPreference(Context context) {
- super(context);
- }
-
- @Override
- public void onBindViewHolder(PreferenceViewHolder holder) {
- super.onBindViewHolder(holder);
-
- if (holder.itemView instanceof ViewGroup) {
- switchView = findSwitchWidget(holder.itemView);
- if (mainColor != null) {
- applyBrand();
- }
- }
- }
-
- @Override
- public void applyBrand(@ColorInt int mainColor) {
- this.mainColor = mainColor;
- // onBindViewHolder is called after applyBrand, therefore we have to store the given values and apply them later.
- applyBrand();
- }
-
- private void applyBrand() {
- if (switchView != null) {
- final int finalMainColor = getSecondaryForegroundColorDependingOnTheme(getContext(), mainColor);
- // int trackColor = Color.argb(77, Color.red(finalMainColor), Color.green(finalMainColor), Color.blue(finalMainColor));
- DrawableCompat.setTintList(switchView.getThumbDrawable(), new ColorStateList(
- new int[][]{new int[]{android.R.attr.state_checked}, new int[]{}},
- new int[]{finalMainColor, getContext().getResources().getColor(R.color.fg_secondary)}
- ));
- DrawableCompat.setTintList(switchView.getTrackDrawable(), new ColorStateList(
- new int[][]{new int[]{android.R.attr.state_checked}, new int[]{}},
- new int[]{finalMainColor, getContext().getResources().getColor(R.color.fg_secondary)}
- ));
- }
- }
-
- /**
- * Recursively go through view tree until we find an android.widget.Switch
- *
- * @param view Root view to start searching
- * @return A Switch class or null
- * @see <a href="https://gist.github.com/marchold/45e22839eb94aa14dfb5">Source</a>
- */
- private Switch findSwitchWidget(View view) {
- if (view instanceof Switch) {
- return (Switch) view;
- }
- if (view instanceof ViewGroup) {
- ViewGroup viewGroup = (ViewGroup) view;
- for (int i = 0; i < viewGroup.getChildCount(); i++) {
- final var child = viewGroup.getChildAt(i);
- if (child instanceof ViewGroup) {
- final var result = findSwitchWidget(child);
- if (result != null) return result;
- }
- if (child instanceof Switch) {
- return (Switch) child;
- }
- }
- }
- return null;
- }
-}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandingUtil.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandingUtil.java
deleted file mode 100644
index ee6a9ccdc..000000000
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandingUtil.java
+++ /dev/null
@@ -1,119 +0,0 @@
-package it.niedermann.nextcloud.deck.ui.branding;
-
-import static it.niedermann.nextcloud.deck.DeckApplication.isDarkTheme;
-import static it.niedermann.nextcloud.deck.util.DeckColorUtil.contrastRatioIsSufficient;
-import static it.niedermann.nextcloud.deck.util.DeckColorUtil.contrastRatioIsSufficientBigAreas;
-
-import android.content.Context;
-import android.content.res.ColorStateList;
-import android.graphics.Color;
-import android.util.TypedValue;
-import android.view.MenuItem;
-
-import androidx.annotation.AttrRes;
-import androidx.annotation.ColorInt;
-import androidx.annotation.NonNull;
-import androidx.core.content.ContextCompat;
-import androidx.core.graphics.drawable.DrawableCompat;
-import androidx.preference.PreferenceManager;
-
-import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;
-import com.google.android.material.floatingactionbutton.FloatingActionButton;
-import com.google.android.material.tabs.TabLayout;
-import com.google.android.material.textfield.TextInputLayout;
-
-import it.niedermann.android.util.ColorUtil;
-import it.niedermann.nextcloud.deck.DeckLog;
-import it.niedermann.nextcloud.deck.R;
-
-public abstract class BrandingUtil {
-
- private BrandingUtil() {
- throw new UnsupportedOperationException("This class must not get instantiated");
- }
-
- @ColorInt
- public static int readBrandMainColor(@NonNull Context context) {
- final var sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext());
- DeckLog.log("--- Read:", context.getString(R.string.shared_preference_theme_main));
- return sharedPreferences.getInt(context.getString(R.string.shared_preference_theme_main), context.getApplicationContext().getResources().getColor(R.color.defaultBrand));
- }
-
- public static void saveBrandColors(@NonNull Context context, @ColorInt int mainColor) {
- final var editor = PreferenceManager.getDefaultSharedPreferences(context).edit();
- DeckLog.log("--- Write:", context.getString(R.string.shared_preference_theme_main), "|", mainColor);
- editor.putInt(context.getString(R.string.shared_preference_theme_main), mainColor);
- editor.apply();
- }
-
- public static void clearBrandColors(@NonNull Context context) {
- final var editor = PreferenceManager.getDefaultSharedPreferences(context).edit();
- DeckLog.log("--- Remove:", context.getString(R.string.shared_preference_theme_main));
- editor.remove(context.getString(R.string.shared_preference_theme_main));
- editor.apply();
- }
-
- /**
- * Since we may collide with dark theme in this area, we have to make sure that the color is visible depending on the background
- */
- @ColorInt
- public static int getSecondaryForegroundColorDependingOnTheme(@NonNull Context context, @ColorInt int mainColor) {
- if (contrastRatioIsSufficient(mainColor, ContextCompat.getColor(context, R.color.primary))) {
- return mainColor;
- }
- DeckLog.verbose("Contrast ratio between brand color", String.format("#%06X", (0xFFFFFF & mainColor)), "and primary theme background is too low. Falling back to WHITE/BLACK as brand color.");
- return isDarkTheme(context) ? Color.WHITE : Color.BLACK;
- }
-
- public static void applyBrandToFAB(@ColorInt int mainColor, @NonNull FloatingActionButton fab) {
- final boolean contrastRatioIsSufficient = contrastRatioIsSufficientBigAreas(mainColor, ContextCompat.getColor(fab.getContext(), R.color.primary));
- fab.setSupportBackgroundTintList(ColorStateList.valueOf(contrastRatioIsSufficient
- ? mainColor
- : ContextCompat.getColor(fab.getContext(), R.color.accent)));
- fab.setColorFilter(contrastRatioIsSufficient ? ColorUtil.INSTANCE.getForegroundColorForBackgroundColor(mainColor) : mainColor);
- }
-
- public static void applyBrandToExtendedFAB(@ColorInt int mainColor, @NonNull ExtendedFloatingActionButton extendedFab) {
- final boolean contrastRatioIsSufficient = contrastRatioIsSufficientBigAreas(mainColor, ContextCompat.getColor(extendedFab.getContext(), R.color.primary));
- @ColorInt final int color = contrastRatioIsSufficient
- ? mainColor
- : ContextCompat.getColor(extendedFab.getContext(), R.color.accent);
- extendedFab.setTextColor(ColorUtil.INSTANCE.getForegroundColorForBackgroundColor(color));
- extendedFab.setIconTint(ColorStateList.valueOf(ColorUtil.INSTANCE.getForegroundColorForBackgroundColor(color)));
- extendedFab.setBackgroundTintList(ColorStateList.valueOf(color));
- }
-
- public static void applyBrandToPrimaryTabLayout(@ColorInt int mainColor, @NonNull TabLayout tabLayout) {
- @ColorInt final int finalMainColor = getSecondaryForegroundColorDependingOnTheme(tabLayout.getContext(), mainColor);
- tabLayout.setBackgroundColor(ContextCompat.getColor(tabLayout.getContext(), R.color.primary));
- final boolean contrastRatioIsSufficient = ColorUtil.INSTANCE.getContrastRatio(mainColor, ContextCompat.getColor(tabLayout.getContext(), R.color.primary)) > 1.7d;
- tabLayout.setSelectedTabIndicatorColor(contrastRatioIsSufficient ? mainColor : finalMainColor);
- }
-
- public static void applyBrandToEditTextInputLayout(@ColorInt int color, @NonNull TextInputLayout til) {
- final int colorPrimary = ContextCompat.getColor(til.getContext(), R.color.primary);
- final int colorAccent = ContextCompat.getColor(til.getContext(), R.color.accent);
- final var colorDanger = ColorStateList.valueOf(ContextCompat.getColor(til.getContext(), R.color.danger));
- til.setBoxStrokeColor(contrastRatioIsSufficientBigAreas(color, colorPrimary) ? color : colorAccent);
- til.setHintTextColor(ColorStateList.valueOf(contrastRatioIsSufficient(color, colorPrimary) ? color : colorAccent));
- til.setErrorTextColor(colorDanger);
- til.setBoxStrokeErrorColor(colorDanger);
- til.setErrorIconTintList(colorDanger);
- }
-
- public static void tintMenuIcon(@NonNull MenuItem menuItem, @ColorInt int color) {
- var drawable = menuItem.getIcon();
- if (drawable != null) {
- drawable = DrawableCompat.wrap(drawable);
- DrawableCompat.setTint(drawable, color);
- menuItem.setIcon(drawable);
- }
- }
-
- @ColorInt
- public static int getAttribute(@NonNull Context context, @AttrRes int id) {
- final var typedValue = new TypedValue();
- context.getTheme().resolveAttribute(id, typedValue, true);
- return typedValue.data;
- }
-}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/AbstractCardViewHolder.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/AbstractCardViewHolder.java
index eb25d1270..6a54d16c6 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/AbstractCardViewHolder.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/AbstractCardViewHolder.java
@@ -9,7 +9,6 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.CallSuper;
-import androidx.annotation.ColorInt;
import androidx.annotation.MenuRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -36,6 +35,7 @@ import it.niedermann.nextcloud.deck.util.AttachmentUtil;
import it.niedermann.nextcloud.deck.util.DateUtil;
import it.niedermann.nextcloud.deck.util.MimeTypeUtil;
import it.niedermann.nextcloud.deck.util.ViewUtil;
+import scheme.Scheme;
public abstract class AbstractCardViewHolder extends RecyclerView.ViewHolder {
@@ -47,7 +47,7 @@ public abstract class AbstractCardViewHolder extends RecyclerView.ViewHolder {
* Removes all {@link OnClickListener} and {@link OnLongClickListener}
*/
@CallSuper
- public void bind(@NonNull FullCard fullCard, @NonNull Account account, @Nullable Long boardRemoteId, boolean hasEditPermission, @MenuRes int optionsMenu, @NonNull CardOptionsItemSelectedListener optionsItemsSelectedListener, @NonNull String counterMaxValue, @ColorInt int mainColor) {
+ public void bind(@NonNull FullCard fullCard, @NonNull Account account, @Nullable Long boardRemoteId, boolean hasEditPermission, @MenuRes int optionsMenu, @NonNull CardOptionsItemSelectedListener optionsItemsSelectedListener, @NonNull String counterMaxValue, @NonNull Scheme scheme) {
final var context = itemView.getContext();
bindCardClickListener(null);
@@ -56,7 +56,10 @@ public abstract class AbstractCardViewHolder extends RecyclerView.ViewHolder {
getCardMenu().setVisibility(hasEditPermission ? View.VISIBLE : View.GONE);
getCardTitle().setText(fullCard.getCard().getTitle().trim());
- DrawableCompat.setTint(getNotSyncedYet().getDrawable(), mainColor);
+ DrawableCompat.setTint(getNotSyncedYet().getDrawable(), scheme.getOnPrimaryContainer());
+ // TODO should be discussed with UX
+ // utils.material.themeCardView(getCard());
+
getNotSyncedYet().setVisibility(DBStatus.LOCAL_EDITED.equals(fullCard.getStatusEnum()) ? View.VISIBLE : View.GONE);
if (fullCard.getCard().getDueDate() != null) {
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/CardAdapter.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/CardAdapter.java
index 1c0567793..1d003ec78 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/CardAdapter.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/CardAdapter.java
@@ -1,7 +1,6 @@
package it.niedermann.nextcloud.deck.ui.card;
import static androidx.preference.PreferenceManager.getDefaultSharedPreferences;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.getSecondaryForegroundColorDependingOnTheme;
import static it.niedermann.nextcloud.deck.util.MimeTypeUtil.TEXT_PLAIN;
import android.app.Activity;
@@ -12,7 +11,6 @@ import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
-import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
@@ -39,12 +37,14 @@ import it.niedermann.nextcloud.deck.model.Stack;
import it.niedermann.nextcloud.deck.model.full.FullCard;
import it.niedermann.nextcloud.deck.persistence.sync.SyncManager;
import it.niedermann.nextcloud.deck.ui.MainViewModel;
-import it.niedermann.nextcloud.deck.ui.branding.Branded;
import it.niedermann.nextcloud.deck.ui.exception.ExceptionDialogFragment;
import it.niedermann.nextcloud.deck.ui.movecard.MoveCardDialogFragment;
+import it.niedermann.nextcloud.deck.ui.theme.ThemeUtils;
+import it.niedermann.nextcloud.deck.ui.theme.Themed;
import it.niedermann.nextcloud.deck.util.CardUtil;
+import scheme.Scheme;
-public class CardAdapter extends RecyclerView.Adapter<AbstractCardViewHolder> implements DragAndDropAdapter<FullCard>, CardOptionsItemSelectedListener, Branded {
+public class CardAdapter extends RecyclerView.Adapter<AbstractCardViewHolder> implements DragAndDropAdapter<FullCard>, CardOptionsItemSelectedListener, Themed {
private final ExecutorService executor;
private final boolean compactMode;
@@ -61,8 +61,8 @@ public class CardAdapter extends RecyclerView.Adapter<AbstractCardViewHolder> im
protected List<FullCard> cardList = new ArrayList<>();
@NonNull
protected String counterMaxValue;
- @ColorInt
- protected int mainColor;
+ @NonNull
+ protected Scheme scheme;
@StringRes
private final int shareLinkRes;
protected final int maxCoverImages;
@@ -79,7 +79,7 @@ public class CardAdapter extends RecyclerView.Adapter<AbstractCardViewHolder> im
this.stackId = stackId;
this.mainViewModel = mainViewModel;
this.selectCardListener = selectCardListener;
- this.mainColor = ContextCompat.getColor(this.activity, R.color.defaultBrand);
+ this.scheme = ThemeUtils.createScheme(ContextCompat.getColor(this.activity, R.color.defaultBrand), this.activity);
this.compactMode = getDefaultSharedPreferences(this.activity).getBoolean(this.activity.getString(R.string.pref_key_compact), false);
this.maxCoverImages = PreferenceManager.getDefaultSharedPreferences(activity).getBoolean(activity.getString(R.string.pref_key_cover_images), true)
? activity.getResources().getInteger(R.integer.max_cover_images)
@@ -124,7 +124,7 @@ public class CardAdapter extends RecyclerView.Adapter<AbstractCardViewHolder> im
@Override
public void onBindViewHolder(@NonNull AbstractCardViewHolder viewHolder, int position) {
@NonNull final var fullCard = cardList.get(position);
- viewHolder.bind(fullCard, mainViewModel.getCurrentAccount(), mainViewModel.getCurrentBoardRemoteId(), mainViewModel.currentBoardHasEditPermission(), R.menu.card_menu, this, counterMaxValue, mainColor);
+ viewHolder.bind(fullCard, mainViewModel.getCurrentAccount(), mainViewModel.getCurrentBoardRemoteId(), mainViewModel.currentBoardHasEditPermission(), R.menu.card_menu, this, counterMaxValue, scheme);
// Only enable details view if there is no one waiting for selecting a card.
viewHolder.bindCardClickListener((v) -> {
@@ -184,8 +184,8 @@ public class CardAdapter extends RecyclerView.Adapter<AbstractCardViewHolder> im
}
@Override
- public void applyBrand(int mainColor) {
- this.mainColor = getSecondaryForegroundColorDependingOnTheme(activity, mainColor);
+ public void applyTheme(int color) {
+ this.scheme = ThemeUtils.createScheme(color, activity);
notifyDataSetChanged();
}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/CompactCardViewHolder.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/CompactCardViewHolder.java
index f019551fe..fd93035de 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/CompactCardViewHolder.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/CompactCardViewHolder.java
@@ -6,7 +6,6 @@ import android.view.View.OnLongClickListener;
import android.widget.ImageView;
import android.widget.TextView;
-import androidx.annotation.ColorInt;
import androidx.annotation.MenuRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -19,6 +18,7 @@ import it.niedermann.nextcloud.deck.databinding.ItemCardCompactBinding;
import it.niedermann.nextcloud.deck.model.Account;
import it.niedermann.nextcloud.deck.model.Label;
import it.niedermann.nextcloud.deck.model.full.FullCard;
+import scheme.Scheme;
public class CompactCardViewHolder extends AbstractCardViewHolder {
private final ItemCardCompactBinding binding;
@@ -35,8 +35,8 @@ public class CompactCardViewHolder extends AbstractCardViewHolder {
* Removes all {@link OnClickListener} and {@link OnLongClickListener}
*/
@Override
- public void bind(@NonNull FullCard fullCard, @NonNull Account account, @Nullable Long boardRemoteId, boolean hasEditPermission, @MenuRes int optionsMenu, @NonNull CardOptionsItemSelectedListener optionsItemsSelectedListener, @NonNull String counterMaxValue, @ColorInt int mainColor) {
- super.bind(fullCard, account, boardRemoteId, hasEditPermission, optionsMenu, optionsItemsSelectedListener, counterMaxValue, mainColor);
+ public void bind(@NonNull FullCard fullCard, @NonNull Account account, @Nullable Long boardRemoteId, boolean hasEditPermission, @MenuRes int optionsMenu, @NonNull CardOptionsItemSelectedListener optionsItemsSelectedListener, @NonNull String counterMaxValue, @NonNull Scheme scheme) {
+ super.bind(fullCard, account, boardRemoteId, hasEditPermission, optionsMenu, optionsItemsSelectedListener, counterMaxValue, scheme);
setupCoverImages(account, binding.coverImages, fullCard, Math.min(maxCoverImagesCount, 1));
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/DefaultCardViewHolder.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/DefaultCardViewHolder.java
index b7e6f911b..2641bf3ad 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/DefaultCardViewHolder.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/DefaultCardViewHolder.java
@@ -7,7 +7,6 @@ import android.view.View.OnLongClickListener;
import android.widget.ImageView;
import android.widget.TextView;
-import androidx.annotation.ColorInt;
import androidx.annotation.MenuRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -19,6 +18,7 @@ import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.databinding.ItemCardDefaultBinding;
import it.niedermann.nextcloud.deck.model.Account;
import it.niedermann.nextcloud.deck.model.full.FullCard;
+import scheme.Scheme;
public class DefaultCardViewHolder extends AbstractCardViewHolder {
private final ItemCardDefaultBinding binding;
@@ -35,8 +35,8 @@ public class DefaultCardViewHolder extends AbstractCardViewHolder {
* Removes all {@link OnClickListener} and {@link OnLongClickListener}
*/
@Override
- public void bind(@NonNull FullCard fullCard, @NonNull Account account, @Nullable Long boardRemoteId, boolean hasEditPermission, @MenuRes int optionsMenu, @NonNull CardOptionsItemSelectedListener optionsItemsSelectedListener, @NonNull String counterMaxValue, @ColorInt int mainColor) {
- super.bind(fullCard, account, boardRemoteId, hasEditPermission, optionsMenu, optionsItemsSelectedListener, counterMaxValue, mainColor);
+ public void bind(@NonNull FullCard fullCard, @NonNull Account account, @Nullable Long boardRemoteId, boolean hasEditPermission, @MenuRes int optionsMenu, @NonNull CardOptionsItemSelectedListener optionsItemsSelectedListener, @NonNull String counterMaxValue, @NonNull Scheme scheme) {
+ super.bind(fullCard, account, boardRemoteId, hasEditPermission, optionsMenu, optionsItemsSelectedListener, counterMaxValue, scheme);
final var context = itemView.getContext();
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/EditActivity.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/EditActivity.java
index 9fa8c3200..895da6bd1 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/EditActivity.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/EditActivity.java
@@ -1,8 +1,6 @@
package it.niedermann.nextcloud.deck.ui.card;
import static it.niedermann.nextcloud.deck.persistence.sync.adapters.db.util.LiveDataHelper.observeOnce;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.applyBrandToPrimaryTabLayout;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.tintMenuIcon;
import android.content.Context;
import android.content.Intent;
@@ -32,6 +30,7 @@ import it.niedermann.nextcloud.deck.model.full.FullCard;
import it.niedermann.nextcloud.deck.model.ocs.Version;
import it.niedermann.nextcloud.deck.ui.MainActivity;
import it.niedermann.nextcloud.deck.ui.exception.ExceptionHandler;
+import it.niedermann.nextcloud.deck.ui.theme.ThemeUtils;
import it.niedermann.nextcloud.deck.util.CardUtil;
public class EditActivity extends AppCompatActivity {
@@ -86,7 +85,7 @@ public class EditActivity extends AppCompatActivity {
setContentView(binding.getRoot());
setSupportActionBar(binding.toolbar);
- viewModel.getBrandingColor().observe(this, this::applyBoardBranding);
+ viewModel.getBoardColor().observe(this, this::applyTheme);
loadDataFromIntent();
}
@@ -94,7 +93,7 @@ public class EditActivity extends AppCompatActivity {
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
- viewModel.setBrandingColor(ContextCompat.getColor(this, R.color.primary));
+ viewModel.setBoardColor(ContextCompat.getColor(this, R.color.primary));
setIntent(intent);
loadDataFromIntent();
}
@@ -129,7 +128,7 @@ public class EditActivity extends AppCompatActivity {
}
observeOnce(viewModel.getFullBoardById(account.getId(), boardLocalId), EditActivity.this, (fullBoard -> {
- viewModel.setBrandingColor(fullBoard.getBoard().getColor());
+ viewModel.setBoardColor(fullBoard.getBoard().getColor());
viewModel.setCanEdit(fullBoard.getBoard().isPermissionEdit());
invalidateOptionsMenu();
observeOnce(viewModel.getFullCardWithProjectsByLocalId(account.getId(), cardLocalId), EditActivity.this, (fullCard) -> {
@@ -155,9 +154,11 @@ public class EditActivity extends AppCompatActivity {
public boolean onCreateOptionsMenu(@NonNull Menu menu) {
if (viewModel.canEdit()) {
getMenuInflater().inflate(R.menu.card_edit_menu, menu);
- @ColorInt final int colorAccent = ContextCompat.getColor(this, R.color.accent);
+ @ColorInt final int color = ContextCompat.getColor(this, R.color.accent);
+ final var utils = ThemeUtils.of(color, this);
+
for (int i = 0; i < menu.size(); i++) {
- tintMenuIcon(menu.getItem(i), colorAccent);
+ utils.platform.colorToolbarMenuIcon(this, menu.getItem(i));
}
} else {
menu.clear();
@@ -175,7 +176,7 @@ public class EditActivity extends AppCompatActivity {
@Override
public boolean onSupportNavigateUp() {
- if(isTaskRoot()) {
+ if (isTaskRoot()) {
Intent intent = new Intent(EditActivity.this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
@@ -281,14 +282,18 @@ public class EditActivity extends AppCompatActivity {
super.finish();
}
- private void applyBoardBranding(int mainColor) {
+ private void applyTheme(int color) {
final var navigationIcon = binding.toolbar.getNavigationIcon();
if (navigationIcon == null) {
DeckLog.error("Expected navigationIcon to be present.");
} else {
DrawableCompat.setTint(binding.toolbar.getNavigationIcon(), ContextCompat.getColor(this, R.color.accent));
}
- applyBrandToPrimaryTabLayout(mainColor, binding.tabLayout);
+
+ final var utils = ThemeUtils.of(color, this);
+
+ utils.platform.colorEditText(binding.title);
+ utils.deck.themeTabLayout(binding.tabLayout);
}
@NonNull
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/EditCardViewModel.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/EditCardViewModel.java
index e97973ee0..f4c652f96 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/EditCardViewModel.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/EditCardViewModel.java
@@ -45,14 +45,14 @@ public class EditCardViewModel extends AndroidViewModel {
private boolean hasCommentsAbility = false;
private boolean pendingSaveOperation = false;
private boolean canEdit = false;
- private final MutableLiveData<Integer> brandingColor$ = new MutableLiveData<>();
+ private final MutableLiveData<Integer> boardColor$ = new MutableLiveData<>();
private final SharedPreferences sharedPreferences;
private final MutableLiveData<Boolean> descriptionIsPreview = new MutableLiveData<>(false);
public EditCardViewModel(@NonNull Application application) {
super(application);
this.syncManager = new SyncManager(application);
- this.brandingColor$.setValue(ContextCompat.getColor(application, R.color.primary));
+ this.boardColor$.setValue(ContextCompat.getColor(application, R.color.primary));
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(application);
}
@@ -87,12 +87,12 @@ public class EditCardViewModel extends AndroidViewModel {
.apply();
}
- public LiveData<Integer> getBrandingColor() {
- return distinctUntilChanged(this.brandingColor$);
+ public LiveData<Integer> getBoardColor() {
+ return distinctUntilChanged(this.boardColor$);
}
- public void setBrandingColor(@ColorInt int brandingColor) {
- this.brandingColor$.setValue(brandingColor);
+ public void setBoardColor(@ColorInt int color) {
+ this.boardColor$.setValue(color);
}
/**
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/NewCardDialog.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/NewCardDialog.java
index 2801c0d7a..fd6231029 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/NewCardDialog.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/NewCardDialog.java
@@ -5,7 +5,6 @@ import static androidx.lifecycle.Transformations.distinctUntilChanged;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
-import android.content.res.ColorStateList;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
@@ -31,9 +30,9 @@ import it.niedermann.nextcloud.deck.databinding.DialogNewCardBinding;
import it.niedermann.nextcloud.deck.exceptions.OfflineException;
import it.niedermann.nextcloud.deck.model.Account;
import it.niedermann.nextcloud.deck.model.full.FullCard;
-import it.niedermann.nextcloud.deck.ui.branding.BrandingUtil;
import it.niedermann.nextcloud.deck.ui.exception.ExceptionDialogFragment;
import it.niedermann.nextcloud.deck.ui.preparecreate.PrepareCreateViewModel;
+import it.niedermann.nextcloud.deck.ui.theme.ThemeUtils;
public class NewCardDialog extends DialogFragment implements DialogInterface.OnClickListener {
@@ -96,8 +95,10 @@ public class NewCardDialog extends DialogFragment implements DialogInterface.OnC
dialog.getButton(DialogInterface.BUTTON_NEGATIVE).setOnClickListener(v -> onClick(dialog, DialogInterface.BUTTON_NEGATIVE));
});
- BrandingUtil.applyBrandToEditTextInputLayout(color, binding.inputWrapper);
- binding.progressCircular.setIndeterminateTintList(ColorStateList.valueOf(BrandingUtil.getSecondaryForegroundColorDependingOnTheme(requireContext(), color)));
+ final var utils = ThemeUtils.of(color, requireContext());
+
+ utils.material.colorTextInputLayout(binding.inputWrapper);
+ utils.platform.colorCircularProgressBar(binding.progressCircular);
binding.input.addTextChangedListener(new TextWatcher() {
@Override
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/assignee/CardAssigneeDialog.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/assignee/CardAssigneeDialog.java
index 6a15a4f6c..9a46cec65 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/assignee/CardAssigneeDialog.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/assignee/CardAssigneeDialog.java
@@ -20,9 +20,9 @@ import com.bumptech.glide.Glide;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.databinding.DialogPreviewBinding;
import it.niedermann.nextcloud.deck.model.User;
-import it.niedermann.nextcloud.deck.ui.branding.DeleteAlertDialogBuilder;
import it.niedermann.nextcloud.deck.ui.card.EditCardViewModel;
import it.niedermann.nextcloud.deck.ui.card.attachments.previewdialog.PreviewDialog;
+import it.niedermann.nextcloud.deck.ui.theme.DeleteAlertDialogBuilder;
/**
* TODO maybe this can be merged with {@link PreviewDialog}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/AttachmentViewHolder.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/AttachmentViewHolder.java
index cb77ae89b..ddc35f76e 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/AttachmentViewHolder.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/AttachmentViewHolder.java
@@ -17,7 +17,7 @@ import it.niedermann.nextcloud.deck.model.Account;
import it.niedermann.nextcloud.deck.model.Attachment;
import it.niedermann.nextcloud.deck.model.enums.DBStatus;
import it.niedermann.nextcloud.deck.model.enums.EAttachmentType;
-import it.niedermann.nextcloud.deck.ui.branding.BrandingUtil;
+import it.niedermann.nextcloud.deck.ui.theme.ThemeUtils;
import it.niedermann.nextcloud.deck.util.AttachmentUtil;
public abstract class AttachmentViewHolder extends RecyclerView.ViewHolder {
@@ -25,10 +25,12 @@ public abstract class AttachmentViewHolder extends RecyclerView.ViewHolder {
super(itemView);
}
- public void bind(@NonNull Account account, @NonNull MenuInflater menuInflater, @NonNull FragmentManager fragmentManager, Long cardRemoteId, Attachment attachment, @Nullable View.OnClickListener onClickListener, @ColorInt int mainColor) {
+ public void bind(@NonNull Account account, @NonNull MenuInflater menuInflater, @NonNull FragmentManager fragmentManager, Long cardRemoteId, Attachment attachment, @Nullable View.OnClickListener onClickListener, @ColorInt int color) {
final String attachmentUri = (attachment.getId() == null || cardRemoteId == null)
? attachment.getLocalPath()
- : AttachmentUtil.getCopyDownloadUrl(account, cardRemoteId, attachment); setNotSyncedYetStatus(!DBStatus.LOCAL_EDITED.equals(attachment.getStatusEnum()), mainColor);
+ : AttachmentUtil.getCopyDownloadUrl(account, cardRemoteId, attachment);
+
+ setNotSyncedYetStatus(!DBStatus.LOCAL_EDITED.equals(attachment.getStatusEnum()), color);
itemView.setOnCreateContextMenuListener((menu, v, menuInfo) -> {
menuInflater.inflate(R.menu.attachment_menu, menu);
if(EAttachmentType.DECK_FILE.equals(attachment.getType())) {
@@ -51,9 +53,11 @@ public abstract class AttachmentViewHolder extends RecyclerView.ViewHolder {
abstract protected ImageView getPreview();
- protected void setNotSyncedYetStatus(boolean synced, @ColorInt int mainColor) {
+ protected void setNotSyncedYetStatus(boolean synced, @ColorInt int color) {
final var notSyncedYet = getNotSyncedYetStatusIcon();
- DrawableCompat.setTint(notSyncedYet.getDrawable(), BrandingUtil.getSecondaryForegroundColorDependingOnTheme(notSyncedYet.getContext(), mainColor));
+ final var scheme = ThemeUtils.createScheme(color, notSyncedYet.getContext());
+
+ DrawableCompat.setTint(notSyncedYet.getDrawable(), scheme.getOnPrimaryContainer());
notSyncedYet.setVisibility(synced ? View.GONE : View.VISIBLE);
}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/CardAttachmentAdapter.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/CardAttachmentAdapter.java
index 3b18515c3..57fe8d1e3 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/CardAttachmentAdapter.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/CardAttachmentAdapter.java
@@ -28,11 +28,11 @@ import it.niedermann.nextcloud.deck.databinding.ItemAttachmentImageBinding;
import it.niedermann.nextcloud.deck.model.Account;
import it.niedermann.nextcloud.deck.model.Attachment;
import it.niedermann.nextcloud.deck.ui.attachments.AttachmentsActivity;
-import it.niedermann.nextcloud.deck.ui.branding.Branded;
+import it.niedermann.nextcloud.deck.ui.theme.Themed;
import it.niedermann.nextcloud.deck.util.MimeTypeUtil;
@SuppressWarnings("WeakerAccess")
-public class CardAttachmentAdapter extends RecyclerView.Adapter<AttachmentViewHolder> implements Branded {
+public class CardAttachmentAdapter extends RecyclerView.Adapter<AttachmentViewHolder> implements Themed {
public static final int VIEW_TYPE_DEFAULT = 2;
public static final int VIEW_TYPE_IMAGE = 1;
@@ -42,7 +42,7 @@ public class CardAttachmentAdapter extends RecyclerView.Adapter<AttachmentViewHo
@NonNull
private final MenuInflater menuInflater;
@ColorInt
- private int mainColor;
+ private int color;
private final Account account;
@Nullable
private Long cardRemoteId = null;
@@ -116,7 +116,7 @@ public class CardAttachmentAdapter extends RecyclerView.Adapter<AttachmentViewHo
break;
}
}
- holder.bind(account, menuInflater, fragmentManager, cardRemoteId, attachment, onClickListener, mainColor);
+ holder.bind(account, menuInflater, fragmentManager, cardRemoteId, attachment, onClickListener, color);
}
@Override
@@ -167,8 +167,8 @@ public class CardAttachmentAdapter extends RecyclerView.Adapter<AttachmentViewHo
}
@Override
- public void applyBrand(@ColorInt int mainColor) {
- this.mainColor = mainColor;
+ public void applyTheme(@ColorInt int color) {
+ this.color = color;
notifyDataSetChanged();
}
}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/CardAttachmentsFragment.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/CardAttachmentsFragment.java
index 01706f9b1..e29f53904 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/CardAttachmentsFragment.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/CardAttachmentsFragment.java
@@ -15,14 +15,12 @@ import static com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_
import static com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_HIDDEN;
import static java.net.HttpURLConnection.HTTP_CONFLICT;
import static it.niedermann.nextcloud.deck.persistence.sync.adapters.db.util.LiveDataHelper.observeOnce;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.applyBrandToFAB;
import static it.niedermann.nextcloud.deck.ui.card.attachments.CardAttachmentAdapter.VIEW_TYPE_DEFAULT;
import static it.niedermann.nextcloud.deck.ui.card.attachments.CardAttachmentAdapter.VIEW_TYPE_IMAGE;
import static it.niedermann.nextcloud.deck.util.FilesUtil.copyContentUriToTempFile;
import android.content.ContentResolver;
import android.content.Intent;
-import android.content.res.ColorStateList;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
@@ -49,6 +47,7 @@ import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.snackbar.Snackbar;
+import com.nextcloud.android.common.ui.theme.utils.ColorRole;
import com.nextcloud.android.sso.exceptions.NextcloudHttpRequestFailedException;
import java.io.File;
@@ -73,7 +72,6 @@ import it.niedermann.nextcloud.deck.model.Attachment;
import it.niedermann.nextcloud.deck.model.Card;
import it.niedermann.nextcloud.deck.model.enums.DBStatus;
import it.niedermann.nextcloud.deck.persistence.sync.SyncManager;
-import it.niedermann.nextcloud.deck.ui.branding.BrandedSnackbar;
import it.niedermann.nextcloud.deck.ui.card.EditCardViewModel;
import it.niedermann.nextcloud.deck.ui.card.attachments.picker.AbstractPickerAdapter;
import it.niedermann.nextcloud.deck.ui.card.attachments.picker.ContactAdapter;
@@ -84,7 +82,8 @@ import it.niedermann.nextcloud.deck.ui.card.attachments.previewdialog.PreviewDia
import it.niedermann.nextcloud.deck.ui.card.attachments.previewdialog.PreviewDialogViewModel;
import it.niedermann.nextcloud.deck.ui.exception.ExceptionDialogFragment;
import it.niedermann.nextcloud.deck.ui.takephoto.TakePhotoActivity;
-import it.niedermann.nextcloud.deck.util.DeckColorUtil;
+import it.niedermann.nextcloud.deck.ui.theme.ThemeUtils;
+import it.niedermann.nextcloud.deck.ui.theme.ThemedSnackbar;
import it.niedermann.nextcloud.deck.util.JavaCompressor;
import it.niedermann.nextcloud.deck.util.MimeTypeUtil;
import it.niedermann.nextcloud.deck.util.VCardUtil;
@@ -223,7 +222,7 @@ public class CardAttachmentsFragment extends Fragment implements AttachmentDelet
}
final var sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext());
compressImagesOnUpload = sharedPreferences.getBoolean(getString(R.string.pref_key_compress_image_attachments), true);
- editViewModel.getBrandingColor().observe(getViewLifecycleOwner(), this::applyBrand);
+ editViewModel.getBoardColor().observe(getViewLifecycleOwner(), this::applyTheme);
return binding.getRoot();
}
@@ -416,7 +415,7 @@ public class CardAttachmentsFragment extends Fragment implements AttachmentDelet
for (final var existingAttachment : editViewModel.getFullCard().getAttachments()) {
final String existingPath = existingAttachment.getLocalPath();
if (existingPath != null && existingPath.equals(fileToUpload.getAbsolutePath())) {
- BrandedSnackbar.make(binding.coordinatorLayout, R.string.attachment_already_exists, Snackbar.LENGTH_LONG).show();
+ ThemedSnackbar.make(binding.coordinatorLayout, R.string.attachment_already_exists, Snackbar.LENGTH_LONG).show();
return;
}
}
@@ -451,7 +450,7 @@ public class CardAttachmentsFragment extends Fragment implements AttachmentDelet
// https://github.com/stefan-niedermann/nextcloud-deck/issues/534
editViewModel.getFullCard().getAttachments().remove(a);
adapter.removeAttachment(a);
- BrandedSnackbar.make(binding.coordinatorLayout, R.string.attachment_already_exists, Snackbar.LENGTH_LONG).show();
+ ThemedSnackbar.make(binding.coordinatorLayout, R.string.attachment_already_exists, Snackbar.LENGTH_LONG).show();
} else {
ExceptionDialogFragment.newInstance(new UploadAttachmentFailedException("Unknown URI scheme", throwable), editViewModel.getAccount()).show(getChildFragmentManager(), ExceptionDialogFragment.class.getSimpleName());
}
@@ -521,13 +520,15 @@ public class CardAttachmentsFragment extends Fragment implements AttachmentDelet
this.clickedItemPosition = position;
}
- private void applyBrand(@ColorInt int boardColor) {
- applyBrandToFAB(boardColor, binding.fab);
- @ColorInt final int finalMainColor = DeckColorUtil.contrastRatioIsSufficient(boardColor, primaryColor) ? boardColor : accentColor;
- final ColorStateList list = new ColorStateList(new int[][]{new int[]{android.R.attr.state_checked}, new int[]{}}, new int[]{finalMainColor, accentColor});
- binding.bottomNavigation.setItemIconTintList(list);
- binding.bottomNavigation.setItemTextColor(list);
- adapter.applyBrand(boardColor);
+ private void applyTheme(@ColorInt int color) {
+ final var utils = ThemeUtils.of(color, requireContext());
+
+ utils.material.themeFAB(binding.fab);
+ utils.deck.colorBottomNavigationView(binding.bottomNavigation);
+ utils.platform.colorViewBackground(binding.pickerHeader, ColorRole.SURFACE);
+ utils.platform.colorViewBackground(binding.pickerRecyclerView, ColorRole.SURFACE);
+
+ adapter.applyTheme(color);
}
public static Fragment newInstance() {
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/DefaultAttachmentViewHolder.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/DefaultAttachmentViewHolder.java
index b41a4e9d1..21f858218 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/DefaultAttachmentViewHolder.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/DefaultAttachmentViewHolder.java
@@ -1,5 +1,8 @@
package it.niedermann.nextcloud.deck.ui.card.attachments;
+import static it.niedermann.nextcloud.deck.util.AttachmentUtil.getIconForMimeType;
+import static it.niedermann.nextcloud.deck.util.AttachmentUtil.openAttachmentInBrowser;
+
import android.text.format.Formatter;
import android.view.MenuInflater;
import android.view.View;
@@ -15,9 +18,6 @@ import it.niedermann.nextcloud.deck.model.Account;
import it.niedermann.nextcloud.deck.model.Attachment;
import it.niedermann.nextcloud.deck.util.DateUtil;
-import static it.niedermann.nextcloud.deck.util.AttachmentUtil.getIconForMimeType;
-import static it.niedermann.nextcloud.deck.util.AttachmentUtil.openAttachmentInBrowser;
-
public class DefaultAttachmentViewHolder extends AttachmentViewHolder {
private final ItemAttachmentDefaultBinding binding;
@@ -37,8 +37,8 @@ public class DefaultAttachmentViewHolder extends AttachmentViewHolder {
return binding.notSyncedYet;
}
- public void bind(@NonNull Account account, @NonNull MenuInflater menuInflater, @NonNull FragmentManager fragmentManager, Long cardRemoteId, Attachment attachment, @Nullable View.OnClickListener onClickListener, @ColorInt int mainColor) {
- super.bind(account, menuInflater, fragmentManager, cardRemoteId, attachment, onClickListener, mainColor);
+ public void bind(@NonNull Account account, @NonNull MenuInflater menuInflater, @NonNull FragmentManager fragmentManager, Long cardRemoteId, Attachment attachment, @Nullable View.OnClickListener onClickListener, @ColorInt int color) {
+ super.bind(account, menuInflater, fragmentManager, cardRemoteId, attachment, onClickListener, color);
getPreview().setImageResource(getIconForMimeType(attachment.getMimetype()));
itemView.setOnClickListener((event) -> openAttachmentInBrowser(account, itemView.getContext(), cardRemoteId, attachment));
binding.filename.setText(attachment.getBasename());
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/DeleteAttachmentDialogFragment.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/DeleteAttachmentDialogFragment.java
index 63441bbd4..532e59dce 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/DeleteAttachmentDialogFragment.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/DeleteAttachmentDialogFragment.java
@@ -9,7 +9,7 @@ import androidx.fragment.app.DialogFragment;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.model.Attachment;
-import it.niedermann.nextcloud.deck.ui.branding.DeleteAlertDialogBuilder;
+import it.niedermann.nextcloud.deck.ui.theme.DeleteAlertDialogBuilder;
public class DeleteAttachmentDialogFragment extends DialogFragment {
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/ImageAttachmentViewHolder.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/ImageAttachmentViewHolder.java
index fae2255f2..72d942618 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/ImageAttachmentViewHolder.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/ImageAttachmentViewHolder.java
@@ -36,8 +36,8 @@ public class ImageAttachmentViewHolder extends AttachmentViewHolder {
return binding.notSyncedYet;
}
- public void bind(@NonNull Account account, @NonNull MenuInflater menuInflater, @NonNull FragmentManager fragmentManager, Long cardRemoteId, Attachment attachment, @Nullable View.OnClickListener onClickListener, @ColorInt int mainColor) {
- super.bind(account, menuInflater, fragmentManager, cardRemoteId, attachment, onClickListener, mainColor);
+ public void bind(@NonNull Account account, @NonNull MenuInflater menuInflater, @NonNull FragmentManager fragmentManager, Long cardRemoteId, Attachment attachment, @Nullable View.OnClickListener onClickListener, @ColorInt int color) {
+ super.bind(account, menuInflater, fragmentManager, cardRemoteId, attachment, onClickListener, color);
getPreview().post(() -> {
@Nullable final String uri = AttachmentUtil.getThumbnailUrl(account, cardRemoteId, attachment, getPreview().getWidth());
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/CardCommentsAdapter.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/CardCommentsAdapter.java
index 18bf21ceb..b392d5725 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/CardCommentsAdapter.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/CardCommentsAdapter.java
@@ -1,7 +1,6 @@
package it.niedermann.nextcloud.deck.ui.card.comments;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.getSecondaryForegroundColorDependingOnTheme;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.readBrandMainColor;
+import static it.niedermann.nextcloud.deck.ui.theme.ThemeUtils.readBrandMainColor;
import android.content.Context;
import android.view.LayoutInflater;
@@ -20,10 +19,12 @@ import it.niedermann.nextcloud.deck.DeckLog;
import it.niedermann.nextcloud.deck.databinding.ItemCommentBinding;
import it.niedermann.nextcloud.deck.model.Account;
import it.niedermann.nextcloud.deck.model.ocs.comment.full.FullDeckComment;
+import it.niedermann.nextcloud.deck.ui.theme.ThemeUtils;
+import scheme.Scheme;
public class CardCommentsAdapter extends RecyclerView.Adapter<ItemCommentViewHolder> {
- private final int mainColor;
+ private final Scheme scheme;
@NonNull
private final List<FullDeckComment> comments = new ArrayList<>();
@NonNull
@@ -46,7 +47,7 @@ public class CardCommentsAdapter extends RecyclerView.Adapter<ItemCommentViewHol
this.selectAsReplyListener = selectAsReplyListener;
this.fragmentManager = fragmentManager;
this.editListener = editListener;
- this.mainColor = getSecondaryForegroundColorDependingOnTheme(context, readBrandMainColor(context));
+ this.scheme = ThemeUtils.createScheme(readBrandMainColor(context), context);
setHasStableIds(true);
}
@@ -64,7 +65,7 @@ public class CardCommentsAdapter extends RecyclerView.Adapter<ItemCommentViewHol
@Override
public void onBindViewHolder(@NonNull ItemCommentViewHolder holder, int position) {
final var comment = comments.get(position);
- holder.bind(comment, account, mainColor, menuInflater, deletedListener, selectAsReplyListener, fragmentManager, (changedText) -> {
+ holder.bind(comment, account, scheme, menuInflater, deletedListener, selectAsReplyListener, fragmentManager, (changedText) -> {
if (!Objects.equals(changedText, comment.getComment().getMessage())) {
DeckLog.info("Toggled checkbox in comment with localId", comment.getLocalId());
this.editListener.onCommentEdited(comment.getLocalId(), changedText.toString());
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/CardCommentsEditDialogFragment.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/CardCommentsEditDialogFragment.java
index b26ee84c5..abb3b1033 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/CardCommentsEditDialogFragment.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/CardCommentsEditDialogFragment.java
@@ -1,7 +1,5 @@
package it.niedermann.nextcloud.deck.ui.card.comments;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.applyBrandToEditTextInputLayout;
-
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
@@ -20,9 +18,10 @@ import java.util.Objects;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.databinding.DialogAddCommentBinding;
-import it.niedermann.nextcloud.deck.ui.branding.BrandedDialogFragment;
+import it.niedermann.nextcloud.deck.ui.theme.ThemeUtils;
+import it.niedermann.nextcloud.deck.ui.theme.ThemedDialogFragment;
-public class CardCommentsEditDialogFragment extends BrandedDialogFragment {
+public class CardCommentsEditDialogFragment extends ThemedDialogFragment {
private static final String BUNDLE_KEY_COMMENT_ID = "commentId";
private static final String BUNDLE_KEY_COMMENT_MESSAGE = "commentMessage";
private CommentEditedListener addCommentListener;
@@ -86,8 +85,10 @@ public class CardCommentsEditDialogFragment extends BrandedDialogFragment {
}
@Override
- public void applyBrand(int mainColor) {
- applyBrandToEditTextInputLayout(mainColor, binding.inputWrapper);
+ public void applyTheme(int color) {
+ final var utils = ThemeUtils.of(color, requireContext());
+
+ utils.material.colorTextInputLayout(binding.inputWrapper);
}
}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/CardCommentsFragment.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/CardCommentsFragment.java
index 7e90e513a..277eb82c2 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/CardCommentsFragment.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/CardCommentsFragment.java
@@ -2,8 +2,6 @@ package it.niedermann.nextcloud.deck.ui.card.comments;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.applyBrandToEditTextInputLayout;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.applyBrandToFAB;
import android.os.Bundle;
import android.text.TextUtils;
@@ -33,6 +31,7 @@ import it.niedermann.nextcloud.deck.persistence.sync.SyncManager;
import it.niedermann.nextcloud.deck.ui.card.EditActivity;
import it.niedermann.nextcloud.deck.ui.card.EditCardViewModel;
import it.niedermann.nextcloud.deck.ui.exception.ExceptionDialogFragment;
+import it.niedermann.nextcloud.deck.ui.theme.ThemeUtils;
import it.niedermann.nextcloud.deck.util.ViewUtil;
public class CardCommentsFragment extends Fragment implements CommentEditedListener, CommentDeletedListener, CommentSelectAsReplyListener {
@@ -131,7 +130,7 @@ public class CardCommentsFragment extends Fragment implements CommentEditedListe
binding.message.requestFocus();
requireActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
}
- mainViewModel.getBrandingColor().observe(getViewLifecycleOwner(), this::applyBrand);
+ mainViewModel.getBoardColor().observe(getViewLifecycleOwner(), this::applyTheme);
}
@Override
@@ -163,9 +162,11 @@ public class CardCommentsFragment extends Fragment implements CommentEditedListe
});
}
- private void applyBrand(int mainColor) {
- applyBrandToFAB(mainColor, binding.fab);
- applyBrandToEditTextInputLayout(mainColor, binding.messageWrapper);
+ private void applyTheme(int color) {
+ final var utils = ThemeUtils.of(color, requireContext());
+
+ utils.material.themeFAB(binding.fab);
+ utils.material.colorTextInputLayout(binding.messageWrapper);
}
@Override
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/ItemCommentViewHolder.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/ItemCommentViewHolder.java
index 88cc1a904..f38e41f93 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/ItemCommentViewHolder.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/ItemCommentViewHolder.java
@@ -4,7 +4,6 @@ import android.text.method.LinkMovementMethod;
import android.view.MenuInflater;
import android.view.View;
-import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.TooltipCompat;
import androidx.core.graphics.drawable.DrawableCompat;
@@ -26,6 +25,7 @@ import it.niedermann.nextcloud.deck.model.enums.DBStatus;
import it.niedermann.nextcloud.deck.model.ocs.comment.full.FullDeckComment;
import it.niedermann.nextcloud.deck.util.DateUtil;
import it.niedermann.nextcloud.deck.util.ViewUtil;
+import scheme.Scheme;
public class ItemCommentViewHolder extends RecyclerView.ViewHolder {
private final ItemCommentBinding binding;
@@ -38,7 +38,7 @@ public class ItemCommentViewHolder extends RecyclerView.ViewHolder {
this.binding.message.setMovementMethod(LinkMovementMethod.getInstance());
}
- public void bind(@NonNull FullDeckComment comment, @NonNull Account account, @ColorInt int mainColor, @NonNull MenuInflater inflater, @NonNull CommentDeletedListener deletedListener, @NonNull CommentSelectAsReplyListener selectAsReplyListener, @NonNull FragmentManager fragmentManager, @NonNull Consumer<CharSequence> editListener) {
+ public void bind(@NonNull FullDeckComment comment, @NonNull Account account, @NonNull Scheme scheme, @NonNull MenuInflater inflater, @NonNull CommentDeletedListener deletedListener, @NonNull CommentSelectAsReplyListener selectAsReplyListener, @NonNull FragmentManager fragmentManager, @NonNull Consumer<CharSequence> editListener) {
ViewUtil.addAvatar(binding.avatar, account.getUrl(), comment.getComment().getActorId(), DimensionUtil.INSTANCE.dpToPx(binding.avatar.getContext(), R.dimen.icon_size_details), R.drawable.ic_person_grey600_24dp);
final var mentions = new HashMap<String, String>(comment.getComment().getMentions().size());
for (final var mention : comment.getComment().getMentions()) {
@@ -80,7 +80,7 @@ public class ItemCommentViewHolder extends RecyclerView.ViewHolder {
});
TooltipCompat.setTooltipText(binding.creationDateTime, comment.getComment().getCreationDateTime().atZone(ZoneId.systemDefault()).format(dateFormatter));
- DrawableCompat.setTint(binding.notSyncedYet.getDrawable(), mainColor);
+ DrawableCompat.setTint(binding.notSyncedYet.getDrawable(), scheme.getOnPrimaryContainer());
binding.notSyncedYet.setVisibility(DBStatus.LOCAL_EDITED.equals(comment.getStatusEnum()) ? View.VISIBLE : View.GONE);
if (comment.getParent() == null) {
@@ -88,7 +88,7 @@ public class ItemCommentViewHolder extends RecyclerView.ViewHolder {
} else {
final int commentParentMaxLines = itemView.getContext().getResources().getInteger(R.integer.comment_parent_max_lines);
binding.parentContainer.setVisibility(View.VISIBLE);
- binding.parentBorder.setBackgroundColor(mainColor);
+ binding.parentBorder.setBackgroundColor(scheme.getOnPrimaryContainer());
binding.parent.setText(comment.getParent().getMessage());
binding.parent.setOnClickListener((v) -> {
final boolean previouslyCollapsed = binding.parent.getMaxLines() == commentParentMaxLines;
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/details/CardDetailsFragment.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/details/CardDetailsFragment.java
index 1a56a195f..4eec53ece 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/details/CardDetailsFragment.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/card/details/CardDetailsFragment.java
@@ -3,7 +3,6 @@ package it.niedermann.nextcloud.deck.ui.card.details;
import static android.view.View.GONE;
import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.applyBrandToEditTextInputLayout;
import android.content.res.ColorStateList;
import android.graphics.drawable.Drawable;
@@ -39,6 +38,7 @@ import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
+import java.util.stream.Stream;
import it.niedermann.android.markdown.MarkdownEditor;
import it.niedermann.android.util.ColorUtil;
@@ -50,15 +50,16 @@ import it.niedermann.nextcloud.deck.databinding.FragmentCardEditTabDetailsBindin
import it.niedermann.nextcloud.deck.model.Label;
import it.niedermann.nextcloud.deck.model.User;
import it.niedermann.nextcloud.deck.model.full.FullCard;
-import it.niedermann.nextcloud.deck.ui.branding.BrandedDatePickerDialog;
-import it.niedermann.nextcloud.deck.ui.branding.BrandedSnackbar;
-import it.niedermann.nextcloud.deck.ui.branding.BrandedTimePickerDialog;
import it.niedermann.nextcloud.deck.ui.card.EditCardViewModel;
import it.niedermann.nextcloud.deck.ui.card.LabelAutoCompleteAdapter;
import it.niedermann.nextcloud.deck.ui.card.UserAutoCompleteAdapter;
import it.niedermann.nextcloud.deck.ui.card.assignee.CardAssigneeDialog;
import it.niedermann.nextcloud.deck.ui.card.assignee.CardAssigneeListener;
import it.niedermann.nextcloud.deck.ui.exception.ExceptionDialogFragment;
+import it.niedermann.nextcloud.deck.ui.theme.ThemeUtils;
+import it.niedermann.nextcloud.deck.ui.theme.ThemedDatePickerDialog;
+import it.niedermann.nextcloud.deck.ui.theme.ThemedSnackbar;
+import it.niedermann.nextcloud.deck.ui.theme.ThemedTimePickerDialog;
public class CardDetailsFragment extends Fragment implements OnDateSetListener, OnTimeSetListener, CardAssigneeListener {
@@ -102,7 +103,7 @@ public class CardDetailsFragment extends Fragment implements OnDateSetListener,
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
- viewModel.getBrandingColor().observe(getViewLifecycleOwner(), this::applyBrand);
+ viewModel.getBoardColor().observe(getViewLifecycleOwner(), this::applyTheme);
}
@Override
@@ -110,8 +111,8 @@ public class CardDetailsFragment extends Fragment implements OnDateSetListener,
super.onResume();
// https://github.com/wdullaer/MaterialDateTimePicker#why-are-my-callbacks-lost-when-the-device-changes-orientation
- final var dpd = (DatePickerDialog) getChildFragmentManager().findFragmentByTag(BrandedDatePickerDialog.class.getCanonicalName());
- final var tpd = (TimePickerDialog) getChildFragmentManager().findFragmentByTag(BrandedTimePickerDialog.class.getCanonicalName());
+ final var dpd = (DatePickerDialog) getChildFragmentManager().findFragmentByTag(ThemedDatePickerDialog.class.getCanonicalName());
+ final var tpd = (TimePickerDialog) getChildFragmentManager().findFragmentByTag(ThemedTimePickerDialog.class.getCanonicalName());
if (tpd != null) tpd.setOnTimeSetListener(this);
if (dpd != null) dpd.setOnDateSetListener(this);
}
@@ -122,15 +123,21 @@ public class CardDetailsFragment extends Fragment implements OnDateSetListener,
this.binding = null;
}
- private void applyBrand(@ColorInt int boardColor) {
+ private void applyTheme(@ColorInt int color) {
+ final var utils = ThemeUtils.of(color, requireContext());
+
+ Stream.of(
+ binding.labelsWrapper,
+ binding.dueDateDateWrapper,
+ binding.dueDateTimeWrapper,
+ binding.peopleWrapper,
+ binding.descriptionEditorWrapper
+ ).forEach(utils.material::colorTextInputLayout);
+
+ binding.descriptionEditor.setSearchColor(color);
+ binding.descriptionViewer.setSearchColor(color);
+
// TODO apply correct branding on the BrandedDatePicker
- applyBrandToEditTextInputLayout(boardColor, binding.labelsWrapper);
- applyBrandToEditTextInputLayout(boardColor, binding.dueDateDateWrapper);
- applyBrandToEditTextInputLayout(boardColor, binding.dueDateTimeWrapper);
- applyBrandToEditTextInputLayout(boardColor, binding.peopleWrapper);
- applyBrandToEditTextInputLayout(boardColor, binding.descriptionEditorWrapper);
- binding.descriptionEditor.setSearchColor(boardColor);
- binding.descriptionViewer.setSearchColor(boardColor);
}
private void setupDescription() {
@@ -191,8 +198,8 @@ public class CardDetailsFragment extends Fragment implements OnDateSetListener,
} else {
date = LocalDate.now();
}
- BrandedDatePickerDialog.newInstance(this, date.getYear(), date.getMonthValue(), date.getDayOfMonth())
- .show(getChildFragmentManager(), BrandedDatePickerDialog.class.getCanonicalName());
+ ThemedDatePickerDialog.newInstance(this, date.getYear(), date.getMonthValue(), date.getDayOfMonth())
+ .show(getChildFragmentManager(), ThemedDatePickerDialog.class.getCanonicalName());
});
binding.dueDateTime.setOnClickListener(v -> {
@@ -202,8 +209,8 @@ public class CardDetailsFragment extends Fragment implements OnDateSetListener,
} else {
time = LocalTime.now();
}
- BrandedTimePickerDialog.newInstance(this, time.getHour(), time.getMinute(), true)
- .show(getChildFragmentManager(), BrandedTimePickerDialog.class.getCanonicalName());
+ ThemedTimePickerDialog.newInstance(this, time.getHour(), time.getMinute(), true)
+ .show(getChildFragmentManager(), ThemedTimePickerDialog.class.getCanonicalName());
});
binding.clearDueDate.setOnClickListener(v -> {
@@ -249,7 +256,7 @@ public class CardDetailsFragment extends Fragment implements OnDateSetListener,
@Override
public void onError(Throwable throwable) {
IResponseCallback.super.onError(throwable);
- requireActivity().runOnUiThread(() -> BrandedSnackbar.make(requireView(), getString(R.string.error_create_label, newLabel.getTitle()), Snackbar.LENGTH_LONG)
+ requireActivity().runOnUiThread(() -> ThemedSnackbar.make(requireView(), getString(R.string.error_create_label, newLabel.getTitle()), Snackbar.LENGTH_LONG)
.setAction(R.string.simple_more, v -> ExceptionDialogFragment.newInstance(throwable, viewModel.getAccount()).show(getChildFragmentManager(), ExceptionDialogFragment.class.getSimpleName())).show());
}
});
@@ -401,9 +408,9 @@ public class CardDetailsFragment extends Fragment implements OnDateSetListener,
viewModel.getFullCard().getAssignedUsers().remove(user);
adapter.removeUser(user);
((UserAutoCompleteAdapter) binding.people.getAdapter()).include(user);
- BrandedSnackbar.make(
- requireView(), getString(R.string.unassigned_user, user.getDisplayname()),
- Snackbar.LENGTH_LONG)
+ ThemedSnackbar.make(
+ requireView(), getString(R.string.unassigned_user, user.getDisplayname()),
+ Snackbar.LENGTH_LONG)
.setAction(R.string.simple_undo, v1 -> {
viewModel.getFullCard().getAssignedUsers().add(user);
((UserAutoCompleteAdapter) binding.people.getAdapter()).exclude(user);
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterDialogFragment.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterDialogFragment.java
index 50e3a05c3..75b30dc1c 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterDialogFragment.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterDialogFragment.java
@@ -1,13 +1,11 @@
package it.niedermann.nextcloud.deck.ui.filter;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.getSecondaryForegroundColorDependingOnTheme;
-
import android.app.Dialog;
+import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
-import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.DialogFragment;
@@ -19,13 +17,13 @@ import androidx.viewpager2.widget.ViewPager2;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.tabs.TabLayoutMediator;
-import it.niedermann.android.util.ColorUtil;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.databinding.DialogFilterBinding;
import it.niedermann.nextcloud.deck.model.enums.EDueType;
-import it.niedermann.nextcloud.deck.ui.branding.BrandedDialogFragment;
+import it.niedermann.nextcloud.deck.ui.theme.ThemeUtils;
+import it.niedermann.nextcloud.deck.ui.theme.ThemedDialogFragment;
-public class FilterDialogFragment extends BrandedDialogFragment {
+public class FilterDialogFragment extends ThemedDialogFragment {
private DialogFilterBinding binding;
private FilterViewModel filterViewModel;
@@ -108,11 +106,10 @@ public class FilterDialogFragment extends BrandedDialogFragment {
}
@Override
- public void applyBrand(int mainColor) {
- @ColorInt final int finalMainColor = getSecondaryForegroundColorDependingOnTheme(binding.tabLayout.getContext(), mainColor);
- final boolean contrastRatioIsSufficient = ColorUtil.INSTANCE.getContrastRatio(mainColor, ContextCompat.getColor(binding.tabLayout.getContext(), R.color.primary)) > 1.7d;
- binding.tabLayout.setSelectedTabIndicatorColor(contrastRatioIsSufficient ? mainColor : finalMainColor);
- indicator.setColorFilter(contrastRatioIsSufficient ? mainColor : finalMainColor, PorterDuff.Mode.SRC_ATOP);
+ public void applyTheme(int color) {
+ final var utils = ThemeUtils.of(color, requireContext());
+
+ utils.deck.themeTabLayout(binding.tabLayout, Color.TRANSPARENT);
}
private static class TabsPagerAdapter extends FragmentStateAdapter {
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/movecard/MoveCardDialogFragment.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/movecard/MoveCardDialogFragment.java
index 95b234439..5dd430d1d 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/movecard/MoveCardDialogFragment.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/movecard/MoveCardDialogFragment.java
@@ -4,7 +4,6 @@ import static android.view.View.GONE;
import static android.view.View.VISIBLE;
import android.content.Context;
-import android.content.res.ColorStateList;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
@@ -20,13 +19,13 @@ import it.niedermann.nextcloud.deck.databinding.DialogMoveCardBinding;
import it.niedermann.nextcloud.deck.model.Account;
import it.niedermann.nextcloud.deck.model.Board;
import it.niedermann.nextcloud.deck.model.Stack;
-import it.niedermann.nextcloud.deck.ui.branding.BrandedDialogFragment;
-import it.niedermann.nextcloud.deck.ui.branding.BrandingUtil;
import it.niedermann.nextcloud.deck.ui.pickstack.PickStackFragment;
import it.niedermann.nextcloud.deck.ui.pickstack.PickStackListener;
import it.niedermann.nextcloud.deck.ui.pickstack.PickStackViewModel;
+import it.niedermann.nextcloud.deck.ui.theme.ThemeUtils;
+import it.niedermann.nextcloud.deck.ui.theme.ThemedDialogFragment;
-public class MoveCardDialogFragment extends BrandedDialogFragment implements PickStackListener {
+public class MoveCardDialogFragment extends ThemedDialogFragment implements PickStackListener {
private static final String KEY_ORIGIN_ACCOUNT_ID = "account_id";
private static final String KEY_ORIGIN_BOARD_LOCAL_ID = "board_local_id";
@@ -107,6 +106,11 @@ public class MoveCardDialogFragment extends BrandedDialogFragment implements Pic
public void onStackPicked(@NonNull Account account, @Nullable Board board, @Nullable Stack stack) {
this.selectedAccount = account;
this.selectedBoard = board;
+
+ if (board != null) {
+ applyTheme(board.getColor());
+ }
+
this.selectedStack = stack;
if (board == null || stack == null) {
binding.submit.setEnabled(false);
@@ -118,10 +122,11 @@ public class MoveCardDialogFragment extends BrandedDialogFragment implements Pic
}
@Override
- public void applyBrand(int mainColor) {
- final ColorStateList mainColorStateList = ColorStateList.valueOf(BrandingUtil.getSecondaryForegroundColorDependingOnTheme(requireContext(), mainColor));
- binding.cancel.setTextColor(mainColorStateList);
- binding.submit.setTextColor(mainColorStateList);
+ public void applyTheme(int color) {
+ final var utils = ThemeUtils.of(color, requireContext());
+
+ utils.material.colorMaterialButtonText(binding.cancel);
+ utils.material.colorMaterialButtonText(binding.submit);
}
public static DialogFragment newInstance(long originAccountId, long originBoardLocalId, String originCardTitle, Long originCardLocalId, boolean hasAttachmentsOrComments) {
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/settings/SettingsFragment.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/settings/SettingsFragment.java
index b4b91a2cb..cc01781e6 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/settings/SettingsFragment.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/settings/SettingsFragment.java
@@ -16,16 +16,16 @@ import it.niedermann.nextcloud.deck.DeckApplication;
import it.niedermann.nextcloud.deck.DeckLog;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.persistence.sync.SyncWorker;
-import it.niedermann.nextcloud.deck.ui.branding.BrandedSwitchPreference;
+import it.niedermann.nextcloud.deck.ui.theme.ThemedSwitchPreference;
public class SettingsFragment extends PreferenceFragmentCompat {
- private BrandedSwitchPreference wifiOnlyPref;
- private BrandedSwitchPreference compactPref;
- private BrandedSwitchPreference coverImagesPref;
- private BrandedSwitchPreference compressImageAttachmentsPref;
- private BrandedSwitchPreference debuggingPref;
- private BrandedSwitchPreference eTagPref;
+ private ThemedSwitchPreference wifiOnlyPref;
+ private ThemedSwitchPreference compactPref;
+ private ThemedSwitchPreference coverImagesPref;
+ private ThemedSwitchPreference compressImageAttachmentsPref;
+ private ThemedSwitchPreference debuggingPref;
+ private ThemedSwitchPreference eTagPref;
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
@@ -76,12 +76,12 @@ public class SettingsFragment extends PreferenceFragmentCompat {
super.onViewCreated(view, savedInstanceState);
DeckApplication.readCurrentAccountColor().observe(getViewLifecycleOwner(), (mainColor) -> {
- wifiOnlyPref.applyBrand(mainColor);
- compactPref.applyBrand(mainColor);
- coverImagesPref.applyBrand(mainColor);
- compressImageAttachmentsPref.applyBrand(mainColor);
- debuggingPref.applyBrand(mainColor);
- eTagPref.applyBrand(mainColor);
+ wifiOnlyPref.applyTheme(mainColor);
+ compactPref.applyTheme(mainColor);
+ coverImagesPref.applyTheme(mainColor);
+ compressImageAttachmentsPref.applyTheme(mainColor);
+ debuggingPref.applyTheme(mainColor);
+ eTagPref.applyTheme(mainColor);
});
}
}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/sharetarget/ShareProgressDialogFragment.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/sharetarget/ShareProgressDialogFragment.java
index 207db9006..852735352 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/sharetarget/ShareProgressDialogFragment.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/sharetarget/ShareProgressDialogFragment.java
@@ -1,8 +1,5 @@
package it.niedermann.nextcloud.deck.ui.sharetarget;
-import static android.graphics.PorterDuff.Mode;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.getSecondaryForegroundColorDependingOnTheme;
-
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
@@ -22,11 +19,12 @@ import it.niedermann.nextcloud.deck.BuildConfig;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.databinding.DialogShareProgressBinding;
import it.niedermann.nextcloud.deck.exceptions.UploadAttachmentFailedException;
-import it.niedermann.nextcloud.deck.ui.branding.BrandedDialogFragment;
import it.niedermann.nextcloud.deck.ui.exception.ExceptionDialogFragment;
+import it.niedermann.nextcloud.deck.ui.theme.ThemeUtils;
+import it.niedermann.nextcloud.deck.ui.theme.ThemedDialogFragment;
import it.niedermann.nextcloud.exception.ExceptionUtil;
-public class ShareProgressDialogFragment extends BrandedDialogFragment {
+public class ShareProgressDialogFragment extends ThemedDialogFragment {
private DialogShareProgressBinding binding;
private ShareProgressViewModel viewModel;
@@ -122,9 +120,10 @@ public class ShareProgressDialogFragment extends BrandedDialogFragment {
}
@Override
- public void applyBrand(int mainColor) {
- binding.progress.getProgressDrawable().setColorFilter(
- getSecondaryForegroundColorDependingOnTheme(requireContext(), mainColor), Mode.SRC_IN);
- binding.errorReportButton.setTextColor(getSecondaryForegroundColorDependingOnTheme(requireContext(), mainColor));
+ public void applyTheme(int color) {
+ final var utils = ThemeUtils.of(color, requireContext());
+
+ utils.platform.themeHorizontalProgressBar(binding.progress);
+ utils.material.colorMaterialButtonText(binding.errorReportButton);
}
}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/stack/DeleteStackDialogFragment.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/stack/DeleteStackDialogFragment.java
index 6594ccc0f..4120e5e00 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/stack/DeleteStackDialogFragment.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/stack/DeleteStackDialogFragment.java
@@ -8,7 +8,7 @@ import androidx.annotation.NonNull;
import androidx.fragment.app.DialogFragment;
import it.niedermann.nextcloud.deck.R;
-import it.niedermann.nextcloud.deck.ui.branding.DeleteAlertDialogBuilder;
+import it.niedermann.nextcloud.deck.ui.theme.DeleteAlertDialogBuilder;
public class DeleteStackDialogFragment extends DialogFragment {
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/stack/EditStackDialogFragment.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/stack/EditStackDialogFragment.java
index eb0ad1e26..4b37a3924 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/stack/EditStackDialogFragment.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/stack/EditStackDialogFragment.java
@@ -1,7 +1,5 @@
package it.niedermann.nextcloud.deck.ui.stack;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.applyBrandToEditTextInputLayout;
-
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
@@ -24,9 +22,10 @@ import java.util.Objects;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.databinding.DialogStackCreateBinding;
-import it.niedermann.nextcloud.deck.ui.branding.BrandedDialogFragment;
+import it.niedermann.nextcloud.deck.ui.theme.ThemeUtils;
+import it.niedermann.nextcloud.deck.ui.theme.ThemedDialogFragment;
-public class EditStackDialogFragment extends BrandedDialogFragment implements DialogInterface.OnClickListener {
+public class EditStackDialogFragment extends ThemedDialogFragment implements DialogInterface.OnClickListener {
private static final String KEY_STACK_ID = "stack_id";
private static final String KEY_OLD_TITLE = "old_title";
private EditStackListener editStackListener;
@@ -135,8 +134,10 @@ public class EditStackDialogFragment extends BrandedDialogFragment implements Di
}
@Override
- public void applyBrand(int mainColor) {
- applyBrandToEditTextInputLayout(mainColor, binding.inputWrapper);
+ public void applyTheme(int color) {
+ final var utils = ThemeUtils.of(color, requireContext());
+
+ utils.material.colorTextInputLayout(binding.inputWrapper);
}
@Override
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/stack/StackFragment.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/stack/StackFragment.java
index c28573289..f090ac59e 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/stack/StackFragment.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/stack/StackFragment.java
@@ -139,7 +139,7 @@ public class StackFragment extends Fragment implements DragAndDropTab<CardAdapte
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
- DeckApplication.readCurrentBoardColor().observe(getViewLifecycleOwner(), this::applyBrand);
+ DeckApplication.readCurrentBoardColor().observe(getViewLifecycleOwner(), this::applyTheme);
}
@Override
@@ -159,9 +159,9 @@ public class StackFragment extends Fragment implements DragAndDropTab<CardAdapte
return binding.recyclerView;
}
- private void applyBrand(int mainColor) {
+ private void applyTheme(int color) {
if (this.adapter != null) {
- this.adapter.applyBrand(mainColor);
+ this.adapter.applyTheme(color);
}
}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/takephoto/TakePhotoActivity.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/takephoto/TakePhotoActivity.java
index 67ca627ca..a8fd87ae6 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/takephoto/TakePhotoActivity.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/takephoto/TakePhotoActivity.java
@@ -34,9 +34,9 @@ import java.util.concurrent.ExecutionException;
import it.niedermann.nextcloud.deck.DeckApplication;
import it.niedermann.nextcloud.deck.DeckLog;
import it.niedermann.nextcloud.deck.databinding.ActivityTakePhotoBinding;
-import it.niedermann.nextcloud.deck.ui.branding.BrandingUtil;
import it.niedermann.nextcloud.deck.ui.exception.ExceptionDialogFragment;
import it.niedermann.nextcloud.deck.ui.exception.ExceptionHandler;
+import it.niedermann.nextcloud.deck.ui.theme.ThemeUtils;
import it.niedermann.nextcloud.deck.util.FilesUtil;
public class TakePhotoActivity extends AppCompatActivity {
@@ -180,7 +180,9 @@ public class TakePhotoActivity extends AppCompatActivity {
return new Intent(context, TakePhotoActivity.class).setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
}
- private void applyBoardColorBrand(int mainColor) {
- Arrays.stream(brandedFABs).forEach(fab -> BrandingUtil.applyBrandToFAB(mainColor, fab));
+ private void applyBoardColorBrand(int color) {
+ final var utils = ThemeUtils.of(color, this);
+
+ Arrays.stream(brandedFABs).forEach(utils.material::themeFAB);
}
}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/DeckViewThemeUtils.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/DeckViewThemeUtils.java
new file mode 100644
index 000000000..ee11cbbea
--- /dev/null
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/DeckViewThemeUtils.java
@@ -0,0 +1,120 @@
+package it.niedermann.nextcloud.deck.ui.theme;
+
+import static com.nextcloud.android.common.ui.util.ColorStateListUtilsKt.buildColorStateList;
+
+import android.content.res.ColorStateList;
+import android.graphics.Color;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.NonNull;
+import androidx.core.content.ContextCompat;
+
+import com.google.android.material.bottomnavigation.BottomNavigationView;
+import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;
+import com.google.android.material.navigation.NavigationView;
+import com.google.android.material.tabs.TabLayout;
+import com.nextcloud.android.common.ui.theme.MaterialSchemes;
+import com.nextcloud.android.common.ui.theme.ViewThemeUtilsBase;
+import com.nextcloud.android.common.ui.theme.utils.MaterialViewThemeUtils;
+
+import it.niedermann.nextcloud.deck.R;
+import kotlin.Pair;
+
+/**
+ * UI Elements which are not yet supported by the <a href="https://github.com/nextcloud/android-common"><code>android-commons</code></a> library.
+ * Ideally there should at least be one Pull Request for Upstream for each method here.
+ */
+public class DeckViewThemeUtils extends ViewThemeUtilsBase {
+
+ private final MaterialViewThemeUtils material;
+
+ public DeckViewThemeUtils(
+ @NonNull MaterialSchemes schemes,
+ @NonNull MaterialViewThemeUtils material
+ ) {
+ super(schemes);
+ this.material = material;
+ }
+
+ /**
+ * @param fab {@link ExtendedFloatingActionButton}
+ * @see <a href="https://github.com/nextcloud/android-common/pull/68">Upstream Pull Request</a>
+ */
+ public void themeExtendedFAB(ExtendedFloatingActionButton fab) {
+ withScheme(fab, scheme -> {
+ fab.setBackgroundTintList(buildColorStateList(
+ new Pair<>(android.R.attr.state_enabled, scheme.getPrimaryContainer()),
+ new Pair<>(-android.R.attr.state_enabled, Color.GRAY)
+ ));
+ fab.setIconTint(buildColorStateList(
+ new Pair<>(android.R.attr.state_enabled, scheme.getOnPrimaryContainer()),
+ new Pair<>(-android.R.attr.state_enabled, Color.WHITE)
+ ));
+ return fab;
+ });
+ }
+
+ /**
+ * @param navigationView {@link NavigationView}
+ * @see <a href="https://github.com/nextcloud/android-common/pull/69">Upstream Pull Request</a>
+ */
+ public void colorNavigationView(NavigationView navigationView) {
+ withScheme(navigationView, scheme -> {
+ if (navigationView.getItemBackground() != null) {
+ navigationView.getItemBackground().setTintList(buildColorStateList(
+ new Pair<>(android.R.attr.state_checked, scheme.getSecondaryContainer()),
+ new Pair<>(-android.R.attr.state_checked, Color.TRANSPARENT)
+ ));
+ }
+ // Fixes https://github.com/nextcloud/android-common/issues/66
+ navigationView.getBackground().setTintList(ColorStateList.valueOf(scheme.getSurface()));
+
+ final var colorStateList = buildColorStateList(
+ new Pair<>(android.R.attr.state_checked, scheme.getOnSecondaryContainer()),
+ new Pair<>(-android.R.attr.state_checked, scheme.getOnSurfaceVariant())
+ );
+
+ navigationView.setItemTextColor(colorStateList);
+ // Fixes https://github.com/nextcloud/android-common/issues/64
+ // navigationView.setItemIconTintList(colorStateList);
+ return navigationView;
+ });
+ }
+
+ /**
+ * @param bottomNavigationView {@link BottomNavigationView}
+ * @see <a href="https://github.com/nextcloud/android-common/pull/71">Upstream Pull Request</a>
+ */
+ public void colorBottomNavigationView(BottomNavigationView bottomNavigationView) {
+ withScheme(bottomNavigationView, scheme -> {
+ bottomNavigationView.setBackgroundColor(scheme.getSurface());
+ bottomNavigationView.setItemIconTintList(buildColorStateList(
+ new Pair<>(android.R.attr.state_checked, scheme.getOnSecondaryContainer()),
+ new Pair<>(-android.R.attr.state_checked, scheme.getOnSurfaceVariant())
+ ));
+ bottomNavigationView.setItemTextColor(buildColorStateList(
+ new Pair<>(android.R.attr.state_checked, scheme.getOnSurface()),
+ new Pair<>(-android.R.attr.state_checked, scheme.getOnSurfaceVariant())
+ ));
+ bottomNavigationView.setItemActiveIndicatorColor(ColorStateList.valueOf(scheme.getSecondaryContainer()));
+
+ return bottomNavigationView;
+ });
+ }
+
+ /**
+ * Convenience method for calling {@link #themeTabLayout(TabLayout, int)} with the primary color
+ */
+ public void themeTabLayout(@NonNull TabLayout tabLayout) {
+ themeTabLayout(tabLayout, ContextCompat.getColor(tabLayout.getContext(), R.color.primary));
+ }
+
+ /**
+ * Themes the <code>tabLayout</code> using {@link MaterialViewThemeUtils#themeTabLayout(TabLayout)}
+ * and then applies <code>backgroundColor</code>.
+ */
+ public void themeTabLayout(@NonNull TabLayout tabLayout, @ColorInt int backgroundColor) {
+ this.material.themeTabLayout(tabLayout);
+ tabLayout.setBackgroundColor(backgroundColor);
+ }
+} \ No newline at end of file
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/DeleteAlertDialogBuilder.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/DeleteAlertDialogBuilder.java
index e769797b4..2b5543e59 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/DeleteAlertDialogBuilder.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/DeleteAlertDialogBuilder.java
@@ -1,4 +1,4 @@
-package it.niedermann.nextcloud.deck.ui.branding;
+package it.niedermann.nextcloud.deck.ui.theme;
import android.content.Context;
import android.content.DialogInterface;
@@ -23,12 +23,12 @@ public class DeleteAlertDialogBuilder extends MaterialAlertDialogBuilder {
@Override
public AlertDialog create() {
this.dialog = super.create();
- applyBrand();
- dialog.setOnShowListener(dialog -> applyBrand());
+ applyTheme();
+ dialog.setOnShowListener(dialog -> applyTheme());
return dialog;
}
- public void applyBrand() {
+ public void applyTheme() {
final var positiveButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
if (positiveButton != null) {
positiveButton.setTextColor(ContextCompat.getColor(getContext(), R.color.danger));
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/ThemeUtils.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/ThemeUtils.java
new file mode 100644
index 000000000..3bd6c6bbf
--- /dev/null
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/ThemeUtils.java
@@ -0,0 +1,81 @@
+package it.niedermann.nextcloud.deck.ui.theme;
+
+import static it.niedermann.nextcloud.deck.DeckApplication.isDarkTheme;
+
+import android.content.Context;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.NonNull;
+import androidx.core.content.ContextCompat;
+import androidx.preference.PreferenceManager;
+
+import com.nextcloud.android.common.ui.color.ColorUtil;
+import com.nextcloud.android.common.ui.theme.MaterialSchemes;
+import com.nextcloud.android.common.ui.theme.ViewThemeUtilsBase;
+import com.nextcloud.android.common.ui.theme.utils.AndroidViewThemeUtils;
+import com.nextcloud.android.common.ui.theme.utils.AndroidXViewThemeUtils;
+import com.nextcloud.android.common.ui.theme.utils.DialogViewThemeUtils;
+import com.nextcloud.android.common.ui.theme.utils.MaterialViewThemeUtils;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import it.niedermann.nextcloud.deck.DeckLog;
+import it.niedermann.nextcloud.deck.R;
+import scheme.Scheme;
+
+public class ThemeUtils extends ViewThemeUtilsBase {
+
+ private static final ConcurrentMap<Integer, ThemeUtils> CACHE = new ConcurrentHashMap<>();
+
+ public final AndroidViewThemeUtils platform;
+ public final MaterialViewThemeUtils material;
+ public final AndroidXViewThemeUtils androidx;
+ public final DialogViewThemeUtils dialog;
+ public final DeckViewThemeUtils deck;
+
+ private ThemeUtils(
+ final MaterialSchemes schemes,
+ final ColorUtil colorUtil
+ ) {
+ super(schemes);
+
+ this.platform = new AndroidViewThemeUtils(schemes, colorUtil);
+ this.material = new MaterialViewThemeUtils(schemes, colorUtil);
+ this.androidx = new AndroidXViewThemeUtils(schemes, this.platform);
+ this.dialog = new DialogViewThemeUtils(schemes);
+ this.deck = new DeckViewThemeUtils(schemes, this.material);
+ }
+
+ public static ThemeUtils of(@ColorInt int color, @NonNull Context context) {
+ return CACHE.computeIfAbsent(color, c -> new ThemeUtils(
+ MaterialSchemes.Companion.fromColor(c),
+ new ColorUtil(context)
+ ));
+ }
+
+ public static Scheme createScheme(@ColorInt int color, @NonNull Context context) {
+ return isDarkTheme(context) ? Scheme.dark(color) : Scheme.light(color);
+ }
+
+ @ColorInt
+ public static int readBrandMainColor(@NonNull Context context) {
+ final var sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext());
+ DeckLog.log("--- Read:", context.getString(R.string.shared_preference_theme_main));
+ return sharedPreferences.getInt(context.getString(R.string.shared_preference_theme_main), ContextCompat.getColor(context, R.color.defaultBrand));
+ }
+
+ public static void saveBrandColors(@NonNull Context context, @ColorInt int color) {
+ final var editor = PreferenceManager.getDefaultSharedPreferences(context).edit();
+ DeckLog.log("--- Write:", context.getString(R.string.shared_preference_theme_main), "|", color);
+ editor.putInt(context.getString(R.string.shared_preference_theme_main), color);
+ editor.apply();
+ }
+
+ public static void clearBrandColors(@NonNull Context context) {
+ final var editor = PreferenceManager.getDefaultSharedPreferences(context).edit();
+ DeckLog.log("--- Remove:", context.getString(R.string.shared_preference_theme_main));
+ editor.remove(context.getString(R.string.shared_preference_theme_main));
+ editor.apply();
+ }
+}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/Themed.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/Themed.java
new file mode 100644
index 000000000..c0cdcc0bf
--- /dev/null
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/Themed.java
@@ -0,0 +1,9 @@
+package it.niedermann.nextcloud.deck.ui.theme;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.UiThread;
+
+public interface Themed {
+ @UiThread
+ void applyTheme(@ColorInt int color);
+} \ No newline at end of file
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedDatePickerDialog.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/ThemedDatePickerDialog.java
index 950fee2e0..6b6a5ddfa 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedDatePickerDialog.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/ThemedDatePickerDialog.java
@@ -1,10 +1,8 @@
-package it.niedermann.nextcloud.deck.ui.branding;
+package it.niedermann.nextcloud.deck.ui.theme;
import static it.niedermann.nextcloud.deck.DeckApplication.isDarkTheme;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.getSecondaryForegroundColorDependingOnTheme;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.readBrandMainColor;
+import static it.niedermann.nextcloud.deck.ui.theme.ThemeUtils.readBrandMainColor;
-import android.graphics.Color;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
@@ -12,38 +10,32 @@ import android.view.ViewGroup;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
-import androidx.core.content.ContextCompat;
import com.wdullaer.materialdatetimepicker.date.DatePickerDialog;
import java.util.Calendar;
-import it.niedermann.nextcloud.deck.R;
-import it.niedermann.nextcloud.deck.util.DeckColorUtil;
+import scheme.Scheme;
-public class BrandedDatePickerDialog extends DatePickerDialog implements Branded {
+public class ThemedDatePickerDialog extends DatePickerDialog implements Themed {
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final var context = requireContext();
setThemeDark(isDarkTheme(context));
- applyBrand(readBrandMainColor(context));
+ applyTheme(readBrandMainColor(context));
return super.onCreateView(inflater, container, savedInstanceState);
}
@Override
- public void applyBrand(int mainColor) {
- @ColorInt final int buttonTextColor = getSecondaryForegroundColorDependingOnTheme(requireContext(), mainColor);
+ public void applyTheme(int color) {
+ final var scheme = ThemeUtils.createScheme(color, requireContext());
+
+ @ColorInt final int buttonTextColor = scheme.getOnPrimaryContainer();
setOkColor(buttonTextColor);
setCancelColor(buttonTextColor);
- setAccentColor(
- DeckColorUtil.contrastRatioIsSufficientBigAreas(Color.WHITE, mainColor)
- ? mainColor
- // Text in picker title is always white (also in dark mode)
- : isThemeDark()
- ? Color.BLACK
- : ContextCompat.getColor(requireContext(), R.color.accent)
- );
+
+ setAccentColor(Scheme.dark(color).getPrimaryContainer());
}
/**
@@ -56,7 +48,7 @@ public class BrandedDatePickerDialog extends DatePickerDialog implements Branded
* @return a new DatePickerDialog instance.
*/
public static DatePickerDialog newInstance(OnDateSetListener callBack, int year, int monthOfYear, int dayOfMonth) {
- final var dialog = new BrandedDatePickerDialog();
+ final var dialog = new ThemedDatePickerDialog();
dialog.initialize(callBack, year, monthOfYear - 1, dayOfMonth);
return dialog;
}
@@ -71,7 +63,7 @@ public class BrandedDatePickerDialog extends DatePickerDialog implements Branded
* @return a new DatePickerDialog instance
*/
public static DatePickerDialog newInstance(OnDateSetListener callback, Calendar initialSelection) {
- final var dialog = new BrandedDatePickerDialog();
+ final var dialog = new ThemedDatePickerDialog();
dialog.initialize(callback, initialSelection);
return dialog;
}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/ThemedDialogFragment.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/ThemedDialogFragment.java
new file mode 100644
index 000000000..8638780f7
--- /dev/null
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/ThemedDialogFragment.java
@@ -0,0 +1,19 @@
+package it.niedermann.nextcloud.deck.ui.theme;
+
+import static it.niedermann.nextcloud.deck.ui.theme.ThemeUtils.readBrandMainColor;
+
+import androidx.annotation.Nullable;
+import androidx.fragment.app.DialogFragment;
+
+public abstract class ThemedDialogFragment extends DialogFragment implements Themed {
+
+ @Override
+ public void onStart() {
+ super.onStart();
+
+ @Nullable final var context = getContext();
+ if (context != null) {
+ applyTheme(readBrandMainColor(context));
+ }
+ }
+}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/ThemedPreferenceCategory.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/ThemedPreferenceCategory.java
new file mode 100644
index 000000000..cb9dd2be1
--- /dev/null
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/ThemedPreferenceCategory.java
@@ -0,0 +1,43 @@
+package it.niedermann.nextcloud.deck.ui.theme;
+
+import static it.niedermann.nextcloud.deck.DeckApplication.readCurrentAccountColor;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceViewHolder;
+
+public class ThemedPreferenceCategory extends PreferenceCategory {
+
+ @Override
+ public void onBindViewHolder(@NonNull PreferenceViewHolder holder) {
+ super.onBindViewHolder(holder);
+
+ final var view = holder.itemView.findViewById(android.R.id.title);
+ @Nullable final Context context = getContext();
+ if (view instanceof TextView) {
+ final var scheme = ThemeUtils.createScheme(readCurrentAccountColor(context), context);
+ ((TextView) view).setTextColor(scheme.getOnPrimaryContainer());
+ }
+ }
+
+ public ThemedPreferenceCategory(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ }
+
+ public ThemedPreferenceCategory(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ public ThemedPreferenceCategory(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public ThemedPreferenceCategory(Context context) {
+ super(context);
+ }
+}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/ThemedSnackbar.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/ThemedSnackbar.java
new file mode 100644
index 000000000..ac6829b12
--- /dev/null
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/ThemedSnackbar.java
@@ -0,0 +1,31 @@
+package it.niedermann.nextcloud.deck.ui.theme;
+
+import static it.niedermann.nextcloud.deck.ui.theme.ThemeUtils.readBrandMainColor;
+
+import android.view.View;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.NonNull;
+import androidx.annotation.StringRes;
+
+import com.google.android.material.snackbar.BaseTransientBottomBar;
+import com.google.android.material.snackbar.Snackbar;
+
+public class ThemedSnackbar {
+
+ @NonNull
+ public static Snackbar make(@NonNull View view, @NonNull CharSequence text, @BaseTransientBottomBar.Duration int duration) {
+ @ColorInt final int color = readBrandMainColor(view.getContext());
+ final var snackbar = Snackbar.make(view, text, duration);
+ final var utils = ThemeUtils.of(color, view.getContext());
+
+ utils.material.themeSnackbar(snackbar);
+
+ return snackbar;
+ }
+
+ @NonNull
+ public static Snackbar make(@NonNull View view, @StringRes int resId, @BaseTransientBottomBar.Duration int duration) {
+ return make(view, view.getResources().getText(resId), duration);
+ }
+} \ No newline at end of file
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/ThemedSwitchPreference.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/ThemedSwitchPreference.java
new file mode 100644
index 000000000..c9cba5b7c
--- /dev/null
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/ThemedSwitchPreference.java
@@ -0,0 +1,89 @@
+package it.niedermann.nextcloud.deck.ui.theme;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Switch;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.Nullable;
+import androidx.preference.PreferenceViewHolder;
+import androidx.preference.SwitchPreference;
+
+public class ThemedSwitchPreference extends SwitchPreference implements Themed {
+
+ @Nullable
+ private ThemeUtils utils = null;
+
+ @SuppressLint("UseSwitchCompatOrMaterialCode")
+ @Nullable
+ private Switch switchView;
+
+ public ThemedSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ }
+
+ public ThemedSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ public ThemedSwitchPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public ThemedSwitchPreference(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder holder) {
+ super.onBindViewHolder(holder);
+
+ if (holder.itemView instanceof ViewGroup) {
+ switchView = findSwitchWidget(holder.itemView);
+ applyTheme();
+ }
+ }
+
+ @Override
+ public void applyTheme(@ColorInt int color) {
+ this.utils = ThemeUtils.of(color, getContext());
+ // onBindViewHolder is called after applyTheme, therefore we have to store the given values and apply them later.
+ applyTheme();
+ }
+
+ private void applyTheme() {
+ if (utils != null && switchView != null) {
+ utils.platform.colorSwitch(switchView);
+ }
+ }
+
+ /**
+ * Recursively go through view tree until we find an android.widget.Switch
+ *
+ * @param view Root view to start searching
+ * @return A Switch class or null
+ * @see <a href="https://gist.github.com/marchold/45e22839eb94aa14dfb5">Source</a>
+ */
+ private Switch findSwitchWidget(View view) {
+ if (view instanceof Switch) {
+ return (Switch) view;
+ }
+ if (view instanceof ViewGroup) {
+ ViewGroup viewGroup = (ViewGroup) view;
+ for (int i = 0; i < viewGroup.getChildCount(); i++) {
+ final var child = viewGroup.getChildAt(i);
+ if (child instanceof ViewGroup) {
+ @SuppressLint("UseSwitchCompatOrMaterialCode") final var result = findSwitchWidget(child);
+ if (result != null) return result;
+ }
+ if (child instanceof Switch) {
+ return (Switch) child;
+ }
+ }
+ }
+ return null;
+ }
+}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedTimePickerDialog.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/ThemedTimePickerDialog.java
index 4a8879f30..3a0ce8561 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedTimePickerDialog.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/theme/ThemedTimePickerDialog.java
@@ -1,11 +1,9 @@
-package it.niedermann.nextcloud.deck.ui.branding;
+package it.niedermann.nextcloud.deck.ui.theme;
import static it.niedermann.nextcloud.deck.DeckApplication.isDarkTheme;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.getSecondaryForegroundColorDependingOnTheme;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.readBrandMainColor;
+import static it.niedermann.nextcloud.deck.ui.theme.ThemeUtils.readBrandMainColor;
import android.content.Context;
-import android.graphics.Color;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
@@ -14,34 +12,34 @@ import android.view.ViewGroup;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.core.content.ContextCompat;
import com.wdullaer.materialdatetimepicker.time.TimePickerDialog;
import java.time.LocalTime;
-import it.niedermann.nextcloud.deck.R;
-import it.niedermann.nextcloud.deck.util.DeckColorUtil;
+import scheme.Scheme;
-public class BrandedTimePickerDialog extends TimePickerDialog implements Branded {
+public class ThemedTimePickerDialog extends TimePickerDialog implements Themed {
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
@Nullable Context context = getContext();
if (context != null) {
setThemeDark(isDarkTheme(context));
- applyBrand(readBrandMainColor(context));
+ applyTheme(readBrandMainColor(context));
}
return super.onCreateView(inflater, container, savedInstanceState);
}
@Override
- public void applyBrand(int mainColor) {
- @ColorInt final int buttonTextColor = getSecondaryForegroundColorDependingOnTheme(requireContext(), mainColor);
+ public void applyTheme(int color) {
+ final var scheme = ThemeUtils.createScheme(color, requireContext());
+
+ @ColorInt final int buttonTextColor = scheme.getOnPrimaryContainer();
setOkColor(buttonTextColor);
setCancelColor(buttonTextColor);
- // Text in picker title is always white
- setAccentColor(DeckColorUtil.contrastRatioIsSufficientBigAreas(Color.WHITE, mainColor) ? mainColor : ContextCompat.getColor(requireContext(), R.color.accent));
+
+ setAccentColor(Scheme.dark(color).getPrimaryContainer());
}
/**
@@ -57,7 +55,7 @@ public class BrandedTimePickerDialog extends TimePickerDialog implements Branded
@SuppressWarnings({"SameParameterValue"})
public static TimePickerDialog newInstance(OnTimeSetListener callback,
int hourOfDay, int minute, int second, boolean is24HourMode) {
- final var dialog = new BrandedTimePickerDialog();
+ final var dialog = new ThemedTimePickerDialog();
dialog.initialize(callback, hourOfDay, minute, second, is24HourMode);
return dialog;
}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/upcomingcards/UpcomingCardsAdapter.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/upcomingcards/UpcomingCardsAdapter.java
index 7f1c64ad6..1df85af63 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/upcomingcards/UpcomingCardsAdapter.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/upcomingcards/UpcomingCardsAdapter.java
@@ -6,7 +6,6 @@ import android.app.Activity;
import android.view.LayoutInflater;
import android.view.ViewGroup;
-import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.FragmentManager;
@@ -32,6 +31,8 @@ import it.niedermann.nextcloud.deck.ui.card.CompactCardViewHolder;
import it.niedermann.nextcloud.deck.ui.card.DefaultCardOnlyTitleViewHolder;
import it.niedermann.nextcloud.deck.ui.card.DefaultCardViewHolder;
import it.niedermann.nextcloud.deck.ui.card.EditActivity;
+import it.niedermann.nextcloud.deck.ui.theme.ThemeUtils;
+import scheme.Scheme;
public class UpcomingCardsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
@@ -44,8 +45,8 @@ public class UpcomingCardsAdapter extends RecyclerView.Adapter<RecyclerView.View
protected List<Object> items = new ArrayList<>();
@NonNull
protected String counterMaxValue;
- @ColorInt
- protected int mainColor;
+ @NonNull
+ protected Scheme scheme;
@NonNull
private final BiConsumer<Account, Card> assignCard;
@NonNull
@@ -64,7 +65,7 @@ public class UpcomingCardsAdapter extends RecyclerView.Adapter<RecyclerView.View
this.activity = activity;
this.counterMaxValue = this.activity.getString(R.string.counter_max_value);
this.fragmentManager = fragmentManager;
- this.mainColor = ContextCompat.getColor(this.activity, R.color.defaultBrand);
+ this.scheme = ThemeUtils.createScheme(ContextCompat.getColor(this.activity, R.color.defaultBrand), this.activity);
this.compactMode = getDefaultSharedPreferences(this.activity).getBoolean(this.activity.getString(R.string.pref_key_compact), false);
this.assignCard = assignCard;
this.unassignCard = unassignCard;
@@ -154,7 +155,7 @@ public class UpcomingCardsAdapter extends RecyclerView.Adapter<RecyclerView.View
unassignCard,
archiveCard,
deleteCard
- ), counterMaxValue, mainColor);
+ ), counterMaxValue, scheme);
cardViewHolder.bindCardClickListener((v) -> activity.startActivity(EditActivity.createEditCardIntent(activity, cardItem.getAccount(), cardItem.getCurrentBoardLocalId(), cardItem.getFullCard().getLocalId())));
} else {
throw new IllegalStateException("Item at position " + position + " is a " + item.getClass().getSimpleName() + " but viewHolder is no " + AbstractCardViewHolder.class.getSimpleName());
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/widget/singlecard/SelectCardForWidgetActivity.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/widget/singlecard/SelectCardForWidgetActivity.java
index c664f1441..ef1451c23 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/widget/singlecard/SelectCardForWidgetActivity.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/widget/singlecard/SelectCardForWidgetActivity.java
@@ -1,6 +1,6 @@
package it.niedermann.nextcloud.deck.ui.widget.singlecard;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.saveBrandColors;
+import static it.niedermann.nextcloud.deck.ui.theme.ThemeUtils.saveBrandColors;
import android.appwidget.AppWidgetManager;
import android.content.Intent;
@@ -15,8 +15,8 @@ import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.model.Board;
import it.niedermann.nextcloud.deck.model.full.FullCard;
import it.niedermann.nextcloud.deck.ui.MainActivity;
-import it.niedermann.nextcloud.deck.ui.branding.BrandingUtil;
import it.niedermann.nextcloud.deck.ui.card.SelectCardListener;
+import it.niedermann.nextcloud.deck.ui.theme.ThemeUtils;
public class SelectCardForWidgetActivity extends MainActivity implements SelectCardListener {
@@ -40,7 +40,7 @@ public class SelectCardForWidgetActivity extends MainActivity implements SelectC
if (appWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
finish();
}
- originalBrandColor = BrandingUtil.readBrandMainColor(this);
+ originalBrandColor = ThemeUtils.readBrandMainColor(this);
}
@Override
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/util/DeckColorUtil.java b/app/src/main/java/it/niedermann/nextcloud/deck/util/DeckColorUtil.java
deleted file mode 100644
index 82a3efd1f..000000000
--- a/app/src/main/java/it/niedermann/nextcloud/deck/util/DeckColorUtil.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package it.niedermann.nextcloud.deck.util;
-
-import androidx.annotation.ColorInt;
-import androidx.annotation.Nullable;
-import androidx.core.util.Pair;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import it.niedermann.android.util.ColorUtil;
-
-public final class DeckColorUtil {
-
- private DeckColorUtil() {
- throw new UnsupportedOperationException("This class must not get instantiated");
- }
-
- private static final Map<ColorPair, Boolean> CONTRAST_RATIO_SUFFICIENT_CACHE = new HashMap<>();
-
- public static boolean contrastRatioIsSufficient(@ColorInt int colorOne, @ColorInt int colorTwo) {
- final var key = new ColorPair(colorOne, colorTwo);
- var ret = CONTRAST_RATIO_SUFFICIENT_CACHE.get(key);
- if (ret == null) {
- ret = ColorUtil.INSTANCE.getContrastRatio(colorOne, colorTwo) > 3d;
- CONTRAST_RATIO_SUFFICIENT_CACHE.put(key, ret);
- return ret;
- }
- return ret;
- }
-
- public static boolean contrastRatioIsSufficientBigAreas(@ColorInt int colorOne, @ColorInt int colorTwo) {
- final var key = new ColorPair(colorOne, colorTwo);
- var ret = CONTRAST_RATIO_SUFFICIENT_CACHE.get(key);
- if (ret == null) {
- ret = ColorUtil.INSTANCE.getContrastRatio(colorOne, colorTwo) > 1.47d;
- CONTRAST_RATIO_SUFFICIENT_CACHE.put(key, ret);
- return ret;
- }
- return ret;
- }
-
- private static class ColorPair extends Pair<Integer, Integer> {
-
- private ColorPair(@Nullable Integer first, @Nullable Integer second) {
- super(first, second);
- }
-
- @SuppressWarnings({"EqualsWhichDoesntCheckParameterClass", "NumberEquality"})
- @Override
- public boolean equals(Object o) {
- final var colorPair = (ColorPair) o;
- if (first != colorPair.first) return false;
- return second == colorPair.second;
- }
-
- @Override
- public int hashCode() {
- int result = first;
- result = 31 * result + second;
- return result;
- }
- }
-}