diff options
Diffstat (limited to 'app/src/main')
26 files changed, 485 insertions, 100 deletions
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 9ec2eac3..ed3cc8c2 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 @@ -37,8 +37,8 @@ public class NotesListViewItemTouchHelper extends ItemTouchHelper { @NonNull ISyncCallback syncCallBack, @NonNull Runnable refreshLists, @Nullable SwipeRefreshLayout swipeRefreshLayout, - @Nullable ViewProvider viewProvider - ) { + @Nullable ViewProvider viewProvider, + boolean gridView) { super(new SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) { private boolean swipeRefreshLayoutEnabled; @@ -48,15 +48,15 @@ public class NotesListViewItemTouchHelper extends ItemTouchHelper { } /** - * Disable swipe on sections + * Disable swipe on sections and if grid view is enabled * * @param recyclerView RecyclerView * @param viewHolder RecyclerView.ViewHoler - * @return 0 if section, otherwise super() + * @return 0 if viewHolder is section or grid view is enabled, otherwise super() */ @Override public int getSwipeDirs(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) { - if (viewHolder instanceof SectionViewHolder) return 0; + if (gridView || viewHolder instanceof SectionViewHolder) return 0; return super.getSwipeDirs(recyclerView, viewHolder); } 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 3daf809a..ccfbbe41 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 @@ -13,6 +13,7 @@ import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.text.TextUtils; +import android.util.DisplayMetrics; import android.util.Log; import android.view.View; import android.view.ViewTreeObserver; @@ -22,11 +23,13 @@ import androidx.annotation.NonNull; import androidx.appcompat.view.ActionMode; import androidx.appcompat.widget.SearchView; import androidx.coordinatorlayout.widget.CoordinatorLayout; +import androidx.core.content.ContextCompat; 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.recyclerview.widget.StaggeredGridLayoutManager; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import com.bumptech.glide.Glide; @@ -62,6 +65,7 @@ import it.niedermann.owncloud.notes.formattinghelp.FormattingHelpActivity; import it.niedermann.owncloud.notes.model.Capabilities; import it.niedermann.owncloud.notes.model.Category; import it.niedermann.owncloud.notes.model.DBNote; +import it.niedermann.owncloud.notes.model.GridItemDecoration; import it.niedermann.owncloud.notes.model.ISyncCallback; import it.niedermann.owncloud.notes.model.Item; import it.niedermann.owncloud.notes.model.ItemAdapter; @@ -70,6 +74,7 @@ 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.model.SectionItemDecoration; import it.niedermann.owncloud.notes.persistence.CapabilitiesClient; import it.niedermann.owncloud.notes.persistence.CapabilitiesWorker; import it.niedermann.owncloud.notes.persistence.LoadNotesListTask; @@ -83,6 +88,8 @@ 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.Notes.isDarkThemeActive; +import static it.niedermann.owncloud.notes.util.Notes.isGridViewEnabled; import static it.niedermann.owncloud.notes.util.SSOUtil.askForNewAccount; import static java.util.Arrays.asList; @@ -90,6 +97,8 @@ public class NotesListViewActivity extends LockedActivity implements NoteClickLi private static final String TAG = NotesListViewActivity.class.getSimpleName(); + private boolean gridView = true; + public static final String CREATED_NOTE = "it.niedermann.owncloud.notes.created_notes"; public static final String ADAPTER_KEY_RECENT = "recent"; public static final String ADAPTER_KEY_STARRED = "starred"; @@ -123,7 +132,7 @@ public class NotesListViewActivity extends LockedActivity implements NoteClickLi protected FloatingActionButton fabCreate; private RecyclerView listView; - protected ItemAdapter adapter = null; + protected ItemAdapter adapter; protected NotesDatabase db = null; private NavigationAdapter adapterCategories; @@ -177,6 +186,11 @@ public class NotesListViewActivity extends LockedActivity implements NoteClickLi db = NotesDatabase.getInstance(this); + gridView = isGridViewEnabled(); + if (!gridView || isDarkThemeActive(this)) { + activityBinding.activityNotesListView.setBackgroundColor(ContextCompat.getColor(this, R.color.primary)); + } + setupToolbars(); setupNavigationList(categoryAdapterSelectedItem); setupNavigationMenu(); @@ -229,7 +243,8 @@ public class NotesListViewActivity extends LockedActivity implements NoteClickLi 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); + new NotesListViewItemTouchHelper(ssoAccount, this, db, adapter, syncCallBack, this::refreshLists, swipeRefreshLayout, this, gridView) + .attachToRecyclerView(listView); synchronize(); } catch (NextcloudFilesAppAccountNotFoundException | NoCurrentAccountSelectedException e) { Log.i(TAG, "Tried to select account, but got an " + e.getClass().getSimpleName() + ". Asking for importing an account..."); @@ -317,7 +332,7 @@ public class NotesListViewActivity extends LockedActivity implements NoteClickLi } private void setupNotesList() { - initList(); + initRecyclerView(); ((RecyclerView) findViewById(R.id.recycler_view)).addOnScrollListener(new RecyclerView.OnScrollListener() { @Override @@ -588,10 +603,32 @@ public class NotesListViewActivity extends LockedActivity implements NoteClickLi binding.navigationMenu.setAdapter(adapterMenu); } - public void initList() { - adapter = new ItemAdapter(this); + private void initRecyclerView() { + adapter = new ItemAdapter(this, gridView); listView.setAdapter(adapter); - listView.setLayoutManager(new LinearLayoutManager(this)); + + if (gridView) { + final DisplayMetrics displayMetrics = getResources().getDisplayMetrics(); + int spanCount = (int) ((displayMetrics.widthPixels / displayMetrics.density) / getResources().getInteger(R.integer.max_dp_grid_view)); + StaggeredGridLayoutManager gridLayoutManager = new StaggeredGridLayoutManager(spanCount, StaggeredGridLayoutManager.VERTICAL); + listView.setLayoutManager(gridLayoutManager); + listView.addItemDecoration(new GridItemDecoration(adapter, + getResources().getDimensionPixelSize(R.dimen.spacer_3x), + getResources().getDimensionPixelSize(R.dimen.spacer_5x), + getResources().getDimensionPixelSize(R.dimen.spacer_3x), + getResources().getDimensionPixelSize(R.dimen.spacer_1x), + getResources().getDimensionPixelSize(R.dimen.spacer_2x) + )); + } else { + LinearLayoutManager layoutManager = new LinearLayoutManager(this); + listView.setLayoutManager(layoutManager); + listView.addItemDecoration(new SectionItemDecoration(adapter, + getResources().getDimensionPixelSize(R.dimen.spacer_6x), + getResources().getDimensionPixelSize(R.dimen.spacer_5x), + getResources().getDimensionPixelSize(R.dimen.spacer_1x), + 0 + )); + } } private void refreshLists() { @@ -787,7 +824,6 @@ public class NotesListViewActivity extends LockedActivity implements NoteClickLi Intent intent = new Intent(getApplicationContext(), EditNoteActivity.class); intent.putExtra(EditNoteActivity.PARAM_NOTE_ID, note.getId()); startActivityForResult(intent, show_single_note_cmd); - } } 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 bebe3fee..f4ea6b02 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 @@ -11,11 +11,13 @@ import androidx.preference.ListPreference; import androidx.preference.Preference; import androidx.preference.PreferenceFragmentCompat; +import it.niedermann.owncloud.notes.BuildConfig; 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.NotesDatabase; import it.niedermann.owncloud.notes.persistence.SyncWorker; import it.niedermann.owncloud.notes.util.DeviceCredentialUtil; import it.niedermann.owncloud.notes.util.Notes; @@ -30,6 +32,7 @@ public class PreferencesFragment extends PreferenceFragmentCompat implements Bra private BrandedSwitchPreference lockPref; private BrandedSwitchPreference wifiOnlyPref; private BrandedSwitchPreference brandingPref; + private BrandedSwitchPreference gridViewPref; @Override public void onCreate(@Nullable Bundle savedInstanceState) { @@ -56,6 +59,20 @@ public class PreferencesFragment extends PreferenceFragmentCompat implements Bra Log.e(TAG, "Could not find preference with key: \"" + getString(R.string.pref_key_branding) + "\""); } + gridViewPref = findPreference(getString(R.string.pref_key_gridview)); + if (gridViewPref != null) { + gridViewPref.setVisible(BuildConfig.DEBUG); + gridViewPref.setOnPreferenceChangeListener((Preference preference, Object newValue) -> { + final Boolean gridView = (Boolean) newValue; + Log.v(TAG, "gridView: " + gridView); + requireActivity().setResult(Activity.RESULT_OK); + Notes.updateGridViewEnabled(gridView); + 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())) { @@ -119,5 +136,6 @@ public class PreferencesFragment extends PreferenceFragmentCompat implements Bra lockPref.applyBrand(mainColor, textColor); wifiOnlyPref.applyBrand(mainColor, textColor); brandingPref.applyBrand(mainColor, textColor); + gridViewPref.applyBrand(mainColor, textColor); } } 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 index f84bd8e4..878917fa 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandingUtil.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/branding/BrandingUtil.java @@ -31,7 +31,6 @@ public class BrandingUtil { } - public static boolean isBrandingEnabled(@NonNull Context context) { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); return prefs.getBoolean(context.getString(R.string.pref_key_branding), true); diff --git a/app/src/main/java/it/niedermann/owncloud/notes/model/GridItemDecoration.java b/app/src/main/java/it/niedermann/owncloud/notes/model/GridItemDecoration.java new file mode 100644 index 00000000..6443121e --- /dev/null +++ b/app/src/main/java/it/niedermann/owncloud/notes/model/GridItemDecoration.java @@ -0,0 +1,51 @@ +package it.niedermann.owncloud.notes.model; + +import android.graphics.Rect; +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.annotation.Px; +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.StaggeredGridLayoutManager; + +public class GridItemDecoration extends SectionItemDecoration { + + @NonNull + private final ItemAdapter adapter; + private final int gutter; + + public GridItemDecoration(@NonNull ItemAdapter adapter, @Px int sectionLeft, @Px int sectionTop, @Px int sectionRight, @Px int sectionBottom, @Px int gutter) { + super(adapter, sectionLeft, sectionTop, sectionRight, sectionBottom); + this.adapter = adapter; + this.gutter = gutter; + } + + @Override + public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { + super.getItemOffsets(outRect, view, parent, state); + final int position = parent.getChildAdapterPosition(view); + final StaggeredGridLayoutManager.LayoutParams lp = (StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams(); + + if (adapter.getItemViewType(position) == ItemAdapter.TYPE_SECTION) { + lp.setFullSpan(true); + } else { + final int spanIndex = lp.getSpanIndex(); + + if (position >= 0) { + // First row gets some spacing at the top + if (position < adapter.getFirstPositionOfViewType(ItemAdapter.TYPE_SECTION)) { + outRect.top = gutter; + } + + // First column gets some spacing at the left and the right side + if (spanIndex == 0) { + outRect.left = gutter; + } + + // All columns get some spacing at the bottom and at the right side + outRect.right = gutter; + outRect.bottom = gutter; + } + } + } +} 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 21eece55..81f46b55 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,6 +1,7 @@ package it.niedermann.owncloud.notes.model; import android.content.Context; +import android.content.SharedPreferences; import android.graphics.Color; import android.text.TextUtils; import android.util.Log; @@ -8,7 +9,10 @@ import android.view.LayoutInflater; import android.view.ViewGroup; import androidx.annotation.ColorInt; +import androidx.annotation.IntRange; import androidx.annotation.NonNull; +import androidx.annotation.Px; +import androidx.preference.PreferenceManager; import androidx.recyclerview.widget.RecyclerView; import java.util.ArrayList; @@ -16,34 +20,58 @@ import java.util.List; import it.niedermann.owncloud.notes.R; import it.niedermann.owncloud.notes.branding.Branded; +import it.niedermann.owncloud.notes.databinding.ItemNotesListNoteItemGridBinding; import it.niedermann.owncloud.notes.databinding.ItemNotesListNoteItemWithExcerptBinding; import it.niedermann.owncloud.notes.databinding.ItemNotesListSectionItemBinding; import static it.niedermann.owncloud.notes.databinding.ItemNotesListNoteItemWithoutExcerptBinding.inflate; +import static it.niedermann.owncloud.notes.util.NoteUtil.getFontSizeFromPreferences; public class ItemAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements Branded { private static final String TAG = ItemAdapter.class.getSimpleName(); - private static final int TYPE_SECTION = R.layout.item_notes_list_section_item; - private static final int TYPE_NOTE_WITH_EXCERPT = R.layout.item_notes_list_note_item_with_excerpt; - private static final int TYPE_NOTE_WITHOUT_EXCERPT = R.layout.item_notes_list_note_item_without_excerpt; + public static final int TYPE_SECTION = 0; + public static final int TYPE_NOTE_WITH_EXCERPT = 1; + public static final int TYPE_NOTE_WITHOUT_EXCERPT = 2; + private final NoteClickListener noteClickListener; + private final boolean gridView; private List<Item> itemList = new ArrayList<>(); private boolean showCategory = true; private CharSequence searchQuery; private final List<Integer> selected = new ArrayList<>(); + @Px + private final float fontSize; + private final boolean monospace; @ColorInt private int mainColor; @ColorInt private int textColor; - public <T extends Context & NoteClickListener> ItemAdapter(@NonNull T context) { + public <T extends Context & NoteClickListener> ItemAdapter(@NonNull T context, boolean gridView) { this.noteClickListener = context; + this.gridView = gridView; this.mainColor = context.getResources().getColor(R.color.defaultBrand); this.textColor = Color.WHITE; + final SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext()); + this.fontSize = getFontSizeFromPreferences(context, sp); + this.monospace = sp.getBoolean(context.getString(R.string.pref_key_font), false); + // FIXME see getItemId() + // setHasStableIds(true); } + + /* + FIXME this causes {@link it.niedermann.owncloud.notes.android.NotesListViewItemTouchHelper} to not call clearView anymore → After marking a note as favorite, it stays yellow. + @Override + public long getItemId(int position) { + return getItemViewType(position) == TYPE_SECTION + ? ((SectionItem) getItem(position)).getTitle().hashCode() * -1 + : ((DBNote) getItem(position)).getId(); + } + */ + /** * Updates the item list and notifies respective view to update. * @@ -76,18 +104,33 @@ public class ItemAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> i @NonNull @Override public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - switch (viewType) { - case TYPE_SECTION: { - return new SectionViewHolder(ItemNotesListSectionItemBinding.inflate(LayoutInflater.from(parent.getContext()))); + if (gridView) { + switch (viewType) { + case TYPE_SECTION: { + return new SectionViewHolder(ItemNotesListSectionItemBinding.inflate(LayoutInflater.from(parent.getContext()))); + } + case TYPE_NOTE_WITH_EXCERPT: + case TYPE_NOTE_WITHOUT_EXCERPT: { + return new NoteViewGridHolder(ItemNotesListNoteItemGridBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false), noteClickListener, monospace, fontSize); + } + default: { + throw new IllegalArgumentException("Not supported viewType: " + viewType); + } } - case TYPE_NOTE_WITH_EXCERPT: { - return new NoteViewHolderWithExcerpt(ItemNotesListNoteItemWithExcerptBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false), noteClickListener); - } - case TYPE_NOTE_WITHOUT_EXCERPT: { - return new NoteViewHolderWithoutExcerpt(inflate(LayoutInflater.from(parent.getContext()), parent, false), noteClickListener); - } - default: { - throw new IllegalArgumentException("Not supported viewType: " + viewType); + } else { + switch (viewType) { + case TYPE_SECTION: { + return new SectionViewHolder(ItemNotesListSectionItemBinding.inflate(LayoutInflater.from(parent.getContext()))); + } + case TYPE_NOTE_WITH_EXCERPT: { + return new NoteViewHolderWithExcerpt(ItemNotesListNoteItemWithExcerptBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false), noteClickListener); + } + case TYPE_NOTE_WITHOUT_EXCERPT: { + return new NoteViewHolderWithoutExcerpt(inflate(LayoutInflater.from(parent.getContext()), parent, false), noteClickListener); + } + default: { + throw new IllegalArgumentException("Not supported viewType: " + viewType); + } } } } @@ -99,12 +142,9 @@ public class ItemAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> i ((SectionViewHolder) holder).bind((SectionItem) itemList.get(position)); break; } - case TYPE_NOTE_WITH_EXCERPT: { - ((NoteViewHolderWithExcerpt) holder).bind((DBNote) itemList.get(position), showCategory, mainColor, textColor, searchQuery); - break; - } + case TYPE_NOTE_WITH_EXCERPT: case TYPE_NOTE_WITHOUT_EXCERPT: { - ((NoteViewHolderWithoutExcerpt) holder).bind((DBNote) itemList.get(position), showCategory, mainColor, textColor, searchQuery); + ((NoteViewHolder) holder).bind((DBNote) itemList.get(position), showCategory, mainColor, textColor, searchQuery); break; } } @@ -114,7 +154,7 @@ public class ItemAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> i return !selected.contains(position) && selected.add(position); } - public void clearSelection(RecyclerView recyclerView) { + public void clearSelection(@NonNull RecyclerView recyclerView) { for (Integer i : getSelected()) { RecyclerView.ViewHolder viewHolder = recyclerView.findViewHolderForAdapterPosition(i); if (viewHolder != null) { @@ -160,6 +200,7 @@ public class ItemAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> i return itemList.size(); } + @IntRange(from = 0, to = 2) @Override public int getItemViewType(int position) { Item item = getItem(position); @@ -183,4 +224,16 @@ public class ItemAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> i public void setHighlightSearchQuery(CharSequence searchQuery) { this.searchQuery = searchQuery; } + + /** + * @return the position of the first item which matches the given viewtype, -1 if not available + */ + public int getFirstPositionOfViewType(@IntRange(from = 0, to = 2) int viewType) { + for (int i = 0; i < itemList.size(); i++) { + if (getItemViewType(i) == viewType) { + return i; + } + } + return -1; + } }
\ No newline at end of file diff --git a/app/src/main/java/it/niedermann/owncloud/notes/model/NoteViewGridHolder.java b/app/src/main/java/it/niedermann/owncloud/notes/model/NoteViewGridHolder.java new file mode 100644 index 00000000..984de175 --- /dev/null +++ b/app/src/main/java/it/niedermann/owncloud/notes/model/NoteViewGridHolder.java @@ -0,0 +1,54 @@ +package it.niedermann.owncloud.notes.model; + +import android.content.Context; +import android.graphics.Typeface; +import android.text.TextUtils; +import android.util.TypedValue; +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.Px; + +import it.niedermann.owncloud.notes.databinding.ItemNotesListNoteItemGridBinding; + +import static android.view.View.GONE; +import static android.view.View.INVISIBLE; +import static android.view.View.VISIBLE; + +public class NoteViewGridHolder extends NoteViewHolder { + @NonNull + private final ItemNotesListNoteItemGridBinding binding; + + public NoteViewGridHolder(@NonNull ItemNotesListNoteItemGridBinding binding, @NonNull NoteClickListener noteClickListener, boolean monospace, @Px float fontSize) { + super(binding.getRoot(), noteClickListener); + this.binding = binding; + + binding.noteTitle.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 1.1f); + binding.noteExcerpt.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * .8f); + if (monospace) { + binding.noteTitle.setTypeface(Typeface.MONOSPACE); + binding.noteExcerpt.setTypeface(Typeface.MONOSPACE); + } + } + + public void showSwipe(boolean left) { + throw new UnsupportedOperationException(NoteViewGridHolder.class.getSimpleName() + " does not support swiping"); + } + + public void bind(@NonNull DBNote note, boolean showCategory, int mainColor, int textColor, @Nullable CharSequence searchQuery) { + super.bind(note, showCategory, mainColor, textColor, searchQuery); + @NonNull final Context context = itemView.getContext(); + bindCategory(context, binding.noteCategory, showCategory, note.getCategory(), mainColor); + binding.noteStatus.setVisibility(DBStatus.VOID.equals(note.getStatus()) ? INVISIBLE : VISIBLE); + bindFavorite(binding.noteFavorite, note.isFavorite()); + bindSearchableContent(context, binding.noteTitle, searchQuery, note.getTitle(), mainColor); + bindSearchableContent(context, binding.noteExcerpt, searchQuery, note.getExcerpt().replace(" ", "\n"), mainColor); + binding.noteExcerpt.setVisibility(TextUtils.isEmpty(note.getExcerpt()) ? GONE : VISIBLE); + } + + @Nullable + public View getNoteSwipeable() { + return null; + } +}
\ 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 index 31155700..c4e222e3 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/model/NoteViewHolder.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/model/NoteViewHolder.java @@ -1,6 +1,7 @@ package it.niedermann.owncloud.notes.model; import android.content.Context; +import android.content.res.ColorStateList; import android.graphics.Color; import android.graphics.drawable.GradientDrawable; import android.os.Build; @@ -12,12 +13,15 @@ import android.view.View; import android.widget.ImageView; import android.widget.TextView; +import androidx.annotation.CallSuper; import androidx.annotation.ColorInt; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.core.graphics.drawable.DrawableCompat; import androidx.recyclerview.widget.RecyclerView; +import com.google.android.material.chip.Chip; + import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -25,31 +29,22 @@ import it.niedermann.owncloud.notes.R; import it.niedermann.owncloud.notes.branding.BrandingUtil; 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 abstract class NoteViewHolder extends RecyclerView.ViewHolder implements View.OnLongClickListener, View.OnClickListener { +public abstract class NoteViewHolder extends RecyclerView.ViewHolder { + @NonNull private final NoteClickListener noteClickListener; public NoteViewHolder(@NonNull View v, @NonNull NoteClickListener noteClickListener) { super(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); + @CallSuper + public void bind(@NonNull DBNote note, boolean showCategory, int mainColor, int textColor, @Nullable CharSequence searchQuery) { + itemView.setOnClickListener((view) -> noteClickListener.onNoteClick(getAdapterPosition(), view)); + itemView.setOnLongClickListener((view) -> noteClickListener.onNoteLongClick(getAdapterPosition(), view)); } protected void bindCategory(@NonNull Context context, @NonNull TextView noteCategory, boolean showCategory, @NonNull String category, int mainColor) { @@ -82,14 +77,19 @@ public abstract class NoteViewHolder extends RecyclerView.ViewHolder implements } } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - DrawableCompat.setTint(noteCategory.getBackground(), categoryBackground); + noteCategory.setTextColor(categoryForeground); + if (noteCategory instanceof Chip) { + ((Chip) noteCategory).setChipStrokeColor(ColorStateList.valueOf(categoryBackground)); + ((Chip) noteCategory).setChipBackgroundColor(ColorStateList.valueOf(isDarkThemeActive ? categoryBackground : Color.TRANSPARENT)); } else { - final GradientDrawable drawable = (GradientDrawable) noteCategory.getBackground(); - drawable.setStroke(1, categoryBackground); - drawable.setColor(isDarkThemeActive ? categoryBackground : Color.TRANSPARENT); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + DrawableCompat.setTint(noteCategory.getBackground(), categoryBackground); + } else { + final GradientDrawable drawable = (GradientDrawable) noteCategory.getBackground(); + drawable.setStroke(1, categoryBackground); + drawable.setColor(isDarkThemeActive ? categoryBackground : Color.TRANSPARENT); + } } - noteCategory.setTextColor(categoryForeground); } protected void bindFavorite(@NonNull ImageView noteFavorite, boolean isFavorite) { @@ -97,7 +97,8 @@ public abstract class NoteViewHolder extends RecyclerView.ViewHolder implements noteFavorite.setOnClickListener(view -> noteClickListener.onNoteFavoriteClick(getAdapterPosition(), view)); } - protected void bindTitleAndExcerpt(@NonNull Context context, @NonNull TextView noteTitle, @Nullable TextView noteExcerpt, @Nullable CharSequence searchQuery, @NonNull DBNote note, int mainColor) { + protected void bindSearchableContent(@NonNull Context context, @NonNull TextView textView, @Nullable CharSequence searchQuery, @NonNull String content, int mainColor) { + CharSequence processedContent = content; if (!TextUtils.isEmpty(searchQuery)) { @ColorInt final int searchBackground = context.getResources().getColor(R.color.bg_highlighted); @ColorInt final int searchForeground = BrandingUtil.getSecondaryForegroundColorDependingOnTheme(context, mainColor); @@ -106,34 +107,21 @@ public abstract class NoteViewHolder extends RecyclerView.ViewHolder implements // 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()); + SpannableString spannableString = new SpannableString(content); 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); - } - 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); } - if (noteExcerpt != null) { - noteExcerpt.setText(spannableString); - } - } else { - noteTitle.setText(note.getTitle()); - if (noteExcerpt != null) { - noteExcerpt.setText(note.getExcerpt()); - } + processedContent = spannableString; } + textView.setText(processedContent); } public abstract void showSwipe(boolean left); + @Nullable public abstract View getNoteSwipeable(); }
\ No newline at end of file diff --git a/app/src/main/java/it/niedermann/owncloud/notes/model/NoteViewHolderWithExcerpt.java b/app/src/main/java/it/niedermann/owncloud/notes/model/NoteViewHolderWithExcerpt.java index 4d1ee302..032e868f 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/model/NoteViewHolderWithExcerpt.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/model/NoteViewHolderWithExcerpt.java @@ -1,6 +1,7 @@ package it.niedermann.owncloud.notes.model; import android.content.Context; +import android.text.TextUtils; import android.view.View; import androidx.annotation.NonNull; @@ -16,8 +17,6 @@ public class NoteViewHolderWithExcerpt extends NoteViewHolder { public NoteViewHolderWithExcerpt(@NonNull ItemNotesListNoteItemWithExcerptBinding binding, @NonNull NoteClickListener noteClickListener) { super(binding.getRoot(), noteClickListener); this.binding = binding; - itemView.setOnClickListener(this); - itemView.setOnLongClickListener(this); } public void showSwipe(boolean left) { @@ -27,14 +26,18 @@ public class NoteViewHolderWithExcerpt extends NoteViewHolder { } public void bind(@NonNull DBNote note, boolean showCategory, int mainColor, int textColor, @Nullable CharSequence searchQuery) { + super.bind(note, showCategory, mainColor, textColor, searchQuery); @NonNull final Context context = itemView.getContext(); binding.noteSwipeable.setAlpha(DBStatus.LOCAL_DELETED.equals(note.getStatus()) ? 0.5f : 1.0f); bindCategory(context, binding.noteCategory, showCategory, note.getCategory(), mainColor); binding.noteStatus.setVisibility(DBStatus.VOID.equals(note.getStatus()) ? View.INVISIBLE : View.VISIBLE); bindFavorite(binding.noteFavorite, note.isFavorite()); - bindTitleAndExcerpt(context, binding.noteTitle, binding.noteExcerpt, searchQuery, note, mainColor); + + bindSearchableContent(context, binding.noteTitle, searchQuery, note.getTitle(), mainColor); + bindSearchableContent(context, binding.noteExcerpt, searchQuery, note.getExcerpt(), mainColor); } + @NonNull public View getNoteSwipeable() { return binding.noteSwipeable; } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/model/NoteViewHolderWithoutExcerpt.java b/app/src/main/java/it/niedermann/owncloud/notes/model/NoteViewHolderWithoutExcerpt.java index bd7c7e9d..acdb4fb6 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/model/NoteViewHolderWithoutExcerpt.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/model/NoteViewHolderWithoutExcerpt.java @@ -16,11 +16,8 @@ public class NoteViewHolderWithoutExcerpt extends NoteViewHolder { public NoteViewHolderWithoutExcerpt(@NonNull ItemNotesListNoteItemWithoutExcerptBinding binding, @NonNull NoteClickListener noteClickListener) { super(binding.getRoot(), noteClickListener); this.binding = binding; - itemView.setOnClickListener(this); - itemView.setOnLongClickListener(this); } - public void showSwipe(boolean left) { binding.noteFavoriteLeft.setVisibility(left ? View.VISIBLE : View.INVISIBLE); binding.noteDeleteRight.setVisibility(left ? View.INVISIBLE : View.VISIBLE); @@ -28,14 +25,16 @@ public class NoteViewHolderWithoutExcerpt extends NoteViewHolder { } public void bind(@NonNull DBNote note, boolean showCategory, int mainColor, int textColor, @Nullable CharSequence searchQuery) { + super.bind(note, showCategory, mainColor, textColor, searchQuery); @NonNull final Context context = itemView.getContext(); binding.noteSwipeable.setAlpha(DBStatus.LOCAL_DELETED.equals(note.getStatus()) ? 0.5f : 1.0f); bindCategory(context, binding.noteCategory, showCategory, note.getCategory(), mainColor); binding.noteStatus.setVisibility(DBStatus.VOID.equals(note.getStatus()) ? View.INVISIBLE : View.VISIBLE); bindFavorite(binding.noteFavorite, note.isFavorite()); - bindTitleAndExcerpt(context, binding.noteTitle, null, searchQuery, note, mainColor); + bindSearchableContent(context, binding.noteTitle, searchQuery, note.getTitle(), mainColor); } + @NonNull public View getNoteSwipeable() { return binding.noteSwipeable; } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/model/SectionItemDecoration.java b/app/src/main/java/it/niedermann/owncloud/notes/model/SectionItemDecoration.java new file mode 100644 index 00000000..baf95926 --- /dev/null +++ b/app/src/main/java/it/niedermann/owncloud/notes/model/SectionItemDecoration.java @@ -0,0 +1,39 @@ +package it.niedermann.owncloud.notes.model; + +import android.graphics.Rect; +import android.view.View; + +import androidx.annotation.CallSuper; +import androidx.annotation.NonNull; +import androidx.annotation.Px; +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.StaggeredGridLayoutManager; + +public class SectionItemDecoration extends RecyclerView.ItemDecoration { + + @NonNull + private final ItemAdapter adapter; + private final int sectionLeft; + private final int sectionTop; + private final int sectionRight; + private final int sectionBottom; + + public SectionItemDecoration(@NonNull ItemAdapter adapter, @Px int sectionLeft, @Px int sectionTop, @Px int sectionRight, @Px int sectionBottom) { + this.adapter = adapter; + this.sectionLeft = sectionLeft; + this.sectionTop = sectionTop; + this.sectionRight = sectionRight; + this.sectionBottom = sectionBottom; + } + + @CallSuper + public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { + final int position = parent.getChildAdapterPosition(view); + if (adapter.getItemViewType(position) == ItemAdapter.TYPE_SECTION) { + outRect.left = sectionLeft; + outRect.top = sectionTop; + outRect.right = sectionRight; + outRect.bottom = sectionBottom; + } + } +} 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 index 98a273a2..eccdd7d9 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/model/SectionViewHolder.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/model/SectionViewHolder.java @@ -1,8 +1,7 @@ package it.niedermann.owncloud.notes.model; -import android.view.View; - import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.StaggeredGridLayoutManager; import it.niedermann.owncloud.notes.databinding.ItemNotesListSectionItemBinding; 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 1a31ae0a..40df4efa 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 @@ -41,8 +41,6 @@ import java.util.Set; import it.niedermann.owncloud.notes.R; import it.niedermann.owncloud.notes.android.activity.EditNoteActivity; -import it.niedermann.owncloud.notes.android.appwidget.NoteListWidget; -import it.niedermann.owncloud.notes.android.appwidget.SingleNoteWidget; import it.niedermann.owncloud.notes.model.ApiVersion; import it.niedermann.owncloud.notes.model.Capabilities; import it.niedermann.owncloud.notes.model.CloudNote; @@ -616,7 +614,7 @@ public class NotesDatabase extends AbstractNotesDatabase { if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { ShortcutManager shortcutManager = getContext().getSystemService(ShortcutManager.class); - if(shortcutManager != null) { + if (shortcutManager != null) { shortcutManager.getPinnedShortcuts().forEach((shortcut) -> { String shortcutId = id + ""; if (shortcut.getId().equals(shortcutId)) { 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 66f89280..1a8c4b15 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 @@ -85,14 +85,10 @@ public class MarkDownUtil { return ""; } - Log.v(TAG, "parseCompat - Original: \"" + text + "\""); - while (TextUtils.indexOf(text, MD_IMAGE_WITH_EMPTY_DESCRIPTION) >= 0) { text = TextUtils.replace(text, MD_IMAGE_WITH_EMPTY_DESCRIPTION_ARRAY, MD_IMAGE_WITH_SPACE_DESCRIPTION_ARRAY); } - Log.v(TAG, "parseCompat - Replaced empty image descriptions: \"" + text + "\""); - return markdownProcessor.parse(text); } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/util/Notes.java b/app/src/main/java/it/niedermann/owncloud/notes/util/Notes.java index 9a4de905..5a5e74c5 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/util/Notes.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/util/Notes.java @@ -6,12 +6,15 @@ import android.content.SharedPreferences; import android.content.res.Configuration; import android.util.Log; +import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatDelegate; import androidx.preference.PreferenceManager; import it.niedermann.owncloud.notes.R; import it.niedermann.owncloud.notes.android.DarkModeSetting; +import static androidx.preference.PreferenceManager.getDefaultSharedPreferences; + public class Notes extends Application { private static final String TAG = Notes.class.getSimpleName(); @@ -20,6 +23,7 @@ public class Notes extends Application { private static boolean isLocked = true; private static long lastInteraction = 0; private static String PREF_KEY_THEME; + private static boolean isGridViewEnabled = false; @Override public void onCreate() { @@ -27,6 +31,7 @@ public class Notes extends Application { setAppTheme(getAppTheme(getApplicationContext())); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); lockedPreference = prefs.getBoolean(getString(R.string.pref_key_lock), false); + isGridViewEnabled = getDefaultSharedPreferences(this).getBoolean(getString(R.string.pref_key_gridview), false); super.onCreate(); } @@ -34,6 +39,14 @@ public class Notes extends Application { AppCompatDelegate.setDefaultNightMode(setting.getModeId()); } + public static boolean isGridViewEnabled() { + return isGridViewEnabled; + } + + public static void updateGridViewEnabled(boolean gridView) { + isGridViewEnabled = gridView; + } + public static DarkModeSetting getAppTheme(Context context) { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); String mode; diff --git a/app/src/main/res/drawable-v21/grid_item_background_selector.xml b/app/src/main/res/drawable-v21/grid_item_background_selector.xml new file mode 100644 index 00000000..37de2a6f --- /dev/null +++ b/app/src/main/res/drawable-v21/grid_item_background_selector.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?><!-- Selector is used for Background Colors in List Items --> +<ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="@color/bg_highlighted"> + <!-- :selected --> + <item> + <selector> + <item android:state_selected="true"> + <color android:color="@color/bg_highlighted" /> + </item> + + <item android:state_activated="true"> + <color android:color="@color/bg_highlighted" /> + </item> + + <item> + <color android:color="@android:color/transparent" /> + </item> + </selector> + </item> +</ripple>
\ No newline at end of file diff --git a/app/src/main/res/drawable-v21/list_item_background_selector.xml b/app/src/main/res/drawable-v21/list_item_background_selector.xml index ea3fa361..8c562151 100644 --- a/app/src/main/res/drawable-v21/list_item_background_selector.xml +++ b/app/src/main/res/drawable-v21/list_item_background_selector.xml @@ -1,8 +1,6 @@ <?xml version="1.0" encoding="utf-8"?><!-- Selector is used for Background Colors in List Items --> <ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="@color/bg_highlighted"> <!-- :selected --> - - <item> <selector> <item android:state_selected="true"> diff --git a/app/src/main/res/drawable/grid_item_background_selector.xml b/app/src/main/res/drawable/grid_item_background_selector.xml new file mode 100644 index 00000000..24ab9be7 --- /dev/null +++ b/app/src/main/res/drawable/grid_item_background_selector.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?><!-- Selector is used for Background Colors in List Items --> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <!-- :selected --> + <item android:drawable="@color/bg_highlighted" android:state_selected="true" /> + <item android:drawable="@android:color/transparent" /> +</selector> diff --git a/app/src/main/res/drawable/ic_baseline_dashboard_24.xml b/app/src/main/res/drawable/ic_baseline_dashboard_24.xml new file mode 100644 index 00000000..6c526e9c --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_dashboard_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,13h8L11,3L3,3v10zM3,21h8v-6L3,15v6zM13,21h8L21,11h-8v10zM13,3v6h8L21,3h-8z"/> +</vector> 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 b1f318ed..47aa0186 100644 --- a/app/src/main/res/layout/activity_notes_list_view.xml +++ b/app/src/main/res/layout/activity_notes_list_view.xml @@ -4,8 +4,7 @@ xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_notes_list_view" android:layout_width="match_parent" - android:layout_height="match_parent" - android:background="@color/primary"> + android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" diff --git a/app/src/main/res/layout/item_notes_list_note_item_grid.xml b/app/src/main/res/layout/item_notes_list_note_item_grid.xml new file mode 100644 index 00000000..edd0dc01 --- /dev/null +++ b/app/src/main/res/layout/item_notes_list_note_item_grid.xml @@ -0,0 +1,104 @@ +<?xml version="1.0" encoding="utf-8"?> +<com.google.android.material.card.MaterialCardView 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:id="@+id/card" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:focusable="true"> + + <LinearLayout + android:id="@+id/wrapper" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="@drawable/grid_item_background_selector" + android:orientation="vertical" + android:paddingBottom="@dimen/spacer_1x"> + + <TextView + android:id="@+id/noteTitle" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginStart="@dimen/spacer_2x" + android:layout_marginLeft="@dimen/spacer_2x" + android:layout_marginTop="@dimen/spacer_2x" + android:layout_marginEnd="@dimen/spacer_2x" + android:layout_marginRight="@dimen/spacer_2x" + android:layout_marginBottom="@dimen/spacer_1x" + android:textAppearance="?attr/textAppearanceHeadline5" + android:textColor="@color/fg_default" + tools:maxLength="50" + tools:text="@tools:sample/lorem/random" /> + + + <TextView + android:id="@+id/noteExcerpt" + android:layout_width="match_parent" + android:layout_height="wrap_content" + 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:textAppearance="?android:attr/textAppearanceMedium" + android:textColor="@color/fg_default" + tools:maxLength="200" + tools:text="@tools:sample/lorem/random" /> + + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:baselineAligned="false" + android:gravity="center_vertical" + android:orientation="horizontal"> + + <FrameLayout + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1"> + + <com.google.android.material.chip.Chip + android:id="@+id/noteCategory" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="@dimen/spacer_2x" + android:layout_marginLeft="@dimen/spacer_2x" + android:layout_marginEnd="0dp" + android:layout_marginRight="0dp" + android:ellipsize="middle" + android:textColor="?android:textColorPrimary" + android:textSize="@dimen/secondary_font_size" + app:chipBackgroundColor="@color/primary" + app:chipStrokeColor="@color/defaultBrand" + app:chipStrokeWidth="1dp" + tools:maxLength="50" + tools:text="@tools:sample/lorem/random" /> + </FrameLayout> + + <FrameLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content"> + + <ImageView + android:id="@+id/noteFavorite" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + 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:baseline="14dp" + app:srcCompat="@drawable/ic_sync_blue_18dp" /> + </FrameLayout> + </LinearLayout> + </LinearLayout> +</com.google.android.material.card.MaterialCardView>
\ No newline at end of file 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 6e20555c..3f29866a 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 @@ -9,15 +9,9 @@ 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:padding="@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/values/dimens.xml b/app/src/main/res/values/dimens.xml index d5578788..3ffa7d38 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -6,6 +6,8 @@ <dimen name="spacer_1x">8dp</dimen> <dimen name="spacer_2x">16dp</dimen> <dimen name="spacer_3x">24dp</dimen> + <dimen name="spacer_5x">40dp</dimen> + <dimen name="spacer_6x">48dp</dimen> <!-- Drawer header --> <dimen name="drawer_header_height">100dp</dimen> diff --git a/app/src/main/res/values/integers.xml b/app/src/main/res/values/integers.xml new file mode 100644 index 00000000..3a6f3f24 --- /dev/null +++ b/app/src/main/res/values/integers.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <integer name="max_dp_grid_view">170</integer> +</resources>
\ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index dedaf45f..7aebd1ce 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -117,6 +117,7 @@ <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_gridview" translatable="false">gridview</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> @@ -191,6 +192,7 @@ <string name="shared_text_empty">Shared text was empty</string> <string name="append_to_note">Append to note</string> <string name="settings_branding">Branding</string> + <string name="settings_gridview">Grid view</string> <string name="simple_security">Security</string> <string name="simple_appearance">Appearance</string> <string name="simple_synchronization">Synchronization</string> diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 191d4819..06e1f1be 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -45,6 +45,12 @@ android:layout="@layout/item_pref" android:title="@string/settings_branding" /> + <it.niedermann.owncloud.notes.branding.BrandedSwitchPreference + android:icon="@drawable/ic_baseline_dashboard_24" + android:key="@string/pref_key_gridview" + android:layout="@layout/item_pref" + android:title="@string/settings_gridview" /> + </it.niedermann.owncloud.notes.branding.BrandedPreferenceCategory> <it.niedermann.owncloud.notes.branding.BrandedPreferenceCategory |