add cancel upload functionality

Signed-off-by: parneet-guraya <gurayaparneet@gmail.com>
This commit is contained in:
parneet-guraya 2024-01-08 21:53:15 +05:30 committed by Marcel Hibbe
parent 64732b8155
commit 6f88c8bcbd
No known key found for this signature in database
GPG key ID: C793F8B59F43CE7B
3 changed files with 75 additions and 12 deletions

View file

@ -60,6 +60,7 @@ import com.nextcloud.talk.utils.permissions.PlatformPermissionUtil
import com.nextcloud.talk.utils.preferences.AppPreferences
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.OkHttpClient
import java.io.File
import javax.inject.Inject
@AutoInjector(NextcloudTalkApplication::class)
@ -91,6 +92,9 @@ class UploadAndShareFilesWorker(val context: Context, workerParameters: WorkerPa
lateinit var roomToken: String
lateinit var conversationName: String
lateinit var currentUser: User
private var isChunkedUploading = false
private var file: File? = null
private var chunkedFileUploader: ChunkedFileUploader? = null
@Suppress("Detekt.TooGenericExceptionCaught")
override fun doWork(): Result {
@ -120,28 +124,30 @@ class UploadAndShareFilesWorker(val context: Context, workerParameters: WorkerPa
val sourceFileUri = Uri.parse(sourceFile)
fileName = FileUtils.getFileName(sourceFileUri, context)
val file = FileUtils.getFileFromUri(context, sourceFileUri)
file = FileUtils.getFileFromUri(context, sourceFileUri)
val remotePath = getRemotePath(currentUser)
val uploadSuccess: Boolean
initNotificationSetup()
file?.let { isChunkedUploading = it.length() > CHUNK_UPLOAD_THRESHOLD_SIZE }
if (file == null) {
uploadSuccess = false
} else if (file.length() > CHUNK_UPLOAD_THRESHOLD_SIZE) {
Log.d(TAG, "starting chunked upload because size is " + file.length())
} else if (isChunkedUploading) {
Log.d(TAG, "starting chunked upload because size is " + file!!.length())
initNotificationWithPercentage()
val mimeType = context.contentResolver.getType(sourceFileUri)?.toMediaTypeOrNull()
uploadSuccess = ChunkedFileUploader(
chunkedFileUploader = ChunkedFileUploader(
okHttpClient,
currentUser,
roomToken,
metaData,
this
).upload(
file,
)
uploadSuccess = chunkedFileUploader!!.upload(
file!!,
mimeType,
remotePath
)
@ -164,6 +170,9 @@ class UploadAndShareFilesWorker(val context: Context, workerParameters: WorkerPa
if (uploadSuccess) {
mNotifyManager?.cancel(notificationId)
return Result.success()
} else if (isStopped) {
// since work is cancelled the result would be ignored anyways
return Result.failure()
}
Log.e(TAG, "Something went wrong when trying to upload file")
@ -195,6 +204,15 @@ class UploadAndShareFilesWorker(val context: Context, workerParameters: WorkerPa
mNotifyManager!!.notify(notificationId, notification)
}
override fun onStopped() {
if (file != null && isChunkedUploading) {
chunkedFileUploader?.abortUpload {
mNotifyManager?.cancel(notificationId)
}
}
super.onStopped()
}
private fun initNotificationSetup() {
mNotifyManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
mBuilder = NotificationCompat.Builder(
@ -206,13 +224,17 @@ class UploadAndShareFilesWorker(val context: Context, workerParameters: WorkerPa
private fun initNotificationWithPercentage() {
notification = mBuilder!!
.setContentTitle(context.resources.getString(R.string.nc_upload_in_progess))
.setContentTitle(getResourceString(context, R.string.nc_upload_in_progess))
.setContentText(getNotificationContentText(ZERO_PERCENT))
.setSmallIcon(R.drawable.upload_white)
.setOngoing(true)
.setProgress(HUNDRED_PERCENT, ZERO_PERCENT, false)
.setPriority(NotificationCompat.PRIORITY_LOW)
.setContentIntent(getIntentToOpenConversation())
.addAction(
R.drawable.ic_cancel_white_24dp, getResourceString(context, R.string.nc_cancel),
getCancelUploadIntent()
)
.build()
notificationId = SystemClock.uptimeMillis().toInt()
@ -221,7 +243,7 @@ class UploadAndShareFilesWorker(val context: Context, workerParameters: WorkerPa
private fun getNotificationContentText(percentage: Int): String {
return String.format(
context.resources.getString(R.string.nc_upload_notification_text),
getResourceString(context, R.string.nc_upload_notification_text),
getShortenedFileName(),
conversationName,
percentage
@ -236,6 +258,11 @@ class UploadAndShareFilesWorker(val context: Context, workerParameters: WorkerPa
}
}
private fun getCancelUploadIntent(): PendingIntent {
return WorkManager.getInstance(applicationContext)
.createCancelPendingIntent(id)
}
private fun getIntentToOpenConversation(): PendingIntent? {
val bundle = Bundle()
val intent = Intent(context, MainActivity::class.java)
@ -257,9 +284,9 @@ class UploadAndShareFilesWorker(val context: Context, workerParameters: WorkerPa
}
private fun showFailedToUploadNotification() {
val failureTitle = context.resources.getString(R.string.nc_upload_failed_notification_title)
val failureTitle = getResourceString(context, R.string.nc_upload_failed_notification_title)
val failureText = String.format(
context.resources.getString(R.string.nc_upload_failed_notification_text),
getResourceString(context, R.string.nc_upload_failed_notification_text),
fileName
)
notification = mBuilder!!
@ -275,6 +302,10 @@ class UploadAndShareFilesWorker(val context: Context, workerParameters: WorkerPa
mNotifyManager!!.notify(SystemClock.uptimeMillis().toInt(), notification)
}
private fun getResourceString(context: Context, resourceId: Int): String {
return context.resources.getString(resourceId)
}
companion object {
private val TAG = UploadAndShareFilesWorker::class.simpleName
private const val DEVICE_SOURCE_FILE = "DEVICE_SOURCE_FILE"
@ -301,6 +332,7 @@ class UploadAndShareFilesWorker(val context: Context, workerParameters: WorkerPa
REQUEST_PERMISSION
)
}
Build.VERSION.SDK_INT > Build.VERSION_CODES.Q -> {
activity.requestPermissions(
arrayOf(
@ -309,6 +341,7 @@ class UploadAndShareFilesWorker(val context: Context, workerParameters: WorkerPa
REQUEST_PERMISSION
)
}
else -> {
activity.requestPermissions(
arrayOf(

View file

@ -76,6 +76,8 @@ class ChunkedFileUploader(
private var okHttpClientNoRedirects: OkHttpClient? = null
private var remoteChunkUrl: String
private var uploadFolderUri: String = ""
private var isUploadAborted = false
init {
initHttpClient(okHttpClient, currentUser)
@ -85,7 +87,7 @@ class ChunkedFileUploader(
@Suppress("Detekt.TooGenericExceptionCaught")
fun upload(localFile: File, mimeType: MediaType?, targetPath: String): Boolean {
try {
val uploadFolderUri: String = remoteChunkUrl + "/" + FileUtils.md5Sum(localFile)
uploadFolderUri = remoteChunkUrl + "/" + FileUtils.md5Sum(localFile)
val davResource = DavResource(
okHttpClientNoRedirects!!,
uploadFolderUri.toHttpUrlOrNull()!!
@ -100,6 +102,7 @@ class ChunkedFileUploader(
Log.d(TAG, "missingChunks: " + missingChunks.size)
for (missingChunk in missingChunks) {
if (isUploadAborted) return false
uploadChunk(localFile, uploadFolderUri, mimeType, missingChunk, missingChunk.length())
}
@ -327,6 +330,19 @@ class ChunkedFileUploader(
}
}
fun abortUpload(onSuccess: () -> Unit) {
isUploadAborted = true
DavResource(
okHttpClientNoRedirects!!,
uploadFolderUri.toHttpUrlOrNull()!!
).delete { response: Response ->
when {
response.isSuccessful -> onSuccess()
else -> isUploadAborted = false
}
}
}
private fun getModelFromResponse(response: at.bitfire.dav4jvm.Response, remotePath: String): RemoteFileBrowserItem {
val remoteFileBrowserItem = RemoteFileBrowserItem()
remoteFileBrowserItem.path = Uri.decode(remotePath)
@ -353,30 +369,39 @@ class ChunkedFileUploader(
is OCId -> {
remoteFileBrowserItem.remoteId = property.ocId
}
is ResourceType -> {
remoteFileBrowserItem.isFile = !property.types.contains(ResourceType.COLLECTION)
}
is GetLastModified -> {
remoteFileBrowserItem.modifiedTimestamp = property.lastModified
}
is GetContentType -> {
remoteFileBrowserItem.mimeType = property.type
}
is OCSize -> {
remoteFileBrowserItem.size = property.ocSize
}
is NCPreview -> {
remoteFileBrowserItem.hasPreview = property.isNcPreview
}
is OCFavorite -> {
remoteFileBrowserItem.isFavorite = property.isOcFavorite
}
is DisplayName -> {
remoteFileBrowserItem.displayName = property.displayName
}
is NCEncrypted -> {
remoteFileBrowserItem.isEncrypted = property.isNcEncrypted
}
is NCPermission -> {
remoteFileBrowserItem.permissions = property.ncPermission
}

View file

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M12,2C6.47,2 2,6.47 2,12s4.47,10 10,10 10,-4.47 10,-10S17.53,2 12,2zM17,15.59L15.59,17 12,13.41 8.41,17 7,15.59 10.59,12 7,8.41 8.41,7 12,10.59 15.59,7 17,8.41 13.41,12 17,15.59z"/>
</vector>