Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
13ac2f7
Albums functionality.
surinder-tsys Jun 2, 2025
5f7bcbb
Rename .java to .kt
surinder-tsys Jun 6, 2025
15bdc32
Code refactoring and operation migrated to kotlin
surinder-tsys Jun 6, 2025
be6664f
Fix -> video click event, overflow menu item hide and theming add menu
surinder-tsys Jun 6, 2025
ae187bc
Fix: preview album items
surinder-tsys Jul 11, 2025
c787986
upload files to album, hide video overlay icon, minor ui and bug fixes
surinder-tsys Jan 22, 2026
fba647b
wip
tobiasKaminsky Jan 23, 2026
1c681f1
Albums functionality.
surinder-tsys Jun 2, 2025
0724265
Rename .java to .kt
surinder-tsys Jun 6, 2025
6274a90
Code refactoring and operation migrated to kotlin
surinder-tsys Jun 6, 2025
9c299dd
upload files to album, hide video overlay icon, minor ui and bug fixes
surinder-tsys Jan 22, 2026
3e7382a
small fix
tobiasKaminsky Jan 26, 2026
2963ee6
code fixes
surinder-tsys Jan 29, 2026
01f2504
album upload worker state handled via localbroadcastmanager
surinder-tsys Jan 30, 2026
2023184
simplify upload file calls
alperozturk96 Feb 2, 2026
bf7d65e
separate worker parameters
alperozturk96 Feb 2, 2026
79d8ce6
separate params
alperozturk96 Feb 2, 2026
d2ded24
simplify album fragment
alperozturk96 Feb 2, 2026
3387cfc
use optional generic function to access fragment
alperozturk96 Feb 3, 2026
817e00c
fix code analytics, simplify
alperozturk96 Feb 3, 2026
94a81e6
m3 card
alperozturk96 Feb 19, 2026
9931721
m3 card
alperozturk96 Feb 19, 2026
b7ee07a
use fab
alperozturk96 Feb 19, 2026
6edfad2
use action bottom sheet for album item actions
alperozturk96 Feb 19, 2026
04168cf
use action bottom sheet for album item actions
alperozturk96 Feb 19, 2026
725e336
fix fab button appereance
alperozturk96 Feb 20, 2026
a75fdbc
Update app/src/main/res/values/strings.xml
alperozturk96 Feb 20, 2026
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 @@ -16,6 +16,7 @@ import com.nextcloud.client.jobs.upload.FileUploadHelper
import com.nextcloud.client.jobs.upload.FileUploadWorker
import com.nextcloud.client.network.Connectivity
import com.nextcloud.client.network.ConnectivityService
import com.nextcloud.model.OCUploadLocalPathData
import com.owncloud.android.AbstractOnServerIT
import com.owncloud.android.datamodel.OCFile
import com.owncloud.android.datamodel.UploadsStorageManager
Expand Down Expand Up @@ -123,7 +124,7 @@ abstract class FileUploaderIT : AbstractOnServerIT() {
fun testKeepLocalAndOverwriteRemoteStatic() {
val file = getDummyFile("chunkedFile.txt")

FileUploadHelper().uploadNewFiles(
val data = OCUploadLocalPathData(
user,
arrayOf(file.absolutePath),
arrayOf("/testFile.txt"),
Expand All @@ -135,6 +136,8 @@ abstract class FileUploaderIT : AbstractOnServerIT() {
NameCollisionPolicy.DEFAULT
)

FileUploadHelper().uploadNewFiles(data)

longSleep()

val result = ReadFileRemoteOperation("/testFile.txt").execute(client)
Expand Down Expand Up @@ -239,7 +242,7 @@ abstract class FileUploaderIT : AbstractOnServerIT() {
fun testKeepBothStatic() {
val file = getDummyFile("nonEmpty.txt")

FileUploadHelper().uploadNewFiles(
val data = OCUploadLocalPathData(
user,
arrayOf(file.absolutePath),
arrayOf("/testFile.txt"),
Expand All @@ -250,6 +253,7 @@ abstract class FileUploaderIT : AbstractOnServerIT() {
false,
NameCollisionPolicy.DEFAULT
)
FileUploadHelper().uploadNewFiles(data)

longSleep()

Expand Down Expand Up @@ -347,7 +351,7 @@ abstract class FileUploaderIT : AbstractOnServerIT() {
fun testKeepServerStatic() {
val file = getDummyFile("chunkedFile.txt")

FileUploadHelper().uploadNewFiles(
val data = OCUploadLocalPathData(
user,
arrayOf(file.absolutePath),
arrayOf("/testFile.txt"),
Expand All @@ -358,6 +362,7 @@ abstract class FileUploaderIT : AbstractOnServerIT() {
false,
NameCollisionPolicy.DEFAULT
)
FileUploadHelper().uploadNewFiles(data)

longSleep()

Expand Down Expand Up @@ -451,7 +456,7 @@ abstract class FileUploaderIT : AbstractOnServerIT() {
fun testKeepCancelStatic() {
val file = getDummyFile("chunkedFile.txt")

FileUploadHelper().uploadNewFiles(
val data = OCUploadLocalPathData(
user,
arrayOf(file.absolutePath),
arrayOf("/testFile.txt"),
Expand All @@ -462,6 +467,7 @@ abstract class FileUploaderIT : AbstractOnServerIT() {
false,
NameCollisionPolicy.DEFAULT
)
FileUploadHelper().uploadNewFiles(data)

longSleep()

Expand Down
5 changes: 4 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Nextcloud - Android Client
~
~ SPDX-FileCopyrightText: 2024 TSI-mc <surinder.kumar@t-systems.com>
~ SPDX-FileCopyrightText: 2024-2025 TSI-mc <surinder.kumar@t-systems.com>
~ SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
~ SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
-->
Expand Down Expand Up @@ -636,6 +636,9 @@
android:launchMode="singleTop"
android:theme="@style/Theme.ownCloud.Dialog.NoTitle"
android:windowSoftInputMode="adjustResize" />
<activity
android:name=".ui.activity.AlbumsPickerActivity"
android:exported="false" />
<activity
android:name=".ui.activity.ShareActivity"
android:exported="false"
Expand Down
22 changes: 21 additions & 1 deletion app/src/main/java/com/nextcloud/client/di/ComponentsModule.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2024 TSI-mc <surinder.kumar@t-systems.com>
* SPDX-FileCopyrightText: 2024-2025 TSI-mc <surinder.kumar@t-systems.com>
* SPDX-FileCopyrightText: 2020 Chris Narkiewicz <hello@ezaquarii.com>
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
Expand Down Expand Up @@ -32,6 +32,7 @@
import com.nextcloud.ui.ImageDetailFragment;
import com.nextcloud.ui.SetOnlineStatusBottomSheet;
import com.nextcloud.ui.SetStatusMessageBottomSheet;
import com.nextcloud.ui.albumItemActions.AlbumItemActionsBottomSheet;
import com.nextcloud.ui.composeActivity.ComposeActivity;
import com.nextcloud.ui.fileactions.FileActionsBottomSheet;
import com.nextcloud.ui.trashbinFileActions.TrashbinFileActionsBottomSheet;
Expand Down Expand Up @@ -82,6 +83,7 @@
import com.owncloud.android.ui.dialog.ChooseTemplateDialogFragment;
import com.owncloud.android.ui.dialog.ConfirmationDialogFragment;
import com.owncloud.android.ui.dialog.ConflictsResolveDialog;
import com.owncloud.android.ui.dialog.CreateAlbumDialogFragment;
import com.owncloud.android.ui.dialog.CreateFolderDialogFragment;
import com.owncloud.android.ui.dialog.ExpirationDatePickerDialogFragment;
import com.owncloud.android.ui.dialog.IndeterminateProgressDialog;
Expand Down Expand Up @@ -115,6 +117,9 @@
import com.owncloud.android.ui.fragment.OCFileListFragment;
import com.owncloud.android.ui.fragment.SharedListFragment;
import com.owncloud.android.ui.fragment.UnifiedSearchFragment;
import com.owncloud.android.ui.fragment.albums.AlbumItemsFragment;
import com.owncloud.android.ui.fragment.albums.AlbumsFragment;
import com.owncloud.android.ui.activity.AlbumsPickerActivity;
import com.owncloud.android.ui.fragment.contactsbackup.BackupFragment;
import com.owncloud.android.ui.fragment.contactsbackup.BackupListFragment;
import com.owncloud.android.ui.preview.FileDownloadFragment;
Expand Down Expand Up @@ -509,4 +514,19 @@ abstract class ComponentsModule {

@ContributesAndroidInjector
abstract SetStatusMessageBottomSheet setStatusMessageBottomSheet();

@ContributesAndroidInjector
abstract AlbumsPickerActivity albumsPickerActivity();

@ContributesAndroidInjector
abstract CreateAlbumDialogFragment createAlbumDialogFragment();

@ContributesAndroidInjector
abstract AlbumsFragment albumsFragment();

@ContributesAndroidInjector
abstract AlbumItemsFragment albumItemsFragment();

@ContributesAndroidInjector
abstract AlbumItemActionsBottomSheet albumItemActionsBottomSheet();
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import com.nextcloud.client.jobs.BackgroundJobManager
import com.nextcloud.client.jobs.upload.FileUploadHelper
import com.nextcloud.client.jobs.upload.FileUploadWorker
import com.nextcloud.client.logger.Logger
import com.nextcloud.model.OCUploadLocalPathData
import com.owncloud.android.datamodel.OCFile
import com.owncloud.android.files.services.NameCollisionPolicy
import com.owncloud.android.operations.UploadFileOperation
Expand Down Expand Up @@ -166,17 +167,8 @@ class DocumentScanViewModel @Inject constructor(
uploadFolder + OCFile.PATH_SEPARATOR + File(it).name
}.toTypedArray()

FileUploadHelper.instance().uploadNewFiles(
currentAccountProvider.user,
pageList.toTypedArray(),
uploadPaths,
FileUploadWorker.LOCAL_BEHAVIOUR_DELETE,
true,
UploadFileOperation.CREATED_BY_USER,
false,
false,
NameCollisionPolicy.ASK_USER
)
val data = OCUploadLocalPathData.forDocument(currentAccountProvider.user, pageList.toTypedArray(), uploadPaths)
FileUploadHelper.instance().uploadNewFiles(data)
}

fun onExportCanceled() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import com.nextcloud.client.account.UserAccountManager
import com.nextcloud.client.jobs.upload.FileUploadHelper
import com.nextcloud.client.jobs.upload.FileUploadWorker
import com.nextcloud.client.logger.Logger
import com.nextcloud.model.OCUploadLocalPathData
import com.owncloud.android.R
import com.owncloud.android.datamodel.OCFile
import com.owncloud.android.files.services.NameCollisionPolicy
Expand Down Expand Up @@ -108,18 +109,8 @@ class GeneratePdfFromImagesWork(
private fun uploadFile(user: User, uploadFolder: String, pdfPath: String) {
val uploadPath = uploadFolder + OCFile.PATH_SEPARATOR + File(pdfPath).name

FileUploadHelper().uploadNewFiles(
user,
arrayOf(pdfPath),
arrayOf(uploadPath),
// MIME type will be detected from file name
FileUploadWorker.LOCAL_BEHAVIOUR_DELETE,
true,
UploadFileOperation.CREATED_BY_USER,
false,
false,
NameCollisionPolicy.ASK_USER
)
val data = OCUploadLocalPathData.forDocument(user, arrayOf(pdfPath), arrayOf(uploadPath))
FileUploadHelper().uploadNewFiles(data)
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import com.canhub.cropper.CropImageView
import com.nextcloud.client.di.Injectable
import com.nextcloud.client.jobs.upload.FileUploadHelper
import com.nextcloud.client.jobs.upload.FileUploadWorker
import com.nextcloud.model.OCUploadLocalPathData
import com.nextcloud.utils.extensions.getParcelableArgument
import com.owncloud.android.R
import com.owncloud.android.databinding.ActivityEditImageBinding
Expand Down Expand Up @@ -95,17 +96,18 @@ class EditImageActivity :
resultUri?.substring(resultUri.lastIndexOf('.'))

resultUri?.let {
FileUploadHelper().uploadNewFiles(
val data = OCUploadLocalPathData(
user = storageManager.user,
localPaths = arrayOf(it),
remotePaths = arrayOf(file.parentRemotePath + File.separator + newFileName),
createRemoteFolder = false,
createdBy = UploadFileOperation.CREATED_BY_USER,
creationType = UploadFileOperation.CREATED_BY_USER,
requiresWifi = false,
requiresCharging = false,
nameCollisionPolicy = NameCollisionPolicy.RENAME,
collisionPolicy = NameCollisionPolicy.RENAME,
localBehavior = FileUploadWorker.LOCAL_BEHAVIOUR_DELETE
)
FileUploadHelper().uploadNewFiles(data)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2020 Chris Narkiewicz <hello@ezaquarii.com>
* SPDX-FileCopyrightText: 2026 TSI-mc <surinder.kumar@t-systems.com>
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.nextcloud.client.jobs
Expand All @@ -28,6 +29,7 @@ import com.nextcloud.client.jobs.download.FileDownloadWorker
import com.nextcloud.client.jobs.folderDownload.FolderDownloadWorker
import com.nextcloud.client.jobs.metadata.MetadataWorker
import com.nextcloud.client.jobs.offlineOperations.OfflineOperationsWorker
import com.nextcloud.client.jobs.upload.AlbumFileUploadWorker
import com.nextcloud.client.jobs.upload.FileUploadWorker
import com.nextcloud.client.logger.Logger
import com.nextcloud.client.network.ConnectivityService
Expand Down Expand Up @@ -96,6 +98,7 @@ class BackgroundJobFactory @Inject constructor(
CalendarImportWork::class -> createCalendarImportWork(context, workerParameters)
FilesExportWork::class -> createFilesExportWork(context, workerParameters)
FileUploadWorker::class -> createFilesUploadWorker(context, workerParameters)
AlbumFileUploadWorker::class -> createAlbumsFilesUploadWorker(context, workerParameters)
FileDownloadWorker::class -> createFilesDownloadWorker(context, workerParameters)
GeneratePdfFromImagesWork::class -> createPDFGenerateWork(context, workerParameters)
HealthStatusWork::class -> createHealthStatusWork(context, workerParameters)
Expand Down Expand Up @@ -251,6 +254,20 @@ class BackgroundJobFactory @Inject constructor(
params
)

private fun createAlbumsFilesUploadWorker(context: Context, params: WorkerParameters): AlbumFileUploadWorker =
AlbumFileUploadWorker(
uploadsStorageManager,
connectivityService,
powerManagementService,
accountManager,
viewThemeUtils.get(),
localBroadcastManager.get(),
backgroundJobManager.get(),
preferences,
context,
params
)

private fun createPDFGenerateWork(context: Context, params: WorkerParameters): GeneratePdfFromImagesWork =
GeneratePdfFromImagesWork(
appContext = context,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2020 Chris Narkiewicz <hello@ezaquarii.com>
* SPDX-FileCopyrightText: 2026 TSI-mc <surinder.kumar@t-systems.com>
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.nextcloud.client.jobs
Expand Down Expand Up @@ -136,6 +137,7 @@ interface BackgroundJobManager {
fun startNotificationJob(subject: String, signature: String)
fun startAccountRemovalJob(accountName: String, remoteWipe: Boolean)
fun startFilesUploadJob(user: User, uploadIds: LongArray, showSameFileAlreadyExistsNotification: Boolean)
fun startAlbumFilesUploadJob(user: User, uploadIds: LongArray, albumName: String)
fun getFileUploads(user: User): LiveData<List<JobInfo>>
fun cancelFilesUploadJob(user: User)
fun isStartFileUploadJobScheduled(accountName: String): Boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2020 Chris Narkiewicz <hello@ezaquarii.com>
* SPDX-FileCopyrightText: 2026 TSI-mc <surinder.kumar@t-systems.com>
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
*/
package com.nextcloud.client.jobs
Expand Down Expand Up @@ -32,6 +33,7 @@ import com.nextcloud.client.jobs.download.FileDownloadWorker
import com.nextcloud.client.jobs.folderDownload.FolderDownloadWorker
import com.nextcloud.client.jobs.metadata.MetadataWorker
import com.nextcloud.client.jobs.offlineOperations.OfflineOperationsWorker
import com.nextcloud.client.jobs.upload.AlbumFileUploadWorker
import com.nextcloud.client.jobs.upload.FileUploadHelper
import com.nextcloud.client.jobs.upload.FileUploadWorker
import com.nextcloud.client.preferences.AppPreferences
Expand Down Expand Up @@ -87,6 +89,7 @@ internal class BackgroundJobManagerImpl(
const val JOB_NOTIFICATION = "notification"
const val JOB_ACCOUNT_REMOVAL = "account_removal"
const val JOB_FILES_UPLOAD = "files_upload"
const val ALBUM_JOB_FILES_UPLOAD = "album_files_upload"
const val JOB_FOLDER_DOWNLOAD = "folder_download"
const val JOB_FILES_DOWNLOAD = "files_download"
const val JOB_PDF_GENERATION = "pdf_generation"
Expand Down Expand Up @@ -608,6 +611,8 @@ internal class BackgroundJobManagerImpl(

private fun startFileUploadJobTag(accountName: String): String = JOB_FILES_UPLOAD + accountName

private fun startAlbumsFileUploadJobTag(accountName: String): String = ALBUM_JOB_FILES_UPLOAD + accountName

override fun isStartFileUploadJobScheduled(accountName: String): Boolean =
workManager.isWorkScheduled(startFileUploadJobTag(accountName))

Expand Down Expand Up @@ -671,6 +676,59 @@ internal class BackgroundJobManagerImpl(
}
}

/**
* This method supports uploading and copying selected files to Album
*
* @param user The user for whom the upload job is being created.
* @param uploadIds Array of upload IDs to be processed. These IDs originate from multiple sources
* and cannot be determined directly from the account name or a single function
* within the worker.
* @param albumName Album on which selected files should be copy after upload
*/
override fun startAlbumFilesUploadJob(user: User, uploadIds: LongArray, albumName: String) {
defaultDispatcherScope.launch {
val batchSize = FileUploadHelper.MAX_FILE_COUNT
val batches = uploadIds.toList().chunked(batchSize)
val tag = startAlbumsFileUploadJobTag(user.accountName)

val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build()

val dataBuilder = Data.Builder()
.putString(AlbumFileUploadWorker.ACCOUNT, user.accountName)
.putInt(AlbumFileUploadWorker.TOTAL_UPLOAD_SIZE, uploadIds.size)
.putString(AlbumFileUploadWorker.ALBUM_NAME, albumName)

val workRequests = batches.mapIndexed { index, batch ->
dataBuilder
.putLongArray(AlbumFileUploadWorker.UPLOAD_IDS, batch.toLongArray())
.putInt(AlbumFileUploadWorker.CURRENT_BATCH_INDEX, index)

oneTimeRequestBuilder(AlbumFileUploadWorker::class, ALBUM_JOB_FILES_UPLOAD, user)
.addTag(tag)
.setInputData(dataBuilder.build())
.setConstraints(constraints)
.build()
}

// Chain the work requests sequentially
if (workRequests.isNotEmpty()) {
var workChain = workManager.beginUniqueWork(
tag,
ExistingWorkPolicy.APPEND_OR_REPLACE,
workRequests.first()
)

workRequests.drop(1).forEach { request ->
workChain = workChain.then(request)
}

workChain.enqueue()
}
}
}

private fun startFileDownloadJobTag(user: User, fileId: Long): String =
JOB_FOLDER_DOWNLOAD + user.accountName + fileId

Expand Down
Loading
Loading