diff --git a/app/src/androidTest/java/com/owncloud/android/AbstractIT.kt b/app/src/androidTest/java/com/owncloud/android/AbstractIT.kt index 661d96d7db03..9b0002e8ef54 100644 --- a/app/src/androidTest/java/com/owncloud/android/AbstractIT.kt +++ b/app/src/androidTest/java/com/owncloud/android/AbstractIT.kt @@ -321,7 +321,7 @@ abstract class AbstractIT { darkMode = DARK AppPreferencesImpl.fromContext(targetContext).setDarkThemeMode(DarkMode.DARK) - MainApp.setAppTheme(DarkMode.DARK) + DarkMode.DARK.setTheme() } @JvmStatic diff --git a/app/src/main/java/com/nextcloud/client/migrations/AutoUploadEntriesMigration.kt b/app/src/main/java/com/nextcloud/client/migrations/AutoUploadEntriesMigration.kt index 7bcf01ce6b43..7a5405b7923f 100644 --- a/app/src/main/java/com/nextcloud/client/migrations/AutoUploadEntriesMigration.kt +++ b/app/src/main/java/com/nextcloud/client/migrations/AutoUploadEntriesMigration.kt @@ -9,8 +9,7 @@ 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.nextcloud.client.preferences.AppPreferences import com.owncloud.android.R import com.owncloud.android.datamodel.MediaFolder import com.owncloud.android.datamodel.MediaFolderType @@ -20,14 +19,28 @@ 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 +import com.owncloud.android.utils.PermissionUtil +import javax.inject.Inject + +class AutoUploadEntriesMigration @Inject constructor( + private val context: Context, + private val preferences: AppPreferences, + private val syncedFolderProvider: SyncedFolderProvider +) { + + fun migrate() { + updateToAutoUpload() + cleanOldEntries() + updateAutoUploadEntries() + + if (PermissionUtil.checkStoragePermission(context)) { + splitOutAutoUploadEntries() + } else { + preferences.isAutoUploadSplitEntriesEnabled = true + } + } -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) + private fun updateToAutoUpload() { if (!preferences.instantPictureUploadEnabled() && !preferences.instantVideoUploadEnabled()) { return } @@ -35,13 +48,13 @@ object AutoUploadEntriesMigration { preferences.removeLegacyPreferences() try { - showAutoUploadAlertDialog(context) + showAutoUploadAlertDialog() } catch (e: BadTokenException) { Log_OC.i(TAG, "Error showing Auto Upload Update dialog, so skipping it: " + e.message) } } - private fun showAutoUploadAlertDialog(context: Context) { + private fun showAutoUploadAlertDialog() { MaterialAlertDialogBuilder(context, R.style.Theme_ownCloud_Dialog) .setTitle(R.string.drawer_synced_folders) .setMessage(R.string.synced_folders_new_info) @@ -56,13 +69,11 @@ object AutoUploadEntriesMigration { .show() } - fun cleanOldEntries(context: Context, clock: Clock) { - val preferences = AppPreferencesImpl.fromContext(context) + private fun cleanOldEntries() { if (preferences.isLegacyClean) { return } - val syncedFolderProvider = SyncedFolderProvider(context.contentResolver, preferences, clock) val newestIds = syncedFolderProvider.syncedFolders .groupBy { it.account to it.localPath } .values @@ -79,24 +90,21 @@ object AutoUploadEntriesMigration { } } - fun updateAutoUploadEntries(context: Context, clock: Clock) { - val preferences = AppPreferencesImpl.fromContext(context) + private fun updateAutoUploadEntries() { if (preferences.isAutoUploadPathsUpdateEnabled) { return } - SyncedFolderProvider(context.contentResolver, preferences, clock).updateAutoUploadPaths(context) + syncedFolderProvider.updateAutoUploadPaths(context) } - fun splitOutAutoUploadEntries(context: Context, clock: Clock) { - val preferences = AppPreferencesImpl.fromContext(context) + private fun splitOutAutoUploadEntries() { 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 @@ -130,4 +138,9 @@ object AutoUploadEntriesMigration { val primaryKey = storeSyncedFolder(newSyncedFolder) Log_OC.i(TAG, "Migrated $mediaTypeLabel synced_folders record: $primaryKey - ${newSyncedFolder.localPath}") } + + companion object { + private val TAG: String = AutoUploadEntriesMigration::class.java.simpleName + private const val MEDIA_FOLDER_ITEM_LIMIT = 1 + } } diff --git a/app/src/main/java/com/nextcloud/client/preferences/DarkMode.java b/app/src/main/java/com/nextcloud/client/preferences/DarkMode.java deleted file mode 100644 index c516893acd0c..000000000000 --- a/app/src/main/java/com/nextcloud/client/preferences/DarkMode.java +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Nextcloud - Android Client - * - * SPDX-FileCopyrightText: 2019 Tobias Kaminsky - * SPDX-FileCopyrightText: 2019 Nextcloud GmbH - * SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only - */ -package com.nextcloud.client.preferences; - -public enum DarkMode { - DARK, LIGHT, SYSTEM -} diff --git a/app/src/main/java/com/nextcloud/client/preferences/DarkMode.kt b/app/src/main/java/com/nextcloud/client/preferences/DarkMode.kt new file mode 100644 index 000000000000..58cd1654ae1a --- /dev/null +++ b/app/src/main/java/com/nextcloud/client/preferences/DarkMode.kt @@ -0,0 +1,25 @@ +/* + * Nextcloud - Android Client + * + * SPDX-FileCopyrightText: 2026 Alper Ozturk + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +package com.nextcloud.client.preferences + +import androidx.appcompat.app.AppCompatDelegate + +enum class DarkMode { + DARK, + LIGHT, + SYSTEM; + + fun setTheme() { + AppCompatDelegate.setDefaultNightMode(toMode()) + } + + private fun toMode(): Int = when (this) { + LIGHT -> AppCompatDelegate.MODE_NIGHT_NO + DARK -> AppCompatDelegate.MODE_NIGHT_YES + SYSTEM -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM + } +} diff --git a/app/src/main/java/com/owncloud/android/MainApp.kt b/app/src/main/java/com/owncloud/android/MainApp.kt index 0b20104cda47..f6bfa309fa53 100644 --- a/app/src/main/java/com/owncloud/android/MainApp.kt +++ b/app/src/main/java/com/owncloud/android/MainApp.kt @@ -17,14 +17,12 @@ import android.content.pm.PackageManager import android.content.res.Resources import android.os.StrictMode import androidx.annotation.StringRes -import androidx.appcompat.app.AppCompatDelegate import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleEventObserver import androidx.lifecycle.ProcessLifecycleOwner import com.nextcloud.appReview.InAppReviewHelper import com.nextcloud.client.account.UserAccountManager import com.nextcloud.client.appinfo.AppInfo -import com.nextcloud.client.core.Clock import com.nextcloud.client.device.PowerManagementService import com.nextcloud.client.di.ActivityInjector import com.nextcloud.client.di.AppComponent @@ -37,12 +35,10 @@ import com.nextcloud.client.migrations.AutoUploadEntriesMigration import com.nextcloud.client.migrations.MigrationsManager import com.nextcloud.client.network.ConnectivityService import com.nextcloud.client.network.NetworkChangeListener -import com.nextcloud.client.network.WalledCheckCache import com.nextcloud.client.notifications.AppNotificationChannels import com.nextcloud.client.onboarding.OnboardingService import com.nextcloud.client.preferences.AppPreferences import com.nextcloud.client.preferences.AppPreferencesImpl -import com.nextcloud.client.preferences.DarkMode import com.nextcloud.client.systembars.SystemBarBackgroundCallbacks import com.nextcloud.ui.composeActivity.ComposeProcessTextAlias import com.nextcloud.utils.extensions.registerBroadcastReceiver @@ -50,7 +46,7 @@ import com.nextcloud.utils.extensions.showToast import com.nextcloud.utils.mdm.MDMConfig import com.owncloud.android.authentication.GlobalPassCodeProtectionCallbacks import com.owncloud.android.authentication.PassCodeManager -import com.owncloud.android.datamodel.ArbitraryDataProviderImpl +import com.owncloud.android.datamodel.ArbitraryDataProvider import com.owncloud.android.datamodel.ReceiverFlag import com.owncloud.android.datamodel.SyncedFolderProvider import com.owncloud.android.datamodel.ThumbnailsCacheManager @@ -63,7 +59,6 @@ import com.owncloud.android.lib.resources.status.OwnCloudVersion import com.owncloud.android.providers.documentstorage.DocumentsStorageProvider import com.owncloud.android.ui.activity.ContactsPreferenceActivity import com.owncloud.android.utils.FilesSyncHelper -import com.owncloud.android.utils.PermissionUtil import com.owncloud.android.utils.ReceiversHelper import com.owncloud.android.utils.SecurityUtils import com.owncloud.android.utils.theme.ViewThemeUtils @@ -72,8 +67,6 @@ import dagger.android.DispatchingAndroidInjector import dagger.android.HasAndroidInjector import edu.umd.cs.findbugs.annotations.SuppressFBWarnings import org.conscrypt.Conscrypt -import org.greenrobot.eventbus.EventBus -import java.lang.ref.WeakReference import java.security.NoSuchAlgorithmException import java.security.Security import javax.inject.Inject @@ -119,28 +112,28 @@ open class MainApp : lateinit var backgroundJobManager: BackgroundJobManager @Inject - lateinit var clock: Clock + lateinit var migrationsManager: MigrationsManager @Inject - lateinit var eventBus: EventBus + lateinit var inAppReviewHelper: InAppReviewHelper @Inject - lateinit var migrationsManager: MigrationsManager + lateinit var passCodeManager: PassCodeManager @Inject - lateinit var inAppReviewHelper: InAppReviewHelper + lateinit var composeProcessTextAlias: ComposeProcessTextAlias @Inject - lateinit var passCodeManager: PassCodeManager + lateinit var viewThemeUtilsProvider: Provider @Inject - lateinit var walledCheckCache: WalledCheckCache + lateinit var arbitraryDataProvider: ArbitraryDataProvider @Inject - lateinit var composeProcessTextAlias: ComposeProcessTextAlias + lateinit var receiversHelper: ReceiversHelper @Inject - lateinit var viewThemeUtilsProvider: Provider + lateinit var autoUploadEntriesMigration: AutoUploadEntriesMigration private val restrictionsFilter = IntentFilter(Intent.ACTION_APPLICATION_RESTRICTIONS_CHANGED) @@ -189,8 +182,7 @@ open class MainApp : @SuppressFBWarnings("ST") override fun onCreate() { enableStrictMode() - val viewThemeUtils = viewThemeUtilsProvider.get() - setAppTheme(preferences.getDarkThemeMode()) + preferences.darkThemeMode.setTheme() super.onCreate() ProcessLifecycleOwner.get().lifecycle.addObserver(lifecycleEventObserver) @@ -212,19 +204,8 @@ open class MainApp : Log_OC.d(TAG, "scheduleContentObserverJob, called") backgroundJobManager.scheduleContentObserverJob() - initSyncOperations( - this, - preferences, - uploadsStorageManager, - accountManager, - connectivityService, - powerManagementService, - backgroundJobManager, - clock, - viewThemeUtils, - walledCheckCache - ) - initContactsBackup(accountManager, backgroundJobManager) + initSyncOperations() + initContactsBackup(arbitraryDataProvider, accountManager, backgroundJobManager) AppNotificationChannels.create(getAppContext()) scheduleBackgroundJobs() registerActivityLifecycleCallbacks(GlobalPassCodeProtectionCallbacks(onboarding, passCodeManager)) @@ -236,6 +217,24 @@ open class MainApp : connectivityService.addListener(this) } + private fun initSyncOperations() { + autoUploadEntriesMigration.migrate() + + if (!preferences.isAutoUploadInitialized()) { + preferences.setAutoUploadInit(true) + } + + FilesSyncHelper.restartUploadsIfNeeded( + uploadsStorageManager, + accountManager, + connectivityService, + powerManagementService + ) + + backgroundJobManager.scheduleOfflineSync() + receiversHelper.registerReceivers() + } + fun disableDocumentsStorageProvider() { packageManager.setComponentEnabledSetting( ComponentName(this, DocumentsStorageProvider::class.java), @@ -312,7 +311,7 @@ open class MainApp : OwnCloudClientManagerFactory.setProxyPort(port) Log_OC.d(TAG, "Proxy configuration successfully set") } catch (e: Resources.NotFoundException) { - Log_OC.e(TAG, "Proxy config cannot able to set due to: \$e") + Log_OC.e(TAG, "Proxy config cannot able to set due to: $e") } } @@ -366,7 +365,7 @@ open class MainApp : private fun disableDeathOnFileUriExposure() { try { StrictMode::class.java.getMethod("disableDeathOnFileUriExposure").invoke(null) - } catch (e: Exception) { + } catch (_: Exception) { Log_OC.d(DEBUG_TAG, "Failed to disable uri exposure") } } @@ -404,7 +403,6 @@ open class MainApp : override fun onTerminate() { super.onTerminate() connectivityService.removeListener(this) - ReceiversHelper.shutdown() AppPreferencesImpl.shutdown() } @@ -424,7 +422,7 @@ open class MainApp : private const val HIGHEST_SECURITY_PROVIDER_POSITION = 1 private const val NO_PACKAGE_INFO_FLAGS = 0 - private var appContext: WeakReference? = null + private lateinit var appContext: Context private var storagePath: String? = null private var appComponent: AppComponent? = null @@ -437,7 +435,7 @@ open class MainApp : private set private fun initGlobalContext(context: Context) { - appContext = WeakReference(context) + appContext = context } @JvmStatic @@ -452,12 +450,11 @@ open class MainApp : get() = getAppContext().resources.getBoolean(R.bool.is_branded_plus_client) @JvmStatic - fun initContactsBackup(accountManager: UserAccountManager?, backgroundJobManager: BackgroundJobManager?) { - if (accountManager == null || backgroundJobManager == null) { - return - } - - val arbitraryDataProvider = ArbitraryDataProviderImpl(getAppContext()) + fun initContactsBackup( + arbitraryDataProvider: ArbitraryDataProvider, + accountManager: UserAccountManager, + backgroundJobManager: BackgroundJobManager + ) { accountManager.allUsers .filter { arbitraryDataProvider.getBooleanValue( @@ -468,64 +465,6 @@ open class MainApp : .forEach { backgroundJobManager.schedulePeriodicContactsBackup(it) } } - @JvmStatic - fun initSyncOperations( - context: Context, - preferences: AppPreferences, - uploadsStorageManager: UploadsStorageManager, - accountManager: UserAccountManager, - connectivityService: ConnectivityService, - powerManagementService: PowerManagementService, - backgroundJobManager: BackgroundJobManager, - clock: Clock, - viewThemeUtils: ViewThemeUtils?, - walledCheckCache: WalledCheckCache? - ) { - val appContext = getAppContext() - AutoUploadEntriesMigration.updateToAutoUpload(context) - AutoUploadEntriesMigration.cleanOldEntries(appContext, clock) - AutoUploadEntriesMigration.updateAutoUploadEntries(appContext, clock) - - if (PermissionUtil.checkStoragePermission(appContext)) { - AutoUploadEntriesMigration.splitOutAutoUploadEntries(appContext, clock) - } else { - preferences.setAutoUploadSplitEntriesEnabled(true) - } - - if (!preferences.isAutoUploadInitialized()) { - preferences.setAutoUploadInit(true) - } - - FilesSyncHelper.restartUploadsIfNeeded( - uploadsStorageManager, - accountManager, - connectivityService, - powerManagementService - ) - - backgroundJobManager.scheduleOfflineSync() - - ReceiversHelper.registerNetworkChangeReceiver( - uploadsStorageManager, - accountManager, - connectivityService, - powerManagementService, - walledCheckCache - ) - ReceiversHelper.registerPowerChangeReceiver( - uploadsStorageManager, - accountManager, - connectivityService, - powerManagementService - ) - ReceiversHelper.registerPowerSaveReceiver( - uploadsStorageManager, - accountManager, - connectivityService, - powerManagementService - ) - } - @JvmStatic fun string(@StringRes id: Int): String = getAppContext().getString(id) @@ -533,12 +472,7 @@ open class MainApp : fun string(@StringRes id: Int, args: Any?): String = getAppContext().getString(id, args) @JvmStatic - fun getAppContext(): Context = appContext!!.get()!! - - @JvmStatic - fun setAppContext(context: Context?) { - appContext = WeakReference(context) - } + fun getAppContext(): Context = appContext @JvmStatic fun getStoragePath(): String? = storagePath @@ -559,14 +493,6 @@ open class MainApp : val authTokenType: String get() = string(R.string.authority) - @JvmStatic - val dbFile: String - get() = string(R.string.db_file) - - @JvmStatic - val dbName: String - get() = string(R.string.db_name) - @JvmStatic val dataFolder: String get() = string(R.string.data_folder) @@ -615,15 +541,5 @@ open class MainApp : "" } } - - @JvmStatic - fun setAppTheme(mode: DarkMode) { - val nightMode = when (mode) { - DarkMode.LIGHT -> AppCompatDelegate.MODE_NIGHT_NO - DarkMode.DARK -> AppCompatDelegate.MODE_NIGHT_YES - DarkMode.SYSTEM -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM - } - AppCompatDelegate.setDefaultNightMode(nightMode) - } } } diff --git a/app/src/main/java/com/owncloud/android/files/BootupBroadcastReceiver.java b/app/src/main/java/com/owncloud/android/files/BootupBroadcastReceiver.java deleted file mode 100644 index 22cae6e42047..000000000000 --- a/app/src/main/java/com/owncloud/android/files/BootupBroadcastReceiver.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Nextcloud - Android Client - * - * SPDX-FileCopyrightText: 2022 Tobias Kaminsky - * SPDX-FileCopyrightText: 2020 Chris Narkiewicz - * SPDX-FileCopyrightText: 2017 Mario Danic - * SPDX-FileCopyrightText: 2015 ownCloud Inc. - * SPDX-FileCopyrightText: 2014 David A. Velasco - * SPDX-FileCopyrightText: 2012 Bartosz Przybylski - * SPDX-License-Identifier: GPL-2.0-only AND (AGPL-3.0-or-later OR GPL-2.0-only) - */ -package com.owncloud.android.files; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; - -import com.nextcloud.client.account.UserAccountManager; -import com.nextcloud.client.core.Clock; -import com.nextcloud.client.device.PowerManagementService; -import com.nextcloud.client.jobs.BackgroundJobManager; -import com.nextcloud.client.network.ConnectivityService; -import com.nextcloud.client.network.WalledCheckCache; -import com.nextcloud.client.preferences.AppPreferences; -import com.owncloud.android.MainApp; -import com.owncloud.android.datamodel.UploadsStorageManager; -import com.owncloud.android.lib.common.utils.Log_OC; -import com.owncloud.android.utils.theme.ViewThemeUtils; - -import javax.inject.Inject; - -import dagger.android.AndroidInjection; - -/** - * App-registered receiver catching the broadcast intent reporting that the system was - * just boot up. - */ -public class BootupBroadcastReceiver extends BroadcastReceiver { - - private static final String TAG = BootupBroadcastReceiver.class.getSimpleName(); - - @Inject AppPreferences preferences; - @Inject UserAccountManager accountManager; - @Inject UploadsStorageManager uploadsStorageManager; - @Inject ConnectivityService connectivityService; - @Inject PowerManagementService powerManagementService; - @Inject BackgroundJobManager backgroundJobManager; - @Inject Clock clock; - @Inject ViewThemeUtils viewThemeUtils; - @Inject WalledCheckCache walledCheckCache; - - /** - * Receives broadcast intent reporting that the system was just boot up. * - * - * @param context The context where the receiver is running. - * @param intent The intent received. - */ - @Override - public void onReceive(Context context, Intent intent) { - AndroidInjection.inject(this, context); - - if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) { - MainApp.initSyncOperations(context, - preferences, - uploadsStorageManager, - accountManager, - connectivityService, - powerManagementService, - backgroundJobManager, - clock, - viewThemeUtils, - walledCheckCache); - Log_OC.d(TAG, "scheduleContentObserverJob, called"); - backgroundJobManager.scheduleContentObserverJob(); - backgroundJobManager.schedulePeriodicAutoUpload(); - MainApp.initContactsBackup(accountManager, backgroundJobManager); - } else { - Log_OC.d(TAG, "Getting wrong intent: " + intent.getAction()); - } - } -} diff --git a/app/src/main/java/com/owncloud/android/files/BootupBroadcastReceiver.kt b/app/src/main/java/com/owncloud/android/files/BootupBroadcastReceiver.kt new file mode 100644 index 000000000000..0b375015d499 --- /dev/null +++ b/app/src/main/java/com/owncloud/android/files/BootupBroadcastReceiver.kt @@ -0,0 +1,52 @@ +/* + * Nextcloud - Android Client + * + * SPDX-FileCopyrightText: 2026 Alper Ozturk + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +package com.owncloud.android.files + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import com.nextcloud.client.account.UserAccountManager +import com.nextcloud.client.jobs.BackgroundJobManager +import com.owncloud.android.MainApp +import com.owncloud.android.datamodel.ArbitraryDataProvider +import com.owncloud.android.lib.common.utils.Log_OC +import dagger.android.AndroidInjection +import javax.inject.Inject + +class BootupBroadcastReceiver : BroadcastReceiver() { + + @Inject + lateinit var arbitraryDataProvider: ArbitraryDataProvider + + @Inject + lateinit var accountManager: UserAccountManager + + @Inject + lateinit var backgroundJobManager: BackgroundJobManager + + override fun onReceive(context: Context, intent: Intent) { + AndroidInjection.inject(this, context) + + if (intent.action != Intent.ACTION_BOOT_COMPLETED) { + Log_OC.d(TAG, "Getting wrong intent: ${intent.action}") + return + } + + scheduleAutoUploadJobs() + MainApp.initContactsBackup(arbitraryDataProvider, accountManager, backgroundJobManager) + } + + private fun scheduleAutoUploadJobs() { + Log_OC.d(TAG, "scheduleContentObserverJob, called") + backgroundJobManager.scheduleContentObserverJob() + backgroundJobManager.schedulePeriodicAutoUpload() + } + + companion object { + private val TAG: String = BootupBroadcastReceiver::class.java.simpleName + } +} diff --git a/app/src/main/java/com/owncloud/android/ui/dialog/ThemeSelectionDialog.kt b/app/src/main/java/com/owncloud/android/ui/dialog/ThemeSelectionDialog.kt index 3e8216df7474..3c46590cba38 100644 --- a/app/src/main/java/com/owncloud/android/ui/dialog/ThemeSelectionDialog.kt +++ b/app/src/main/java/com/owncloud/android/ui/dialog/ThemeSelectionDialog.kt @@ -16,7 +16,6 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.nextcloud.client.di.Injectable import com.nextcloud.client.preferences.AppPreferences import com.nextcloud.client.preferences.DarkMode -import com.owncloud.android.MainApp import com.owncloud.android.R import com.owncloud.android.databinding.DialogThemeSelectionBinding import com.owncloud.android.ui.dialog.extensions.themeButtons @@ -83,13 +82,13 @@ class ThemeSelectionDialog : return builder.create() } - private fun applyTheme(mode: DarkMode) { - preferences.setDarkThemeMode(mode) - MainApp.setAppTheme(mode) + private fun applyTheme(darkMode: DarkMode) { + preferences.setDarkThemeMode(darkMode) + darkMode.setTheme() setFragmentResult( ExtendedSettingsActivityDialog.ThemeSelection.key, - bundleOf(ExtendedSettingsActivityDialog.ThemeSelection.key to mode.name) + bundleOf(ExtendedSettingsActivityDialog.ThemeSelection.key to darkMode.name) ) } diff --git a/app/src/main/java/com/owncloud/android/utils/ReceiversHelper.java b/app/src/main/java/com/owncloud/android/utils/ReceiversHelper.java deleted file mode 100644 index b3f1778ce40b..000000000000 --- a/app/src/main/java/com/owncloud/android/utils/ReceiversHelper.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Nextcloud - Android Client - * - * SPDX-FileCopyrightText: 2020 Chris Narkiewicz - * SPDX-FileCopyrightText: 2017 Mario Danic - * SPDX-FileCopyrightText: 2017 Nextcloud GmbH - * SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only - */ -package com.owncloud.android.utils; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; - -import com.nextcloud.client.account.UserAccountManager; -import com.nextcloud.client.device.PowerManagementService; -import com.nextcloud.client.network.ConnectivityKey; -import com.nextcloud.client.network.ConnectivityService; -import com.nextcloud.client.network.WalledCheckCache; -import com.nextcloud.common.DNSCache; -import com.nextcloud.utils.extensions.ContextExtensionsKt; -import com.owncloud.android.MainApp; -import com.owncloud.android.datamodel.ReceiverFlag; -import com.owncloud.android.datamodel.UploadsStorageManager; -import com.owncloud.android.lib.common.utils.Log_OC; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -/** - * Helper for setting up network and power receivers - */ -public final class ReceiversHelper { - - private ReceiversHelper() { - // utility class -> private constructor - } - - private static final String TAG = ReceiversHelper.class.getSimpleName(); - private static final ExecutorService executor = Executors.newSingleThreadExecutor(); - - public static void registerNetworkChangeReceiver(final UploadsStorageManager uploadsStorageManager, - final UserAccountManager accountManager, - final ConnectivityService connectivityService, - final PowerManagementService powerManagementService, - final WalledCheckCache walledCheckCache) { - Context context = MainApp.getAppContext(); - - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE"); - intentFilter.addAction("android.net.wifi.STATE_CHANGE"); - - BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - executor.execute(() -> { - DNSCache.clear(); - walledCheckCache.clear(ConnectivityKey.Companion.getBy(accountManager)); - Log_OC.d(TAG,"DNS caches are cleared"); - }); - - if (connectivityService.getConnectivity().isConnected()) { - FilesSyncHelper.restartUploadsIfNeeded(uploadsStorageManager, - accountManager, - connectivityService, - powerManagementService); - } - } - }; - - ContextExtensionsKt.registerBroadcastReceiver(context, broadcastReceiver, intentFilter, ReceiverFlag.NotExported); - } - - public static void registerPowerChangeReceiver( - final UploadsStorageManager uploadsStorageManager, - final UserAccountManager accountManager, - final ConnectivityService connectivityService, - final PowerManagementService powerManagementService - ) { - Context context = MainApp.getAppContext(); - - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(Intent.ACTION_POWER_CONNECTED); - intentFilter.addAction(Intent.ACTION_POWER_DISCONNECTED); - - BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (Intent.ACTION_POWER_CONNECTED.equals(intent.getAction())) { - FilesSyncHelper.restartUploadsIfNeeded(uploadsStorageManager, - accountManager, - connectivityService, - powerManagementService); - } - } - }; - - ContextExtensionsKt.registerBroadcastReceiver(context, broadcastReceiver, intentFilter, ReceiverFlag.NotExported); - } - - public static void registerPowerSaveReceiver( - final UploadsStorageManager uploadsStorageManager, - final UserAccountManager accountManager, - final ConnectivityService connectivityService, - final PowerManagementService powerManagementService - ) { - Context context = MainApp.getAppContext(); - - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction("android.os.action.POWER_SAVE_MODE_CHANGED"); - - BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (!powerManagementService.isPowerSavingEnabled()) { - FilesSyncHelper.restartUploadsIfNeeded(uploadsStorageManager, - accountManager, - connectivityService, - powerManagementService); - } - } - }; - - ContextExtensionsKt.registerBroadcastReceiver(context, broadcastReceiver, intentFilter, ReceiverFlag.NotExported); - } - - public static void shutdown() { - executor.shutdown(); - } -} diff --git a/app/src/main/java/com/owncloud/android/utils/ReceiversHelper.kt b/app/src/main/java/com/owncloud/android/utils/ReceiversHelper.kt new file mode 100644 index 000000000000..6ea6d5e1ecd4 --- /dev/null +++ b/app/src/main/java/com/owncloud/android/utils/ReceiversHelper.kt @@ -0,0 +1,102 @@ +/* + * Nextcloud - Android Client + * + * SPDX-FileCopyrightText: 2026 Alper Ozturk + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +package com.owncloud.android.utils + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.content.IntentFilter +import android.net.ConnectivityManager +import android.net.wifi.WifiManager +import android.os.PowerManager +import com.nextcloud.client.account.UserAccountManager +import com.nextcloud.client.device.PowerManagementService +import com.nextcloud.client.di.ApplicationScope +import com.nextcloud.client.network.ConnectivityKey +import com.nextcloud.client.network.ConnectivityService +import com.nextcloud.client.network.WalledCheckCache +import com.nextcloud.common.DNSCache +import com.nextcloud.utils.extensions.registerBroadcastReceiver +import com.owncloud.android.datamodel.ReceiverFlag +import com.owncloud.android.datamodel.UploadsStorageManager +import com.owncloud.android.lib.common.utils.Log_OC +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch +import javax.inject.Inject + +class ReceiversHelper @Inject constructor( + private val context: Context, + private val uploadsStorageManager: UploadsStorageManager, + private val accountManager: UserAccountManager, + private val connectivityService: ConnectivityService, + private val powerManagementService: PowerManagementService, + private val walledCheckCache: WalledCheckCache, + @param:ApplicationScope private val appScope: CoroutineScope +) { + + fun registerReceivers() { + registerNetworkChangeReceiver() + registerPowerChangeReceiver() + registerPowerSaveReceiver() + } + + private fun registerNetworkChangeReceiver() { + registerReceiver(CONNECTIVITY_CHANGE_ACTION, WifiManager.NETWORK_STATE_CHANGED_ACTION) { + appScope.launch { clearNetworkCaches() } + + if (!connectivityService.connectivity.isConnected) return@registerReceiver + + restartUploadsIfNeeded() + } + } + + private fun registerPowerChangeReceiver() { + registerReceiver(Intent.ACTION_POWER_CONNECTED, Intent.ACTION_POWER_DISCONNECTED) { intent -> + if (intent.action != Intent.ACTION_POWER_CONNECTED) return@registerReceiver + + restartUploadsIfNeeded() + } + } + + private fun registerPowerSaveReceiver() { + registerReceiver(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED) { + if (powerManagementService.isPowerSavingEnabled) return@registerReceiver + + restartUploadsIfNeeded() + } + } + + private fun registerReceiver(vararg actions: String, onIntent: (Intent) -> Unit) { + val intentFilter = IntentFilter().apply { actions.forEach(::addAction) } + val broadcastReceiver = object : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) = onIntent(intent) + } + context.registerBroadcastReceiver(broadcastReceiver, intentFilter, ReceiverFlag.NotExported) + } + + private fun restartUploadsIfNeeded() { + FilesSyncHelper.restartUploadsIfNeeded( + uploadsStorageManager, + accountManager, + connectivityService, + powerManagementService + ) + } + + private fun clearNetworkCaches() { + DNSCache.clear() + walledCheckCache.clear(ConnectivityKey.getBy(accountManager)) + Log_OC.d(TAG, "DNS caches are cleared") + } + + companion object { + private val TAG: String = ReceiversHelper::class.java.simpleName + + @Suppress("DEPRECATION") + private const val CONNECTIVITY_CHANGE_ACTION = ConnectivityManager.CONNECTIVITY_ACTION + } +}