Skip to content
Closed
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
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
* Nextcloud Android client application
*
* @author Álvaro Brey
* @author TSI-mc
* Copyright (C) 2022 Álvaro Brey
* Copyright (C) 2022 Nextcloud GmbH
* Copyright (C) 2023 TSI-mc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
Expand Down Expand Up @@ -199,7 +201,8 @@ class DocumentScanViewModel @Inject constructor(
UploadFileOperation.CREATED_BY_USER,
false,
false,
NameCollisionPolicy.ASK_USER
NameCollisionPolicy.ASK_USER,
false
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
* Nextcloud Android client application
*
* @author Chris Narkiewicz
* @author TSI-mc
* Copyright (C) 2021 Chris Narkiewicz <hello@ezaquarii.com>
* Copyright (C) 2023 TSI-mc
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
Expand Down Expand Up @@ -87,6 +89,7 @@ class UploadTask(
upload.isUseWifiOnly,
upload.isWhileChargingOnly,
false,
false,
fileDataStorageManager
)
val client = clientProvider()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
* Nextcloud Android client application
*
* @author Chris Narkiewicz
* @author TSI-mc
* Copyright (C) 2020 Chris Narkiewicz <hello@ezaquarii.com>
* Copyright (C) 2023 TSI-mc
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
Expand Down Expand Up @@ -105,6 +107,7 @@ class BackgroundJobFactory @Inject constructor(
CalendarImportWork::class -> createCalendarImportWork(context, workerParameters)
FilesExportWork::class -> createFilesExportWork(context, workerParameters)
FilesUploadWorker::class -> createFilesUploadWorker(context, workerParameters)
UploadImagesWorker::class -> createUploadImagesWork(context, workerParameters)
GeneratePdfFromImagesWork::class -> createPDFGenerateWork(context, workerParameters)
else -> null // caller falls back to default factory
}
Expand Down Expand Up @@ -257,6 +260,16 @@ class BackgroundJobFactory @Inject constructor(
)
}

private fun createUploadImagesWork(context: Context, params: WorkerParameters): UploadImagesWorker {
return UploadImagesWorker(
context = context,
params = params,
notificationManager,
accountManager,
viewThemeUtils.get()
)
}

