Loading app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java +2 −3 Original line number Diff line number Diff line Loading @@ -325,7 +325,7 @@ public class NotesListViewActivity extends LockedActivity implements NoteClickLi } private void setupNotesList() { initList(); initRecyclerView(); ((RecyclerView) findViewById(R.id.recycler_view)).addOnScrollListener(new RecyclerView.OnScrollListener() { @Override Loading Loading @@ -596,7 +596,7 @@ public class NotesListViewActivity extends LockedActivity implements NoteClickLi binding.navigationMenu.setAdapter(adapterMenu); } private void initList() { private void initRecyclerView() { adapter = new ItemAdapter(this, gridView); listView.setAdapter(adapter); Loading Loading @@ -802,7 +802,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); } } Loading app/src/main/java/it/niedermann/owncloud/notes/android/fragment/PreferencesFragment.java +2 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ 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; Loading Loading @@ -61,6 +62,7 @@ public class PreferencesFragment extends PreferenceFragmentCompat implements Bra if (gridViewPref != null) { gridViewPref.setOnPreferenceChangeListener((Preference preference, Object newValue) -> { final Boolean gridView = (Boolean) newValue; NotesDatabase.getInstance(requireContext()).regenerateExcerpts(!gridView); Log.v(TAG, "gridView: " + gridView); requireActivity().setResult(Activity.RESULT_OK); return true; Loading app/src/main/java/it/niedermann/owncloud/notes/model/ItemAdapter.java +0 −1 Original line number Diff line number Diff line Loading @@ -11,7 +11,6 @@ import androidx.annotation.ColorInt; import androidx.annotation.IntRange; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.StaggeredGridLayoutManager; import java.util.ArrayList; import java.util.List; Loading app/src/main/java/it/niedermann/owncloud/notes/model/NoteViewGridHolder.java +4 −4 Original line number Diff line number Diff line package it.niedermann.owncloud.notes.model; import android.content.Context; import android.util.Log; import android.view.View; import androidx.annotation.NonNull; Loading @@ -13,13 +14,12 @@ public class NoteViewGridHolder extends NoteViewHolder { private final ItemNotesListNoteItemGridBinding binding; public NoteViewGridHolder(@NonNull ItemNotesListNoteItemGridBinding binding, @NonNull NoteClickListener noteClickListener) { super(binding.getRoot(), noteClickListener); super(binding.getRoot(), noteClickListener, true); this.binding = binding; itemView.setOnClickListener(this); itemView.setOnLongClickListener(this); } public void showSwipe(boolean left) { } Loading @@ -29,8 +29,8 @@ public class NoteViewGridHolder extends NoteViewHolder { 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()); bindTitle(context, binding.noteTitle, searchQuery, note, mainColor); bindExcerpt(context, binding.noteContent, searchQuery, note, mainColor); bindSearchableContent(context, binding.noteTitle, searchQuery, note.getTitle(), mainColor); bindSearchableContent(context, binding.noteContent, searchQuery, note.getExcerpt(), mainColor); } public View getNoteSwipeable() { Loading app/src/main/java/it/niedermann/owncloud/notes/model/NoteViewHolder.java +34 −26 Original line number Diff line number Diff line Loading @@ -4,6 +4,8 @@ import android.content.Context; import android.graphics.Color; import android.graphics.drawable.GradientDrawable; import android.os.Build; import android.os.Handler; import android.os.Looper; import android.text.SpannableString; import android.text.TextUtils; import android.text.style.BackgroundColorSpan; Loading @@ -18,23 +20,36 @@ import androidx.annotation.Nullable; import androidx.core.graphics.drawable.DrawableCompat; import androidx.recyclerview.widget.RecyclerView; import com.yydcdut.markdown.MarkdownProcessor; import com.yydcdut.markdown.syntax.text.TextFactory; 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.util.MarkDownUtil; 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; import static it.niedermann.owncloud.notes.util.MarkDownUtil.parseCompat; public abstract class NoteViewHolder extends RecyclerView.ViewHolder implements View.OnLongClickListener, View.OnClickListener { private final NoteClickListener noteClickListener; private final boolean renderMarkdown; private MarkdownProcessor markdownProcessor; public NoteViewHolder(@NonNull View v, @NonNull NoteClickListener noteClickListener) { public NoteViewHolder(@NonNull View v, @NonNull NoteClickListener noteClickListener, boolean renderMarkdown) { super(v); this.noteClickListener = noteClickListener; this.renderMarkdown = renderMarkdown; if (renderMarkdown) { markdownProcessor = new MarkdownProcessor(itemView.getContext()); markdownProcessor.factory(TextFactory.create()); markdownProcessor.config(MarkDownUtil.getMarkDownConfiguration(itemView.getContext()).build()); } v.setOnClickListener(this); v.setOnLongClickListener(this); } Loading Loading @@ -99,10 +114,9 @@ public abstract class NoteViewHolder extends RecyclerView.ViewHolder implements noteFavorite.setOnClickListener(view -> noteClickListener.onNoteFavoriteClick(getAdapterPosition(), view)); } protected void bindTitle(@NonNull Context context, @NonNull TextView noteTitle, @Nullable CharSequence searchQuery, @NonNull DBNote note, int mainColor) { if (TextUtils.isEmpty(searchQuery)) { noteTitle.setText(note.getTitle()); } else { 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); Loading @@ -110,36 +124,30 @@ 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); processedContent = spannableString; } bindContent(textView, processedContent); } protected void bindExcerpt(@NonNull Context context, @NonNull TextView noteExcerpt, @Nullable CharSequence searchQuery, @NonNull DBNote note, int mainColor) { if (TextUtils.isEmpty(searchQuery)) { noteExcerpt.setText(note.getExcerpt()); } else { @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.getExcerpt()); 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); private void bindContent(@NonNull TextView textView, @NonNull CharSequence charSequence) { textView.setText(charSequence); if (renderMarkdown) { new Thread(() -> { try { final CharSequence parsedCharSequence = parseCompat(markdownProcessor, charSequence); new Handler(Looper.getMainLooper()).post(() -> textView.setText(parsedCharSequence)); } catch (StringIndexOutOfBoundsException e) { // Workaround for RxMarkdown: https://github.com/stefan-niedermann/nextcloud-notes/issues/668 } noteExcerpt.setText(spannableString); }).start(); } } Loading Loading
app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java +2 −3 Original line number Diff line number Diff line Loading @@ -325,7 +325,7 @@ public class NotesListViewActivity extends LockedActivity implements NoteClickLi } private void setupNotesList() { initList(); initRecyclerView(); ((RecyclerView) findViewById(R.id.recycler_view)).addOnScrollListener(new RecyclerView.OnScrollListener() { @Override Loading Loading @@ -596,7 +596,7 @@ public class NotesListViewActivity extends LockedActivity implements NoteClickLi binding.navigationMenu.setAdapter(adapterMenu); } private void initList() { private void initRecyclerView() { adapter = new ItemAdapter(this, gridView); listView.setAdapter(adapter); Loading Loading @@ -802,7 +802,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); } } Loading
app/src/main/java/it/niedermann/owncloud/notes/android/fragment/PreferencesFragment.java +2 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ 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; Loading Loading @@ -61,6 +62,7 @@ public class PreferencesFragment extends PreferenceFragmentCompat implements Bra if (gridViewPref != null) { gridViewPref.setOnPreferenceChangeListener((Preference preference, Object newValue) -> { final Boolean gridView = (Boolean) newValue; NotesDatabase.getInstance(requireContext()).regenerateExcerpts(!gridView); Log.v(TAG, "gridView: " + gridView); requireActivity().setResult(Activity.RESULT_OK); return true; Loading
app/src/main/java/it/niedermann/owncloud/notes/model/ItemAdapter.java +0 −1 Original line number Diff line number Diff line Loading @@ -11,7 +11,6 @@ import androidx.annotation.ColorInt; import androidx.annotation.IntRange; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.StaggeredGridLayoutManager; import java.util.ArrayList; import java.util.List; Loading
app/src/main/java/it/niedermann/owncloud/notes/model/NoteViewGridHolder.java +4 −4 Original line number Diff line number Diff line package it.niedermann.owncloud.notes.model; import android.content.Context; import android.util.Log; import android.view.View; import androidx.annotation.NonNull; Loading @@ -13,13 +14,12 @@ public class NoteViewGridHolder extends NoteViewHolder { private final ItemNotesListNoteItemGridBinding binding; public NoteViewGridHolder(@NonNull ItemNotesListNoteItemGridBinding binding, @NonNull NoteClickListener noteClickListener) { super(binding.getRoot(), noteClickListener); super(binding.getRoot(), noteClickListener, true); this.binding = binding; itemView.setOnClickListener(this); itemView.setOnLongClickListener(this); } public void showSwipe(boolean left) { } Loading @@ -29,8 +29,8 @@ public class NoteViewGridHolder extends NoteViewHolder { 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()); bindTitle(context, binding.noteTitle, searchQuery, note, mainColor); bindExcerpt(context, binding.noteContent, searchQuery, note, mainColor); bindSearchableContent(context, binding.noteTitle, searchQuery, note.getTitle(), mainColor); bindSearchableContent(context, binding.noteContent, searchQuery, note.getExcerpt(), mainColor); } public View getNoteSwipeable() { Loading
app/src/main/java/it/niedermann/owncloud/notes/model/NoteViewHolder.java +34 −26 Original line number Diff line number Diff line Loading @@ -4,6 +4,8 @@ import android.content.Context; import android.graphics.Color; import android.graphics.drawable.GradientDrawable; import android.os.Build; import android.os.Handler; import android.os.Looper; import android.text.SpannableString; import android.text.TextUtils; import android.text.style.BackgroundColorSpan; Loading @@ -18,23 +20,36 @@ import androidx.annotation.Nullable; import androidx.core.graphics.drawable.DrawableCompat; import androidx.recyclerview.widget.RecyclerView; import com.yydcdut.markdown.MarkdownProcessor; import com.yydcdut.markdown.syntax.text.TextFactory; 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.util.MarkDownUtil; 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; import static it.niedermann.owncloud.notes.util.MarkDownUtil.parseCompat; public abstract class NoteViewHolder extends RecyclerView.ViewHolder implements View.OnLongClickListener, View.OnClickListener { private final NoteClickListener noteClickListener; private final boolean renderMarkdown; private MarkdownProcessor markdownProcessor; public NoteViewHolder(@NonNull View v, @NonNull NoteClickListener noteClickListener) { public NoteViewHolder(@NonNull View v, @NonNull NoteClickListener noteClickListener, boolean renderMarkdown) { super(v); this.noteClickListener = noteClickListener; this.renderMarkdown = renderMarkdown; if (renderMarkdown) { markdownProcessor = new MarkdownProcessor(itemView.getContext()); markdownProcessor.factory(TextFactory.create()); markdownProcessor.config(MarkDownUtil.getMarkDownConfiguration(itemView.getContext()).build()); } v.setOnClickListener(this); v.setOnLongClickListener(this); } Loading Loading @@ -99,10 +114,9 @@ public abstract class NoteViewHolder extends RecyclerView.ViewHolder implements noteFavorite.setOnClickListener(view -> noteClickListener.onNoteFavoriteClick(getAdapterPosition(), view)); } protected void bindTitle(@NonNull Context context, @NonNull TextView noteTitle, @Nullable CharSequence searchQuery, @NonNull DBNote note, int mainColor) { if (TextUtils.isEmpty(searchQuery)) { noteTitle.setText(note.getTitle()); } else { 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); Loading @@ -110,36 +124,30 @@ 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); processedContent = spannableString; } bindContent(textView, processedContent); } protected void bindExcerpt(@NonNull Context context, @NonNull TextView noteExcerpt, @Nullable CharSequence searchQuery, @NonNull DBNote note, int mainColor) { if (TextUtils.isEmpty(searchQuery)) { noteExcerpt.setText(note.getExcerpt()); } else { @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.getExcerpt()); 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); private void bindContent(@NonNull TextView textView, @NonNull CharSequence charSequence) { textView.setText(charSequence); if (renderMarkdown) { new Thread(() -> { try { final CharSequence parsedCharSequence = parseCompat(markdownProcessor, charSequence); new Handler(Looper.getMainLooper()).post(() -> textView.setText(parsedCharSequence)); } catch (StringIndexOutOfBoundsException e) { // Workaround for RxMarkdown: https://github.com/stefan-niedermann/nextcloud-notes/issues/668 } noteExcerpt.setText(spannableString); }).start(); } } Loading