Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UI update a file #63

Merged
merged 9 commits into from
Jul 5, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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) }
}
}
}
Expand All @@ -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) }
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<String>
private lateinit var filePickerUpload: ActivityResultLauncher<String>
private lateinit var filePickerUpdate: ActivityResultLauncher<String>
private lateinit var requestPermissionLauncher: ActivityResultLauncher<Array<String>>

override fun onCreate(savedInstanceState: Bundle?) {
Expand All @@ -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)
}
}

Expand Down Expand Up @@ -110,9 +124,7 @@ class FileViewerActivity :
}

R.id.uploadFile -> {
filePicker.launch(
FileViewerViewModel.ANY_MIME_TYPE
)
filePickerUpload.launch(FileViewerViewModel.ANY_MIME_TYPE)
}

R.id.signOut -> {
Expand All @@ -130,6 +142,7 @@ class FileViewerActivity :
FileViewerViewState.Finish -> buildFinishState()
FileViewerViewState.CheckPermissions -> requestPermissions()
FileViewerViewState.SignOut -> buildSignOutState()
is FileViewerViewState.ShowUpdateFilePicker -> launchUpdateFilePicker()
}

private fun buildInitialState() {
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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()
Expand All @@ -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<String> = arrayOf(
Manifest.permission.READ_EXTERNAL_STORAGE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,18 @@ sealed class FileViewerViewEvent : ViewEvent {
override fun getEventName() = "FileViewerViewEvent.UploadFile"
}

class UpdateFile(val context: Context, val uri: Uri, val fileName: String) : FileViewerViewEvent() {
HectorNarvaez marked this conversation as resolved.
Show resolved Hide resolved

override fun getEventName() = "FileViewerViewEvent.UpdateFile"
}

object SignOut : FileViewerViewEvent() {

override fun getEventName() = "FileViewerViewEvent.SignOut"
}

class UpdateFileClicked(val file: OmhFile) : FileViewerViewEvent() {

override fun getEventName() = "FileViewerViewEvent.UpdateFileClicked"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.content.Context
import android.net.Uri
import com.omh.android.auth.api.OmhAuthClient
import android.os.Environment
import androidx.documentfile.provider.DocumentFile
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
Expand Down Expand Up @@ -39,10 +40,11 @@ class FileViewerViewModel @Inject constructor(
const val DEFAULT_FILE_NAME = "Untitled"
}

var isUpload = false
var isGridLayoutManager = true
var createFileSelectedType: OmhFileType? = null
private val parentIdStack = Stack<String>().apply { push(ID_ROOT) }
private var lastFileClicked: OmhFile? = null
var lastFileClicked: OmhFile? = null

override fun getInitialState(): FileViewerViewState = FileViewerViewState.Initial

Expand All @@ -56,8 +58,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)
}
}

Expand Down Expand Up @@ -111,14 +115,14 @@ class FileViewerViewModel @Inject constructor(
}

private fun downloadFileEvent() {
setState(FileViewerViewState.Loading)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why we moved this?

user should see a loading screen once we start to execute any logic

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because if the file is not downloadable, the file will not be downloadable then the loading state won't be dismissed

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can dismiss it dispatching a refresh event:

setState(FileViewerViewState.Loading)

if (!file.isDownloadable()) {
            toastMessage.postValue("${file.name} is not downloadable")
            refreshFileListEvent()
            return
}


lastFileClicked?.let { file ->
if (!file.isDownloadable()) {
toastMessage.postValue("${file.name} is not downloadable")
return
}

setState(FileViewerViewState.Loading)

val mimeType = file.normalizedMimeType()
val cancellable = omhStorageClient.downloadFile(file.id, mimeType)
.addOnSuccess { data ->
Expand All @@ -138,6 +142,35 @@ class FileViewerViewModel @Inject constructor(
}
}

private fun updateFileEvent(event: FileViewerViewEvent.UpdateFile) {
val fileId = lastFileClicked?.id ?: return

setState(FileViewerViewState.Loading)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please move this below method declaration

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you move below the method declaration, the state loading will be there if the lastFileClicked is null

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above, call refresh method


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()
Expand Down Expand Up @@ -234,6 +267,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
Expand All @@ -253,4 +291,6 @@ class FileViewerViewModel @Inject constructor(
super.onCleared()
cancellableCollector.clear()
}

fun getFileName(documentFileName: String?): String = documentFileName ?: DEFAULT_FILE_NAME
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,9 @@ sealed class FileViewerViewState : ViewState {

override fun getName() = "FileViewerViewState.SignOut"
}

object ShowUpdateFilePicker : FileViewerViewState() {

override fun getName() = "FileViewerViewState.FilePicker"
}
}
11 changes: 11 additions & 0 deletions storage-sample/src/main/res/layout/file_grid_adapter.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,17 @@
android:background="@drawable/rounded_for_grid"
android:orientation="vertical">

<ImageView
android:id="@+id/buttonUpdate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_marginEnd="5dp"
android:src="@android:drawable/ic_menu_edit"
app:layout_constraintEnd_toStartOf="@id/buttonDelete"
app:layout_constraintTop_toTopOf="parent"
app:tint="@color/black" />

<ImageView
android:id="@+id/buttonDelete"
android:layout_width="wrap_content"
Expand Down
13 changes: 12 additions & 1 deletion storage-sample/src/main/res/layout/file_linear_adapter.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,22 @@
android:ellipsize="end"
android:maxLines="1"
app:layout_constraintBottom_toBottomOf="@+id/fileIcon"
app:layout_constraintEnd_toStartOf="@+id/buttonDelete"
app:layout_constraintEnd_toStartOf="@+id/buttonUpdate"
app:layout_constraintStart_toEndOf="@+id/fileIcon"
app:layout_constraintTop_toTopOf="@+id/fileIcon"
tools:text="File Name" />

<ImageView
android:id="@+id/buttonUpdate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="5dp"
android:src="@android:drawable/ic_menu_edit"
app:layout_constraintBottom_toBottomOf="@+id/fileName"
app:layout_constraintEnd_toStartOf="@+id/buttonDelete"
app:layout_constraintTop_toTopOf="@+id/fileName"
app:tint="@color/black" />

<ImageView
android:id="@+id/buttonDelete"
android:layout_width="wrap_content"
Expand Down
2 changes: 2 additions & 0 deletions storage-sample/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
<string name="text_file_type_label">File Type:</string>
<string name="text_upload_file_title">Upload File</string>
<string name="text_upload">Upload</string>
<string name="text_update_file_title">Update File</string>
<string name="text_update">Update</string>
<string name="text_cancel">Cancel</string>
<string name="text_sign_out">Sign out</string>
</resources>