From 040e6036b9e6e884a7fb88a92f1e5a27dc685af4 Mon Sep 17 00:00:00 2001 From: daniele-verducci Date: Tue, 1 Sep 2026 11:33:10 +0200 Subject: [PATCH 1/2] 2272: Avoid edit button to cover cursor when the text is scrolled due to the user deleting an entire line Signed-off-by: daniele-verducci --- .../owncloud/notes/edit/NoteDirectEditFragment.kt | 1 + .../owncloud/notes/edit/NoteEditFragment.java | 8 ++++++++ .../owncloud/notes/edit/NotePreviewFragment.java | 12 ++++++++++++ .../notes/edit/SearchableBaseNoteFragment.java | 7 +++++-- .../owncloud/notes/shared/util/ExtendedFabUtil.kt | 5 +++-- 5 files changed, 29 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/it/niedermann/owncloud/notes/edit/NoteDirectEditFragment.kt b/app/src/main/java/it/niedermann/owncloud/notes/edit/NoteDirectEditFragment.kt index 9d957b5d9..d649e3c6d 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/edit/NoteDirectEditFragment.kt +++ b/app/src/main/java/it/niedermann/owncloud/notes/edit/NoteDirectEditFragment.kt @@ -109,6 +109,7 @@ class NoteDirectEditFragment : BaseNoteFragment(), Branded { plainEditingFab, scrollStart, scrollEnd, + false ) } } diff --git a/app/src/main/java/it/niedermann/owncloud/notes/edit/NoteEditFragment.java b/app/src/main/java/it/niedermann/owncloud/notes/edit/NoteEditFragment.java index 8d8b8a6b1..f0a8c334d 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/edit/NoteEditFragment.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/edit/NoteEditFragment.java @@ -58,6 +58,8 @@ public class NoteEditFragment extends SearchableBaseNoteFragment { private Handler handler; private boolean saveActive; private boolean unsavedEdit; + private long lastTextChange = 0; + private final Runnable runAutoSave = new Runnable() { @Override public void run() { @@ -124,6 +126,11 @@ protected ExtendedFloatingActionButton getNormalEditButton() { return null; } + @Override + protected boolean userIsChangingText() { + return System.currentTimeMillis() - lastTextChange < USER_CHANGING_TEXT_TIMEOUT; + } + @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { @@ -148,6 +155,7 @@ public void onTextChanged(CharSequence s, int start, int before, int count) { @Override public void afterTextChanged(final Editable s) { + lastTextChange = System.currentTimeMillis(); unsavedEdit = true; if (!saveActive) { handler.removeCallbacks(runAutoSave); diff --git a/app/src/main/java/it/niedermann/owncloud/notes/edit/NotePreviewFragment.java b/app/src/main/java/it/niedermann/owncloud/notes/edit/NotePreviewFragment.java index b982baca9..e7bbde4d2 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/edit/NotePreviewFragment.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/edit/NotePreviewFragment.java @@ -54,6 +54,8 @@ public class NotePreviewFragment extends SearchableBaseNoteFragment implements O @Nullable private Runnable setScrollY; + private long lastTextChange = 0; + @Override public void onPrepareOptionsMenu(@NonNull Menu menu) { super.onPrepareOptionsMenu(menu); @@ -101,6 +103,11 @@ protected ExtendedFloatingActionButton getNormalEditButton() { return binding.edit; } + @Override + protected boolean userIsChangingText() { + return System.currentTimeMillis() - lastTextChange < USER_CHANGING_TEXT_TIMEOUT; + } + @Override protected Layout getLayout() { binding.singleNoteContent.onPreDraw(); @@ -140,6 +147,7 @@ protected void onNoteLoaded(Note note) { noteLoaded = true; registerInternalNoteLinkHandler(); + registerInternalNoteTextChangedHandler(); lifecycleScopeIOJob(() -> { final String content = note.getContent(); @@ -179,6 +187,10 @@ protected void registerInternalNoteLinkHandler() { }); } + protected void registerInternalNoteTextChangedHandler() { + binding.singleNoteContent.setMarkdownStringChangedListener(charSequence -> lastTextChange = System.currentTimeMillis()); + } + @Override protected void colorWithText(@NonNull String newText, @Nullable Integer current, @ColorInt int color) { if (binding != null && isAttachedToWindow(binding.singleNoteContent)) { diff --git a/app/src/main/java/it/niedermann/owncloud/notes/edit/SearchableBaseNoteFragment.java b/app/src/main/java/it/niedermann/owncloud/notes/edit/SearchableBaseNoteFragment.java index 469c24825..ee1127b08 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/edit/SearchableBaseNoteFragment.java +++ b/app/src/main/java/it/niedermann/owncloud/notes/edit/SearchableBaseNoteFragment.java @@ -42,6 +42,7 @@ public abstract class SearchableBaseNoteFragment extends BaseNoteFragment { private static final String TAG = SearchableBaseNoteFragment.class.getSimpleName(); private static final String saved_instance_key_searchQuery = "searchQuery"; private static final String saved_instance_key_currentOccurrence = "currentOccurrence"; + protected static final long USER_CHANGING_TEXT_TIMEOUT = 200; private int currentOccurrence = 1; private int occurrenceCount = 0; @@ -80,9 +81,9 @@ protected void onScroll(int scrollY, int oldScrollY) { final ExtendedFloatingActionButton directFab = getDirectEditingButton(); final ExtendedFloatingActionButton normalFab = getNormalEditButton(); if (directEditEnabled) { - ExtendedFabUtil.toggleVisibilityOnScroll(directFab, scrollY, oldScrollY); + ExtendedFabUtil.toggleVisibilityOnScroll(directFab, scrollY, oldScrollY, userIsChangingText()); } else if (normalFab != null) { - ExtendedFabUtil.toggleVisibilityOnScroll(normalFab, scrollY, oldScrollY); + ExtendedFabUtil.toggleVisibilityOnScroll(normalFab, scrollY, oldScrollY, userIsChangingText()); } } } @@ -284,6 +285,8 @@ public void onSaveInstanceState(@NonNull Bundle outState) { protected abstract ExtendedFloatingActionButton getNormalEditButton(); + protected abstract boolean userIsChangingText(); + private void showSearchFabs() { ExtendedFabUtil.setExtendedFabVisibility(getDirectEditingButton(), false); final ExtendedFloatingActionButton normalFab = getNormalEditButton(); diff --git a/app/src/main/java/it/niedermann/owncloud/notes/shared/util/ExtendedFabUtil.kt b/app/src/main/java/it/niedermann/owncloud/notes/shared/util/ExtendedFabUtil.kt index 895443fc6..92c68c5d2 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/shared/util/ExtendedFabUtil.kt +++ b/app/src/main/java/it/niedermann/owncloud/notes/shared/util/ExtendedFabUtil.kt @@ -24,7 +24,7 @@ object ExtendedFabUtil { if (extendedFab.isExtended) { extendedFab.hide() } else { - if (extendedFab.animation == null) { + if (extendedFab.animation == null && extendedFab.isShown) { val animation = AnimationUtils.loadAnimation( extendedFab.context, @@ -64,9 +64,10 @@ object ExtendedFabUtil { extendedFab: ExtendedFloatingActionButton, scrollY: Int, oldScrollY: Int, + isTyping: Boolean ) { @Suppress("ConvertTwoComparisonsToRangeCheck") - if (oldScrollY > 0 && scrollY > oldScrollY && extendedFab.isShown) { + if (isTyping || (oldScrollY > 0 && scrollY > oldScrollY && extendedFab.isShown)) { setExtendedFabVisibility(extendedFab, false) } else if (scrollY < oldScrollY && !extendedFab.isShown) { setExtendedFabVisibility(extendedFab, true) From 20bcda2c58a6d35ce24a80a7868895162518b858 Mon Sep 17 00:00:00 2001 From: daniele-verducci Date: Thu, 3 Sep 2026 10:15:00 +0200 Subject: [PATCH 2/2] 2272: fix codacy Signed-off-by: daniele-verducci --- .../niedermann/owncloud/notes/shared/util/ExtendedFabUtil.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/it/niedermann/owncloud/notes/shared/util/ExtendedFabUtil.kt b/app/src/main/java/it/niedermann/owncloud/notes/shared/util/ExtendedFabUtil.kt index 92c68c5d2..d201e2d0b 100644 --- a/app/src/main/java/it/niedermann/owncloud/notes/shared/util/ExtendedFabUtil.kt +++ b/app/src/main/java/it/niedermann/owncloud/notes/shared/util/ExtendedFabUtil.kt @@ -67,7 +67,8 @@ object ExtendedFabUtil { isTyping: Boolean ) { @Suppress("ConvertTwoComparisonsToRangeCheck") - if (isTyping || (oldScrollY > 0 && scrollY > oldScrollY && extendedFab.isShown)) { + val hasScrolledDown = oldScrollY > 0 && scrollY > oldScrollY && extendedFab.isShown + if (isTyping || hasScrolledDown) { setExtendedFabVisibility(extendedFab, false) } else if (scrollY < oldScrollY && !extendedFab.isShown) { setExtendedFabVisibility(extendedFab, true)