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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,8 @@
android:name="com.nextcloud.client.player.ui.PlayerActivity"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
android:launchMode="singleTask"
android:supportsPictureInPicture="true" />
android:supportsPictureInPicture="true"
android:theme="@style/Theme.ownCloud.NoActionBar" />

<service
android:name="com.nextcloud.client.player.media3.PlaybackService"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import com.nextcloud.client.di.ViewModelFactory
import com.nextcloud.client.player.model.file.PlaybackFileType
import com.nextcloud.client.player.ui.audio.AudioPlayerView
import com.nextcloud.client.player.ui.video.VideoPlayerView
import com.nextcloud.ui.fileactions.FileAction
import com.nextcloud.ui.fileactions.FileActionsBottomSheet
import com.nextcloud.utils.extensions.getSerializableArgument
import com.owncloud.android.R
Expand Down Expand Up @@ -184,18 +183,19 @@ class PlayerActivity :

private fun handleEvent(event: PlayerScreenEvent) {
when (event) {
is PlayerScreenEvent.ShowFileActions -> showFileActions(event.file, event.actionIds)
is PlayerScreenEvent.ShowFileActions -> showFileActions(event.file, event.actionsToHide)
is PlayerScreenEvent.ShowFileDetails -> showFileDetails(event.file)
is PlayerScreenEvent.ShowFileExportStartedMessage -> showFileExportStartedMessage()
is PlayerScreenEvent.ShowShareFileDialog -> fileOperationsHelper.sendShareFile(event.file)
is PlayerScreenEvent.ShowRemoveFileDialog -> showRemoveFileDialog(event.file)
is PlayerScreenEvent.LaunchOpenFileIntent -> fileOperationsHelper.openFile(event.file)
is PlayerScreenEvent.LaunchStreamFileIntent -> fileOperationsHelper.streamMediaFile(event.file)
is PlayerScreenEvent.ToggleFileLock -> fileOperationsHelper.toggleFileLock(event.file, event.shouldBeLocked)
is PlayerScreenEvent.AddFileToAlbum -> fileOperationsHelper.addFileToAlbum(listOf(event.file))
}
}

