Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import com.owncloud.android.R
import com.owncloud.android.lib.common.utils.Log_OC
import com.owncloud.android.ui.activity.FileDisplayActivity
import com.owncloud.android.ui.fragment.EmptyListState
import com.owncloud.android.ui.fragment.FabState
import com.owncloud.android.utils.ScreenshotTest
import org.junit.Assert
import org.junit.Rule
Expand All @@ -48,7 +49,7 @@ class FileDisplayActivityScreenshotIT : AbstractIT() {
scenario.onActivity { sut ->
sut.run {
listOfFilesFragment?.let {
it.setFabEnabled(false)
it.setFabState(FabState.DISABLED)
resetScrolling(true)
it.setEmptyListMessage(EmptyListState.LOADING)
it.isLoading = false
Expand Down Expand Up @@ -78,7 +79,7 @@ class FileDisplayActivityScreenshotIT : AbstractIT() {
activity = sut
val fragment = sut.listOfFilesFragment
Assert.assertNotNull(fragment)
fragment!!.setFabEnabled(false)
fragment!!.setFabState(FabState.DISABLED)
fragment.setEmptyListMessage(EmptyListState.LOADING)
fragment.isLoading = false
}
Expand All @@ -91,7 +92,7 @@ class FileDisplayActivityScreenshotIT : AbstractIT() {
.perform(NavigationViewActions.navigateTo(R.id.nav_all_files))

val fragment = activity!!.listOfFilesFragment
fragment!!.setFabEnabled(false)
fragment!!.setFabState(FabState.DISABLED)
fragment.setEmptyListMessage(EmptyListState.LOADING)
fragment.isLoading = false

Expand All @@ -117,7 +118,7 @@ class FileDisplayActivityScreenshotIT : AbstractIT() {
resetScrolling(true)

listOfFilesFragment?.let {
it.setFabEnabled(false)
it.setFabState(FabState.DISABLED)
it.setEmptyListMessage(EmptyListState.LOADING)
it.isLoading = false
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1097,7 +1097,7 @@ class FileDisplayActivity :
file = currentFile

currentFile?.let {
listOfFiles.setFabVisible(it.canCreateFileAndFolder())
listOfFiles.updateFabState()
listOfFiles.registerFabListener()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ open class ExtendedListFragment :
if (activity is FileDisplayActivity) {
val fragment = activity.leftFragment
if (fragment is OCFileListFragment) {
fragment.setFabVisible(!hasFocus)
if (hasFocus) fragment.setFabState(FabState.HIDDEN) else fragment.updateFabState()
}
}

Expand Down
38 changes: 38 additions & 0 deletions app/src/main/java/com/owncloud/android/ui/fragment/FabState.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2026 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
package com.owncloud.android.ui.fragment

import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.nextcloud.utils.extensions.slideHideBottomBehavior
import com.owncloud.android.datamodel.FileDataStorageManager
import com.owncloud.android.datamodel.OCFile
import com.owncloud.android.utils.theme.ViewThemeUtils

enum class FabState {
HIDDEN,
DISABLED,
ENABLED;

fun applyTo(fab: FloatingActionButton, viewThemeUtils: ViewThemeUtils) {
val visible = this != HIDDEN
if (visible) fab.show() else fab.hide()
fab.isEnabled = this == ENABLED
viewThemeUtils.material.themeFAB(fab)
fab.slideHideBottomBehavior(visible)
}

companion object {
fun from(folder: OCFile?, storageManager: FileDataStorageManager?, hiddenByScreen: Boolean): FabState = when {
hiddenByScreen || folder.isReadOnly(storageManager) -> HIDDEN
folder != null && (folder.canCreateFileAndFolder() || folder.isOfflineOperation) -> ENABLED
else -> DISABLED
}

private fun OCFile?.isReadOnly(storageManager: FileDataStorageManager?): Boolean =
this != null && storageManager?.isReadOnly(this) == true
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ class GalleryFragment :
// always show first stored items
showAllGalleryItems()

setFabVisible(false)
setFabState(FabState.HIDDEN)

searchAndDisplay()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -379,10 +379,8 @@ open class OCFileListFragment :
setAdapter(args)

hideFab = args?.getBoolean(ARG_HIDE_FAB, false) == true
if (hideFab) {
setFabVisible(false)
} else {
setFabVisible(currentFile?.let { canCreateInside(it) } ?: true)
updateFabState()
if (!hideFab) {
registerFabListener()
}

Expand Down Expand Up @@ -477,50 +475,23 @@ open class OCFileListFragment :
}
}

fun setFabVisible(visible: Boolean) {
val fab = fabMain ?: return

fun updateFabState() {
val fileDisplayActivity = activity as? FileDisplayActivity
if (fileDisplayActivity != null &&
(fileDisplayActivity.isAlbumsFragment || fileDisplayActivity.isAlbumItemsFragment)
) {
fab.hide()
return
}

val activity = activity ?: return
activity.runOnUiThread {
if (visible) {
fab.show()
viewThemeUtils.material.themeFAB(fab)
} else {
fab.hide()
}
fab.slideHideBottomBehavior(visible)
}
val isAlbumScreen = fileDisplayActivity?.isAlbumsFragment == true ||
fileDisplayActivity?.isAlbumItemsFragment == true
val hiddenByScreen = hideFab || isSearchFragment || isAlbumScreen
setFabState(FabState.from(currentFile, containerActivity?.storageManager, hiddenByScreen))
}

fun setFabEnabled(enabled: Boolean) {
fun setFabState(state: FabState) {
val fab = fabMain ?: return
val activity = activity ?: return
activity.runOnUiThread {
fab.isEnabled = enabled
viewThemeUtils.material.themeFAB(fab)
}
activity?.runOnUiThread { state.applyTo(fab, viewThemeUtils) }
}

private fun setBottomNavigationVisible(visible: Boolean) {
val drawerActivity = activity as? DrawerActivity ?: return
drawerActivity.bottomNavigationView.slideHideBottomBehavior(visible)
}

private fun isReadOnlyFolder(folder: OCFile?): Boolean {
folder ?: return false
val storageManager = containerActivity?.storageManager ?: return false
return storageManager.isReadOnly(folder)
}

private fun canCreateInside(folder: OCFile): Boolean = folder.canCreateFileAndFolder() && !isReadOnlyFolder(folder)
//endregion

//region Create and upload actions
Expand Down Expand Up @@ -801,7 +772,9 @@ open class OCFileListFragment :
fileDisplayActivity.previewFile(
file,
object : CompletionCallback {
override fun onComplete(value: Boolean) = setFabVisible(value)
override fun onComplete(value: Boolean) {
if (value) updateFabState() else setFabState(FabState.HIDDEN)
}
}
)

Expand Down Expand Up @@ -833,7 +806,7 @@ open class OCFileListFragment :

when {
!file.isEncrypted && fileDisplayActivity != null && fileDisplayActivity.canPreviewInAudioPlayer(file) -> {
setFabVisible(false)
setFabState(FabState.HIDDEN)
fileDisplayActivity.startAudioPreview(file, true, true)
}

Expand Down Expand Up @@ -1192,7 +1165,7 @@ open class OCFileListFragment :
fun refreshDirectory() {
isSearchFragment = false
val folder = currentFile ?: return
setFabVisible(canCreateInside(folder))
updateFabState()
listDirectory(folder, MainApp.isOnlyOnDevice())
}

Expand All @@ -1210,12 +1183,8 @@ open class OCFileListFragment :
fileListLayoutManager?.setLayoutViewMode()
updateSortButtonLabel()
setLayoutSwitchButton()

val folder = currentFile
val readOnly = isReadOnlyFolder(folder)
setFabVisible(!hideFab && !readOnly)
updateFabState()
setBottomNavigationVisible(!hideFab)
setFabEnabled(folder != null && !readOnly && (folder.canCreateFileAndFolder() || folder.isOfflineOperation))

activeActionMode?.invalidate()
}
Expand Down Expand Up @@ -1349,7 +1318,7 @@ open class OCFileListFragment :

applySearchEvent(event)
isSearchFragment = true
setFabVisible(false)
setFabState(FabState.HIDDEN)

mainHandler.post {
updateSortButtonLabel()
Expand Down Expand Up @@ -1446,7 +1415,7 @@ open class OCFileListFragment :
updateActionBarTitleAndHomeButton(null)
}

currentFile?.let { setFabVisible(canCreateInside(it)) }
updateFabState()
setBottomNavigationVisible(true)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ internal class OCFileListMultiChoiceModeListener(private val fragment: OCFileLis

mode?.invalidate()
colorStatusBar(activity)
fragment.setFabVisible(false)
fragment.setFabState(FabState.HIDDEN)

if (fragment is GalleryFragment && activity is AlbumsPickerActivity) {
placeholderItem.isVisible = false
Expand Down Expand Up @@ -139,9 +139,7 @@ internal class OCFileListMultiChoiceModeListener(private val fragment: OCFileLis
Log_OC.d(TAG, "Selection mode finished")
activeActionMode = null

if (!fragment.hideFab && !fragment.isSearchFragment) {
fragment.currentFile?.let { fragment.setFabVisible(it.canCreateFileAndFolder()) }
}
fragment.updateFabState()

fragment.activity?.let {
fragment.viewThemeUtils.platform.resetStatusBar(it)
Expand Down
Loading