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 95b76550d..ce74f72a4 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 @@ -23,6 +23,7 @@ import android.webkit.WebView import android.webkit.WebViewClient import android.widget.ScrollView import androidx.core.view.isVisible +import androidx.preference.PreferenceManager import com.google.android.material.snackbar.Snackbar import com.nextcloud.android.common.ui.theme.utils.ColorRole import com.nextcloud.android.sso.helper.SingleAccountHelper @@ -55,6 +56,7 @@ class NoteDirectEditFragment : BaseNoteFragment(), Branded { private val disposables: DisposableSet = DisposableSet() private var switchToEditPending = false + private var switchToPreviewPending = false val account: SingleSignOnAccount by lazy { SingleAccountHelper.getCurrentSingleSignOnAccount( @@ -95,6 +97,18 @@ class NoteDirectEditFragment : BaseNoteFragment(), Branded { plainEditingFab.isExtended = false ExtendedFabUtil.toggleExtendedOnLongClick(plainEditingFab) + previewFab.isExtended = false + ExtendedFabUtil.toggleExtendedOnLongClick(previewFab) + + if (isDirectEditEnabled()) { + val shift = resources.getDimension(R.dimen.fab_size) * 0.75f + val reducedOffset = resources.getDimension(R.dimen.fab_stack_offset_reduced) + val originalOffset = resources.getDimension(R.dimen.fab_stack_offset) + + previewFab.translationY = -shift + plainEditingFab.translationY = -shift - (reducedOffset - originalOffset) + } + // manually detect scroll as we can't get it from the webview (maybe with custom JS?) noteWebview.setOnTouchListener { _, event -> when (event.action) { @@ -108,11 +122,17 @@ class NoteDirectEditFragment : BaseNoteFragment(), Branded { scrollStart, scrollEnd, ) + ExtendedFabUtil.toggleVisibilityOnScroll( + previewFab, + scrollStart, + scrollEnd, + ) } } return@setOnTouchListener false } plainEditingFab.setOnClickListener { switchToPlainEdit() } + previewFab.setOnClickListener { switchToPreview() } } } @@ -122,7 +142,19 @@ class NoteDirectEditFragment : BaseNoteFragment(), Branded { val resultWithoutQuotes = result.replace("\"", "") if (resultWithoutQuotes != JS_RESULT_OK) { Log.w(TAG, "Closing via JS failed: $resultWithoutQuotes") - changeToEditMode() + changeMode(NoteFragmentListener.Mode.EDIT) + } + // if result is OK, switch will be handled by JS interface callback + } + } + + private fun switchToPreview() { + switchToPreviewPending = true + binding?.noteWebview?.evaluateJavascript(JS_CLOSE) { result -> + val resultWithoutQuotes = result.replace("\"", "") + if (resultWithoutQuotes != JS_RESULT_OK) { + Log.w(TAG, "Closing via JS failed: $resultWithoutQuotes") + changeMode(NoteFragmentListener.Mode.PREVIEW) } // if result is OK, switch will be handled by JS interface callback } @@ -225,7 +257,7 @@ class NoteDirectEditFragment : BaseNoteFragment(), Branded { if (note != null) { snackbar.setAction(R.string.switch_to_plain_editing) { - changeToEditMode() + changeMode(NoteFragmentListener.Mode.EDIT) } } else { snackbar.setAction(R.string.action_back) { @@ -329,6 +361,7 @@ class NoteDirectEditFragment : BaseNoteFragment(), Branded { binding?.run { util.material.themeExtendedFAB(plainEditingFab) + util.material.themeExtendedFAB(previewFab) util.platform.colorCircularProgressBar(progress, ColorRole.PRIMARY) } } @@ -353,14 +386,17 @@ class NoteDirectEditFragment : BaseNoteFragment(), Branded { private fun close() { if (switchToEditPending) { Log.d(TAG, "close: switching to plain edit") - changeToEditMode() + changeMode(NoteFragmentListener.Mode.EDIT) + } else if (switchToPreviewPending) { + Log.d(TAG, "close: switching to preview") + changeMode(NoteFragmentListener.Mode.PREVIEW) } else { Log.d(TAG, "close: closing") listener?.close() } } - private fun changeToEditMode() { + private fun changeMode(targetMode: NoteFragmentListener.Mode) { if (note == null || note.remoteId == null) { Log.d(TAG, "note is null, cant edit") return @@ -376,10 +412,10 @@ class NoteDirectEditFragment : BaseNoteFragment(), Branded { .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe({ - listener?.changeMode(NoteFragmentListener.Mode.EDIT, true) + listener?.changeMode(targetMode, true) }, { throwable -> - Log.e(TAG, "changeToEditMode: ", throwable) - listener?.changeMode(NoteFragmentListener.Mode.EDIT, true) + Log.e(TAG, "changeMode: ", throwable) + listener?.changeMode(targetMode, true) }) disposables.add(updateDisposable) } @@ -399,10 +435,16 @@ class NoteDirectEditFragment : BaseNoteFragment(), Branded { progress.isVisible = loading noteWebview.isVisible = !loading plainEditingFab.isVisible = !loading + previewFab.isVisible = !loading } } } + private fun isDirectEditEnabled(): Boolean { + val sp = PreferenceManager.getDefaultSharedPreferences(requireContext().applicationContext) + return sp.getBoolean(getString(R.string.pref_key_enable_direct_edit), true) + } + companion object { private const val TAG = "NoteDirectEditFragment" private const val LOAD_TIMEOUT_SECONDS = 10L 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..96efa233e 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 @@ -83,7 +83,9 @@ public void onCreate(@Nullable Bundle savedInstanceState) { public void onPrepareOptionsMenu(@NonNull Menu menu) { super.onPrepareOptionsMenu(menu); menu.findItem(R.id.menu_edit).setVisible(false); - menu.findItem(R.id.menu_preview).setVisible(true); + final boolean fabVisible = (getNormalEditButton() != null && getNormalEditButton().getVisibility() == View.VISIBLE) + || (getDirectEditingButton() != null && getDirectEditingButton().getVisibility() == View.VISIBLE); + menu.findItem(R.id.menu_preview).setVisible(!fabVisible); } @Override @@ -119,9 +121,23 @@ protected FloatingActionButton getSearchPrevButton() { return binding.directEditing; } + @Override + protected void onDirectEditFabClick() { + if (listener != null) { + listener.changeMode(NoteFragmentListener.Mode.DIRECT_EDIT, true); + } + } + + @Override + protected void onNormalEditFabClick() { + if (listener != null) { + listener.changeMode(NoteFragmentListener.Mode.PREVIEW, true); + } + } + + @Override protected ExtendedFloatingActionButton getNormalEditButton() { - // the edit fragment does not have a button - return null; + return binding.preview; } @Nullable 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..749382c56 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 @@ -57,11 +57,9 @@ public class NotePreviewFragment extends SearchableBaseNoteFragment implements O @Override public void onPrepareOptionsMenu(@NonNull Menu menu) { super.onPrepareOptionsMenu(menu); - menu.findItem(R.id.menu_edit).setVisible(true); - if(getNormalEditButton().getVisibility() == View.VISIBLE) { - menu.findItem(R.id.menu_edit).setVisible(false); - } - + final boolean fabVisible = (getNormalEditButton() != null && getNormalEditButton().getVisibility() == View.VISIBLE) + || (getDirectEditingButton() != null && getDirectEditingButton().getVisibility() == View.VISIBLE); + menu.findItem(R.id.menu_edit).setVisible(!fabVisible); menu.findItem(R.id.menu_preview).setVisible(false); } 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 503fbc9d2..f4f7969da 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 @@ -75,11 +75,19 @@ public void onActivityCreated(@Nullable Bundle savedInstanceState) { @Override protected void onScroll(int scrollY, int oldScrollY) { super.onScroll(scrollY, oldScrollY); - if (isDirectEditEnabled()) { - // only show FAB if search is not active - if (getSearchNextButton() == null || getSearchNextButton().getVisibility() != View.VISIBLE) { - final ExtendedFloatingActionButton directFab = getDirectEditingButton(); + // only show FAB if search is not active + if (getSearchNextButton() == null || getSearchNextButton().getVisibility() != View.VISIBLE) { + final ExtendedFloatingActionButton directFab = getDirectEditingButton(); + final ExtendedFloatingActionButton editFab = getNormalEditButton(); + if (isDirectEditEnabled()) { ExtendedFabUtil.toggleVisibilityOnScroll(directFab, scrollY, oldScrollY); + if (editFab != null && editFab != directFab) { + ExtendedFabUtil.toggleVisibilityOnScroll(editFab, scrollY, oldScrollY); + } + } else { + if (editFab != null) { + ExtendedFabUtil.toggleVisibilityOnScroll(editFab, scrollY, oldScrollY); + } } } } @@ -88,32 +96,51 @@ protected void onScroll(int scrollY, int oldScrollY) { public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); checkDirectEditingAvailable(); + + final var directEditFab = getDirectEditingButton(); + final var normalEditFab = getNormalEditButton(); + if (isDirectEditEnabled()) { - ExtendedFloatingActionButton edit = getNormalEditButton(); - if (edit != null) edit.setVisibility(View.GONE); - final ExtendedFloatingActionButton directEditingButton = getDirectEditingButton(); - directEditingButton.setExtended(false); - directEditingButton.setVisibility(View.VISIBLE); - ExtendedFabUtil.toggleExtendedOnLongClick(directEditingButton); - directEditingButton.setOnClickListener(v -> { - if (listener != null) { - listener.changeMode(NoteFragmentListener.Mode.DIRECT_EDIT, false); - } - }); + if (directEditFab != null) { + directEditFab.setExtended(false); + directEditFab.show(); + directEditFab.setTranslationY(-getResources().getDimension(R.dimen.fab_size) * 0.75f); + ExtendedFabUtil.toggleExtendedOnLongClick(directEditFab); + directEditFab.setOnClickListener(v -> onDirectEditFabClick()); + } + if (normalEditFab != null && normalEditFab != directEditFab) { + normalEditFab.setExtended(false); + normalEditFab.show(); + normalEditFab.setTranslationY(-getResources().getDimension(R.dimen.fab_size) * 0.75f - getResources().getDimension(R.dimen.fab_stack_offset_reduced)); + ExtendedFabUtil.toggleExtendedOnLongClick(normalEditFab); + normalEditFab.setOnClickListener(v -> onNormalEditFabClick()); + } } else { - getDirectEditingButton().setVisibility(View.GONE); - ExtendedFloatingActionButton edit = getNormalEditButton(); - if(edit!=null) { - edit.setVisibility(View.VISIBLE); - edit.setOnClickListener(v -> { - if (listener != null) { - listener.changeMode(NoteFragmentListener.Mode.EDIT, true); - } - }); + if (directEditFab != null && directEditFab != normalEditFab) { + directEditFab.hide(); + } + if (normalEditFab != null) { + normalEditFab.setExtended(false); + normalEditFab.show(); + normalEditFab.setTranslationY(0); + ExtendedFabUtil.toggleExtendedOnLongClick(normalEditFab); + normalEditFab.setOnClickListener(v -> onNormalEditFabClick()); } } } + protected void onDirectEditFabClick() { + if (listener != null) { + listener.changeMode(NoteFragmentListener.Mode.DIRECT_EDIT, false); + } + } + + protected void onNormalEditFabClick() { + if (listener != null) { + listener.changeMode(NoteFragmentListener.Mode.EDIT, true); + } + } + private void checkDirectEditingAvailable() { try { final SingleSignOnAccount ssoAccount = SingleAccountHelper.getCurrentSingleSignOnAccount(requireContext()); @@ -285,6 +312,10 @@ public void onSaveInstanceState(@NonNull Bundle outState) { private void showSearchFabs() { ExtendedFabUtil.setExtendedFabVisibility(getDirectEditingButton(), false); + final var edit = getNormalEditButton(); + if (edit != null) { + ExtendedFabUtil.setExtendedFabVisibility(edit, false); + } final var next = getSearchNextButton(); final var prev = getSearchPrevButton(); if (prev != null) { @@ -304,6 +335,18 @@ private void hideSearchFabs() { if (next != null) { next.hide(); } + final var directEditFab = getDirectEditingButton(); + final var normalEditFab = getNormalEditButton(); + if (isDirectEditEnabled()) { + directEditFab.show(); + if (normalEditFab != null && normalEditFab != directEditFab) { + normalEditFab.show(); + } + } else { + if (normalEditFab != null) { + normalEditFab.show(); + } + } } private void jumpToOccurrence() { diff --git a/app/src/main/res/layout/fragment_note_direct_edit.xml b/app/src/main/res/layout/fragment_note_direct_edit.xml index 9ea531c40..399977282 100644 --- a/app/src/main/res/layout/fragment_note_direct_edit.xml +++ b/app/src/main/res/layout/fragment_note_direct_edit.xml @@ -33,15 +33,29 @@ style="?attr/floatingActionButtonPrimaryStyle" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginBottom="@dimen/note_direct_edit_fab_margin_bottom" + android:layout_marginBottom="88dp" android:layout_marginEnd="@dimen/spacer_2x" android:contentDescription="@string/noteMode_plain_edit" android:text="@string/noteMode_plain_edit" android:visibility="gone" app:backgroundTint="@color/defaultBrand" app:icon="@drawable/ic_notes" - app:layout_anchor="@id/note_webview" - app:layout_anchorGravity="bottom|end" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + tools:visibility="visible" /> + + diff --git a/app/src/main/res/layout/fragment_note_edit.xml b/app/src/main/res/layout/fragment_note_edit.xml index 4de3e67b8..64b8d197f 100644 --- a/app/src/main/res/layout/fragment_note_edit.xml +++ b/app/src/main/res/layout/fragment_note_edit.xml @@ -70,6 +70,21 @@ app:srcCompat="@drawable/ic_keyboard_arrow_down_white_24dp" tools:visibility="visible" /> + + + app:layout_anchorGravity="bottom|end" /> diff --git a/app/src/main/res/layout/fragment_note_preview.xml b/app/src/main/res/layout/fragment_note_preview.xml index 82aeadfc0..e5c573ea2 100644 --- a/app/src/main/res/layout/fragment_note_preview.xml +++ b/app/src/main/res/layout/fragment_note_preview.xml @@ -100,7 +100,7 @@ android:text="@string/noteMode_plain_edit" android:visibility="visible" app:backgroundTint="@color/defaultBrand" - app:icon="@drawable/ic_edit_grey600_24dp" - app:layout_anchor="@+id/direct_editing" - app:layout_anchorGravity="center" /> + app:icon="@drawable/ic_notes" + app:layout_anchor="@id/scrollView" + app:layout_anchorGravity="bottom|end" /> diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index b42e9c41b..e7c27f676 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -82,4 +82,8 @@ 56dp 60dp 24dp + + 56dp + 72dp + 64dp