private fun showFileActions(file: OCFile, actionIds: List<Int>) {
val actionsToHide = FileAction.entries.map(FileAction::id).filter { it !in actionIds }
private fun showFileActions(file: OCFile, actionsToHide: List<Int>) {
FileActionsBottomSheet.newInstance(file, false, actionsToHide)
.setResultListener(supportFragmentManager, this) { viewModel.onFileActionChosen(file, it) }
.show(supportFragmentManager, "actions")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import com.owncloud.android.datamodel.OCFile

sealed interface PlayerScreenEvent {

data class ShowFileActions(val file: OCFile, val actionIds: List<Int>) : PlayerScreenEvent
data class ShowFileActions(val file: OCFile, val actionsToHide: List<Int>) : PlayerScreenEvent

data class ShowFileDetails(val file: OCFile) : PlayerScreenEvent

Expand All @@ -24,4 +24,8 @@ sealed interface PlayerScreenEvent {
data class LaunchOpenFileIntent(val file: OCFile) : PlayerScreenEvent

data class LaunchStreamFileIntent(val file: OCFile) : PlayerScreenEvent

data class ToggleFileLock(val file: OCFile, val shouldBeLocked: Boolean) : PlayerScreenEvent

data class AddFileToAlbum(val file: OCFile) : PlayerScreenEvent
}
29 changes: 19 additions & 10 deletions app/src/main/java/com/nextcloud/client/player/ui/PlayerViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import com.nextcloud.client.jobs.BackgroundJobManager
import com.nextcloud.client.jobs.download.FileDownloadHelper
import com.nextcloud.client.logger.Logger
import com.nextcloud.client.player.media3.PlaybackModel
import com.nextcloud.ui.fileactions.FileAction
import com.owncloud.android.R
import com.owncloud.android.datamodel.FileDataStorageManager
import com.owncloud.android.datamodel.OCFile
Expand All @@ -41,28 +42,36 @@ class PlayerViewModel @Inject constructor(
fun onMoreButtonClick() {
viewModelScope.launch {
val file = getCurrentOCFile() ?: return@launch
val actionIds = listOf(
R.id.action_see_details,
R.id.action_download_file,
R.id.action_export_file,
R.id.action_send_share_file,
R.id.action_remove_file,
R.id.action_open_file_with,
R.id.action_stream_media
)
eventChannel.trySend(PlayerScreenEvent.ShowFileActions(file, actionIds))
val actionsToHide = FileAction.getFilePreviewActions(file)
eventChannel.trySend(PlayerScreenEvent.ShowFileActions(file, actionsToHide))
}
}

fun onFileActionChosen(file: OCFile, actionId: Int) {
when (actionId) {
R.id.action_see_details -> eventChannel.trySend(PlayerScreenEvent.ShowFileDetails(file))

R.id.action_download_file -> startFileDownloading(file)

R.id.action_export_file -> startFileExport(file)

R.id.action_send_share_file -> eventChannel.trySend(PlayerScreenEvent.ShowShareFileDialog(file))

R.id.action_remove_file -> eventChannel.trySend(PlayerScreenEvent.ShowRemoveFileDialog(file))

R.id.action_open_file_with -> onOpenFileWithClick(file)

R.id.action_stream_media -> onStreamFileClick(file)

R.id.action_lock_file -> eventChannel.trySend(
PlayerScreenEvent.ToggleFileLock(file, shouldBeLocked = true)
)

R.id.action_unlock_file -> eventChannel.trySend(
PlayerScreenEvent.ToggleFileLock(file, shouldBeLocked = false)
)

R.id.action_add_to_album -> eventChannel.trySend(PlayerScreenEvent.AddFileToAlbum(file))
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,23 @@ package com.owncloud.android.ui.preview

import android.os.Bundle
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import androidx.activity.OnBackPressedCallback
import androidx.activity.addCallback
import androidx.core.content.ContextCompat
import androidx.core.os.bundleOf
import androidx.core.view.MenuProvider
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import com.google.android.material.snackbar.Snackbar
import com.nextcloud.client.account.UserAccountManager
import com.nextcloud.client.jobs.BackgroundJobManager
import com.nextcloud.client.player.media3.PlaybackModel
import com.nextcloud.client.player.model.ThumbnailLoader
import com.nextcloud.client.player.model.file.PlaybackCollection
Expand All @@ -29,14 +38,24 @@ import com.nextcloud.client.player.ui.PlayerLauncher
import com.nextcloud.client.player.util.PlayerUtil.applyVideoSize
import com.nextcloud.client.player.util.PlayerUtil.isPictureInPictureAllowed
import com.nextcloud.client.player.util.PlayerUtil.ownsPlayback
import com.nextcloud.ui.fileactions.FileAction
import com.nextcloud.ui.fileactions.FileActionsBottomSheet
import com.nextcloud.utils.extensions.getParcelableArgument
import com.nextcloud.utils.extensions.getSerializableArgument
import com.owncloud.android.R
import com.owncloud.android.databinding.PreviewPlaybackFragmentBinding
import com.owncloud.android.datamodel.OCFile
import com.owncloud.android.lib.common.utils.Log_OC
import com.owncloud.android.operations.FetchRemoteFileOperation
import com.owncloud.android.ui.dialog.ConfirmationDialogFragment
import com.owncloud.android.ui.dialog.RemoveFilesDialogFragment
import com.owncloud.android.utils.DisplayUtils
import com.owncloud.android.utils.MimeTypeUtil
import com.owncloud.android.utils.theme.ViewThemeUtils
import dagger.android.support.AndroidSupportInjection
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import javax.inject.Inject

/**
Expand All @@ -49,6 +68,7 @@ class PreviewPlaybackFragment :
PlaybackModel.Listener {

companion object {
private val TAG = PreviewPlaybackFragment::class.java.simpleName
private const val ARGUMENT_FILE = "ARGUMENT_FILE"
private const val ARGUMENT_COLLECTION = "ARGUMENT_COLLECTION"
private const val ARGUMENT_AUTOPLAY = "ARGUMENT_AUTOPLAY"
Expand Down Expand Up @@ -81,6 +101,15 @@ class PreviewPlaybackFragment :
@Inject
lateinit var thumbnailLoader: ThumbnailLoader

@Inject
lateinit var accountManager: UserAccountManager

@Inject
lateinit var backgroundJobManager: BackgroundJobManager

@Inject
lateinit var viewThemeUtils: ViewThemeUtils

private lateinit var binding: PreviewPlaybackFragmentBinding
private lateinit var file: OCFile
private lateinit var playbackFile: PlaybackFile
Expand Down Expand Up @@ -116,6 +145,133 @@ class PreviewPlaybackFragment :
return binding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
requireActivity().addMenuProvider(
object : MenuProvider {
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
menuInflater.inflate(R.menu.custom_menu_placeholder, menu)
val item = menu.findItem(R.id.custom_menu_placeholder_item)
item.icon?.let {
item.setIcon(
viewThemeUtils.platform.colorDrawable(
it,
ContextCompat.getColor(requireContext(), R.color.white)
)
)
}
}

override fun onMenuItemSelected(menuItem: MenuItem): Boolean = when (menuItem.itemId) {
R.id.custom_menu_placeholder_item -> {
onOverflowClick()
true
}

else -> false
}
},
viewLifecycleOwner,
Lifecycle.State.RESUMED
)
}

private fun onOverflowClick(isManualClick: Boolean = false) {
val storageManager = previewActivity()?.storageManager ?: return
val updatedFile = storageManager.getFileById(file.fileId)

// check for albums file for album file both local and remoteId will be same configured at operation level
if (!isManualClick && updatedFile != null && updatedFile.localId.toString() == updatedFile.remoteId) {
fetchFileMetaDataIfAbsent(updatedFile)
return
}

updatedFile?.let { actionsFile ->
val additionalFilter = FileAction.getFilePreviewActions(actionsFile)
FileActionsBottomSheet.newInstance(actionsFile, false, additionalFilter)
.setResultListener(childFragmentManager, viewLifecycleOwner) { itemId: Int ->
onFileActionChosen(itemId)
}
.show(childFragmentManager, "actions")
}
}

private fun fetchFileMetaDataIfAbsent(ocFile: OCFile) {
val previewActivity = previewActivity() ?: return
val context = context ?: return

previewActivity.showLoadingDialog(getString(R.string.wait_a_moment))
lifecycleScope.launch(Dispatchers.IO) {
val operation = FetchRemoteFileOperation(
context,
accountManager.user,
ocFile,
removeFileFromDb = true,
storageManager = previewActivity.storageManager
)
val result = operation.execute(context)

withContext(Dispatchers.Main) {
previewActivity.dismissLoadingDialog()

if (result?.isSuccess == true && result.resultData != null) {
file = result.resultData as OCFile
onOverflowClick(isManualClick = true)
} else {
Log_OC.d(TAG, result?.logMessage)
DisplayUtils.showSnackMessage(binding.root, result.getLogMessage(context))
}
}
}
}

@Suppress("CyclomaticComplexMethod")
private fun onFileActionChosen(itemId: Int) {
val previewActivity = previewActivity() ?: return
val fileOperationsHelper = previewActivity.fileOperationsHelper

when (itemId) {
R.id.action_see_details -> previewActivity.showDetails(file)

R.id.action_download_file -> previewActivity.requestForDownload(file)

R.id.action_export_file -> fileOperationsHelper.exportFiles(
arrayListOf(file),
context,
view,
backgroundJobManager
)

R.id.action_send_share_file -> if (file.isSharedWithMe && !file.canReshare()) {
Snackbar.make(requireView(), R.string.resharing_is_not_allowed, Snackbar.LENGTH_LONG).show()
} else {
fileOperationsHelper.sendShareFile(file)
}

R.id.action_send_file -> fileOperationsHelper.sendShareFile(file, true)

R.id.action_open_file_with -> fileOperationsHelper.openFile(file)

R.id.action_stream_media -> {
playbackModel.pause()
fileOperationsHelper.streamMediaFile(file)
}

R.id.action_remove_file -> {
playbackModel.pause()
RemoveFilesDialogFragment.newInstance(
file
).show(parentFragmentManager, ConfirmationDialogFragment.FTAG_CONFIRMATION)
}

R.id.action_add_to_album -> fileOperationsHelper.addFileToAlbum(listOf(file))

R.id.action_lock_file -> fileOperationsHelper.toggleFileLock(file, true)

R.id.action_unlock_file -> fileOperationsHelper.toggleFileLock(file, false)
}
}

private fun registerPictureInPictureOnBack() {
if (!pictureInPictureOnBack || !MimeTypeUtil.isVideo(file)) {
return
Expand Down
Loading