Loading app/src/main/java/it/niedermann/owncloud/notes/edit/NoteDirectEditFragment.kt +59 −49 Original line number Original line Diff line number Diff line Loading @@ -50,8 +50,8 @@ import java.util.concurrent.TimeUnit class NoteDirectEditFragment : BaseNoteFragment(), Branded { class NoteDirectEditFragment : BaseNoteFragment(), Branded { private var _binding: FragmentNoteDirectEditBinding? = null private var _binding: FragmentNoteDirectEditBinding? = null private val binding: FragmentNoteDirectEditBinding private val binding: FragmentNoteDirectEditBinding? get() = _binding!! get() = _binding private val disposables: DisposableSet = DisposableSet() private val disposables: DisposableSet = DisposableSet() private var switchToEditPending = false private var switchToEditPending = false Loading Loading @@ -81,20 +81,22 @@ class NoteDirectEditFragment : BaseNoteFragment(), Branded { inflater: LayoutInflater, inflater: LayoutInflater, container: ViewGroup?, container: ViewGroup?, savedInstanceState: Bundle?, savedInstanceState: Bundle?, ): View { ): View? { Log.d(TAG, "onCreateView() called") Log.d(TAG, "onCreateView() called") _binding = FragmentNoteDirectEditBinding.inflate(inflater, container, false) _binding = FragmentNoteDirectEditBinding.inflate(inflater, container, false) setupFab() setupFab() prepareWebView() prepareWebView() return binding.root return binding?.root } } @SuppressLint("ClickableViewAccessibility") // touch listener only for UI purposes, no need to handle click @SuppressLint("ClickableViewAccessibility") // touch listener only for UI purposes, no need to handle click private fun setupFab() { private fun setupFab() { binding.plainEditingFab.isExtended = false binding?.run { ExtendedFabUtil.toggleExtendedOnLongClick(binding.plainEditingFab) plainEditingFab.isExtended = false ExtendedFabUtil.toggleExtendedOnLongClick(plainEditingFab) // manually detect scroll as we can't get it from the webview (maybe with custom JS?) // manually detect scroll as we can't get it from the webview (maybe with custom JS?) binding.noteWebview.setOnTouchListener { _, event -> noteWebview.setOnTouchListener { _, event -> when (event.action) { when (event.action) { MotionEvent.ACTION_DOWN -> { MotionEvent.ACTION_DOWN -> { scrollStart = event.y.toInt() scrollStart = event.y.toInt() Loading @@ -102,7 +104,7 @@ class NoteDirectEditFragment : BaseNoteFragment(), Branded { MotionEvent.ACTION_UP -> { MotionEvent.ACTION_UP -> { val scrollEnd = event.y.toInt() val scrollEnd = event.y.toInt() ExtendedFabUtil.toggleVisibilityOnScroll( ExtendedFabUtil.toggleVisibilityOnScroll( binding.plainEditingFab, plainEditingFab, scrollStart, scrollStart, scrollEnd, scrollEnd, ) ) Loading @@ -110,12 +112,13 @@ class NoteDirectEditFragment : BaseNoteFragment(), Branded { } } return@setOnTouchListener false return@setOnTouchListener false } } binding.plainEditingFab.setOnClickListener { switchToPlainEdit() } plainEditingFab.setOnClickListener { switchToPlainEdit() } } } } private fun switchToPlainEdit() { private fun switchToPlainEdit() { switchToEditPending = true switchToEditPending = true binding.noteWebview.evaluateJavascript(JS_CLOSE) { result -> binding?.noteWebview?.evaluateJavascript(JS_CLOSE) { result -> val resultWithoutQuotes = result.replace("\"", "") val resultWithoutQuotes = result.replace("\"", "") if (resultWithoutQuotes != JS_RESULT_OK) { if (resultWithoutQuotes != JS_RESULT_OK) { Log.w(TAG, "Closing via JS failed: $resultWithoutQuotes") Log.w(TAG, "Closing via JS failed: $resultWithoutQuotes") Loading @@ -128,7 +131,7 @@ class NoteDirectEditFragment : BaseNoteFragment(), Branded { override fun onDestroyView() { override fun onDestroyView() { super.onDestroyView() super.onDestroyView() disposables.dispose() disposables.dispose() binding.noteWebview.destroy() binding?.noteWebview?.destroy() _binding = null _binding = null } } Loading @@ -137,7 +140,7 @@ class NoteDirectEditFragment : BaseNoteFragment(), Branded { val timeoutDisposable = Single.just(Unit) val timeoutDisposable = Single.just(Unit) .delay(LOAD_TIMEOUT_SECONDS, TimeUnit.SECONDS) .delay(LOAD_TIMEOUT_SECONDS, TimeUnit.SECONDS) .map { .map { if (!binding.noteWebview.isVisible) { if (binding?.noteWebview?.isVisible == false) { Log.w(TAG, "Editor not loaded after $LOAD_TIMEOUT_SECONDS seconds") Log.w(TAG, "Editor not loaded after $LOAD_TIMEOUT_SECONDS seconds") handleLoadError() handleLoadError() } } Loading Loading @@ -197,7 +200,7 @@ class NoteDirectEditFragment : BaseNoteFragment(), Branded { if (BuildConfig.DEBUG) { if (BuildConfig.DEBUG) { Log.d(TAG, "loadNoteInWebView: url = $url") Log.d(TAG, "loadNoteInWebView: url = $url") } } binding.noteWebview.loadUrl(url) binding?.noteWebview?.loadUrl(url) } } }, { throwable -> }, { throwable -> handleLoadError() handleLoadError() Loading @@ -208,8 +211,9 @@ class NoteDirectEditFragment : BaseNoteFragment(), Branded { } } private fun handleLoadError() { private fun handleLoadError() { binding?.run { val snackbar = BrandedSnackbar.make( val snackbar = BrandedSnackbar.make( binding.plainEditingFab, plainEditingFab, getString(R.string.direct_editing_error), getString(R.string.direct_editing_error), Snackbar.LENGTH_INDEFINITE, Snackbar.LENGTH_INDEFINITE, ) ) Loading @@ -226,12 +230,13 @@ class NoteDirectEditFragment : BaseNoteFragment(), Branded { snackbar.show() snackbar.show() } } } override fun shouldShowToolbar(): Boolean = false override fun shouldShowToolbar(): Boolean = false @SuppressLint("SetJavaScriptEnabled") @SuppressLint("SetJavaScriptEnabled") private fun prepareWebView() { private fun prepareWebView() { binding.noteWebview.settings.run { binding?.noteWebview?.settings?.run { // enable zoom // enable zoom setSupportZoom(true) setSupportZoom(true) builtInZoomControls = true builtInZoomControls = true Loading Loading @@ -260,15 +265,15 @@ class NoteDirectEditFragment : BaseNoteFragment(), Branded { if (BuildConfig.DEBUG) { if (BuildConfig.DEBUG) { // caching disabled in debug mode // caching disabled in debug mode binding.noteWebview.settings.cacheMode = WebSettings.LOAD_NO_CACHE binding?.noteWebview?.settings?.cacheMode = WebSettings.LOAD_NO_CACHE } } binding.noteWebview.addJavascriptInterface( binding?.noteWebview?.addJavascriptInterface( DirectEditingMobileInterface(this), DirectEditingMobileInterface(this), JS_INTERFACE_NAME, JS_INTERFACE_NAME, ) ) binding.noteWebview.webViewClient = object : WebViewClient() { binding?.noteWebview?.webViewClient = object : WebViewClient() { override fun onReceivedError( override fun onReceivedError( view: WebView?, view: WebView?, request: WebResourceRequest?, request: WebResourceRequest?, Loading Loading @@ -316,8 +321,11 @@ class NoteDirectEditFragment : BaseNoteFragment(), Branded { override fun applyBrand(color: Int) { override fun applyBrand(color: Int) { val util = BrandingUtil.of(color, requireContext()) val util = BrandingUtil.of(color, requireContext()) util.material.themeExtendedFAB(binding.plainEditingFab) util.platform.colorCircularProgressBar(binding.progress, ColorRole.PRIMARY) binding?.run { util.material.themeExtendedFAB(plainEditingFab) util.platform.colorCircularProgressBar(progress, ColorRole.PRIMARY) } } } private class DirectEditingMobileInterface(val noteDirectEditFragment: NoteDirectEditFragment) { private class DirectEditingMobileInterface(val noteDirectEditFragment: NoteDirectEditFragment) { Loading Loading @@ -382,9 +390,11 @@ class NoteDirectEditFragment : BaseNoteFragment(), Branded { private fun toggleLoadingUI(loading: Boolean) { private fun toggleLoadingUI(loading: Boolean) { activity?.runOnUiThread { activity?.runOnUiThread { binding.progress.isVisible = loading binding?.run { binding.noteWebview.isVisible = !loading progress.isVisible = loading binding.plainEditingFab.isVisible = !loading noteWebview.isVisible = !loading plainEditingFab.isVisible = !loading } } } } } Loading Loading
app/src/main/java/it/niedermann/owncloud/notes/edit/NoteDirectEditFragment.kt +59 −49 Original line number Original line Diff line number Diff line Loading @@ -50,8 +50,8 @@ import java.util.concurrent.TimeUnit class NoteDirectEditFragment : BaseNoteFragment(), Branded { class NoteDirectEditFragment : BaseNoteFragment(), Branded { private var _binding: FragmentNoteDirectEditBinding? = null private var _binding: FragmentNoteDirectEditBinding? = null private val binding: FragmentNoteDirectEditBinding private val binding: FragmentNoteDirectEditBinding? get() = _binding!! get() = _binding private val disposables: DisposableSet = DisposableSet() private val disposables: DisposableSet = DisposableSet() private var switchToEditPending = false private var switchToEditPending = false Loading Loading @@ -81,20 +81,22 @@ class NoteDirectEditFragment : BaseNoteFragment(), Branded { inflater: LayoutInflater, inflater: LayoutInflater, container: ViewGroup?, container: ViewGroup?, savedInstanceState: Bundle?, savedInstanceState: Bundle?, ): View { ): View? { Log.d(TAG, "onCreateView() called") Log.d(TAG, "onCreateView() called") _binding = FragmentNoteDirectEditBinding.inflate(inflater, container, false) _binding = FragmentNoteDirectEditBinding.inflate(inflater, container, false) setupFab() setupFab() prepareWebView() prepareWebView() return binding.root return binding?.root } } @SuppressLint("ClickableViewAccessibility") // touch listener only for UI purposes, no need to handle click @SuppressLint("ClickableViewAccessibility") // touch listener only for UI purposes, no need to handle click private fun setupFab() { private fun setupFab() { binding.plainEditingFab.isExtended = false binding?.run { ExtendedFabUtil.toggleExtendedOnLongClick(binding.plainEditingFab) plainEditingFab.isExtended = false ExtendedFabUtil.toggleExtendedOnLongClick(plainEditingFab) // manually detect scroll as we can't get it from the webview (maybe with custom JS?) // manually detect scroll as we can't get it from the webview (maybe with custom JS?) binding.noteWebview.setOnTouchListener { _, event -> noteWebview.setOnTouchListener { _, event -> when (event.action) { when (event.action) { MotionEvent.ACTION_DOWN -> { MotionEvent.ACTION_DOWN -> { scrollStart = event.y.toInt() scrollStart = event.y.toInt() Loading @@ -102,7 +104,7 @@ class NoteDirectEditFragment : BaseNoteFragment(), Branded { MotionEvent.ACTION_UP -> { MotionEvent.ACTION_UP -> { val scrollEnd = event.y.toInt() val scrollEnd = event.y.toInt() ExtendedFabUtil.toggleVisibilityOnScroll( ExtendedFabUtil.toggleVisibilityOnScroll( binding.plainEditingFab, plainEditingFab, scrollStart, scrollStart, scrollEnd, scrollEnd, ) ) Loading @@ -110,12 +112,13 @@ class NoteDirectEditFragment : BaseNoteFragment(), Branded { } } return@setOnTouchListener false return@setOnTouchListener false } } binding.plainEditingFab.setOnClickListener { switchToPlainEdit() } plainEditingFab.setOnClickListener { switchToPlainEdit() } } } } private fun switchToPlainEdit() { private fun switchToPlainEdit() { switchToEditPending = true switchToEditPending = true binding.noteWebview.evaluateJavascript(JS_CLOSE) { result -> binding?.noteWebview?.evaluateJavascript(JS_CLOSE) { result -> val resultWithoutQuotes = result.replace("\"", "") val resultWithoutQuotes = result.replace("\"", "") if (resultWithoutQuotes != JS_RESULT_OK) { if (resultWithoutQuotes != JS_RESULT_OK) { Log.w(TAG, "Closing via JS failed: $resultWithoutQuotes") Log.w(TAG, "Closing via JS failed: $resultWithoutQuotes") Loading @@ -128,7 +131,7 @@ class NoteDirectEditFragment : BaseNoteFragment(), Branded { override fun onDestroyView() { override fun onDestroyView() { super.onDestroyView() super.onDestroyView() disposables.dispose() disposables.dispose() binding.noteWebview.destroy() binding?.noteWebview?.destroy() _binding = null _binding = null } } Loading @@ -137,7 +140,7 @@ class NoteDirectEditFragment : BaseNoteFragment(), Branded { val timeoutDisposable = Single.just(Unit) val timeoutDisposable = Single.just(Unit) .delay(LOAD_TIMEOUT_SECONDS, TimeUnit.SECONDS) .delay(LOAD_TIMEOUT_SECONDS, TimeUnit.SECONDS) .map { .map { if (!binding.noteWebview.isVisible) { if (binding?.noteWebview?.isVisible == false) { Log.w(TAG, "Editor not loaded after $LOAD_TIMEOUT_SECONDS seconds") Log.w(TAG, "Editor not loaded after $LOAD_TIMEOUT_SECONDS seconds") handleLoadError() handleLoadError() } } Loading Loading @@ -197,7 +200,7 @@ class NoteDirectEditFragment : BaseNoteFragment(), Branded { if (BuildConfig.DEBUG) { if (BuildConfig.DEBUG) { Log.d(TAG, "loadNoteInWebView: url = $url") Log.d(TAG, "loadNoteInWebView: url = $url") } } binding.noteWebview.loadUrl(url) binding?.noteWebview?.loadUrl(url) } } }, { throwable -> }, { throwable -> handleLoadError() handleLoadError() Loading @@ -208,8 +211,9 @@ class NoteDirectEditFragment : BaseNoteFragment(), Branded { } } private fun handleLoadError() { private fun handleLoadError() { binding?.run { val snackbar = BrandedSnackbar.make( val snackbar = BrandedSnackbar.make( binding.plainEditingFab, plainEditingFab, getString(R.string.direct_editing_error), getString(R.string.direct_editing_error), Snackbar.LENGTH_INDEFINITE, Snackbar.LENGTH_INDEFINITE, ) ) Loading @@ -226,12 +230,13 @@ class NoteDirectEditFragment : BaseNoteFragment(), Branded { snackbar.show() snackbar.show() } } } override fun shouldShowToolbar(): Boolean = false override fun shouldShowToolbar(): Boolean = false @SuppressLint("SetJavaScriptEnabled") @SuppressLint("SetJavaScriptEnabled") private fun prepareWebView() { private fun prepareWebView() { binding.noteWebview.settings.run { binding?.noteWebview?.settings?.run { // enable zoom // enable zoom setSupportZoom(true) setSupportZoom(true) builtInZoomControls = true builtInZoomControls = true Loading Loading @@ -260,15 +265,15 @@ class NoteDirectEditFragment : BaseNoteFragment(), Branded { if (BuildConfig.DEBUG) { if (BuildConfig.DEBUG) { // caching disabled in debug mode // caching disabled in debug mode binding.noteWebview.settings.cacheMode = WebSettings.LOAD_NO_CACHE binding?.noteWebview?.settings?.cacheMode = WebSettings.LOAD_NO_CACHE } } binding.noteWebview.addJavascriptInterface( binding?.noteWebview?.addJavascriptInterface( DirectEditingMobileInterface(this), DirectEditingMobileInterface(this), JS_INTERFACE_NAME, JS_INTERFACE_NAME, ) ) binding.noteWebview.webViewClient = object : WebViewClient() { binding?.noteWebview?.webViewClient = object : WebViewClient() { override fun onReceivedError( override fun onReceivedError( view: WebView?, view: WebView?, request: WebResourceRequest?, request: WebResourceRequest?, Loading Loading @@ -316,8 +321,11 @@ class NoteDirectEditFragment : BaseNoteFragment(), Branded { override fun applyBrand(color: Int) { override fun applyBrand(color: Int) { val util = BrandingUtil.of(color, requireContext()) val util = BrandingUtil.of(color, requireContext()) util.material.themeExtendedFAB(binding.plainEditingFab) util.platform.colorCircularProgressBar(binding.progress, ColorRole.PRIMARY) binding?.run { util.material.themeExtendedFAB(plainEditingFab) util.platform.colorCircularProgressBar(progress, ColorRole.PRIMARY) } } } private class DirectEditingMobileInterface(val noteDirectEditFragment: NoteDirectEditFragment) { private class DirectEditingMobileInterface(val noteDirectEditFragment: NoteDirectEditFragment) { Loading Loading @@ -382,9 +390,11 @@ class NoteDirectEditFragment : BaseNoteFragment(), Branded { private fun toggleLoadingUI(loading: Boolean) { private fun toggleLoadingUI(loading: Boolean) { activity?.runOnUiThread { activity?.runOnUiThread { binding.progress.isVisible = loading binding?.run { binding.noteWebview.isVisible = !loading progress.isVisible = loading binding.plainEditingFab.isVisible = !loading noteWebview.isVisible = !loading plainEditingFab.isVisible = !loading } } } } } Loading