private fun createPDFGenerateWork(context: Context, params: WorkerParameters): GeneratePdfFromImagesWork {
return GeneratePdfFromImagesWork(
appContext = context,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
* Nextcloud Android client application
*
* @author Chris Narkiewicz
* @author TSI-mc
* Copyright (C) 2020 Chris Narkiewicz <hello@ezaquarii.com>
* Copyright (C) 2023 TSI-mc
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
Expand Down Expand Up @@ -140,6 +142,7 @@ interface BackgroundJobManager {
fun startAccountRemovalJob(accountName: String, remoteWipe: Boolean)
fun startFilesUploadJob(user: User)
fun getFileUploads(user: User): LiveData<List<JobInfo>>
fun scheduleImmediateUploadImagesJob(): LiveData<JobInfo?>

fun startPdfGenerateAndUploadWork(user: User, uploadFolder: String, imagePaths: List<String>, pdfPath: String)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
* Nextcloud Android client application
*
* @author Chris Narkiewicz
* @author TSI-mc
* Copyright (C) 2020 Chris Narkiewicz <hello@ezaquarii.com>
* Copyright (C) 2023 TSI-mc
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
Expand Down Expand Up @@ -82,6 +84,7 @@ internal class BackgroundJobManagerImpl(
const val JOB_ACCOUNT_REMOVAL = "account_removal"
const val JOB_FILES_UPLOAD = "files_upload"
const val JOB_PDF_GENERATION = "pdf_generation"
const val JOB_IMAGE_FILES_UPLOAD = "immediate_image_files_upload"
const val JOB_IMMEDIATE_CALENDAR_BACKUP = "immediate_calendar_backup"
const val JOB_IMMEDIATE_FILES_EXPORT = "immediate_files_export"

Expand Down Expand Up @@ -464,6 +467,14 @@ internal class BackgroundJobManagerImpl(
return workInfo.map { it -> it.map { fromWorkInfo(it) ?: JobInfo() } }
}

override fun scheduleImmediateUploadImagesJob(): LiveData<JobInfo?> {
val request = oneTimeRequestBuilder(UploadImagesWorker::class, JOB_IMAGE_FILES_UPLOAD)
.build()

workManager.enqueueUniqueWork(JOB_IMAGE_FILES_UPLOAD, ExistingWorkPolicy.APPEND_OR_REPLACE, request)
return workManager.getJobInfo(request.id)
}

override fun startPdfGenerateAndUploadWork(
user: User,
uploadFolder: String,
Expand Down
5 changes: 4 additions & 1 deletion app/src/main/java/com/nextcloud/client/jobs/FilesSyncWork.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
*
* @author Mario Danic
* @author Chris Narkiewicz
* @author TSI-mc
* Copyright (C) 2017 Mario Danic
* Copyright (C) 2017 Nextcloud
* Copyright (C) 2020 Chris Narkiewicz
* Copyright (C) 2023 TSI-mc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
Expand Down Expand Up @@ -180,7 +182,8 @@ class FilesSyncWork(
UploadFileOperation.CREATED_AS_INSTANT_PICTURE,
needsWifi,
needsCharging,
syncedFolder.nameCollisionPolicy
syncedFolder.nameCollisionPolicy,
false
)

for (path in paths) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
* Nextcloud Android client application
*
* @author Tobias Kaminsky
* @author TSI-mc
* Copyright (C) 2022 Tobias Kaminsky
* Copyright (C) 2022 Nextcloud GmbH
* Copyright (C) 2023 TSI-mc
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
Expand Down Expand Up @@ -142,6 +144,7 @@ class FilesUploadWorker(
upload.isUseWifiOnly,
upload.isWhileChargingOnly,
true,
false,
FileDataStorageManager(user, context.contentResolver)
).apply {
addDataTransferProgressListener(this@FilesUploadWorker)
Expand Down
164 changes: 164 additions & 0 deletions app/src/main/java/com/nextcloud/client/jobs/UploadImagesWorker.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
/*
* Nextcloud Android client application
*
* @author TSI-mc
* Copyright (C) 2023 TSI-mc
* Copyright (C) 2023 NextCloud GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.nextcloud.client.jobs

import android.app.NotificationManager
import android.content.Context
import android.graphics.BitmapFactory
import android.os.Build
import androidx.core.app.NotificationCompat
import androidx.work.Worker
import androidx.work.WorkerParameters
import com.nextcloud.client.account.UserAccountManager
import com.owncloud.android.utils.FileUtil
import com.owncloud.android.R
import com.owncloud.android.files.services.FileUploader
import com.owncloud.android.files.services.NameCollisionPolicy
import com.owncloud.android.operations.UploadFileOperation
import com.owncloud.android.ui.notifications.NotificationUtils
import com.owncloud.android.ui.preview.PreviewImageActivity
import com.owncloud.android.ui.preview.PreviewImageFragment
import com.owncloud.android.utils.theme.ViewThemeUtils
import java.io.File
import java.security.SecureRandom

/**
* worker to upload the files in background when app is not running or app is killed
* right now we are using it for to save rotated images
*/
class UploadImagesWorker constructor(
private val context: Context,
params: WorkerParameters,
private val notificationManager: NotificationManager,
private val accountManager: UserAccountManager,
val viewThemeUtils: ViewThemeUtils
) : Worker(context, params) {

private val notificationBuilder: NotificationCompat.Builder =
NotificationUtils.newNotificationBuilder(context, viewThemeUtils)
private val savedFiles = mutableListOf<String>()
private val remotePaths = mutableListOf<String>()

companion object {
const val TAG = "UploadImagesWorkerJob"
const val IMAGE_COMPRESSION_PERCENTAGE = 100
}

override fun doWork(): Result {

val bitmapHashMap: HashMap<Int, PreviewImageFragment.LoadImage> = HashMap(PreviewImageActivity.bitmapHashMap)

//clear the static bitmap once the images are stored in work manager instance
PreviewImageActivity.bitmapHashMap.clear()

val randomId = SecureRandom()
val pushNotificationId = randomId.nextInt()
showNotification(pushNotificationId)

for ((_, value) in bitmapHashMap) {
val fileName = value.ocFile.fileName
//get the file extension
val extension: String = fileName.substring(fileName.lastIndexOf("."))
//get the file name without extension
val fileNameWithoutExt: String = fileName.replace(extension, "")

//if extension is jpg then save the image as jpg
if (extension.lowercase() == ".jpg" || extension.lowercase() == ".jpeg") {
val jpgFile =
FileUtil.saveJpgImage(context, value.bitmap, fileNameWithoutExt, IMAGE_COMPRESSION_PERCENTAGE)

//if file is available on local then rewrite the file as well
if (value.ocFile.isDown) {
FileUtil.saveJpgImage(
value.bitmap,
File(value.ocFile.storagePath),
IMAGE_COMPRESSION_PERCENTAGE
)
}
onImageSaveSuccess(value, jpgFile)

//if extension is other than jpg/jpeg save the image as png
} else {
val pngFile =
FileUtil.savePngImage(context, value.bitmap, fileNameWithoutExt, IMAGE_COMPRESSION_PERCENTAGE)

//if file is available on local then rewrite the file as well
if (value.ocFile.isDown) {
FileUtil.savePngImage(
value.bitmap,
File(value.ocFile.storagePath),
IMAGE_COMPRESSION_PERCENTAGE
)
}
onImageSaveSuccess(value, pngFile)
}
}

notificationManager.cancel(pushNotificationId)

//upload image files
if (savedFiles.isNotEmpty() && remotePaths.isNotEmpty()) {
uploadImageFiles()
}

return Result.success()
}

private fun onImageSaveSuccess(
value: PreviewImageFragment.LoadImage,
imageFile: File
) {
savedFiles.add(imageFile.path)
remotePaths.add(value.ocFile.remotePath)
}

private fun showNotification(pushNotificationId: Int) {
notificationBuilder
.setSmallIcon(R.drawable.notification_icon)
.setLargeIcon(BitmapFactory.decodeResource(context.resources, R.drawable.notification_icon))
.setContentTitle(context.resources.getString(R.string.app_name))
.setContentText(context.resources.getString(R.string.foreground_service_save))
.setAutoCancel(false)

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
notificationBuilder.setChannelId(NotificationUtils.NOTIFICATION_CHANNEL_IMAGE_SAVE)
}

notificationManager.notify(pushNotificationId, notificationBuilder.build())
}

private fun uploadImageFiles() {
FileUploader.uploadNewFile(
context,
accountManager.user,
savedFiles.toTypedArray(),
remotePaths.toTypedArray(),
null, // MIME type will be detected from file name
FileUploader.LOCAL_BEHAVIOUR_MOVE, //move the local file to make file offline available
false, // do not create parent folder if not existent
UploadFileOperation.CREATED_BY_USER,
false,
false,
NameCollisionPolicy.OVERWRITE, //overwrite the images
true
)
}
}
8 changes: 7 additions & 1 deletion app/src/main/java/com/nextcloud/ui/fileactions/FileAction.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
* Nextcloud Android client application
*
* @author Álvaro Brey
* @author TSI-mc
* Copyright (C) 2022 Álvaro Brey
* Copyright (C) 2022 Nextcloud GmbH
* Copyright (C) 2023 TSI-mc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
Expand Down Expand Up @@ -68,7 +70,10 @@ enum class FileAction(@IdRes val id: Int, @StringRes val title: Int, @DrawableRe
LOCK_FILE(R.id.action_lock_file, R.string.lock_file, R.drawable.ic_lock),

// Shortcuts
PIN_TO_HOMESCREEN(R.id.action_pin_to_homescreen, R.string.pin_home, R.drawable.add_to_home_screen);
PIN_TO_HOMESCREEN(R.id.action_pin_to_homescreen, R.string.pin_home, R.drawable.add_to_home_screen),

// Rotate
ROTATE_IMAGE(R.id.action_rotate_image, R.string.action_rotate, R.drawable.ic_rotate_right);

companion object {
/**
Expand All @@ -85,6 +90,7 @@ enum class FileAction(@IdRes val id: Int, @StringRes val title: Int, @DrawableRe
RENAME_FILE,
MOVE,
COPY,
ROTATE_IMAGE,
DOWNLOAD_FILE,
EXPORT_FILE,
STREAM_MEDIA,
Expand Down
4 changes: 4 additions & 0 deletions app/src/main/java/com/owncloud/android/MainApp.java
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,10 @@ public static void notificationChannels() {
createChannel(notificationManager, NotificationUtils.NOTIFICATION_CHANNEL_GENERAL, R.string
.notification_channel_general_name, R.string.notification_channel_general_description,
context, NotificationManager.IMPORTANCE_DEFAULT);

createChannel(notificationManager, NotificationUtils.NOTIFICATION_CHANNEL_IMAGE_SAVE,
R.string.notification_channel_image_save,
R.string.notification_channel_image_save_description, context);
} else {
Log_OC.e(TAG, "Notification manager is null");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
* @author Tobias Kaminsky
* @author David A. Velasco
* @author Chris Narkiewicz
* @author TSI-mc
* Copyright (C) 2015 ownCloud Inc.
* Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
* Copyright (C) 2023 TSI-mc
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
Expand Down Expand Up @@ -216,6 +218,14 @@ public static void addBitmapToCache(String key, Bitmap bitmap) {
}
}

public static void removeBitmapFromCache(String key) {
synchronized (mThumbnailsDiskCacheLock) {
if (mThumbnailCache != null) {
mThumbnailCache.removeKey(key);
}
}
}

public static boolean containsBitmap(String key) {
return mThumbnailCache.containsKey(key);
}
Expand Down
Loading