Skip to content
Merged
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
2 changes: 1 addition & 1 deletion app/src/main/java/com/nextcloud/client/NominatimClient.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class NominatimClient constructor(geocoderBaseUrl: String, email: String) {
private val reverseUrl = "${geocoderBaseUrl}reverse?format=jsonv2&email=${URLEncoder.encode(email, ENCODING_UTF_8)}"

private fun doRequest(requestUrl: String): String? {
val request = Request.Builder().url(requestUrl).header(HEADER_USER_AGENT, MainApp.getUserAgent()).build()
val request = Request.Builder().url(requestUrl).header(HEADER_USER_AGENT, MainApp.userAgent).build()

try {
val response = client.newCall(request).execute()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ class InternalTwoWaySyncWork(

return try {
val freeSpaceLeft = file.freeSpace
val localFolder = File(storagePath, MainApp.getDataFolder())
val localFolder = File(storagePath, MainApp.dataFolder)
val localFolderSize = FileStorageUtils.getFolderSize(localFolder)
val remoteFolderSize = folder.fileLength

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class MediaFoldersDetectionWork(
private const val ACCOUNT_NAME_GLOBAL = "global"
private const val KEY_MEDIA_FOLDERS = "media_folders"
const val NOTIFICATION_ID = "NOTIFICATION_ID"
private val DISABLE_DETECTION_CLICK = MainApp.getAuthority() + "_DISABLE_DETECTION_CLICK"
private val DISABLE_DETECTION_CLICK = MainApp.authority + "_DISABLE_DETECTION_CLICK"
}

private val randomIdGenerator = Random(clock.currentTime)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2026 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
package com.nextcloud.client.migrations

import android.content.Context
import android.view.WindowManager.BadTokenException
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.nextcloud.client.core.Clock
import com.nextcloud.client.preferences.AppPreferencesImpl
import com.owncloud.android.R
import com.owncloud.android.datamodel.MediaFolder
import com.owncloud.android.datamodel.MediaFolderType
import com.owncloud.android.datamodel.MediaProvider
import com.owncloud.android.datamodel.SyncedFolder
import com.owncloud.android.datamodel.SyncedFolderProvider
import com.owncloud.android.lib.common.utils.Log_OC
import com.owncloud.android.ui.navigation.NavigatorActivity
import com.owncloud.android.ui.navigation.NavigatorScreen

object AutoUploadEntriesMigration {

private val TAG: String = AutoUploadEntriesMigration::class.java.simpleName
private const val MEDIA_FOLDER_ITEM_LIMIT = 1

fun updateToAutoUpload(context: Context) {
val preferences = AppPreferencesImpl.fromContext(context)
if (!preferences.instantPictureUploadEnabled() && !preferences.instantVideoUploadEnabled()) {
return
}

preferences.removeLegacyPreferences()

try {
showAutoUploadAlertDialog(context)
} catch (e: BadTokenException) {
Log_OC.i(TAG, "Error showing Auto Upload Update dialog, so skipping it: " + e.message)
}
}

private fun showAutoUploadAlertDialog(context: Context) {
MaterialAlertDialogBuilder(context, R.style.Theme_ownCloud_Dialog)
.setTitle(R.string.drawer_synced_folders)
.setMessage(R.string.synced_folders_new_info)
.setPositiveButton(R.string.drawer_open) { dialog, _ ->
val folderSyncIntent = NavigatorActivity.intent(context, NavigatorScreen.AutoUpload)
dialog.dismiss()
context.startActivity(folderSyncIntent)
}
.setNegativeButton(R.string.drawer_close) { dialog, _ -> dialog.dismiss() }
.setIcon(R.drawable.nav_synced_folders)
.create()
.show()
}

fun cleanOldEntries(context: Context, clock: Clock) {
val preferences = AppPreferencesImpl.fromContext(context)
if (preferences.isLegacyClean) {
return
}

val syncedFolderProvider = SyncedFolderProvider(context.contentResolver, preferences, clock)
val newestIds = syncedFolderProvider.syncedFolders
.groupBy { it.account to it.localPath }
.values
.map { duplicates -> duplicates.maxOf { it.id } }

if (newestIds.isEmpty()) {
preferences.isLegacyClean = true
return
}

val deletedCount = syncedFolderProvider.deleteSyncedFoldersNotInList(newestIds.toMutableList<Long?>())
if (deletedCount > 0) {
preferences.isLegacyClean = true
}
}

fun updateAutoUploadEntries(context: Context, clock: Clock) {
val preferences = AppPreferencesImpl.fromContext(context)
if (preferences.isAutoUploadPathsUpdateEnabled) {
return
}

SyncedFolderProvider(context.contentResolver, preferences, clock).updateAutoUploadPaths(context)
}

fun splitOutAutoUploadEntries(context: Context, clock: Clock) {
val preferences = AppPreferencesImpl.fromContext(context)
if (preferences.isAutoUploadSplitEntriesEnabled) {
return
}

Log_OC.i(TAG, "Migrate synced_folders records for image/video split")
val contentResolver = context.contentResolver
val syncedFolderProvider = SyncedFolderProvider(contentResolver, preferences, clock)
val imageMediaFolders = MediaProvider.getImageFolders(contentResolver, MEDIA_FOLDER_ITEM_LIMIT, null, true)
val videoMediaFolders = MediaProvider.getVideoFolders(contentResolver, MEDIA_FOLDER_ITEM_LIMIT, null, true)
val syncedFolders = syncedFolderProvider.syncedFolders

syncedFolders.forEach { syncedFolder ->
Log_OC.i(TAG, "Migration check for synced_folders record: ${syncedFolder.id} - ${syncedFolder.localPath}")
syncedFolderProvider.storeCopyIfMediaFolder(syncedFolder, imageMediaFolders, MediaFolderType.IMAGE, "image")
syncedFolderProvider.storeCopyIfMediaFolder(syncedFolder, videoMediaFolders, MediaFolderType.VIDEO, "video")
}

syncedFolders.forEach { syncedFolder ->
Log_OC.i(TAG, "Removing legacy synced_folders record: ${syncedFolder.id}")
syncedFolderProvider.deleteSyncedFolder(syncedFolder.id)
}

preferences.isAutoUploadSplitEntriesEnabled = true
}

private fun SyncedFolderProvider.storeCopyIfMediaFolder(
syncedFolder: SyncedFolder,
mediaFolders: List<MediaFolder>,
mediaType: MediaFolderType,
mediaTypeLabel: String
) {
val isMediaFolder = mediaFolders.any { it.absolutePath != null && it.absolutePath == syncedFolder.localPath }
if (!isMediaFolder) {
return
}

val newSyncedFolder = (syncedFolder.clone() as SyncedFolder).apply { setType(mediaType) }
val primaryKey = storeSyncedFolder(newSyncedFolder)
Log_OC.i(TAG, "Migrated $mediaTypeLabel synced_folders record: $primaryKey - ${newSyncedFolder.localPath}")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2026 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
package com.nextcloud.client.notifications

import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import com.owncloud.android.R
import com.owncloud.android.lib.common.utils.Log_OC
import com.owncloud.android.ui.notifications.NotificationUtils

object AppNotificationChannels {

private val TAG: String = AppNotificationChannels::class.java.simpleName

private val channels = listOf(
NotificationChannelSpec(
NotificationUtils.NOTIFICATION_CHANNEL_DOWNLOAD,
R.string.notification_channel_download_name_short,
R.string.notification_channel_download_description
),
NotificationChannelSpec(
NotificationUtils.NOTIFICATION_CHANNEL_UPLOAD,
R.string.notification_channel_upload_name_short,
R.string.notification_channel_upload_description
),
NotificationChannelSpec(
NotificationUtils.NOTIFICATION_CHANNEL_MEDIA,
R.string.notification_channel_media_name,
R.string.notification_channel_media_description
),
NotificationChannelSpec(
NotificationUtils.NOTIFICATION_CHANNEL_FILE_SYNC,
R.string.notification_channel_file_sync_name,
R.string.notification_channel_file_sync_description
),
NotificationChannelSpec(
NotificationUtils.NOTIFICATION_CHANNEL_PUSH,
R.string.notification_channel_push_name,
R.string.notification_channel_push_description,
NotificationManager.IMPORTANCE_DEFAULT
),
NotificationChannelSpec(
NotificationUtils.NOTIFICATION_CHANNEL_BACKGROUND_OPERATIONS,
R.string.notification_channel_background_operations_name,
R.string.notification_channel_background_operations_description
),
NotificationChannelSpec(
NotificationUtils.NOTIFICATION_CHANNEL_GENERAL,
R.string.notification_channel_general_name,
R.string.notification_channel_general_description,
NotificationManager.IMPORTANCE_DEFAULT
),
NotificationChannelSpec(
NotificationUtils.NOTIFICATION_CHANNEL_OFFLINE_OPERATIONS,
R.string.notification_channel_offline_operations_name_short,
R.string.notification_channel_offline_operations_description
),
NotificationChannelSpec(
NotificationUtils.NOTIFICATION_CHANNEL_CONTENT_OBSERVER,
R.string.notification_channel_content_observer_name_short,
R.string.notification_channel_content_observer_description
)
)

fun create(context: Context) {
val notificationManager = context.getSystemService(NotificationManager::class.java)
if (notificationManager == null) {
Log_OC.e(TAG, "Notification manager is null")
return
}

channels.forEach { notificationManager.createNotificationChannel(it.toNotificationChannel(context)) }
notificationManager.deleteNotificationChannel(NotificationUtils.NOTIFICATION_CHANNEL_FILE_OBSERVER)
}

private fun NotificationChannelSpec.toNotificationChannel(context: Context): NotificationChannel =
NotificationChannel(id, context.getString(nameRes), importance).apply {
description = context.getString(descriptionRes)
enableLights(false)
enableVibration(false)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2026 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
package com.nextcloud.client.notifications

import android.app.NotificationManager
import androidx.annotation.StringRes

data class NotificationChannelSpec(
val id: String,
@StringRes val nameRes: Int,
@StringRes val descriptionRes: Int,
val importance: Int = NotificationManager.IMPORTANCE_LOW
)
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,6 @@ class PlaybackDataSourceFactory @Inject constructor(
private fun createHttpDataSourceFactory(): HttpDataSource.Factory {
val client = clientFactory.createNextcloudClient(accountManager.user).client
return OkHttpDataSource.Factory(client)
.setUserAgent(MainApp.getUserAgent())
.setUserAgent(MainApp.userAgent)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class PlayerThumbnailLoader @Inject constructor(
"${client.baseUri}/index.php/core/preview?fileId=${file.id}&x=$width&y=$height&a=1&mode=cover&forceIcon=0",
LazyHeaders.Builder()
.addHeader("Authorization", client.credentials)
.addHeader("User-Agent", MainApp.getUserAgent())
.addHeader("User-Agent", MainApp.userAgent)
.build()
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class PlaybackFilesRepository @Inject constructor(
PlaybackCollection.GALLERY -> observeGalleryPlaybackFiles(fileType)
PlaybackCollection.SHARED -> observeSharedPlaybackFiles(fileType)
PlaybackCollection.ALBUM -> observeAlbumPlaybackFiles(fileType)
PlaybackCollection.FOLDER -> observeFolderPlaybackFiles(folderId, fileType, MainApp.isOnlyOnDevice())
PlaybackCollection.FOLDER -> observeFolderPlaybackFiles(folderId, fileType, MainApp.isOnlyOnDevice)
}

private fun observeAlbumPlaybackFiles(fileType: PlaybackFileType): Flow<PlaybackFiles> =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ class ImageDetailInfo(private val fragment: FileInfoFragment, private val viewTh
longitude: Double,
zoom: Double = 13.0
) {
Configuration.getInstance().userAgentValue = MainApp.getUserAgent()
Configuration.getInstance().userAgentValue = MainApp.userAgent

val location = GeoPoint(latitude, longitude)

Expand Down
Loading
Loading