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
path: root/app
diff options
context:
space:
mode:
authorStefan Niedermann <info@niedermann.it>2020-07-04 20:03:34 +0300
committerStefan Niedermann <info@niedermann.it>2020-07-04 20:03:34 +0300
commit4c7076ca1d5e16918d5074bfb0ce6619d592f3db (patch)
tree51ba4c1522ddcd63513bcaec272ac3cc4ba3a347 /app
parentbb5dcb191e00d6bfcbe14c543feeed963e12ff25 (diff)
parentf302d4ac2de08138064bf1b8aa3863fd3b05a1d0 (diff)
Merge branch 'master' into 561_search_users
# Conflicts: # app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/SyncManager.java
Diffstat (limited to 'app')
-rw-r--r--app/src/main/AndroidManifest.xml26
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/DeckApplication.java (renamed from app/src/main/java/it/niedermann/nextcloud/deck/Application.java)56
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/SyncManager.java344
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/SyncWorker.java33
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/DataBaseAdapter.java90
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/DeckDatabase.java17
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/AccessControlDao.java3
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/AccountDao.java6
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/BoardDao.java3
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/util/LiveDataHelper.java8
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/providers/partial/BoardWitAclDownSyncDataProvider.java32
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/ImportAccountActivity.java10
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/MainActivity.java81
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/MainViewModel.java15
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/PushNotificationActivity.java34
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/about/AboutActivity.java7
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/about/AboutFragmentLicenseTab.java17
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/accountswitcher/AccountSwitcherDialog.java7
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/accountswitcher/AccountSwitcherViewHolder.java3
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/archivedboards/ArchivedBoardsActvitiy.java6
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/archivedcards/ArchivedCardsActvitiy.java4
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/board/EditBoardDialogFragment.java7
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/board/accesscontrol/AccessControlAdapter.java13
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/board/accesscontrol/AccessControlDialogFragment.java8
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/board/managelabels/EditLabelDialogFragment.java7
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/board/managelabels/ManageLabelsAdapter.java11
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/board/managelabels/ManageLabelsDialogFragment.java9
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/Branded.java2
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedActivity.java145
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedAlertDialogBuilder.java14
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedDatePickerDialog.java22
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedDeleteAlertDialogBuilder.java4
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedDialogFragment.java10
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedFragment.java10
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedPreferenceCategory.java9
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedSnackbar.java13
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedSwitchPreference.java20
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedTimePickerDialog.java22
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandingUtil.java128
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/CardAdapter.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/attachments/CardAttachmentAdapter.java3
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/attachments/CardAttachmentsFragment.java6
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/CardCommentsAdapter.java4
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/CardCommentsEditDialogFragment.java7
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/comments/CardCommentsFragment.java10
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/card/details/CardDetailsFragment.java14
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/exception/ExceptionActivity.java6
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/exception/ExceptionDialogFragment.java80
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/exception/tips/TipsAdapter.java92
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/filter/FilterDialogFragment.java7
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/manageaccounts/ManageAccountViewHolder.java3
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/manageaccounts/ManageAccountsActivity.java20
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/preparecreate/PrepareCreateActivity.java70
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/settings/SettingsActivity.java4
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/settings/SettingsFragment.java19
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/sharetarget/ShareProgressDialogFragment.java4
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/stack/EditStackDialogFragment.java8
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/stack/StackFragment.java4
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/view/OverlappingAvatars.java2
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/ui/widget/singlecard/SelectCardForWidgetActivity.java7
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/util/ColorUtil.java13
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/util/ViewUtil.java5
-rw-r--r--app/src/main/res/drawable/ic_arrow_back_white_24dp.xml4
-rw-r--r--app/src/main/res/drawable/ic_baseline_account_circle_24.xml6
-rw-r--r--app/src/main/res/drawable/ic_check_white_24dp.xml2
-rw-r--r--app/src/main/res/drawable/ic_close_white_24dp.xml2
-rw-r--r--app/src/main/res/drawable/selected.xml2
-rw-r--r--app/src/main/res/drawable/splash_screen.xml2
-rw-r--r--app/src/main/res/layout/activity_about.xml9
-rw-r--r--app/src/main/res/layout/activity_archived.xml1
-rw-r--r--app/src/main/res/layout/activity_attachments.xml1
-rw-r--r--app/src/main/res/layout/activity_edit.xml27
-rw-r--r--app/src/main/res/layout/activity_exception.xml63
-rw-r--r--app/src/main/res/layout/activity_import_account.xml5
-rw-r--r--app/src/main/res/layout/activity_main.xml18
-rw-r--r--app/src/main/res/layout/activity_manage_accounts.xml4
-rw-r--r--app/src/main/res/layout/activity_prepare_create.xml9
-rw-r--r--app/src/main/res/layout/activity_push_notification.xml3
-rw-r--r--app/src/main/res/layout/activity_settings.xml3
-rw-r--r--app/src/main/res/layout/dialog_board_manage_labels.xml2
-rw-r--r--app/src/main/res/layout/dialog_filter.xml3
-rw-r--r--app/src/main/res/layout/fragment_about_license_tab.xml4
-rw-r--r--app/src/main/res/layout/fragment_card_edit_tab_attachments.xml2
-rw-r--r--app/src/main/res/layout/fragment_card_edit_tab_comments.xml2
-rw-r--r--app/src/main/res/layout/item_autocomplete_label.xml7
-rw-r--r--app/src/main/res/layout/item_card.xml3
-rw-r--r--app/src/main/res/layout/item_comment.xml2
-rw-r--r--app/src/main/res/layout/item_manage_label.xml5
-rw-r--r--app/src/main/res/layout/item_tip.xml1
-rw-r--r--app/src/main/res/layout/nav_header_main.xml3
-rw-r--r--app/src/main/res/values-night/booleans.xml4
-rw-r--r--app/src/main/res/values-night/colors.xml5
-rw-r--r--app/src/main/res/values-v23/styles.xml7
-rw-r--r--app/src/main/res/values-v27/styles.xml17
-rw-r--r--app/src/main/res/values/attrs.xml2
-rw-r--r--app/src/main/res/values/booleans.xml4
-rw-r--r--app/src/main/res/values/colors.xml9
-rw-r--r--app/src/main/res/values/setup.xml1
-rw-r--r--app/src/main/res/values/strings.xml2
-rw-r--r--app/src/main/res/values/styles.xml34
101 files changed, 1206 insertions, 749 deletions
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 132beb6ce..ce4530d5d 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -9,7 +9,7 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
- android:name="it.niedermann.nextcloud.deck.Application"
+ android:name="it.niedermann.nextcloud.deck.DeckApplication"
android:allowBackup="true"
android:fullBackupContent="false"
android:hardwareAccelerated="true"
@@ -70,20 +70,17 @@
<activity
android:name=".ui.archivedcards.ArchivedCardsActvitiy"
android:label="@string/archived_cards"
- android:parentActivityName="it.niedermann.nextcloud.deck.ui.MainActivity"
- android:theme="@style/AppTheme" />
+ android:parentActivityName="it.niedermann.nextcloud.deck.ui.MainActivity" />
<activity
android:name=".ui.archivedboards.ArchivedBoardsActvitiy"
android:label="@string/archived_boards"
- android:parentActivityName="it.niedermann.nextcloud.deck.ui.MainActivity"
- android:theme="@style/AppTheme" />
+ android:parentActivityName="it.niedermann.nextcloud.deck.ui.MainActivity" />
<activity
android:name=".ui.card.EditActivity"
android:label="@string/edit"
- android:parentActivityName="it.niedermann.nextcloud.deck.ui.MainActivity"
- android:theme="@style/AppTheme" />
+ android:parentActivityName="it.niedermann.nextcloud.deck.ui.MainActivity" />
<activity
android:name=".ui.attachments.AttachmentsActivity"
@@ -94,19 +91,16 @@
<activity
android:name=".ui.settings.SettingsActivity"
android:label="@string/simple_settings"
- android:parentActivityName="it.niedermann.nextcloud.deck.ui.MainActivity"
- android:theme="@style/AppTheme" />
+ android:parentActivityName="it.niedermann.nextcloud.deck.ui.MainActivity" />
<activity
android:name=".ui.ImportAccountActivity"
- android:label="@string/app_name"
- android:theme="@style/AppTheme" />
+ android:label="@string/app_name" />
<activity
android:name=".ui.preparecreate.PrepareCreateActivity"
android:description="@string/add_a_new_card_using_the_button"
- android:label="@string/add_card"
- android:theme="@style/AppTheme">
+ android:label="@string/add_card" >
<intent-filter>
<action android:name="android.intent.action.SEND" />
@@ -118,13 +112,11 @@
<activity
android:name=".ui.about.AboutActivity"
android:label="@string/about"
- android:parentActivityName="it.niedermann.nextcloud.deck.ui.MainActivity"
- android:theme="@style/AppTheme" />
+ android:parentActivityName="it.niedermann.nextcloud.deck.ui.MainActivity" />
<activity
android:name=".ui.PushNotificationActivity"
- android:label="@string/app_name"
- android:theme="@style/AppTheme">
+ android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/Application.java b/app/src/main/java/it/niedermann/nextcloud/deck/DeckApplication.java
index 6fbf7c8a2..ff492c226 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/Application.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/DeckApplication.java
@@ -1,23 +1,20 @@
package it.niedermann.nextcloud.deck;
+import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
-import android.graphics.Color;
-import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.preference.PreferenceManager;
import com.jakewharton.threetenabp.AndroidThreeTen;
-import it.niedermann.nextcloud.deck.ui.branding.BrandedActivity;
-
import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO;
import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES;
import static androidx.appcompat.app.AppCompatDelegate.setDefaultNightMode;
import static androidx.multidex.MultiDex.install;
-public class Application extends android.app.Application {
+public class DeckApplication extends Application {
public static final long NO_ACCOUNT_ID = -1L;
public static final long NO_BOARD_ID = -1L;
@@ -25,7 +22,7 @@ public class Application extends android.app.Application {
@Override
public void onCreate() {
- setAppTheme(getAppTheme(getApplicationContext()));
+ setAppTheme(isDarkTheme(getApplicationContext()));
super.onCreate();
AndroidThreeTen.init(this);
}
@@ -48,56 +45,11 @@ public class Application extends android.app.Application {
setDefaultNightMode(darkTheme ? MODE_NIGHT_YES : MODE_NIGHT_NO);
}
- public static boolean getAppTheme(@NonNull Context context) {
+ public static boolean isDarkTheme(@NonNull Context context) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
return prefs.getBoolean(context.getString(R.string.pref_key_dark_theme), false);
}
- // --------
- // Branding
- // --------
-
- public static boolean isBrandingEnabled(@NonNull Context context) {
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
- return prefs.getBoolean(context.getString(R.string.pref_key_branding), true);
- }
-
- @ColorInt
- public static int readBrandMainColor(@NonNull Context context) {
- if (Application.isBrandingEnabled(context)) {
- SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext());
- DeckLog.log("--- Read: shared_preference_theme_main");
- return sharedPreferences.getInt(context.getString(R.string.shared_preference_theme_main), context.getApplicationContext().getResources().getColor(R.color.primary));
- } else {
- return context.getResources().getColor(R.color.primary);
- }
- }
-
- @ColorInt
- public static int readBrandTextColor(@NonNull Context context) {
- if (isBrandingEnabled(context)) {
- SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext());
- DeckLog.log("--- Read: shared_preference_theme_text");
- return sharedPreferences.getInt(context.getString(R.string.shared_preference_theme_text), context.getApplicationContext().getResources().getColor(android.R.color.white));
- } else {
- return Color.WHITE;
- }
- }
-
- public static void saveBrandColors(@NonNull Context context, @ColorInt int mainColor, @ColorInt int textColor) {
- if (isBrandingEnabled(context) && context instanceof BrandedActivity) {
- final BrandedActivity activity = (BrandedActivity) context;
- activity.applyBrand(mainColor, textColor);
- BrandedActivity.applyBrandToStatusbar(activity.getWindow(), mainColor, textColor);
- }
- SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(context).edit();
- DeckLog.log("--- Write: shared_preference_theme_main" + " | " + mainColor);
- DeckLog.log("--- Write: shared_preference_theme_text" + " | " + textColor);
- editor.putInt(context.getString(R.string.shared_preference_theme_main), mainColor);
- editor.putInt(context.getString(R.string.shared_preference_theme_text), textColor);
- editor.apply();
- }
-
// --------------------------------------
// Current account / board / stack states
// --------------------------------------
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/SyncManager.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/SyncManager.java
index 735436f64..0f9845dee 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/SyncManager.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/SyncManager.java
@@ -3,6 +3,7 @@ package it.niedermann.nextcloud.deck.persistence.sync;
import android.content.Context;
import android.database.sqlite.SQLiteConstraintException;
+import androidx.annotation.AnyThread;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
@@ -65,6 +66,7 @@ import it.niedermann.nextcloud.deck.persistence.sync.helpers.providers.CardPropa
import it.niedermann.nextcloud.deck.persistence.sync.helpers.providers.DeckCommentsDataProvider;
import it.niedermann.nextcloud.deck.persistence.sync.helpers.providers.LabelDataProvider;
import it.niedermann.nextcloud.deck.persistence.sync.helpers.providers.StackDataProvider;
+import it.niedermann.nextcloud.deck.persistence.sync.helpers.providers.partial.BoardWitAclDownSyncDataProvider;
import it.niedermann.nextcloud.deck.util.DateUtil;
import static java.net.HttpURLConnection.HTTP_UNAVAILABLE;
@@ -79,10 +81,12 @@ public class SyncManager {
@NonNull
private ServerAdapter serverAdapter;
+ @AnyThread
public SyncManager(@NonNull Context context) {
this(context, null);
}
+ @AnyThread
public SyncManager(@NonNull Context context, @Nullable String ssoAccountName) {
appContext = context.getApplicationContext();
LastSyncUtil.init(appContext);
@@ -90,11 +94,13 @@ public class SyncManager {
this.serverAdapter = new ServerAdapter(appContext, ssoAccountName);
}
- private void doAsync(Runnable r) {
+ @AnyThread
+ private void doAsync(@NonNull Runnable r) {
new Thread(r).start();
}
- public MutableLiveData<FullCard> synchronizeCardByRemoteId(long cardRemoteId, Account account) {
+ @AnyThread
+ public MutableLiveData<FullCard> synchronizeCardByRemoteId(long cardRemoteId, @NonNull Account account) {
MutableLiveData<FullCard> liveData = new MutableLiveData<>();
doAsync(() -> {
Long accountId = account.getId();
@@ -120,10 +126,12 @@ public class SyncManager {
}
// TODO if the card does not exist yet, try to synchronize it first, instead of directly returning null. If sync failed, return null.
- public LiveData<Long> getLocalBoardIdByCardRemoteIdAndAccount(long cardRemoteId, Account account) {
+ @AnyThread
+ public LiveData<Long> getLocalBoardIdByCardRemoteIdAndAccount(long cardRemoteId, @NonNull Account account) {
return dataBaseAdapter.getLocalBoardIdByCardRemoteIdAndAccountId(cardRemoteId, account.getId());
}
+ @AnyThread
public boolean synchronizeEverything() {
List<Account> accounts = dataBaseAdapter.getAllAccountsDirectly();
if (accounts.size() > 0) {
@@ -156,11 +164,13 @@ public class SyncManager {
return true;
}
- public void synchronize(IResponseCallback<Boolean> responseCallback) {
- if (responseCallback == null ||
- responseCallback.getAccount() == null ||
- responseCallback.getAccount().getId() == null) {
- throw new IllegalArgumentException("please provide an account ID.");
+ @AnyThread
+ public void synchronize(@NonNull IResponseCallback<Boolean> responseCallback) {
+ if(responseCallback.getAccount() == null) {
+ throw new IllegalArgumentException(Account.class.getSimpleName() + " object in given " + IResponseCallback.class.getSimpleName() + " must not be null.");
+ }
+ if(responseCallback.getAccount().getId() == null) {
+ throw new IllegalArgumentException(Account.class.getSimpleName() + " object in given " + IResponseCallback.class.getSimpleName() + " must contain a valid id, but given id was null.");
}
doAsync(() -> refreshCapabilities(new IResponseCallback<Capabilities>(responseCallback.getAccount()) {
@Override
@@ -260,11 +270,13 @@ public class SyncManager {
// return remoteEntity;
// }
+ @AnyThread
public LiveData<Boolean> hasAccounts() {
return dataBaseAdapter.hasAccounts();
}
- public WrappedLiveData<Account> createAccount(Account accout) {
+ @AnyThread
+ public WrappedLiveData<Account> createAccount(@NonNull Account accout) {
return dataBaseAdapter.createAccount(accout);
}
@@ -283,14 +295,17 @@ public class SyncManager {
dataBaseAdapter.updateAccount(account);
}
+ @AnyThread
public LiveData<Account> readAccount(long id) {
return dataBaseAdapter.readAccount(id);
}
- public LiveData<Account> readAccount(String name) {
+ @AnyThread
+ public LiveData<Account> readAccount(@Nullable String name) {
return dataBaseAdapter.readAccount(name);
}
+ @AnyThread
public LiveData<List<Account>> readAccounts() {
return dataBaseAdapter.readAccounts();
}
@@ -307,11 +322,29 @@ public class SyncManager {
* - located at the given {@param host}
* - and have the permission to read the board with the given {@param boardRemoteId} (aka the {@link Board} is shared with this {@link User}).
*/
+ @AnyThread
public LiveData<List<Account>> readAccountsForHostWithReadAccessToBoard(String host, long boardRemoteId) {
- throw new UnsupportedOperationException("Not yet implemented");
+ MediatorLiveData<List<Account>> liveData = new MediatorLiveData<>();
+ liveData.addSource(dataBaseAdapter.readAccountsForHostWithReadAccessToBoard(host, boardRemoteId), accounts -> {
+ liveData.postValue(accounts);
+ doAsync(() -> {
+ for (Account account : accounts) {
+ new SyncHelper(serverAdapter, dataBaseAdapter, null)
+ .setResponseCallback(new IResponseCallback<Boolean>(account) {
+ @Override
+ public void onResponse(Boolean response) {
+ liveData.postValue(dataBaseAdapter.readAccountsForHostWithReadAccessToBoardDirectly(host, boardRemoteId));
+ }
+ }).doSyncFor(new BoardWitAclDownSyncDataProvider());
+ }
+ });
+ });
+
+ return liveData;
}
- public void refreshCapabilities(IResponseCallback<Capabilities> callback) {
+ @AnyThread
+ public void refreshCapabilities(@NonNull IResponseCallback<Capabilities> callback) {
doAsync(() -> {
try {
serverAdapter.getCapabilities(new IResponseCallback<Capabilities>(callback.getAccount()) {
@@ -354,6 +387,7 @@ public class SyncManager {
* @param archived Decides whether only archived or not-archived boards for the specified account will be returned
* @return all archived or non-archived <code>Board</code>s depending on <code>archived</code> parameter
*/
+ @AnyThread
public LiveData<List<Board>> getBoards(long accountId, boolean archived) {
return dataBaseAdapter.getBoards(accountId, archived);
}
@@ -363,6 +397,7 @@ public class SyncManager {
* @param archived Decides whether only archived or not-archived boards for the specified account will be returned
* @return all archived or non-archived <code>FullBoard</code>s depending on <code>archived</code> parameter
*/
+ @AnyThread
public LiveData<List<FullBoard>> getFullBoards(long accountId, boolean archived) {
return dataBaseAdapter.getFullBoards(accountId, archived);
}
@@ -373,15 +408,18 @@ public class SyncManager {
* @param accountId ID of the account
* @return all non-archived <code>Board</code>s with edit permission
*/
+ @AnyThread
public LiveData<List<Board>> getBoardsWithEditPermission(long accountId) {
return dataBaseAdapter.getBoardsWithEditPermission(accountId);
}
+ @AnyThread
public LiveData<Boolean> hasArchivedBoards(long accountId) {
return dataBaseAdapter.hasArchivedBoards(accountId);
}
- public LiveData<FullBoard> createBoard(long accountId, Board board) {
+ @AnyThread
+ public LiveData<FullBoard> createBoard(long accountId, @NonNull Board board) {
MutableLiveData<FullBoard> liveData = new MutableLiveData<>();
doAsync(() -> {
Account account = dataBaseAdapter.getAccountByIdDirectly(accountId);
@@ -412,11 +450,62 @@ public class SyncManager {
* Owner of the target {@link Board} will be the {@link User} with the {@link Account} of {@param targetAccountId}.
* Does <strong>not</strong> clone any {@link Card} or {@link AccessControl} from the origin {@link Board}.
*/
- public LiveData<FullBoard> cloneBoard(long originAccountId, long originBoardLocalId, long targetAccountId, String targetBoardTitle, String targetBoardColor) {
- throw new UnsupportedOperationException("Not yet implemented");
+ @AnyThread
+ public WrappedLiveData<FullBoard> cloneBoard(long originAccountId, long originBoardLocalId, long targetAccountId, String targetBoardTitle, String targetBoardColor) {
+ WrappedLiveData<FullBoard> liveData = new WrappedLiveData<>();
+
+ doAsync(() -> {
+ Account originAccount = dataBaseAdapter.getAccountByIdDirectly(originAccountId);
+ User newOwner = dataBaseAdapter.getUserByUidDirectly(originAccountId, originAccount.getUserName());
+ FullBoard originalBoard = dataBaseAdapter.getFullBoardByLocalIdDirectly(originAccountId, originBoardLocalId);
+ originalBoard.setAccountId(targetAccountId);
+ originalBoard.getBoard().setTitle(targetBoardTitle);
+ originalBoard.getBoard().setColor(targetBoardColor);
+ originalBoard.getBoard().setOwnerId(newOwner.getId());
+ originalBoard.setStatusEnum(DBStatus.LOCAL_EDITED);
+ originalBoard.setOwner(newOwner);
+ originalBoard.setId(null);
+ originalBoard.setLocalId(null);
+ long newBoardId = dataBaseAdapter.createBoardDirectly(originAccountId, originalBoard.getBoard());
+ originalBoard.setLocalId(newBoardId);
+
+ for (Stack stack : originalBoard.getStacks()) {
+ stack.setLocalId(null);
+ stack.setId(null);
+ stack.setStatusEnum(DBStatus.LOCAL_EDITED);
+ stack.setAccountId(targetAccountId);
+ stack.setBoardId(newBoardId);
+ dataBaseAdapter.createStack(targetAccountId, stack);
+ }
+ for (Label label : originalBoard.getLabels()) {
+ label.setLocalId(null);
+ label.setId(null);
+ label.setAccountId(targetAccountId);
+ label.setStatusEnum(DBStatus.LOCAL_EDITED);
+ label.setBoardId(newBoardId);
+ dataBaseAdapter.createLabel(targetAccountId, label);
+ }
+ Account targetAccount = dataBaseAdapter.getAccountByIdDirectly(targetAccountId);
+ new SyncHelper(serverAdapter, dataBaseAdapter, null)
+ .setResponseCallback(new IResponseCallback<Boolean>(targetAccount) {
+ @Override
+ public void onResponse(Boolean response) {
+ liveData.postValue(dataBaseAdapter.getFullBoardByLocalIdDirectly(targetAccountId, newBoardId));
+ }
+
+ @Override
+ public void onError(Throwable throwable) {
+ super.onError(throwable);
+ liveData.postError(throwable);
+ }
+ }).doSyncFor(new BoardDataProvider());
+
+ });
+ return liveData;
}
- public LiveData<List<it.niedermann.nextcloud.deck.model.ocs.Activity>> syncActivitiesForCard(Card card) {
+ @AnyThread
+ public LiveData<List<it.niedermann.nextcloud.deck.model.ocs.Activity>> syncActivitiesForCard(@NonNull Card card) {
doAsync(() -> {
if (serverAdapter.hasInternetConnection()) {
if (card.getId() != null) {
@@ -435,7 +524,8 @@ public class SyncManager {
return dataBaseAdapter.getActivitiesForCard(card.getLocalId());
}
- public void addCommentToCard(long accountId, long cardId, DeckComment comment) {
+ @AnyThread
+ public void addCommentToCard(long accountId, long cardId, @NonNull DeckComment comment) {
doAsync(() -> {
Account account = dataBaseAdapter.getAccountByIdDirectly(accountId);
Card card = dataBaseAdapter.getCardByLocalIdDirectly(accountId, cardId);
@@ -449,6 +539,7 @@ public class SyncManager {
});
}
+ @AnyThread
public void updateComment(long accountId, long localCardId, long localCommentId, String comment) {
doAsync(() -> {
Account account = dataBaseAdapter.getAccountByIdDirectly(accountId);
@@ -465,6 +556,7 @@ public class SyncManager {
});
}
+ @AnyThread
public WrappedLiveData<Void> deleteComment(long accountId, long localCardId, long localCommentId) {
WrappedLiveData<Void> liveData = new WrappedLiveData<>();
doAsync(() -> {
@@ -482,7 +574,8 @@ public class SyncManager {
return dataBaseAdapter.getFullCommentsForLocalCardId(localCardId);
}
- public WrappedLiveData<Void> deleteBoard(Board board) {
+ @AnyThread
+ public WrappedLiveData<Void> deleteBoard(@NonNull Board board) {
WrappedLiveData<Void> liveData = new WrappedLiveData<>();
doAsync(() -> {
long accountId = board.getAccountId();
@@ -493,7 +586,8 @@ public class SyncManager {
return liveData;
}
- public WrappedLiveData<FullBoard> updateBoard(FullBoard board) {
+ @AnyThread
+ public WrappedLiveData<FullBoard> updateBoard(@NonNull FullBoard board) {
WrappedLiveData<FullBoard> liveData = new WrappedLiveData<>();
long accountId = board.getAccountId();
doAsync(() -> {
@@ -521,6 +615,7 @@ public class SyncManager {
return dataBaseAdapter.getStack(accountId, localStackId);
}
+ @AnyThread
public WrappedLiveData<AccessControl> createAccessControl(long accountId, AccessControl entity) {
WrappedLiveData<AccessControl> liveData = new WrappedLiveData<>();
doAsync(() -> {
@@ -537,6 +632,7 @@ public class SyncManager {
return liveData;
}
+ @WorkerThread
public AccessControl getAccessControlByRemoteIdDirectly(long accountId, Long id) {
return dataBaseAdapter.getAccessControlByRemoteIdDirectly(accountId, id);
}
@@ -545,7 +641,8 @@ public class SyncManager {
return dataBaseAdapter.getAccessControlByLocalBoardId(accountId, id);
}
- public WrappedLiveData<AccessControl> updateAccessControl(AccessControl entity) {
+ @AnyThread
+ public WrappedLiveData<AccessControl> updateAccessControl(@NonNull AccessControl entity) {
WrappedLiveData<AccessControl> liveData = new WrappedLiveData<>();
doAsync(() -> {
Account account = dataBaseAdapter.getAccountByIdDirectly(entity.getAccountId());
@@ -556,7 +653,8 @@ public class SyncManager {
return liveData;
}
- private <T> IResponseCallback<T> getCallbackToLiveDataConverter(Account account, WrappedLiveData<T> liveData) {
+ @AnyThread
+ private <T> IResponseCallback<T> getCallbackToLiveDataConverter(Account account, @NonNull WrappedLiveData<T> liveData) {
return new IResponseCallback<T>(account) {
@Override
public void onResponse(T response) {
@@ -570,7 +668,8 @@ public class SyncManager {
};
}
- public WrappedLiveData<Void> deleteAccessControl(AccessControl entity) {
+ @AnyThread
+ public WrappedLiveData<Void> deleteAccessControl(@NonNull AccessControl entity) {
WrappedLiveData<Void> liveData = new WrappedLiveData<>();
doAsync(() -> {
Account account = dataBaseAdapter.getAccountByIdDirectly(entity.getAccountId());
@@ -599,8 +698,8 @@ public class SyncManager {
return dataBaseAdapter.getFullBoardById(accountId, localId);
}
-
- public WrappedLiveData<FullStack> createStack(long accountId, Stack stack) {
+ @AnyThread
+ public WrappedLiveData<FullStack> createStack(long accountId, @NonNull Stack stack) {
WrappedLiveData<FullStack> liveData = new WrappedLiveData<>();
doAsync(() -> {
Account account = dataBaseAdapter.getAccountByIdDirectly(accountId);
@@ -616,6 +715,7 @@ public class SyncManager {
return liveData;
}
+ @AnyThread
public WrappedLiveData<Void> deleteStack(long accountId, long stackLocalId, long boardLocalId) {
WrappedLiveData<Void> liveData = new WrappedLiveData<>();
doAsync(() -> {
@@ -627,7 +727,8 @@ public class SyncManager {
return liveData;
}
- public WrappedLiveData<FullStack> updateStack(FullStack stack) {
+ @AnyThread
+ public WrappedLiveData<FullStack> updateStack(@NonNull FullStack stack) {
WrappedLiveData<FullStack> liveData = new WrappedLiveData<>();
doAsync(() -> {
Account account = dataBaseAdapter.getAccountByIdDirectly(stack.getAccountId());
@@ -638,6 +739,7 @@ public class SyncManager {
}
+ @AnyThread
private void updateStack(@NonNull Account account, @NonNull FullBoard board, @NonNull FullStack stack, @Nullable WrappedLiveData<FullStack> liveData) {
doAsync(() -> {
new DataPropagationHelper(serverAdapter, dataBaseAdapter).updateEntity(new StackDataProvider(null, board), stack, new IResponseCallback<FullStack>(account) {
@@ -663,6 +765,7 @@ public class SyncManager {
*
* @param stackLocalIds The first item of the pair will be updated first
*/
+ @AnyThread
public void swapStackOrder(long accountId, long boardLocalId, @NonNull Pair<Long, Long> stackLocalIds) {
if (stackLocalIds.first == null || stackLocalIds.second == null) {
throw new IllegalArgumentException("Given stackLocalIds must not be null");
@@ -733,8 +836,8 @@ public class SyncManager {
// return liveData;
// }
- public LiveData<FullCard> createFullCard(long accountId, long localBoardId, long localStackId, FullCard card) {
-
+ @AnyThread
+ public LiveData<FullCard> createFullCard(long accountId, long localBoardId, long localStackId, @NonNull FullCard card) {
MutableLiveData<FullCard> liveData = new MutableLiveData<>();
doAsync(() -> {
Account account = dataBaseAdapter.getAccountByIdDirectly(accountId);
@@ -782,7 +885,8 @@ public class SyncManager {
return liveData;
}
- public WrappedLiveData<Void> deleteCard(Card card) {
+ @AnyThread
+ public WrappedLiveData<Void> deleteCard(@NonNull Card card) {
WrappedLiveData<Void> liveData = new WrappedLiveData<>();
doAsync(() -> {
FullCard fullCard = dataBaseAdapter.getFullCardByLocalIdDirectly(card.getAccountId(), card.getLocalId());
@@ -797,7 +901,8 @@ public class SyncManager {
return liveData;
}
- public WrappedLiveData<FullCard> archiveCard(FullCard card) {
+ @AnyThread
+ public WrappedLiveData<FullCard> archiveCard(@NonNull FullCard card) {
WrappedLiveData<FullCard> liveData = new WrappedLiveData<>();
doAsync(() -> {
Account account = dataBaseAdapter.getAccountByIdDirectly(card.getAccountId());
@@ -809,11 +914,12 @@ public class SyncManager {
return liveData;
}
- private void updateCardForArchive(Account account, FullStack stack, Board board, FullCard card, IResponseCallback<FullCard> callback) {
+ private void updateCardForArchive(Account account, FullStack stack, Board board, FullCard card, @NonNull IResponseCallback<FullCard> callback) {
new DataPropagationHelper(serverAdapter, dataBaseAdapter).updateEntity(new CardDataProvider(null, board, stack), card, callback);
}
- public WrappedLiveData<FullCard> dearchiveCard(FullCard card) {
+ @AnyThread
+ public WrappedLiveData<FullCard> dearchiveCard(@NonNull FullCard card) {
WrappedLiveData<FullCard> liveData = new WrappedLiveData<>();
doAsync(() -> {
Account account = dataBaseAdapter.getAccountByIdDirectly(card.getAccountId());
@@ -825,6 +931,7 @@ public class SyncManager {
return liveData;
}
+ @AnyThread
public WrappedLiveData<Void> archiveCardsInStack(long accountId, long stackLocalId) {
WrappedLiveData<Void> liveData = new WrappedLiveData<>();
doAsync(() -> {
@@ -862,7 +969,8 @@ public class SyncManager {
return liveData;
}
- public void archiveBoard(Board board) {
+ @AnyThread
+ public void archiveBoard(@NonNull Board board) {
doAsync(() -> {
FullBoard b = dataBaseAdapter.getFullBoardByLocalIdDirectly(board.getAccountId(), board.getLocalId());
b.getBoard().setArchived(true);
@@ -870,7 +978,8 @@ public class SyncManager {
});
}
- public void dearchiveBoard(Board board) {
+ @AnyThread
+ public void dearchiveBoard(@NonNull Board board) {
doAsync(() -> {
FullBoard b = dataBaseAdapter.getFullBoardByLocalIdDirectly(board.getAccountId(), board.getLocalId());
b.getBoard().setArchived(false);
@@ -878,7 +987,8 @@ public class SyncManager {
});
}
- public WrappedLiveData<FullCard> updateCard(FullCard card) {
+ @AnyThread
+ public WrappedLiveData<FullCard> updateCard(@NonNull FullCard card) {
WrappedLiveData<FullCard> liveData = new WrappedLiveData<>();
doAsync(() -> {
FullCard fullCardFromDB = dataBaseAdapter.getFullCardByLocalIdDirectly(card.getAccountId(), card.getLocalId());
@@ -934,6 +1044,7 @@ public class SyncManager {
/**
* Moves the given {@param originCardLocalId} to the new target coordinates specified by {@param targetAccountId}, {@param targetBoardLocalId} and {@param targetStackLocalId}.
* If the {@param targetBoardLocalId} changes, this will apply some logic to make sure that we migrate as much data as possible without the risk of getting an illegal state.
+ * Attachments are not copied or anything.
* <p>
* 1) {@link FullCard#labels}
* <p>
@@ -951,10 +1062,130 @@ public class SyncManager {
* https://github.com/stefan-niedermann/nextcloud-deck/issues/453
*/
@SuppressWarnings("JavadocReference")
+ @AnyThread
public WrappedLiveData<Void> moveCard(long originAccountId, long originCardLocalId, long targetAccountId, long targetBoardLocalId, long targetStackLocalId) {
- throw new UnsupportedOperationException("Not yet implemented");
+ return LiveDataHelper.wrapInLiveData(() -> {
+
+ FullCard originalCard = dataBaseAdapter.getFullCardByLocalIdDirectly(originAccountId, originCardLocalId);
+ int newIndex = dataBaseAdapter.getHighestCardOrderInStack(targetStackLocalId) + 1;
+ FullBoard originalBoard = dataBaseAdapter.getFullBoardByLocalCardIdDirectly(originCardLocalId);
+ // ### maybe shortcut possible? (just moved to another stack)
+ if (targetBoardLocalId == originalBoard.getLocalId()) {
+ reorder(originAccountId, originalCard, targetStackLocalId, newIndex);
+ return null;
+ }
+ // ### get rid of original card where it is now.
+ Card originalInnerCard = originalCard.getCard();
+ deleteCard(originalInnerCard);
+ // ### clone card itself
+ Card targetCard = originalInnerCard;
+ targetCard.setAccountId(targetAccountId);
+ targetCard.setId(null);
+ targetCard.setLocalId(null);
+ targetCard.setStatusEnum(DBStatus.LOCAL_EDITED);
+ targetCard.setStackId(targetStackLocalId);
+ targetCard.setOrder(newIndex);
+ //TODO: this needs to propagate to server as well, since anything else propagates as well (otherwise card isn't known on server)
+ FullCard fullCardForServerPropagation = new FullCard();
+ fullCardForServerPropagation.setCard(targetCard);
+
+ Account targetAccount = dataBaseAdapter.getAccountByIdDirectly(targetAccountId);
+ FullBoard targetBoard = dataBaseAdapter.getFullBoardByLocalIdDirectly(targetAccountId, targetBoardLocalId);
+ FullStack targetFullStack = dataBaseAdapter.getFullStackByLocalIdDirectly(targetStackLocalId);
+ User userOfTargetAccount = dataBaseAdapter.getUserByUidDirectly(targetAccountId, targetAccount.getUserName());
+ CountDownLatch latch = new CountDownLatch(1);
+ new DataPropagationHelper(serverAdapter, dataBaseAdapter).createEntity(new CardPropagationDataProvider(null, targetBoard.getBoard(), targetFullStack), fullCardForServerPropagation, new IResponseCallback<FullCard>(targetAccount) {
+ @Override
+ public void onResponse(FullCard response) {
+ targetCard.setId(response.getId());
+ targetCard.setLocalId(response.getLocalId());
+ latch.countDown();
+ }
+
+ @Override
+ public void onError(Throwable throwable) {
+ super.onError(throwable);
+ throw new RuntimeException("unable to create card in moveCard target", throwable);
+ }
+ }, (FullCard entity, FullCard response) -> {
+ response.getCard().setUserId(entity.getCard().getUserId());
+ response.getCard().setStackId(targetFullStack.getLocalId());
+ });
+
+ try {
+ latch.await();
+ } catch (InterruptedException e) {
+ DeckLog.logError(e);
+ throw new RuntimeException("error fulfilling countDownLatch", e);
+ }
+
+ long newCardId = targetCard.getLocalId();
+
+ // ### clone labels, assign them
+ // prepare
+ // has user of targetaccount manage permissions?
+ boolean hasManagePermission = targetBoard.getBoard().getOwnerId() == userOfTargetAccount.getLocalId();
+ List<AccessControl> aclOfTargetBoard = dataBaseAdapter.getAccessControlByLocalBoardIdDirectly(targetAccountId, targetBoard.getLocalId());
+ if (!hasManagePermission) {
+ for (AccessControl accessControl : aclOfTargetBoard) {
+ if (accessControl.getUserId() == userOfTargetAccount.getLocalId() && accessControl.isPermissionManage()) {
+ hasManagePermission = true;
+ break;
+ }
+ }
+ }
+
+ // actual doing
+ for (Label originalLabel : originalCard.getLabels()) {
+ // already exists?
+ Label existingMatch = null;
+ for (Label targetBoardLabel : targetBoard.getLabels()) {
+ if (originalLabel.getTitle().trim().equalsIgnoreCase(targetBoardLabel.getTitle().trim())) {
+ existingMatch = targetBoardLabel;
+ break;
+ }
+ }
+ if (existingMatch == null) {
+ if (hasManagePermission) {
+ originalLabel.setBoardId(targetBoardLocalId);
+ originalLabel.setId(null);
+ originalLabel.setLocalId(null);
+ originalLabel.setStatusEnum(DBStatus.LOCAL_EDITED);
+ originalLabel.setAccountId(targetBoard.getAccountId());
+ createAndAssignLabelToCard(originalBoard.getAccountId(), originalLabel, newCardId);
+ }
+ } else {
+ assignLabelToCard(existingMatch, targetCard);
+ }
+ }
+
+ // ### Clone assigned users
+ Account originalAccount = dataBaseAdapter.getAccountByIdDirectly(originAccountId);
+ // same instance? otherwise doesn't make sense
+ if (originalAccount.getUrl().equalsIgnoreCase(targetAccount.getUrl())) {
+ for (User assignedUser : originalCard.getAssignedUsers()) {
+ // has assignedUser at least view permissions?
+ boolean hasViewPermission = targetBoard.getBoard().getOwnerId() == assignedUser.getLocalId();
+ if (!hasViewPermission) {
+ for (AccessControl accessControl : aclOfTargetBoard) {
+ if (accessControl.getUserId() == userOfTargetAccount.getLocalId()) {
+ // ACL exists, so viewing is granted
+ hasViewPermission = true;
+ break;
+ }
+ }
+ }
+ if (hasViewPermission) {
+ assignUserToCard(assignedUser, targetCard);
+ }
+ }
+ }
+ // since this is LiveData<Void>
+ return null;
+ });
}
+ @AnyThread
public WrappedLiveData<Label> createLabel(long accountId, Label label, long localBoardId) {
WrappedLiveData<Label> liveData = new WrappedLiveData<>();
doAsync(() -> {
@@ -983,7 +1214,8 @@ public class SyncManager {
return liveData;
}
- public MutableLiveData<Label> createAndAssignLabelToCard(long accountId, Label label, long localCardId) {
+ @AnyThread
+ public MutableLiveData<Label> createAndAssignLabelToCard(long accountId, @NonNull Label label, long localCardId) {
MutableLiveData<Label> liveData = new MutableLiveData<>();
doAsync(() -> {
Account account = dataBaseAdapter.getAccountByIdDirectly(accountId);
@@ -1008,7 +1240,8 @@ public class SyncManager {
return liveData;
}
- public WrappedLiveData<Void> deleteLabel(Label label) {
+ @AnyThread
+ public WrappedLiveData<Void> deleteLabel(@NonNull Label label) {
WrappedLiveData<Void> liveData = new WrappedLiveData<>();
doAsync(() -> {
Account account = dataBaseAdapter.getAccountByIdDirectly(label.getAccountId());
@@ -1019,7 +1252,8 @@ public class SyncManager {
return liveData;
}
- public WrappedLiveData<Label> updateLabel(Label label) {
+ @AnyThread
+ public WrappedLiveData<Label> updateLabel(@NonNull Label label) {
WrappedLiveData<Label> liveData = new WrappedLiveData<>();
doAsync(() -> {
Account account = dataBaseAdapter.getAccountByIdDirectly(label.getAccountId());
@@ -1030,7 +1264,8 @@ public class SyncManager {
return liveData;
}
- public void assignUserToCard(User user, Card card) {
+ @AnyThread
+ public void assignUserToCard(@NonNull User user, @NonNull Card card) {
doAsync(() -> {
final long localUserId = user.getLocalId();
final long localCardId = card.getLocalId();
@@ -1054,7 +1289,8 @@ public class SyncManager {
});
}
- public void assignLabelToCard(Label label, Card card) {
+ @AnyThread
+ public void assignLabelToCard(@NonNull Label label, @NonNull Card card) {
doAsync(() -> {
final long localLabelId = label.getLocalId();
final long localCardId = card.getLocalId();
@@ -1077,7 +1313,8 @@ public class SyncManager {
});
}
- public void unassignLabelFromCard(Label label, Card card) {
+ @AnyThread
+ public void unassignLabelFromCard(@NonNull Label label, @NonNull Card card) {
doAsync(() -> {
dataBaseAdapter.deleteJoinedLabelForCard(card.getLocalId(), label.getLocalId());
Stack stack = dataBaseAdapter.getStackByLocalIdDirectly(card.getStackId());
@@ -1094,7 +1331,8 @@ public class SyncManager {
});
}
- public void unassignUserFromCard(User user, Card card) {
+ @AnyThread
+ public void unassignUserFromCard(@NonNull User user, @NonNull Card card) {
doAsync(() -> {
dataBaseAdapter.deleteJoinedUserForCard(card.getLocalId(), user.getLocalId());
if (serverAdapter.hasInternetConnection()) {
@@ -1138,6 +1376,7 @@ public class SyncManager {
return dataBaseAdapter.getUserByUid(accountId, uid);
}
+ @WorkerThread
public User getUserByUidDirectly(long accountId, String uid) {
return dataBaseAdapter.getUserByUidDirectly(accountId, uid);
}
@@ -1166,11 +1405,11 @@ public class SyncManager {
return dataBaseAdapter.createUser(accountId, user);
}
- public void updateUser(long accountId, User user) {
+ public void updateUser(long accountId, @NonNull User user) {
dataBaseAdapter.updateUser(accountId, user, true);
}
- public LiveData<List<Label>> searchNotYetAssignedLabelsByTitle(final long accountId, final long boardId, final long notYetAssignedToLocalCardId, String searchTerm) {
+ public LiveData<List<Label>> searchNotYetAssignedLabelsByTitle(final long accountId, final long boardId, final long notYetAssignedToLocalCardId, @NonNull String searchTerm) {
return dataBaseAdapter.searchNotYetAssignedLabelsByTitle(accountId, boardId, notYetAssignedToLocalCardId, searchTerm);
}
@@ -1181,7 +1420,8 @@ public class SyncManager {
/**
* @see <a href="https://github.com/stefan-niedermann/nextcloud-deck/issues/360">reenable reorder</a>
*/
- public void reorder(long accountId, FullCard movedCard, long newStackId, int newIndex) {
+ @AnyThread
+ public void reorder(long accountId, @NonNull FullCard movedCard, long newStackId, int newIndex) {
doAsync(() -> {
// read cards of new stack
List<FullCard> cardsOfNewStack = dataBaseAdapter.getFullCardsForStackDirectly(accountId, newStackId);
@@ -1266,7 +1506,7 @@ public class SyncManager {
}
- private void reorderLocally(List<FullCard> cardsOfNewStack, FullCard movedCard, long newStackId, int newOrder) {
+ private void reorderLocally(List<FullCard> cardsOfNewStack, @NonNull FullCard movedCard, long newStackId, int newOrder) {
// set new stack and order
Card movedInnerCard = movedCard.getCard();
int oldOrder = movedInnerCard.getOrder();
@@ -1324,7 +1564,7 @@ public class SyncManager {
reorderAscending(movedInnerCard, changedCards, startingAtOrder);
}
- private void reorderAscending(Card movedCard, List<Card> cardsToReorganize, int startingAtOrder) {
+ private void reorderAscending(@NonNull Card movedCard, @NonNull List<Card> cardsToReorganize, int startingAtOrder) {
Date now = new Date();
for (Card card : cardsToReorganize) {
card.setOrder(startingAtOrder);
@@ -1348,6 +1588,7 @@ public class SyncManager {
* The problem is, that the attachment is still in our local database and everytime one tries to sync, the log is spammed with 500 errors
* Also this leads to the attachment being present in the card forever with a DBStatus.LOCAL_EDITED
*/
+ @AnyThread
public WrappedLiveData<Attachment> addAttachmentToCard(long accountId, long localCardId, @NonNull String mimeType, @NonNull File file) {
WrappedLiveData<Attachment> liveData = new WrappedLiveData<>();
doAsync(() -> {
@@ -1367,7 +1608,8 @@ public class SyncManager {
return liveData;
}
- public WrappedLiveData<Attachment> updateAttachmentForCard(long accountId, Attachment existing, @NonNull String mimeType, @NonNull File file) {
+ @AnyThread
+ public WrappedLiveData<Attachment> updateAttachmentForCard(long accountId, @NonNull Attachment existing, @NonNull String mimeType, @NonNull File file) {
WrappedLiveData<Attachment> liveData = new WrappedLiveData<>();
doAsync(() -> {
Attachment attachment = populateAttachmentEntityForFile(existing, existing.getCardId(), mimeType, file);
@@ -1394,7 +1636,8 @@ public class SyncManager {
return liveData;
}
- private Attachment populateAttachmentEntityForFile(Attachment target, long localCardId, @NonNull String mimeType, @NonNull File file) {
+ @AnyThread
+ private static Attachment populateAttachmentEntityForFile(@NonNull Attachment target, long localCardId, @NonNull String mimeType, @NonNull File file) {
Attachment attachment = target;
attachment.setCardId(localCardId);
attachment.setMimetype(mimeType);
@@ -1406,6 +1649,7 @@ public class SyncManager {
return attachment;
}
+ @AnyThread
public WrappedLiveData<Void> deleteAttachmentOfCard(long accountId, long localCardId, long localAttachmentId) {
WrappedLiveData<Void> liveData = new WrappedLiveData<>();
doAsync(() -> {
@@ -1431,6 +1675,7 @@ public class SyncManager {
* Can be called from a configuration screen or a picker.
* Creates a new entry in the database, if row with given widgetId does not yet exist.
*/
+ @AnyThread
public void addOrUpdateSingleCardWidget(int widgetId, long accountId, long boardId, long localCardId) {
doAsync(() -> dataBaseAdapter.createSingleCardWidget(widgetId, accountId, boardId, localCardId));
}
@@ -1444,6 +1689,7 @@ public class SyncManager {
return model;
}
+ @AnyThread
public void deleteSingleCardWidgetModel(int widgetId) {
doAsync(() -> dataBaseAdapter.deleteSingleCardWidget(widgetId));
}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/SyncWorker.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/SyncWorker.java
index 25c8b726b..f43cbd34f 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/SyncWorker.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/SyncWorker.java
@@ -36,11 +36,11 @@ public class SyncWorker extends Worker {
SharedPreferences.Editor sharedPreferencesEditor = sharedPreferences.edit();
SyncManager syncManager = new SyncManager(getApplicationContext(), null);
if (syncManager.hasInternetConnection()) {
- DeckLog.log("Starting background synchronization");
+ DeckLog.info("Starting background synchronization");
sharedPreferencesEditor.putLong(getApplicationContext().getString(R.string.shared_preference_last_background_sync), System.currentTimeMillis());
sharedPreferencesEditor.apply();
boolean success = syncManager.synchronizeEverything();
- DeckLog.log("Finishing background synchronization with result " + success);
+ DeckLog.info("Finishing background synchronization with result " + success);
return success ? Result.failure() : Result.success();
}
return Result.success();
@@ -53,25 +53,30 @@ public class SyncWorker extends Worker {
public static void update(@NonNull Context context, String preferenceValue) {
deregister(context);
- if (!context.getString(R.string.pref_value_background_sync_off).equals(preferenceValue)) {
- int repeatInterval = 15;
- TimeUnit unit = TimeUnit.MINUTES;
- if (context.getString(R.string.pref_value_background_1_hour).equals(preferenceValue)) {
- repeatInterval = 1;
- unit = TimeUnit.HOURS;
- } else if (context.getString(R.string.pref_value_background_6_hours).equals(preferenceValue)) {
- repeatInterval = 6;
- unit = TimeUnit.HOURS;
- }
+ int repeatInterval = -1;
+ TimeUnit unit = null;
+ if (context.getString(R.string.pref_value_background_15_minutes).equals(preferenceValue)) {
+ repeatInterval = 15;
+ unit = TimeUnit.MINUTES;
+ } else if (context.getString(R.string.pref_value_background_1_hour).equals(preferenceValue)) {
+ repeatInterval = 1;
+ unit = TimeUnit.HOURS;
+ } else if (context.getString(R.string.pref_value_background_6_hours).equals(preferenceValue)) {
+ repeatInterval = 6;
+ unit = TimeUnit.HOURS;
+ }
+ if (unit == null) {
+ DeckLog.info("Do not register a new " + SyncWorker.class.getSimpleName() + " because setting " + preferenceValue + " is not a valid time frame");
+ } else {
final PeriodicWorkRequest work = new PeriodicWorkRequest.Builder(SyncWorker.class, repeatInterval, unit)
.setConstraints(constraints).build();
- DeckLog.log("Registering worker running each " + repeatInterval + " " + unit);
+ DeckLog.info("Registering " + SyncWorker.class.getSimpleName() + " running each " + repeatInterval + " " + unit);
WorkManager.getInstance(context.getApplicationContext()).enqueueUniquePeriodicWork(SyncWorker.WORKER_TAG, ExistingPeriodicWorkPolicy.REPLACE, work);
}
}
private static void deregister(@NonNull Context context) {
- DeckLog.log("Deregistering all workers with tag \"" + WORKER_TAG + "\"");
+ DeckLog.info("Deregistering all " + SyncWorker.class.getSimpleName() + " with tag \"" + WORKER_TAG + "\"");
WorkManager.getInstance(context.getApplicationContext()).cancelAllWorkByTag(WORKER_TAG);
}
}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/DataBaseAdapter.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/DataBaseAdapter.java
index fe8492c88..f0e33a0e7 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/DataBaseAdapter.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/DataBaseAdapter.java
@@ -3,6 +3,8 @@ package it.niedermann.nextcloud.deck.persistence.sync.adapters.db;
import android.content.Context;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.WorkerThread;
import androidx.lifecycle.LiveData;
import androidx.sqlite.db.SimpleSQLiteQuery;
@@ -36,8 +38,8 @@ import it.niedermann.nextcloud.deck.model.internal.FilterInformation;
import it.niedermann.nextcloud.deck.model.ocs.Activity;
import it.niedermann.nextcloud.deck.model.ocs.comment.DeckComment;
import it.niedermann.nextcloud.deck.model.ocs.comment.Mention;
-import it.niedermann.nextcloud.deck.model.widget.singlecard.SingleCardWidgetModel;
import it.niedermann.nextcloud.deck.model.ocs.comment.full.FullDeckComment;
+import it.niedermann.nextcloud.deck.model.widget.singlecard.SingleCardWidgetModel;
import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.util.LiveDataHelper;
import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.util.WrappedLiveData;
import it.niedermann.nextcloud.deck.ui.widget.singlecard.SingleCardWidget;
@@ -123,7 +125,7 @@ public class DataBaseAdapter {
return db.getCardDao().getFullCardByLocalIdDirectly(accountId, localId);
}
- public void filterRelationsForCard(FullCard card) {
+ public void filterRelationsForCard(@Nullable FullCard card) {
if (card != null) {
if (card.getLabels() != null && !card.getLabels().isEmpty()) {
List<Long> filteredIDs = db.getJoinCardWithLabelDao().filterDeleted(card.getLocalId(), getLocalIDs(card.getLabels()));
@@ -136,7 +138,7 @@ public class DataBaseAdapter {
}
}
- private <T> List<Long> getLocalIDs(List<? extends AbstractRemoteEntity> remoteEntityList) {
+ private <T> List<Long> getLocalIDs(@NonNull List<? extends AbstractRemoteEntity> remoteEntityList) {
ArrayList<Long> ids = new ArrayList<>(remoteEntityList.size());
for (AbstractRemoteEntity entity : remoteEntityList) {
ids.add(entity.getLocalId());
@@ -144,7 +146,7 @@ public class DataBaseAdapter {
return ids;
}
- public void readRelationsForACL(List<AccessControl> acl) {
+ public void readRelationsForACL(@Nullable List<AccessControl> acl) {
if (acl != null) {
for (AccessControl accessControl : acl) {
readRelationsForACL(accessControl);
@@ -152,7 +154,7 @@ public class DataBaseAdapter {
}
}
- public void readRelationsForACL(AccessControl acl) {
+ public void readRelationsForACL(@Nullable AccessControl acl) {
if (acl != null) {
if (acl.getUserId() != null) {
acl.setUser(db.getUserDao().getUserByLocalIdDirectly(acl.getUserId()));
@@ -160,7 +162,7 @@ public class DataBaseAdapter {
}
}
- private void filterRelationsForCard(List<FullCard> card) {
+ private void filterRelationsForCard(@Nullable List<FullCard> card) {
if (card == null) {
return;
}
@@ -169,6 +171,7 @@ public class DataBaseAdapter {
}
}
+ @WorkerThread
public Card getCardByRemoteIdDirectly(long accountId, long remoteId) {
return db.getCardDao().getCardByRemoteIdDirectly(accountId, remoteId);
}
@@ -221,7 +224,7 @@ public class DataBaseAdapter {
}
- private void fillSqlWithListValues(StringBuilder query, List<Object> args, List<? extends IRemoteEntity> entities) {
+ private void fillSqlWithListValues(StringBuilder query, List<Object> args, @NonNull List<? extends IRemoteEntity> entities) {
for (int i = 0; i < entities.size(); i++) {
if (i > 0) {
query.append(", ");
@@ -231,10 +234,12 @@ public class DataBaseAdapter {
}
}
+ @WorkerThread
public List<FullCard> getFullCardsForStackDirectly(long accountId, long localStackId) {
return db.getCardDao().getFullCardsForStackDirectly(accountId, localStackId);
}
+ @WorkerThread
public User getUserByUidDirectly(long accountId, String uid) {
return db.getUserDao().getUserByUidDirectly(accountId, uid);
}
@@ -254,11 +259,12 @@ public class DataBaseAdapter {
return distinctUntilChanged(db.getLabelDao().getLabelByRemoteId(accountId, remoteId));
}
+ @WorkerThread
public Label getLabelByRemoteIdDirectly(long accountId, long remoteId) {
return db.getLabelDao().getLabelByRemoteIdDirectly(accountId, remoteId);
}
- public long createLabel(long accountId, Label label) {
+ public long createLabel(long accountId, @NonNull Label label) {
label.setAccountId(accountId);
return db.getLabelDao().insert(label);
}
@@ -356,7 +362,6 @@ public class DataBaseAdapter {
return LiveDataHelper.wrapInLiveData(() -> {
long id = db.getAccountDao().insert(account);
return readAccountDirectly(id);
-
});
}
@@ -377,6 +382,7 @@ public class DataBaseAdapter {
// return distinctUntilChanged(db.getAccountDao().getAccountByName(name));
}
+ @WorkerThread
public Account readAccountDirectly(long id) {
return db.getAccountDao().getAccountByIdDirectly(id);
}
@@ -396,7 +402,7 @@ public class DataBaseAdapter {
return distinctUntilChanged(db.getBoardDao().getBoardsWithEditPermissionsForAccount(accountId));
}
- public WrappedLiveData<Board> createBoard(long accountId, Board board) {
+ public WrappedLiveData<Board> createBoard(long accountId, @NonNull Board board) {
return LiveDataHelper.wrapInLiveData(() -> {
board.setAccountId(accountId);
long id = db.getBoardDao().insert(board);
@@ -405,7 +411,8 @@ public class DataBaseAdapter {
});
}
- public long createBoardDirectly(long accountId, Board board) {
+ @WorkerThread
+ public long createBoardDirectly(long accountId, @NonNull Board board) {
board.setAccountId(accountId);
return db.getBoardDao().insert(board);
}
@@ -428,6 +435,7 @@ public class DataBaseAdapter {
return distinctUntilChanged(db.getStackDao().getFullStacksForBoard(accountId, localBoardId));
}
+ @WorkerThread
public List<FullStack> getFullStacksForBoardDirectly(long accountId, long localBoardId) {
return db.getStackDao().getFullStacksForBoardDirectly(accountId, localBoardId);
}
@@ -455,6 +463,7 @@ public class DataBaseAdapter {
db.getStackDao().update(stack);
}
+ @WorkerThread
public Card getCardByLocalIdDirectly(long accountId, long localCardId) {
return db.getCardDao().getCardByLocalIdDirectly(accountId, localCardId);
}
@@ -463,10 +472,12 @@ public class DataBaseAdapter {
return LiveDataHelper.interceptLiveData(db.getCardDao().getFullCardByLocalId(accountId, localCardId), this::filterRelationsForCard);
}
+ @WorkerThread
public List<FullCard> getLocallyChangedCardsDirectly(long accountId) {
return db.getCardDao().getLocallyChangedCardsDirectly(accountId);
}
+ @WorkerThread
public List<FullCard> getLocallyChangedCardsByLocalStackIdDirectly(long accountId, long localStackId) {
return db.getCardDao().getLocallyChangedCardsByLocalStackIdDirectly(accountId, localStackId);
}
@@ -493,7 +504,7 @@ public class DataBaseAdapter {
db.getCardDao().delete(card);
}
- public void updateCard(Card card, boolean setStatus) {
+ public void updateCard(@NonNull Card card, boolean setStatus) {
markAsEditedIfNeeded(card, setStatus);
db.getCardDao().update(card);
if (db.getSingleCardWidgetModelDao().containsCardLocalId(card.getLocalId())) {
@@ -502,19 +513,22 @@ public class DataBaseAdapter {
}
}
- public long createAccessControl(long accountId, AccessControl entity) {
+ public long createAccessControl(long accountId, @NonNull AccessControl entity) {
entity.setAccountId(accountId);
return db.getAccessControlDao().insert(entity);
}
+ @WorkerThread
public AccessControl getAccessControlByRemoteIdDirectly(long accountId, Long id) {
return db.getAccessControlDao().getAccessControlByRemoteIdDirectly(accountId, id);
}
- public LiveData<List<AccessControl>> getAccessControlByLocalBoardId(long accountId, Long id) {
- return LiveDataHelper.interceptLiveData(db.getAccessControlDao().getAccessControlByLocalBoardId(accountId, id), (acl) -> {
- readRelationsForACL(acl);
- });
+ public LiveData<List<AccessControl>> getAccessControlByLocalBoardId(long accountId, Long localBoardId) {
+ return LiveDataHelper.interceptLiveData(db.getAccessControlDao().getAccessControlByLocalBoardId(accountId, localBoardId), this::readRelationsForACL);
+ }
+
+ public List<AccessControl> getAccessControlByLocalBoardIdDirectly(long accountId, Long localBoardId) {
+ return db.getAccessControlDao().getAccessControlByLocalBoardIdDirectly(accountId, localBoardId);
}
public void updateAccessControl(AccessControl entity, boolean setStatus) {
@@ -535,6 +549,7 @@ public class DataBaseAdapter {
return distinctUntilChanged(db.getBoardDao().getFullBoardById(accountId, localId));
}
+ @WorkerThread
public Board getBoardByLocalIdDirectly(long localId) {
return db.getBoardDao().getBoardByIdDirectly(localId);
}
@@ -582,34 +597,38 @@ public class DataBaseAdapter {
return db.getLabelDao().findProposalsForLabelsToAssign(accountId, boardId, notAssignedToLocalCardId);
}
-
+ @WorkerThread
public Attachment getAttachmentByRemoteIdDirectly(long accountId, Long id) {
return db.getAttachmentDao().getAttachmentByRemoteIdDirectly(accountId, id);
}
+ @WorkerThread
public Attachment getAttachmentByLocalIdDirectly(long accountId, Long id) {
return db.getAttachmentDao().getAttachmentByLocalIdDirectly(accountId, id);
}
+ @WorkerThread
public List<Attachment> getAttachmentsForLocalCardIdDirectly(long accountId, Long localCardId) {
return db.getAttachmentDao().getAttachmentsForLocalCardIdDirectly(accountId, localCardId);
}
+ @WorkerThread
public List<Attachment> getLocallyChangedAttachmentsByLocalCardIdDirectly(long accountId, Long localCardId) {
return db.getAttachmentDao().getLocallyChangedAttachmentsByLocalCardIdDirectly(accountId, localCardId);
}
+ @WorkerThread
public List<Attachment> getLocallyChangedAttachmentsDirectly(long accountId) {
return db.getAttachmentDao().getLocallyChangedAttachmentsDirectly(accountId);
}
- public long createAttachment(long accountId, Attachment attachment) {
+ public long createAttachment(long accountId, @NonNull Attachment attachment) {
attachment.setAccountId(accountId);
attachment.setCreatedAt(new Date());
return db.getAttachmentDao().insert(attachment);
}
- public void updateAttachment(long accountId, Attachment attachment, boolean setStatus) {
+ public void updateAttachment(long accountId, @NonNull Attachment attachment, boolean setStatus) {
markAsEditedIfNeeded(attachment, setStatus);
attachment.setAccountId(accountId);
db.getAttachmentDao().update(attachment);
@@ -625,20 +644,23 @@ public class DataBaseAdapter {
}
}
- private void validateSearchTerm(String searchTerm) {
+ private void validateSearchTerm(@Nullable String searchTerm) {
if (searchTerm == null || searchTerm.trim().length() < 1) {
throw new IllegalArgumentException("please provide a proper search term! \"" + searchTerm + "\" doesn't seem right...");
}
}
+ @WorkerThread
public Account getAccountByIdDirectly(long accountId) {
return db.getAccountDao().getAccountByIdDirectly(accountId);
}
+ @WorkerThread
public List<Account> getAllAccountsDirectly() {
return db.getAccountDao().getAllAccountsDirectly();
}
+ @WorkerThread
public User getUserByLocalIdDirectly(long localUserId) {
return db.getUserDao().getUserByLocalIdDirectly(localUserId);
}
@@ -651,6 +673,7 @@ public class DataBaseAdapter {
db.getJoinCardWithLabelDao().setDbStatus(localCardId, localLabelId, status);
}
+ @WorkerThread
public Label getLabelByLocalIdDirectly(long localLabelId) {
return db.getLabelDao().getLabelsByIdDirectly(localLabelId);
}
@@ -679,10 +702,16 @@ public class DataBaseAdapter {
return db.getLabelDao().getLocallyChangedLabelsDirectly(accountId);
}
+ @WorkerThread
public Board getBoardByLocalCardIdDirectly(long localCardId) {
return db.getBoardDao().getBoardByLocalCardIdDirectly(localCardId);
}
+ @WorkerThread
+ public FullBoard getFullBoardByLocalCardIdDirectly(long localCardId) {
+ return db.getBoardDao().getFullBoardByLocalCardIdDirectly(localCardId);
+ }
+
public JoinCardWithLabel getJoinCardWithLabel(Long localLabelId, Long localCardId) {
return db.getJoinCardWithLabelDao().getJoin(localLabelId, localCardId);
}
@@ -724,6 +753,7 @@ public class DataBaseAdapter {
return db.getActivityDao().insert(activity);
}
+ @WorkerThread
public Activity getActivityByRemoteIdDirectly(long accountId, long remoteActivityId) {
return db.getActivityDao().getActivityByRemoteIdDirectly(accountId, remoteActivityId);
}
@@ -764,10 +794,12 @@ public class DataBaseAdapter {
});
}
+ @WorkerThread
public DeckComment getCommentByRemoteIdDirectly(long accountId, Long remoteCommentId) {
return db.getCommentDao().getCommentByRemoteIdDirectly(accountId, remoteCommentId);
}
+ @WorkerThread
public DeckComment getCommentByLocalIdDirectly(long accountId, Long localCommentId) {
return db.getCommentDao().getCommentByLocalIdDirectly(accountId, localCommentId);
}
@@ -791,6 +823,7 @@ public class DataBaseAdapter {
}
}
+ @WorkerThread
public List<DeckComment> getLocallyChangedCommentsByLocalCardIdDirectly(long accountId, long localCardId) {
return db.getCommentDao().getLocallyChangedCommentsByLocalCardIdDirectly(accountId, localCardId);
}
@@ -803,6 +836,7 @@ public class DataBaseAdapter {
return db.getMentionDao().insert(mention);
}
+ @WorkerThread
public List<DeckComment> getCommentByLocalCardIdDirectly(Long localCardId) {
return db.getCommentDao().getCommentByLocalCardIdDirectly(localCardId);
}
@@ -811,6 +845,7 @@ public class DataBaseAdapter {
return db.getCardDao().getCardsWithLocallyChangedCommentsDirectly(accountId);
}
+ @WorkerThread
public Long getLocalStackIdByRemoteStackIdDirectly(long accountId, Long stackId) {
return db.getStackDao().getLocalStackIdByRemoteStackIdDirectly(accountId, stackId);
}
@@ -827,6 +862,7 @@ public class DataBaseAdapter {
return db.getJoinCardWithLabelDao().countCardsWithLabel(localLabelId);
}
+ @WorkerThread
public Label getLabelByBoardIdAndTitleDirectly(long boardId, String title) {
return db.getLabelDao().getLabelByBoardIdAndTitleDirectly(boardId, title);
}
@@ -839,9 +875,12 @@ public class DataBaseAdapter {
return LiveDataHelper.postCustomValue(distinctUntilChanged(db.getBoardDao().countArchivedBoards(accountId)), data -> data != null && data > 0);
}
+ @WorkerThread
public Long getRemoteCommentIdForLocalIdDirectly(Long localCommentId) {
return db.getCommentDao().getRemoteCommentIdForLocalIdDirectly(localCommentId);
}
+
+ @WorkerThread
public Long getLocalCommentIdForRemoteIdDirectly(long accountId, Long remoteCommentId) {
return db.getCommentDao().getLocalCommentIdForRemoteIdDirectly(accountId, remoteCommentId);
}
@@ -851,6 +890,7 @@ public class DataBaseAdapter {
// Widgets
// -------------------
+ @WorkerThread
public long createSingleCardWidget(int widgetId, long accountId, long boardLocalId, long cardLocalId) {
SingleCardWidgetModel model = new SingleCardWidgetModel();
model.setWidgetId(widgetId);
@@ -873,4 +913,12 @@ public class DataBaseAdapter {
model.setWidgetId(widgetId);
db.getSingleCardWidgetModelDao().delete(model);
}
+
+ public LiveData<List<Account>> readAccountsForHostWithReadAccessToBoard(String host, long boardRemoteId) {
+ return db.getAccountDao().readAccountsForHostWithReadAccessToBoard("%"+host+"%", boardRemoteId);
+ }
+
+ public List<Account> readAccountsForHostWithReadAccessToBoardDirectly(String host, long boardRemoteId) {
+ return db.getAccountDao().readAccountsForHostWithReadAccessToBoardDirectly("%"+host+"%", boardRemoteId);
+ }
}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/DeckDatabase.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/DeckDatabase.java
index 82fb86c6e..0e86557fa 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/DeckDatabase.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/DeckDatabase.java
@@ -4,6 +4,7 @@ import android.content.Context;
import android.database.Cursor;
import androidx.annotation.NonNull;
+import androidx.preference.PreferenceManager;
import androidx.room.Database;
import androidx.room.Room;
import androidx.room.RoomDatabase;
@@ -32,6 +33,7 @@ import it.niedermann.nextcloud.deck.model.ocs.Activity;
import it.niedermann.nextcloud.deck.model.ocs.comment.DeckComment;
import it.niedermann.nextcloud.deck.model.ocs.comment.Mention;
import it.niedermann.nextcloud.deck.model.widget.singlecard.SingleCardWidgetModel;
+import it.niedermann.nextcloud.deck.persistence.sync.SyncWorker;
import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.dao.AccessControlDao;
import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.dao.AccountDao;
import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.dao.ActivityDao;
@@ -73,7 +75,7 @@ import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.dao.UserDao;
SingleCardWidgetModel.class,
},
exportSchema = false,
- version = 14
+ version = 15
)
@TypeConverters({DateTypeConverter.class})
public abstract class DeckDatabase extends RoomDatabase {
@@ -201,6 +203,19 @@ public abstract class DeckDatabase extends RoomDatabase {
.addMigrations(MIGRATION_11_12)
.addMigrations(MIGRATION_12_13)
.addMigrations(MIGRATION_13_14)
+ .addMigrations(new Migration(14, 15) {
+ @Override
+ public void migrate(@NonNull SupportSQLiteDatabase database) {
+ // https://github.com/stefan-niedermann/nextcloud-deck/issues/570
+ SyncWorker.update(context);
+ // https://github.com/stefan-niedermann/nextcloud-deck/issues/525
+ PreferenceManager
+ .getDefaultSharedPreferences(context)
+ .edit()
+ .remove("it.niedermann.nextcloud.deck.theme_text")
+ .apply();
+ }
+ })
.fallbackToDestructiveMigration()
.addCallback(ON_CREATE_CALLBACK)
.build();
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/AccessControlDao.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/AccessControlDao.java
index 9dc9b7b3d..2ed1e7d59 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/AccessControlDao.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/AccessControlDao.java
@@ -17,6 +17,9 @@ public interface AccessControlDao extends GenericDao<AccessControl> {
@Query("SELECT * FROM AccessControl WHERE accountId = :accountId and boardId = :localBoardId and status <> 3")
LiveData<List<AccessControl>> getAccessControlByLocalBoardId(final long accountId, final long localBoardId);
+ @Query("SELECT * FROM AccessControl WHERE accountId = :accountId and boardId = :localBoardId and status <> 3")
+ List<AccessControl> getAccessControlByLocalBoardIdDirectly(final long accountId, final long localBoardId);
+
@Query("SELECT * FROM AccessControl WHERE accountId = :accountId and id = :remoteId")
AccessControl getAccessControlByRemoteIdDirectly(final long accountId, final long remoteId);
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/AccountDao.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/AccountDao.java
index 515ecc0a4..6ebe4a8f3 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/AccountDao.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/AccountDao.java
@@ -36,4 +36,10 @@ public interface AccountDao extends GenericDao<Account> {
@Query("SELECT * from account")
List<Account> getAllAccountsDirectly();
+
+ @Query("SELECT * from account a where a.url like :hostLike and exists (select 1 from board b where b.id = :boardRemoteId and a.id = b.accountId)")
+ LiveData<List<Account>> readAccountsForHostWithReadAccessToBoard(String hostLike, long boardRemoteId);
+
+ @Query("SELECT * from account a where a.url like :hostLike and exists (select 1 from board b where b.id = :boardRemoteId and a.id = b.accountId)")
+ List<Account> readAccountsForHostWithReadAccessToBoardDirectly(String hostLike, long boardRemoteId);
} \ No newline at end of file
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/BoardDao.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/BoardDao.java
index 0f4117481..bd189e846 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/BoardDao.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/BoardDao.java
@@ -52,6 +52,9 @@ public interface BoardDao extends GenericDao<Board> {
@Query("SELECT b.* FROM board b JOIN stack s ON s.boardId = b.localId JOIN card c ON c.localId = :localCardId")
Board getBoardByLocalCardIdDirectly(long localCardId);
+ @Query("SELECT b.* FROM board b JOIN stack s ON s.boardId = b.localId JOIN card c ON c.localId = :localCardId")
+ FullBoard getFullBoardByLocalCardIdDirectly(long localCardId);
+
@Transaction
@Query("SELECT * FROM board WHERE accountId = :accountId")
List<FullBoard> getAllFullBoards(long accountId);
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/util/LiveDataHelper.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/util/LiveDataHelper.java
index 650c903b3..10a18bb09 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/util/LiveDataHelper.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/util/LiveDataHelper.java
@@ -85,7 +85,13 @@ public class LiveDataHelper {
public static <T> WrappedLiveData<T> wrapInLiveData(final LiveDataWrapper<T> liveDataWrapper) {
final WrappedLiveData<T> liveData = new WrappedLiveData<>();
- doAsync(() -> liveDataWrapper.postResult(liveData));
+ doAsync(() -> {
+ try {
+ liveDataWrapper.postResult(liveData);
+ } catch (Throwable t) {
+ liveData.postError(t);
+ }
+ });
return liveData;
}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/providers/partial/BoardWitAclDownSyncDataProvider.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/providers/partial/BoardWitAclDownSyncDataProvider.java
new file mode 100644
index 000000000..326d257ab
--- /dev/null
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/providers/partial/BoardWitAclDownSyncDataProvider.java
@@ -0,0 +1,32 @@
+package it.niedermann.nextcloud.deck.persistence.sync.helpers.providers.partial;
+
+import java.util.List;
+
+import it.niedermann.nextcloud.deck.api.IResponseCallback;
+import it.niedermann.nextcloud.deck.model.AccessControl;
+import it.niedermann.nextcloud.deck.model.full.FullBoard;
+import it.niedermann.nextcloud.deck.persistence.sync.adapters.ServerAdapter;
+import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.DataBaseAdapter;
+import it.niedermann.nextcloud.deck.persistence.sync.helpers.SyncHelper;
+import it.niedermann.nextcloud.deck.persistence.sync.helpers.providers.AccessControlDataProvider;
+import it.niedermann.nextcloud.deck.persistence.sync.helpers.providers.BoardDataProvider;
+
+public class BoardWitAclDownSyncDataProvider extends BoardDataProvider {
+
+ @Override
+ public void goDeeper(SyncHelper syncHelper, FullBoard existingEntity, FullBoard entityFromServer, IResponseCallback<Boolean> callback) {
+
+ List<AccessControl> acl = entityFromServer.getParticipants();
+ if (acl != null && !acl.isEmpty()){
+ for (AccessControl ac : acl){
+ ac.setBoardId(existingEntity.getLocalId());
+ }
+ syncHelper.doSyncFor(new AccessControlDataProvider(this, existingEntity, acl));
+ }
+ }
+
+ @Override
+ public void goDeeperForUpSync(SyncHelper syncHelper, ServerAdapter serverAdapter, DataBaseAdapter dataBaseAdapter, IResponseCallback<Boolean> callback) {
+ // do nothing!
+ }
+}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/ImportAccountActivity.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/ImportAccountActivity.java
index ae7ab3683..854b99a6a 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/ImportAccountActivity.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/ImportAccountActivity.java
@@ -4,13 +4,17 @@ import android.annotation.SuppressLint;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.sqlite.SQLiteConstraintException;
+import android.graphics.drawable.Drawable;
import android.net.Uri;
+import android.os.Build;
import android.os.Bundle;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.content.ContextCompat;
+import androidx.core.graphics.drawable.DrawableCompat;
import androidx.preference.PreferenceManager;
import com.nextcloud.android.sso.AccountImporter;
@@ -81,6 +85,12 @@ public class ImportAccountActivity extends AppCompatActivity {
AccountImporter.requestAndroidAccountPermissionsAndPickAccount(this);
}
});
+
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+ Drawable wrapDrawable = DrawableCompat.wrap(binding.progressCircular.getIndeterminateDrawable());
+ DrawableCompat.setTint(wrapDrawable, ContextCompat.getColor(this, R.color.defaultBrand));
+ binding.progressCircular.setIndeterminateDrawable(DrawableCompat.unwrap(wrapDrawable));
+ }
}
@Override
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 84b7f8d3b..81e2afa71 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
@@ -5,7 +5,6 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.database.sqlite.SQLiteConstraintException;
import android.graphics.Color;
-import android.graphics.drawable.Drawable;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkInfo;
@@ -26,6 +25,7 @@ import androidx.annotation.RequiresApi;
import androidx.annotation.UiThread;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AppCompatDelegate;
+import androidx.core.content.ContextCompat;
import androidx.core.graphics.drawable.DrawableCompat;
import androidx.core.util.Pair;
import androidx.core.view.GravityCompat;
@@ -53,7 +53,6 @@ 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.nextcloud.deck.Application;
import it.niedermann.nextcloud.deck.DeckLog;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.api.IResponseCallback;
@@ -97,12 +96,23 @@ import it.niedermann.nextcloud.deck.ui.stack.StackAdapter;
import it.niedermann.nextcloud.deck.ui.stack.StackFragment;
import it.niedermann.nextcloud.deck.util.DrawerMenuUtil;
-import static android.graphics.Color.parseColor;
import static androidx.lifecycle.Transformations.switchMap;
-import static it.niedermann.nextcloud.deck.Application.NO_ACCOUNT_ID;
-import static it.niedermann.nextcloud.deck.Application.NO_BOARD_ID;
-import static it.niedermann.nextcloud.deck.Application.NO_STACK_ID;
+import static it.niedermann.nextcloud.deck.DeckApplication.NO_ACCOUNT_ID;
+import static it.niedermann.nextcloud.deck.DeckApplication.NO_BOARD_ID;
+import static it.niedermann.nextcloud.deck.DeckApplication.NO_STACK_ID;
+import static it.niedermann.nextcloud.deck.DeckApplication.readCurrentAccountId;
+import static it.niedermann.nextcloud.deck.DeckApplication.readCurrentBoardId;
+import static it.niedermann.nextcloud.deck.DeckApplication.readCurrentStackId;
+import static it.niedermann.nextcloud.deck.DeckApplication.saveCurrentAccountId;
+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.applyBrandToFAB;
+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.saveBrandColors;
+import static it.niedermann.nextcloud.deck.util.ColorUtil.contrastRatioIsSufficient;
+import static it.niedermann.nextcloud.deck.util.ColorUtil.contrastRatioIsSufficientBigAreas;
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;
@@ -159,6 +169,8 @@ public class MainActivity extends BrandedActivity implements DeleteStackListener
Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler(this));
+ setTheme(R.style.AppTheme);
+
binding = ActivityMainBinding.inflate(getLayoutInflater());
headerBinding = NavHeaderMainBinding.bind(binding.navigationView.getHeaderView(0));
setContentView(binding.getRoot());
@@ -190,18 +202,18 @@ public class MainActivity extends BrandedActivity implements DeleteStackListener
}
}).observe(this, (List<Account> accounts) -> {
if (accounts == null || accounts.size() == 0) {
- // Last account has been deleted. hasAccounts LiveData will handle this, but we make sure, that branding is reset.
- Application.saveBrandColors(this, getResources().getColor(R.color.primary), Color.WHITE);
+ // Last account has been deleted. hasAccounts LiveData will handle this, but we make sure, that branding is reset.
+ saveBrandColors(this, ContextCompat.getColor(this, R.color.defaultBrand));
return;
}
accountsList = accounts;
- long lastAccountId = Application.readCurrentAccountId(this);
+ long lastAccountId = readCurrentAccountId(this);
for (Account account : accountsList) {
if (lastAccountId == account.getId() || lastAccountId == NO_ACCOUNT_ID) {
- mainViewModel.setCurrentAccount(account, account.getServerDeckVersionAsObject().isSupported(this));
+ mainViewModel.setCurrentAccount(account);
if (!firstAccountAdded) {
DeckLog.info("Syncing the current account on app start");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
@@ -229,13 +241,12 @@ public class MainActivity extends BrandedActivity implements DeleteStackListener
SingleAccountHelper.setCurrentAccount(getApplicationContext(), mainViewModel.getCurrentAccount().getName());
syncManager = new SyncManager(this);
- Application.saveBrandColors(this, parseColor(mainViewModel.getCurrentAccount().getColor()), parseColor(mainViewModel.getCurrentAccount().getTextColor()));
- Application.saveCurrentAccountId(this, mainViewModel.getCurrentAccount().getId());
+ saveCurrentAccountId(this, mainViewModel.getCurrentAccount().getId());
if (mainViewModel.getCurrentAccount().isMaintenanceEnabled()) {
refreshCapabilities(mainViewModel.getCurrentAccount());
}
- lastBoardId = Application.readCurrentBoardId(this, mainViewModel.getCurrentAccount().getId());
+ lastBoardId = readCurrentBoardId(this, mainViewModel.getCurrentAccount().getId());
if (boardsLiveData != null && boardsLiveDataObserver != null) {
boardsLiveData.removeObserver(boardsLiveDataObserver);
@@ -262,6 +273,7 @@ public class MainActivity extends BrandedActivity implements DeleteStackListener
setCurrentBoard(boardsList.get(0));
}
} else {
+ clearBrandColors(this);
clearCurrentBoard();
}
@@ -277,13 +289,11 @@ public class MainActivity extends BrandedActivity implements DeleteStackListener
};
boardsLiveData.observe(this, boardsLiveDataObserver);
- final Drawable placeholderAvatar = getResources().getDrawable(R.drawable.ic_baseline_account_circle_24);
- DrawableCompat.setTint(placeholderAvatar, parseColor(currentAccount.getTextColor()));
Glide
.with(binding.accountSwitcher.getContext())
.load(currentAccount.getAvatarUrl(64))
- .placeholder(placeholderAvatar)
- .error(placeholderAvatar)
+ .placeholder(R.drawable.ic_baseline_account_circle_24)
+ .error(R.drawable.ic_baseline_account_circle_24)
.apply(RequestOptions.circleCropTransform())
.into(binding.accountSwitcher);
@@ -345,7 +355,7 @@ public class MainActivity extends BrandedActivity implements DeleteStackListener
binding.viewPager.post(() -> {
// stackAdapter size might differ from position when an account has been deleted
if (stackAdapter.getItemCount() > position) {
- Application.saveCurrentStackId(getApplicationContext(), mainViewModel.getCurrentAccount().getId(), mainViewModel.getCurrentBoardLocalId(), stackAdapter.getItem(position).getLocalId());
+ saveCurrentStackId(getApplicationContext(), mainViewModel.getCurrentAccount().getId(), mainViewModel.getCurrentBoardLocalId(), stackAdapter.getItem(position).getLocalId());
} else {
DeckLog.logError(new IllegalStateException("Tried to save current Stack which cannot be available (stackAdapter doesn't have this position)"));
}
@@ -411,23 +421,15 @@ public class MainActivity extends BrandedActivity implements DeleteStackListener
}
@Override
- public void applyBrand(@ColorInt int mainColor, @ColorInt int textColor) {
- applyBrandToPrimaryToolbar(mainColor, textColor, binding.toolbar);
- applyBrandToPrimaryTabLayout(mainColor, textColor, binding.stackTitles);
- applyBrandToFAB(mainColor, textColor, binding.fab);
-
- // Is null as soon as the avatar has been set
-// @Nullable
-// Drawable accountSwitcherDrawable = binding.accountSwitcher.getDrawable();
-// if (accountSwitcherDrawable != null) {
-// DrawableCompat.setTint(accountSwitcherDrawable, textColor);
-// }
-
- binding.listMenuButton.setBackgroundColor(mainColor);
- binding.listMenuButton.setColorFilter(textColor);
-
+ public void applyBrand(@ColorInt int mainColor) {
+ applyBrandToPrimaryTabLayout(mainColor, binding.stackTitles);
+ applyBrandToFAB(mainColor, binding.fab);
+ // TODO We assume, that the background of the spinner is always white
+ binding.swipeRefreshLayout.setColorSchemeColors(contrastRatioIsSufficient(Color.WHITE, mainColor) ? mainColor : colorAccent);
headerBinding.headerView.setBackgroundColor(mainColor);
- headerBinding.appName.setTextColor(textColor);
+ @ColorInt final int headerTextColor = contrastRatioIsSufficientBigAreas(mainColor, Color.WHITE) ? Color.WHITE : Color.BLACK;
+ DrawableCompat.setTint(headerBinding.logo.getDrawable(), headerTextColor);
+ headerBinding.appName.setTextColor(headerTextColor);
}
@Override
@@ -522,9 +524,6 @@ public class MainActivity extends BrandedActivity implements DeleteStackListener
if (mainViewModel.getCurrentAccount().getServerDeckVersionAsObject().isSupported(MainActivity.this) && !response.getDeckVersion().isSupported(MainActivity.this)) {
recreate();
}
- @ColorInt final int mainColor = parseColor(response.getColor());
- @ColorInt final int textColor = parseColor(response.getTextColor());
- runOnUiThread(() -> Application.saveBrandColors(MainActivity.this, mainColor, textColor));
}
}
@@ -551,11 +550,12 @@ public class MainActivity extends BrandedActivity implements DeleteStackListener
if (stacksLiveData != null) {
stacksLiveData.removeObservers(this);
}
+ saveBrandColors(this, Color.parseColor('#' + board.getColor()));
mainViewModel.setCurrentBoard(board);
filterViewModel.clearFilterInformation();
lastBoardId = board.getLocalId();
- Application.saveCurrentBoardId(this, mainViewModel.getCurrentAccount().getId(), mainViewModel.getCurrentBoardLocalId());
+ saveCurrentBoardId(this, mainViewModel.getCurrentAccount().getId(), mainViewModel.getCurrentBoardLocalId());
binding.toolbar.setTitle(board.getTitle());
@@ -590,7 +590,7 @@ public class MainActivity extends BrandedActivity implements DeleteStackListener
int stackPositionInAdapter = 0;
stackAdapter.setStacks(fullStacks);
- long currentStackId = Application.readCurrentStackId(this, mainViewModel.getCurrentAccount().getId(), mainViewModel.getCurrentBoardLocalId());
+ long currentStackId = readCurrentStackId(this, mainViewModel.getCurrentAccount().getId(), mainViewModel.getCurrentBoardLocalId());
for (int i = 0; i < currentBoardStacksCount; i++) {
if (fullStacks.get(i).getLocalId() == currentStackId || currentStackId == NO_STACK_ID) {
stackPositionInAdapter = i;
@@ -797,7 +797,7 @@ public class MainActivity extends BrandedActivity implements DeleteStackListener
if (response.getDeckVersion().isSupported(getApplicationContext())) {
runOnUiThread(() -> {
syncManager = importSyncManager;
- mainViewModel.setCurrentAccount(account, account.getServerDeckVersionAsObject().isSupported(MainActivity.this));
+ mainViewModel.setCurrentAccount(account);
final Snackbar importSnackbar = BrandedSnackbar.make(binding.coordinatorLayout, R.string.account_is_getting_imported, Snackbar.LENGTH_INDEFINITE);
importSnackbar.show();
@@ -943,6 +943,7 @@ public class MainActivity extends BrandedActivity implements DeleteStackListener
} else if (this.boardsList.size() > 1) { // Select second board after deletion
setCurrentBoard(this.boardsList.get(1));
} else { // No other board is available, open create dialog
+ clearBrandColors(this);
clearCurrentBoard();
EditBoardDialogFragment.newInstance().show(getSupportFragmentManager(), addBoard);
}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/MainViewModel.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/MainViewModel.java
index b9ba588df..e5bd4f482 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/MainViewModel.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/MainViewModel.java
@@ -1,15 +1,18 @@
package it.niedermann.nextcloud.deck.ui;
+import android.app.Application;
+
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
-import androidx.lifecycle.ViewModel;
import it.niedermann.nextcloud.deck.model.Account;
import it.niedermann.nextcloud.deck.model.Board;
@SuppressWarnings("WeakerAccess")
-public class MainViewModel extends ViewModel {
+public class MainViewModel extends AndroidViewModel {
private MutableLiveData<Account> currentAccount = new MutableLiveData<>();
private Board currentBoard;
@@ -17,6 +20,10 @@ public class MainViewModel extends ViewModel {
private boolean currentAccountIsSupportedVersion = false;
+ public MainViewModel(@NonNull Application application) {
+ super(application);
+ }
+
public Account getCurrentAccount() {
return currentAccount.getValue();
}
@@ -25,9 +32,9 @@ public class MainViewModel extends ViewModel {
return this.currentAccount;
}
- public void setCurrentAccount(Account currentAccount, boolean versionIsSupported) {
+ public void setCurrentAccount(Account currentAccount) {
this.currentAccount.setValue(currentAccount);
- this.currentAccountIsSupportedVersion = versionIsSupported;
+ this.currentAccountIsSupportedVersion = currentAccount.getServerDeckVersionAsObject().isSupported(getApplication().getApplicationContext());
}
public void setCurrentBoard(Board currentBoard) {
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 f3d462c90..b0b0d68ae 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,40 +1,31 @@
package it.niedermann.nextcloud.deck.ui;
import android.content.Intent;
-import android.graphics.Color;
import android.net.Uri;
import android.text.TextUtils;
import android.view.View;
-import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.annotation.UiThread;
import androidx.appcompat.app.AppCompatActivity;
import com.nextcloud.android.sso.helper.SingleAccountHelper;
-import it.niedermann.nextcloud.deck.Application;
import it.niedermann.nextcloud.deck.DeckLog;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.databinding.ActivityPushNotificationBinding;
import it.niedermann.nextcloud.deck.model.Account;
import it.niedermann.nextcloud.deck.persistence.sync.SyncManager;
-import it.niedermann.nextcloud.deck.ui.branding.Branded;
import it.niedermann.nextcloud.deck.ui.card.EditActivity;
import it.niedermann.nextcloud.deck.ui.exception.ExceptionHandler;
import static android.graphics.Color.parseColor;
import static it.niedermann.nextcloud.deck.persistence.sync.adapters.db.util.LiveDataHelper.observeOnce;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandedActivity.applyBrandToPrimaryToolbar;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandedActivity.applyBrandToStatusbar;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandedActivity.getSecondaryForegroundColorDependingOnTheme;
-public class PushNotificationActivity extends AppCompatActivity implements Branded {
+public class PushNotificationActivity extends AppCompatActivity {
private ActivityPushNotificationBinding binding;
- private boolean brandingEnabled;
-
// Provided by Files app NotificationJob
private static final String KEY_SUBJECT = "subject";
private static final String KEY_MESSAGE = "message";
@@ -56,8 +47,6 @@ public class PushNotificationActivity extends AppCompatActivity implements Brand
setContentView(binding.getRoot());
setSupportActionBar(binding.toolbar);
- brandingEnabled = Application.isBrandingEnabled(this);
-
binding.subject.setText(getIntent().getStringExtra(KEY_SUBJECT));
final String message = getIntent().getStringExtra(KEY_MESSAGE);
@@ -82,13 +71,6 @@ public class PushNotificationActivity extends AppCompatActivity implements Brand
if (account != null) {
SingleAccountHelper.setCurrentAccount(this, account.getName());
final SyncManager syncManager = new SyncManager(this);
- try {
- if (brandingEnabled) {
- applyBrand(parseColor(account.getColor()), parseColor(account.getTextColor()));
- }
- } catch (Throwable t) {
- DeckLog.logError(t);
- }
DeckLog.verbose("account: " + account);
observeOnce(syncManager.getLocalBoardIdByCardRemoteIdAndAccount(cardRemoteId, account), PushNotificationActivity.this, (boardLocalId -> {
DeckLog.verbose("BoardLocalId " + boardLocalId);
@@ -153,11 +135,6 @@ public class PushNotificationActivity extends AppCompatActivity implements Brand
@UiThread
private void launchEditActivity(@NonNull Account account, Long boardId, Long cardId) {
- try {
- Application.saveBrandColors(this, Color.parseColor(account.getColor()), Color.parseColor(account.getTextColor()));
- } catch (Throwable t) {
- DeckLog.logError(t);
- }
DeckLog.info("starting " + EditActivity.class.getSimpleName() + " with [" + account + ", " + boardId + ", " + cardId + "]");
startActivity(EditActivity.createEditCardIntent(this, account, boardId, cardId));
finish();
@@ -169,15 +146,6 @@ public class PushNotificationActivity extends AppCompatActivity implements Brand
return true;
}
- @Override
- public void applyBrand(@ColorInt int mainColor, @ColorInt int textColor) {
- if (brandingEnabled) {
- applyBrandToStatusbar(getWindow(), mainColor, textColor);
- applyBrandToPrimaryToolbar(mainColor, textColor, binding.toolbar);
- binding.cancel.setTextColor(getSecondaryForegroundColorDependingOnTheme(this, mainColor));
- }
- }
-
public void applyBrandToSubmitButton(@NonNull Account account) {
try {
binding.submit.setBackgroundColor(parseColor(account.getColor()));
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 943e48bd6..bf3734b72 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
@@ -19,6 +19,8 @@ import it.niedermann.nextcloud.deck.model.Account;
import it.niedermann.nextcloud.deck.ui.branding.BrandedActivity;
import it.niedermann.nextcloud.deck.ui.exception.ExceptionHandler;
+import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.applyBrandToPrimaryTabLayout;
+
public class AboutActivity extends BrandedActivity {
private static final String BUNDLE_KEY_ACCOUNT = "account";
@@ -82,9 +84,8 @@ public class AboutActivity extends BrandedActivity {
}
@Override
- public void applyBrand(int mainColor, int textColor) {
- applyBrandToPrimaryToolbar(mainColor, textColor, binding.toolbar);
- applyBrandToPrimaryTabLayout(mainColor, textColor, binding.tabLayout);
+ public void applyBrand(int mainColor) {
+ applyBrandToPrimaryTabLayout(mainColor, binding.tabLayout);
}
@NonNull
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 f33b30ea3..c00ff212a 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,18 +1,26 @@
package it.niedermann.nextcloud.deck.ui.about;
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.core.content.ContextCompat;
+import androidx.core.graphics.drawable.DrawableCompat;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.databinding.FragmentAboutLicenseTabBinding;
import it.niedermann.nextcloud.deck.ui.branding.BrandedFragment;
+import it.niedermann.nextcloud.deck.util.ColorUtil;
+import static it.niedermann.nextcloud.deck.DeckApplication.isDarkTheme;
+import static it.niedermann.nextcloud.deck.util.ColorUtil.contrastRatioIsSufficientBigAreas;
import static it.niedermann.nextcloud.deck.util.SpannableUtil.setTextWithURL;
public class AboutFragmentLicenseTab extends BrandedFragment {
@@ -29,8 +37,11 @@ public class AboutFragmentLicenseTab extends BrandedFragment {
}
@Override
- public void applyBrand(int mainColor, int textColor) {
- binding.aboutAppLicenseButton.setBackgroundColor(mainColor);
- binding.aboutAppLicenseButton.setTextColor(textColor);
+ public void applyBrand(int 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.getForegroundColorForBackgroundColor(finalMainColor));
}
} \ No newline at end of file
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 bae4720b9..592f2e8cc 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
@@ -53,14 +53,15 @@ public class AccountSwitcherDialog extends BrandedDialogFragment {
Glide.with(requireContext())
.load(viewModel.getCurrentAccount().getAvatarUrl(dpToPx(binding.currentAccountItemAvatar.getContext(), R.dimen.avatar_size)))
- .error(R.drawable.ic_person_grey600_24dp)
+ .placeholder(R.drawable.ic_baseline_account_circle_24)
+ .error(R.drawable.ic_baseline_account_circle_24)
.apply(RequestOptions.circleCropTransform())
.into(binding.currentAccountItemAvatar);
binding.accountLayout.setOnClickListener((v) -> dismiss());
adapter = new AccountSwitcherAdapter((localAccount -> {
- viewModel.setCurrentAccount(localAccount, localAccount.getServerDeckVersionAsObject().isSupported(requireContext()));
+ viewModel.setCurrentAccount(localAccount);
dismiss();
}));
@@ -97,7 +98,7 @@ public class AccountSwitcherDialog extends BrandedDialogFragment {
}
@Override
- public void applyBrand(int mainColor, int textColor) {
+ public void applyBrand(int mainColor) {
// applyBrandToLayerDrawable((LayerDrawable) binding.check.getDrawable(), R.id.area, mainColor);
}
}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/accountswitcher/AccountSwitcherViewHolder.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/accountswitcher/AccountSwitcherViewHolder.java
index 9de4185b1..9c93c422e 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/accountswitcher/AccountSwitcherViewHolder.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/accountswitcher/AccountSwitcherViewHolder.java
@@ -31,7 +31,8 @@ public class AccountSwitcherViewHolder extends RecyclerView.ViewHolder {
binding.accountHost.setText(Uri.parse(account.getUrl()).getHost());
Glide.with(itemView.getContext())
.load(new SingleSignOnUrl(account.getName(), account.getAvatarUrl(dpToPx(binding.accountItemAvatar.getContext(), R.dimen.avatar_size))))
- .error(R.drawable.ic_person_grey600_24dp)
+ .placeholder(R.drawable.ic_baseline_account_circle_24)
+ .error(R.drawable.ic_baseline_account_circle_24)
.apply(RequestOptions.circleCropTransform())
.into(binding.accountItemAvatar);
itemView.setOnClickListener((v) -> onAccountClick.accept(account));
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/archivedboards/ArchivedBoardsActvitiy.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/archivedboards/ArchivedBoardsActvitiy.java
index 07ca40661..7c3a2d23c 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/archivedboards/ArchivedBoardsActvitiy.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/archivedboards/ArchivedBoardsActvitiy.java
@@ -53,7 +53,7 @@ public class ArchivedBoardsActvitiy extends BrandedActivity implements DeleteBoa
setSupportActionBar(binding.toolbar);
viewModel = new ViewModelProvider(this).get(MainViewModel.class);
- viewModel.setCurrentAccount(account, account.getServerDeckVersionAsObject().isSupported(this));
+ viewModel.setCurrentAccount(account);
syncManager = new SyncManager(this);
adapter = new ArchivedBoardsAdapter(viewModel.isCurrentAccountIsSupportedVersion(), getSupportFragmentManager(), (board) -> syncManager.dearchiveBoard(board));
@@ -67,8 +67,8 @@ public class ArchivedBoardsActvitiy extends BrandedActivity implements DeleteBoa
}
@Override
- public void applyBrand(int mainColor, int textColor) {
- applyBrandToPrimaryToolbar(mainColor, textColor, binding.toolbar);
+ public void applyBrand(int mainColor) {
+ // Nothing to do...
}
@NonNull
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/archivedcards/ArchivedCardsActvitiy.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/archivedcards/ArchivedCardsActvitiy.java
index 00500ae97..ed2ee7097 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/archivedcards/ArchivedCardsActvitiy.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/archivedcards/ArchivedCardsActvitiy.java
@@ -65,8 +65,8 @@ public class ArchivedCardsActvitiy extends BrandedActivity {
}
@Override
- public void applyBrand(int mainColor, int textColor) {
- applyBrandToPrimaryToolbar(mainColor, textColor, binding.toolbar);
+ public void applyBrand(int mainColor) {
+ // Nothing to do...
}
@NonNull
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 1283695e0..e5d0a482b 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
@@ -15,10 +15,11 @@ import it.niedermann.nextcloud.deck.databinding.DialogTextColorInputBinding;
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.BrandedActivity;
import it.niedermann.nextcloud.deck.ui.branding.BrandedAlertDialogBuilder;
import it.niedermann.nextcloud.deck.ui.branding.BrandedDialogFragment;
+import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.applyBrandToEditText;
+
public class EditBoardDialogFragment extends BrandedDialogFragment {
private DialogTextColorInputBinding binding;
@@ -95,7 +96,7 @@ public class EditBoardDialogFragment extends BrandedDialogFragment {
}
@Override
- public void applyBrand(int mainColor, int textColor) {
- BrandedActivity.applyBrandToEditText(mainColor, textColor, binding.input);
+ public void applyBrand(int mainColor) {
+ applyBrandToEditText(mainColor, binding.input);
}
} \ No newline at end of file
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 4ab3ac80b..e5a50d9f4 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
@@ -17,7 +17,6 @@ import java.util.LinkedList;
import java.util.List;
import java.util.NoSuchElementException;
-import it.niedermann.nextcloud.deck.Application;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.databinding.ItemAccessControlBinding;
import it.niedermann.nextcloud.deck.databinding.ItemAccessControlOwnerBinding;
@@ -25,10 +24,10 @@ 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.branding.BrandedActivity;
import it.niedermann.nextcloud.deck.util.ViewUtil;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandedActivity.getSecondaryForegroundColorDependingOnTheme;
+import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.getSecondaryForegroundColorDependingOnTheme;
+import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.isBrandingEnabled;
public class AccessControlAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements Branded {
@@ -122,7 +121,7 @@ public class AccessControlAdapter extends RecyclerView.Adapter<RecyclerView.View
accessControlChangedListener.updateAccessControl(ac);
});
- if (Application.isBrandingEnabled(context)) {
+ if (isBrandingEnabled(context)) {
if (hasManagePermission) {
brandSwitch(context, acHolder.binding.permissionEdit, mainColor);
brandSwitch(context, acHolder.binding.permissionManage, mainColor);
@@ -159,9 +158,9 @@ public class AccessControlAdapter extends RecyclerView.Adapter<RecyclerView.View
}
@Override
- public void applyBrand(int mainColor, int textColor) {
- if (Application.isBrandingEnabled(context)) {
- this.mainColor = BrandedActivity.getSecondaryForegroundColorDependingOnTheme(context, mainColor);
+ public void applyBrand(int mainColor) {
+ if (isBrandingEnabled(context)) {
+ this.mainColor = getSecondaryForegroundColorDependingOnTheme(context, mainColor);
notifyDataSetChanged();
}
}
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 9b170aacd..33c0fe5b1 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
@@ -25,7 +25,6 @@ import it.niedermann.nextcloud.deck.model.full.FullBoard;
import it.niedermann.nextcloud.deck.persistence.sync.SyncManager;
import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.util.WrappedLiveData;
import it.niedermann.nextcloud.deck.ui.MainViewModel;
-import it.niedermann.nextcloud.deck.ui.branding.BrandedActivity;
import it.niedermann.nextcloud.deck.ui.branding.BrandedAlertDialogBuilder;
import it.niedermann.nextcloud.deck.ui.branding.BrandedDialogFragment;
import it.niedermann.nextcloud.deck.ui.branding.BrandedSnackbar;
@@ -34,6 +33,7 @@ import it.niedermann.nextcloud.deck.ui.exception.ExceptionDialogFragment;
import static it.niedermann.nextcloud.deck.persistence.sync.adapters.db.util.LiveDataHelper.observeOnce;
import static it.niedermann.nextcloud.deck.ui.board.accesscontrol.AccessControlAdapter.HEADER_ITEM_LOCAL_ID;
+import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.applyBrandToEditText;
public class AccessControlDialogFragment extends BrandedDialogFragment implements AccessControlChangedListener, OnItemClickListener {
@@ -135,9 +135,9 @@ public class AccessControlDialogFragment extends BrandedDialogFragment implement
}
@Override
- public void applyBrand(int mainColor, int textColor) {
- BrandedActivity.applyBrandToEditText(mainColor, textColor, binding.people);
- this.adapter.applyBrand(mainColor, textColor);
+ public void applyBrand(int mainColor) {
+ applyBrandToEditText(mainColor, binding.people);
+ this.adapter.applyBrand(mainColor);
}
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 7570510fd..d460d1590 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
@@ -11,10 +11,11 @@ import androidx.fragment.app.DialogFragment;
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.BrandedActivity;
import it.niedermann.nextcloud.deck.ui.branding.BrandedAlertDialogBuilder;
import it.niedermann.nextcloud.deck.ui.branding.BrandedDialogFragment;
+import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.applyBrandToEditText;
+
public class EditLabelDialogFragment extends BrandedDialogFragment {
private DialogTextColorInputBinding binding;
@@ -83,7 +84,7 @@ public class EditLabelDialogFragment extends BrandedDialogFragment {
}
@Override
- public void applyBrand(int mainColor, int textColor) {
- BrandedActivity.applyBrandToEditText(mainColor, textColor, binding.input);
+ public void applyBrand(int mainColor) {
+ applyBrandToEditText(mainColor, binding.input);
}
} \ 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 34c06530c..d8bb57a11 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
@@ -11,12 +11,13 @@ import java.util.LinkedList;
import java.util.List;
import java.util.NoSuchElementException;
-import it.niedermann.nextcloud.deck.Application;
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 it.niedermann.nextcloud.deck.ui.branding.BrandedActivity;
+
+import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.getSecondaryForegroundColorDependingOnTheme;
+import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.isBrandingEnabled;
public class ManageLabelsAdapter extends RecyclerView.Adapter<ManageLabelsViewHolder> implements Branded {
@@ -74,9 +75,9 @@ public class ManageLabelsAdapter extends RecyclerView.Adapter<ManageLabelsViewHo
}
@Override
- public void applyBrand(int mainColor, int textColor) {
- if (Application.isBrandingEnabled(context)) {
- this.mainColor = BrandedActivity.getSecondaryForegroundColorDependingOnTheme(context, mainColor);
+ public void applyBrand(int mainColor) {
+ if (isBrandingEnabled(context)) {
+ 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 d6727f4b0..3391c7a99 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
@@ -20,12 +20,13 @@ import it.niedermann.nextcloud.deck.model.Label;
import it.niedermann.nextcloud.deck.persistence.sync.SyncManager;
import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.util.WrappedLiveData;
import it.niedermann.nextcloud.deck.ui.MainViewModel;
-import it.niedermann.nextcloud.deck.ui.branding.BrandedActivity;
import it.niedermann.nextcloud.deck.ui.branding.BrandedAlertDialogBuilder;
import it.niedermann.nextcloud.deck.ui.branding.BrandedDeleteAlertDialogBuilder;
import it.niedermann.nextcloud.deck.ui.branding.BrandedDialogFragment;
import static it.niedermann.nextcloud.deck.persistence.sync.adapters.db.util.LiveDataHelper.observeOnce;
+import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.applyBrandToEditText;
+import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.applyBrandToFAB;
public class ManageLabelsDialogFragment extends BrandedDialogFragment implements ManageLabelListener, EditLabelListener {
@@ -108,9 +109,9 @@ public class ManageLabelsDialogFragment extends BrandedDialogFragment implements
}
@Override
- public void applyBrand(int mainColor, int textColor) {
- BrandedActivity.applyBrandToFAB(mainColor, textColor, binding.fab);
- BrandedActivity.applyBrandToEditText(mainColor, textColor, binding.addLabelTitle);
+ public void applyBrand(int mainColor) {
+ applyBrandToFAB(mainColor, binding.fab);
+ applyBrandToEditText(mainColor, binding.addLabelTitle);
}
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
index 15ffb8528..99ad9c074 100644
--- 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
@@ -5,5 +5,5 @@ import androidx.annotation.UiThread;
public interface Branded {
@UiThread
- void applyBrand(@ColorInt int mainColor, @ColorInt int textColor);
+ void applyBrand(@ColorInt int mainColor);
} \ No newline at end of file
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedActivity.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedActivity.java
index 6278ac1f5..3420e888b 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedActivity.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedActivity.java
@@ -1,158 +1,41 @@
package it.niedermann.nextcloud.deck.ui.branding;
-import android.content.Context;
-import android.content.res.ColorStateList;
-import android.graphics.Color;
-import android.graphics.PorterDuff;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
+import android.util.TypedValue;
import android.view.Menu;
-import android.view.View;
-import android.view.Window;
-import android.widget.EditText;
import androidx.annotation.ColorInt;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
-import androidx.appcompat.widget.Toolbar;
-import androidx.core.graphics.drawable.DrawableCompat;
-import com.google.android.material.floatingactionbutton.FloatingActionButton;
-import com.google.android.material.tabs.TabLayout;
-
-import it.niedermann.nextcloud.deck.Application;
-import it.niedermann.nextcloud.deck.DeckLog;
import it.niedermann.nextcloud.deck.R;
-import it.niedermann.nextcloud.deck.util.ColorUtil;
-import static android.os.Build.VERSION.SDK_INT;
-import static android.os.Build.VERSION_CODES.LOLLIPOP;
-import static android.os.Build.VERSION_CODES.M;
-import static it.niedermann.nextcloud.deck.util.ColorUtil.contrastRatioIsSufficient;
-import static it.niedermann.nextcloud.deck.util.ColorUtil.isColorDark;
+import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.isBrandingEnabled;
+import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.readBrandMainColor;
+import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.tintMenuIcon;
public abstract class BrandedActivity extends AppCompatActivity implements Branded {
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- if (Application.isBrandingEnabled(this)) {
- @ColorInt final int mainColor = Application.readBrandMainColor(this);
- @ColorInt final int textColor = Application.readBrandTextColor(this);
- setTheme(ColorUtil.isColorDark(textColor) ? R.style.AppThemeLightBrand : R.style.AppTheme);
- applyBrandToStatusbar(getWindow(), mainColor, textColor);
- } else {
- setTheme(R.style.AppTheme);
- }
- }
+ @ColorInt
+ protected int colorAccent;
@Override
protected void onStart() {
super.onStart();
- if (Application.isBrandingEnabled(this)) {
- @ColorInt final int mainColor = Application.readBrandMainColor(this);
- @ColorInt final int textColor = Application.readBrandTextColor(this);
- applyBrand(mainColor, textColor);
+ final TypedValue typedValue = new TypedValue();
+ getTheme().resolveAttribute(R.attr.colorAccent, typedValue, true);
+ colorAccent = typedValue.data;
+
+ if (isBrandingEnabled(this)) {
+ @ColorInt final int mainColor = readBrandMainColor(this);
+ applyBrand(mainColor);
}
}
- // TODO maybe this can be handled in R.style.AppThemLightBrand
@Override
public boolean onCreateOptionsMenu(Menu menu) {
- @ColorInt final int textColor = Application.readBrandTextColor(this);
for (int i = 0; i < menu.size(); i++) {
- Drawable drawable = menu.getItem(i).getIcon();
- if (drawable != null) {
- drawable = DrawableCompat.wrap(drawable);
- DrawableCompat.setTint(drawable, textColor);
- menu.getItem(i).setIcon(drawable);
- }
+ tintMenuIcon(menu.getItem(i), colorAccent);
}
return super.onCreateOptionsMenu(menu);
}
-
- public static void applyBrandToStatusbar(@NonNull Window window, @ColorInt int mainColor, @ColorInt int textColor) {
- if (SDK_INT >= LOLLIPOP) { // Set status bar color
- window.setStatusBarColor(mainColor);
- if (SDK_INT >= M) { // Set icon and text color of status bar
- final View decorView = window.getDecorView();
- if (isColorDark(mainColor)) {
- int flags = decorView.getSystemUiVisibility();
- flags &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
- decorView.setSystemUiVisibility(flags);
- } else {
- decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
- }
- }
- }
- }
-
- public static void applyBrandToPrimaryToolbar(@ColorInt int mainColor, @ColorInt int textColor, @NonNull Toolbar toolbar) {
- toolbar.setBackgroundColor(mainColor);
- toolbar.setTitleTextColor(textColor);
- final Drawable overflowDrawable = toolbar.getOverflowIcon();
- if (overflowDrawable != null) {
- overflowDrawable.setColorFilter(textColor, PorterDuff.Mode.SRC_ATOP);
- toolbar.setOverflowIcon(overflowDrawable);
- }
-
- final Drawable navigationDrawable = toolbar.getNavigationIcon();
- if (navigationDrawable != null) {
- navigationDrawable.setColorFilter(textColor, PorterDuff.Mode.SRC_ATOP);
- toolbar.setNavigationIcon(navigationDrawable);
- }
- }
-
- protected void applyBrandToPrimaryTabLayout(@ColorInt int mainColor, @ColorInt int textColor, @NonNull TabLayout tabLayout) {
- tabLayout.setBackgroundColor(mainColor);
- tabLayout.setTabTextColors(textColor, textColor);
- tabLayout.setTabIconTint(ColorStateList.valueOf(textColor));
- tabLayout.setSelectedTabIndicatorColor(textColor);
- }
-
- public static void applyBrandToFAB(@ColorInt int mainColor, @ColorInt int textColor, @NonNull FloatingActionButton fab) {
- fab.setSupportBackgroundTintList(ColorStateList.valueOf(mainColor));
- fab.setColorFilter(textColor);
- }
-
- public static void applyBrandToEditText(@ColorInt int mainColor, @ColorInt int textColor, @NonNull EditText editText) {
- @ColorInt final int finalMainColor = getSecondaryForegroundColorDependingOnTheme(editText.getContext(), mainColor);
- DrawableCompat.setTintList(editText.getBackground(), new ColorStateList(
- new int[][]{
- new int[]{android.R.attr.state_active},
- new int[]{android.R.attr.state_activated},
- new int[]{android.R.attr.state_focused},
- new int[]{android.R.attr.state_pressed},
- new int[]{}
- },
- new int[]{
- finalMainColor,
- finalMainColor,
- finalMainColor,
- finalMainColor,
- editText.getContext().getResources().getColor(R.color.fg_secondary)
- }
- ));
- }
-
- /**
- * 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) {
- final boolean isDarkTheme = Application.getAppTheme(context);
- if (isDarkTheme && !contrastRatioIsSufficient(mainColor, Color.BLACK)) {
- DeckLog.verbose("Contrast ratio between brand color " + String.format("#%06X", (0xFFFFFF & mainColor)) + " and dark theme is too low. Falling back to WHITE as brand color.");
- return Color.WHITE;
- } else if (!isDarkTheme && !contrastRatioIsSufficient(mainColor, Color.WHITE)) {
- DeckLog.verbose("Contrast ratio between brand color " + String.format("#%06X", (0xFFFFFF & mainColor)) + " and light theme is too low. Falling back to BLACK as brand color.");
- return Color.BLACK;
- } else {
- return mainColor;
- }
- }
}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedAlertDialogBuilder.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedAlertDialogBuilder.java
index d502772b3..cfeffe7dc 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedAlertDialogBuilder.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedAlertDialogBuilder.java
@@ -11,7 +11,8 @@ import androidx.appcompat.app.AlertDialog;
import org.jetbrains.annotations.NotNull;
-import it.niedermann.nextcloud.deck.Application;
+import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.getSecondaryForegroundColorDependingOnTheme;
+import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.readBrandMainColor;
public class BrandedAlertDialogBuilder extends AlertDialog.Builder implements Branded {
@@ -27,23 +28,22 @@ public class BrandedAlertDialogBuilder extends AlertDialog.Builder implements Br
this.dialog = super.create();
@NonNull Context context = getContext();
- @ColorInt final int mainColor = Application.readBrandMainColor(context);
- @ColorInt final int textColor = Application.readBrandTextColor(context);
- applyBrand(mainColor, textColor);
- dialog.setOnShowListener(dialog -> applyBrand(mainColor, textColor));
+ @ColorInt final int mainColor = readBrandMainColor(context);
+ applyBrand(mainColor);
+ dialog.setOnShowListener(dialog -> applyBrand(mainColor));
return dialog;
}
@CallSuper
@Override
- public void applyBrand(int mainColor, int textColor) {
+ public void applyBrand(int mainColor) {
final Button[] buttons = new Button[3];
buttons[0] = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
buttons[1] = dialog.getButton(DialogInterface.BUTTON_NEGATIVE);
buttons[2] = dialog.getButton(DialogInterface.BUTTON_NEUTRAL);
for (Button button : buttons) {
if (button != null) {
- button.setTextColor(BrandedActivity.getSecondaryForegroundColorDependingOnTheme(button.getContext(), mainColor));
+ button.setTextColor(getSecondaryForegroundColorDependingOnTheme(button.getContext(), mainColor));
}
}
}
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/branding/BrandedDatePickerDialog.java
index b56ad3669..5bef66f2c 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedDatePickerDialog.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedDatePickerDialog.java
@@ -10,37 +10,41 @@ 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.date.DatePickerDialog;
import java.util.Calendar;
-import it.niedermann.nextcloud.deck.Application;
+import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.util.ColorUtil;
+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.isBrandingEnabled;
+import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.readBrandMainColor;
+
public class BrandedDatePickerDialog extends DatePickerDialog implements Branded {
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
@Nullable Context context = getContext();
if (context != null) {
- setThemeDark(Application.getAppTheme(context));
- if (Application.isBrandingEnabled(context)) {
- @ColorInt final int mainColor = Application.readBrandMainColor(context);
- @ColorInt final int textColor = Application.readBrandTextColor(context);
- applyBrand(mainColor, textColor);
+ setThemeDark(isDarkTheme(context));
+ if (isBrandingEnabled(context)) {
+ applyBrand(readBrandMainColor(context));
}
}
return super.onCreateView(inflater, container, savedInstanceState);
}
@Override
- public void applyBrand(int mainColor, int textColor) {
- @ColorInt final int buttonTextColor = BrandedActivity.getSecondaryForegroundColorDependingOnTheme(requireContext(), mainColor);
+ public void applyBrand(int mainColor) {
+ @ColorInt final int buttonTextColor = getSecondaryForegroundColorDependingOnTheme(requireContext(), mainColor);
setOkColor(buttonTextColor);
setCancelColor(buttonTextColor);
// Text in picker title is always white
- setAccentColor(ColorUtil.contrastRatioIsSufficient(Color.WHITE, mainColor) ? mainColor : textColor);
+ setAccentColor(ColorUtil.contrastRatioIsSufficientBigAreas(Color.WHITE, mainColor) ? mainColor : ContextCompat.getColor(requireContext(), R.color.accent));
}
/**
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedDeleteAlertDialogBuilder.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedDeleteAlertDialogBuilder.java
index 29cac691f..ec3cef553 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedDeleteAlertDialogBuilder.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedDeleteAlertDialogBuilder.java
@@ -16,8 +16,8 @@ public class BrandedDeleteAlertDialogBuilder extends BrandedAlertDialogBuilder {
@CallSuper
@Override
- public void applyBrand(int mainColor, int textColor) {
- super.applyBrand(mainColor, textColor);
+ public void applyBrand(int mainColor) {
+ super.applyBrand(mainColor);
final Button positiveButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
if (positiveButton != null) {
positiveButton.setTextColor(getContext().getResources().getColor(R.color.danger));
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
index 75eb90b12..adf3844e9 100644
--- 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
@@ -2,11 +2,11 @@ package it.niedermann.nextcloud.deck.ui.branding;
import android.content.Context;
-import androidx.annotation.ColorInt;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
-import it.niedermann.nextcloud.deck.Application;
+import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.isBrandingEnabled;
+import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.readBrandMainColor;
public abstract class BrandedDialogFragment extends DialogFragment implements Branded {
@@ -16,10 +16,8 @@ public abstract class BrandedDialogFragment extends DialogFragment implements Br
@Nullable Context context = getContext();
if (context != null) {
- if (Application.isBrandingEnabled(context)) {
- @ColorInt final int mainColor = Application.readBrandMainColor(context);
- @ColorInt final int textColor = Application.readBrandTextColor(context);
- applyBrand(mainColor, textColor);
+ if (isBrandingEnabled(context)) {
+ applyBrand(readBrandMainColor(context));
}
}
}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedFragment.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedFragment.java
index 0854b547b..fe202f48c 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedFragment.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedFragment.java
@@ -2,11 +2,11 @@ package it.niedermann.nextcloud.deck.ui.branding;
import android.content.Context;
-import androidx.annotation.ColorInt;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
-import it.niedermann.nextcloud.deck.Application;
+import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.isBrandingEnabled;
+import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.readBrandMainColor;
public abstract class BrandedFragment extends Fragment implements Branded {
@@ -15,10 +15,8 @@ public abstract class BrandedFragment extends Fragment implements Branded {
super.onStart();
@Nullable Context context = getContext();
- if (context != null && Application.isBrandingEnabled(context)) {
- @ColorInt final int mainColor = Application.readBrandMainColor(context);
- @ColorInt final int textColor = Application.readBrandTextColor(context);
- applyBrand(mainColor, textColor);
+ if (context != null && isBrandingEnabled(context)) {
+ 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
index dd7f0a037..e01c523c6 100644
--- 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
@@ -10,10 +10,9 @@ import androidx.annotation.Nullable;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceViewHolder;
-import it.niedermann.nextcloud.deck.Application;
-
-import static it.niedermann.nextcloud.deck.Application.readBrandMainColor;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandedActivity.getSecondaryForegroundColorDependingOnTheme;
+import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.getSecondaryForegroundColorDependingOnTheme;
+import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.isBrandingEnabled;
+import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.readBrandMainColor;
public class BrandedPreferenceCategory extends PreferenceCategory {
@@ -21,7 +20,7 @@ public class BrandedPreferenceCategory extends PreferenceCategory {
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
- if (Application.isBrandingEnabled(getContext())) {
+ if (isBrandingEnabled(getContext())) {
final View v = holder.itemView.findViewById(android.R.id.title);
@Nullable final Context context = getContext();
if (context != null && v instanceof TextView) {
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
index b28b00ac0..20e6f8dc8 100644
--- 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
@@ -3,24 +3,31 @@ package it.niedermann.nextcloud.deck.ui.branding;
import android.graphics.Color;
import android.view.View;
+import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
+import androidx.core.content.ContextCompat;
import com.google.android.material.snackbar.BaseTransientBottomBar;
import com.google.android.material.snackbar.Snackbar;
-import it.niedermann.nextcloud.deck.Application;
+import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.util.ColorUtil;
+import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.isBrandingEnabled;
+import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.readBrandMainColor;
+
public class BrandedSnackbar {
@NonNull
public static Snackbar make(
@NonNull View view, @NonNull CharSequence text, @BaseTransientBottomBar.Duration int duration) {
final Snackbar snackbar = Snackbar.make(view, text, duration);
- if (Application.isBrandingEnabled(view.getContext())) {
- int color = Application.readBrandMainColor(view.getContext());
+ if (isBrandingEnabled(view.getContext())) {
+ @ColorInt final int color = readBrandMainColor(view.getContext());
snackbar.setActionTextColor(ColorUtil.isColorDark(color) ? Color.WHITE : color);
+ } else {
+ snackbar.setActionTextColor(ContextCompat.getColor(view.getContext(), R.color.primary));
}
return snackbar;
}
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
index a0b2c222e..463800a0a 100644
--- 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
@@ -13,21 +13,16 @@ import androidx.core.graphics.drawable.DrawableCompat;
import androidx.preference.PreferenceViewHolder;
import androidx.preference.SwitchPreference;
-import it.niedermann.nextcloud.deck.Application;
import it.niedermann.nextcloud.deck.R;
-import static android.os.Build.VERSION.SDK_INT;
-import static android.os.Build.VERSION_CODES.JELLY_BEAN;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandedActivity.getSecondaryForegroundColorDependingOnTheme;
+import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.getSecondaryForegroundColorDependingOnTheme;
+import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.isBrandingEnabled;
public class BrandedSwitchPreference extends SwitchPreference implements Branded {
@ColorInt
private Integer mainColor = null;
- @ColorInt
- private Integer textColor = null;
-
@Nullable
private Switch switchView;
@@ -51,26 +46,25 @@ public class BrandedSwitchPreference extends SwitchPreference implements Branded
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
- if (Application.isBrandingEnabled(getContext()) && holder.itemView instanceof ViewGroup) {
+ if (isBrandingEnabled(getContext()) && holder.itemView instanceof ViewGroup) {
switchView = findSwitchWidget(holder.itemView);
- if (mainColor != null && textColor != null) {
+ if (mainColor != null) {
applyBrand();
}
}
}
@Override
- public void applyBrand(@ColorInt int mainColor, @ColorInt int textColor) {
+ public void applyBrand(@ColorInt int mainColor) {
this.mainColor = mainColor;
- this.textColor = textColor;
// onBindViewHolder is called after applyBrand, therefore we have to store the given values and apply them later.
- if (Application.isBrandingEnabled(getContext())) {
+ if (isBrandingEnabled(getContext())) {
applyBrand();
}
}
private void applyBrand() {
- if (switchView != null && SDK_INT >= JELLY_BEAN) {
+ 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(
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/branding/BrandedTimePickerDialog.java
index cd67d7820..a1963aa18 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedTimePickerDialog.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandedTimePickerDialog.java
@@ -10,37 +10,41 @@ 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.util.Calendar;
-import it.niedermann.nextcloud.deck.Application;
+import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.util.ColorUtil;
+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.isBrandingEnabled;
+import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.readBrandMainColor;
+
public class BrandedTimePickerDialog extends TimePickerDialog implements Branded {
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
@Nullable Context context = getContext();
if (context != null) {
- setThemeDark(Application.getAppTheme(context));
- if (Application.isBrandingEnabled(context)) {
- @ColorInt final int mainColor = Application.readBrandMainColor(context);
- @ColorInt final int textColor = Application.readBrandTextColor(context);
- applyBrand(mainColor, textColor);
+ setThemeDark(isDarkTheme(context));
+ if (isBrandingEnabled(context)) {
+ applyBrand(readBrandMainColor(context));
}
}
return super.onCreateView(inflater, container, savedInstanceState);
}
@Override
- public void applyBrand(int mainColor, int textColor) {
- @ColorInt final int buttonTextColor = BrandedActivity.getSecondaryForegroundColorDependingOnTheme(requireContext(), mainColor);
+ public void applyBrand(int mainColor) {
+ @ColorInt final int buttonTextColor = getSecondaryForegroundColorDependingOnTheme(requireContext(), mainColor);
setOkColor(buttonTextColor);
setCancelColor(buttonTextColor);
// Text in picker title is always white
- setAccentColor(ColorUtil.contrastRatioIsSufficient(Color.WHITE, mainColor) ? mainColor : textColor);
+ setAccentColor(ColorUtil.contrastRatioIsSufficientBigAreas(Color.WHITE, mainColor) ? mainColor : ContextCompat.getColor(requireContext(), R.color.accent));
}
/**
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
new file mode 100644
index 000000000..02ad6b309
--- /dev/null
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/branding/BrandingUtil.java
@@ -0,0 +1,128 @@
+package it.niedermann.nextcloud.deck.ui.branding;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.res.ColorStateList;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
+import android.view.MenuItem;
+import android.widget.EditText;
+
+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.FloatingActionButton;
+import com.google.android.material.tabs.TabLayout;
+
+import it.niedermann.nextcloud.deck.DeckLog;
+import it.niedermann.nextcloud.deck.R;
+
+import static it.niedermann.nextcloud.deck.DeckApplication.isDarkTheme;
+import static it.niedermann.nextcloud.deck.util.ColorUtil.contrastRatioIsSufficient;
+import static it.niedermann.nextcloud.deck.util.ColorUtil.contrastRatioIsSufficientBigAreas;
+import static it.niedermann.nextcloud.deck.util.ColorUtil.getContrastRatio;
+import static it.niedermann.nextcloud.deck.util.ColorUtil.getForegroundColorForBackgroundColor;
+
+public abstract class BrandingUtil {
+
+ private BrandingUtil() {
+ // Util class
+ }
+
+ public static boolean isBrandingEnabled(@NonNull Context context) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+ return prefs.getBoolean(context.getString(R.string.pref_key_branding), true);
+ }
+
+ @ColorInt
+ public static int readBrandMainColor(@NonNull Context context) {
+ if (isBrandingEnabled(context)) {
+ SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext());
+ DeckLog.log("--- Read: shared_preference_theme_main");
+ return sharedPreferences.getInt(context.getString(R.string.shared_preference_theme_main), context.getApplicationContext().getResources().getColor(R.color.defaultBrand));
+ } else {
+ return context.getResources().getColor(R.color.defaultBrand);
+ }
+ }
+
+ public static void saveBrandColors(@NonNull Context context, @ColorInt int mainColor) {
+ if (isBrandingEnabled(context) && context instanceof BrandedActivity) {
+ final BrandedActivity activity = (BrandedActivity) context;
+ activity.applyBrand(mainColor);
+ }
+ SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(context).edit();
+ DeckLog.log("--- Write: 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) {
+ if (isBrandingEnabled(context) && context instanceof BrandedActivity) {
+ final BrandedActivity activity = (BrandedActivity) context;
+ activity.applyBrand(ContextCompat.getColor(context, R.color.defaultBrand));
+ }
+ SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(context).edit();
+ DeckLog.log("--- Write: Remove: 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 ? getForegroundColorForBackgroundColor(mainColor) : mainColor);
+ }
+
+ public static void applyBrandToPrimaryTabLayout(@ColorInt int mainColor, @NonNull TabLayout tabLayout) {
+ @ColorInt int finalMainColor = getSecondaryForegroundColorDependingOnTheme(tabLayout.getContext(), mainColor);
+ tabLayout.setBackgroundColor(ContextCompat.getColor(tabLayout.getContext(), R.color.primary));
+ final boolean contrastRatioIsSufficient = getContrastRatio(mainColor, ContextCompat.getColor(tabLayout.getContext(), R.color.primary)) > 1.7d;
+ tabLayout.setSelectedTabIndicatorColor(contrastRatioIsSufficient ? mainColor : finalMainColor);
+ }
+
+ public static void applyBrandToEditText(@ColorInt int mainColor, @NonNull EditText editText) {
+ @ColorInt final int finalMainColor = getSecondaryForegroundColorDependingOnTheme(editText.getContext(), mainColor);
+ DrawableCompat.setTintList(editText.getBackground(), new ColorStateList(
+ new int[][]{
+ new int[]{android.R.attr.state_active},
+ new int[]{android.R.attr.state_activated},
+ new int[]{android.R.attr.state_focused},
+ new int[]{android.R.attr.state_pressed},
+ new int[]{}
+ },
+ new int[]{
+ finalMainColor,
+ finalMainColor,
+ finalMainColor,
+ finalMainColor,
+ editText.getContext().getResources().getColor(R.color.fg_secondary)
+ }
+ ));
+ }
+
+ public static void tintMenuIcon(@NonNull MenuItem menuItem, @ColorInt int color) {
+ Drawable drawable = menuItem.getIcon();
+ if (drawable != null) {
+ drawable = DrawableCompat.wrap(drawable);
+ DrawableCompat.setTint(drawable, color);
+ menuItem.setIcon(drawable);
+ }
+ }
+}
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 b618c16a9..986a66cad 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
@@ -44,13 +44,13 @@ import it.niedermann.nextcloud.deck.persistence.sync.SyncManager;
import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.util.LiveDataHelper;
import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.util.WrappedLiveData;
import it.niedermann.nextcloud.deck.ui.branding.Branded;
-import it.niedermann.nextcloud.deck.ui.branding.BrandedActivity;
import it.niedermann.nextcloud.deck.ui.branding.BrandedAlertDialogBuilder;
import it.niedermann.nextcloud.deck.ui.exception.ExceptionDialogFragment;
import it.niedermann.nextcloud.deck.util.DateUtil;
import it.niedermann.nextcloud.deck.util.ViewUtil;
import static it.niedermann.nextcloud.deck.persistence.sync.adapters.db.util.LiveDataHelper.observeOnce;
+import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.getSecondaryForegroundColorDependingOnTheme;
import static it.niedermann.nextcloud.deck.util.MimeTypeUtil.TEXT_PLAIN;
public class CardAdapter extends RecyclerView.Adapter<ItemCardViewHolder> implements DragAndDropAdapter<FullCard>, Branded {
@@ -346,8 +346,8 @@ public class CardAdapter extends RecyclerView.Adapter<ItemCardViewHolder> implem
}
@Override
- public void applyBrand(int mainColor, int textColor) {
- this.mainColor = BrandedActivity.getSecondaryForegroundColorDependingOnTheme(context, mainColor);
+ public void applyBrand(int mainColor) {
+ this.mainColor = getSecondaryForegroundColorDependingOnTheme(context, mainColor);
notifyDataSetChanged();
}
}
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 c039b2952..0710b7d7c 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
@@ -2,7 +2,7 @@ package it.niedermann.nextcloud.deck.ui.card;
import android.content.Context;
import android.content.Intent;
-import android.graphics.Color;
+import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.text.Editable;
import android.text.InputFilter;
@@ -15,11 +15,13 @@ import android.view.WindowManager;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.graphics.drawable.DrawableCompat;
import androidx.lifecycle.ViewModelProvider;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;
+import it.niedermann.nextcloud.deck.DeckLog;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.databinding.ActivityEditBinding;
import it.niedermann.nextcloud.deck.model.Account;
@@ -31,6 +33,8 @@ import it.niedermann.nextcloud.deck.util.CardUtil;
import static android.graphics.Color.parseColor;
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.isBrandingEnabled;
public class EditActivity extends BrandedActivity {
private static final String BUNDLE_KEY_ACCOUNT = "account";
@@ -87,9 +91,9 @@ public class EditActivity extends BrandedActivity {
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
+ applyBrand(colorAccent);
setIntent(intent);
loadDataFromIntent();
- applyBrand(parseColor(viewModel.getAccount().getColor()), parseColor(viewModel.getAccount().getTextColor()));
}
private void loadDataFromIntent() {
@@ -117,6 +121,7 @@ public class EditActivity extends BrandedActivity {
final long boardId = args.getLong(BUNDLE_KEY_BOARD_ID);
observeOnce(syncManager.getFullBoardById(account.getId(), boardId), EditActivity.this, (fullBoard -> {
+ applyBrand(parseColor('#' + fullBoard.getBoard().getColor()));
viewModel.setCanEdit(fullBoard.getBoard().isPermissionEdit());
invalidateOptionsMenu();
if (viewModel.isCreateMode()) {
@@ -290,12 +295,16 @@ public class EditActivity extends BrandedActivity {
}
@Override
- public void applyBrand(int mainColor, int textColor) {
- applyBrandToPrimaryToolbar(mainColor, textColor, binding.toolbar);
- applyBrandToPrimaryTabLayout(mainColor, textColor, binding.tabLayout);
- final int highlightColor = Color.argb(77, Color.red(textColor), Color.green(textColor), Color.blue(textColor));
- binding.title.setHighlightColor(highlightColor);
- binding.title.setTextColor(textColor);
+ public void applyBrand(int mainColor) {
+ if(isBrandingEnabled(this)) {
+ final Drawable navigationIcon = binding.toolbar.getNavigationIcon();
+ if (navigationIcon == null) {
+ DeckLog.error("Excpected navigationIcon to be present.");
+ } else {
+ DrawableCompat.setTint(binding.toolbar.getNavigationIcon(), colorAccent);
+ }
+ applyBrandToPrimaryTabLayout(mainColor, binding.tabLayout);
+ }
}
@NonNull
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 3ecee8583..a72ed8ef2 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
@@ -35,8 +35,6 @@ import it.niedermann.nextcloud.deck.util.DateUtil;
import it.niedermann.nextcloud.deck.util.MimeTypeUtil;
import static androidx.recyclerview.widget.RecyclerView.NO_ID;
-import static it.niedermann.nextcloud.deck.Application.readBrandMainColor;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandedActivity.getSecondaryForegroundColorDependingOnTheme;
import static it.niedermann.nextcloud.deck.util.ClipboardUtil.copyToClipboard;
@SuppressWarnings("WeakerAccess")
@@ -73,7 +71,6 @@ public class CardAttachmentAdapter extends RecyclerView.Adapter<AttachmentViewHo
this.attachmentClickedListener = attachmentClickedListener;
this.account = account;
this.cardLocalId = cardLocalId == null ? NO_ID : cardLocalId;
- this.mainColor = getSecondaryForegroundColorDependingOnTheme(context, readBrandMainColor(context));
setHasStableIds(true);
}
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 dff12272e..c291c5bdf 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
@@ -44,7 +44,7 @@ import it.niedermann.nextcloud.deck.ui.card.EditCardViewModel;
import it.niedermann.nextcloud.deck.ui.exception.ExceptionDialogFragment;
import static it.niedermann.nextcloud.deck.persistence.sync.adapters.db.util.LiveDataHelper.observeOnce;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandedActivity.applyBrandToFAB;
+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.AttachmentUtil.copyContentUriToTempFile;
@@ -275,7 +275,7 @@ public class CardAttachmentsFragment extends BrandedFragment implements Attachme
}
@Override
- public void applyBrand(int mainColor, int textColor) {
- applyBrandToFAB(mainColor, textColor, binding.fab);
+ public void applyBrand(int mainColor) {
+ applyBrandToFAB(mainColor, binding.fab);
}
}
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 5e9324a3c..169a37c79 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
@@ -16,8 +16,8 @@ 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 static it.niedermann.nextcloud.deck.Application.readBrandMainColor;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandedActivity.getSecondaryForegroundColorDependingOnTheme;
+import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.getSecondaryForegroundColorDependingOnTheme;
+import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.readBrandMainColor;
public class CardCommentsAdapter extends RecyclerView.Adapter<ItemCommentViewHolder> {
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 f43ccb5a0..692f8eb8f 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
@@ -16,10 +16,11 @@ import java.util.Objects;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.databinding.DialogAddCommentBinding;
-import it.niedermann.nextcloud.deck.ui.branding.BrandedActivity;
import it.niedermann.nextcloud.deck.ui.branding.BrandedAlertDialogBuilder;
import it.niedermann.nextcloud.deck.ui.branding.BrandedDialogFragment;
+import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.applyBrandToEditText;
+
public class CardCommentsEditDialogFragment extends BrandedDialogFragment {
private static final String BUNDLE_KEY_COMMENT_ID = "commentId";
private static final String BUNDLE_KEY_COMMENT_MESSAGE = "commentMessage";
@@ -78,8 +79,8 @@ public class CardCommentsEditDialogFragment extends BrandedDialogFragment {
}
@Override
- public void applyBrand(int mainColor, int textColor) {
- BrandedActivity.applyBrandToEditText(mainColor, textColor, binding.input);
+ public void applyBrand(int mainColor) {
+ applyBrandToEditText(mainColor, binding.input);
}
}
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 302173544..e261c37a2 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
@@ -29,8 +29,8 @@ import it.niedermann.nextcloud.deck.ui.card.EditCardViewModel;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandedActivity.applyBrandToEditText;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandedActivity.applyBrandToFAB;
+import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.applyBrandToEditText;
+import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.applyBrandToFAB;
import static it.niedermann.nextcloud.deck.util.ViewUtil.setupMentions;
public class CardCommentsFragment extends BrandedFragment implements CommentEditedListener, CommentDeletedListener, CommentSelectAsReplyListener {
@@ -142,9 +142,9 @@ public class CardCommentsFragment extends BrandedFragment implements CommentEdit
}
@Override
- public void applyBrand(int mainColor, int textColor) {
- applyBrandToEditText(mainColor, textColor, binding.message);
- applyBrandToFAB(mainColor, textColor, binding.fab);
+ public void applyBrand(int mainColor) {
+ applyBrandToEditText(mainColor, binding.message);
+ applyBrandToFAB(mainColor, binding.fab);
}
@Override
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 a2a01b618..3182fffa2 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
@@ -58,7 +58,7 @@ import it.niedermann.nextcloud.deck.util.ViewUtil;
import static android.text.format.DateFormat.getDateFormat;
import static it.niedermann.nextcloud.deck.persistence.sync.adapters.db.util.LiveDataHelper.observeOnce;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandedActivity.applyBrandToEditText;
+import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.applyBrandToEditText;
import static it.niedermann.nextcloud.deck.util.DimensionUtil.dpToPx;
public class CardDetailsFragment extends BrandedFragment implements OnDateSetListener, OnTimeSetListener {
@@ -136,12 +136,12 @@ public class CardDetailsFragment extends BrandedFragment implements OnDateSetLis
}
@Override
- public void applyBrand(int mainColor, int textColor) {
- applyBrandToEditText(mainColor, textColor, binding.labels);
- applyBrandToEditText(mainColor, textColor, binding.dueDateDate);
- applyBrandToEditText(mainColor, textColor, binding.dueDateTime);
- applyBrandToEditText(mainColor, textColor, binding.people);
- applyBrandToEditText(mainColor, textColor, binding.description);
+ public void applyBrand(int mainColor) {
+ applyBrandToEditText(mainColor, binding.labels);
+ applyBrandToEditText(mainColor, binding.dueDateDate);
+ applyBrandToEditText(mainColor, binding.dueDateTime);
+ applyBrandToEditText(mainColor, binding.people);
+ applyBrandToEditText(mainColor, binding.description);
}
private void setupDescription() {
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/exception/ExceptionActivity.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/exception/ExceptionActivity.java
index 3ba3eb59f..9eef878c3 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/exception/ExceptionActivity.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/exception/ExceptionActivity.java
@@ -11,6 +11,7 @@ import androidx.appcompat.app.AppCompatActivity;
import it.niedermann.nextcloud.deck.DeckLog;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.databinding.ActivityExceptionBinding;
+import it.niedermann.nextcloud.deck.ui.exception.tips.TipsAdapter;
import it.niedermann.nextcloud.deck.util.ExceptionUtil;
import static it.niedermann.nextcloud.deck.util.ClipboardUtil.copyToClipboard;
@@ -41,6 +42,11 @@ public class ExceptionActivity extends AppCompatActivity {
binding.stacktrace.setText(debugInfo);
+ final TipsAdapter adapter = new TipsAdapter(this::startActivity);
+ binding.tips.setAdapter(adapter);
+ binding.tips.setNestedScrollingEnabled(false);
+ adapter.setThrowable(this, null, throwable);
+
binding.copy.setOnClickListener((v) -> copyToClipboard(this, getString(R.string.simple_exception), "```\n" + debugInfo + "\n```"));
binding.close.setOnClickListener((v) -> finish());
}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/exception/ExceptionDialogFragment.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/exception/ExceptionDialogFragment.java
index 9ab9b70c8..6c0d0ba79 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/exception/ExceptionDialogFragment.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/exception/ExceptionDialogFragment.java
@@ -2,8 +2,6 @@ package it.niedermann.nextcloud.deck.ui.exception;
import android.app.Dialog;
import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
import android.os.Bundle;
import android.view.View;
@@ -13,27 +11,13 @@ import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatDialogFragment;
import androidx.fragment.app.DialogFragment;
-import com.nextcloud.android.sso.exceptions.NextcloudApiNotRespondingException;
-import com.nextcloud.android.sso.exceptions.NextcloudFilesAppNotSupportedException;
-import com.nextcloud.android.sso.exceptions.NextcloudHttpRequestFailedException;
-import com.nextcloud.android.sso.exceptions.TokenMismatchException;
-
-import org.json.JSONException;
-
-import java.net.ConnectException;
-import java.net.SocketTimeoutException;
-
-import it.niedermann.nextcloud.deck.BuildConfig;
import it.niedermann.nextcloud.deck.DeckLog;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.databinding.DialogExceptionBinding;
-import it.niedermann.nextcloud.deck.exceptions.DeckException;
-import it.niedermann.nextcloud.deck.exceptions.UploadAttachmentFailedException;
import it.niedermann.nextcloud.deck.model.Account;
import it.niedermann.nextcloud.deck.ui.exception.tips.TipsAdapter;
import it.niedermann.nextcloud.deck.util.ExceptionUtil;
-import static android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS;
import static it.niedermann.nextcloud.deck.util.ClipboardUtil.copyToClipboard;
public class ExceptionDialogFragment extends AppCompatDialogFragment {
@@ -75,69 +59,7 @@ public class ExceptionDialogFragment extends AppCompatDialogFragment {
DeckLog.logError(throwable);
- if (throwable instanceof TokenMismatchException) {
- adapter.add(R.string.error_dialog_tip_token_mismatch_retry);
- adapter.add(R.string.error_dialog_tip_token_mismatch_clear_storage);
- Intent intent = new Intent(ACTION_APPLICATION_DETAILS_SETTINGS)
- .setData(Uri.parse("package:" + BuildConfig.APPLICATION_ID))
- .putExtra(INTENT_EXTRA_BUTTON_TEXT, R.string.error_action_open_deck_info);
- adapter.add(R.string.error_dialog_tip_clear_storage, intent);
- } else if (throwable instanceof NextcloudFilesAppNotSupportedException) {
- adapter.add(R.string.error_dialog_tip_files_outdated);
- } else if (throwable instanceof NextcloudApiNotRespondingException) {
- adapter.add(R.string.error_dialog_tip_files_force_stop);
- adapter.add(R.string.error_dialog_tip_files_delete_storage);
- } else if (throwable instanceof SocketTimeoutException || throwable instanceof ConnectException) {
- adapter.add(R.string.error_dialog_timeout_instance);
- adapter.add(R.string.error_dialog_timeout_toggle, new Intent(android.provider.Settings.ACTION_WIFI_SETTINGS).putExtra(INTENT_EXTRA_BUTTON_TEXT, R.string.error_action_open_network));
- } else if (throwable instanceof JSONException || throwable instanceof NullPointerException) {
- adapter.add(R.string.error_dialog_check_server);
- } else if (throwable instanceof NextcloudHttpRequestFailedException) {
- int statusCode = ((NextcloudHttpRequestFailedException) throwable).getStatusCode();
- switch (statusCode) {
- case 302:
- adapter.add(R.string.error_dialog_redirect);
- break;
- case 500:
- if (account != null) {
- adapter.add(R.string.error_dialog_check_server_logs, new Intent(Intent.ACTION_VIEW)
- .putExtra(INTENT_EXTRA_BUTTON_TEXT, R.string.error_action_server_logs)
- .setData(Uri.parse(account.getUrl() + getString(R.string.url_fragment_server_logs))));
- } else {
- adapter.add(R.string.error_dialog_check_server_logs);
- }
- break;
- case 503:
- adapter.add(R.string.error_dialog_check_maintenance);
- break;
- case 507:
- adapter.add(R.string.error_dialog_insufficient_storage);
- break;
- }
- } else if (throwable instanceof UploadAttachmentFailedException) {
- adapter.add(R.string.error_dialog_attachment_upload_failed);
- } else if (throwable instanceof DeckException) {
- switch (((DeckException) throwable).getHint()) {
- case CAPABILITIES_VERSION_NOT_PARSABLE:
- if (account != null) {
- adapter.add(R.string.error_dialog_version_not_parsable, new Intent(Intent.ACTION_VIEW)
- .putExtra(INTENT_EXTRA_BUTTON_TEXT, R.string.error_action_install)
- .setData(Uri.parse(account.getUrl() + getString(R.string.url_fragment_install_deck))));
- } else {
- adapter.add(R.string.error_dialog_version_not_parsable);
- }
- break;
- case CAPABILITIES_NOT_PARSABLE:
- default:
- if (account != null) {
- adapter.add(R.string.error_dialog_capabilities_not_parsable, new Intent(Intent.ACTION_VIEW)
- .putExtra(INTENT_EXTRA_BUTTON_TEXT, R.string.error_action_server_logs)
- .setData(Uri.parse(account.getUrl() + getString(R.string.url_fragment_server_logs))));
- } else {
- adapter.add(R.string.error_dialog_capabilities_not_parsable);
- }
- }
- }
+ adapter.setThrowable(requireContext(), account, throwable);
return new AlertDialog.Builder(requireActivity())
.setView(binding.getRoot())
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/exception/tips/TipsAdapter.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/exception/tips/TipsAdapter.java
index 8ca1a4e09..fa4113b1e 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/exception/tips/TipsAdapter.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/exception/tips/TipsAdapter.java
@@ -1,6 +1,11 @@
package it.niedermann.nextcloud.deck.ui.exception.tips;
+import android.content.Context;
import android.content.Intent;
+import android.net.Uri;
+import android.os.Build.VERSION;
+import android.os.Build.VERSION_CODES;
+import android.provider.Settings;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -11,10 +16,26 @@ import androidx.annotation.StringRes;
import androidx.core.util.Consumer;
import androidx.recyclerview.widget.RecyclerView;
+import com.nextcloud.android.sso.exceptions.NextcloudApiNotRespondingException;
+import com.nextcloud.android.sso.exceptions.NextcloudFilesAppNotSupportedException;
+import com.nextcloud.android.sso.exceptions.NextcloudHttpRequestFailedException;
+import com.nextcloud.android.sso.exceptions.TokenMismatchException;
+
+import org.json.JSONException;
+
+import java.net.ConnectException;
+import java.net.SocketTimeoutException;
import java.util.LinkedList;
import java.util.List;
+import it.niedermann.nextcloud.deck.BuildConfig;
import it.niedermann.nextcloud.deck.R;
+import it.niedermann.nextcloud.deck.exceptions.DeckException;
+import it.niedermann.nextcloud.deck.exceptions.UploadAttachmentFailedException;
+import it.niedermann.nextcloud.deck.model.Account;
+
+import static android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS;
+import static it.niedermann.nextcloud.deck.ui.exception.ExceptionDialogFragment.INTENT_EXTRA_BUTTON_TEXT;
public class TipsAdapter extends RecyclerView.Adapter<TipsViewHolder> {
@@ -44,6 +65,77 @@ public class TipsAdapter extends RecyclerView.Adapter<TipsViewHolder> {
return tips.size();
}
+ public void setThrowable(@NonNull Context context, @Nullable Account account, @NonNull Throwable throwable) {
+ if (throwable instanceof TokenMismatchException) {
+ add(R.string.error_dialog_tip_token_mismatch_retry);
+ add(R.string.error_dialog_tip_token_mismatch_clear_storage);
+ Intent intent = new Intent(ACTION_APPLICATION_DETAILS_SETTINGS)
+ .setData(Uri.parse("package:" + BuildConfig.APPLICATION_ID))
+ .putExtra(INTENT_EXTRA_BUTTON_TEXT, R.string.error_action_open_deck_info);
+ add(R.string.error_dialog_tip_clear_storage, intent);
+ } else if (throwable instanceof NextcloudFilesAppNotSupportedException) {
+ add(R.string.error_dialog_tip_files_outdated);
+ } else if (throwable instanceof NextcloudApiNotRespondingException) {
+ if (VERSION.SDK_INT >= VERSION_CODES.M) {
+ add(R.string.error_dialog_tip_disable_battery_optimizations, new Intent().setAction(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS).putExtra(INTENT_EXTRA_BUTTON_TEXT, R.string.error_action_open_battery_settings));
+ } else {
+ add(R.string.error_dialog_tip_disable_battery_optimizations);
+ }
+ add(R.string.error_dialog_tip_files_force_stop);
+ add(R.string.error_dialog_tip_files_delete_storage);
+ } else if (throwable instanceof SocketTimeoutException || throwable instanceof ConnectException) {
+ add(R.string.error_dialog_timeout_instance);
+ add(R.string.error_dialog_timeout_toggle, new Intent(Settings.ACTION_WIFI_SETTINGS).putExtra(INTENT_EXTRA_BUTTON_TEXT, R.string.error_action_open_network));
+ } else if (throwable instanceof JSONException || throwable instanceof NullPointerException) {
+ add(R.string.error_dialog_check_server);
+ } else if (throwable instanceof NextcloudHttpRequestFailedException) {
+ int statusCode = ((NextcloudHttpRequestFailedException) throwable).getStatusCode();
+ switch (statusCode) {
+ case 302:
+ add(R.string.error_dialog_redirect);
+ break;
+ case 500:
+ if (account != null) {
+ add(R.string.error_dialog_check_server_logs, new Intent(Intent.ACTION_VIEW)
+ .putExtra(INTENT_EXTRA_BUTTON_TEXT, R.string.error_action_server_logs)
+ .setData(Uri.parse(account.getUrl() + context.getString(R.string.url_fragment_server_logs))));
+ } else {
+ add(R.string.error_dialog_check_server_logs);
+ }
+ break;
+ case 503:
+ add(R.string.error_dialog_check_maintenance);
+ break;
+ case 507:
+ add(R.string.error_dialog_insufficient_storage);
+ break;
+ }
+ } else if (throwable instanceof UploadAttachmentFailedException) {
+ add(R.string.error_dialog_attachment_upload_failed);
+ } else if (throwable instanceof DeckException) {
+ switch (((DeckException) throwable).getHint()) {
+ case CAPABILITIES_VERSION_NOT_PARSABLE:
+ if (account != null) {
+ add(R.string.error_dialog_version_not_parsable, new Intent(Intent.ACTION_VIEW)
+ .putExtra(INTENT_EXTRA_BUTTON_TEXT, R.string.error_action_install)
+ .setData(Uri.parse(account.getUrl() + context.getString(R.string.url_fragment_install_deck))));
+ } else {
+ add(R.string.error_dialog_version_not_parsable);
+ }
+ break;
+ case CAPABILITIES_NOT_PARSABLE:
+ default:
+ if (account != null) {
+ add(R.string.error_dialog_capabilities_not_parsable, new Intent(Intent.ACTION_VIEW)
+ .putExtra(INTENT_EXTRA_BUTTON_TEXT, R.string.error_action_server_logs)
+ .setData(Uri.parse(account.getUrl() + context.getString(R.string.url_fragment_server_logs))));
+ } else {
+ add(R.string.error_dialog_capabilities_not_parsable);
+ }
+ }
+ }
+ }
+
public void add(@StringRes int text) {
add(text, null);
}
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 12dd38eac..aa6f59d04 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
@@ -23,10 +23,11 @@ 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.model.internal.FilterInformation;
-import it.niedermann.nextcloud.deck.ui.branding.BrandedActivity;
import it.niedermann.nextcloud.deck.ui.branding.BrandedAlertDialogBuilder;
import it.niedermann.nextcloud.deck.ui.branding.BrandedDialogFragment;
+import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.getSecondaryForegroundColorDependingOnTheme;
+
public class FilterDialogFragment extends BrandedDialogFragment {
private DialogFilterBinding binding;
@@ -101,8 +102,8 @@ public class FilterDialogFragment extends BrandedDialogFragment {
}
@Override
- public void applyBrand(int mainColor, int textColor) {
- @ColorInt int finalMainColor = BrandedActivity.getSecondaryForegroundColorDependingOnTheme(requireContext(), mainColor);
+ public void applyBrand(int mainColor) {
+ @ColorInt int finalMainColor = getSecondaryForegroundColorDependingOnTheme(requireContext(), mainColor);
binding.tabLayout.setSelectedTabIndicatorColor(finalMainColor);
indicator.setColorFilter(finalMainColor, PorterDuff.Mode.SRC_ATOP);
}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/manageaccounts/ManageAccountViewHolder.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/manageaccounts/ManageAccountViewHolder.java
index 231e3f124..4b43cbed6 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/manageaccounts/ManageAccountViewHolder.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/manageaccounts/ManageAccountViewHolder.java
@@ -34,7 +34,8 @@ public class ManageAccountViewHolder extends RecyclerView.ViewHolder {
binding.accountHost.setText(Uri.parse(account.getUrl()).getHost());
Glide.with(itemView.getContext())
.load(new SingleSignOnUrl(account.getName(), account.getAvatarUrl(dpToPx(binding.accountItemAvatar.getContext(), R.dimen.avatar_size))))
- .error(R.drawable.ic_person_grey600_24dp)
+ .placeholder(R.drawable.ic_baseline_account_circle_24)
+ .error(R.drawable.ic_baseline_account_circle_24)
.apply(RequestOptions.circleCropTransform())
.into(binding.accountItemAvatar);
binding.currentAccountIndicator.setSelected(isCurrentAccount);
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/manageaccounts/ManageAccountsActivity.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/manageaccounts/ManageAccountsActivity.java
index ed62e85cb..9d273cdcb 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/manageaccounts/ManageAccountsActivity.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/manageaccounts/ManageAccountsActivity.java
@@ -1,6 +1,5 @@
package it.niedermann.nextcloud.deck.ui.manageaccounts;
-import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
@@ -9,15 +8,15 @@ import androidx.appcompat.app.AppCompatActivity;
import com.nextcloud.android.sso.helper.SingleAccountHelper;
-import it.niedermann.nextcloud.deck.Application;
import it.niedermann.nextcloud.deck.databinding.ActivityManageAccountsBinding;
import it.niedermann.nextcloud.deck.model.Account;
import it.niedermann.nextcloud.deck.persistence.sync.SyncManager;
-import it.niedermann.nextcloud.deck.ui.branding.BrandedActivity;
+import static it.niedermann.nextcloud.deck.DeckApplication.readCurrentAccountId;
+import static it.niedermann.nextcloud.deck.DeckApplication.saveCurrentAccountId;
import static it.niedermann.nextcloud.deck.persistence.sync.adapters.db.util.LiveDataHelper.observeOnce;
-public class ManageAccountsActivity extends BrandedActivity {
+public class ManageAccountsActivity extends AppCompatActivity {
private static final String TAG = ManageAccountsActivity.class.getSimpleName();
@@ -39,8 +38,7 @@ public class ManageAccountsActivity extends BrandedActivity {
adapter = new ManageAccountAdapter((account) -> {
SingleAccountHelper.setCurrentAccount(getApplicationContext(), account.getName());
syncManager = new SyncManager(this);
- Application.saveBrandColors(this, Color.parseColor(account.getColor()), Color.parseColor(account.getTextColor()));
- Application.saveCurrentAccountId(this, account.getId());
+ saveCurrentAccountId(this, account.getId());
}, (accountPair) -> {
if (accountPair.first != null) {
syncManager.deleteAccount(accountPair.first.getId());
@@ -50,8 +48,7 @@ public class ManageAccountsActivity extends BrandedActivity {
Account newAccount = accountPair.second;
if (newAccount != null) {
SingleAccountHelper.setCurrentAccount(getApplicationContext(), newAccount.getName());
- Application.saveBrandColors(this, Color.parseColor(newAccount.getColor()), Color.parseColor(newAccount.getTextColor()));
- Application.saveCurrentAccountId(this, newAccount.getId());
+ saveCurrentAccountId(this, newAccount.getId());
syncManager = new SyncManager(this);
} else {
Log.i(TAG, "Got delete account request, but new account is null. Maybe last account has been deleted?");
@@ -59,7 +56,7 @@ public class ManageAccountsActivity extends BrandedActivity {
});
binding.accounts.setAdapter(adapter);
- observeOnce(syncManager.readAccount(Application.readCurrentAccountId(this)), this, (account -> {
+ observeOnce(syncManager.readAccount(readCurrentAccountId(this)), this, (account -> {
adapter.setCurrentAccount(account);
syncManager.readAccounts().observe(this, (localAccounts -> {
if (localAccounts.size() == 0) {
@@ -77,9 +74,4 @@ public class ManageAccountsActivity extends BrandedActivity {
public void onBackPressed() {
onSupportNavigateUp();
}
-
- @Override
- public void applyBrand(int mainColor, int textColor) {
- applyBrandToPrimaryToolbar(mainColor, textColor, binding.toolbar);
- }
}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/preparecreate/PrepareCreateActivity.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/preparecreate/PrepareCreateActivity.java
index b2e9cb012..ab0cc4816 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/preparecreate/PrepareCreateActivity.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/preparecreate/PrepareCreateActivity.java
@@ -2,34 +2,51 @@ package it.niedermann.nextcloud.deck.ui.preparecreate;
import android.content.ClipData;
import android.content.Intent;
+import android.content.res.ColorStateList;
+import android.graphics.Color;
import android.os.Bundle;
import android.text.TextUtils;
import android.widget.ArrayAdapter;
+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.LiveData;
import androidx.lifecycle.Observer;
import java.util.List;
-import it.niedermann.nextcloud.deck.Application;
import it.niedermann.nextcloud.deck.DeckLog;
+import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.databinding.ActivityPrepareCreateBinding;
import it.niedermann.nextcloud.deck.model.Account;
import it.niedermann.nextcloud.deck.model.Board;
import it.niedermann.nextcloud.deck.model.full.FullStack;
import it.niedermann.nextcloud.deck.persistence.sync.SyncManager;
import it.niedermann.nextcloud.deck.ui.ImportAccountActivity;
-import it.niedermann.nextcloud.deck.ui.branding.BrandedActivity;
+import it.niedermann.nextcloud.deck.ui.branding.Branded;
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.util.ColorUtil;
import static android.graphics.Color.parseColor;
import static androidx.lifecycle.Transformations.switchMap;
-
-public class PrepareCreateActivity extends BrandedActivity {
+import static it.niedermann.nextcloud.deck.DeckApplication.isDarkTheme;
+import static it.niedermann.nextcloud.deck.DeckApplication.readCurrentAccountId;
+import static it.niedermann.nextcloud.deck.DeckApplication.readCurrentBoardId;
+import static it.niedermann.nextcloud.deck.DeckApplication.readCurrentStackId;
+import static it.niedermann.nextcloud.deck.DeckApplication.saveCurrentAccountId;
+import static it.niedermann.nextcloud.deck.DeckApplication.saveCurrentBoardId;
+import static it.niedermann.nextcloud.deck.DeckApplication.saveCurrentStackId;
+import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.getSecondaryForegroundColorDependingOnTheme;
+import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.isBrandingEnabled;
+import static it.niedermann.nextcloud.deck.util.ColorUtil.contrastRatioIsSufficientBigAreas;
+
+public class PrepareCreateActivity extends AppCompatActivity implements Branded {
private ActivityPrepareCreateBinding binding;
@@ -59,10 +76,12 @@ public class PrepareCreateActivity extends BrandedActivity {
for (Board board : boards) {
if (board.getLocalId() == lastBoardId) {
binding.boardSelect.setSelection(boardAdapter.getPosition(board));
+ applyBrand(Color.parseColor('#' + board.getColor()));
break;
}
}
} else {
+ applyBrand(ContextCompat.getColor(this, R.color.defaultBrand));
binding.boardSelect.setEnabled(false);
binding.submit.setEnabled(false);
}
@@ -97,7 +116,7 @@ public class PrepareCreateActivity extends BrandedActivity {
Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler(this));
- brandingEnabled = Application.isBrandingEnabled(this);
+ brandingEnabled = isBrandingEnabled(this);
binding = ActivityPrepareCreateBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
@@ -127,9 +146,9 @@ public class PrepareCreateActivity extends BrandedActivity {
throw new IllegalStateException("hasAccounts() returns true, but readAccounts() returns null or has no entry");
}
- lastAccountId = Application.readCurrentAccountId(this);
- lastBoardId = Application.readCurrentBoardId(this, lastAccountId);
- lastStackId = Application.readCurrentStackId(this, lastAccountId, lastBoardId);
+ lastAccountId = readCurrentAccountId(this);
+ lastBoardId = readCurrentBoardId(this, lastAccountId);
+ lastStackId = readCurrentStackId(this, lastAccountId, lastBoardId);
accountAdapter.clear();
accountAdapter.addAll(accounts);
@@ -144,12 +163,13 @@ public class PrepareCreateActivity extends BrandedActivity {
});
binding.accountSelect.setOnItemSelectedListener((SelectedListener) (parent, view, position, id) -> {
- applyTemporaryBrand(accountAdapter.getItem(position));
updateLiveDataSource(boardsLiveData, boardsObserver, syncManager.getBoardsWithEditPermission(parent.getSelectedItemId()));
});
- binding.boardSelect.setOnItemSelectedListener((SelectedListener) (parent, view, position, id) ->
- updateLiveDataSource(stacksLiveData, stacksObserver, syncManager.getStacksForBoard(binding.accountSelect.getSelectedItemId(), parent.getSelectedItemId())));
+ binding.boardSelect.setOnItemSelectedListener((SelectedListener) (parent, view, position, id) -> {
+ applyBrand(Color.parseColor('#' + ((Board) binding.boardSelect.getSelectedItem()).getColor()));
+ updateLiveDataSource(stacksLiveData, stacksObserver, syncManager.getStacksForBoard(binding.accountSelect.getSelectedItemId(), parent.getSelectedItemId()));
+ });
binding.cancel.setOnClickListener((v) -> finish());
binding.submit.setOnClickListener((v) -> onSubmit());
@@ -181,10 +201,10 @@ public class PrepareCreateActivity extends BrandedActivity {
startActivity(EditActivity.createNewCardIntent(this, account, boardId, stackId, receivedClipData));
}
- Application.saveCurrentAccountId(this, account.getId());
- Application.saveCurrentBoardId(this, account.getId(), boardId);
- Application.saveCurrentStackId(this, account.getId(), boardId, stackId);
- applyBrand(parseColor(account.getColor()), parseColor(account.getTextColor()));
+ saveCurrentAccountId(this, account.getId());
+ saveCurrentBoardId(this, account.getId(), boardId);
+ saveCurrentStackId(this, account.getId(), boardId, stackId);
+ applyBrand(parseColor(account.getColor()));
finish();
} else {
@@ -213,21 +233,19 @@ public class PrepareCreateActivity extends BrandedActivity {
return TextUtils.isEmpty(text) ? null : text.toString();
}
- private void applyTemporaryBrand(@Nullable Account account) {
+ @Override
+ public void applyBrand(int mainColor) {
try {
- if (account != null && brandingEnabled) {
- applyBrand(parseColor(account.getColor()), parseColor(account.getTextColor()));
+ if (brandingEnabled) {
+ @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.getForegroundColorForBackgroundColor(finalMainColor));
+ binding.cancel.setTextColor(getSecondaryForegroundColorDependingOnTheme(this, mainColor));
}
} catch (Throwable t) {
DeckLog.logError(t);
}
}
-
- @Override
- public void applyBrand(int mainColor, int textColor) {
- applyBrandToPrimaryToolbar(mainColor, textColor, binding.toolbar);
- binding.submit.setBackgroundColor(mainColor);
- binding.submit.setTextColor(textColor);
- binding.cancel.setTextColor(getSecondaryForegroundColorDependingOnTheme(this, mainColor));
- }
} \ No newline at end of file
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/settings/SettingsActivity.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/settings/SettingsActivity.java
index 363e5b46e..6f5a9a7e8 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/settings/SettingsActivity.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/settings/SettingsActivity.java
@@ -37,7 +37,7 @@ public class SettingsActivity extends BrandedActivity {
}
@Override
- public void applyBrand(int mainColor, int textColor) {
- applyBrandToPrimaryToolbar(mainColor, textColor, binding.toolbar);
+ public void applyBrand(int mainColor) {
+ // Nothing to do...
}
}
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 f531abbe1..ea8d90f22 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
@@ -4,19 +4,20 @@ import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
-import androidx.annotation.ColorInt;
import androidx.annotation.Nullable;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
-import it.niedermann.nextcloud.deck.Application;
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.Branded;
import it.niedermann.nextcloud.deck.ui.branding.BrandedSwitchPreference;
+import static it.niedermann.nextcloud.deck.DeckApplication.setAppTheme;
+import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.readBrandMainColor;
+
public class SettingsFragment extends PreferenceFragmentCompat implements Branded {
private BrandedSwitchPreference wifiOnlyPref;
@@ -44,7 +45,7 @@ public class SettingsFragment extends PreferenceFragmentCompat implements Brande
themePref.setOnPreferenceChangeListener((Preference preference, Object newValue) -> {
final Boolean darkTheme = (Boolean) newValue;
DeckLog.log("darkTheme: " + darkTheme);
- Application.setAppTheme(darkTheme);
+ setAppTheme(darkTheme);
requireActivity().setResult(Activity.RESULT_OK);
requireActivity().recreate();
return true;
@@ -82,16 +83,14 @@ public class SettingsFragment extends PreferenceFragmentCompat implements Brande
super.onStart();
@Nullable Context context = getContext();
if (context != null) {
- @ColorInt final int mainColor = Application.readBrandMainColor(context);
- @ColorInt final int textColor = Application.readBrandTextColor(context);
- applyBrand(mainColor, textColor);
+ applyBrand(readBrandMainColor(context));
}
}
@Override
- public void applyBrand(int mainColor, int textColor) {
- wifiOnlyPref.applyBrand(mainColor, textColor);
- themePref.applyBrand(mainColor, textColor);
- brandingPref.applyBrand(mainColor, textColor);
+ public void applyBrand(int mainColor) {
+ wifiOnlyPref.applyBrand(mainColor);
+ themePref.applyBrand(mainColor);
+ brandingPref.applyBrand(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 12a06bb11..271b60489 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
@@ -21,7 +21,7 @@ import it.niedermann.nextcloud.deck.ui.branding.BrandedDialogFragment;
import it.niedermann.nextcloud.deck.ui.exception.ExceptionDialogFragment;
import static android.graphics.PorterDuff.Mode;
-import static it.niedermann.nextcloud.deck.ui.branding.BrandedActivity.getSecondaryForegroundColorDependingOnTheme;
+import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.getSecondaryForegroundColorDependingOnTheme;
import static it.niedermann.nextcloud.deck.util.ExceptionUtil.getDebugInfos;
public class ShareProgressDialogFragment extends BrandedDialogFragment {
@@ -114,7 +114,7 @@ public class ShareProgressDialogFragment extends BrandedDialogFragment {
}
@Override
- public void applyBrand(int mainColor, int textColor) {
+ public void applyBrand(int mainColor) {
binding.progress.getProgressDrawable().setColorFilter(
getSecondaryForegroundColorDependingOnTheme(requireContext(), mainColor), Mode.SRC_IN);
binding.errorReportButton.setTextColor(getSecondaryForegroundColorDependingOnTheme(requireContext(), mainColor));
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 92272b99e..6bedd0a0f 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
@@ -17,11 +17,11 @@ import java.util.Objects;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.databinding.DialogStackCreateBinding;
-import it.niedermann.nextcloud.deck.ui.branding.BrandedActivity;
import it.niedermann.nextcloud.deck.ui.branding.BrandedAlertDialogBuilder;
import it.niedermann.nextcloud.deck.ui.branding.BrandedDialogFragment;
-import static it.niedermann.nextcloud.deck.Application.NO_STACK_ID;
+import static it.niedermann.nextcloud.deck.DeckApplication.NO_STACK_ID;
+import static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.applyBrandToEditText;
public class EditStackDialogFragment extends BrandedDialogFragment {
private static final String KEY_STACK_ID = "stack_id";
@@ -90,7 +90,7 @@ public class EditStackDialogFragment extends BrandedDialogFragment {
}
@Override
- public void applyBrand(int mainColor, int textColor) {
- BrandedActivity.applyBrandToEditText(mainColor, textColor, binding.input);
+ public void applyBrand(int mainColor) {
+ applyBrandToEditText(mainColor, binding.input);
}
}
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 942310199..726a74184 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
@@ -138,9 +138,9 @@ public class StackFragment extends BrandedFragment implements DragAndDropTab<Car
}
@Override
- public void applyBrand(int mainColor, int textColor) {
+ public void applyBrand(int mainColor) {
if (this.adapter != null) {
- this.adapter.applyBrand(mainColor, textColor);
+ this.adapter.applyBrand(mainColor);
}
}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/ui/view/OverlappingAvatars.java b/app/src/main/java/it/niedermann/nextcloud/deck/ui/view/OverlappingAvatars.java
index 63be42465..501d33106 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/ui/view/OverlappingAvatars.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/ui/view/OverlappingAvatars.java
@@ -48,7 +48,7 @@ public class OverlappingAvatars extends RelativeLayout {
avatarSize = dpToPx(context, R.dimen.avatar_size_small) + avatarBorderSize * 2;
overlapPx = dpToPx(context, R.dimen.avatar_size_small_overlapping);
borderDrawable = getResources().getDrawable(R.drawable.avatar_border);
- DrawableCompat.setTint(borderDrawable, getResources().getColor(R.color.avatars_overlapping_border_color));
+ DrawableCompat.setTint(borderDrawable, getResources().getColor(R.color.bg_card));
}
public void setAvatars(@NonNull Account account, @NonNull List<User> assignedUsers) {
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 cda805450..8c1fbe1fa 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
@@ -6,17 +6,22 @@ import android.os.Bundle;
import android.view.Menu;
import android.view.View;
+import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
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 static it.niedermann.nextcloud.deck.ui.branding.BrandingUtil.saveBrandColors;
+
public class SelectCardForWidgetActivity extends MainActivity implements SelectCardListener {
private int appWidgetId;
+ @ColorInt private int originalBrandColor;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -35,6 +40,7 @@ public class SelectCardForWidgetActivity extends MainActivity implements SelectC
if (appWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
finish();
}
+ originalBrandColor = BrandingUtil.readBrandMainColor(this);
}
@Override
@@ -45,6 +51,7 @@ public class SelectCardForWidgetActivity extends MainActivity implements SelectC
.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
setResult(RESULT_OK, updateIntent);
getApplicationContext().sendBroadcast(updateIntent);
+ saveBrandColors(this, originalBrandColor);
finish();
}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/util/ColorUtil.java b/app/src/main/java/it/niedermann/nextcloud/deck/util/ColorUtil.java
index 4adf43b34..08354c5fb 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/util/ColorUtil.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/util/ColorUtil.java
@@ -109,7 +109,18 @@ public final class ColorUtil {
return ret;
}
- private static double getContrastRatio(@ColorInt int colorOne, @ColorInt int colorTwo) {
+ public static boolean contrastRatioIsSufficientBigAreas(@ColorInt int colorOne, @ColorInt int colorTwo) {
+ ColorPair key = new ColorPair(colorOne, colorTwo);
+ Boolean ret = CONTRAST_RATIO_SUFFICIENT_CACHE.get(key);
+ if (ret == null) {
+ ret = getContrastRatio(colorOne, colorTwo) > 1.47d;
+ CONTRAST_RATIO_SUFFICIENT_CACHE.put(key, ret);
+ return ret;
+ }
+ return ret;
+ }
+
+ public static double getContrastRatio(@ColorInt int colorOne, @ColorInt int colorTwo) {
final double lum1 = getLuminanace(colorOne);
final double lum2 = getLuminanace(colorTwo);
final double brightest = Math.max(lum1, lum2);
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/util/ViewUtil.java b/app/src/main/java/it/niedermann/nextcloud/deck/util/ViewUtil.java
index 1039b5c95..6abbde557 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/util/ViewUtil.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/util/ViewUtil.java
@@ -27,11 +27,12 @@ import com.bumptech.glide.request.transition.Transition;
import java.util.Date;
import java.util.List;
-import it.niedermann.nextcloud.deck.Application;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.model.Account;
import it.niedermann.nextcloud.deck.model.ocs.comment.Mention;
+import static it.niedermann.nextcloud.deck.DeckApplication.isDarkTheme;
+
public final class ViewUtil {
private ViewUtil() {
}
@@ -53,7 +54,7 @@ public final class ViewUtil {
long diff = DateUtil.getDayDifference(new Date(), dueDate);
int backgroundDrawable = 0;
- int textColor = Application.getAppTheme(context) ? R.color.dark_fg_primary : R.color.grey600;
+ int textColor = isDarkTheme(context) ? R.color.dark_fg_primary : R.color.grey600;
if (diff == 1) {
// due date: tomorrow
diff --git a/app/src/main/res/drawable/ic_arrow_back_white_24dp.xml b/app/src/main/res/drawable/ic_arrow_back_white_24dp.xml
index cc2b6f531..17d6150d8 100644
--- a/app/src/main/res/drawable/ic_arrow_back_white_24dp.xml
+++ b/app/src/main/res/drawable/ic_arrow_back_white_24dp.xml
@@ -1,5 +1,5 @@
<vector android:autoMirrored="true" android:height="24dp"
- android:tint="#FFFFFF" android:viewportHeight="24.0"
+ android:tint="@color/accent" android:viewportHeight="24.0"
android:viewportWidth="24.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="#FF000000" android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z"/>
+ <path android:fillColor="@color/accent" android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z"/>
</vector>
diff --git a/app/src/main/res/drawable/ic_baseline_account_circle_24.xml b/app/src/main/res/drawable/ic_baseline_account_circle_24.xml
index 0945faff9..2cb60dcfb 100644
--- a/app/src/main/res/drawable/ic_baseline_account_circle_24.xml
+++ b/app/src/main/res/drawable/ic_baseline_account_circle_24.xml
@@ -1,5 +1,5 @@
-<vector android:autoMirrored="true" android:height="24dp"
- android:tint="#FFFFFF" android:viewportHeight="24"
+<vector android:height="24dp"
+ android:tint="@color/accent" android:viewportHeight="24"
android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,5c1.66,0 3,1.34 3,3s-1.34,3 -3,3 -3,-1.34 -3,-3 1.34,-3 3,-3zM12,19.2c-2.5,0 -4.71,-1.28 -6,-3.22 0.03,-1.99 4,-3.08 6,-3.08 1.99,0 5.97,1.09 6,3.08 -1.29,1.94 -3.5,3.22 -6,3.22z"/>
+ <path android:fillColor="@color/accent" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,5c1.66,0 3,1.34 3,3s-1.34,3 -3,3 -3,-1.34 -3,-3 1.34,-3 3,-3zM12,19.2c-2.5,0 -4.71,-1.28 -6,-3.22 0.03,-1.99 4,-3.08 6,-3.08 1.99,0 5.97,1.09 6,3.08 -1.29,1.94 -3.5,3.22 -6,3.22z"/>
</vector>
diff --git a/app/src/main/res/drawable/ic_check_white_24dp.xml b/app/src/main/res/drawable/ic_check_white_24dp.xml
index 65eff3fd3..47dd2131a 100644
--- a/app/src/main/res/drawable/ic_check_white_24dp.xml
+++ b/app/src/main/res/drawable/ic_check_white_24dp.xml
@@ -1,5 +1,5 @@
<vector android:height="24dp"
- android:tint="#FFFFFF" android:viewportHeight="24.0"
+ android:tint="@android:color/white" android:viewportHeight="24.0"
android:viewportWidth="24.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z"/>
</vector>
diff --git a/app/src/main/res/drawable/ic_close_white_24dp.xml b/app/src/main/res/drawable/ic_close_white_24dp.xml
index 8f4d17880..1c878294b 100644
--- a/app/src/main/res/drawable/ic_close_white_24dp.xml
+++ b/app/src/main/res/drawable/ic_close_white_24dp.xml
@@ -1,5 +1,5 @@
<vector android:autoMirrored="true" android:height="24dp"
- android:tint="#FFFFFF" android:viewportHeight="24.0"
+ android:tint="@color/accent" android:viewportHeight="24.0"
android:viewportWidth="24.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"/>
</vector>
diff --git a/app/src/main/res/drawable/selected.xml b/app/src/main/res/drawable/selected.xml
index cb301fd84..f28dd14cd 100644
--- a/app/src/main/res/drawable/selected.xml
+++ b/app/src/main/res/drawable/selected.xml
@@ -4,7 +4,7 @@
<layer-list>
<item>
<shape android:shape="oval">
- <solid android:color="@android:color/holo_green_light" />
+ <solid android:color="@color/defaultBrand" />
<stroke android:width="1dp" android:color="@android:color/white" />
</shape>
</item>
diff --git a/app/src/main/res/drawable/splash_screen.xml b/app/src/main/res/drawable/splash_screen.xml
index 14234ed34..d22531b3f 100644
--- a/app/src/main/res/drawable/splash_screen.xml
+++ b/app/src/main/res/drawable/splash_screen.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:drawable="@color/primary" />
+ <item android:drawable="@color/defaultBrand" />
<item>
<bitmap
diff --git a/app/src/main/res/layout/activity_about.xml b/app/src/main/res/layout/activity_about.xml
index 739c9c33f..67c7a900c 100644
--- a/app/src/main/res/layout/activity_about.xml
+++ b/app/src/main/res/layout/activity_about.xml
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
- xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical">
<com.google.android.material.appbar.AppBarLayout
@@ -15,15 +15,16 @@
android:layout_width="match_parent"
android:layout_height="?android:actionBarSize"
app:navigationIcon="@drawable/ic_arrow_back_white_24dp"
- app:titleTextColor="@android:color/white"
tools:title="@string/about" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:theme="@style/ThemeOverlay.AppCompat.Dark"
- app:tabIndicatorColor="@color/accent" />
+ app:tabBackground="?attr/colorPrimary"
+ app:tabIndicatorColor="@color/defaultBrand"
+ app:tabMode="fixed"
+ app:tabTextColor="?attr/colorAccent" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager2.widget.ViewPager2
diff --git a/app/src/main/res/layout/activity_archived.xml b/app/src/main/res/layout/activity_archived.xml
index fd03521fd..6dd7024dc 100644
--- a/app/src/main/res/layout/activity_archived.xml
+++ b/app/src/main/res/layout/activity_archived.xml
@@ -15,7 +15,6 @@
android:layout_width="match_parent"
android:layout_height="?android:actionBarSize"
app:navigationIcon="@drawable/ic_arrow_back_white_24dp"
- app:titleTextColor="@android:color/white"
tools:title="@string/archived_cards" />
</com.google.android.material.appbar.AppBarLayout>
diff --git a/app/src/main/res/layout/activity_attachments.xml b/app/src/main/res/layout/activity_attachments.xml
index 2e9f68414..5a820f9d3 100644
--- a/app/src/main/res/layout/activity_attachments.xml
+++ b/app/src/main/res/layout/activity_attachments.xml
@@ -16,7 +16,6 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:navigationIcon="@drawable/ic_arrow_back_white_24dp"
- app:titleTextColor="@android:color/white"
tools:title="@string/attachments" />
</com.google.android.material.appbar.AppBarLayout>
diff --git a/app/src/main/res/layout/activity_edit.xml b/app/src/main/res/layout/activity_edit.xml
index 16f310fb8..4d59b296f 100644
--- a/app/src/main/res/layout/activity_edit.xml
+++ b/app/src/main/res/layout/activity_edit.xml
@@ -16,16 +16,15 @@
android:layout_height="wrap_content"
app:navigationIcon="@drawable/ic_close_white_24dp">
- <EditText
- android:id="@+id/title"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- app:theme="@style/EditTextOnPrimaryBackground"
- android:layout_marginEnd="16dp"
- android:importantForAutofill="no"
- android:inputType="textMultiLine"
- android:maxLines="5"
- tools:text="@tools:sample/lorem" />
+ <EditText
+ android:id="@+id/title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="16dp"
+ android:importantForAutofill="no"
+ android:inputType="textMultiLine"
+ android:maxLines="5"
+ tools:text="@tools:sample/lorem" />
</androidx.appcompat.widget.Toolbar>
@@ -34,10 +33,12 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark"
+ app:tabBackground="?attr/colorPrimary"
app:tabGravity="center"
- app:tabIconTint="@android:color/white"
- app:tabIndicatorColor="@color/accent"
- app:tabMode="fixed" />
+ app:tabIconTint="?attr/colorAccent"
+ app:tabIndicatorColor="@color/defaultBrand"
+ app:tabMode="fixed"
+ app:tabTextColor="?attr/colorAccent" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager2.widget.ViewPager2
diff --git a/app/src/main/res/layout/activity_exception.xml b/app/src/main/res/layout/activity_exception.xml
index 782b401e8..881c8fa85 100644
--- a/app/src/main/res/layout/activity_exception.xml
+++ b/app/src/main/res/layout/activity_exception.xml
@@ -14,7 +14,6 @@
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?android:actionBarSize"
- app:titleTextColor="@android:color/white"
tools:title="@string/simple_exception" />
</com.google.android.material.appbar.AppBarLayout>
@@ -36,23 +35,53 @@
</LinearLayout>
- <HorizontalScrollView
+ <ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
- android:layout_marginStart="@dimen/spacer_2x"
- android:layout_marginEnd="@dimen/spacer_2x"
- android:layout_weight="1"
- android:background="@color/bg_highlighted">
+ android:layout_weight="1">
- <TextView
- android:id="@+id/stacktrace"
- android:layout_width="wrap_content"
+ <LinearLayout
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:padding="@dimen/spacer_1x"
- android:textIsSelectable="true"
- android:typeface="monospace"
- tools:text="@string/android_get_accounts_permission_not_granted_exception_message" />
- </HorizontalScrollView>
+ android:orientation="vertical">
+
+ <androidx.recyclerview.widget.RecyclerView
+ android:id="@+id/tips"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:paddingStart="@dimen/spacer_2x"
+ android:paddingEnd="@dimen/spacer_2x"
+ app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
+ tools:itemCount="2"
+ tools:listitem="@layout/item_tip" />
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:padding="@dimen/spacer_2x"
+ android:text="@string/error_dialog_we_need_info"
+ android:textAppearance="?attr/textAppearanceBody2" />
+
+ <HorizontalScrollView
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_marginStart="@dimen/spacer_2x"
+ android:layout_marginEnd="@dimen/spacer_2x"
+ android:layout_weight="1"
+ android:background="@color/bg_highlighted">
+
+ <TextView
+ android:id="@+id/stacktrace"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="@dimen/spacer_1x"
+ android:textIsSelectable="true"
+ android:typeface="monospace"
+ tools:text="@string/android_get_accounts_permission_not_granted_exception_message" />
+ </HorizontalScrollView>
+ </LinearLayout>
+ </ScrollView>
<LinearLayout
android:layout_width="match_parent"
@@ -69,7 +98,8 @@
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/spacer_1x"
android:layout_weight=".5"
- android:text="@string/simple_close" />
+ android:text="@string/simple_close"
+ android:textColor="@color/defaultBrand" />
<com.google.android.material.button.MaterialButton
android:id="@+id/copy"
@@ -78,7 +108,8 @@
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/spacer_1x"
android:layout_weight=".5"
- android:text="@string/simple_copy" />
+ android:text="@string/simple_copy"
+ app:backgroundTint="@color/defaultBrand" />
</LinearLayout>
</LinearLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/activity_import_account.xml b/app/src/main/res/layout/activity_import_account.xml
index b4294db7b..088c26426 100644
--- a/app/src/main/res/layout/activity_import_account.xml
+++ b/app/src/main/res/layout/activity_import_account.xml
@@ -48,7 +48,8 @@
android:paddingTop="24dp"
android:paddingEnd="32dp"
android:paddingBottom="24dp"
- android:text="@string/choose_account" />
+ android:text="@string/choose_account"
+ app:backgroundTint="@color/defaultBrand" />
<TextView
android:id="@+id/status"
@@ -70,6 +71,7 @@
android:layout_below="@id/add_button"
android:layout_centerHorizontal="true"
android:layout_marginTop="32dp"
+ android:indeterminateTint="@color/defaultBrand"
android:visibility="gone" />
<Button
@@ -81,6 +83,7 @@
android:layout_centerHorizontal="true"
android:layout_marginTop="16dp"
android:text="@string/simple_update"
+ android:textColor="@color/defaultBrand"
android:visibility="gone"
tools:visibility="visible" />
</RelativeLayout>
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index d3b024d98..5413b6219 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -5,6 +5,7 @@
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:background="@color/bg_card_wrapper"
android:fitsSystemWindows="true">
<androidx.coordinatorlayout.widget.CoordinatorLayout
@@ -107,9 +108,6 @@
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
- android:background="?attr/colorPrimary"
- android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
- app:titleTextColor="@android:color/white"
tools:title="Deck">
<ImageView
@@ -132,6 +130,7 @@
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/simple_filter"
android:padding="12dp"
+ android:tint="?attr/colorAccent"
android:tooltipText="@string/simple_filter"
android:translationX="6dp"
app:srcCompat="@drawable/ic_filter_list_white_24dp"
@@ -145,6 +144,7 @@
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/action_archived_cards"
android:padding="12dp"
+ android:tint="?attr/colorAccent"
android:tooltipText="@string/action_archived_cards"
android:translationX="12dp"
android:visibility="gone"
@@ -163,19 +163,20 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
+ app:tabBackground="?attr/colorPrimary"
app:tabGravity="center"
- app:tabIndicatorColor="@color/accent"
+ app:tabIndicatorColor="@color/defaultBrand"
app:tabMode="fixed"
- app:tabTextColor="@android:color/white" />
+ app:tabTextColor="?attr/colorAccent" />
<androidx.appcompat.widget.AppCompatImageButton
android:id="@+id/list_menu_button"
android:layout_width="48dp"
android:layout_height="match_parent"
- android:background="@android:color/transparent"
+ android:background="?attr/colorPrimary"
android:contentDescription="@string/add_list"
android:foreground="?attr/selectableItemBackgroundBorderless"
- android:tint="@android:color/white"
+ android:tint="?attr/colorAccent"
android:tooltipText="@string/manage_list"
app:srcCompat="@drawable/ic_menu"
tools:ignore="UnusedAttribute" />
@@ -190,7 +191,7 @@
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
android:contentDescription="@string/add_card"
- app:backgroundTint="@color/primary"
+ app:backgroundTint="@color/defaultBrand"
app:srcCompat="@drawable/ic_add_white_24dp" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
@@ -202,6 +203,7 @@
android:layout_gravity="start"
android:fitsSystemWindows="false"
android:theme="@style/NavigationView"
+ android:background="?attr/colorPrimary"
app:headerLayout="@layout/nav_header_main" />
</androidx.drawerlayout.widget.DrawerLayout>
diff --git a/app/src/main/res/layout/activity_manage_accounts.xml b/app/src/main/res/layout/activity_manage_accounts.xml
index 4cd084a88..bbf1b75c4 100644
--- a/app/src/main/res/layout/activity_manage_accounts.xml
+++ b/app/src/main/res/layout/activity_manage_accounts.xml
@@ -14,12 +14,10 @@
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
- android:background="?attr/colorPrimary"
app:contentInsetStartWithNavigation="0dp"
app:navigationIcon="@drawable/ic_arrow_back_white_24dp"
app:title="@string/manage_accounts"
- app:titleMarginStart="0dp"
- app:titleTextColor="@android:color/white" />
+ app:titleMarginStart="0dp" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.recyclerview.widget.RecyclerView
diff --git a/app/src/main/res/layout/activity_prepare_create.xml b/app/src/main/res/layout/activity_prepare_create.xml
index f4aff7cb8..1128f04f4 100644
--- a/app/src/main/res/layout/activity_prepare_create.xml
+++ b/app/src/main/res/layout/activity_prepare_create.xml
@@ -15,8 +15,7 @@
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?android:actionBarSize"
- app:title="@string/add_card"
- app:titleTextColor="@android:color/white" />
+ app:title="@string/add_card" />
</com.google.android.material.appbar.AppBarLayout>
<ScrollView
@@ -73,7 +72,8 @@
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/spacer_1x"
android:layout_weight=".5"
- android:text="@android:string/cancel" />
+ android:text="@android:string/cancel"
+ android:textColor="@color/defaultBrand" />
<com.google.android.material.button.MaterialButton
android:id="@+id/submit"
@@ -82,6 +82,7 @@
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/spacer_1x"
android:layout_weight=".5"
- android:text="@string/simple_add" />
+ android:text="@string/simple_add"
+ app:backgroundTint="@color/defaultBrand" />
</LinearLayout>
</RelativeLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/activity_push_notification.xml b/app/src/main/res/layout/activity_push_notification.xml
index 6fb41be3a..eb14f38d1 100644
--- a/app/src/main/res/layout/activity_push_notification.xml
+++ b/app/src/main/res/layout/activity_push_notification.xml
@@ -21,8 +21,7 @@
android:layout_width="match_parent"
android:layout_height="?android:actionBarSize"
app:navigationIcon="@drawable/ic_arrow_back_white_24dp"
- app:title="@string/app_name"
- app:titleTextColor="@android:color/white" />
+ app:title="@string/app_name" />
</com.google.android.material.appbar.AppBarLayout>
<ProgressBar
diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml
index e5c8b0214..07f7a62fe 100644
--- a/app/src/main/res/layout/activity_settings.xml
+++ b/app/src/main/res/layout/activity_settings.xml
@@ -15,8 +15,7 @@
android:layout_width="match_parent"
android:layout_height="?android:actionBarSize"
app:navigationIcon="@drawable/ic_arrow_back_white_24dp"
- app:title="@string/simple_settings"
- app:titleTextColor="@android:color/white" />
+ app:title="@string/simple_settings" />
</com.google.android.material.appbar.AppBarLayout>
</LinearLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/dialog_board_manage_labels.xml b/app/src/main/res/layout/dialog_board_manage_labels.xml
index 0792d8094..ccd4481bc 100644
--- a/app/src/main/res/layout/dialog_board_manage_labels.xml
+++ b/app/src/main/res/layout/dialog_board_manage_labels.xml
@@ -29,7 +29,7 @@
android:layout_height="wrap_content"
android:layout_gravity="center"
android:contentDescription="@string/add_comment"
- android:tint="@android:color/white"
+ app:backgroundTint="@color/defaultBrand"
app:fabSize="mini"
app:srcCompat="@drawable/ic_send_white_24dp" />
</LinearLayout>
diff --git a/app/src/main/res/layout/dialog_filter.xml b/app/src/main/res/layout/dialog_filter.xml
index e7d9ebd6a..8741e7e36 100644
--- a/app/src/main/res/layout/dialog_filter.xml
+++ b/app/src/main/res/layout/dialog_filter.xml
@@ -9,7 +9,10 @@
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ app:tabIndicatorColor="@color/defaultBrand"
app:tabInlineLabel="true"
+ app:tabMode="fixed"
+ app:tabTextColor="?attr/colorAccent"
app:tabUnboundedRipple="true" />
<androidx.viewpager2.widget.ViewPager2
diff --git a/app/src/main/res/layout/fragment_about_license_tab.xml b/app/src/main/res/layout/fragment_about_license_tab.xml
index aac8e79a0..e6730390b 100644
--- a/app/src/main/res/layout/fragment_about_license_tab.xml
+++ b/app/src/main/res/layout/fragment_about_license_tab.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
@@ -26,7 +27,8 @@
style="@style/Widget.MaterialComponents.Button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/about_app_license_button" />
+ android:text="@string/about_app_license_button"
+ app:backgroundTint="@color/defaultBrand" />
<TextView
style="?android:attr/listSeparatorTextViewStyle"
diff --git a/app/src/main/res/layout/fragment_card_edit_tab_attachments.xml b/app/src/main/res/layout/fragment_card_edit_tab_attachments.xml
index b2e5df74a..5aa23961d 100644
--- a/app/src/main/res/layout/fragment_card_edit_tab_attachments.xml
+++ b/app/src/main/res/layout/fragment_card_edit_tab_attachments.xml
@@ -32,7 +32,7 @@
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
android:visibility="gone"
- app:backgroundTint="@color/primary"
+ app:backgroundTint="@color/defaultBrand"
app:srcCompat="@drawable/ic_file_upload_white_24dp"
tools:visibility="visible" />
</androidx.coordinatorlayout.widget.CoordinatorLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_card_edit_tab_comments.xml b/app/src/main/res/layout/fragment_card_edit_tab_comments.xml
index da76e2a50..3350480cb 100644
--- a/app/src/main/res/layout/fragment_card_edit_tab_comments.xml
+++ b/app/src/main/res/layout/fragment_card_edit_tab_comments.xml
@@ -114,7 +114,7 @@
android:layout_height="wrap_content"
android:layout_gravity="center"
android:contentDescription="@string/add_comment"
- android:tint="@android:color/white"
+ app:backgroundTint="@color/defaultBrand"
app:fabSize="mini"
app:srcCompat="@drawable/ic_send_white_24dp" />
</LinearLayout>
diff --git a/app/src/main/res/layout/item_autocomplete_label.xml b/app/src/main/res/layout/item_autocomplete_label.xml
index adfa5bd93..49b98db0b 100644
--- a/app/src/main/res/layout/item_autocomplete_label.xml
+++ b/app/src/main/res/layout/item_autocomplete_label.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -12,11 +13,15 @@
android:id="@+id/label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_marginTop="@dimen/spacer_1x"
+ android:layout_marginBottom="@dimen/spacer_1x"
android:clickable="false"
android:ellipsize="middle"
android:focusable="false"
+ android:padding="@dimen/spacer_1x"
+ app:ensureMinTouchTargetSize="false"
tools:backgroundTint="@color/board_default_color"
- tools:text="@tools:sample/lorem"
+ tools:text="@tools:sample/cities"
tools:textColor="@android:color/white" />
</LinearLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/item_card.xml b/app/src/main/res/layout/item_card.xml
index a3ae195fc..c0457f5e4 100644
--- a/app/src/main/res/layout/item_card.xml
+++ b/app/src/main/res/layout/item_card.xml
@@ -9,6 +9,7 @@
android:layout_marginTop="@dimen/spacer_1x"
android:layout_marginEnd="@dimen/spacer_2x"
android:layout_marginBottom="@dimen/spacer_1x"
+ app:cardBackgroundColor="@color/bg_card"
android:focusable="true">
<LinearLayout
@@ -32,6 +33,7 @@
android:layout_marginTop="4sp"
android:layout_weight="1"
android:textSize="18sp"
+ android:textColor="?attr/colorAccent"
tools:ignore="RtlSymmetry"
tools:text="Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut l" />
@@ -146,6 +148,7 @@
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/label_menu"
android:padding="@dimen/spacer_1hx"
+ android:tint="?attr/colorAccent"
app:srcCompat="@drawable/ic_menu" />
</LinearLayout>
</LinearLayout>
diff --git a/app/src/main/res/layout/item_comment.xml b/app/src/main/res/layout/item_comment.xml
index 9769f681d..754e989fe 100644
--- a/app/src/main/res/layout/item_comment.xml
+++ b/app/src/main/res/layout/item_comment.xml
@@ -22,7 +22,7 @@
android:id="@+id/parentBorder"
android:layout_width="2dp"
android:layout_height="match_parent"
- android:background="@color/primary" />
+ android:background="?attr/colorPrimary" />
<TextView
android:id="@+id/parent"
diff --git a/app/src/main/res/layout/item_manage_label.xml b/app/src/main/res/layout/item_manage_label.xml
index fc5c86a07..7bc7a7194 100644
--- a/app/src/main/res/layout/item_manage_label.xml
+++ b/app/src/main/res/layout/item_manage_label.xml
@@ -17,7 +17,12 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
+ android:layout_marginStart="@dimen/spacer_1hx"
+ android:layout_marginTop="@dimen/spacer_1x"
+ android:layout_marginEnd="@dimen/spacer_1hx"
+ android:layout_marginBottom="@dimen/spacer_1x"
android:ellipsize="middle"
+ app:ensureMinTouchTargetSize="false"
tools:text="@tools:sample/cities" />
</LinearLayout>
diff --git a/app/src/main/res/layout/item_tip.xml b/app/src/main/res/layout/item_tip.xml
index 96df0e431..2177d013c 100644
--- a/app/src/main/res/layout/item_tip.xml
+++ b/app/src/main/res/layout/item_tip.xml
@@ -27,6 +27,7 @@
android:layout_height="wrap_content"
android:layout_marginStart="40dp"
android:layout_marginEnd="@dimen/spacer_1x"
+ android:textColor="@color/defaultBrand"
android:visibility="visible"
tools:text="@string/error_action_open_deck_info"
tools:visibility="visible" />
diff --git a/app/src/main/res/layout/nav_header_main.xml b/app/src/main/res/layout/nav_header_main.xml
index 6f65fba00..34d7cdc7a 100644
--- a/app/src/main/res/layout/nav_header_main.xml
+++ b/app/src/main/res/layout/nav_header_main.xml
@@ -4,7 +4,7 @@
android:id="@+id/header_view"
android:layout_width="match_parent"
android:layout_height="@dimen/drawer_header_height"
- android:background="@color/primary">
+ android:background="@color/defaultBrand">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/logo"
@@ -14,6 +14,7 @@
android:layout_margin="@dimen/spacer_2x"
android:gravity="center"
android:padding="@dimen/spacer_1hx"
+ android:tint="@android:color/white"
app:srcCompat="@drawable/ic_app_logo" />
<TextView
diff --git a/app/src/main/res/values-night/booleans.xml b/app/src/main/res/values-night/booleans.xml
new file mode 100644
index 000000000..41cc6feb9
--- /dev/null
+++ b/app/src/main/res/values-night/booleans.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <bool name="isDayMode">false</bool>
+</resources>
diff --git a/app/src/main/res/values-night/colors.xml b/app/src/main/res/values-night/colors.xml
index 06862fe83..fb270e106 100644
--- a/app/src/main/res/values-night/colors.xml
+++ b/app/src/main/res/values-night/colors.xml
@@ -1,9 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
+ <color name="primary">@android:color/black</color>
+ <color name="accent">@android:color/white</color>
<color name="fg_secondary">#666</color>
<color name="bg_highlighted">#2a2a2a</color>
<color name="bg_info_box">#222222</color>
- <color name="avatars_overlapping_border_color">#424242</color>
+ <color name="bg_card">#121212</color>
+ <color name="bg_card_wrapper">@color/primary</color>
<color name="widget_background">#cc212121</color>
<color name="widget_foreground">#ccf5f5f5</color>
diff --git a/app/src/main/res/values-v23/styles.xml b/app/src/main/res/values-v23/styles.xml
new file mode 100644
index 000000000..88e43bf09
--- /dev/null
+++ b/app/src/main/res/values-v23/styles.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <style name="AppTheme" parent="BaseTheme">
+ <item name="android:windowLightStatusBar">@bool/isDayMode</item>
+ <item name="android:statusBarColor">?attr/colorPrimary</item>
+ </style>
+</resources> \ No newline at end of file
diff --git a/app/src/main/res/values-v27/styles.xml b/app/src/main/res/values-v27/styles.xml
new file mode 100644
index 000000000..15ac19bf3
--- /dev/null
+++ b/app/src/main/res/values-v27/styles.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <style name="AppTheme" parent="BaseTheme">
+ <item name="android:windowLightStatusBar">@bool/isDayMode</item>
+ <item name="android:statusBarColor">?attr/colorPrimary</item>
+ <item name="android:navigationBarColor">?attr/colorPrimary</item>
+ <item name="android:windowLightNavigationBar">@bool/isDayMode</item>
+ </style>
+
+ <style name="SplashTheme" parent="Theme.AppCompat.NoActionBar">
+ <item name="android:windowBackground">@drawable/splash_screen</item>
+ <item name="colorPrimaryDark">@color/defaultBrand</item>
+ <item name="android:navigationBarColor">@color/defaultBrand</item>
+ <item name="android:windowLightNavigationBar">true</item>
+ </style>
+</resources> \ No newline at end of file
diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml
index 02124655d..715f8b814 100644
--- a/app/src/main/res/values/attrs.xml
+++ b/app/src/main/res/values/attrs.xml
@@ -8,6 +8,4 @@
<attr name="description" format="string" />
<attr name="image" format="reference" />
</declare-styleable>
- <attr name="toolbarEditTextColor" format="reference" />
- <attr name="toolbarEditTextHighlightColor" format="reference" />
</resources> \ No newline at end of file
diff --git a/app/src/main/res/values/booleans.xml b/app/src/main/res/values/booleans.xml
new file mode 100644
index 000000000..c47017c70
--- /dev/null
+++ b/app/src/main/res/values/booleans.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <bool name="isDayMode">true</bool>
+</resources>
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index d295b8fae..120fcac27 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -1,7 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
- <color name="primary">#0082c9</color>
- <color name="accent">#ffffff</color>
+ <color name="primary">@android:color/white</color>
+ <color name="accent">#000000</color>
+ <color name="defaultBrand">#0082C9</color>
<color name="toolbarEditTextHighlightColor">#55ffffff</color>
<color name="danger">#d40000</color>
<color name="fg_accent">#fff</color>
@@ -10,8 +11,8 @@
<color name="bg_highlighted">#eee</color>
<color name="grey600">#757575</color>
<color name="bg_info_box">#dddddd</color>
-
- <color name="avatars_overlapping_border_color">#ffffff</color>
+ <color name="bg_card">@android:color/white</color>
+ <color name="bg_card_wrapper">#fafafa</color>
<color name="dark_fg_primary">#e5e5e5</color>
diff --git a/app/src/main/res/values/setup.xml b/app/src/main/res/values/setup.xml
index fb917ffb7..247bb0697 100644
--- a/app/src/main/res/values/setup.xml
+++ b/app/src/main/res/values/setup.xml
@@ -4,7 +4,6 @@
<string name="shared_preference_last_background_sync" translatable="false">it.niedermann.nextcloud.deck.last_background_sync</string>
<string name="shared_preference_theme_main" translatable="false">it.niedermann.nextcloud.deck.theme_main</string>
- <string name="shared_preference_theme_text" translatable="false">it.niedermann.nextcloud.deck.theme_text</string>
<string name="pref_key_wifi_only" translatable="false">wifiOnly</string>
<string name="pref_key_dark_theme" translatable="false">darkTheme</string>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 2d0867b74..51cd41e20 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -256,6 +256,7 @@
<string name="error_dialog_version_not_parsable">We could not determine the version of the server side Deck app. Please make sure it is installed and enabled.</string>
<string name="error_dialog_capabilities_not_parsable">We could not fetch the capabilities of your server. Please make sure your server is running well and other client apps are able to access Nextcloud.</string>
<string name="error_dialog_attachment_upload_failed">An attachment could not be uploaded. Please try to share it on another way and let us know about this bug.</string>
+ <string name="error_dialog_tip_disable_battery_optimizations">Please disable all battery optimizations for Nextcloud and the Deck app.</string>
<string name="error_action_open_deck_info">Open App info</string>
<string name="error_action_open_network">Network settings</string>
<string name="error_action_server_logs">Server logs</string>
@@ -276,4 +277,5 @@
<item quantity="other">%1$d errors while uploading</item>
</plurals>
<string name="simple_report">Report</string>
+ <string name="error_action_open_battery_settings">Battery settings</string>
</resources>
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index d6121c306..f0bff78fe 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -1,37 +1,23 @@
-<resources xmlns:tools="http://schemas.android.com/tools">
+<resources>
- <!-- Default is a light theme with the dark blue brand -->
- <style name="AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar.Bridge">
+ <style name="BaseTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar.Bridge">
<item name="colorPrimary">@color/primary</item>
<item name="colorPrimaryDark">@color/primary</item>
- <item name="colorAccent">@color/primary</item>
- <item name="toolbarEditTextColor">@android:color/white</item>
- <item name="toolbarEditTextHighlightColor">@color/toolbarEditTextHighlightColor</item>
- <item name="android:windowContentOverlay">@null</item>
- <item name="android:elevation" tools:targetApi="lollipop">@null</item>
- </style>
-
- <!-- This is a light theme with a bright brand color like yellow -->
- <style name="AppThemeLightBrand" parent="AppTheme">
- <item name="toolbarEditTextColor">@android:color/black</item>
+ <item name="colorAccent">@color/accent</item>
+ <item name="toolbarStyle">@style/toolbarStyle</item>
+ <item name="android:windowBackground">?attr/colorPrimary</item>
</style>
- <!-- This styles an EditText which is on a primary background like in the toolbar -->
- <style name="EditTextOnPrimaryBackground" parent="ThemeOverlay.MaterialComponents.Dark">
- <item name="android:textColor">?toolbarEditTextColor</item>
- <item name="android:textColorHighlight">?toolbarEditTextHighlightColor</item>
- <item name="colorControlNormal">?toolbarEditTextColor</item>
- <item name="colorControlActivated">?toolbarEditTextColor</item>
- <item name="colorControlHighlight">?toolbarEditTextColor</item>
+ <style name="toolbarStyle" parent="@style/Widget.AppCompat.Toolbar">
+ <item name="android:background">?attr/colorPrimary</item>
</style>
- <style name="DarkTextView" parent="Widget.AppCompat.TextView">
- <item name="android:textColor">@color/dark_fg_primary</item>
- </style>
+ <!-- Default is a light theme with the dark blue brand -->
+ <style name="AppTheme" parent="BaseTheme" />
<style name="SplashTheme" parent="Theme.AppCompat.NoActionBar">
<item name="android:windowBackground">@drawable/splash_screen</item>
- <item name="colorPrimaryDark">@color/primary</item>
+ <item name="colorPrimaryDark">@color/defaultBrand</item>
</style>
<style name="NavigationView">