diff --git a/storage-sample/src/main/java/com/omh/android/storage/sample/presentation/file_viewer/FileAdapter.kt b/storage-sample/src/main/java/com/omh/android/storage/sample/presentation/file_viewer/FileAdapter.kt index 9797a6a2..9ee757ef 100644 --- a/storage-sample/src/main/java/com/omh/android/storage/sample/presentation/file_viewer/FileAdapter.kt +++ b/storage-sample/src/main/java/com/omh/android/storage/sample/presentation/file_viewer/FileAdapter.kt @@ -94,6 +94,8 @@ class FileAdapter( fun onFileClicked(file: OmhFile) fun onDeleteClicked(file: OmhFile) + + fun onUpdateClicked(file: OmhFile) } abstract class FileViewHolder(binding: View) : RecyclerView.ViewHolder(binding) { @@ -114,6 +116,7 @@ class FileAdapter( loadFileIcon(context, iconLink, fileIcon) root.setOnClickListener { listener.onFileClicked(file) } buttonDelete.setOnClickListener { listener.onDeleteClicked(file) } + buttonUpdate.setOnClickListener { listener.onUpdateClicked(file) } } } } @@ -131,6 +134,7 @@ class FileAdapter( loadFileIcon(context, iconLink, fileIcon) root.setOnClickListener { listener.onFileClicked(file) } buttonDelete.setOnClickListener { listener.onDeleteClicked(file) } + buttonUpdate.setOnClickListener { listener.onUpdateClicked(file) } } } } diff --git a/storage-sample/src/main/java/com/omh/android/storage/sample/presentation/file_viewer/FileViewerActivity.kt b/storage-sample/src/main/java/com/omh/android/storage/sample/presentation/file_viewer/FileViewerActivity.kt index fc8e4141..151c53fb 100644 --- a/storage-sample/src/main/java/com/omh/android/storage/sample/presentation/file_viewer/FileViewerActivity.kt +++ b/storage-sample/src/main/java/com/omh/android/storage/sample/presentation/file_viewer/FileViewerActivity.kt @@ -46,7 +46,8 @@ class FileViewerActivity : private lateinit var binding: ActivityFileViewerBinding private var filesAdapter: FileAdapter? = null private lateinit var onBackPressedCallback: OnBackPressedCallback - private lateinit var filePicker: ActivityResultLauncher + private lateinit var filePickerUpload: ActivityResultLauncher + private lateinit var filePickerUpdate: ActivityResultLauncher private lateinit var requestPermissionLauncher: ActivityResultLauncher> override fun onCreate(savedInstanceState: Bundle?) { @@ -61,11 +62,24 @@ class FileViewerActivity : } } - filePicker = registerForActivityResult( + filePickerUpload = registerForActivityResult(ActivityResultContracts.GetContent() + ) { uri: Uri? -> + uri?.let { + val titleText = getString(R.string.text_upload_file_title) + val positiveText = getString(R.string.text_upload) + + showBeforeSubmitFileDialog(uri, titleText, positiveText, ::configureUploadFilePositiveButtonEvent) + } + } + + filePickerUpdate = registerForActivityResult( ActivityResultContracts.GetContent() ) { uri: Uri? -> - uri?.let { validUri -> - showUploadFileDialog(validUri) + uri?.let { + val titleText = getString(R.string.text_update_file_title) + val positiveText = getString(R.string.text_update) + + showBeforeSubmitFileDialog(uri, titleText, positiveText, ::configureUpdateFilePositiveButtonEvent) } } @@ -110,9 +124,7 @@ class FileViewerActivity : } R.id.uploadFile -> { - filePicker.launch( - FileViewerViewModel.ANY_MIME_TYPE - ) + filePickerUpload.launch(FileViewerViewModel.ANY_MIME_TYPE) } R.id.signOut -> { @@ -130,6 +142,7 @@ class FileViewerActivity : FileViewerViewState.Finish -> buildFinishState() FileViewerViewState.CheckPermissions -> requestPermissions() FileViewerViewState.SignOut -> buildSignOutState() + is FileViewerViewState.ShowUpdateFilePicker -> launchUpdateFilePicker() } private fun buildInitialState() { @@ -195,6 +208,14 @@ class FileViewerActivity : dispatchEvent(FileViewerViewEvent.DeleteFile(file)) } + override fun onUpdateClicked(file: OmhFile) { + dispatchEvent(FileViewerViewEvent.UpdateFileClicked(file)) + } + + private fun launchUpdateFilePicker() { + filePickerUpdate.launch(FileViewerViewModel.ANY_MIME_TYPE) + } + private fun buildFinishState() = finish().also { finishAffinity() } private fun showCreateFileDialog() { @@ -266,18 +287,22 @@ class FileViewerActivity : } } - private fun showUploadFileDialog(uri: Uri) { - val fileName: String = DocumentFile - .fromSingleUri(this, uri)?.name - ?: FileViewerViewModel.DEFAULT_FILE_NAME - + private fun showBeforeSubmitFileDialog( + uri: Uri, + titleText: String, + positiveTextButton: String, + positiveAction: (DialogInterface, String, Uri) -> Unit + ) { val dialogUploadFileView = DialogUploadFileBinding.inflate(layoutInflater) + val documentFileName = DocumentFile.fromSingleUri(this, uri)?.name + val fileName = viewModel.getFileName(documentFileName) + dialogUploadFileView.fileName.text = fileName val uploadFileDialogBuilder = AlertDialog.Builder(this) - .setTitle(getString(R.string.text_upload_file_title)) - .setPositiveButton(getString(R.string.text_upload)) { dialog, _ -> - configureUploadFilePositiveButtonEvent(dialog, fileName, uri) + .setTitle(titleText) + .setPositiveButton(positiveTextButton) { dialog, _ -> + positiveAction(dialog, fileName, uri) } .setNegativeButton(getString(R.string.text_cancel)) { dialog, _ -> dialog.cancel() @@ -303,6 +328,15 @@ class FileViewerActivity : dialog.dismiss() } + private fun configureUpdateFilePositiveButtonEvent( + dialog: DialogInterface, + fileName: String, + uri: Uri + ) { + dispatchEvent(FileViewerViewEvent.UpdateFile(this, uri, fileName)) + dialog.dismiss() + } + private fun requestPermissions() { val permissionsToRequest: Array = arrayOf( Manifest.permission.READ_EXTERNAL_STORAGE, diff --git a/storage-sample/src/main/java/com/omh/android/storage/sample/presentation/file_viewer/FileViewerViewEvent.kt b/storage-sample/src/main/java/com/omh/android/storage/sample/presentation/file_viewer/FileViewerViewEvent.kt index 39ee7a92..8119702a 100644 --- a/storage-sample/src/main/java/com/omh/android/storage/sample/presentation/file_viewer/FileViewerViewEvent.kt +++ b/storage-sample/src/main/java/com/omh/android/storage/sample/presentation/file_viewer/FileViewerViewEvent.kt @@ -56,4 +56,14 @@ sealed class FileViewerViewEvent : ViewEvent { override fun getEventName() = "FileViewerViewEvent.SignOut" } + + class UpdateFileClicked(val file: OmhFile) : FileViewerViewEvent() { + + override fun getEventName() = "FileViewerViewEvent.UpdateFileClicked" + } + + class UpdateFile(val context: Context, val uri: Uri, val fileName: String) : FileViewerViewEvent() { + + override fun getEventName() = "FileViewerViewEvent.UpdateFile" + } } diff --git a/storage-sample/src/main/java/com/omh/android/storage/sample/presentation/file_viewer/FileViewerViewModel.kt b/storage-sample/src/main/java/com/omh/android/storage/sample/presentation/file_viewer/FileViewerViewModel.kt index 0299fd00..8dbf8749 100644 --- a/storage-sample/src/main/java/com/omh/android/storage/sample/presentation/file_viewer/FileViewerViewModel.kt +++ b/storage-sample/src/main/java/com/omh/android/storage/sample/presentation/file_viewer/FileViewerViewModel.kt @@ -2,8 +2,8 @@ package com.omh.android.storage.sample.presentation.file_viewer import android.content.Context import android.net.Uri -import com.omh.android.auth.api.OmhAuthClient import android.os.Environment +import com.omh.android.auth.api.OmhAuthClient import com.omh.android.storage.api.OmhStorageClient import com.omh.android.storage.api.domain.model.OmhFile import com.omh.android.storage.api.domain.model.OmhFileType @@ -11,8 +11,8 @@ import com.omh.android.storage.api.domain.usecase.DownloadFileUseCaseResult import com.omh.android.storage.sample.domain.model.FileType import com.omh.android.storage.sample.presentation.BaseViewModel import com.omh.android.storage.sample.util.getNameWithExtension -import com.omh.android.storage.sample.util.normalizedMimeType import com.omh.android.storage.sample.util.isDownloadable +import com.omh.android.storage.sample.util.normalizedMimeType import dagger.hilt.android.lifecycle.HiltViewModel import java.io.File import java.io.FileOutputStream @@ -39,6 +39,7 @@ class FileViewerViewModel @Inject constructor( const val DEFAULT_FILE_NAME = "Untitled" } + var isUpload = false var isGridLayoutManager = true var createFileSelectedType: OmhFileType? = null private val parentIdStack = Stack().apply { push(ID_ROOT) } @@ -56,8 +57,10 @@ class FileViewerViewModel @Inject constructor( is FileViewerViewEvent.CreateFile -> createFileEvent(event) is FileViewerViewEvent.DeleteFile -> deleteFileEvent(event) is FileViewerViewEvent.UploadFile -> uploadFile(event) + is FileViewerViewEvent.UpdateFile -> updateFileEvent(event) FileViewerViewEvent.SignOut -> signOut() FileViewerViewEvent.DownloadFile -> downloadFileEvent() + is FileViewerViewEvent.UpdateFileClicked -> updateFileClickEvent(event) } } @@ -116,6 +119,7 @@ class FileViewerViewModel @Inject constructor( lastFileClicked?.let { file -> if (!file.isDownloadable()) { toastMessage.postValue("${file.name} is not downloadable") + refreshFileListEvent() return } @@ -138,6 +142,38 @@ class FileViewerViewModel @Inject constructor( } } + private fun updateFileEvent(event: FileViewerViewEvent.UpdateFile) { + val fileId = lastFileClicked?.id + + if (fileId.isNullOrBlank()) { + refreshFileListEvent() + return + } + + val filePath = getFile(event.context, event.uri, event.fileName) + val cancellable = omhStorageClient.updateFile(filePath, fileId) + .addOnSuccess { result -> + val resultMessage = if (result.file == null) { + "${event.fileName} was not updated" + } else { + "${event.fileName} was successfully updated" + } + + toastMessage.postValue(resultMessage) + + refreshFileListEvent() + } + .addOnFailure { e -> + toastMessage.postValue("ERROR: ${event.fileName} was not updated") + e.printStackTrace() + + refreshFileListEvent() + } + .execute() + + cancellableCollector.addCancellable(cancellable) + } + private fun createFileEvent(event: FileViewerViewEvent.CreateFile) { setState(FileViewerViewState.Loading) val parentId = parentIdStack.peek() @@ -234,6 +270,11 @@ class FileViewerViewModel @Inject constructor( cancellableCollector.addCancellable(cancellable) } + private fun updateFileClickEvent(event: FileViewerViewEvent.UpdateFileClicked) { + lastFileClicked = event.file + setState(FileViewerViewState.ShowUpdateFilePicker) + } + private fun handleDownloadSuccess( result: DownloadFileUseCaseResult, file: OmhFile @@ -253,4 +294,6 @@ class FileViewerViewModel @Inject constructor( super.onCleared() cancellableCollector.clear() } + + fun getFileName(documentFileName: String?): String = documentFileName ?: DEFAULT_FILE_NAME } diff --git a/storage-sample/src/main/java/com/omh/android/storage/sample/presentation/file_viewer/FileViewerViewState.kt b/storage-sample/src/main/java/com/omh/android/storage/sample/presentation/file_viewer/FileViewerViewState.kt index ebc51fe0..6cadbe44 100644 --- a/storage-sample/src/main/java/com/omh/android/storage/sample/presentation/file_viewer/FileViewerViewState.kt +++ b/storage-sample/src/main/java/com/omh/android/storage/sample/presentation/file_viewer/FileViewerViewState.kt @@ -39,4 +39,9 @@ sealed class FileViewerViewState : ViewState { override fun getName() = "FileViewerViewState.SignOut" } + + object ShowUpdateFilePicker : FileViewerViewState() { + + override fun getName() = "FileViewerViewState.FilePicker" + } } diff --git a/storage-sample/src/main/res/layout/file_grid_adapter.xml b/storage-sample/src/main/res/layout/file_grid_adapter.xml index fa0ab920..c3c54f29 100644 --- a/storage-sample/src/main/res/layout/file_grid_adapter.xml +++ b/storage-sample/src/main/res/layout/file_grid_adapter.xml @@ -9,6 +9,17 @@ android:background="@drawable/rounded_for_grid" android:orientation="vertical"> + + + + File Type: Upload File Upload + Update File + Update Cancel Sign out \ No newline at end of file