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

github.com/stefan-niedermann/nextcloud-notes.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/app/src
diff options
context:
space:
mode:
Diffstat (limited to 'app/src')
-rw-r--r--app/src/androidTest/java/it/niedermann/nextcloud/deck/util/ColorUtilTest.java25
-rw-r--r--app/src/main/AndroidManifest.xml6
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/accountswitcher/AccountSwitcherAdapter.java54
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/accountswitcher/AccountSwitcherDialog.java115
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/accountswitcher/AccountSwitcherListener.java11
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/accountswitcher/AccountSwitcherViewHolder.java36
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/android/MultiSelectedActionModeCallback.java28
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/android/NotesListViewItemTouchHelper.java15
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/android/activity/AboutActivity.java12
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/android/activity/AppendToNoteActivity.java11
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/android/activity/EditNoteActivity.java12
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/android/activity/LockedActivity.java4
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/android/activity/NoteListWidgetConfigurationActivity.java6
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java497
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/android/activity/PreferencesActivity.java9
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/android/fragment/AccountChooserAdapter.java12
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/android/fragment/BaseNoteFragment.java50
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/android/fragment/CategoryDialogFragment.java17
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/android/fragment/MoveAccountDialogFragment.java (renamed from app/src/main/java/it/niedermann/owncloud/notes/android/fragment/AccountChooserDialogFragment.java)26
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/android/fragment/NoteEditFragment.java10
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/android/fragment/NotePreviewFragment.java10
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/android/fragment/NoteReadonlyFragment.java10
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/android/fragment/PreferencesFragment.java54
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/android/fragment/SearchableBaseNoteFragment.java39
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/android/fragment/about/AboutFragmentLicenseTab.java20
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/branding/Branded.java9
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedActivity.java67
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedAlertDialogBuilder.java48
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedDeleteAlertDialogBuilder.java26
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedDialogFragment.java24
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedFragment.java49
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedPreferenceCategory.java46
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedSnackbar.java31
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedSwitchPreference.java116
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/branding/BrandingUtil.java134
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/manageaccounts/ManageAccountAdapter.java80
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/manageaccounts/ManageAccountViewHolder.java53
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/manageaccounts/ManageAccountsActivity.java74
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/model/ItemAdapter.java118
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/model/NavigationAdapter.java22
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/model/NoteClickListener.java11
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/model/NoteViewHolder.java143
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/model/SectionItem.java2
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/model/SectionViewHolder.java20
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/persistence/AbstractNotesDatabase.java2
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/persistence/LoadNotesListTask.java45
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/persistence/NoteServerSyncHelper.java3
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesDatabase.java28
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/util/ColorUtil.java44
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/util/DisplayUtils.java64
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/util/MarkDownUtil.java2
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/util/SSOUtil.java4
-rw-r--r--app/src/main/res/animator/appbar_elevation_off.xml9
-rw-r--r--app/src/main/res/animator/appbar_elevation_on.xml11
-rw-r--r--app/src/main/res/drawable-night/border.xml10
-rw-r--r--app/src/main/res/drawable/border.xml12
-rw-r--r--app/src/main/res/drawable/check.xml12
-rw-r--r--app/src/main/res/drawable/ic_arrow_back_grey600_24dp.xml (renamed from app/src/main/res/drawable/ic_arrow_back_white_24dp.xml)2
-rw-r--r--app/src/main/res/drawable/ic_baseline_menu_24.xml5
-rw-r--r--app/src/main/res/drawable/ic_check_white_24dp.xml5
-rw-r--r--app/src/main/res/drawable/ic_color_lens_grey600_24dp.xml5
-rw-r--r--app/src/main/res/drawable/ic_delete_white_24dp.xml5
-rw-r--r--app/src/main/res/drawable/ic_edit_grey600_24dp.xml (renamed from app/src/main/res/drawable/ic_edit_white_24dp.xml)2
-rw-r--r--app/src/main/res/drawable/ic_eye_grey600_24dp.xml (renamed from app/src/main/res/drawable/ic_eye_white_24dp.xml)2
-rw-r--r--app/src/main/res/drawable/ic_launcher_foreground_full.xml13
-rw-r--r--app/src/main/res/drawable/ic_remove_red_eye_grey_24dp.xml10
-rw-r--r--app/src/main/res/drawable/ic_search_grey600_24dp.xml9
-rw-r--r--app/src/main/res/drawable/ic_search_white_24dp.xml5
-rw-r--r--app/src/main/res/drawable/ic_send_grey600_24dp.xml (renamed from app/src/main/res/drawable/ic_send_white_24dp.xml)2
-rw-r--r--app/src/main/res/drawable/splashscreen.xml2
-rw-r--r--app/src/main/res/layout/activity_about.xml40
-rw-r--r--app/src/main/res/layout/activity_edit.xml26
-rw-r--r--app/src/main/res/layout/activity_exception.xml17
-rw-r--r--app/src/main/res/layout/activity_manage_accounts.xml32
-rw-r--r--app/src/main/res/layout/activity_note_list_configuration.xml1
-rw-r--r--app/src/main/res/layout/activity_notes_list_view.xml97
-rw-r--r--app/src/main/res/layout/activity_preferences.xml26
-rw-r--r--app/src/main/res/layout/dialog_account_switcher.xml139
-rw-r--r--app/src/main/res/layout/dialog_change_category.xml19
-rw-r--r--app/src/main/res/layout/dialog_exception.xml2
-rw-r--r--app/src/main/res/layout/drawer_layout.xml133
-rw-r--r--app/src/main/res/layout/fragment_about_license_tab.xml9
-rw-r--r--app/src/main/res/layout/fragment_note_edit.xml9
-rw-r--r--app/src/main/res/layout/fragment_note_preview.xml10
-rw-r--r--app/src/main/res/layout/item_account.xml4
-rw-r--r--app/src/main/res/layout/item_account_choose.xml62
-rw-r--r--app/src/main/res/layout/item_category.xml10
-rw-r--r--app/src/main/res/layout/item_navigation.xml44
-rw-r--r--app/src/main/res/layout/item_notes_list_note_item.xml60
-rw-r--r--app/src/main/res/layout/item_notes_list_section_item.xml49
-rw-r--r--app/src/main/res/layout/item_pref.xml5
-rw-r--r--app/src/main/res/layout/item_preference_category.xml12
-rw-r--r--app/src/main/res/menu/menu_list_context_multiple.xml4
-rw-r--r--app/src/main/res/menu/menu_list_view.xml12
-rw-r--r--app/src/main/res/menu/menu_note_activity.xml4
-rw-r--r--app/src/main/res/menu/menu_note_fragment.xml6
-rw-r--r--app/src/main/res/values-night/booleans.xml4
-rw-r--r--app/src/main/res/values-night/colors.xml10
-rw-r--r--app/src/main/res/values-nl/strings.xml2
-rw-r--r--app/src/main/res/values-tr/strings.xml2
-rw-r--r--app/src/main/res/values-v23/styles.xml14
-rw-r--r--app/src/main/res/values-v27/styles.xml18
-rw-r--r--app/src/main/res/values/booleans.xml4
-rw-r--r--app/src/main/res/values/colors.xml15
-rw-r--r--app/src/main/res/values/dimens.xml5
-rw-r--r--app/src/main/res/values/strings.xml12
-rw-r--r--app/src/main/res/values/styles.xml15
-rw-r--r--app/src/main/res/xml/preferences.xml139
108 files changed, 2672 insertions, 875 deletions
diff --git a/app/src/androidTest/java/it/niedermann/nextcloud/deck/util/ColorUtilTest.java b/app/src/androidTest/java/it/niedermann/nextcloud/deck/util/ColorUtilTest.java
index bde7ef68..2977c08b 100644
--- a/app/src/androidTest/java/it/niedermann/nextcloud/deck/util/ColorUtilTest.java
+++ b/app/src/androidTest/java/it/niedermann/nextcloud/deck/util/ColorUtilTest.java
@@ -6,7 +6,9 @@ import androidx.annotation.ColorInt;
import androidx.core.util.Pair;
import androidx.test.ext.junit.runners.AndroidJUnit4;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import java.util.ArrayList;
@@ -98,4 +100,27 @@ public class ColorUtilTest {
);
}
}
+
+ @Rule
+ public final ExpectedException exception = ExpectedException.none();
+
+ @Test
+ public void testGetCleanHexaColorString() {
+ final List<Pair<String, String>> validColors = new ArrayList<>();
+ validColors.add(new Pair<>("#0082C9", "#0082C9"));
+ validColors.add(new Pair<>("0082C9", "#0082C9"));
+ validColors.add(new Pair<>("#CCC", "#CCCCCC"));
+ validColors.add(new Pair<>("ccc", "#cccccc"));
+ validColors.add(new Pair<>("af0", "#aaff00"));
+ validColors.add(new Pair<>("#af0", "#aaff00"));
+ for (Pair<String, String> color : validColors) {
+ assertEquals("Expect " + color.first + " to be cleaned up to " + color.second, color.second, ColorUtil.formatColorToParsableHexString(color.first));
+ }
+
+ final String[] invalidColors = new String[]{null, "", "cc", "c", "#a", "#55L", "55L"};
+ for (String color : invalidColors) {
+ exception.expect(IllegalArgumentException.class);
+ ColorUtil.formatColorToParsableHexString(color);
+ }
+ }
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 6180a1a6..fc42c3cf 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -63,6 +63,12 @@
android:label="@string/app_name" />
<activity
+ android:name=".manageaccounts.ManageAccountsActivity"
+ android:label="@string/manage_accounts"
+ android:parentActivityName=".android.activity.NotesListViewActivity"
+ android:windowSoftInputMode="stateHidden" />
+
+ <activity
android:name=".android.activity.PreferencesActivity"
android:label="@string/action_settings"
android:parentActivityName=".android.activity.NotesListViewActivity"
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/accountswitcher/AccountSwitcherAdapter.java b/app/src/main/java/it/niedermann/owncloud/notes/accountswitcher/AccountSwitcherAdapter.java
new file mode 100644
index 00000000..0223a53f
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/accountswitcher/AccountSwitcherAdapter.java
@@ -0,0 +1,54 @@
+package it.niedermann.owncloud.notes.accountswitcher;
+
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.core.util.Consumer;
+import androidx.recyclerview.widget.RecyclerView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import it.niedermann.owncloud.notes.R;
+import it.niedermann.owncloud.notes.model.LocalAccount;
+
+public class AccountSwitcherAdapter extends RecyclerView.Adapter<AccountSwitcherViewHolder> {
+
+ @NonNull
+ private final List<LocalAccount> localAccounts = new ArrayList<>();
+ @NonNull
+ private final Consumer<LocalAccount> onAccountClick;
+
+ public AccountSwitcherAdapter(@NonNull Consumer<LocalAccount> onAccountClick) {
+ this.onAccountClick = onAccountClick;
+ setHasStableIds(true);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return localAccounts.get(position).getId();
+ }
+
+ @NonNull
+ @Override
+ public AccountSwitcherViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ return new AccountSwitcherViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_account_choose, parent, false));
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull AccountSwitcherViewHolder holder, int position) {
+ holder.bind(localAccounts.get(position), onAccountClick);
+ }
+
+ @Override
+ public int getItemCount() {
+ return localAccounts.size();
+ }
+
+ public void setLocalAccounts(@NonNull List<LocalAccount> localAccounts) {
+ this.localAccounts.clear();
+ this.localAccounts.addAll(localAccounts);
+ notifyDataSetChanged();
+ }
+}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/accountswitcher/AccountSwitcherDialog.java b/app/src/main/java/it/niedermann/owncloud/notes/accountswitcher/AccountSwitcherDialog.java
new file mode 100644
index 00000000..249d2c3d
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/accountswitcher/AccountSwitcherDialog.java
@@ -0,0 +1,115 @@
+package it.niedermann.owncloud.notes.accountswitcher;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.drawable.LayerDrawable;
+import android.net.Uri;
+import android.os.Bundle;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.DialogFragment;
+
+import com.bumptech.glide.Glide;
+import com.bumptech.glide.request.RequestOptions;
+
+import java.util.List;
+
+import it.niedermann.owncloud.notes.R;
+import it.niedermann.owncloud.notes.branding.BrandedDialogFragment;
+import it.niedermann.owncloud.notes.databinding.DialogAccountSwitcherBinding;
+import it.niedermann.owncloud.notes.manageaccounts.ManageAccountsActivity;
+import it.niedermann.owncloud.notes.model.LocalAccount;
+import it.niedermann.owncloud.notes.persistence.NotesDatabase;
+
+import static it.niedermann.owncloud.notes.android.activity.NotesListViewActivity.manage_account;
+import static it.niedermann.owncloud.notes.branding.BrandingUtil.applyBrandToLayerDrawable;
+
+public class AccountSwitcherDialog extends BrandedDialogFragment {
+
+ private static final String KEY_CURRENT_ACCOUNT_ID = "current_account_id";
+
+ private NotesDatabase db;
+ private DialogAccountSwitcherBinding binding;
+ private AccountSwitcherListener accountSwitcherListener;
+ private long currentAccountId;
+
+ @Override
+ public void onAttach(@NonNull Context context) {
+ super.onAttach(context);
+ if (context instanceof AccountSwitcherListener) {
+ this.accountSwitcherListener = (AccountSwitcherListener) context;
+ } else {
+ throw new ClassCastException("Caller must implement " + AccountSwitcherListener.class.getSimpleName());
+ }
+
+ final Bundle args = getArguments();
+
+ if (args == null || !args.containsKey(KEY_CURRENT_ACCOUNT_ID)) {
+ throw new IllegalArgumentException("Please provide at least " + KEY_CURRENT_ACCOUNT_ID);
+ } else {
+ this.currentAccountId = args.getLong(KEY_CURRENT_ACCOUNT_ID);
+ }
+
+ db = NotesDatabase.getInstance(getActivity());
+ }
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ binding = DialogAccountSwitcherBinding.inflate(requireActivity().getLayoutInflater());
+
+ LocalAccount currentLocalAccount = db.getAccount(currentAccountId);
+ binding.accountItemLabel.setText(currentLocalAccount.getAccountName());
+ Glide.with(requireContext())
+ .load(currentLocalAccount.getUrl() + "/index.php/avatar/" + Uri.encode(currentLocalAccount.getUserName()) + "/64")
+ .error(R.drawable.ic_account_circle_grey_24dp)
+ .apply(RequestOptions.circleCropTransform())
+ .into(binding.currentAccountItemAvatar);
+ binding.accountLayout.setOnClickListener((v) -> dismiss());
+
+ AccountSwitcherAdapter adapter = new AccountSwitcherAdapter((localAccount -> {
+ accountSwitcherListener.onAccountChosen(localAccount);
+ dismiss();
+ }));
+ binding.accountsList.setAdapter(adapter);
+ List<LocalAccount> localAccounts = db.getAccounts();
+ for (LocalAccount localAccount : localAccounts) {
+ if (localAccount.getId() == currentLocalAccount.getId()) {
+ localAccounts.remove(localAccount);
+ break;
+ }
+ }
+ adapter.setLocalAccounts(localAccounts);
+
+ binding.addAccount.setOnClickListener((v) -> {
+ accountSwitcherListener.addAccount();
+ dismiss();
+ });
+
+ binding.manageAccounts.setOnClickListener((v) -> {
+ requireActivity().startActivityForResult(new Intent(requireContext(), ManageAccountsActivity.class), manage_account);
+ dismiss();
+ });
+
+ return new AlertDialog.Builder(requireContext())
+ .setView(binding.getRoot())
+ .create();
+ }
+
+ public static DialogFragment newInstance(long currentAccountId) {
+ DialogFragment dialog = new AccountSwitcherDialog();
+
+ Bundle args = new Bundle();
+ args.putLong(KEY_CURRENT_ACCOUNT_ID, currentAccountId);
+ dialog.setArguments(args);
+
+ return dialog;
+ }
+
+ @Override
+ public void applyBrand(int mainColor, int textColor) {
+ applyBrandToLayerDrawable((LayerDrawable) binding.check.getDrawable(), R.id.area, mainColor);
+ }
+}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/accountswitcher/AccountSwitcherListener.java b/app/src/main/java/it/niedermann/owncloud/notes/accountswitcher/AccountSwitcherListener.java
new file mode 100644
index 00000000..2e26277f
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/accountswitcher/AccountSwitcherListener.java
@@ -0,0 +1,11 @@
+package it.niedermann.owncloud.notes.accountswitcher;
+
+import it.niedermann.owncloud.notes.model.LocalAccount;
+
+public interface AccountSwitcherListener {
+ void addAccount();
+
+ void onAccountChosen(LocalAccount localAccount);
+
+ void onAccountDeleted(LocalAccount localAccount);
+}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/accountswitcher/AccountSwitcherViewHolder.java b/app/src/main/java/it/niedermann/owncloud/notes/accountswitcher/AccountSwitcherViewHolder.java
new file mode 100644
index 00000000..7093e651
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/accountswitcher/AccountSwitcherViewHolder.java
@@ -0,0 +1,36 @@
+package it.niedermann.owncloud.notes.accountswitcher;
+
+import android.net.Uri;
+import android.view.View;
+
+import androidx.annotation.NonNull;
+import androidx.core.util.Consumer;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.bumptech.glide.Glide;
+import com.bumptech.glide.request.RequestOptions;
+
+import it.niedermann.owncloud.notes.R;
+import it.niedermann.owncloud.notes.databinding.ItemAccountChooseBinding;
+import it.niedermann.owncloud.notes.model.LocalAccount;
+
+public class AccountSwitcherViewHolder extends RecyclerView.ViewHolder {
+
+ ItemAccountChooseBinding binding;
+
+ public AccountSwitcherViewHolder(@NonNull View itemView) {
+ super(itemView);
+ binding = ItemAccountChooseBinding.bind(itemView);
+ }
+
+ public void bind(@NonNull LocalAccount localAccount, @NonNull Consumer<LocalAccount> onAccountClick) {
+ binding.accountItemLabel.setText(localAccount.getAccountName());
+ Glide.with(itemView.getContext())
+ .load(localAccount.getUrl() + "/index.php/avatar/" + Uri.encode(localAccount.getUserName()) + "/64")
+ .error(R.drawable.ic_account_circle_grey_24dp)
+ .apply(RequestOptions.circleCropTransform())
+ .into(binding.accountItemAvatar);
+ itemView.setOnClickListener((v) -> onAccountClick.accept(localAccount));
+ binding.delete.setVisibility(View.GONE);
+ }
+}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/MultiSelectedActionModeCallback.java b/app/src/main/java/it/niedermann/owncloud/notes/android/MultiSelectedActionModeCallback.java
index 499aa212..b90be5d7 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/android/MultiSelectedActionModeCallback.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/android/MultiSelectedActionModeCallback.java
@@ -1,14 +1,18 @@
package it.niedermann.owncloud.notes.android;
import android.content.Context;
+import android.graphics.drawable.Drawable;
import android.text.TextUtils;
+import android.util.TypedValue;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
+import androidx.annotation.ColorInt;
import androidx.appcompat.view.ActionMode;
import androidx.appcompat.view.ActionMode.Callback;
import androidx.appcompat.widget.SearchView;
+import androidx.core.graphics.drawable.DrawableCompat;
import androidx.fragment.app.FragmentManager;
import androidx.recyclerview.widget.RecyclerView;
@@ -23,7 +27,8 @@ import java.util.List;
import it.niedermann.owncloud.notes.R;
import it.niedermann.owncloud.notes.android.activity.NotesListViewActivity;
-import it.niedermann.owncloud.notes.android.fragment.AccountChooserDialogFragment;
+import it.niedermann.owncloud.notes.android.fragment.MoveAccountDialogFragment;
+import it.niedermann.owncloud.notes.branding.BrandedSnackbar;
import it.niedermann.owncloud.notes.model.DBNote;
import it.niedermann.owncloud.notes.model.ItemAdapter;
import it.niedermann.owncloud.notes.persistence.NoteServerSyncHelper.ViewProvider;
@@ -32,6 +37,9 @@ import it.niedermann.owncloud.notes.util.ShareUtil;
public class MultiSelectedActionModeCallback implements Callback {
+ @ColorInt
+ private int colorAccent;
+
private final Context context;
private final ViewProvider viewProvider;
private final NotesDatabase db;
@@ -51,12 +59,24 @@ public class MultiSelectedActionModeCallback implements Callback {
this.refreshLists = refreshLists;
this.fragmentManager = fragmentManager;
this.searchView = searchView;
+
+ final TypedValue typedValue = new TypedValue();
+ context.getTheme().resolveAttribute(R.attr.colorAccent, typedValue, true);
+ colorAccent = typedValue.data;
}
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// inflate contextual menu
mode.getMenuInflater().inflate(R.menu.menu_list_context_multiple, menu);
+ for (int i = 0; i < menu.size(); i++) {
+ Drawable drawable = menu.getItem(i).getIcon();
+ if (drawable != null) {
+ drawable = DrawableCompat.wrap(drawable);
+ DrawableCompat.setTint(drawable, colorAccent);
+ menu.getItem(i).setIcon(drawable);
+ }
+ }
return true;
}
@@ -90,7 +110,7 @@ public class MultiSelectedActionModeCallback implements Callback {
String deletedSnackbarTitle = deletedNotes.size() == 1
? context.getString(R.string.action_note_deleted, deletedNotes.get(0).getTitle())
: context.getString(R.string.bulk_notes_deleted, deletedNotes.size());
- Snackbar.make(viewProvider.getView(), deletedSnackbarTitle, Snackbar.LENGTH_LONG)
+ BrandedSnackbar.make(viewProvider.getView(), deletedSnackbarTitle, Snackbar.LENGTH_LONG)
.setAction(R.string.action_undo, (View v) -> {
db.getNoteServerSyncHelper().addCallbackPush(ssoAccount, refreshLists::run);
for (DBNote deletedNote : deletedNotes) {
@@ -100,7 +120,7 @@ public class MultiSelectedActionModeCallback implements Callback {
String restoreSnackbarTitle = deletedNotes.size() == 1
? context.getString(R.string.action_note_restored, deletedNotes.get(0).getTitle())
: context.getString(R.string.bulk_notes_restored, deletedNotes.size());
- Snackbar.make(viewProvider.getView(), restoreSnackbarTitle, Snackbar.LENGTH_SHORT)
+ BrandedSnackbar.make(viewProvider.getView(), restoreSnackbarTitle, Snackbar.LENGTH_SHORT)
.show();
})
.show();
@@ -109,7 +129,7 @@ public class MultiSelectedActionModeCallback implements Callback {
}
return true;
case R.id.menu_move:
- AccountChooserDialogFragment.newInstance().show(fragmentManager, NotesListViewActivity.class.getSimpleName());
+ MoveAccountDialogFragment.newInstance().show(fragmentManager, NotesListViewActivity.class.getSimpleName());
return true;
case R.id.menu_share:
final String subject = (adapter.getSelected().size() == 1)
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/NotesListViewItemTouchHelper.java b/app/src/main/java/it/niedermann/owncloud/notes/android/NotesListViewItemTouchHelper.java
index ccb3cd9c..9ec2eac3 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/android/NotesListViewItemTouchHelper.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/android/NotesListViewItemTouchHelper.java
@@ -16,9 +16,12 @@ import com.google.android.material.snackbar.Snackbar;
import com.nextcloud.android.sso.model.SingleSignOnAccount;
import it.niedermann.owncloud.notes.R;
+import it.niedermann.owncloud.notes.branding.BrandedSnackbar;
import it.niedermann.owncloud.notes.model.DBNote;
import it.niedermann.owncloud.notes.model.ISyncCallback;
import it.niedermann.owncloud.notes.model.ItemAdapter;
+import it.niedermann.owncloud.notes.model.NoteViewHolder;
+import it.niedermann.owncloud.notes.model.SectionViewHolder;
import it.niedermann.owncloud.notes.persistence.NoteServerSyncHelper.ViewProvider;
import it.niedermann.owncloud.notes.persistence.NotesDatabase;
@@ -53,7 +56,7 @@ public class NotesListViewItemTouchHelper extends ItemTouchHelper {
*/
@Override
public int getSwipeDirs(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
- if (viewHolder instanceof ItemAdapter.SectionViewHolder) return 0;
+ if (viewHolder instanceof SectionViewHolder) return 0;
return super.getSwipeDirs(recyclerView, viewHolder);
}
@@ -76,12 +79,12 @@ public class NotesListViewItemTouchHelper extends ItemTouchHelper {
if (viewProvider == null) {
Toast.makeText(context, context.getString(R.string.action_note_deleted, dbNote.getTitle()), Toast.LENGTH_LONG).show();
} else {
- Snackbar.make(viewProvider.getView(), context.getString(R.string.action_note_deleted, dbNote.getTitle()), Snackbar.LENGTH_LONG)
+ BrandedSnackbar.make(viewProvider.getView(), context.getString(R.string.action_note_deleted, dbNote.getTitle()), Snackbar.LENGTH_LONG)
.setAction(R.string.action_undo, (View v) -> {
db.getNoteServerSyncHelper().addCallbackPush(ssoAccount, refreshLists::run);
db.addNoteAndSync(ssoAccount, dbNote.getAccountId(), dbNote);
refreshLists.run();
- Snackbar.make(viewProvider.getView(), context.getString(R.string.action_note_restored, dbNote.getTitle()), Snackbar.LENGTH_SHORT)
+ BrandedSnackbar.make(viewProvider.getView(), context.getString(R.string.action_note_restored, dbNote.getTitle()), Snackbar.LENGTH_SHORT)
.show();
})
.show();
@@ -99,11 +102,11 @@ public class NotesListViewItemTouchHelper extends ItemTouchHelper {
@Override
public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
- ItemAdapter.NoteViewHolder noteViewHolder = (ItemAdapter.NoteViewHolder) viewHolder;
+ NoteViewHolder noteViewHolder = (NoteViewHolder) viewHolder;
// show swipe icon on the side
noteViewHolder.showSwipe(dX > 0);
// move only swipeable part of item (not leave-behind)
- getDefaultUIUtil().onDraw(c, recyclerView, noteViewHolder.noteSwipeable, dX, dY, actionState, isCurrentlyActive);
+ getDefaultUIUtil().onDraw(c, recyclerView, noteViewHolder.getNoteSwipeable(), dX, dY, actionState, isCurrentlyActive);
}
@Override
@@ -122,7 +125,7 @@ public class NotesListViewItemTouchHelper extends ItemTouchHelper {
if (swipeRefreshLayout != null) {
swipeRefreshLayout.setEnabled(swipeRefreshLayoutEnabled);
}
- getDefaultUIUtil().clearView(((ItemAdapter.NoteViewHolder) viewHolder).noteSwipeable);
+ getDefaultUIUtil().clearView(((NoteViewHolder) viewHolder).getNoteSwipeable());
}
@Override
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/AboutActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/AboutActivity.java
index 0334ba64..d6cd1c39 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/AboutActivity.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/AboutActivity.java
@@ -2,6 +2,7 @@ package it.niedermann.owncloud.notes.android.activity;
import android.os.Bundle;
+import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
@@ -11,15 +12,18 @@ import it.niedermann.owncloud.notes.R;
import it.niedermann.owncloud.notes.android.fragment.about.AboutFragmentContributingTab;
import it.niedermann.owncloud.notes.android.fragment.about.AboutFragmentCreditsTab;
import it.niedermann.owncloud.notes.android.fragment.about.AboutFragmentLicenseTab;
+import it.niedermann.owncloud.notes.branding.BrandingUtil;
import it.niedermann.owncloud.notes.databinding.ActivityAboutBinding;
public class AboutActivity extends LockedActivity {
+ private ActivityAboutBinding binding;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- ActivityAboutBinding binding = ActivityAboutBinding.inflate(getLayoutInflater());
+ binding = ActivityAboutBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
setSupportActionBar(binding.toolbar);
@@ -27,6 +31,12 @@ public class AboutActivity extends LockedActivity {
binding.tabs.setupWithViewPager(binding.pager);
}
+ @Override
+ public void applyBrand(int mainColor, int textColor) {
+ @ColorInt int finalMainColor = BrandingUtil.getSecondaryForegroundColorDependingOnTheme(this, mainColor);
+ binding.tabs.setSelectedTabIndicatorColor(finalMainColor);
+ }
+
private class TabsPagerAdapter extends FragmentPagerAdapter {
TabsPagerAdapter(FragmentManager fragmentManager) {
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/AppendToNoteActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/AppendToNoteActivity.java
index 3f286c1c..2cc72aea 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/AppendToNoteActivity.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/AppendToNoteActivity.java
@@ -2,9 +2,13 @@ package it.niedermann.owncloud.notes.android.activity;
import android.content.Intent;
import android.os.Bundle;
+import android.util.Log;
import android.view.View;
import android.widget.Toast;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.ActionBar;
+
import it.niedermann.owncloud.notes.R;
import it.niedermann.owncloud.notes.model.DBNote;
@@ -20,7 +24,12 @@ public class AppendToNoteActivity extends NotesListViewActivity {
super.onCreate(savedInstanceState);
final Intent receivedIntent = getIntent();
receivedText = receivedIntent.getStringExtra(Intent.EXTRA_TEXT);
- binding.activityNotesListView.toolbar.setTitle(R.string.append_to_note);
+ @Nullable final ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ getSupportActionBar().setTitle(R.string.append_to_note);
+ } else {
+ Log.e(TAG, "SupportActioBar is null. Expected toolbar to be present to set a title.");
+ }
binding.activityNotesListView.toolbar.setSubtitle(receivedText);
}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/EditNoteActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/EditNoteActivity.java
index d9e9fb7d..6e6fc2e6 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/EditNoteActivity.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/EditNoteActivity.java
@@ -29,9 +29,9 @@ import it.niedermann.owncloud.notes.model.DBNote;
import it.niedermann.owncloud.notes.model.LocalAccount;
import it.niedermann.owncloud.notes.util.NoteUtil;
-import static it.niedermann.owncloud.notes.android.fragment.AccountChooserAdapter.AccountChooserListener;
+import static it.niedermann.owncloud.notes.android.fragment.AccountChooserAdapter.MoveAccountListener;
-public class EditNoteActivity extends LockedActivity implements BaseNoteFragment.NoteFragmentListener, AccountChooserListener {
+public class EditNoteActivity extends LockedActivity implements BaseNoteFragment.NoteFragmentListener, MoveAccountListener {
private static final String TAG = EditNoteActivity.class.getSimpleName();
@@ -54,6 +54,7 @@ public class EditNoteActivity extends LockedActivity implements BaseNoteFragment
binding = ActivityEditBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
+ setSupportActionBar(binding.toolbar);
if (savedInstanceState == null) {
launchNoteFragment();
@@ -267,7 +268,12 @@ public class EditNoteActivity extends LockedActivity implements BaseNoteFragment
}
@Override
- public void onAccountChosen(LocalAccount account) {
+ public void moveToAccount(LocalAccount account) {
fragment.moveNote(account);
}
+
+ @Override
+ public void applyBrand(int mainColor, int textColor) {
+ applyBrandToPrimaryToolbar(binding.toolbar);
+ }
} \ No newline at end of file
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/LockedActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/LockedActivity.java
index 0b0ca7c1..07a544df 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/LockedActivity.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/LockedActivity.java
@@ -8,13 +8,13 @@ import android.os.Bundle;
import android.util.Log;
import androidx.annotation.Nullable;
-import androidx.appcompat.app.AppCompatActivity;
import it.niedermann.owncloud.notes.ExceptionHandler;
import it.niedermann.owncloud.notes.R;
+import it.niedermann.owncloud.notes.branding.BrandedActivity;
import it.niedermann.owncloud.notes.util.Notes;
-public abstract class LockedActivity extends AppCompatActivity {
+public abstract class LockedActivity extends BrandedActivity {
private static final String TAG = LockedActivity.class.getSimpleName();
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NoteListWidgetConfigurationActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NoteListWidgetConfigurationActivity.java
index eefe770a..92f20c4b 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NoteListWidgetConfigurationActivity.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NoteListWidgetConfigurationActivity.java
@@ -82,7 +82,7 @@ public class NoteListWidgetConfigurationActivity extends LockedActivity {
RecyclerView recyclerView;
RecyclerView.LayoutManager layoutManager;
- adapterCategories = new NavigationAdapter(new NavigationAdapter.ClickListener() {
+ adapterCategories = new NavigationAdapter(this, new NavigationAdapter.ClickListener() {
@Override
public void onItemClick(NavigationAdapter.NavigationItem item) {
NoteListsWidgetData data = new NoteListsWidgetData();
@@ -136,6 +136,10 @@ public class NoteListWidgetConfigurationActivity extends LockedActivity {
new LoadCategoryListTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
+ @Override
+ public void applyBrand(int mainColor, int textColor) {
+ }
+
private class LoadCategoryListTask extends AsyncTask<Void, Void, List<NavigationAdapter.NavigationItem>> {
@Override
protected List<NavigationAdapter.NavigationItem> doInBackground(Void... voids) {
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java
index 447006e8..6efa0ce6 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java
@@ -1,31 +1,30 @@
package it.niedermann.owncloud.notes.android.activity;
+import android.animation.AnimatorInflater;
+import android.annotation.SuppressLint;
import android.app.SearchManager;
import android.content.Intent;
-import android.content.res.Configuration;
-import android.database.sqlite.SQLiteConstraintException;
+import android.database.sqlite.SQLiteException;
+import android.graphics.Color;
+import android.graphics.PorterDuff;
import android.net.Uri;
import android.os.AsyncTask;
+import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
+import android.text.TextUtils;
import android.util.Log;
-import android.view.Menu;
-import android.view.MenuItem;
import android.view.View;
import android.view.ViewTreeObserver;
-import android.widget.ImageView;
import android.widget.LinearLayout;
-import android.widget.TextView;
import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.view.ActionMode;
-import androidx.appcompat.widget.AppCompatImageView;
import androidx.appcompat.widget.SearchView;
-import androidx.appcompat.widget.Toolbar;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
+import androidx.core.graphics.drawable.DrawableCompat;
import androidx.core.view.GravityCompat;
+import androidx.core.view.ViewCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
@@ -39,6 +38,7 @@ import com.nextcloud.android.sso.exceptions.AccountImportCancelledException;
import com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountNotFoundException;
import com.nextcloud.android.sso.exceptions.NextcloudHttpRequestFailedException;
import com.nextcloud.android.sso.exceptions.NoCurrentAccountSelectedException;
+import com.nextcloud.android.sso.exceptions.TokenMismatchException;
import com.nextcloud.android.sso.helper.SingleAccountHelper;
import com.nextcloud.android.sso.model.SingleSignOnAccount;
@@ -48,10 +48,15 @@ import java.util.List;
import java.util.Map;
import it.niedermann.owncloud.notes.R;
+import it.niedermann.owncloud.notes.accountswitcher.AccountSwitcherDialog;
+import it.niedermann.owncloud.notes.accountswitcher.AccountSwitcherListener;
import it.niedermann.owncloud.notes.android.MultiSelectedActionModeCallback;
import it.niedermann.owncloud.notes.android.NotesListViewItemTouchHelper;
-import it.niedermann.owncloud.notes.android.fragment.AccountChooserAdapter.AccountChooserListener;
+import it.niedermann.owncloud.notes.android.fragment.AccountChooserAdapter.MoveAccountListener;
import it.niedermann.owncloud.notes.android.fragment.ExceptionDialogFragment;
+import it.niedermann.owncloud.notes.branding.BrandedSnackbar;
+import it.niedermann.owncloud.notes.branding.BrandingUtil;
+import it.niedermann.owncloud.notes.databinding.ActivityNotesListViewBinding;
import it.niedermann.owncloud.notes.databinding.DrawerLayoutBinding;
import it.niedermann.owncloud.notes.model.Capabilities;
import it.niedermann.owncloud.notes.model.Category;
@@ -63,17 +68,23 @@ import it.niedermann.owncloud.notes.model.LocalAccount;
import it.niedermann.owncloud.notes.model.NavigationAdapter;
import it.niedermann.owncloud.notes.model.NavigationAdapter.CategoryNavigationItem;
import it.niedermann.owncloud.notes.model.NavigationAdapter.NavigationItem;
+import it.niedermann.owncloud.notes.model.NoteClickListener;
import it.niedermann.owncloud.notes.persistence.CapabilitiesClient;
import it.niedermann.owncloud.notes.persistence.CapabilitiesWorker;
import it.niedermann.owncloud.notes.persistence.LoadNotesListTask;
import it.niedermann.owncloud.notes.persistence.LoadNotesListTask.NotesLoadedListener;
import it.niedermann.owncloud.notes.persistence.NoteServerSyncHelper;
+import it.niedermann.owncloud.notes.persistence.NoteServerSyncHelper.ViewProvider;
import it.niedermann.owncloud.notes.persistence.NotesDatabase;
import it.niedermann.owncloud.notes.util.NoteUtil;
+import static android.view.View.GONE;
+import static android.view.View.VISIBLE;
+import static it.niedermann.owncloud.notes.branding.BrandingUtil.getSecondaryForegroundColorDependingOnTheme;
+import static it.niedermann.owncloud.notes.util.ColorUtil.contrastRatioIsSufficient;
import static it.niedermann.owncloud.notes.util.SSOUtil.askForNewAccount;
-public class NotesListViewActivity extends LockedActivity implements ItemAdapter.NoteClickListener, NoteServerSyncHelper.ViewProvider, AccountChooserListener {
+public class NotesListViewActivity extends LockedActivity implements NoteClickListener, ViewProvider, MoveAccountListener, AccountSwitcherListener {
private static final String TAG = NotesListViewActivity.class.getSimpleName();
@@ -91,6 +102,7 @@ public class NotesListViewActivity extends LockedActivity implements ItemAdapter
private final static int show_single_note_cmd = 1;
private final static int server_settings = 2;
private final static int about = 3;
+ public final static int manage_account = 4;
/**
* Used to detect the onResume() call after the import dialog has been displayed.
@@ -102,6 +114,7 @@ public class NotesListViewActivity extends LockedActivity implements ItemAdapter
protected LocalAccount localAccount;
protected DrawerLayoutBinding binding;
+ protected ActivityNotesListViewBinding activityBinding;
private CoordinatorLayout coordinatorLayout;
private SwipeRefreshLayout swipeRefreshLayout;
@@ -111,15 +124,14 @@ public class NotesListViewActivity extends LockedActivity implements ItemAdapter
protected ItemAdapter adapter = null;
protected NotesDatabase db = null;
- private ActionBarDrawerToggle drawerToggle;
private NavigationAdapter adapterCategories;
private NavigationItem itemRecent;
private NavigationItem itemFavorites;
private NavigationItem itemUncategorized;
+ @NonNull
private Category navigationSelection = new Category(null, null);
private String navigationOpen = "";
private ActionMode mActionMode;
- private SearchView searchView = null;
private final ISyncCallback syncCallBack = () -> {
adapter.clearSelection(listView);
if (mActionMode != null) {
@@ -128,7 +140,6 @@ public class NotesListViewActivity extends LockedActivity implements ItemAdapter
refreshLists();
swipeRefreshLayout.setRefreshing(false);
};
- private boolean accountChooserActive;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -136,7 +147,10 @@ public class NotesListViewActivity extends LockedActivity implements ItemAdapter
CapabilitiesWorker.update(this);
binding = DrawerLayoutBinding.inflate(getLayoutInflater());
+ activityBinding = ActivityNotesListViewBinding.bind(binding.activityNotesListView.getRoot());
+
setContentView(binding.getRoot());
+
this.coordinatorLayout = binding.activityNotesListView.activityNotesListView;
this.swipeRefreshLayout = binding.activityNotesListView.swiperefreshlayout;
this.fabCreate = binding.activityNotesListView.fabCreate;
@@ -151,15 +165,17 @@ public class NotesListViewActivity extends LockedActivity implements ItemAdapter
navigationSelection = new Category(null, true);
}
} else {
- navigationSelection = (Category) savedInstanceState.getSerializable(SAVED_STATE_NAVIGATION_SELECTION);
+ Object savedCategory = savedInstanceState.getSerializable(SAVED_STATE_NAVIGATION_SELECTION);
+ if (savedCategory != null) {
+ navigationSelection = (Category) savedCategory;
+ }
navigationOpen = savedInstanceState.getString(SAVED_STATE_NAVIGATION_OPEN);
categoryAdapterSelectedItem = savedInstanceState.getString(SAVED_STATE_NAVIGATION_ADAPTER_SLECTION);
}
db = NotesDatabase.getInstance(this);
- setupHeader();
- setupActionBar();
+ setupToolbars();
setupNavigationList(categoryAdapterSelectedItem);
setupNavigationMenu();
setupNotesList();
@@ -194,18 +210,6 @@ public class NotesListViewActivity extends LockedActivity implements ItemAdapter
}
@Override
- protected void onPostCreate(@Nullable Bundle savedInstanceState) {
- super.onPostCreate(savedInstanceState);
- drawerToggle.syncState();
- }
-
- @Override
- public void onConfigurationChanged(@NonNull Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- drawerToggle.syncState();
- }
-
- @Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
if (localAccount != null) {
@@ -221,6 +225,7 @@ public class NotesListViewActivity extends LockedActivity implements ItemAdapter
localAccount = db.getLocalAccountByAccountName(accountName);
if (localAccount != null) {
try {
+ BrandingUtil.saveBrandColors(this, localAccount.getColor(), localAccount.getTextColor());
ssoAccount = SingleAccountHelper.getCurrentSingleSignOnAccount(getApplicationContext());
new NotesListViewItemTouchHelper(ssoAccount, this, db, adapter, syncCallBack, this::refreshLists, swipeRefreshLayout, this).attachToRecyclerView(listView);
synchronize();
@@ -230,14 +235,21 @@ public class NotesListViewActivity extends LockedActivity implements ItemAdapter
}
refreshLists();
fabCreate.show();
- setupHeader();
+ activityBinding.launchAccountSwitcher.setOnClickListener((v) -> {
+ if (localAccount == null) {
+ handleNotAuthorizedAccount();
+ } else {
+ AccountSwitcherDialog.newInstance(localAccount.getId()).show(getSupportFragmentManager(), AccountSwitcherDialog.class.getSimpleName());
+ }
+ });
setupNavigationList(ADAPTER_KEY_RECENT);
- updateUsernameInDrawer();
} else {
if (!notAuthorizedAccountHandled) {
handleNotAuthorizedAccount();
}
+ binding.navigationList.setAdapter(null);
}
+ updateCurrentAccountAvatar();
}
private void handleNotAuthorizedAccount() {
@@ -247,55 +259,59 @@ public class NotesListViewActivity extends LockedActivity implements ItemAdapter
notAuthorizedAccountHandled = true;
}
- private void setupHeader() {
- binding.accountChooser.removeAllViews();
- for (LocalAccount localAccount : db.getAccounts()) {
- View v = View.inflate(this, R.layout.item_account, null);
- ((TextView) v.findViewById(R.id.accountItemLabel)).setText(localAccount.getAccountName());
- Glide
- .with(this)
- .load(localAccount.getUrl() + "/index.php/avatar/" + Uri.encode(localAccount.getUserName()) + "/64")
- .error(R.drawable.ic_account_circle_grey_24dp)
- .apply(RequestOptions.circleCropTransform())
- .into(((ImageView) v.findViewById(R.id.accountItemAvatar)));
- v.setOnClickListener(clickedView -> {
- clickHeader();
- binding.drawerLayout.closeDrawer(GravityCompat.START);
- selectAccount(localAccount.getAccountName());
- });
- v.findViewById(R.id.delete).setOnClickListener(clickedView -> {
- db.deleteAccount(localAccount);
- if (localAccount.getId() == this.localAccount.getId()) {
- List<LocalAccount> remainingAccounts = db.getAccounts();
- if (remainingAccounts.size() > 0) {
- this.localAccount = remainingAccounts.get(0);
- selectAccount(this.localAccount.getAccountName());
+ private void setupToolbars() {
+ setSupportActionBar(binding.activityNotesListView.toolbar);
+ updateCurrentAccountAvatar();
+ activityBinding.homeToolbar.setOnClickListener((v) -> {
+ if (activityBinding.toolbar.getVisibility() == GONE) {
+ updateToolbars(false);
+ }
+ });
+
+ activityBinding.launchAccountSwitcher.setOnClickListener((v) -> askForNewAccount(this));
+ activityBinding.menuButton.setOnClickListener((v) -> binding.drawerLayout.openDrawer(GravityCompat.START));
+
+ final LinearLayout searchEditFrame = activityBinding.searchView.findViewById(R.id
+ .search_edit_frame);
+
+ searchEditFrame.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
+ int oldVisibility = -1;
+
+ @Override
+ public void onGlobalLayout() {
+ int currentVisibility = searchEditFrame.getVisibility();
+
+ if (currentVisibility != oldVisibility) {
+ if (currentVisibility == VISIBLE) {
+ fabCreate.hide();
} else {
- selectAccount(null);
- askForNewAccount(this);
+ new Handler().postDelayed(() -> fabCreate.show(), 150);
}
+
+ oldVisibility = currentVisibility;
}
- setupHeader();
- clickHeader();
- binding.drawerLayout.closeDrawer(GravityCompat.START);
- });
- binding.accountChooser.addView(v);
- }
- View addButton = View.inflate(this, R.layout.item_account, null);
- ((TextView) addButton.findViewById(R.id.accountItemLabel)).setText(getString(R.string.add_account));
- ((AppCompatImageView) addButton.findViewById(R.id.accountItemAvatar)).setImageResource(R.drawable.ic_person_add_grey600_24dp);
- addButton.setOnClickListener((btn) -> askForNewAccount(this));
- addButton.findViewById(R.id.delete).setVisibility(View.GONE);
- binding.accountChooser.addView(addButton);
- binding.headerView.setOnClickListener(view -> clickHeader());
- }
+ }
- private void setupActionBar() {
- Toolbar toolbar = binding.activityNotesListView.toolbar;
- setSupportActionBar(toolbar);
- drawerToggle = new ActionBarDrawerToggle(this, binding.drawerLayout, toolbar, R.string.action_drawer_open, R.string.action_drawer_close);
- drawerToggle.setDrawerIndicatorEnabled(true);
- binding.drawerLayout.addDrawerListener(drawerToggle);
+ });
+ activityBinding.searchView.setOnCloseListener(() -> {
+ if (activityBinding.toolbar.getVisibility() == VISIBLE && TextUtils.isEmpty(activityBinding.searchView.getQuery())) {
+ updateToolbars(true);
+ return true;
+ }
+ return false;
+ });
+ activityBinding.searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
+ @Override
+ public boolean onQueryTextSubmit(String query) {
+ return false;
+ }
+
+ @Override
+ public boolean onQueryTextChange(String newText) {
+ refreshLists();
+ return true;
+ }
+ });
}
private void setupNotesList() {
@@ -330,6 +346,9 @@ public class NotesListViewActivity extends LockedActivity implements ItemAdapter
db.updateCapabilitiesETag(localAccount.getId(), capabilities.getETag());
db.updateBrand(localAccount.getId(), capabilities);
db.updateBrand(localAccount.getId(), capabilities);
+ localAccount.setColor(Color.parseColor(capabilities.getColor()));
+ localAccount.setTextColor(Color.parseColor(capabilities.getTextColor()));
+ BrandingUtil.saveBrandColors(this, localAccount.getColor(), localAccount.getTextColor());
db.updateApiVersion(localAccount.getId(), capabilities.getApiVersion());
Log.i(TAG, capabilities.toString());
} catch (Exception e) {
@@ -350,8 +369,8 @@ public class NotesListViewActivity extends LockedActivity implements ItemAdapter
fabCreate.setOnClickListener((View view) -> {
Intent createIntent = new Intent(getApplicationContext(), EditNoteActivity.class);
createIntent.putExtra(EditNoteActivity.PARAM_CATEGORY, navigationSelection);
- if (searchView != null && !searchView.isIconified() && searchView.getQuery().length() > 0) {
- createIntent.putExtra(EditNoteActivity.PARAM_CONTENT, searchView.getQuery().toString());
+ if (activityBinding.searchView.getQuery().length() > 0) {
+ createIntent.putExtra(EditNoteActivity.PARAM_CONTENT, activityBinding.searchView.getQuery().toString());
invalidateOptionsMenu();
}
startActivityForResult(createIntent, create_note_cmd);
@@ -361,7 +380,7 @@ public class NotesListViewActivity extends LockedActivity implements ItemAdapter
private void setupNavigationList(final String selectedItem) {
itemRecent = new NavigationItem(ADAPTER_KEY_RECENT, getString(R.string.label_all_notes), null, R.drawable.ic_access_time_grey600_24dp);
itemFavorites = new NavigationItem(ADAPTER_KEY_STARRED, getString(R.string.label_favorites), null, R.drawable.ic_star_yellow_24dp);
- adapterCategories = new NavigationAdapter(new NavigationAdapter.ClickListener() {
+ adapterCategories = new NavigationAdapter(this, new NavigationAdapter.ClickListener() {
@Override
public void onItemClick(NavigationItem item) {
selectItem(item, true);
@@ -414,21 +433,40 @@ public class NotesListViewActivity extends LockedActivity implements ItemAdapter
binding.navigationList.setAdapter(adapterCategories);
}
- private void clickHeader() {
- if (this.accountChooserActive) {
- binding.accountChooser.setVisibility(View.GONE);
- binding.accountNavigation.setVisibility(View.VISIBLE);
- } else {
- binding.accountChooser.setVisibility(View.VISIBLE);
- binding.accountNavigation.setVisibility(View.GONE);
+ @Override
+ public CoordinatorLayout getView() {
+ return this.coordinatorLayout;
+ }
+ @Override
+ public void applyBrand(int mainColor, int textColor) {
+ applyBrandToPrimaryToolbar(activityBinding.toolbar);
+ applyBrandToFAB(mainColor, textColor, activityBinding.fabCreate);
+
+ binding.headerView.setBackgroundColor(mainColor);
+ binding.appName.setTextColor(textColor);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ activityBinding.progressCircular.getIndeterminateDrawable().setColorFilter(getSecondaryForegroundColorDependingOnTheme(this, mainColor), PorterDuff.Mode.SRC_IN);
}
- this.accountChooserActive = !this.accountChooserActive;
+
+ // TODO We assume, that the background of the spinner is always white
+ activityBinding.swiperefreshlayout.setColorSchemeColors(contrastRatioIsSufficient(Color.WHITE, mainColor) ? mainColor : Color.BLACK);
+ binding.appName.setTextColor(textColor);
+ DrawableCompat.setTint(binding.logo.getDrawable(), textColor);
+
+ adapter.applyBrand(mainColor, textColor);
+ adapterCategories.applyBrand(mainColor, textColor);
+ invalidateOptionsMenu();
}
@Override
- public CoordinatorLayout getView() {
- return this.coordinatorLayout;
+ public boolean onSupportNavigateUp() {
+ if (activityBinding.toolbar.getVisibility() == VISIBLE) {
+ updateToolbars(true);
+ return true;
+ } else {
+ return super.onSupportNavigateUp();
+ }
}
private class LoadCategoryListTask extends AsyncTask<Void, Void, List<NavigationItem>> {
@@ -521,12 +559,12 @@ public class NotesListViewActivity extends LockedActivity implements ItemAdapter
final NavigationItem itemSettings = new NavigationItem("settings", getString(R.string.action_settings), null, R.drawable.ic_settings_grey600_24dp);
final NavigationItem itemAbout = new NavigationItem("about", getString(R.string.simple_about), null, R.drawable.ic_info_outline_grey600_24dp);
- ArrayList<NavigationItem> itemsMenu = new ArrayList<>();
+ ArrayList<NavigationItem> itemsMenu = new ArrayList<>(3);
itemsMenu.add(itemTrashbin);
itemsMenu.add(itemSettings);
itemsMenu.add(itemAbout);
- NavigationAdapter adapterMenu = new NavigationAdapter(new NavigationAdapter.ClickListener() {
+ NavigationAdapter adapterMenu = new NavigationAdapter(this, new NavigationAdapter.ClickListener() {
@Override
public void onItemClick(NavigationItem item) {
if (itemSettings.equals(item)) {
@@ -545,9 +583,6 @@ public class NotesListViewActivity extends LockedActivity implements ItemAdapter
onItemClick(item);
}
});
-
-
- this.updateUsernameInDrawer();
adapterMenu.setItems(itemsMenu);
binding.navigationMenu.setAdapter(adapterMenu);
}
@@ -569,35 +604,36 @@ public class NotesListViewActivity extends LockedActivity implements ItemAdapter
return;
}
View emptyContentView = binding.activityNotesListView.emptyContentView.getRoot();
- emptyContentView.setVisibility(View.GONE);
- binding.activityNotesListView.progressCircular.setVisibility(View.VISIBLE);
+ emptyContentView.setVisibility(GONE);
+ binding.activityNotesListView.progressCircular.setVisibility(VISIBLE);
fabCreate.show();
String subtitle;
if (navigationSelection.category != null) {
if (navigationSelection.category.isEmpty()) {
- subtitle = getString(R.string.action_uncategorized);
+ subtitle = getString(R.string.search_in_category, getString(R.string.action_uncategorized));
} else {
- subtitle = NoteUtil.extendCategory(navigationSelection.category);
+ subtitle = getString(R.string.search_in_category, NoteUtil.extendCategory(navigationSelection.category));
}
} else if (navigationSelection.favorite != null && navigationSelection.favorite) {
- subtitle = getString(R.string.label_favorites);
+ subtitle = getString(R.string.search_in_category, getString(R.string.label_favorites));
} else {
- subtitle = getString(R.string.app_name);
+ subtitle = getString(R.string.search_in_all);
}
- setTitle(subtitle);
+ activityBinding.searchText.setText(subtitle);
CharSequence query = null;
- if (searchView != null && !searchView.isIconified() && searchView.getQuery().length() != 0) {
- query = searchView.getQuery();
+ if (activityBinding.searchView.getQuery().length() != 0) {
+ query = activityBinding.searchView.getQuery();
}
- NotesLoadedListener callback = (List<Item> notes, boolean showCategory) -> {
+ NotesLoadedListener callback = (List<Item> notes, boolean showCategory, CharSequence searchQuery) -> {
adapter.setShowCategory(showCategory);
+ adapter.setHighlightSearchQuery(searchQuery);
adapter.setItemList(notes);
- binding.activityNotesListView.progressCircular.setVisibility(View.GONE);
+ binding.activityNotesListView.progressCircular.setVisibility(GONE);
if (notes.size() > 0) {
- emptyContentView.setVisibility(View.GONE);
+ emptyContentView.setVisibility(GONE);
} else {
- emptyContentView.setVisibility(View.VISIBLE);
+ emptyContentView.setVisibility(VISIBLE);
}
if (scrollToTop) {
listView.scrollToPosition(0);
@@ -607,62 +643,10 @@ public class NotesListViewActivity extends LockedActivity implements ItemAdapter
new LoadCategoryListTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
-
- /**
- * Adds the Menu Items to the Action Bar.
- *
- * @param menu Menu
- * @return boolean
- */
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.menu_list_view, menu);
- // Associate searchable configuration with the SearchView
- final MenuItem item = menu.findItem(R.id.search);
- searchView = (SearchView) item.getActionView();
-
- final LinearLayout searchEditFrame = searchView.findViewById(R.id
- .search_edit_frame);
-
- searchEditFrame.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
- int oldVisibility = -1;
-
- @Override
- public void onGlobalLayout() {
- int currentVisibility = searchEditFrame.getVisibility();
-
- if (currentVisibility != oldVisibility) {
- if (currentVisibility == View.VISIBLE) {
- fabCreate.hide();
- } else {
- new Handler().postDelayed(() -> fabCreate.show(), 150);
- }
-
- oldVisibility = currentVisibility;
- }
- }
-
- });
-
- searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
- @Override
- public boolean onQueryTextSubmit(String query) {
- return false;
- }
-
- @Override
- public boolean onQueryTextChange(String newText) {
- refreshLists();
- return true;
- }
- });
- return true;
- }
-
@Override
protected void onNewIntent(Intent intent) {
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
- searchView.setQuery(intent.getStringExtra(SearchManager.QUERY), true);
+ activityBinding.searchView.setQuery(intent.getStringExtra(SearchManager.QUERY), true);
}
super.onNewIntent(intent);
}
@@ -684,98 +668,99 @@ public class NotesListViewActivity extends LockedActivity implements ItemAdapter
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
- // Check which request we're responding to
- if (requestCode == create_note_cmd) {
- // Make sure the request was successful
- if (resultCode == RESULT_OK) {
- //not need because of db.synchronisation in createActivity
-
- Bundle bundle = data.getExtras();
- if (bundle != null && bundle.containsKey(CREATED_NOTE)) {
- DBNote createdNote = (DBNote) bundle.getSerializable(CREATED_NOTE);
- if (createdNote != null) {
- adapter.add(createdNote);
+ switch (requestCode) {
+ case create_note_cmd: {
+ // Make sure the request was successful
+ if (resultCode == RESULT_OK) {
+ //not need because of db.synchronisation in createActivity
+
+ Bundle bundle = data.getExtras();
+ if (bundle != null && bundle.containsKey(CREATED_NOTE)) {
+ DBNote createdNote = (DBNote) bundle.getSerializable(CREATED_NOTE);
+ if (createdNote != null) {
+ adapter.add(createdNote);
+ } else {
+ Log.w(TAG, "createdNote must not be null");
+ }
} else {
- Log.w(TAG, "createdNote must not be null");
+ Log.w(TAG, "Provide at least " + CREATED_NOTE);
}
- } else {
- Log.w(TAG, "Provide at least " + CREATED_NOTE);
}
+ listView.scrollToPosition(0);
+ break;
}
- listView.scrollToPosition(0);
- } else if (requestCode == server_settings) {
- // Recreate activity completely, because theme switching makes problems when only invalidating the views.
- // @see https://github.com/stefan-niedermann/nextcloud-notes/issues/529
- recreate();
- } else {
- try {
- AccountImporter.onActivityResult(requestCode, resultCode, data, this, (ssoAccount) -> {
- CapabilitiesWorker.update(this);
- new Thread(() -> {
- Log.i(TAG, "Added account: " + "name:" + ssoAccount.name + ", " + ssoAccount.url + ", userId" + ssoAccount.userId);
- try {
- Log.i(TAG, "Refreshing capabilities for " + ssoAccount.name);
- final Capabilities capabilities = CapabilitiesClient.getCapabilities(getApplicationContext(), ssoAccount, null);
- db.addAccount(ssoAccount.url, ssoAccount.userId, ssoAccount.name, capabilities);
- Log.i(TAG, capabilities.toString());
- runOnUiThread(() -> {
- selectAccount(ssoAccount.name);
- this.accountChooserActive = false;
- binding.accountChooser.setVisibility(View.GONE);
- binding.accountNavigation.setVisibility(View.VISIBLE);
- binding.drawerLayout.closeDrawer(GravityCompat.START);
- });
- } catch (SQLiteConstraintException e) {
- if (db.getAccounts().size() > 1) { // TODO ideally only show snackbar when this is a not migrated account
- runOnUiThread(() -> {
- Snackbar.make(coordinatorLayout, R.string.account_already_imported, Snackbar.LENGTH_LONG).show();
- selectAccount(ssoAccount.name);
- this.accountChooserActive = false;
- binding.accountChooser.setVisibility(View.GONE);
- binding.accountNavigation.setVisibility(View.VISIBLE);
- binding.drawerLayout.closeDrawer(GravityCompat.START);
- });
+ case server_settings: {
+ // Recreate activity completely, because theme switching makes problems when only invalidating the views.
+ // @see https://github.com/stefan-niedermann/nextcloud-notes/issues/529
+ recreate();
+ break;
+ }
+ case manage_account: {
+ if (resultCode == RESULT_FIRST_USER) {
+ selectAccount(null);
+ }
+ break;
+ }
+ default: {
+ try {
+ AccountImporter.onActivityResult(requestCode, resultCode, data, this, (ssoAccount) -> {
+ CapabilitiesWorker.update(this);
+ new Thread(() -> {
+ Log.i(TAG, "Added account: " + "name:" + ssoAccount.name + ", " + ssoAccount.url + ", userId" + ssoAccount.userId);
+ try {
+ Log.i(TAG, "Refreshing capabilities for " + ssoAccount.name);
+ final Capabilities capabilities = CapabilitiesClient.getCapabilities(getApplicationContext(), ssoAccount, null);
+ db.addAccount(ssoAccount.url, ssoAccount.userId, ssoAccount.name, capabilities);
+ Log.i(TAG, capabilities.toString());
+ runOnUiThread(() -> selectAccount(ssoAccount.name));
+ } catch (SQLiteException e) {
+ // Happens when upgrading from version ≤ 1.0.1 and importing the account
+ runOnUiThread(() -> selectAccount(ssoAccount.name));
+ } catch (Exception e) {
+ // Happens when importing an already existing account the second time
+ if (e instanceof TokenMismatchException && db.getLocalAccountByAccountName(ssoAccount.name) != null) {
+ Log.w(TAG, "Received " + TokenMismatchException.class.getSimpleName() + " and the given ssoAccount.name (" + ssoAccount.name + ") does already exist in the database. Assume that this account has already been imported.");
+ runOnUiThread(() -> {
+ selectAccount(ssoAccount.name);
+ // TODO there is already a sync in progress and results in displaying a TokenMissMatchException snackbar which conflicts with this one
+ coordinatorLayout.post(() -> BrandedSnackbar.make(coordinatorLayout, R.string.account_already_imported, Snackbar.LENGTH_LONG).show());
+ });
+ } else {
+ e.printStackTrace();
+ runOnUiThread(() -> {
+ binding.activityNotesListView.progressCircular.setVisibility(GONE);
+ ExceptionDialogFragment.newInstance(e).show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName());
+ });
+ }
}
- } catch (Exception e) {
- e.printStackTrace();
- runOnUiThread(() -> {
- this.accountChooserActive = true;
- binding.accountChooser.setVisibility(View.VISIBLE);
- binding.accountNavigation.setVisibility(View.GONE);
- binding.drawerLayout.openDrawer(GravityCompat.START);
- binding.activityNotesListView.progressCircular.setVisibility(View.GONE);
- ExceptionDialogFragment.newInstance(e).show(getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName());
- });
- }
- }).start();
- });
- } catch (AccountImportCancelledException e) {
- Log.i(TAG, "AccountImport has been cancelled.");
+ }).start();
+ });
+ } catch (AccountImportCancelledException e) {
+ Log.i(TAG, "AccountImport has been cancelled.");
+ }
}
}
}
- private void updateUsernameInDrawer() {
+ private void updateCurrentAccountAvatar() {
try {
String url = localAccount.getUrl();
if (url != null) {
- binding.account.setText(localAccount.getAccountName());
Glide
.with(this)
.load(url + "/index.php/avatar/" + Uri.encode(localAccount.getUserName()) + "/64")
- .error(R.mipmap.ic_launcher)
+ .error(R.drawable.ic_account_circle_grey_24dp)
.apply(RequestOptions.circleCropTransform())
- .into(binding.currentAccountImage);
+ .into(activityBinding.launchAccountSwitcher);
} else {
Log.w(TAG, "url is null");
}
} catch (NullPointerException e) { // No local account - show generic header
- binding.account.setText(R.string.app_name_long);
Glide
.with(this)
- .load(R.mipmap.ic_launcher)
+ .load(R.drawable.ic_account_circle_grey_24dp)
.apply(RequestOptions.circleCropTransform())
- .into(binding.currentAccountImage);
+ .into(activityBinding.launchAccountSwitcher);
Log.w(TAG, "Tried to update username in drawer, but localAccount was null");
}
}
@@ -820,7 +805,7 @@ public class NotesListViewActivity extends LockedActivity implements ItemAdapter
if (selected) {
v.setSelected(true);
mActionMode = startSupportActionMode(new MultiSelectedActionModeCallback(
- this, this, db, mActionMode, adapter, listView, this::refreshLists, getSupportFragmentManager(), searchView
+ this, this, db, mActionMode, adapter, listView, this::refreshLists, getSupportFragmentManager(), activityBinding.searchView
));
int checkedItemCount = adapter.getSelected().size();
mActionMode.setTitle(getResources().getQuantityString(R.plurals.ab_selected, checkedItemCount, checkedItemCount));
@@ -830,11 +815,27 @@ public class NotesListViewActivity extends LockedActivity implements ItemAdapter
@Override
public void onBackPressed() {
- if (searchView == null || searchView.isIconified()) {
+ if (activityBinding.toolbar.getVisibility() == VISIBLE) {
+ updateToolbars(true);
+ } else {
super.onBackPressed();
+ }
+ }
+
+ @SuppressLint("PrivateResource")
+ private void updateToolbars(boolean disableSearch) {
+ activityBinding.homeToolbar.setVisibility(disableSearch ? VISIBLE : GONE);
+ activityBinding.toolbar.setVisibility(disableSearch ? GONE : VISIBLE);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ activityBinding.appBar.setStateListAnimator(AnimatorInflater.loadStateListAnimator(activityBinding.appBar.getContext(),
+ disableSearch ? R.animator.appbar_elevation_off : R.animator.appbar_elevation_on));
} else {
- invalidateOptionsMenu();
+ ViewCompat.setElevation(activityBinding.appBar, disableSearch ? 0 : getResources().getDimension(R.dimen.design_appbar_elevation));
}
+ if (disableSearch) {
+ activityBinding.searchView.setQuery(null, true);
+ }
+ activityBinding.searchView.setIconified(disableSearch);
}
private void synchronize() {
@@ -849,14 +850,39 @@ public class NotesListViewActivity extends LockedActivity implements ItemAdapter
Log.d(TAG, "Network is connected, but sync is not possible");
} else {
Log.d(TAG, "Sync is not possible, because network is not connected");
- Snackbar.make(coordinatorLayout, getString(R.string.error_sync, getString(R.string.error_no_network)), Snackbar.LENGTH_LONG).show();
+ BrandedSnackbar.make(coordinatorLayout, getString(R.string.error_sync, getString(R.string.error_no_network)), Snackbar.LENGTH_LONG).show();
}
}
}
+ @Override
+ public void addAccount() {
+ askForNewAccount(this);
+ }
+
+ @Override
+ public void onAccountChosen(LocalAccount localAccount) {
+ binding.drawerLayout.closeDrawer(GravityCompat.START);
+ selectAccount(localAccount.getAccountName());
+ }
+
+ @Override
+ public void onAccountDeleted(LocalAccount localAccount) {
+ db.deleteAccount(localAccount);
+ if (localAccount.getId() == this.localAccount.getId()) {
+ List<LocalAccount> remainingAccounts = db.getAccounts();
+ if (remainingAccounts.size() > 0) {
+ this.localAccount = remainingAccounts.get(0);
+ selectAccount(this.localAccount.getAccountName());
+ } else {
+ selectAccount(null);
+ askForNewAccount(this);
+ }
+ }
+ }
@Override
- public void onAccountChosen(LocalAccount account) {
+ public void moveToAccount(LocalAccount account) {
List<Integer> selection = new ArrayList<>(adapter.getSelected());
adapter.deselect(0);
@@ -872,7 +898,6 @@ public class NotesListViewActivity extends LockedActivity implements ItemAdapter
}
mActionMode.finish();
- searchView.setIconified(true);
refreshLists();
}
}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/PreferencesActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/PreferencesActivity.java
index 3efc1ad5..ec1566b2 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/PreferencesActivity.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/PreferencesActivity.java
@@ -14,11 +14,13 @@ import it.niedermann.owncloud.notes.databinding.ActivityPreferencesBinding;
public class PreferencesActivity extends LockedActivity {
+ private ActivityPreferencesBinding binding;
+
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- ActivityPreferencesBinding binding = ActivityPreferencesBinding.inflate(getLayoutInflater());
+ binding = ActivityPreferencesBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
setSupportActionBar(binding.toolbar);
@@ -27,4 +29,9 @@ public class PreferencesActivity extends LockedActivity {
.replace(R.id.fragment_container_view, new PreferencesFragment())
.commit();
}
+
+ @Override
+ public void applyBrand(int mainColor, int textColor) {
+ applyBrandToPrimaryToolbar(binding.toolbar);
+ }
}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/AccountChooserAdapter.java b/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/AccountChooserAdapter.java
index cf20c7b6..135e1426 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/AccountChooserAdapter.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/AccountChooserAdapter.java
@@ -26,14 +26,14 @@ public class AccountChooserAdapter extends RecyclerView.Adapter<RecyclerView.Vie
@NonNull
private final List<LocalAccount> localAccounts;
@NonNull
- private final AccountChooserListener accountChooserListener;
+ private final MoveAccountListener moveAccountListener;
@NonNull
private final Context context;
- AccountChooserAdapter(@NonNull List<LocalAccount> localAccounts, @NonNull AccountChooserListener accountChooserListener, @NonNull Context context) {
+ AccountChooserAdapter(@NonNull List<LocalAccount> localAccounts, @NonNull MoveAccountListener moveAccountListener, @NonNull Context context) {
super();
this.localAccounts = localAccounts;
- this.accountChooserListener = accountChooserListener;
+ this.moveAccountListener = moveAccountListener;
this.context = context;
}
@@ -48,7 +48,7 @@ public class AccountChooserAdapter extends RecyclerView.Adapter<RecyclerView.Vie
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
LocalAccount localAccount = localAccounts.get(position);
AccountChooserViewHolder accountChooserViewHolder = (AccountChooserViewHolder) holder;
- accountChooserViewHolder.getAccountLayout().setOnClickListener((v) -> accountChooserListener.onAccountChosen(localAccount));
+ accountChooserViewHolder.getAccountLayout().setOnClickListener((v) -> moveAccountListener.moveToAccount(localAccount));
Glide
.with(context)
@@ -86,7 +86,7 @@ public class AccountChooserAdapter extends RecyclerView.Adapter<RecyclerView.Vie
}
}
- public interface AccountChooserListener {
- void onAccountChosen(LocalAccount account);
+ public interface MoveAccountListener {
+ void moveToAccount(LocalAccount account);
}
}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/BaseNoteFragment.java b/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/BaseNoteFragment.java
index 18d56ebb..a2fe34cf 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/BaseNoteFragment.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/BaseNoteFragment.java
@@ -6,6 +6,7 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager;
+import android.graphics.Color;
import android.graphics.drawable.Icon;
import android.os.Build;
import android.os.Bundle;
@@ -14,9 +15,11 @@ import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
+import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
+import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
@@ -30,19 +33,24 @@ import it.niedermann.owncloud.notes.android.activity.EditNoteActivity;
import it.niedermann.owncloud.notes.android.fragment.CategoryDialogFragment.CategoryDialogListener;
import it.niedermann.owncloud.notes.android.fragment.EditTitleDialogFragment.EditTitleListener;
import it.niedermann.owncloud.notes.model.ApiVersion;
+import it.niedermann.owncloud.notes.branding.BrandedFragment;
import it.niedermann.owncloud.notes.model.CloudNote;
import it.niedermann.owncloud.notes.model.DBNote;
import it.niedermann.owncloud.notes.model.DBStatus;
import it.niedermann.owncloud.notes.model.ISyncCallback;
import it.niedermann.owncloud.notes.model.LocalAccount;
import it.niedermann.owncloud.notes.persistence.NotesDatabase;
+import it.niedermann.owncloud.notes.util.ColorUtil;
import it.niedermann.owncloud.notes.util.NoteUtil;
import it.niedermann.owncloud.notes.util.ShareUtil;
import static androidx.core.content.pm.ShortcutManagerCompat.isRequestPinShortcutSupported;
import static it.niedermann.owncloud.notes.android.activity.EditNoteActivity.ACTION_SHORTCUT;
+import static it.niedermann.owncloud.notes.branding.BrandingUtil.tintMenuIcon;
+import static it.niedermann.owncloud.notes.util.ColorUtil.isColorDark;
+import static it.niedermann.owncloud.notes.util.Notes.isDarkThemeActive;
-public abstract class BaseNoteFragment extends Fragment implements CategoryDialogListener, EditTitleListener {
+public abstract class BaseNoteFragment extends BrandedFragment implements CategoryDialogListener, EditTitleListener {
private static final String TAG = BaseNoteFragment.class.getSimpleName();
@@ -146,12 +154,14 @@ public abstract class BaseNoteFragment extends Fragment implements CategoryDialo
}
@Override
- public void onCreateOptionsMenu(@NonNull Menu menu, MenuInflater inflater) {
+ public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
inflater.inflate(R.menu.menu_note_fragment, menu);
if (isRequestPinShortcutSupported(requireActivity()) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
menu.add(Menu.NONE, MENU_ID_PIN, 110, R.string.pin_to_homescreen);
}
+
+ super.onCreateOptionsMenu(menu, inflater);
}
@Override
@@ -167,6 +177,7 @@ public abstract class BaseNoteFragment extends Fragment implements CategoryDialo
private void prepareFavoriteOption(MenuItem item) {
item.setIcon(note.isFavorite() ? R.drawable.ic_star_white_24dp : R.drawable.ic_star_border_white_24dp);
item.setChecked(note.isFavorite());
+ tintMenuIcon(item, colorAccent);
}
/**
@@ -199,7 +210,7 @@ public abstract class BaseNoteFragment extends Fragment implements CategoryDialo
showEditTitleDialog();
return true;
case R.id.menu_move:
- AccountChooserDialogFragment.newInstance().show(requireActivity().getSupportFragmentManager(), BaseNoteFragment.class.getSimpleName());
+ MoveAccountDialogFragment.newInstance().show(requireActivity().getSupportFragmentManager(), BaseNoteFragment.class.getSimpleName());
return true;
case R.id.menu_share:
ShareUtil.openShareDialog(requireContext(), note.getTitle(), note.getContent());
@@ -340,6 +351,39 @@ public abstract class BaseNoteFragment extends Fragment implements CategoryDialo
listener.close();
}
+ @ColorInt
+ protected static int getTextHighlightBackgroundColor(@NonNull Context context, @ColorInt int mainColor, @ColorInt int colorPrimary, @ColorInt int colorAccent) {
+ if (isDarkThemeActive(context)) { // Dark background
+ if (isColorDark(mainColor)) { // Dark brand color
+ if (ColorUtil.contrastRatioIsSufficient(mainColor, colorPrimary)) { // But also dark text
+ return mainColor;
+ } else {
+ return ContextCompat.getColor(context, R.color.defaultTextHighlightBackground);
+ }
+ } else { // Light brand color
+ if (ColorUtil.contrastRatioIsSufficient(mainColor, colorAccent)) { // But also dark text
+ return Color.argb(77, Color.red(mainColor), Color.green(mainColor), Color.blue(mainColor));
+ } else {
+ return ContextCompat.getColor(context, R.color.defaultTextHighlightBackground);
+ }
+ }
+ } else { // Light background
+ if (isColorDark(mainColor)) { // Dark brand color
+ if (ColorUtil.contrastRatioIsSufficient(mainColor, colorAccent)) { // But also dark text
+ return Color.argb(77, Color.red(mainColor), Color.green(mainColor), Color.blue(mainColor));
+ } else {
+ return ContextCompat.getColor(context, R.color.defaultTextHighlightBackground);
+ }
+ } else { // Light brand color
+ if (ColorUtil.contrastRatioIsSufficient(mainColor, colorPrimary)) { // But also dark text
+ return mainColor;
+ } else {
+ return ContextCompat.getColor(context, R.color.defaultTextHighlightBackground);
+ }
+ }
+ }
+ }
+
public interface NoteFragmentListener {
void close();
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/CategoryDialogFragment.java b/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/CategoryDialogFragment.java
index a05ad4b7..cd194cc0 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/CategoryDialogFragment.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/CategoryDialogFragment.java
@@ -1,6 +1,5 @@
package it.niedermann.owncloud.notes.android.fragment;
-import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.Context;
@@ -14,12 +13,14 @@ import android.view.WindowManager;
import android.widget.EditText;
import androidx.annotation.NonNull;
-import androidx.appcompat.app.AppCompatDialogFragment;
import androidx.fragment.app.Fragment;
import java.util.List;
import it.niedermann.owncloud.notes.R;
+import it.niedermann.owncloud.notes.branding.BrandedAlertDialogBuilder;
+import it.niedermann.owncloud.notes.branding.BrandedDialogFragment;
+import it.niedermann.owncloud.notes.branding.BrandingUtil;
import it.niedermann.owncloud.notes.databinding.DialogChangeCategoryBinding;
import it.niedermann.owncloud.notes.model.NavigationAdapter;
import it.niedermann.owncloud.notes.persistence.NotesDatabase;
@@ -29,16 +30,22 @@ import it.niedermann.owncloud.notes.persistence.NotesDatabase;
* It targetFragment is set it must implement the interface {@link CategoryDialogListener}.
* The calling Activity must implement the interface {@link CategoryDialogListener}.
*/
-public class CategoryDialogFragment extends AppCompatDialogFragment {
+public class CategoryDialogFragment extends BrandedDialogFragment {
private static final String TAG = CategoryDialogFragment.class.getSimpleName();
private static final String STATE_CATEGORY = "category";
+ private DialogChangeCategoryBinding binding;
private NotesDatabase db;
private CategoryDialogListener listener;
private EditText editCategory;
+ @Override
+ public void applyBrand(int mainColor, int textColor) {
+ BrandingUtil.applyBrandToEditText(mainColor, textColor, binding.search);
+ }
+
/**
* Interface that must be implemented by the calling Activity.
*/
@@ -81,7 +88,7 @@ public class CategoryDialogFragment extends AppCompatDialogFragment {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
View dialogView = View.inflate(getContext(), R.layout.dialog_change_category, null);
- DialogChangeCategoryBinding binding = DialogChangeCategoryBinding.bind(dialogView);
+ binding = DialogChangeCategoryBinding.bind(dialogView);
this.editCategory = binding.search;
if (savedInstanceState == null) {
@@ -131,7 +138,7 @@ public class CategoryDialogFragment extends AppCompatDialogFragment {
}
});
- return new AlertDialog.Builder(getActivity())
+ return new BrandedAlertDialogBuilder(getActivity())
.setTitle(R.string.change_category_title)
.setView(dialogView)
.setCancelable(true)
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/AccountChooserDialogFragment.java b/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/MoveAccountDialogFragment.java
index 880eafb6..ec0d2ff5 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/AccountChooserDialogFragment.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/MoveAccountDialogFragment.java
@@ -10,7 +10,6 @@ import android.view.WindowManager;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatDialogFragment;
import androidx.recyclerview.widget.RecyclerView;
@@ -18,27 +17,28 @@ import java.util.List;
import java.util.Objects;
import it.niedermann.owncloud.notes.R;
-import it.niedermann.owncloud.notes.android.fragment.AccountChooserAdapter.AccountChooserListener;
+import it.niedermann.owncloud.notes.android.fragment.AccountChooserAdapter.MoveAccountListener;
+import it.niedermann.owncloud.notes.branding.BrandedAlertDialogBuilder;
import it.niedermann.owncloud.notes.databinding.DialogChooseAccountBinding;
import it.niedermann.owncloud.notes.model.LocalAccount;
import it.niedermann.owncloud.notes.persistence.NotesDatabase;
-public class AccountChooserDialogFragment extends AppCompatDialogFragment implements AccountChooserListener {
- private AccountChooserListener accountChooserListener;
+public class MoveAccountDialogFragment extends AppCompatDialogFragment implements MoveAccountListener {
+ private MoveAccountListener moveAccountListener;
/**
* Use newInstance()-Method
*/
- public AccountChooserDialogFragment() {
+ public MoveAccountDialogFragment() {
}
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
- if (context instanceof AccountChooserListener) {
- this.accountChooserListener = (AccountChooserListener) context;
+ if (context instanceof MoveAccountListener) {
+ this.moveAccountListener = (MoveAccountListener) context;
} else {
- throw new ClassCastException("Caller must implement " + AccountChooserListener.class.getSimpleName());
+ throw new ClassCastException("Caller must implement " + MoveAccountListener.class.getSimpleName());
}
}
@@ -54,7 +54,7 @@ public class AccountChooserDialogFragment extends AppCompatDialogFragment implem
RecyclerView.Adapter adapter = new AccountChooserAdapter(accountsList, this, requireActivity());
binding.accountsList.setAdapter(adapter);
- return new AlertDialog.Builder(requireActivity())
+ return new BrandedAlertDialogBuilder(requireActivity())
.setView(binding.getRoot())
.setTitle(R.string.simple_move)
.setNegativeButton(android.R.string.cancel, null)
@@ -68,13 +68,13 @@ public class AccountChooserDialogFragment extends AppCompatDialogFragment implem
return super.onCreateView(inflater, container, savedInstanceState);
}
- public static AccountChooserDialogFragment newInstance() {
- return new AccountChooserDialogFragment();
+ public static MoveAccountDialogFragment newInstance() {
+ return new MoveAccountDialogFragment();
}
@Override
- public void onAccountChosen(LocalAccount account) {
- accountChooserListener.onAccountChosen(account);
+ public void moveToAccount(LocalAccount account) {
+ moveAccountListener.moveToAccount(account);
dismiss();
}
}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/NoteEditFragment.java b/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/NoteEditFragment.java
index 9caa38a8..b1125092 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/NoteEditFragment.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/NoteEditFragment.java
@@ -243,10 +243,16 @@ public class NoteEditFragment extends SearchableBaseNoteFragment {
}
@Override
- protected void colorWithText(@NonNull String newText, @Nullable Integer current) {
+ protected void colorWithText(@NonNull String newText, @Nullable Integer current, int mainColor, int textColor) {
if (binding != null && isAttachedToWindow(binding.editContent)) {
binding.editContent.clearFocus();
- binding.editContent.setText(searchAndColor(new SpannableString(getContent()), newText, requireContext(), current), TextView.BufferType.SPANNABLE);
+ binding.editContent.setText(searchAndColor(new SpannableString(getContent()), newText, requireContext(), current, mainColor, textColor), TextView.BufferType.SPANNABLE);
}
}
+
+ @Override
+ public void applyBrand(int mainColor, int textColor) {
+ super.applyBrand(mainColor, textColor);
+ binding.editContent.setHighlightColor(getTextHighlightBackgroundColor(requireContext(), mainColor, colorPrimary, colorAccent));
+ }
}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/NotePreviewFragment.java b/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/NotePreviewFragment.java
index 85fd5d7a..8aa258b8 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/NotePreviewFragment.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/NotePreviewFragment.java
@@ -182,10 +182,10 @@ public class NotePreviewFragment extends SearchableBaseNoteFragment implements O
}
@Override
- protected void colorWithText(@NonNull String newText, @Nullable Integer current) {
+ protected void colorWithText(@NonNull String newText, @Nullable Integer current, int mainColor, int textColor) {
if (binding != null && ViewCompat.isAttachedToWindow(binding.singleNoteContent)) {
binding.singleNoteContent.setText(
- searchAndColor(new SpannableString(parseCompat(markdownProcessor, getContent())), newText, requireContext(), current),
+ searchAndColor(new SpannableString(parseCompat(markdownProcessor, getContent())), newText, requireContext(), current, mainColor, textColor),
TextView.BufferType.SPANNABLE);
}
}
@@ -216,4 +216,10 @@ public class NotePreviewFragment extends SearchableBaseNoteFragment implements O
Toast.makeText(requireContext(), getString(R.string.error_sync, getString(R.string.error_no_network)), Toast.LENGTH_LONG).show();
}
}
+
+ @Override
+ public void applyBrand(int mainColor, int textColor) {
+ super.applyBrand(mainColor, textColor);
+ binding.singleNoteContent.setHighlightColor(getTextHighlightBackgroundColor(requireContext(), mainColor, colorPrimary, colorAccent));
+ }
}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/NoteReadonlyFragment.java b/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/NoteReadonlyFragment.java
index c0c8e2fb..fe8b5273 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/NoteReadonlyFragment.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/NoteReadonlyFragment.java
@@ -147,9 +147,9 @@ public class NoteReadonlyFragment extends SearchableBaseNoteFragment {
}
@Override
- protected void colorWithText(@NonNull String newText, @Nullable Integer current) {
+ protected void colorWithText(@NonNull String newText, @Nullable Integer current, int mainColor, int textColor) {
if ((binding != null) && isAttachedToWindow(binding.singleNoteContent)) {
- binding.singleNoteContent.setText(searchAndColor(new SpannableString(parseCompat(markdownProcessor, getContent())), newText, requireContext(), current), TextView.BufferType.SPANNABLE);
+ binding.singleNoteContent.setText(searchAndColor(new SpannableString(parseCompat(markdownProcessor, getContent())), newText, requireContext(), current, mainColor, textColor), TextView.BufferType.SPANNABLE);
}
}
@@ -157,4 +157,10 @@ public class NoteReadonlyFragment extends SearchableBaseNoteFragment {
protected String getContent() {
return note.getContent();
}
+
+ @Override
+ public void applyBrand(int mainColor, int textColor) {
+ super.applyBrand(mainColor, textColor);
+ binding.singleNoteContent.setHighlightColor(getTextHighlightBackgroundColor(requireContext(), mainColor, colorPrimary, colorAccent));
+ }
}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/PreferencesFragment.java b/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/PreferencesFragment.java
index 27ce4fc7..ccc046cf 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/PreferencesFragment.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/PreferencesFragment.java
@@ -1,24 +1,34 @@
package it.niedermann.owncloud.notes.android.fragment;
import android.app.Activity;
+import android.content.Context;
import android.os.Bundle;
import android.util.Log;
+import androidx.annotation.ColorInt;
import androidx.annotation.Nullable;
import androidx.preference.ListPreference;
+import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
-import androidx.preference.SwitchPreference;
import it.niedermann.owncloud.notes.R;
import it.niedermann.owncloud.notes.android.DarkModeSetting;
+import it.niedermann.owncloud.notes.branding.Branded;
+import it.niedermann.owncloud.notes.branding.BrandedSwitchPreference;
+import it.niedermann.owncloud.notes.branding.BrandingUtil;
import it.niedermann.owncloud.notes.persistence.SyncWorker;
import it.niedermann.owncloud.notes.util.DeviceCredentialUtil;
import it.niedermann.owncloud.notes.util.Notes;
-public class PreferencesFragment extends PreferenceFragmentCompat {
+public class PreferencesFragment extends PreferenceFragmentCompat implements Branded {
private static final String TAG = PreferencesFragment.class.getSimpleName();
+ private BrandedSwitchPreference fontPref;
+ private BrandedSwitchPreference lockPref;
+ private BrandedSwitchPreference wifiOnlyPref;
+ private BrandedSwitchPreference brandingPref;
+
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -28,10 +38,26 @@ public class PreferencesFragment extends PreferenceFragmentCompat {
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.preferences);
- final SwitchPreference lockPref = findPreference(getString(R.string.pref_key_lock));
+ fontPref = findPreference(getString(R.string.pref_key_font));
+
+ brandingPref = findPreference(getString(R.string.pref_key_branding));
+ if (brandingPref != null) {
+ brandingPref.setOnPreferenceChangeListener((Preference preference, Object newValue) -> {
+ final Boolean branding = (Boolean) newValue;
+ Log.v(TAG, "branding: " + branding);
+ requireActivity().setResult(Activity.RESULT_OK);
+ requireActivity().recreate();
+ return true;
+ });
+ } else {
+ Log.e(TAG, "Could not find preference with key: \"" + getString(R.string.pref_key_branding) + "\"");
+ }
+
+ lockPref = findPreference(getString(R.string.pref_key_lock));
if (lockPref != null) {
if (!DeviceCredentialUtil.areCredentialsAvailable(requireContext())) {
lockPref.setVisible(false);
+ findPreference(getString(R.string.pref_category_security)).setVisible(false);
} else {
lockPref.setOnPreferenceChangeListener((preference, newValue) -> {
Notes.setLockedPreference((Boolean) newValue);
@@ -51,7 +77,7 @@ public class PreferencesFragment extends PreferenceFragmentCompat {
return true;
});
- final SwitchPreference wifiOnlyPref = findPreference(getString(R.string.pref_key_wifi_only));
+ wifiOnlyPref = findPreference(getString(R.string.pref_key_wifi_only));
assert wifiOnlyPref != null;
wifiOnlyPref.setOnPreferenceChangeListener((preference, newValue) -> {
Log.i(TAG, "syncOnWifiOnly: " + newValue);
@@ -66,4 +92,24 @@ public class PreferencesFragment extends PreferenceFragmentCompat {
return true;
});
}
+
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ @Nullable Context context = getContext();
+ if (context != null) {
+ @ColorInt final int mainColor = BrandingUtil.readBrandMainColor(context);
+ @ColorInt final int textColor = BrandingUtil.readBrandTextColor(context);
+ applyBrand(mainColor, textColor);
+ }
+ }
+
+ @Override
+ public void applyBrand(int mainColor, int textColor) {
+ fontPref.applyBrand(mainColor, textColor);
+ lockPref.applyBrand(mainColor, textColor);
+ wifiOnlyPref.applyBrand(mainColor, textColor);
+ brandingPref.applyBrand(mainColor, textColor);
+ }
}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/SearchableBaseNoteFragment.java b/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/SearchableBaseNoteFragment.java
index 10080457..f0949432 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/SearchableBaseNoteFragment.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/SearchableBaseNoteFragment.java
@@ -1,5 +1,6 @@
package it.niedermann.owncloud.notes.android.fragment;
+import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.text.Layout;
@@ -12,6 +13,8 @@ import android.view.ViewTreeObserver;
import android.widget.LinearLayout;
import android.widget.ScrollView;
+import androidx.annotation.CallSuper;
+import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.SearchView;
@@ -22,6 +25,7 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import it.niedermann.owncloud.notes.R;
+import it.niedermann.owncloud.notes.branding.BrandedActivity;
public abstract class SearchableBaseNoteFragment extends BaseNoteFragment {
@@ -35,6 +39,18 @@ public abstract class SearchableBaseNoteFragment extends BaseNoteFragment {
private String searchQuery = null;
private static final int delay = 50; // If the search string does not change after $delay ms, then the search task starts.
+ @ColorInt
+ private int mainColor;
+ @ColorInt
+ private int textColor;
+
+ @Override
+ public void onStart() {
+ this.mainColor = getResources().getColor(R.color.defaultBrand);
+ this.textColor = Color.WHITE;
+ super.onStart();
+ }
+
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
@@ -73,12 +89,12 @@ public abstract class SearchableBaseNoteFragment extends BaseNoteFragment {
if (currentVisibility != oldVisibility) {
if (currentVisibility != View.VISIBLE) {
- colorWithText("", null);
+ colorWithText("", null, mainColor, textColor);
searchQuery = "";
hideSearchFabs();
} else {
jumpToOccurrence();
- colorWithText(searchQuery, null);
+ colorWithText(searchQuery, null, mainColor, textColor);
occurrenceCount = countOccurrences(getContent(), searchQuery);
showSearchFabs();
}
@@ -96,7 +112,7 @@ public abstract class SearchableBaseNoteFragment extends BaseNoteFragment {
next.setOnClickListener(v -> {
currentOccurrence++;
jumpToOccurrence();
- colorWithText(searchView.getQuery().toString(), currentOccurrence);
+ colorWithText(searchView.getQuery().toString(), currentOccurrence, mainColor, textColor);
});
}
@@ -105,7 +121,7 @@ public abstract class SearchableBaseNoteFragment extends BaseNoteFragment {
occurrenceCount = countOccurrences(getContent(), searchView.getQuery().toString());
currentOccurrence--;
jumpToOccurrence();
- colorWithText(searchView.getQuery().toString(), currentOccurrence);
+ colorWithText(searchView.getQuery().toString(), currentOccurrence, mainColor, textColor);
});
}
@@ -117,7 +133,7 @@ public abstract class SearchableBaseNoteFragment extends BaseNoteFragment {
public boolean onQueryTextSubmit(@NonNull String query) {
currentOccurrence++;
jumpToOccurrence();
- colorWithText(query, currentOccurrence);
+ colorWithText(query, currentOccurrence, mainColor, textColor);
return true;
}
@@ -137,7 +153,7 @@ public abstract class SearchableBaseNoteFragment extends BaseNoteFragment {
}
currentOccurrence = 1;
jumpToOccurrence();
- colorWithText(searchQuery, currentOccurrence);
+ colorWithText(searchQuery, currentOccurrence, mainColor, textColor);
}
private void queryWithHandler(@NonNull String newText) {
@@ -183,7 +199,7 @@ public abstract class SearchableBaseNoteFragment extends BaseNoteFragment {
}
}
- protected abstract void colorWithText(@NonNull String newText, @Nullable Integer current);
+ protected abstract void colorWithText(@NonNull String newText, @Nullable Integer current, int mainColor, int textColor);
protected abstract ScrollView getScrollView();
@@ -273,4 +289,13 @@ public abstract class SearchableBaseNoteFragment extends BaseNoteFragment {
}
return count;
}
+
+ @CallSuper
+ @Override
+ public void applyBrand(int mainColor, int textColor) {
+ this.mainColor = mainColor;
+ this.textColor = textColor;
+ BrandedActivity.applyBrandToFAB(mainColor, textColor, getSearchPrevButton());
+ BrandedActivity.applyBrandToFAB(mainColor, textColor, getSearchNextButton());
+ }
}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/about/AboutFragmentLicenseTab.java b/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/about/AboutFragmentLicenseTab.java
index 4ce5d5dc..b5b984cd 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/about/AboutFragmentLicenseTab.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/android/fragment/about/AboutFragmentLicenseTab.java
@@ -1,20 +1,27 @@
package it.niedermann.owncloud.notes.android.fragment.about;
import android.content.Intent;
+import android.content.res.ColorStateList;
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.fragment.app.Fragment;
+import androidx.core.graphics.drawable.DrawableCompat;
import it.niedermann.owncloud.notes.R;
+import it.niedermann.owncloud.notes.branding.BrandedFragment;
+import it.niedermann.owncloud.notes.branding.BrandingUtil;
import it.niedermann.owncloud.notes.databinding.FragmentAboutLicenseTabBinding;
+import it.niedermann.owncloud.notes.util.ColorUtil;
import it.niedermann.owncloud.notes.util.SupportUtil;
-public class AboutFragmentLicenseTab extends Fragment {
+public class AboutFragmentLicenseTab extends BrandedFragment {
+
+ private FragmentAboutLicenseTabBinding binding;
private void openLicense() {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.url_license))));
@@ -22,9 +29,16 @@ public class AboutFragmentLicenseTab extends Fragment {
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- FragmentAboutLicenseTabBinding binding = FragmentAboutLicenseTabBinding.inflate(inflater, container, false);
+ binding = FragmentAboutLicenseTabBinding.inflate(inflater, container, false);
binding.aboutAppLicenseButton.setOnClickListener((v) -> openLicense());
SupportUtil.setHtml(binding.aboutIconsDisclaimer, R.string.about_icons_disclaimer, getString(R.string.about_app_icon_author));
return binding.getRoot();
}
+
+ @Override
+ public void applyBrand(int mainColor, int textColor) {
+ @ColorInt final int finalMainColor = BrandingUtil.getSecondaryForegroundColorDependingOnTheme(requireContext(), mainColor);
+ 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/owncloud/notes/branding/Branded.java b/app/src/main/java/it/niedermann/owncloud/notes/branding/Branded.java
new file mode 100644
index 00000000..7ef9138d
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/branding/Branded.java
@@ -0,0 +1,9 @@
+package it.niedermann.owncloud.notes.branding;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.UiThread;
+
+public interface Branded {
+ @UiThread
+ void applyBrand(@ColorInt int mainColor, @ColorInt int textColor);
+} \ No newline at end of file
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedActivity.java
new file mode 100644
index 00000000..0eea5bff
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedActivity.java
@@ -0,0 +1,67 @@
+package it.niedermann.owncloud.notes.branding;
+
+import android.content.res.ColorStateList;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
+import android.util.TypedValue;
+import android.view.Menu;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
+
+import com.google.android.material.floatingactionbutton.FloatingActionButton;
+
+import it.niedermann.owncloud.notes.R;
+
+import static it.niedermann.owncloud.notes.branding.BrandingUtil.tintMenuIcon;
+
+public abstract class BrandedActivity extends AppCompatActivity implements Branded {
+
+ @ColorInt
+ protected int colorAccent;
+
+ public static void applyBrandToFAB(@ColorInt int mainColor, @ColorInt int textColor, @NonNull FloatingActionButton fab) {
+ fab.setSupportBackgroundTintList(ColorStateList.valueOf(mainColor));
+ fab.setColorFilter(textColor);
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+
+ final TypedValue typedValue = new TypedValue();
+ getTheme().resolveAttribute(R.attr.colorAccent, typedValue, true);
+ colorAccent = typedValue.data;
+
+ if (BrandingUtil.isBrandingEnabled(this)) {
+ @ColorInt final int mainColor = BrandingUtil.readBrandMainColor(this);
+ @ColorInt final int textColor = BrandingUtil.readBrandTextColor(this);
+ applyBrand(mainColor, textColor);
+ }
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ for (int i = 0; i < menu.size(); i++) {
+ tintMenuIcon(menu.getItem(i), colorAccent);
+ }
+ return super.onCreateOptionsMenu(menu);
+ }
+
+ public void applyBrandToPrimaryToolbar(@NonNull Toolbar toolbar) {
+ final Drawable overflowDrawable = toolbar.getOverflowIcon();
+ if (overflowDrawable != null) {
+ overflowDrawable.setColorFilter(colorAccent, PorterDuff.Mode.SRC_ATOP);
+ toolbar.setOverflowIcon(overflowDrawable);
+ }
+
+ final Drawable navigationDrawable = toolbar.getNavigationIcon();
+ if (navigationDrawable != null) {
+ navigationDrawable.setColorFilter(colorAccent, PorterDuff.Mode.SRC_ATOP);
+ toolbar.setNavigationIcon(navigationDrawable);
+ }
+ }
+
+}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedAlertDialogBuilder.java b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedAlertDialogBuilder.java
new file mode 100644
index 00000000..940d978d
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedAlertDialogBuilder.java
@@ -0,0 +1,48 @@
+package it.niedermann.owncloud.notes.branding;
+
+import android.content.Context;
+import android.content.DialogInterface;
+import android.widget.Button;
+
+import androidx.annotation.CallSuper;
+import androidx.annotation.ColorInt;
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
+
+import static it.niedermann.owncloud.notes.branding.BrandingUtil.getSecondaryForegroundColorDependingOnTheme;
+
+public class BrandedAlertDialogBuilder extends AlertDialog.Builder implements Branded {
+
+ protected AlertDialog dialog;
+
+ public BrandedAlertDialogBuilder(Context context) {
+ super(context);
+ }
+
+ @NonNull
+ @Override
+ public AlertDialog create() {
+ this.dialog = super.create();
+
+ @NonNull Context context = getContext();
+ @ColorInt final int mainColor = BrandingUtil.readBrandMainColor(context);
+ @ColorInt final int textColor = BrandingUtil.readBrandTextColor(context);
+ applyBrand(mainColor, textColor);
+ dialog.setOnShowListener(dialog -> applyBrand(mainColor, textColor));
+ return dialog;
+ }
+
+ @CallSuper
+ @Override
+ public void applyBrand(int mainColor, int textColor) {
+ 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(getSecondaryForegroundColorDependingOnTheme(button.getContext(), mainColor));
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedDeleteAlertDialogBuilder.java b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedDeleteAlertDialogBuilder.java
new file mode 100644
index 00000000..113acf49
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedDeleteAlertDialogBuilder.java
@@ -0,0 +1,26 @@
+package it.niedermann.owncloud.notes.branding;
+
+import android.content.Context;
+import android.content.DialogInterface;
+import android.widget.Button;
+
+import androidx.annotation.CallSuper;
+
+import it.niedermann.owncloud.notes.R;
+
+public class BrandedDeleteAlertDialogBuilder extends BrandedAlertDialogBuilder {
+
+ public BrandedDeleteAlertDialogBuilder(Context context) {
+ super(context);
+ }
+
+ @CallSuper
+ @Override
+ public void applyBrand(int mainColor, int textColor) {
+ super.applyBrand(mainColor, textColor);
+ final Button positiveButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
+ if (positiveButton != null) {
+ positiveButton.setTextColor(getContext().getResources().getColor(R.color.bg_attention));
+ }
+ }
+}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedDialogFragment.java b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedDialogFragment.java
new file mode 100644
index 00000000..63eb2a69
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedDialogFragment.java
@@ -0,0 +1,24 @@
+package it.niedermann.owncloud.notes.branding;
+
+import android.content.Context;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.DialogFragment;
+
+public abstract class BrandedDialogFragment extends DialogFragment implements Branded {
+
+ @Override
+ public void onStart() {
+ super.onStart();
+
+ @Nullable Context context = getContext();
+ if (context != null) {
+ if (BrandingUtil.isBrandingEnabled(context)) {
+ @ColorInt final int mainColor = BrandingUtil.readBrandMainColor(context);
+ @ColorInt final int textColor = BrandingUtil.readBrandTextColor(context);
+ applyBrand(mainColor, textColor);
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedFragment.java b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedFragment.java
new file mode 100644
index 00000000..5752bff8
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedFragment.java
@@ -0,0 +1,49 @@
+package it.niedermann.owncloud.notes.branding;
+
+import android.content.Context;
+import android.util.TypedValue;
+import android.view.Menu;
+import android.view.MenuInflater;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+
+import it.niedermann.owncloud.notes.R;
+
+import static it.niedermann.owncloud.notes.branding.BrandingUtil.tintMenuIcon;
+
+public abstract class BrandedFragment extends Fragment implements Branded {
+
+ @ColorInt
+ protected int colorAccent;
+ @ColorInt
+ protected int colorPrimary;
+
+ @Override
+ public void onStart() {
+ super.onStart();
+
+ final TypedValue typedValue = new TypedValue();
+ requireActivity().getTheme().resolveAttribute(R.attr.colorAccent, typedValue, true);
+ colorAccent = typedValue.data;
+ requireActivity().getTheme().resolveAttribute(R.attr.colorPrimary, typedValue, true);
+ colorPrimary = typedValue.data;
+
+ @Nullable Context context = getContext();
+ if (context != null && BrandingUtil.isBrandingEnabled(context)) {
+ @ColorInt final int mainColor = BrandingUtil.readBrandMainColor(context);
+ @ColorInt final int textColor = BrandingUtil.readBrandTextColor(context);
+ applyBrand(mainColor, textColor);
+ }
+ }
+
+ @Override
+ public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
+ super.onCreateOptionsMenu(menu, inflater);
+ for (int i = 0; i < menu.size(); i++) {
+ tintMenuIcon(menu.getItem(i), colorAccent);
+ }
+ }
+}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedPreferenceCategory.java b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedPreferenceCategory.java
new file mode 100644
index 00000000..d2bcd274
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedPreferenceCategory.java
@@ -0,0 +1,46 @@
+package it.niedermann.owncloud.notes.branding;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.TextView;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.Nullable;
+import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceViewHolder;
+
+import static it.niedermann.owncloud.notes.branding.BrandingUtil.getSecondaryForegroundColorDependingOnTheme;
+
+public class BrandedPreferenceCategory extends PreferenceCategory {
+
+ public BrandedPreferenceCategory(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ }
+
+ public BrandedPreferenceCategory(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ public BrandedPreferenceCategory(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public BrandedPreferenceCategory(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder holder) {
+ super.onBindViewHolder(holder);
+
+ if (BrandingUtil.isBrandingEnabled(getContext())) {
+ final View v = holder.itemView.findViewById(android.R.id.title);
+ @Nullable final Context context = getContext();
+ if (context != null && v instanceof TextView) {
+ @ColorInt final int mainColor = getSecondaryForegroundColorDependingOnTheme(context, BrandingUtil.readBrandMainColor(context));
+ ((TextView) v).setTextColor(mainColor);
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedSnackbar.java b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedSnackbar.java
new file mode 100644
index 00000000..42b9c5cb
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedSnackbar.java
@@ -0,0 +1,31 @@
+package it.niedermann.owncloud.notes.branding;
+
+import android.graphics.Color;
+import android.view.View;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.StringRes;
+
+import com.google.android.material.snackbar.BaseTransientBottomBar;
+import com.google.android.material.snackbar.Snackbar;
+
+import it.niedermann.owncloud.notes.util.ColorUtil;
+
+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 (BrandingUtil.isBrandingEnabled(view.getContext())) {
+ int color = BrandingUtil.readBrandMainColor(view.getContext());
+ snackbar.setActionTextColor(ColorUtil.isColorDark(color) ? Color.WHITE : color);
+ }
+ return snackbar;
+ }
+
+ @NonNull
+ public static Snackbar make(@NonNull View view, @StringRes int resId, @BaseTransientBottomBar.Duration int duration) {
+ return make(view, view.getResources().getText(resId), duration);
+ }
+
+} \ No newline at end of file
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedSwitchPreference.java b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedSwitchPreference.java
new file mode 100644
index 00000000..541d2f4a
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandedSwitchPreference.java
@@ -0,0 +1,116 @@
+package it.niedermann.owncloud.notes.branding;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.graphics.Color;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Switch;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.Nullable;
+import androidx.core.graphics.drawable.DrawableCompat;
+import androidx.preference.PreferenceViewHolder;
+import androidx.preference.SwitchPreference;
+
+import it.niedermann.owncloud.notes.R;
+
+import static android.os.Build.VERSION.SDK_INT;
+import static android.os.Build.VERSION_CODES.JELLY_BEAN;
+import static it.niedermann.owncloud.notes.branding.BrandingUtil.getSecondaryForegroundColorDependingOnTheme;
+
+public class BrandedSwitchPreference extends SwitchPreference implements Branded {
+
+ @ColorInt
+ private Integer mainColor = null;
+
+ @ColorInt
+ private Integer textColor = null;
+
+ @Nullable
+ private Switch switchView;
+
+ public BrandedSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ }
+
+ public BrandedSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ public BrandedSwitchPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public BrandedSwitchPreference(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder holder) {
+ super.onBindViewHolder(holder);
+
+ if (holder.itemView instanceof ViewGroup) {
+ switchView = findSwitchWidget(holder.itemView);
+ if (mainColor != null && textColor != null) {
+ applyBrand();
+ }
+ }
+ }
+
+ @Override
+ public void applyBrand(@ColorInt int mainColor, @ColorInt int textColor) {
+ if (BrandingUtil.isBrandingEnabled(getContext())) {
+ this.mainColor = mainColor;
+ this.textColor = textColor;
+ } else {
+ this.mainColor = getContext().getResources().getColor(R.color.defaultBrand);
+ this.textColor = Color.WHITE;
+ }
+ // onBindViewHolder is called after applyBrand, therefore we have to store the given values and apply them later.
+ applyBrand();
+ }
+
+ private void applyBrand() {
+ if (switchView != null && SDK_INT >= JELLY_BEAN) {
+ final int finalMainColor = getSecondaryForegroundColorDependingOnTheme(getContext(), mainColor);
+ // int trackColor = Color.argb(77, Color.red(finalMainColor), Color.green(finalMainColor), Color.blue(finalMainColor));
+ DrawableCompat.setTintList(switchView.getThumbDrawable(), new ColorStateList(
+ new int[][]{new int[]{android.R.attr.state_checked}, new int[]{}},
+ new int[]{finalMainColor, getContext().getResources().getColor(R.color.fg_default_low)}
+ ));
+ DrawableCompat.setTintList(switchView.getTrackDrawable(), new ColorStateList(
+ new int[][]{new int[]{android.R.attr.state_checked}, new int[]{}},
+ new int[]{finalMainColor, getContext().getResources().getColor(R.color.fg_default_low)}
+ ));
+ }
+ }
+
+ /**
+ * Recursively go through view tree until we find an android.widget.Switch
+ *
+ * @param view Root view to start searching
+ * @return A Switch class or null
+ * @see <a href="https://gist.github.com/marchold/45e22839eb94aa14dfb5">Source</a>
+ */
+ private Switch findSwitchWidget(View view) {
+ if (view instanceof Switch) {
+ return (Switch) view;
+ }
+ if (view instanceof ViewGroup) {
+ ViewGroup viewGroup = (ViewGroup) view;
+ for (int i = 0; i < viewGroup.getChildCount(); i++) {
+ View child = viewGroup.getChildAt(i);
+ if (child instanceof ViewGroup) {
+ Switch result = findSwitchWidget(child);
+ if (result != null) return result;
+ }
+ if (child instanceof Switch) {
+ return (Switch) child;
+ }
+ }
+ }
+ return null;
+ }
+}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandingUtil.java b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandingUtil.java
new file mode 100644
index 00000000..f84bd8e4
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandingUtil.java
@@ -0,0 +1,134 @@
+package it.niedermann.owncloud.notes.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.graphics.drawable.LayerDrawable;
+import android.util.Log;
+import android.view.MenuItem;
+import android.widget.EditText;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.IdRes;
+import androidx.annotation.NonNull;
+import androidx.core.graphics.drawable.DrawableCompat;
+import androidx.preference.PreferenceManager;
+
+import it.niedermann.owncloud.notes.R;
+import it.niedermann.owncloud.notes.util.Notes;
+
+import static it.niedermann.owncloud.notes.util.ColorUtil.contrastRatioIsSufficient;
+
+public class BrandingUtil {
+
+ private static final String TAG = BrandingUtil.class.getSimpleName();
+ private static final String pref_key_branding_main = "branding_main";
+ private static final String pref_key_branding_text = "branding_text";
+
+ private BrandingUtil() {
+
+ }
+
+
+ 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 (BrandingUtil.isBrandingEnabled(context)) {
+ SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext());
+ Log.v(TAG, "--- Read: shared_preference_theme_main");
+ return sharedPreferences.getInt(pref_key_branding_main, context.getApplicationContext().getResources().getColor(R.color.defaultBrand));
+ } else {
+ return context.getResources().getColor(R.color.defaultBrand);
+ }
+ }
+
+ @ColorInt
+ public static int readBrandTextColor(@NonNull Context context) {
+ if (isBrandingEnabled(context)) {
+ SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext());
+ Log.v(TAG, "--- Read: shared_preference_theme_text");
+ return sharedPreferences.getInt(pref_key_branding_text, Color.WHITE);
+ } else {
+ return Color.WHITE;
+ }
+ }
+
+ public static void saveBrandColors(@NonNull Context context, @ColorInt int mainColor, @ColorInt int textColor) {
+ final int previousMainColor = readBrandMainColor(context);
+ final int previousTextColor = readBrandTextColor(context);
+ SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(context).edit();
+ Log.v(TAG, "--- Write: shared_preference_theme_main" + " | " + mainColor);
+ Log.v(TAG, "--- Write: shared_preference_theme_text" + " | " + textColor);
+ editor.putInt(pref_key_branding_main, mainColor);
+ editor.putInt(pref_key_branding_text, textColor);
+ editor.apply();
+ if (isBrandingEnabled(context) && context instanceof BrandedActivity) {
+ if (mainColor != previousMainColor || textColor != previousTextColor) {
+ final BrandedActivity activity = (BrandedActivity) context;
+ activity.runOnUiThread(activity::recreate);
+ }
+ }
+ }
+
+ /**
+ * 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 int primaryColor = context.getResources().getColor(R.color.primary);
+ final boolean isDarkTheme = Notes.isDarkThemeActive(context);
+ if (isDarkTheme && !contrastRatioIsSufficient(mainColor, primaryColor)) {
+ Log.v(TAG, "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, primaryColor)) {
+ Log.v(TAG, "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;
+ }
+ }
+
+ 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_default_low)
+ }
+ ));
+ }
+
+ 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);
+ }
+ }
+
+ public static void applyBrandToLayerDrawable(@NonNull LayerDrawable check, @IdRes int areaToColor, @ColorInt int mainColor) {
+ final Drawable drawable = check.findDrawableByLayerId(areaToColor);
+ if (drawable == null) {
+ Log.e(TAG, "Could not find areaToColor (" + areaToColor + "). Cannot apply brand.");
+ } else {
+ DrawableCompat.setTint(drawable, mainColor);
+ }
+ }
+}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/manageaccounts/ManageAccountAdapter.java b/app/src/main/java/it/niedermann/owncloud/notes/manageaccounts/ManageAccountAdapter.java
new file mode 100644
index 00000000..50ab925b
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/manageaccounts/ManageAccountAdapter.java
@@ -0,0 +1,80 @@
+package it.niedermann.owncloud.notes.manageaccounts;
+
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.core.util.Consumer;
+import androidx.recyclerview.widget.RecyclerView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import it.niedermann.owncloud.notes.R;
+import it.niedermann.owncloud.notes.model.LocalAccount;
+
+public class ManageAccountAdapter extends RecyclerView.Adapter<ManageAccountViewHolder> {
+
+ @Nullable
+ private LocalAccount currentLocalAccount = null;
+ @NonNull
+ private final List<LocalAccount> localAccounts = new ArrayList<>();
+ @NonNull
+ private final Consumer<LocalAccount> onAccountClick;
+ @Nullable
+ private final Consumer<LocalAccount> onAccountDelete;
+
+ public ManageAccountAdapter(@NonNull Consumer<LocalAccount> onAccountClick, @Nullable Consumer<LocalAccount> onAccountDelete) {
+ this.onAccountClick = onAccountClick;
+ this.onAccountDelete = onAccountDelete;
+ setHasStableIds(true);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return localAccounts.get(position).getId();
+ }
+
+ @NonNull
+ @Override
+ public ManageAccountViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ return new ManageAccountViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_account_choose, parent, false));
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull ManageAccountViewHolder holder, int position) {
+ final LocalAccount localAccount = localAccounts.get(position);
+ holder.bind(localAccount, (localAccountClicked) -> {
+ setCurrentLocalAccount(localAccountClicked);
+ onAccountClick.accept(localAccountClicked);
+ }, (localAccountToDelete -> {
+ if (onAccountDelete != null) {
+ for (int i = 0; i < localAccounts.size(); i++) {
+ if (localAccounts.get(i).getId() == localAccountToDelete.getId()) {
+ localAccounts.remove(i);
+ notifyItemRemoved(i);
+ break;
+ }
+ }
+ onAccountDelete.accept(localAccountToDelete);
+ }
+ }), currentLocalAccount != null && currentLocalAccount.getId() == localAccount.getId());
+ }
+
+ @Override
+ public int getItemCount() {
+ return localAccounts.size();
+ }
+
+ public void setLocalAccounts(@NonNull List<LocalAccount> localAccounts) {
+ this.localAccounts.clear();
+ this.localAccounts.addAll(localAccounts);
+ notifyDataSetChanged();
+ }
+
+ public void setCurrentLocalAccount(@Nullable LocalAccount currentLocalAccount) {
+ this.currentLocalAccount = currentLocalAccount;
+ notifyDataSetChanged();
+ }
+}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/manageaccounts/ManageAccountViewHolder.java b/app/src/main/java/it/niedermann/owncloud/notes/manageaccounts/ManageAccountViewHolder.java
new file mode 100644
index 00000000..df56fba5
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/manageaccounts/ManageAccountViewHolder.java
@@ -0,0 +1,53 @@
+package it.niedermann.owncloud.notes.manageaccounts;
+
+import android.graphics.drawable.LayerDrawable;
+import android.net.Uri;
+import android.view.View;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.core.util.Consumer;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.bumptech.glide.Glide;
+import com.bumptech.glide.request.RequestOptions;
+
+import it.niedermann.owncloud.notes.R;
+import it.niedermann.owncloud.notes.databinding.ItemAccountChooseBinding;
+import it.niedermann.owncloud.notes.model.LocalAccount;
+
+import static android.view.View.GONE;
+import static android.view.View.VISIBLE;
+import static it.niedermann.owncloud.notes.branding.BrandingUtil.applyBrandToLayerDrawable;
+
+public class ManageAccountViewHolder extends RecyclerView.ViewHolder {
+
+ private ItemAccountChooseBinding binding;
+
+ public ManageAccountViewHolder(@NonNull View itemView) {
+ super(itemView);
+ binding = ItemAccountChooseBinding.bind(itemView);
+ }
+
+ public void bind(@NonNull LocalAccount localAccount, @NonNull Consumer<LocalAccount> onAccountClick, @Nullable Consumer<LocalAccount> onAccountDelete, boolean isCurrentAccount) {
+ binding.accountItemLabel.setText(localAccount.getAccountName());
+ Glide.with(itemView.getContext())
+ .load(localAccount.getUrl() + "/index.php/avatar/" + Uri.encode(localAccount.getUserName()) + "/64")
+ .error(R.drawable.ic_account_circle_grey_24dp)
+ .apply(RequestOptions.circleCropTransform())
+ .into(binding.accountItemAvatar);
+ itemView.setOnClickListener((v) -> onAccountClick.accept(localAccount));
+ if (onAccountDelete == null) {
+ binding.delete.setVisibility(GONE);
+ } else {
+ binding.delete.setVisibility(VISIBLE);
+ binding.delete.setOnClickListener((v) -> onAccountDelete.accept(localAccount));
+ }
+ if (isCurrentAccount) {
+ binding.currentAccountIndicator.setVisibility(VISIBLE);
+ applyBrandToLayerDrawable((LayerDrawable) binding.currentAccountIndicator.getDrawable(), R.id.area, localAccount.getColor());
+ } else {
+ binding.currentAccountIndicator.setVisibility(GONE);
+ }
+ }
+}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/manageaccounts/ManageAccountsActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/manageaccounts/ManageAccountsActivity.java
new file mode 100644
index 00000000..123f345e
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/manageaccounts/ManageAccountsActivity.java
@@ -0,0 +1,74 @@
+package it.niedermann.owncloud.notes.manageaccounts;
+
+import android.os.Bundle;
+
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountNotFoundException;
+import com.nextcloud.android.sso.exceptions.NoCurrentAccountSelectedException;
+import com.nextcloud.android.sso.helper.SingleAccountHelper;
+import com.nextcloud.android.sso.model.SingleSignOnAccount;
+
+import java.util.List;
+
+import it.niedermann.owncloud.notes.android.activity.LockedActivity;
+import it.niedermann.owncloud.notes.databinding.ActivityManageAccountsBinding;
+import it.niedermann.owncloud.notes.model.LocalAccount;
+import it.niedermann.owncloud.notes.persistence.NotesDatabase;
+
+public class ManageAccountsActivity extends LockedActivity {
+
+ private ActivityManageAccountsBinding binding;
+ private ManageAccountAdapter adapter;
+ private NotesDatabase db = null;
+
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ binding = ActivityManageAccountsBinding.inflate(getLayoutInflater());
+ setContentView(binding.getRoot());
+
+ setSupportActionBar(binding.toolbar);
+
+ db = NotesDatabase.getInstance(this);
+
+ List<LocalAccount> localAccounts = db.getAccounts();
+
+ adapter = new ManageAccountAdapter((localAccount) -> {
+ SingleAccountHelper.setCurrentAccount(getApplicationContext(), localAccount.getAccountName());
+ }, (localAccount) -> {
+ db.deleteAccount(localAccount);
+ for (LocalAccount temp : localAccounts) {
+ if (temp.getId() == localAccount.getId()) {
+ localAccounts.remove(temp);
+ break;
+ }
+ }
+ if (localAccounts.size() > 0) {
+ SingleAccountHelper.setCurrentAccount(getApplicationContext(), localAccounts.get(0).getAccountName());
+ adapter.setCurrentLocalAccount(localAccounts.get(0));
+ } else {
+ setResult(AppCompatActivity.RESULT_FIRST_USER);
+ finish();
+ }
+ });
+ adapter.setLocalAccounts(localAccounts);
+ try {
+ SingleSignOnAccount ssoAccount = SingleAccountHelper.getCurrentSingleSignOnAccount(this);
+ if (ssoAccount != null) {
+ adapter.setCurrentLocalAccount(db.getLocalAccountByAccountName(ssoAccount.name));
+ }
+ } catch (NextcloudFilesAppAccountNotFoundException | NoCurrentAccountSelectedException e) {
+ e.printStackTrace();
+ }
+ binding.accounts.setAdapter(adapter);
+ }
+
+ @Override
+ public void applyBrand(int mainColor, int textColor) {
+ applyBrandToPrimaryToolbar(binding.toolbar);
+ }
+}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/model/ItemAdapter.java b/app/src/main/java/it/niedermann/owncloud/notes/model/ItemAdapter.java
index c2f2cc4b..ba6042bc 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/model/ItemAdapter.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/model/ItemAdapter.java
@@ -1,13 +1,13 @@
package it.niedermann.owncloud.notes.model;
-import android.text.Html;
+import android.content.Context;
+import android.graphics.Color;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.TextView;
+import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
@@ -15,26 +15,31 @@ import java.util.ArrayList;
import java.util.List;
import it.niedermann.owncloud.notes.R;
-import it.niedermann.owncloud.notes.databinding.ItemNotesListNoteItemBinding;
-import it.niedermann.owncloud.notes.databinding.ItemNotesListSectionItemBinding;
+import it.niedermann.owncloud.notes.branding.Branded;
-import static androidx.recyclerview.widget.RecyclerView.NO_POSITION;
-
-public class ItemAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
+public class ItemAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements Branded {
private static final String TAG = ItemAdapter.class.getSimpleName();
private static final int section_type = 0;
private static final int note_type = 1;
private final NoteClickListener noteClickListener;
- private List<Item> itemList;
+ private List<Item> itemList = new ArrayList<>();
private boolean showCategory = true;
- private final List<Integer> selected;
+ private CharSequence searchQuery;
+ @NonNull
+ private Context context;
+ private final List<Integer> selected = new ArrayList<>();
+ @ColorInt
+ private int mainColor;
+ @ColorInt
+ private int textColor;
- public ItemAdapter(@NonNull NoteClickListener noteClickListener) {
- this.itemList = new ArrayList<>();
- this.selected = new ArrayList<>();
- this.noteClickListener = noteClickListener;
+ public <T extends Context & NoteClickListener> ItemAdapter(@NonNull T context) {
+ this.context = context;
+ this.noteClickListener = context;
+ this.mainColor = context.getResources().getColor(R.color.defaultBrand);
+ this.textColor = Color.WHITE;
}
/**
@@ -66,7 +71,6 @@ public class ItemAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
notifyDataSetChanged();
}
- // Create new views (invoked by the layout manager)
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
@@ -77,30 +81,17 @@ public class ItemAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
} else {
v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_notes_list_note_item, parent, false);
- return new NoteViewHolder(v);
+ return new NoteViewHolder(v, noteClickListener);
}
}
- // Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, int position) {
- // - get element from your dataset at this position
- // - replace the contents of the view with that element
- Item item = itemList.get(position);
+ final Item item = itemList.get(position);
if (item.isSection()) {
- SectionItem section = (SectionItem) item;
- ((SectionViewHolder) holder).sectionTitle.setText(section.geTitle());
+ ((SectionViewHolder) holder).bind((SectionItem) item);
} else {
- final DBNote note = (DBNote) item;
- final NoteViewHolder nvHolder = ((NoteViewHolder) holder);
- nvHolder.noteSwipeable.setAlpha(DBStatus.LOCAL_DELETED.equals(note.getStatus()) ? 0.5f : 1.0f);
- nvHolder.noteTitle.setText(Html.fromHtml(note.getTitle()));
- nvHolder.noteCategory.setVisibility(showCategory && !note.getCategory().isEmpty() ? View.VISIBLE : View.GONE);
- nvHolder.noteCategory.setText(Html.fromHtml(note.getCategory()));
- nvHolder.noteExcerpt.setText(Html.fromHtml(note.getExcerpt()));
- nvHolder.noteStatus.setVisibility(DBStatus.VOID.equals(note.getStatus()) ? View.INVISIBLE : View.VISIBLE);
- nvHolder.noteFavorite.setImageResource(note.isFavorite() ? R.drawable.ic_star_yellow_24dp : R.drawable.ic_star_grey_ccc_24dp);
- nvHolder.noteFavorite.setOnClickListener(view -> noteClickListener.onNoteFavoriteClick(holder.getAdapterPosition(), view));
+ ((NoteViewHolder) holder).bind((DBNote) item, noteClickListener, showCategory, mainColor, textColor, searchQuery);
}
}
@@ -159,63 +150,14 @@ public class ItemAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
return getItem(position).isSection() ? section_type : note_type;
}
- public interface NoteClickListener {
- void onNoteClick(int position, View v);
-
- void onNoteFavoriteClick(int position, View v);
-
- boolean onNoteLongClick(int position, View v);
- }
-
- public class NoteViewHolder extends RecyclerView.ViewHolder implements View.OnLongClickListener, View.OnClickListener {
- public View noteSwipeable;
- private final ItemNotesListNoteItemBinding b;
- private final TextView noteTitle;
- private final TextView noteCategory;
- private final TextView noteExcerpt;
- private final ImageView noteStatus;
- private final ImageView noteFavorite;
-
- private NoteViewHolder(View v) {
- super(v);
- b = ItemNotesListNoteItemBinding.bind(v);
- this.noteSwipeable = b.noteSwipeable;
- this.noteTitle = b.noteTitle;
- this.noteCategory = b.noteCategory;
- this.noteExcerpt = b.noteExcerpt;
- this.noteStatus = b.noteStatus;
- this.noteFavorite = b.noteFavorite;
- v.setOnClickListener(this);
- v.setOnLongClickListener(this);
- }
-
- @Override
- public void onClick(View v) {
- final int adapterPosition = getAdapterPosition();
- if (adapterPosition != NO_POSITION) {
- noteClickListener.onNoteClick(adapterPosition, v);
- }
- }
-
- @Override
- public boolean onLongClick(View v) {
- return noteClickListener.onNoteLongClick(getAdapterPosition(), v);
- }
-
- public void showSwipe(boolean left) {
- b.noteFavoriteLeft.setVisibility(left ? View.VISIBLE : View.INVISIBLE);
- b.noteDeleteRight.setVisibility(left ? View.INVISIBLE : View.VISIBLE);
- b.noteSwipeFrame.setBackgroundResource(left ? R.color.bg_warning : R.color.bg_attention);
- }
+ @Override
+ public void applyBrand(int mainColor, int textColor) {
+ this.mainColor = mainColor;
+ this.textColor = textColor;
+ notifyDataSetChanged();
}
- public static class SectionViewHolder extends RecyclerView.ViewHolder {
- private TextView sectionTitle;
-
- private SectionViewHolder(View view) {
- super(view);
- ItemNotesListSectionItemBinding binding = ItemNotesListSectionItemBinding.bind(view);
- this.sectionTitle = binding.sectionTitle;
- }
+ public void setHighlightSearchQuery(CharSequence searchQuery) {
+ this.searchQuery = searchQuery;
}
} \ No newline at end of file
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/model/NavigationAdapter.java b/app/src/main/java/it/niedermann/owncloud/notes/model/NavigationAdapter.java
index f4a4bb36..751fc581 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/model/NavigationAdapter.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/model/NavigationAdapter.java
@@ -1,5 +1,6 @@
package it.niedermann.owncloud.notes.model;
+import android.content.Context;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
@@ -7,6 +8,7 @@ import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
+import androidx.annotation.ColorInt;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -17,11 +19,16 @@ import java.util.ArrayList;
import java.util.List;
import it.niedermann.owncloud.notes.R;
+import it.niedermann.owncloud.notes.branding.BrandingUtil;
import it.niedermann.owncloud.notes.databinding.ItemNavigationBinding;
import it.niedermann.owncloud.notes.util.NoteUtil;
public class NavigationAdapter extends RecyclerView.Adapter<NavigationAdapter.ViewHolder> {
+ @NonNull
+ private final Context context;
+ @ColorInt
+ private int mainColor;
@DrawableRes
public static final int ICON_FOLDER = R.drawable.ic_folder_grey600_24dp;
@DrawableRes
@@ -35,6 +42,11 @@ public class NavigationAdapter extends RecyclerView.Adapter<NavigationAdapter.Vi
@DrawableRes
public static final int ICON_SUB_MULTIPLE = R.drawable.ic_create_new_folder_grey600_18dp;
+ public void applyBrand(int mainColor, int textColor) {
+ this.mainColor = BrandingUtil.getSecondaryForegroundColorDependingOnTheme(context, mainColor);
+ notifyDataSetChanged();
+ }
+
public static class NavigationItem {
@NonNull
public String id;
@@ -87,7 +99,7 @@ public class NavigationAdapter extends RecyclerView.Adapter<NavigationAdapter.Vi
itemView.setOnClickListener(view -> clickListener.onItemClick(currentItem));
}
- private void assignItem(@NonNull NavigationItem item) {
+ private void bind(@NonNull NavigationItem item) {
currentItem = item;
boolean isSelected = item.id.equals(selectedItem);
name.setText(NoteUtil.extendCategory(item.label));
@@ -100,7 +112,7 @@ public class NavigationAdapter extends RecyclerView.Adapter<NavigationAdapter.Vi
icon.setVisibility(View.GONE);
}
view.setBackgroundColor(isSelected ? view.getResources().getColor(R.color.bg_highlighted) : Color.TRANSPARENT);
- int textColor = view.getResources().getColor(isSelected ? R.color.primary_dark : R.color.fg_default);
+ int textColor = isSelected ? mainColor : view.getResources().getColor(R.color.fg_default);
name.setTextColor(textColor);
count.setTextColor(textColor);
@@ -120,7 +132,9 @@ public class NavigationAdapter extends RecyclerView.Adapter<NavigationAdapter.Vi
@NonNull
private final ClickListener clickListener;
- public NavigationAdapter(@NonNull ClickListener clickListener) {
+ public NavigationAdapter(@NonNull Context context, @NonNull ClickListener clickListener) {
+ this.context = context;
+ this.mainColor = BrandingUtil.getSecondaryForegroundColorDependingOnTheme(context, BrandingUtil.readBrandMainColor(context));
this.clickListener = clickListener;
}
@@ -133,7 +147,7 @@ public class NavigationAdapter extends RecyclerView.Adapter<NavigationAdapter.Vi
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
- holder.assignItem(items.get(position));
+ holder.bind(items.get(position));
}
@Override
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/model/NoteClickListener.java b/app/src/main/java/it/niedermann/owncloud/notes/model/NoteClickListener.java
new file mode 100644
index 00000000..8dd1748d
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/model/NoteClickListener.java
@@ -0,0 +1,11 @@
+package it.niedermann.owncloud.notes.model;
+
+import android.view.View;
+
+public interface NoteClickListener {
+ void onNoteClick(int position, View v);
+
+ void onNoteFavoriteClick(int position, View v);
+
+ boolean onNoteLongClick(int position, View v);
+} \ No newline at end of file
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/model/NoteViewHolder.java b/app/src/main/java/it/niedermann/owncloud/notes/model/NoteViewHolder.java
new file mode 100644
index 00000000..a42c8377
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/model/NoteViewHolder.java
@@ -0,0 +1,143 @@
+package it.niedermann.owncloud.notes.model;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.drawable.GradientDrawable;
+import android.os.Build;
+import android.text.SpannableString;
+import android.text.TextUtils;
+import android.text.style.BackgroundColorSpan;
+import android.text.style.ForegroundColorSpan;
+import android.view.View;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.core.graphics.drawable.DrawableCompat;
+import androidx.recyclerview.widget.RecyclerView;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import it.niedermann.owncloud.notes.R;
+import it.niedermann.owncloud.notes.branding.BrandingUtil;
+import it.niedermann.owncloud.notes.databinding.ItemNotesListNoteItemBinding;
+import it.niedermann.owncloud.notes.util.Notes;
+
+import static androidx.recyclerview.widget.RecyclerView.NO_POSITION;
+import static it.niedermann.owncloud.notes.util.ColorUtil.contrastRatioIsSufficient;
+import static it.niedermann.owncloud.notes.util.ColorUtil.isColorDark;
+
+public class NoteViewHolder extends RecyclerView.ViewHolder implements View.OnLongClickListener, View.OnClickListener {
+ private final ItemNotesListNoteItemBinding binding;
+ private final NoteClickListener noteClickListener;
+
+ public NoteViewHolder(View v, NoteClickListener noteClickListener) {
+ super(v);
+ binding = ItemNotesListNoteItemBinding.bind(v);
+ this.noteClickListener = noteClickListener;
+ v.setOnClickListener(this);
+ v.setOnLongClickListener(this);
+ }
+
+ @Override
+ public void onClick(View v) {
+ final int adapterPosition = getAdapterPosition();
+ if (adapterPosition != NO_POSITION) {
+ noteClickListener.onNoteClick(adapterPosition, v);
+ }
+ }
+
+ @Override
+ public boolean onLongClick(View v) {
+ return noteClickListener.onNoteLongClick(getAdapterPosition(), v);
+ }
+
+ public void showSwipe(boolean left) {
+ binding.noteFavoriteLeft.setVisibility(left ? View.VISIBLE : View.INVISIBLE);
+ binding.noteDeleteRight.setVisibility(left ? View.INVISIBLE : View.VISIBLE);
+ binding.noteSwipeFrame.setBackgroundResource(left ? R.color.bg_warning : R.color.bg_attention);
+ }
+
+ public void bind(DBNote note, NoteClickListener noteClickListener, boolean showCategory, int mainColor, int textColor, @Nullable CharSequence searchQuery) {
+ @NonNull final Context context = itemView.getContext();
+ final boolean isDarkThemeActive = Notes.isDarkThemeActive(context);
+
+ binding.noteSwipeable.setAlpha(DBStatus.LOCAL_DELETED.equals(note.getStatus()) ? 0.5f : 1.0f);
+
+ binding.noteCategory.setVisibility(showCategory && !note.getCategory().isEmpty() ? View.VISIBLE : View.GONE);
+ binding.noteCategory.setText(note.getCategory());
+
+ @ColorInt int categoryForeground;
+ @ColorInt int categoryBackground;
+
+ if (isDarkThemeActive) {
+ if (isColorDark(mainColor)) {
+ if (contrastRatioIsSufficient(mainColor, Color.BLACK)) {
+ categoryBackground = mainColor;
+ categoryForeground = Color.WHITE;
+ } else {
+ categoryBackground = Color.WHITE;
+ categoryForeground = mainColor;
+ }
+ } else {
+ categoryBackground = mainColor;
+ categoryForeground = Color.BLACK;
+ }
+ } else {
+ categoryForeground = Color.BLACK;
+ if (isColorDark(mainColor) || contrastRatioIsSufficient(mainColor, Color.WHITE)) {
+ categoryBackground = mainColor;
+ } else {
+ categoryBackground = Color.BLACK;
+ }
+ }
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ DrawableCompat.setTint(binding.noteCategory.getBackground(), categoryBackground);
+ } else {
+ final GradientDrawable drawable = (GradientDrawable) binding.noteCategory.getBackground();
+ drawable.setStroke(1, categoryBackground);
+ drawable.setColor(isDarkThemeActive ? categoryBackground : Color.TRANSPARENT);
+ }
+ binding.noteCategory.setTextColor(categoryForeground);
+
+ binding.noteStatus.setVisibility(DBStatus.VOID.equals(note.getStatus()) ? View.INVISIBLE : View.VISIBLE);
+ binding.noteFavorite.setImageResource(note.isFavorite() ? R.drawable.ic_star_yellow_24dp : R.drawable.ic_star_grey_ccc_24dp);
+ binding.noteFavorite.setOnClickListener(view -> noteClickListener.onNoteFavoriteClick(getAdapterPosition(), view));
+
+ if (!TextUtils.isEmpty(searchQuery)) {
+ @ColorInt final int searchBackground = context.getResources().getColor(R.color.bg_highlighted);
+ @ColorInt final int searchForeground = BrandingUtil.getSecondaryForegroundColorDependingOnTheme(context, mainColor);
+
+ // The Pattern.quote method will add \Q to the very beginning of the string and \E to the end of the string
+ // It implies that the string between \Q and \E is a literal string and thus the reserved keyword in such string will be ignored.
+ // See https://stackoverflow.com/questions/15409296/what-is-the-use-of-pattern-quote-method
+ final Pattern pattern = Pattern.compile("(" + Pattern.quote(searchQuery.toString()) + ")", Pattern.CASE_INSENSITIVE);
+ SpannableString spannableString = new SpannableString(note.getTitle());
+ Matcher matcher = pattern.matcher(spannableString);
+ while (matcher.find()) {
+ spannableString.setSpan(new ForegroundColorSpan(searchForeground), matcher.start(), matcher.end(), 0);
+ spannableString.setSpan(new BackgroundColorSpan(searchBackground), matcher.start(), matcher.end(), 0);
+ }
+
+ binding.noteTitle.setText(spannableString);
+
+ spannableString = new SpannableString(note.getExcerpt());
+ matcher = pattern.matcher(spannableString);
+ while (matcher.find()) {
+ spannableString.setSpan(new ForegroundColorSpan(searchForeground), matcher.start(), matcher.end(), 0);
+ spannableString.setSpan(new BackgroundColorSpan(searchBackground), matcher.start(), matcher.end(), 0);
+ }
+
+ binding.noteExcerpt.setText(spannableString);
+ } else {
+ binding.noteTitle.setText(note.getTitle());
+ binding.noteExcerpt.setText(note.getExcerpt());
+ }
+ }
+
+ public View getNoteSwipeable() {
+ return binding.noteSwipeable;
+ }
+} \ No newline at end of file
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/model/SectionItem.java b/app/src/main/java/it/niedermann/owncloud/notes/model/SectionItem.java
index c144211b..27e4758a 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/model/SectionItem.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/model/SectionItem.java
@@ -8,7 +8,7 @@ public class SectionItem implements Item {
this.title = title;
}
- public String geTitle() {
+ public String getTitle() {
return title;
}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/model/SectionViewHolder.java b/app/src/main/java/it/niedermann/owncloud/notes/model/SectionViewHolder.java
new file mode 100644
index 00000000..3441cc85
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/model/SectionViewHolder.java
@@ -0,0 +1,20 @@
+package it.niedermann.owncloud.notes.model;
+
+import android.view.View;
+
+import androidx.recyclerview.widget.RecyclerView;
+
+import it.niedermann.owncloud.notes.databinding.ItemNotesListSectionItemBinding;
+
+public class SectionViewHolder extends RecyclerView.ViewHolder {
+ private final ItemNotesListSectionItemBinding binding;
+
+ public SectionViewHolder(View view) {
+ super(view);
+ binding = ItemNotesListSectionItemBinding.bind(view);
+ }
+
+ public void bind(SectionItem item) {
+ binding.sectionTitle.setText(item.getTitle());
+ }
+} \ No newline at end of file
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/AbstractNotesDatabase.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/AbstractNotesDatabase.java
index 45d58a50..13a37b93 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/AbstractNotesDatabase.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/AbstractNotesDatabase.java
@@ -34,7 +34,7 @@ abstract class AbstractNotesDatabase extends SQLiteOpenHelper {
private static final int database_version = 16;
@NonNull
- private final Context context;
+ protected final Context context;
protected static final String database_name = "OWNCLOUD_NOTES";
protected static final String table_notes = "NOTES";
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/LoadNotesListTask.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/LoadNotesListTask.java
index a6b77024..4dbdbcbf 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/LoadNotesListTask.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/LoadNotesListTask.java
@@ -1,14 +1,8 @@
package it.niedermann.owncloud.notes.persistence;
import android.content.Context;
-import android.graphics.Color;
import android.os.AsyncTask;
-import android.text.Html;
-import android.text.SpannableString;
-import android.text.TextUtils;
import android.text.format.DateUtils;
-import android.text.style.BackgroundColorSpan;
-import android.text.style.ForegroundColorSpan;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -17,15 +11,12 @@ import androidx.annotation.WorkerThread;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
import it.niedermann.owncloud.notes.R;
import it.niedermann.owncloud.notes.model.Category;
import it.niedermann.owncloud.notes.model.DBNote;
import it.niedermann.owncloud.notes.model.Item;
import it.niedermann.owncloud.notes.model.SectionItem;
-import it.niedermann.owncloud.notes.util.DisplayUtils;
import it.niedermann.owncloud.notes.util.NoteUtil;
public class LoadNotesListTask extends AsyncTask<Void, Void, List<Item>> {
@@ -35,8 +26,6 @@ public class LoadNotesListTask extends AsyncTask<Void, Void, List<Item>> {
private final Category category;
private final CharSequence searchQuery;
private final long accountId;
- private final int searchForeground;
- private final int searchBackground;
public LoadNotesListTask(long accountId, @NonNull Context context, @NonNull NotesLoadedListener callback, @NonNull Category category, @Nullable CharSequence searchQuery) {
this.context = context;
@@ -44,8 +33,6 @@ public class LoadNotesListTask extends AsyncTask<Void, Void, List<Item>> {
this.category = category;
this.searchQuery = searchQuery;
this.accountId = accountId;
- this.searchBackground = context.getResources().getColor(R.color.bg_highlighted);
- this.searchForeground = DisplayUtils.getForeground(Integer.toHexString(this.searchBackground)) ? Color.WHITE : context.getResources().getColor(R.color.primary);
}
@Override
@@ -61,30 +48,6 @@ public class LoadNotesListTask extends AsyncTask<Void, Void, List<Item>> {
}
}
- private DBNote colorTheNote(DBNote dbNote) {
- if (!TextUtils.isEmpty(searchQuery)) {
- SpannableString spannableString = new SpannableString(dbNote.getTitle());
- Matcher matcher = Pattern.compile("(" + searchQuery + ")", Pattern.CASE_INSENSITIVE).matcher(spannableString);
- while (matcher.find()) {
- spannableString.setSpan(new ForegroundColorSpan(searchForeground), matcher.start(), matcher.end(), 0);
- spannableString.setSpan(new BackgroundColorSpan(searchBackground), matcher.start(), matcher.end(), 0);
- }
-
- dbNote.setTitle(Html.toHtml(spannableString));
-
- spannableString = new SpannableString(dbNote.getExcerpt());
- matcher = Pattern.compile("(" + searchQuery + ")", Pattern.CASE_INSENSITIVE).matcher(spannableString);
- while (matcher.find()) {
- spannableString.setSpan(new ForegroundColorSpan(searchForeground), matcher.start(), matcher.end(), 0);
- spannableString.setSpan(new BackgroundColorSpan(searchBackground), matcher.start(), matcher.end(), 0);
- }
-
- dbNote.setExcerpt(Html.toHtml(spannableString));
- }
-
- return dbNote;
- }
-
@NonNull
@WorkerThread
private List<Item> fillListByCategory(@NonNull List<DBNote> noteList) {
@@ -95,7 +58,7 @@ public class LoadNotesListTask extends AsyncTask<Void, Void, List<Item>> {
itemList.add(new SectionItem(NoteUtil.extendCategory(note.getCategory())));
}
- itemList.add(colorTheNote(note));
+ itemList.add(note);
currentCategory = note.getCategory();
}
return itemList;
@@ -113,7 +76,7 @@ public class LoadNotesListTask extends AsyncTask<Void, Void, List<Item>> {
if (i > 0 && !timeslot.equals(lastTimeslot)) {
itemList.add(new SectionItem(timeslot));
}
- itemList.add(colorTheNote(currentNote));
+ itemList.add(currentNote);
lastTimeslot = timeslot;
}
@@ -122,11 +85,11 @@ public class LoadNotesListTask extends AsyncTask<Void, Void, List<Item>> {
@Override
protected void onPostExecute(List<Item> items) {
- callback.onNotesLoaded(items, category.category == null);
+ callback.onNotesLoaded(items, category.category == null, searchQuery);
}
public interface NotesLoadedListener {
- void onNotesLoaded(List<Item> notes, boolean showCategory);
+ void onNotesLoaded(List<Item> notes, boolean showCategory, CharSequence searchQuery);
}
private class Timeslotter {
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NoteServerSyncHelper.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NoteServerSyncHelper.java
index d48b7529..cb6c2717 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NoteServerSyncHelper.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NoteServerSyncHelper.java
@@ -34,6 +34,7 @@ import java.util.Set;
import it.niedermann.owncloud.notes.R;
import it.niedermann.owncloud.notes.android.fragment.ExceptionDialogFragment;
+import it.niedermann.owncloud.notes.branding.BrandedSnackbar;
import it.niedermann.owncloud.notes.model.CloudNote;
import it.niedermann.owncloud.notes.model.DBNote;
import it.niedermann.owncloud.notes.model.DBStatus;
@@ -499,7 +500,7 @@ public class NoteServerSyncHelper {
}
if (!status.pullSuccessful || !status.pushSuccessful) {
if (context instanceof ViewProvider && context instanceof AppCompatActivity) {
- Snackbar.make(((ViewProvider) context).getView(), R.string.error_synchronization, Snackbar.LENGTH_LONG)
+ BrandedSnackbar.make(((ViewProvider) context).getView(), R.string.error_synchronization, Snackbar.LENGTH_LONG)
.setAction(R.string.simple_more, v -> ExceptionDialogFragment.newInstance(exceptions)
.show(((AppCompatActivity) context).getSupportFragmentManager(), ExceptionDialogFragment.class.getSimpleName()))
.show();
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesDatabase.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesDatabase.java
index 63391fc5..fe3600e1 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesDatabase.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NotesDatabase.java
@@ -20,6 +20,7 @@ import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
+import androidx.core.content.ContextCompat;
import com.nextcloud.android.sso.AccountImporter;
import com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountNotFoundException;
@@ -52,6 +53,7 @@ import it.niedermann.owncloud.notes.model.LocalAccount;
import it.niedermann.owncloud.notes.model.NavigationAdapter;
import it.niedermann.owncloud.notes.model.NoteListsWidgetData;
import it.niedermann.owncloud.notes.model.SingleNoteWidgetData;
+import it.niedermann.owncloud.notes.util.ColorUtil;
import it.niedermann.owncloud.notes.util.NoteUtil;
import static it.niedermann.owncloud.notes.android.activity.EditNoteActivity.ACTION_SHORTCUT;
@@ -716,10 +718,9 @@ public class NotesDatabase extends AbstractNotesDatabase {
values.put(key_url, url);
values.put(key_username, username);
values.put(key_account_name, accountName);
- values.put(key_color, capabilities.getColor().substring(1));
- values.put(key_text_color, capabilities.getTextColor().substring(1));
values.put(key_capabilities_etag, capabilities.getETag());
- db.insertOrThrow(table_accounts, null, values);
+ long accountId = db.insertOrThrow(table_accounts, null, values);
+ updateBrand(accountId, capabilities);
}
/**
@@ -807,15 +808,26 @@ public class NotesDatabase extends AbstractNotesDatabase {
public void updateBrand(long accountId, @NonNull Capabilities capabilities) throws IllegalArgumentException {
validateAccountId(accountId);
- // Validate color format
- Color.parseColor(capabilities.getColor());
- Color.parseColor(capabilities.getTextColor());
+
+ String color;
+ try {
+ color = ColorUtil.formatColorToParsableHexString(capabilities.getColor()).substring(1);
+ } catch (Exception e) {
+ color = String.format("%06X", (0xFFFFFF & ContextCompat.getColor(context, R.color.defaultBrand)));
+ }
+
+ String textColor;
+ try {
+ textColor = ColorUtil.formatColorToParsableHexString(capabilities.getTextColor()).substring(1);
+ } catch (Exception e) {
+ textColor = String.format("%06X", (0xFFFFFF & ContextCompat.getColor(context, android.R.color.white)));
+ }
final SQLiteDatabase db = this.getWritableDatabase();
final ContentValues values = new ContentValues();
- values.put(key_color, capabilities.getColor().substring(1));
- values.put(key_text_color, capabilities.getTextColor().substring(1));
+ values.put(key_color, color);
+ values.put(key_text_color, textColor);
final int updatedRows = db.update(table_accounts, values, key_id + " = ?", new String[]{String.valueOf(accountId)});
if (updatedRows == 1) {
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/util/ColorUtil.java b/app/src/main/java/it/niedermann/owncloud/notes/util/ColorUtil.java
index 8649d7a0..3b44c0f2 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/util/ColorUtil.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/util/ColorUtil.java
@@ -3,6 +3,7 @@ package it.niedermann.owncloud.notes.util;
import android.graphics.Color;
import androidx.annotation.ColorInt;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.util.Pair;
@@ -107,4 +108,47 @@ public final class ColorUtil {
return result;
}
}
+
+ /**
+ * @return well formatted string starting with a hash followed by 6 hex numbers that is parsable by {@link Color#parseColor(String)}.
+ */
+ public static String formatColorToParsableHexString(String input) {
+ if (input == null) {
+ throw new IllegalArgumentException("input color string is null");
+ }
+ if (isParsableValidHexColorString(input)) {
+ return input;
+ }
+ final char[] chars = input.replaceAll("#", "").toCharArray();
+ final StringBuilder sb = new StringBuilder(7).append("#");
+ if (chars.length == 6) {
+ sb.append(chars);
+ } else if (chars.length == 3) {
+ for (char c : chars) {
+ sb.append(c).append(c);
+ }
+ } else {
+ throw new IllegalArgumentException("unparsable color string: \"" + input + "\"");
+ }
+ final String formattedHexColor = sb.toString();
+ if (isParsableValidHexColorString(formattedHexColor)) {
+ return formattedHexColor;
+ } else {
+ throw new IllegalArgumentException("\"" + input + "\" is not a valid color string. Result of tried normalizing: " + formattedHexColor);
+ }
+ }
+
+ /**
+ * Checking for {@link Color#parseColor(String)} being able to parse the input is the important part because we don't know the implementation and rely on it to be able to parse the color.
+ *
+ * @return true, if the input starts with a hash followed by 6 characters of hex numbers and is parsable by {@link Color#parseColor(String)}.
+ */
+ private static boolean isParsableValidHexColorString(@NonNull String input) {
+ try {
+ Color.parseColor(input);
+ return input.matches("#[a-fA-F0-9]{6}");
+ } catch (Exception e) {
+ return false;
+ }
+ }
}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/util/DisplayUtils.java b/app/src/main/java/it/niedermann/owncloud/notes/util/DisplayUtils.java
index a4fd4c41..50931618 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/util/DisplayUtils.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/util/DisplayUtils.java
@@ -26,6 +26,7 @@ import android.text.TextPaint;
import android.text.TextUtils;
import android.text.style.MetricAffectingSpan;
+import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -33,6 +34,9 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import it.niedermann.owncloud.notes.R;
+import it.niedermann.owncloud.notes.branding.BrandingUtil;
+
+import static it.niedermann.owncloud.notes.util.ColorUtil.isColorDark;
public class DisplayUtils {
@@ -40,7 +44,7 @@ public class DisplayUtils {
}
- public static Spannable searchAndColor(Spannable spannable, CharSequence searchText, Context context, @Nullable Integer current) {
+ public static Spannable searchAndColor(Spannable spannable, CharSequence searchText, @NonNull Context context, @Nullable Integer current, @ColorInt int mainColor, @ColorInt int textColor) {
CharSequence text = spannable.toString();
Object[] spansToRemove = spannable.getSpans(0, text.length(), Object.class);
@@ -60,7 +64,7 @@ public class DisplayUtils {
while (m.find()) {
int start = m.start();
int end = m.end();
- spannable.setSpan(new SearchSpan(context, (current != null && i == current)), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ spannable.setSpan(new SearchSpan(context, mainColor, textColor, (current != null && i == current)), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
i++;
}
@@ -71,19 +75,51 @@ public class DisplayUtils {
static class SearchSpan extends MetricAffectingSpan {
private final boolean current;
- private final int bgColorPrimary;
- private final int bgColorSecondary;
-
- SearchSpan(Context context, boolean current) {
+ @NonNull
+ Context context;
+ @ColorInt
+ private final int mainColor;
+ @ColorInt
+ private final int textColor;
+ @ColorInt
+ private final int highlightColor;
+
+ SearchSpan(@NonNull Context context, @ColorInt int mainColor, @ColorInt int textColor, boolean current) {
+ this.context = context;
+ this.mainColor = mainColor;
+ this.textColor = textColor;
this.current = current;
- this.bgColorPrimary = context.getResources().getColor(R.color.bg_search_primary);
- this.bgColorSecondary = context.getResources().getColor(R.color.bg_search_secondary);
+ this.highlightColor = context.getResources().getColor(R.color.bg_highlighted);
}
@Override
public void updateDrawState(TextPaint tp) {
- tp.bgColor = current ? bgColorPrimary : bgColorSecondary;
- tp.setColor(current ? (getForeground(Integer.toHexString(tp.bgColor)) ? Color.WHITE : Color.BLACK) : bgColorPrimary);
+ if (current) {
+ if (Notes.isDarkThemeActive(context)) {
+ if (isColorDark(mainColor)) {
+ tp.bgColor = Color.WHITE;
+ tp.setColor(mainColor);
+ } else {
+ tp.bgColor = mainColor;
+ tp.setColor(Color.BLACK);
+ }
+ } else {
+ if (isColorDark(mainColor)) {
+ tp.bgColor = mainColor;
+ tp.setColor(Color.WHITE);
+ } else {
+ if (ColorUtil.contrastRatioIsSufficient(mainColor, highlightColor)) {
+ tp.bgColor = highlightColor;
+ } else {
+ tp.bgColor = Color.BLACK;
+ }
+ tp.setColor(mainColor);
+ }
+ }
+ } else {
+ tp.bgColor = highlightColor;
+ tp.setColor(BrandingUtil.getSecondaryForegroundColorDependingOnTheme(context, mainColor));
+ }
tp.setFakeBoldText(true);
}
@@ -92,12 +128,4 @@ public class DisplayUtils {
tp.setFakeBoldText(true);
}
}
-
- public static boolean getForeground(String backgroundColorHex) {
- return ((float) (
- 0.2126 * Integer.valueOf(backgroundColorHex.substring(1, 3), 16)
- + 0.7152 * Integer.valueOf(backgroundColorHex.substring(3, 5), 16)
- + 0.0722 * Integer.valueOf(backgroundColorHex.substring(5, 7), 16)
- ) < 140);
- }
}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/util/MarkDownUtil.java b/app/src/main/java/it/niedermann/owncloud/notes/util/MarkDownUtil.java
index 9d9abe95..66f89280 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/util/MarkDownUtil.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/util/MarkDownUtil.java
@@ -65,7 +65,7 @@ public class MarkDownUtil {
darkTheme ? R.color.widget_fg_dark_theme : R.color.widget_fg_default, null))
.setTodoDoneColor(ResourcesCompat.getColor(context.getResources(),
darkTheme ? R.color.widget_fg_dark_theme : R.color.widget_fg_default, null))
- .setLinkFontColor(ResourcesCompat.getColor(context.getResources(), R.color.primary, null))
+ .setLinkFontColor(ResourcesCompat.getColor(context.getResources(), R.color.defaultBrand, null))
.setRxMDImageLoader(new NotesImageLoader(context))
.setDefaultImageSize(400, 300);
}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/util/SSOUtil.java b/app/src/main/java/it/niedermann/owncloud/notes/util/SSOUtil.java
index 5089f14d..77fa0d2c 100644
--- a/app/src/main/java/it/niedermann/owncloud/notes/util/SSOUtil.java
+++ b/app/src/main/java/it/niedermann/owncloud/notes/util/SSOUtil.java
@@ -45,9 +45,7 @@ public class SSOUtil {
try {
SingleAccountHelper.getCurrentSingleSignOnAccount(context);
return true;
- } catch (NextcloudFilesAppAccountNotFoundException e) {
- return false;
- } catch (NoCurrentAccountSelectedException e) {
+ } catch (NextcloudFilesAppAccountNotFoundException | NoCurrentAccountSelectedException e) {
return false;
}
}
diff --git a/app/src/main/res/animator/appbar_elevation_off.xml b/app/src/main/res/animator/appbar_elevation_off.xml
new file mode 100644
index 00000000..d24dcb34
--- /dev/null
+++ b/app/src/main/res/animator/appbar_elevation_off.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item>
+ <objectAnimator
+ android:propertyName="elevation"
+ android:valueTo="0dp"
+ android:valueType="floatType" />
+ </item>
+</selector>
diff --git a/app/src/main/res/animator/appbar_elevation_on.xml b/app/src/main/res/animator/appbar_elevation_on.xml
new file mode 100644
index 00000000..6bd52cf3
--- /dev/null
+++ b/app/src/main/res/animator/appbar_elevation_on.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ tools:ignore="PrivateResource">
+ <item>
+ <objectAnimator
+ android:propertyName="elevation"
+ android:valueTo="@dimen/design_appbar_elevation"
+ android:valueType="floatType" />
+ </item>
+</selector>
diff --git a/app/src/main/res/drawable-night/border.xml b/app/src/main/res/drawable-night/border.xml
index 48ec3e9b..ab9d52ea 100644
--- a/app/src/main/res/drawable-night/border.xml
+++ b/app/src/main/res/drawable-night/border.xml
@@ -1,6 +1,8 @@
-<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
<solid android:color="@color/category_background" />
- <stroke android:width="1dip" android:color="@color/category_border"/>
- <corners
- android:radius="4dp" />
+ <stroke
+ android:width="1dip"
+ android:color="@color/category_border" />
+ <corners android:radius="4dp" />
</shape> \ No newline at end of file
diff --git a/app/src/main/res/drawable/border.xml b/app/src/main/res/drawable/border.xml
index 48ec3e9b..319814a6 100644
--- a/app/src/main/res/drawable/border.xml
+++ b/app/src/main/res/drawable/border.xml
@@ -1,6 +1,8 @@
-<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
- <solid android:color="@color/category_background" />
- <stroke android:width="1dip" android:color="@color/category_border"/>
- <corners
- android:radius="4dp" />
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <solid android:color="@android:color/transparent" />
+ <stroke
+ android:width="1dip"
+ android:color="@color/category_border" />
+ <corners android:radius="4dp" />
</shape> \ No newline at end of file
diff --git a/app/src/main/res/drawable/check.xml b/app/src/main/res/drawable/check.xml
new file mode 100644
index 00000000..4c6c6b76
--- /dev/null
+++ b/app/src/main/res/drawable/check.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@+id/area">
+ <shape android:shape="oval">
+ <solid android:color="@color/defaultBrand" />
+ <stroke
+ android:width="1dp"
+ android:color="@android:color/white" />
+ </shape>
+ </item>
+ <item android:drawable="@drawable/ic_check_white_24dp" />
+</layer-list> \ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_arrow_back_white_24dp.xml b/app/src/main/res/drawable/ic_arrow_back_grey600_24dp.xml
index cc2b6f53..99f77385 100644
--- a/app/src/main/res/drawable/ic_arrow_back_white_24dp.xml
+++ b/app/src/main/res/drawable/ic_arrow_back_grey600_24dp.xml
@@ -1,5 +1,5 @@
<vector android:autoMirrored="true" android:height="24dp"
- android:tint="#FFFFFF" android:viewportHeight="24.0"
+ android:tint="#757575" 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"/>
</vector>
diff --git a/app/src/main/res/drawable/ic_baseline_menu_24.xml b/app/src/main/res/drawable/ic_baseline_menu_24.xml
new file mode 100644
index 00000000..be2baed8
--- /dev/null
+++ b/app/src/main/res/drawable/ic_baseline_menu_24.xml
@@ -0,0 +1,5 @@
+<vector android:autoMirrored="true" android:height="24dp"
+ android:tint="#757575" 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="M3,18h18v-2L3,16v2zM3,13h18v-2L3,11v2zM3,6v2h18L21,6L3,6z"/>
+</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
new file mode 100644
index 00000000..65eff3fd
--- /dev/null
+++ b/app/src/main/res/drawable/ic_check_white_24dp.xml
@@ -0,0 +1,5 @@
+<vector android:height="24dp"
+ android:tint="#FFFFFF" 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_color_lens_grey600_24dp.xml b/app/src/main/res/drawable/ic_color_lens_grey600_24dp.xml
new file mode 100644
index 00000000..33db0157
--- /dev/null
+++ b/app/src/main/res/drawable/ic_color_lens_grey600_24dp.xml
@@ -0,0 +1,5 @@
+<vector android:autoMirrored="true" android:height="24dp"
+ android:tint="#757575" 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="M12,3c-4.97,0 -9,4.03 -9,9s4.03,9 9,9c0.83,0 1.5,-0.67 1.5,-1.5 0,-0.39 -0.15,-0.74 -0.39,-1.01 -0.23,-0.26 -0.38,-0.61 -0.38,-0.99 0,-0.83 0.67,-1.5 1.5,-1.5L16,16c2.76,0 5,-2.24 5,-5 0,-4.42 -4.03,-8 -9,-8zM6.5,12c-0.83,0 -1.5,-0.67 -1.5,-1.5S5.67,9 6.5,9 8,9.67 8,10.5 7.33,12 6.5,12zM9.5,8C8.67,8 8,7.33 8,6.5S8.67,5 9.5,5s1.5,0.67 1.5,1.5S10.33,8 9.5,8zM14.5,8c-0.83,0 -1.5,-0.67 -1.5,-1.5S13.67,5 14.5,5s1.5,0.67 1.5,1.5S15.33,8 14.5,8zM17.5,12c-0.83,0 -1.5,-0.67 -1.5,-1.5S16.67,9 17.5,9s1.5,0.67 1.5,1.5 -0.67,1.5 -1.5,1.5z"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_delete_white_24dp.xml b/app/src/main/res/drawable/ic_delete_white_24dp.xml
deleted file mode 100644
index 4d020aff..00000000
--- a/app/src/main/res/drawable/ic_delete_white_24dp.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<vector android:autoMirrored="true" android:height="24dp"
- android:tint="#FFFFFF" android:viewportHeight="24.0"
- android:viewportWidth="24.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="#FFFFFFFF" android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4z"/>
-</vector>
diff --git a/app/src/main/res/drawable/ic_edit_white_24dp.xml b/app/src/main/res/drawable/ic_edit_grey600_24dp.xml
index 5af858dd..1c520a99 100644
--- a/app/src/main/res/drawable/ic_edit_white_24dp.xml
+++ b/app/src/main/res/drawable/ic_edit_grey600_24dp.xml
@@ -1,5 +1,5 @@
<vector android:autoMirrored="true" android:height="24dp"
- android:tint="#FFFFFF" android:viewportHeight="24.0"
+ android:tint="#757575" android:viewportHeight="24.0"
android:viewportWidth="24.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FFFFFFFF" android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z"/>
</vector>
diff --git a/app/src/main/res/drawable/ic_eye_white_24dp.xml b/app/src/main/res/drawable/ic_eye_grey600_24dp.xml
index 2386233f..64cf84b1 100644
--- a/app/src/main/res/drawable/ic_eye_white_24dp.xml
+++ b/app/src/main/res/drawable/ic_eye_grey600_24dp.xml
@@ -1,5 +1,5 @@
<vector android:autoMirrored="true" android:height="24dp"
- android:tint="#FFFFFF" android:viewportHeight="24.0"
+ android:tint="#757575" android:viewportHeight="24.0"
android:viewportWidth="24.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FFFFFFFF" android:pathData="M12,4.5C7,4.5 2.73,7.61 1,12c1.73,4.39 6,7.5 11,7.5s9.27,-3.11 11,-7.5c-1.73,-4.39 -6,-7.5 -11,-7.5zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5zM12,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3 3,-1.34 3,-3 -1.34,-3 -3,-3z"/>
</vector>
diff --git a/app/src/main/res/drawable/ic_launcher_foreground_full.xml b/app/src/main/res/drawable/ic_launcher_foreground_full.xml
new file mode 100644
index 00000000..e3e1f1ac
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_foreground_full.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="108dp"
+ android:height="108dp"
+ android:viewportWidth="32"
+ android:viewportHeight="32">
+ <group android:translateX="0"
+ android:translateY="0">
+ <path
+ android:fillColor="#fff"
+ android:pathData="m24.484 3.5156c-1.0237 0-2.0471 0.38887-2.8281 1.1699l5.6582 5.6582c1.5621-1.5621 1.5621-4.0961 0-5.6582-0.78105-0.78105-1.8064-1.1699-2.8301-1.1699zm-4.2422 2.584-12.02 12.021 5.6562 5.6562 12.021-12.02-5.6582-5.6582zm-13.436 13.436-2.1211 7.7793 7.7793-2.1211-5.6582-5.6582z" />
+ </group>
+</vector> \ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_remove_red_eye_grey_24dp.xml b/app/src/main/res/drawable/ic_remove_red_eye_grey_24dp.xml
index dc85cfe3..d9b1702d 100644
--- a/app/src/main/res/drawable/ic_remove_red_eye_grey_24dp.xml
+++ b/app/src/main/res/drawable/ic_remove_red_eye_grey_24dp.xml
@@ -1,9 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
<path
android:fillColor="#FF757575"
- android:pathData="M12,4.5C7,4.5 2.73,7.61 1,12c1.73,4.39 6,7.5 11,7.5s9.27,-3.11 11,-7.5c-1.73,-4.39 -6,-7.5 -11,-7.5zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5zM12,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3 3,-1.34 3,-3 -1.34,-3 -3,-3z"/>
+ android:pathData="M12,4.5C7,4.5 2.73,7.61 1,12c1.73,4.39 6,7.5 11,7.5s9.27,-3.11 11,-7.5c-1.73,-4.39 -6,-7.5 -11,-7.5zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5zM12,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3 3,-1.34 3,-3 -1.34,-3 -3,-3z" />
</vector>
diff --git a/app/src/main/res/drawable/ic_search_grey600_24dp.xml b/app/src/main/res/drawable/ic_search_grey600_24dp.xml
new file mode 100644
index 00000000..d46f2cb3
--- /dev/null
+++ b/app/src/main/res/drawable/ic_search_grey600_24dp.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="#FF757575"
+ android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zM9.5,14C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z" />
+</vector>
diff --git a/app/src/main/res/drawable/ic_search_white_24dp.xml b/app/src/main/res/drawable/ic_search_white_24dp.xml
deleted file mode 100644
index 3e71206e..00000000
--- a/app/src/main/res/drawable/ic_search_white_24dp.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<vector android:height="24dp" android:tint="#FFFFFF"
- android:viewportHeight="24.0" android:viewportWidth="24.0"
- android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="#FFFFFFFF" android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zM9.5,14C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z"/>
-</vector>
diff --git a/app/src/main/res/drawable/ic_send_white_24dp.xml b/app/src/main/res/drawable/ic_send_grey600_24dp.xml
index 97dd32a4..08fdc123 100644
--- a/app/src/main/res/drawable/ic_send_white_24dp.xml
+++ b/app/src/main/res/drawable/ic_send_grey600_24dp.xml
@@ -1,5 +1,5 @@
<vector android:autoMirrored="true" android:height="24dp"
- android:tint="#FFFFFF" android:viewportHeight="24.0"
+ android:tint="#757575" 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="M2.01,21L23,12 2.01,3 2,10l15,2 -15,2z"/>
</vector>
diff --git a/app/src/main/res/drawable/splashscreen.xml b/app/src/main/res/drawable/splashscreen.xml
index e61ed69b..e6856ad7 100644
--- a/app/src/main/res/drawable/splashscreen.xml
+++ b/app/src/main/res/drawable/splashscreen.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="@drawable/ic_launcher_background" />
+ <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 3aac5851..8e6c0a2f 100644
--- a/app/src/main/res/layout/activity_about.xml
+++ b/app/src/main/res/layout/activity_about.xml
@@ -1,31 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
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"
android:orientation="vertical">
- <androidx.appcompat.widget.Toolbar
- android:id="@+id/toolbar"
+ <com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
- android:layout_height="?attr/actionBarSize"
- android:background="?attr/colorPrimary"
- android:theme="@style/toolbarStyle"
- app:contentInsetStartWithNavigation="0dp"
- app:elevation="4dp"
- app:navigationIcon="@drawable/ic_arrow_back_white_24dp"
- app:titleMarginStart="0dp"
- tools:title="@string/simple_about" />
+ android:layout_height="wrap_content">
- <com.google.android.material.tabs.TabLayout
- android:id="@+id/tabs"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
+ <androidx.appcompat.widget.Toolbar
+ 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_grey600_24dp"
+ app:titleMarginStart="0dp"
+ tools:title="@string/simple_about" />
+
+ <com.google.android.material.tabs.TabLayout
+ android:id="@+id/tabs"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ app:tabIndicatorColor="@color/defaultBrand"
+ android:background="?attr/colorPrimary" />
+ </com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager.widget.ViewPager
android:id="@+id/pager"
android:layout_width="match_parent"
- android:layout_height="wrap_content" />
+ android:layout_height="wrap_content"
+ android:background="?attr/colorPrimary" />
</LinearLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/activity_edit.xml b/app/src/main/res/layout/activity_edit.xml
index c01930b7..e7da04b0 100644
--- a/app/src/main/res/layout/activity_edit.xml
+++ b/app/src/main/res/layout/activity_edit.xml
@@ -1,26 +1,30 @@
<?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">
- <androidx.appcompat.widget.Toolbar
- android:id="@+id/toolbar"
+ <com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
- android:layout_height="?attr/actionBarSize"
- android:background="?attr/colorPrimary"
- android:theme="@style/toolbarStyle"
- app:contentInsetStartWithNavigation="0dp"
- app:elevation="4dp"
- app:navigationIcon="@drawable/ic_arrow_back_white_24dp"
- app:titleMarginStart="0dp"
- tools:title="Edit Sample note" />
+ android:layout_height="wrap_content">
+
+ <androidx.appcompat.widget.Toolbar
+ 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_grey600_24dp"
+ app:titleMarginStart="0dp"
+ tools:title="Edit Sample note" />
+ </com.google.android.material.appbar.AppBarLayout>
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragment_container_view"
android:layout_width="match_parent"
+ android:background="?attr/colorPrimary"
android:layout_height="match_parent" />
</LinearLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/activity_exception.xml b/app/src/main/res/layout/activity_exception.xml
index 37dc4bcb..e1e25491 100644
--- a/app/src/main/res/layout/activity_exception.xml
+++ b/app/src/main/res/layout/activity_exception.xml
@@ -4,6 +4,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:background="?attr/colorPrimary"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar
@@ -11,7 +12,6 @@
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
- android:theme="@style/toolbarStyle"
app:contentInsetStartWithNavigation="0dp"
app:elevation="4dp"
app:titleMarginStart="0dp"
@@ -30,12 +30,12 @@
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginStart="@dimen/spacer_2x"
- android:layout_marginLeft="16dp"
- android:layout_marginEnd="16dp"
- android:layout_marginRight="16dp"
+ android:layout_marginLeft="@dimen/spacer_2x"
+ android:layout_marginEnd="@dimen/spacer_2x"
+ android:layout_marginRight="@dimen/spacer_2x"
android:layout_weight="1"
android:background="@color/bg_highlighted"
- android:padding="8dp"
+ android:padding="@dimen/spacer_1x"
android:scrollbars="horizontal|vertical"
android:textIsSelectable="true"
android:typeface="monospace"
@@ -45,7 +45,7 @@
style="?android:buttonBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_margin="16dp"
+ android:layout_margin="@dimen/spacer_2x"
android:gravity="end"
android:orientation="horizontal"
android:weightSum="1.0">
@@ -56,7 +56,8 @@
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight=".5"
- android:text="@string/simple_close" />
+ android:text="@string/simple_close"
+ android:textColor="@color/defaultBrand" />
<Button
android:id="@+id/copy"
@@ -66,7 +67,7 @@
android:layout_marginTop="6dp"
android:layout_marginBottom="6dp"
android:layout_weight=".5"
- android:background="@color/primary"
+ android:background="@color/defaultBrand"
android:foreground="?attr/selectableItemBackground"
android:text="@string/simple_copy"
android:textColor="@color/fg_contrast"
diff --git a/app/src/main/res/layout/activity_manage_accounts.xml b/app/src/main/res/layout/activity_manage_accounts.xml
new file mode 100644
index 00000000..60e684cf
--- /dev/null
+++ b/app/src/main/res/layout/activity_manage_accounts.xml
@@ -0,0 +1,32 @@
+<?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"
+ android:background="?attr/colorPrimary"
+ android:orientation="vertical">
+
+ <com.google.android.material.appbar.AppBarLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <androidx.appcompat.widget.Toolbar
+ 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_grey600_24dp"
+ app:title="@string/manage_accounts"
+ app:titleMarginStart="0dp" />
+ </com.google.android.material.appbar.AppBarLayout>
+
+ <androidx.recyclerview.widget.RecyclerView
+ android:id="@+id/accounts"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
+ tools:listitem="@layout/item_account_choose" />
+
+</LinearLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/activity_note_list_configuration.xml b/app/src/main/res/layout/activity_note_list_configuration.xml
index bf14a9fe..061784e3 100644
--- a/app/src/main/res/layout/activity_note_list_configuration.xml
+++ b/app/src/main/res/layout/activity_note_list_configuration.xml
@@ -1,3 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView 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"
diff --git a/app/src/main/res/layout/activity_notes_list_view.xml b/app/src/main/res/layout/activity_notes_list_view.xml
index 2915f416..1b022607 100644
--- a/app/src/main/res/layout/activity_notes_list_view.xml
+++ b/app/src/main/res/layout/activity_notes_list_view.xml
@@ -11,23 +11,94 @@
android:layout_height="match_parent"
android:orientation="vertical">
- <androidx.appcompat.widget.Toolbar
- android:id="@+id/toolbar"
+ <com.google.android.material.appbar.AppBarLayout
+ android:id="@+id/app_bar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
- android:background="?attr/colorPrimary"
- android:theme="@style/toolbarStyle"
- app:contentInsetStartWithNavigation="0dp"
- app:elevation="4dp"
- app:titleMarginStart="0dp"
- tools:navigationIcon="@drawable/ic_arrow_back_white_24dp"
- tools:title="@string/app_name" />
+ app:elevation="0dp">
+
+ <androidx.appcompat.widget.Toolbar
+ android:id="@+id/toolbar"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="gone"
+ app:contentInsetStartWithNavigation="0dp"
+ app:navigationIcon="@drawable/ic_arrow_back_grey600_24dp"
+ app:titleMarginStart="0dp"
+ tools:title="@string/app_name">
+
+ <androidx.appcompat.widget.SearchView
+ android:id="@+id/search_view"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+ </androidx.appcompat.widget.Toolbar>
+
+ <com.google.android.material.card.MaterialCardView
+ android:id="@+id/home_toolbar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/spacer_1x"
+ android:layout_marginLeft="@dimen/spacer_1x"
+ android:layout_marginTop="@dimen/design_appbar_elevation"
+ android:layout_marginEnd="@dimen/spacer_1x"
+ android:layout_marginRight="@dimen/spacer_1x"
+ android:layout_marginBottom="@dimen/design_appbar_elevation"
+ app:cardCornerRadius="@dimen/spacer_1x"
+ app:cardElevation="6dp"
+ app:strokeWidth="0dp">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+
+ <androidx.appcompat.widget.AppCompatImageButton
+ android:id="@+id/menu_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:background="?attr/selectableItemBackgroundBorderless"
+ android:paddingStart="@dimen/spacer_1x"
+ android:paddingLeft="@dimen/spacer_1x"
+ android:paddingTop="@dimen/spacer_2x"
+ android:paddingEnd="@dimen/spacer_1x"
+ android:paddingRight="@dimen/spacer_1x"
+ android:paddingBottom="@dimen/spacer_2x"
+ android:tint="?attr/colorAccent"
+ app:srcCompat="@drawable/ic_baseline_menu_24" />
+
+ <com.google.android.material.textview.MaterialTextView
+ android:id="@+id/search_text"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_marginStart="@dimen/spacer_1x"
+ android:layout_marginLeft="@dimen/spacer_1x"
+ android:layout_marginEnd="@dimen/spacer_1x"
+ android:layout_marginRight="@dimen/spacer_1x"
+ android:layout_weight="1"
+ android:ellipsize="end"
+ android:gravity="start"
+ android:lines="1"
+ android:textSize="16sp"
+ tools:text="@string/search_in_all" />
+
+ <androidx.appcompat.widget.AppCompatImageView
+ android:id="@+id/launchAccountSwitcher"
+ android:layout_width="?attr/actionBarSize"
+ android:layout_height="?attr/actionBarSize"
+ android:layout_gravity="center_vertical|end"
+ android:background="?attr/selectableItemBackgroundBorderless"
+ android:padding="12dp"
+ app:srcCompat="@drawable/ic_account_circle_grey_24dp" />
+ </LinearLayout>
+
+ </com.google.android.material.card.MaterialCardView>
+ </com.google.android.material.appbar.AppBarLayout>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/swiperefreshlayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="@color/bg_normal"
tools:context="it.niedermann.owncloud.notes.android.activity.NotesListViewActivity">
<FrameLayout
@@ -43,13 +114,14 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
+ android:indeterminateTint="@color/defaultBrand"
+ tools:targetApi="lollipop"
tools:visibility="gone" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:background="@color/bg_highlighted"
android:scrollbars="vertical"
tools:listitem="@layout/item_notes_list_note_item" />
</FrameLayout>
@@ -61,7 +133,6 @@
android:id="@+id/fab_create"
style="@style/fab"
android:title="@string/action_create"
- app:backgroundTint="@color/primary"
- app:rippleColor="@color/primary_dark"
+ app:backgroundTint="@color/defaultBrand"
app:srcCompat="@drawable/ic_add_white_24dp" />
</androidx.coordinatorlayout.widget.CoordinatorLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/activity_preferences.xml b/app/src/main/res/layout/activity_preferences.xml
index a8e43cc1..10b8089e 100644
--- a/app/src/main/res/layout/activity_preferences.xml
+++ b/app/src/main/res/layout/activity_preferences.xml
@@ -5,21 +5,25 @@
android:layout_height="match_parent"
android:orientation="vertical">
- <androidx.appcompat.widget.Toolbar
- android:id="@+id/toolbar"
+ <com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
- android:layout_height="?attr/actionBarSize"
- android:background="?attr/colorPrimary"
- android:theme="@style/toolbarStyle"
- app:contentInsetStartWithNavigation="0dp"
- app:elevation="4dp"
- app:navigationIcon="@drawable/ic_arrow_back_white_24dp"
- app:title="@string/action_settings"
- app:titleMarginStart="0dp" />
+ android:layout_height="wrap_content">
+
+ <androidx.appcompat.widget.Toolbar
+ 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_grey600_24dp"
+ app:title="@string/action_settings"
+ app:titleMarginStart="0dp" />
+ </com.google.android.material.appbar.AppBarLayout>
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragment_container_view"
android:layout_width="match_parent"
- android:layout_height="match_parent" />
+ android:layout_height="match_parent"
+ android:background="?attr/colorPrimary" />
</LinearLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/dialog_account_switcher.xml b/app/src/main/res/layout/dialog_account_switcher.xml
new file mode 100644
index 00000000..f5260947
--- /dev/null
+++ b/app/src/main/res/layout/dialog_account_switcher.xml
@@ -0,0 +1,139 @@
+<?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"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:id="@+id/accountLayout"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="?attr/selectableItemBackground"
+ android:orientation="horizontal"
+ android:padding="@dimen/spacer_3x">
+
+ <androidx.appcompat.widget.AppCompatImageView
+ android:id="@+id/currentAccountItemAvatar"
+ android:layout_width="36dp"
+ android:layout_height="36dp"
+ android:contentDescription="@null"
+ android:focusable="false"
+ android:scaleType="center"
+ app:srcCompat="@drawable/ic_account_circle_grey_24dp" />
+
+ <TextView
+ android:id="@+id/accountItemLabel"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:layout_marginStart="@dimen/spacer_2x"
+ android:layout_marginLeft="@dimen/spacer_2x"
+ android:layout_marginEnd="@dimen/spacer_2x"
+ android:layout_marginRight="@dimen/spacer_2x"
+ android:layout_weight="1"
+ android:ellipsize="middle"
+ android:singleLine="true"
+ android:textAppearance="@style/TextAppearance.AppCompat.Widget.TextView.SpinnerItem"
+ android:textColor="?android:textColorPrimary"
+ tools:text="@tools:sample/full_names" />
+
+ <androidx.appcompat.widget.AppCompatImageView
+ android:id="@+id/check"
+ android:layout_width="36dp"
+ android:layout_height="36dp"
+ android:contentDescription="@null"
+ android:focusable="false"
+ android:scaleType="center"
+ app:srcCompat="@drawable/check" />
+ </LinearLayout>
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:background="@color/fg_default_high" />
+
+ <androidx.recyclerview.widget.RecyclerView
+ android:id="@+id/accounts_list"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="0dp"
+ android:scrollbarStyle="outsideOverlay"
+ android:scrollbars="vertical"
+ app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
+ tools:itemCount="3"
+ tools:listitem="@layout/item_account_choose" />
+
+ <LinearLayout
+ android:id="@+id/add_account"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="?attr/selectableItemBackground"
+ android:orientation="horizontal"
+ android:paddingStart="@dimen/spacer_3x"
+ android:paddingLeft="@dimen/spacer_3x"
+ android:paddingTop="@dimen/spacer_1x"
+ android:paddingEnd="@dimen/spacer_3x"
+ android:paddingRight="@dimen/spacer_3x"
+ android:paddingBottom="@dimen/spacer_1x">
+
+ <androidx.appcompat.widget.AppCompatImageView
+ android:layout_width="36dp"
+ android:layout_height="36dp"
+ android:contentDescription="@null"
+ android:focusable="false"
+ android:scaleType="center"
+ app:srcCompat="@drawable/ic_person_add_grey600_24dp" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:layout_marginStart="@dimen/spacer_2x"
+ android:layout_marginLeft="@dimen/spacer_2x"
+ android:ellipsize="middle"
+ android:singleLine="true"
+ android:text="@string/add_account"
+ android:textAppearance="@style/TextAppearance.AppCompat.Widget.TextView.SpinnerItem"
+ android:textColor="?android:textColorPrimary" />
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:id="@+id/manage_accounts"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="@dimen/spacer_2x"
+ android:background="?attr/selectableItemBackground"
+ android:orientation="horizontal"
+ android:paddingStart="@dimen/spacer_3x"
+ android:paddingLeft="@dimen/spacer_3x"
+ android:paddingTop="@dimen/spacer_1x"
+ android:paddingEnd="@dimen/spacer_3x"
+ android:paddingRight="@dimen/spacer_3x"
+ android:paddingBottom="@dimen/spacer_1x">
+
+ <androidx.appcompat.widget.AppCompatImageView
+ android:layout_width="36dp"
+ android:layout_height="36dp"
+ android:contentDescription="@null"
+ android:focusable="false"
+ android:scaleType="center"
+ app:srcCompat="@drawable/ic_settings_grey600_24dp" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:layout_marginStart="@dimen/spacer_2x"
+ android:layout_marginLeft="@dimen/spacer_2x"
+ android:ellipsize="middle"
+ android:singleLine="true"
+ android:text="@string/manage_accounts"
+ android:textAppearance="@style/TextAppearance.AppCompat.Widget.TextView.SpinnerItem"
+ android:textColor="?android:textColorPrimary" />
+
+ </LinearLayout>
+</LinearLayout>
+
diff --git a/app/src/main/res/layout/dialog_change_category.xml b/app/src/main/res/layout/dialog_change_category.xml
index a73a32e9..86243c23 100644
--- a/app/src/main/res/layout/dialog_change_category.xml
+++ b/app/src/main/res/layout/dialog_change_category.xml
@@ -5,21 +5,16 @@
android:id="@+id/editCategoryLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:orientation="vertical">
+ android:orientation="vertical"
+ android:padding="?attr/dialogPreferredPadding">
- <com.google.android.material.textfield.TextInputLayout
+ <EditText
+ android:id="@+id/search"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:padding="16dp">
-
- <EditText
- android:id="@+id/search"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:hint="@string/change_category_title"
- android:importantForAutofill="no"
- android:inputType="text" />
- </com.google.android.material.textfield.TextInputLayout>
+ android:hint="@string/change_category_title"
+ android:importantForAutofill="no"
+ android:inputType="text" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
diff --git a/app/src/main/res/layout/dialog_exception.xml b/app/src/main/res/layout/dialog_exception.xml
index c5327464..875605ac 100644
--- a/app/src/main/res/layout/dialog_exception.xml
+++ b/app/src/main/res/layout/dialog_exception.xml
@@ -47,7 +47,7 @@
android:layout_marginBottom="@dimen/spacer_2x"
android:layout_weight="1"
android:background="@color/bg_highlighted"
- android:padding="8dp"
+ android:padding="@dimen/spacer_1x"
android:scrollbars="horizontal|vertical"
android:textIsSelectable="true"
android:typeface="monospace"
diff --git a/app/src/main/res/layout/drawer_layout.xml b/app/src/main/res/layout/drawer_layout.xml
index 74419fd9..ec445d1c 100644
--- a/app/src/main/res/layout/drawer_layout.xml
+++ b/app/src/main/res/layout/drawer_layout.xml
@@ -5,7 +5,6 @@
android:id="@+id/drawerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:fitsSystemWindows="true"
tools:openDrawer="left">
<include
@@ -23,7 +22,8 @@
<androidx.core.widget.NestedScrollView
android:id="@+id/scrollView"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ android:background="?attr/colorPrimary">
<LinearLayout
android:layout_width="match_parent"
@@ -33,120 +33,53 @@
<RelativeLayout
android:id="@+id/header_view"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:background="?attr/colorPrimary"
- android:theme="@style/ThemeOverlay.AppCompat.Dark">
-
- <androidx.appcompat.widget.AppCompatImageView
- android:layout_width="match_parent"
- android:layout_height="164dp"
- android:contentDescription="@null"
- android:scaleType="centerCrop"
- app:srcCompat="@drawable/background" />
+ android:layout_height="@dimen/drawer_header_height"
+ android:background="@color/defaultBrand">
<androidx.appcompat.widget.AppCompatImageView
- android:id="@+id/current_account_image"
- android:layout_width="@dimen/avatar_size"
- android:layout_height="@dimen/avatar_size"
- android:layout_gravity="center_vertical"
- android:layout_marginStart="@dimen/header_padding"
- android:layout_marginLeft="@dimen/header_padding"
- android:layout_marginTop="46dp"
- android:contentDescription="@string/app_name"
- app:srcCompat="@mipmap/ic_launcher" />
+ android:id="@+id/logo"
+ android:layout_width="@dimen/drawer_header_logo_size"
+ android:layout_height="@dimen/drawer_header_logo_size"
+ android:layout_centerVertical="true"
+ android:layout_margin="@dimen/spacer_2x"
+ android:gravity="center"
+ app:srcCompat="@drawable/ic_launcher_foreground_full" />
<TextView
android:id="@+id/app_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_below="@id/current_account_image"
- android:layout_marginTop="6dp"
- android:layout_marginStart="@dimen/header_padding"
- android:layout_marginLeft="@dimen/header_padding"
- android:layout_marginEnd="@dimen/header_padding"
- android:layout_marginRight="@dimen/header_padding"
- android:ellipsize="end"
- android:shadowColor="@android:color/black"
- android:shadowDx="0.5"
- android:shadowDy="0"
- android:shadowRadius="2"
- android:text="@string/app_name_long"
- android:textColor="@android:color/white"
- android:textSize="14sp"
- android:textStyle="bold" />
-
- <TextView
- android:id="@+id/account"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_below="@+id/app_name"
- android:layout_marginStart="@dimen/header_padding"
- android:layout_marginLeft="@dimen/header_padding"
- android:layout_marginEnd="@dimen/widget_margin"
- android:layout_marginRight="@dimen/widget_margin"
+ android:layout_centerVertical="true"
+ android:layout_toEndOf="@id/logo"
+ android:layout_toRightOf="@id/logo"
android:ellipsize="end"
- android:maxLines="1"
- android:shadowColor="@android:color/black"
- android:layout_alignParentStart="true"
- android:layout_toStartOf="@id/account_arrow"
- android:shadowDx="0.5"
- android:shadowDy="0"
- android:shadowRadius="2"
+ android:fontFamily="sans-serif-light"
+ android:gravity="center_vertical"
+ android:text="@string/app_name"
android:textColor="@android:color/white"
- android:textSize="12sp"
- tools:text="user@nextcloud.example.comuser@nextcloud.example.comuser@nextcloud.example.com"
- android:layout_alignParentLeft="true"
- android:layout_toLeftOf="@id/account_arrow" />
-
- <androidx.appcompat.widget.AppCompatImageView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:id="@+id/account_arrow"
- app:srcCompat="@drawable/ic_arrow_drop_down_white_24dp"
- android:layout_alignParentEnd="true"
- android:layout_alignBottom="@+id/account"
- android:layout_marginEnd="@dimen/header_padding"
- android:layout_alignParentRight="true"
- android:layout_marginRight="@dimen/header_padding" />
+ android:textSize="24sp" />
</RelativeLayout>
- <LinearLayout
- android:id="@+id/accountNavigation"
+ <androidx.recyclerview.widget.RecyclerView
+ android:id="@+id/navigationList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="vertical">
-
- <androidx.recyclerview.widget.RecyclerView
- android:id="@+id/navigationList"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingTop="8dp"
- android:paddingBottom="8dp"
- app:layoutManager="LinearLayoutManager"
- tools:listitem="@layout/item_navigation" />
-
- <androidx.recyclerview.widget.RecyclerView
- android:id="@+id/navigationMenu"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingTop="8dp"
- android:paddingBottom="8dp"
- app:layoutManager="LinearLayoutManager"
- tools:listitem="@layout/item_navigation" />
- </LinearLayout>
-
- <LinearLayout
- android:id="@+id/accountChooser"
+ android:paddingTop="@dimen/spacer_1x"
+ android:paddingBottom="@dimen/spacer_1x"
+ app:layoutManager="LinearLayoutManager"
+ tools:itemCount="6"
+ tools:listitem="@layout/item_navigation" />
+
+ <androidx.recyclerview.widget.RecyclerView
+ android:id="@+id/navigationMenu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:paddingTop="8dp"
- android:paddingBottom="8dp"
- android:orientation="vertical"
- android:visibility="gone"/>
+ android:paddingTop="@dimen/spacer_1x"
+ android:paddingBottom="@dimen/spacer_1x"
+ app:layoutManager="LinearLayoutManager"
+ tools:itemCount="3"
+ tools:listitem="@layout/item_navigation" />
</LinearLayout>
-
</androidx.core.widget.NestedScrollView>
-
</com.google.android.material.navigation.NavigationView>
-
</androidx.drawerlayout.widget.DrawerLayout> \ No newline at end of file
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 c57c88ed..6afaa763 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">
@@ -22,17 +23,19 @@
android:padding="10dp"
android:text="@string/about_app_license" />
- <Button
+ <com.google.android.material.button.MaterialButton
android:id="@+id/about_app_license_button"
+ 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"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginTop="16dp"
+ android:layout_marginTop="@dimen/spacer_2x"
android:text="@string/about_icons_disclaimer_title" />
<TextView
diff --git a/app/src/main/res/layout/fragment_note_edit.xml b/app/src/main/res/layout/fragment_note_edit.xml
index 954351b0..1c0417d2 100644
--- a/app/src/main/res/layout/fragment_note_edit.xml
+++ b/app/src/main/res/layout/fragment_note_edit.xml
@@ -3,7 +3,8 @@
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">
+ android:layout_height="match_parent"
+ tools:background="?attr/colorPrimary">
<ScrollView
android:id="@+id/scrollView"
@@ -17,12 +18,12 @@
android:id="@+id/editContent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:background="@null"
android:ems="10"
android:gravity="top"
android:inputType="textMultiLine|textCapSentences"
- android:padding="16dp"
+ android:padding="@dimen/spacer_2x"
android:textColor="@color/fg_default"
+ android:theme="@style/textViewStyle"
tools:text="@tools:sample/lorem/random" />
</ScrollView>
@@ -32,6 +33,7 @@
android:layout_gravity="bottom|end"
android:translationY="-56dp"
android:visibility="gone"
+ app:backgroundTint="@color/defaultBrand"
app:fabSize="mini"
app:srcCompat="@drawable/ic_keyboard_arrow_up_white_24dp"
tools:visibility="visible" />
@@ -41,6 +43,7 @@
style="@style/fab"
android:layout_gravity="bottom|end"
android:visibility="gone"
+ app:backgroundTint="@color/defaultBrand"
app:fabSize="mini"
app:srcCompat="@drawable/ic_keyboard_arrow_down_white_24dp"
tools:visibility="visible" />
diff --git a/app/src/main/res/layout/fragment_note_preview.xml b/app/src/main/res/layout/fragment_note_preview.xml
index 0e81b33e..d841f3c2 100644
--- a/app/src/main/res/layout/fragment_note_preview.xml
+++ b/app/src/main/res/layout/fragment_note_preview.xml
@@ -3,13 +3,13 @@
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">
+ android:layout_height="match_parent"
+ tools:background="?attr/colorPrimary">
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/swiperefreshlayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="@color/bg_normal"
tools:context="it.niedermann.owncloud.notes.android.activity.NotesListViewActivity"
tools:ignore="MergeRootFrame">
@@ -24,11 +24,11 @@
android:id="@+id/single_note_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:background="@color/bg_normal"
- android:padding="16dp"
+ android:padding="@dimen/spacer_2x"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@color/fg_default"
android:textIsSelectable="true"
+ android:theme="@style/textViewStyle"
tools:text="@tools:sample/lorem/random" />
</ScrollView>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
@@ -39,6 +39,7 @@
android:layout_gravity="bottom|end"
android:translationY="-56dp"
android:visibility="gone"
+ app:backgroundTint="@color/defaultBrand"
app:fabSize="mini"
app:srcCompat="@drawable/ic_keyboard_arrow_up_white_24dp"
tools:visibility="visible" />
@@ -48,6 +49,7 @@
style="@style/fab"
android:layout_gravity="bottom|end"
android:visibility="gone"
+ app:backgroundTint="@color/defaultBrand"
app:fabSize="mini"
app:srcCompat="@drawable/ic_keyboard_arrow_down_white_24dp"
tools:visibility="visible" />
diff --git a/app/src/main/res/layout/item_account.xml b/app/src/main/res/layout/item_account.xml
index ac14985b..18c6f52e 100644
--- a/app/src/main/res/layout/item_account.xml
+++ b/app/src/main/res/layout/item_account.xml
@@ -6,8 +6,8 @@
android:background="?attr/selectableItemBackground"
android:paddingLeft="6dp"
android:paddingStart="6dp"
- android:paddingRight="8dp"
- android:paddingEnd="8dp">
+ android:paddingRight="@dimen/spacer_1x"
+ android:paddingEnd="@dimen/spacer_1x">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/accountItemAvatar"
diff --git a/app/src/main/res/layout/item_account_choose.xml b/app/src/main/res/layout/item_account_choose.xml
index fc4899aa..33abe594 100644
--- a/app/src/main/res/layout/item_account_choose.xml
+++ b/app/src/main/res/layout/item_account_choose.xml
@@ -5,28 +5,60 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
- android:padding="24dp"
- android:orientation="horizontal">
+ android:orientation="horizontal"
+ android:padding="@dimen/spacer_3x">
- <androidx.appcompat.widget.AppCompatImageView
- android:id="@+id/accountItemAvatar"
- android:layout_width="32dp"
- android:layout_height="32dp"
- android:scaleType="center"
- android:focusable="false"
- app:srcCompat="@drawable/ic_account_circle_grey_24dp"
- android:contentDescription="@null" />
+ <FrameLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="@dimen/spacer_1hx"
+ android:layout_marginRight="@dimen/spacer_1hx">
+
+ <androidx.appcompat.widget.AppCompatImageView
+ android:id="@+id/accountItemAvatar"
+ android:layout_width="36dp"
+ android:layout_height="36dp"
+ android:contentDescription="@null"
+ android:focusable="false"
+ android:scaleType="center"
+ app:srcCompat="@drawable/ic_account_circle_grey_24dp" />
+
+ <androidx.appcompat.widget.AppCompatImageView
+ android:id="@+id/currentAccountIndicator"
+ android:layout_width="12dp"
+ android:layout_height="12dp"
+ android:layout_gravity="end|bottom"
+ android:visibility="gone"
+ app:srcCompat="@drawable/check"
+ tools:visibility="visible" />
+ </FrameLayout>
<TextView
android:id="@+id/accountItemLabel"
+ android:layout_width="0dp"
android:layout_height="wrap_content"
- android:layout_width="wrap_content"
android:layout_gravity="center"
+ android:layout_marginStart="@dimen/spacer_2x"
+ android:layout_marginLeft="@dimen/spacer_2x"
+ android:layout_marginEnd="@dimen/spacer_2x"
+ android:layout_marginRight="@dimen/spacer_2x"
+ android:layout_weight="1"
android:ellipsize="middle"
android:singleLine="true"
- android:layout_marginLeft="16dp"
- android:layout_marginStart="16dp"
+ android:textAppearance="@style/TextAppearance.AppCompat.Widget.TextView.SpinnerItem"
android:textColor="?android:textColorPrimary"
- tools:hint="Username"/>
+ tools:text="@tools:sample/full_names" />
+
-</LinearLayout> \ No newline at end of file
+ <androidx.appcompat.widget.AppCompatImageView
+ android:id="@+id/delete"
+ android:layout_width="36dp"
+ android:layout_height="36dp"
+ android:background="?attr/selectableItemBackgroundBorderless"
+ android:contentDescription="@null"
+ android:focusable="false"
+ android:scaleType="center"
+ android:visibility="gone"
+ app:srcCompat="@drawable/ic_delete_grey600_24dp"
+ tools:visibility="visible" />
+</LinearLayout>
diff --git a/app/src/main/res/layout/item_category.xml b/app/src/main/res/layout/item_category.xml
index 95c76732..b23a6e3f 100644
--- a/app/src/main/res/layout/item_category.xml
+++ b/app/src/main/res/layout/item_category.xml
@@ -7,14 +7,14 @@
android:background="?android:selectableItemBackground"
android:clickable="true"
android:focusable="true"
- android:padding="16dp">
+ android:padding="@dimen/spacer_2x">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginEnd="16dp"
- android:layout_marginRight="16dp"
+ android:layout_marginEnd="@dimen/spacer_2x"
+ android:layout_marginRight="@dimen/spacer_2x"
android:contentDescription="@null"
android:focusable="false"
android:scaleType="center"
@@ -36,8 +36,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|end"
- android:layout_marginStart="16dp"
- android:layout_marginLeft="16dp"
+ android:layout_marginStart="@dimen/spacer_2x"
+ android:layout_marginLeft="@dimen/spacer_2x"
android:textColor="@color/fg_default"
tools:text="23" />
</LinearLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/item_navigation.xml b/app/src/main/res/layout/item_navigation.xml
index 65fb4438..e1dc16e8 100644
--- a/app/src/main/res/layout/item_navigation.xml
+++ b/app/src/main/res/layout/item_navigation.xml
@@ -1,12 +1,13 @@
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<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"
- android:paddingStart="6dp"
- android:paddingLeft="6dp"
- android:paddingEnd="8dp"
- android:paddingRight="8dp">
+ android:gravity="center_vertical"
+ android:paddingStart="@dimen/spacer_1x"
+ android:paddingLeft="@dimen/spacer_1x"
+ android:paddingEnd="@dimen/spacer_1x"
+ android:paddingRight="@dimen/spacer_1x">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/navigationItemIcon"
@@ -14,33 +15,26 @@
android:layout_height="44dp"
android:contentDescription="@null"
android:focusable="false"
- android:padding="10dp"
android:scaleType="center"
app:srcCompat="@drawable/ic_folder_grey600_24dp" />
<TextView
- android:id="@+id/navigationItemCount"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentEnd="true"
- android:layout_alignParentRight="true"
- android:layout_centerVertical="true"
- android:padding="8dp"
- android:textColor="?android:textColorPrimary"
- tools:text="37" />
-
- <TextView
android:id="@+id/navigationItemLabel"
- android:layout_width="match_parent"
+ android:layout_width="0dp"
android:layout_height="wrap_content"
- android:layout_centerVertical="true"
- android:layout_marginStart="64dp"
- android:layout_marginLeft="64dp"
- android:layout_toStartOf="@id/navigationItemCount"
- android:layout_toLeftOf="@id/navigationItemCount"
+ android:layout_marginStart="@dimen/spacer_1x"
+ android:layout_marginLeft="@dimen/spacer_1x"
+ android:layout_weight="1"
android:ellipsize="end"
android:lines="1"
android:textColor="?android:textColorSecondary"
- tools:text="Category 1" />
+ tools:text="@tools:sample/lorem/random" />
-</RelativeLayout> \ No newline at end of file
+ <TextView
+ android:id="@+id/navigationItemCount"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="@dimen/spacer_1x"
+ android:textColor="?android:textColorPrimary"
+ tools:text="37" />
+</LinearLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/item_notes_list_note_item.xml b/app/src/main/res/layout/item_notes_list_note_item.xml
index 61ad02fc..ba88af2a 100644
--- a/app/src/main/res/layout/item_notes_list_note_item.xml
+++ b/app/src/main/res/layout/item_notes_list_note_item.xml
@@ -12,8 +12,8 @@
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_gravity="center_vertical"
- android:layout_marginLeft="@dimen/button_padding"
android:layout_marginStart="@dimen/button_padding"
+ android:layout_marginLeft="@dimen/button_padding"
android:contentDescription="@string/menu_favorite"
app:srcCompat="@drawable/ic_star_white_24dp" />
@@ -34,42 +34,43 @@
android:background="@drawable/list_item_background_selector">
<FrameLayout
- android:layout_centerVertical="true"
android:layout_width="wrap_content"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ android:layout_centerVertical="true">
<ImageView
android:id="@+id/noteFavorite"
- android:contentDescription="@string/menu_favorite"
- android:padding="16dp"
android:layout_width="wrap_content"
android:layout_height="match_parent"
- tools:src="@drawable/ic_star_yellow_24dp"/>
+ android:background="?attr/selectableItemBackgroundBorderless"
+ android:contentDescription="@string/menu_favorite"
+ android:padding="@dimen/spacer_2x"
+ tools:src="@drawable/ic_star_yellow_24dp" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/noteStatus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical|end"
+ android:layout_marginTop="12dp"
android:layout_marginEnd="4dp"
android:layout_marginRight="4dp"
- android:layout_marginTop="12dp"
- android:layout_gravity="center_vertical|end"
android:baseline="14dp"
app:srcCompat="@drawable/ic_sync_blue_18dp" />
</FrameLayout>
<androidx.appcompat.widget.LinearLayoutCompat
- android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:paddingTop="16dp"
- android:paddingRight="16dp"
- android:paddingEnd="16dp"
- android:paddingLeft="0dp"
+ android:layout_weight="1"
+ android:orientation="vertical"
android:paddingStart="0dp"
- android:paddingBottom="16dp"
- android:orientation="vertical">
+ android:paddingLeft="0dp"
+ android:paddingTop="@dimen/spacer_2x"
+ android:paddingEnd="@dimen/spacer_2x"
+ android:paddingRight="@dimen/spacer_2x"
+ android:paddingBottom="@dimen/spacer_2x">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
@@ -79,12 +80,12 @@
android:id="@+id/noteTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_weight="1"
android:ellipsize="end"
android:maxLines="1"
- android:layout_weight="1"
- android:textSize="@dimen/primary_font_size"
android:textColor="?android:textColorPrimary"
- tools:text="@tools:sample/lorem/random"/>
+ android:textSize="@dimen/primary_font_size"
+ tools:text="@tools:sample/lorem/random" />
</androidx.appcompat.widget.LinearLayoutCompat>
@@ -96,34 +97,35 @@
android:id="@+id/noteExcerpt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
+ android:layout_alignParentLeft="true"
+ android:layout_weight="1"
android:ellipsize="end"
android:maxLines="1"
- android:paddingBottom="1dp"
android:paddingTop="1dp"
- android:layout_weight="1"
+ android:paddingBottom="1dp"
android:textSize="@dimen/secondary_font_size"
- tools:text="@tools:sample/lorem/random"/>
+ tools:text="@tools:sample/lorem/random" />
<TextView
android:id="@+id/noteCategory"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
+ android:layout_alignParentRight="true"
+ android:layout_marginStart="@dimen/spacer_1x"
+ android:layout_marginLeft="@dimen/spacer_1x"
android:background="@drawable/border"
android:maxLines="1"
- android:paddingBottom="1dp"
- android:paddingLeft="8dp"
- android:paddingRight="8dp"
+ android:paddingLeft="@dimen/spacer_1x"
android:paddingTop="1dp"
- android:layout_marginStart="8dp"
- android:layout_marginLeft="8dp"
+ android:paddingRight="@dimen/spacer_1x"
+ android:paddingBottom="1dp"
android:singleLine="true"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/secondary_font_size"
- tools:text="@string/category_work"/>
+ tools:maxLength="15"
+ tools:text="@tools:sample/lorem/random" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
diff --git a/app/src/main/res/layout/item_notes_list_section_item.xml b/app/src/main/res/layout/item_notes_list_section_item.xml
index 68af3740..6e20555c 100644
--- a/app/src/main/res/layout/item_notes_list_section_item.xml
+++ b/app/src/main/res/layout/item_notes_list_section_item.xml
@@ -1,28 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content">
-
- <TextView
- android:id="@+id/sectionTitle"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentEnd="false"
- android:layout_alignParentRight="true"
- android:layout_alignParentStart="true"
- android:layout_alignParentLeft="true"
- android:layout_alignParentTop="true"
- android:layout_alignWithParentIfMissing="true"
- android:background="@color/bg_normal"
- android:ellipsize="end"
- android:gravity="center_vertical"
- android:paddingBottom="8dp"
- android:paddingLeft="56dp"
- android:paddingStart="56dp"
- android:paddingRight="16dp"
- android:paddingEnd="16dp"
- android:paddingTop="48dp"
- android:textColor="@color/fg_default_selection"
- android:textSize="@dimen/secondary_font_size"
- android:hint="@string/listview_updated_yesterday"/>
-</RelativeLayout> \ No newline at end of file
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/sectionTitle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignWithParentIfMissing="true"
+ android:layout_alignParentStart="true"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentEnd="false"
+ android:layout_alignParentRight="true"
+ android:background="@color/bg_normal"
+ android:ellipsize="end"
+ android:gravity="center_vertical"
+ android:hint="@string/listview_updated_yesterday"
+ android:paddingStart="56dp"
+ android:paddingLeft="56dp"
+ android:paddingTop="48dp"
+ android:paddingEnd="@dimen/spacer_2x"
+ android:paddingRight="@dimen/spacer_2x"
+ android:paddingBottom="@dimen/spacer_1x"
+ android:textColor="@color/fg_default_selection"
+ android:textSize="@dimen/secondary_font_size" /> \ No newline at end of file
diff --git a/app/src/main/res/layout/item_pref.xml b/app/src/main/res/layout/item_pref.xml
index 8237bdad..48d035ef 100644
--- a/app/src/main/res/layout/item_pref.xml
+++ b/app/src/main/res/layout/item_pref.xml
@@ -11,7 +11,7 @@
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:contentDescription="@null"
- android:padding="16dp"
+ android:padding="@dimen/spacer_2x"
tools:src="@drawable/ic_settings_grey600_24dp" />
<LinearLayout
@@ -22,7 +22,6 @@
android:orientation="vertical"
tools:ignore="RtlSymmetry">
-
<TextView
android:id="@android:id/title"
android:layout_width="wrap_content"
@@ -49,6 +48,6 @@
android:layout_height="match_parent"
android:gravity="center_vertical"
android:orientation="vertical"
- android:padding="16dp" />
+ android:padding="@dimen/spacer_2x" />
</LinearLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/item_preference_category.xml b/app/src/main/res/layout/item_preference_category.xml
new file mode 100644
index 00000000..4580a438
--- /dev/null
+++ b/app/src/main/res/layout/item_preference_category.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@android:id/title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="56dp"
+ android:paddingLeft="56dp"
+ android:paddingTop="@dimen/spacer_3x"
+ android:paddingEnd="0dp"
+ android:paddingRight="0dp"
+ tools:text="@tools:sample/lorem" />
diff --git a/app/src/main/res/menu/menu_list_context_multiple.xml b/app/src/main/res/menu/menu_list_context_multiple.xml
index b31ae774..9e44a799 100644
--- a/app/src/main/res/menu/menu_list_context_multiple.xml
+++ b/app/src/main/res/menu/menu_list_context_multiple.xml
@@ -11,14 +11,14 @@
<item
android:id="@+id/menu_delete"
- android:icon="@drawable/ic_delete_white_24dp"
+ android:icon="@drawable/ic_delete_grey600_24dp"
android:orderInCategory="100"
android:title="@string/menu_delete"
app:showAsAction="ifRoom" />
<item
android:id="@+id/menu_move"
- android:icon="@drawable/ic_send_white_24dp"
+ android:icon="@drawable/ic_send_grey600_24dp"
android:orderInCategory="110"
android:title="@string/simple_move"
app:showAsAction="ifRoom" />
diff --git a/app/src/main/res/menu/menu_list_view.xml b/app/src/main/res/menu/menu_list_view.xml
deleted file mode 100644
index 70103414..00000000
--- a/app/src/main/res/menu/menu_list_view.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<menu xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- xmlns:tools="http://schemas.android.com/tools"
- tools:context="com.example.owncloudnotes.NotesListViewActivity">
- <item
- android:id="@+id/search"
- android:title="@string/action_search"
- android:icon="@drawable/ic_search_white_24dp"
- app:actionViewClass="androidx.appcompat.widget.SearchView"
- app:showAsAction="collapseActionView|always" />
-</menu> \ No newline at end of file
diff --git a/app/src/main/res/menu/menu_note_activity.xml b/app/src/main/res/menu/menu_note_activity.xml
index 311c5108..967bb4f0 100644
--- a/app/src/main/res/menu/menu_note_activity.xml
+++ b/app/src/main/res/menu/menu_note_activity.xml
@@ -3,13 +3,13 @@
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/menu_preview"
- android:icon="@drawable/ic_eye_white_24dp"
+ android:icon="@drawable/ic_eye_grey600_24dp"
android:orderInCategory="60"
android:title="@string/menu_preview"
app:showAsAction="ifRoom" />
<item
android:id="@+id/menu_edit"
- android:icon="@drawable/ic_edit_white_24dp"
+ android:icon="@drawable/ic_edit_grey600_24dp"
android:orderInCategory="60"
android:title="@string/simple_edit"
app:showAsAction="ifRoom" />
diff --git a/app/src/main/res/menu/menu_note_fragment.xml b/app/src/main/res/menu/menu_note_fragment.xml
index 14d8db0e..97cfad95 100644
--- a/app/src/main/res/menu/menu_note_fragment.xml
+++ b/app/src/main/res/menu/menu_note_fragment.xml
@@ -5,7 +5,7 @@
<item
android:id="@+id/search"
android:title="@string/action_search"
- android:icon="@drawable/ic_search_white_24dp"
+ android:icon="@drawable/ic_search_grey600_24dp"
android:orderInCategory="50"
app:actionViewClass="androidx.appcompat.widget.SearchView"
app:showAsAction="ifRoom|collapseActionView" />
@@ -36,7 +36,7 @@
app:showAsAction="never" />
<item
android:id="@+id/menu_move"
- android:icon="@drawable/ic_send_white_24dp"
+ android:icon="@drawable/ic_send_grey600_24dp"
android:orderInCategory="120"
android:title="@string/simple_move"
app:showAsAction="never" />
@@ -48,7 +48,7 @@
app:showAsAction="never" />
<item
android:id="@+id/menu_delete"
- android:icon="@drawable/ic_delete_white_24dp"
+ android:icon="@drawable/ic_delete_grey600_24dp"
android:orderInCategory="140"
android:title="@string/menu_delete"
app:showAsAction="never" />
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 00000000..41cc6feb
--- /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 c01010ad..3c3e134c 100644
--- a/app/src/main/res/values-night/colors.xml
+++ b/app/src/main/res/values-night/colors.xml
@@ -2,10 +2,14 @@
<resources>
<!-- Colors -->
- <color name="primary_dark">#286090</color>
+ <color name="primary">#121212</color>
+ <color name="accent">#f5f5f5</color>
+
+ <color name="cursorHandles">#eee5e5ee</color>
+ <color name="defaultTextHighlightBackground">#55eeeeff</color>
<color name="bg_highlighted">#2a2a2a</color>
- <color name="bg_normal">#121212</color>
+ <color name="bg_normal">@color/primary</color>
<color name="bg_attention">#ff3333</color>
<color name="fg_default">#eeeeee</color>
<color name="fg_default_selection">#cccccc</color>
@@ -13,5 +17,5 @@
<color name="fg_default_high">#757575</color>
<color name="fg_contrast">#000000</color>
- <color name="category_background">@color/primary</color>
+ <color name="category_background">@color/defaultBrand</color>
</resources> \ No newline at end of file
diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml
index 808e2899..1ba46f37 100644
--- a/app/src/main/res/values-nl/strings.xml
+++ b/app/src/main/res/values-nl/strings.xml
@@ -151,6 +151,8 @@
<string name="added_content">\"%1$s\" toegevoegd</string>
<string name="shared_text_empty">Gedeelde tekst was leeg</string>
<string name="append_to_note">Achteraan toevoegen aan notitie</string>
+ <string name="share_multiple">Deel de inhoud van %1$d notities</string>
+
<!-- Array: note modes -->
<string-array name="noteMode_entries">
<item>Open in wbewerkmodus</item>
diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml
index 3d6a8234..9c95df31 100644
--- a/app/src/main/res/values-tr/strings.xml
+++ b/app/src/main/res/values-tr/strings.xml
@@ -150,6 +150,8 @@
<string name="added_content">\"%1$s\" eklendi</string>
<string name="shared_text_empty">Paylaşılan metin boş</string>
<string name="append_to_note">Nota ekle</string>
+ <string name="share_multiple">%1$d notun içeriğini paylaş</string>
+
<!-- Array: note modes -->
<string-array name="noteMode_entries">
<item>Düzenleme kipinde aç</item>
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 00000000..812e48ee
--- /dev/null
+++ b/app/src/main/res/values-v23/styles.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <style name="AppTheme" parent="BaseTheme">
+ <item name="android:statusBarColor">?attr/colorPrimary</item>
+ <item name="android:windowLightStatusBar">@bool/isDayMode</item>
+ </style>
+
+ <style name="SplashTheme" parent="AppTheme">
+ <item name="android:windowBackground">@drawable/splashscreen</item>
+ <item name="android:statusBarColor">@color/defaultBrand</item>
+ <item name="android:windowLightStatusBar">false</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 00000000..477789c3
--- /dev/null
+++ b/app/src/main/res/values-v27/styles.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <style name="AppTheme" parent="BaseTheme">
+ <item name="android:statusBarColor">?attr/colorPrimary</item>
+ <item name="android:windowLightStatusBar">@bool/isDayMode</item>
+ <item name="android:navigationBarColor">?attr/colorPrimary</item>
+ <item name="android:windowLightNavigationBar">@bool/isDayMode</item>
+ </style>
+
+ <style name="SplashTheme" parent="AppTheme">
+ <item name="android:windowBackground">@drawable/splashscreen</item>
+ <item name="android:statusBarColor">@color/defaultBrand</item>
+ <item name="android:windowLightStatusBar">false</item>
+ <item name="android:navigationBarColor">@color/defaultBrand</item>
+ <item name="android:windowLightNavigationBar">false</item>
+ </style>
+</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 00000000..c47017c7
--- /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 db265c9f..c9c94fde 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -2,11 +2,16 @@
<resources>
<!-- Colors -->
- <color name="primary">#0082C9</color>
- <color name="primary_dark">#286090</color>
+ <color name="primary">#ffffff</color>
+ <color name="accent">#121212</color>
+
+ <color name="defaultBrand">#0082C9</color>
+
+ <color name="cursorHandles">#555566</color>
+ <color name="defaultTextHighlightBackground">#2233334a</color>
<color name="bg_highlighted">#eee</color>
- <color name="bg_normal">#ffffff</color>
+ <color name="bg_normal">@color/primary</color>
<color name="bg_attention">#d40000</color>
<color name="bg_warning">#ffcc00</color>
<color name="fg_default">#000000</color>
@@ -17,7 +22,7 @@
<color name="icon_color_default">#757575</color>
- <color name="bg_search_primary">@color/primary</color>
+ <color name="bg_search_primary">@color/defaultBrand</color>
<color name="bg_search_secondary">#eee</color>
<color name="widget_background">#dfffffff</color>
@@ -25,7 +30,7 @@
<color name="widget_fg_contrast">#ffffff</color>
<color name="category_background">@color/bg_normal</color>
- <color name="category_border">@color/primary</color>
+ <color name="category_border">@color/defaultBrand</color>
<!-- Dark Theme -->
<!-- Defined here until appwidgets can use night/colors -->
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
index b615b358..d5578788 100644
--- a/app/src/main/res/values/dimens.xml
+++ b/app/src/main/res/values/dimens.xml
@@ -5,6 +5,11 @@
<dimen name="spacer_1hx">4dp</dimen>
<dimen name="spacer_1x">8dp</dimen>
<dimen name="spacer_2x">16dp</dimen>
+ <dimen name="spacer_3x">24dp</dimen>
+
+ <!-- Drawer header -->
+ <dimen name="drawer_header_height">100dp</dimen>
+ <dimen name="drawer_header_logo_size">42dp</dimen>
<!-- Buttons -->
<dimen name="button_padding">@dimen/spacer_2x</dimen>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 7d381d65..7b316949 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -13,6 +13,7 @@
<string name="simple_edit">Edit</string>
<string name="action_edit_save">Save</string>
<string name="simple_about">About</string>
+ <string name="simple_accounts">Accounts</string>
<string name="simple_bold">Bold</string>
<string name="simple_link">Link</string>
<string name="simple_italic">Italic</string>
@@ -28,6 +29,9 @@
<string name="menu_preview">Preview</string>
<string name="menu_share">Share</string>
+ <string name="search_in_category">Search in %1$s</string>
+ <string name="search_in_all">Search all notes</string>
+
<string name="change_category_title">Choose a category</string>
<string name="listview_updated_today">Today</string>
@@ -112,9 +116,11 @@
<string name="pref_key_note_mode" translatable="false">noteMode</string>
<string name="pref_key_theme" translatable="false">darkTheme</string>
<string name="pref_key_font" translatable="false">font</string>
+ <string name="pref_key_branding" translatable="false">branding</string>
<string name="pref_key_font_size" translatable="false">fontSize</string>
<string name="pref_key_wifi_only" translatable="false">wifiOnly</string>
<string name="pref_key_lock" translatable="false">lock</string>
+ <string name="pref_category_security" translatable="false">security</string>
<string name="pref_key_last_note_mode" translatable="false">lastNoteMode</string>
<string name="pref_key_background_sync" translatable="false">backgroundSync</string>
<string name="pref_value_mode_edit" translatable="false">edit</string>
@@ -186,7 +192,13 @@
<string name="append_to_note">Append to note</string>
<string name="change_note_title">Change note title</string>
<string name="menu_edit_title">Edit title</string>
+ <string name="settings_branding">Branding</string>
+ <string name="simple_security">Security</string>
+ <string name="simple_appearance">Appearance</string>
+ <string name="simple_synchronization">Synchronization</string>
+ <string name="simple_behavior">Behavior</string>
<string name="share_multiple">Share content of %1$d notes</string>
+ <string name="manage_accounts">Manage accounts</string>
<!-- Array: note modes -->
<string-array name="noteMode_entries">
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index edf7acee..ffce1eed 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -1,16 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
- <style name="AppTheme" parent="@style/Theme.AppCompat.DayNight.NoActionBar">
+ <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="colorAccent">@color/accent</item>
+ <item name="android:actionModeBackground">?attr/colorPrimary</item>
+ <item name="colorControlNormal">?attr/colorAccent</item>
<item name="windowActionModeOverlay">true</item>
- <item name="android:colorBackground">@color/bg_normal</item>
</style>
- <style name="toolbarStyle" parent="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
- <item name="colorAccent">#fff</item>
+ <style name="AppTheme" parent="BaseTheme" />
+
+ <style name="textViewStyle">
+ <item name="colorAccent">@color/cursorHandles</item>
+ <item name="android:textColorHighlight">@color/defaultTextHighlightBackground</item>
</style>
<style name="fab">
diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml
index c0d1d5ac..3fc5b4f9 100644
--- a/app/src/main/res/xml/preferences.xml
+++ b/app/src/main/res/xml/preferences.xml
@@ -1,66 +1,93 @@
<?xml version="1.0" encoding="utf-8"?>
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+ <it.niedermann.owncloud.notes.branding.BrandedPreferenceCategory
- <SwitchPreference
- android:defaultValue="@string/pref_value_lock"
- android:icon="@drawable/ic_lock_grey600_24dp"
- android:key="@string/pref_key_lock"
- android:layout="@layout/item_pref"
- android:summary="@string/simple_beta"
- android:title="@string/settings_lock" />
+ app:layout="@layout/item_preference_category"
+ app:title="@string/simple_synchronization">
- <ListPreference
- android:defaultValue="@string/pref_value_mode_edit"
- android:entries="@array/noteMode_entries"
- android:entryValues="@array/noteMode_values"
- android:icon="@drawable/ic_remove_red_eye_grey_24dp"
- android:key="@string/pref_key_note_mode"
- android:layout="@layout/item_pref"
- android:summary="%s"
- android:title="@string/settings_note_mode" />
+ <it.niedermann.owncloud.notes.branding.BrandedSwitchPreference
+ android:defaultValue="@string/pref_value_wifi_and_mobile"
+ android:icon="@drawable/ic_network_wifi_grey600_24dp"
+ android:key="@string/pref_key_wifi_only"
+ android:layout="@layout/item_pref"
+ android:title="@string/settings_wifi_only" />
- <ListPreference
- android:defaultValue="@string/pref_value_theme_system_default"
- android:entries="@array/darkmode_entries"
- android:entryValues="@array/darkMode_values"
- android:summary="%s"
- android:icon="@drawable/ic_brightness_2_grey_24dp"
- android:key="@string/pref_key_theme"
- android:layout="@layout/item_pref"
- android:title="@string/settings_theme_title" />
+ <ListPreference
+ android:defaultValue="@string/pref_value_sync_off"
+ android:entries="@array/sync_entries"
+ android:entryValues="@array/sync_values"
+ android:icon="@drawable/ic_sync_black_24dp"
+ android:key="@string/pref_key_background_sync"
+ android:layout="@layout/item_pref"
+ android:summary="%s"
+ android:title="@string/settings_background_sync" />
+ </it.niedermann.owncloud.notes.branding.BrandedPreferenceCategory>
- <SwitchPreference
- android:defaultValue="@string/pref_value_font_normal"
- android:icon="@drawable/ic_text_format_grey600_24dp"
- android:key="@string/pref_key_font"
- android:layout="@layout/item_pref"
- android:title="@string/settings_font_title" />
+ <it.niedermann.owncloud.notes.branding.BrandedPreferenceCategory
- <ListPreference
- android:defaultValue="@string/pref_value_font_size_medium"
- android:entries="@array/fontSize_entries"
- android:entryValues="@array/fontSize_values"
- android:icon="@drawable/ic_format_size_black_24dp"
- android:key="@string/pref_key_font_size"
- android:layout="@layout/item_pref"
- android:summary="%s"
- android:title="@string/settings_font_size" />
+ app:layout="@layout/item_preference_category"
+ app:title="@string/simple_appearance">
- <SwitchPreference
- android:defaultValue="@string/pref_value_wifi_and_mobile"
- android:icon="@drawable/ic_network_wifi_grey600_24dp"
- android:key="@string/pref_key_wifi_only"
- android:layout="@layout/item_pref"
- android:title="@string/settings_wifi_only" />
+ <ListPreference
+ android:defaultValue="@string/pref_value_theme_system_default"
+ android:entries="@array/darkmode_entries"
+ android:entryValues="@array/darkMode_values"
+ android:icon="@drawable/ic_brightness_2_grey_24dp"
+ android:key="@string/pref_key_theme"
+ android:layout="@layout/item_pref"
+ android:summary="%s"
+ android:title="@string/settings_theme_title" />
- <ListPreference
- android:defaultValue="@string/pref_value_sync_off"
- android:entries="@array/sync_entries"
- android:entryValues="@array/sync_values"
- android:icon="@drawable/ic_sync_black_24dp"
- android:key="@string/pref_key_background_sync"
- android:layout="@layout/item_pref"
- android:summary="%s"
- android:title="@string/settings_background_sync" />
+ <it.niedermann.owncloud.notes.branding.BrandedSwitchPreference
+ android:defaultValue="true"
+ android:icon="@drawable/ic_color_lens_grey600_24dp"
+ android:key="@string/pref_key_branding"
+ android:layout="@layout/item_pref"
+ android:title="@string/settings_branding" />
+ </it.niedermann.owncloud.notes.branding.BrandedPreferenceCategory>
+ <it.niedermann.owncloud.notes.branding.BrandedPreferenceCategory
+ android:key="@string/pref_category_security"
+ app:layout="@layout/item_preference_category"
+ app:title="@string/simple_security">
+ <it.niedermann.owncloud.notes.branding.BrandedSwitchPreference
+ android:defaultValue="@string/pref_value_lock"
+ android:icon="@drawable/ic_lock_grey600_24dp"
+ android:key="@string/pref_key_lock"
+ android:layout="@layout/item_pref"
+ android:summary="@string/simple_beta"
+ android:title="@string/settings_lock" />
+ </it.niedermann.owncloud.notes.branding.BrandedPreferenceCategory>
+
+ <it.niedermann.owncloud.notes.branding.BrandedPreferenceCategory
+
+ app:layout="@layout/item_preference_category"
+ app:title="@string/simple_behavior">
+ <it.niedermann.owncloud.notes.branding.BrandedSwitchPreference
+ android:defaultValue="@string/pref_value_font_normal"
+ android:icon="@drawable/ic_text_format_grey600_24dp"
+ android:key="@string/pref_key_font"
+ android:layout="@layout/item_pref"
+ android:title="@string/settings_font_title" />
+ <ListPreference
+ android:defaultValue="@string/pref_value_mode_edit"
+ android:entries="@array/noteMode_entries"
+ android:entryValues="@array/noteMode_values"
+ android:icon="@drawable/ic_remove_red_eye_grey_24dp"
+ android:key="@string/pref_key_note_mode"
+ android:layout="@layout/item_pref"
+ android:summary="%s"
+ android:title="@string/settings_note_mode" />
+
+ <ListPreference
+ android:defaultValue="@string/pref_value_font_size_medium"
+ android:entries="@array/fontSize_entries"
+ android:entryValues="@array/fontSize_values"
+ android:icon="@drawable/ic_format_size_black_24dp"
+ android:key="@string/pref_key_font_size"
+ android:layout="@layout/item_pref"
+ android:summary="%s"
+ android:title="@string/settings_font_size" />
+ </it.niedermann.owncloud.notes.branding.BrandedPreferenceCategory>
</PreferenceScreen>