From b73c097f3c8733deff57a89d71e9e2ec04a74037 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Aug 2022 23:08:10 +0000 Subject: [PATCH 01/55] Bump dagger from 2.42 to 2.43.2 Bumps `dagger` from 2.42 to 2.43.2. Updates `hilt-android-gradle-plugin` from 2.42 to 2.43.2 - [Release notes](https://github.com/google/dagger/releases) - [Changelog](https://github.com/google/dagger/blob/master/CHANGELOG.md) - [Commits](https://github.com/google/dagger/compare/dagger-2.42...dagger-2.43.2) Updates `dagger` from 2.42 to 2.43.2 - [Release notes](https://github.com/google/dagger/releases) - [Changelog](https://github.com/google/dagger/blob/master/CHANGELOG.md) - [Commits](https://github.com/google/dagger/compare/dagger-2.42...dagger-2.43.2) Updates `dagger-compiler` from 2.42 to 2.43.2 - [Release notes](https://github.com/google/dagger/releases) - [Changelog](https://github.com/google/dagger/blob/master/CHANGELOG.md) - [Commits](https://github.com/google/dagger/compare/dagger-2.42...dagger-2.43.2) Updates `hilt-android` from 2.42 to 2.43.2 - [Release notes](https://github.com/google/dagger/releases) - [Changelog](https://github.com/google/dagger/blob/master/CHANGELOG.md) - [Commits](https://github.com/google/dagger/compare/dagger-2.42...dagger-2.43.2) Updates `hilt-android-testing` from 2.42 to 2.43.2 - [Release notes](https://github.com/google/dagger/releases) - [Changelog](https://github.com/google/dagger/blob/master/CHANGELOG.md) - [Commits](https://github.com/google/dagger/compare/dagger-2.42...dagger-2.43.2) Updates `hilt-compiler` from 2.42 to 2.43.2 - [Release notes](https://github.com/google/dagger/releases) - [Changelog](https://github.com/google/dagger/blob/master/CHANGELOG.md) - [Commits](https://github.com/google/dagger/compare/dagger-2.42...dagger-2.43.2) --- updated-dependencies: - dependency-name: com.google.dagger:hilt-android-gradle-plugin dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.google.dagger:dagger dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.google.dagger:dagger-compiler dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.google.dagger:hilt-android dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.google.dagger:hilt-android-testing dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.google.dagger:hilt-compiler dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- dependencies.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies.gradle b/dependencies.gradle index 93a62a548e..e319fd2629 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -14,7 +14,7 @@ def gradle = "7.1.3" // Ref: https://kotlinlang.org/releases.html def kotlin = "1.6.21" def kotlinCoroutines = "1.6.4" -def dagger = "2.42" +def dagger = "2.43.2" def appDistribution = "16.0.0-beta03" def retrofit = "2.9.0" def arrow = "0.8.2" From e02cf61f2ff410b4accd1481ea1e0b564fb05ee9 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Mon, 8 Aug 2022 16:57:51 +0100 Subject: [PATCH 02/55] decoupling debug receiver from the variants by introducing vector layer interface --- .../app/features/debug/di/DebugModule.kt | 32 ++++++++++++++++ ...ebugReceiver.kt => VectorDebugReceiver.kt} | 12 +++++- .../vector/app/core/platform/DebugReceiver.kt | 24 ++++++++++++ .../app/core/platform/VectorBaseActivity.kt | 21 +++------- .../java/im/vector/app/core/di/DebugModule.kt | 38 +++++++++++++++++++ 5 files changed, 110 insertions(+), 17 deletions(-) create mode 100644 vector/src/debug/java/im/vector/app/features/debug/di/DebugModule.kt rename vector/src/debug/java/im/vector/app/receivers/{DebugReceiver.kt => VectorDebugReceiver.kt} (88%) create mode 100644 vector/src/main/java/im/vector/app/core/platform/DebugReceiver.kt create mode 100644 vector/src/release/java/im/vector/app/core/di/DebugModule.kt diff --git a/vector/src/debug/java/im/vector/app/features/debug/di/DebugModule.kt b/vector/src/debug/java/im/vector/app/features/debug/di/DebugModule.kt new file mode 100644 index 0000000000..d68d6c743f --- /dev/null +++ b/vector/src/debug/java/im/vector/app/features/debug/di/DebugModule.kt @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.debug.di + +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import im.vector.app.core.platform.DebugReceiver +import im.vector.app.receivers.VectorDebugReceiver + +@InstallIn(SingletonComponent::class) +@Module +abstract class DebugModule { + + @Binds + abstract fun bindsDebugReceiver(receiver: VectorDebugReceiver): DebugReceiver +} diff --git a/vector/src/debug/java/im/vector/app/receivers/DebugReceiver.kt b/vector/src/debug/java/im/vector/app/receivers/VectorDebugReceiver.kt similarity index 88% rename from vector/src/debug/java/im/vector/app/receivers/DebugReceiver.kt rename to vector/src/debug/java/im/vector/app/receivers/VectorDebugReceiver.kt index 9ec475d6d3..9b547a433e 100644 --- a/vector/src/debug/java/im/vector/app/receivers/DebugReceiver.kt +++ b/vector/src/debug/java/im/vector/app/receivers/VectorDebugReceiver.kt @@ -23,13 +23,23 @@ import android.content.IntentFilter import android.content.SharedPreferences import androidx.core.content.edit import im.vector.app.core.di.DefaultSharedPreferences +import im.vector.app.core.platform.DebugReceiver import im.vector.app.core.utils.lsFiles import timber.log.Timber +import javax.inject.Inject /** * Receiver to handle some command from ADB */ -class DebugReceiver : BroadcastReceiver() { +class VectorDebugReceiver @Inject constructor() : BroadcastReceiver(), DebugReceiver { + + override fun register(context: Context) { + context.registerReceiver(this, getIntentFilter(context)) + } + + override fun unregister(context: Context) { + context.unregisterReceiver(this) + } override fun onReceive(context: Context, intent: Intent) { Timber.v("Received debug action: ${intent.action}") diff --git a/vector/src/main/java/im/vector/app/core/platform/DebugReceiver.kt b/vector/src/main/java/im/vector/app/core/platform/DebugReceiver.kt new file mode 100644 index 0000000000..aeb99f312d --- /dev/null +++ b/vector/src/main/java/im/vector/app/core/platform/DebugReceiver.kt @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.core.platform + +import android.content.Context + +interface DebugReceiver { + fun register(context: Context) + fun unregister(context: Context) +} diff --git a/vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt b/vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt index 8a09b6bd46..e5c7ab9228 100644 --- a/vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt +++ b/vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt @@ -91,7 +91,7 @@ import im.vector.app.features.settings.FontScalePreferencesImpl import im.vector.app.features.settings.VectorPreferences import im.vector.app.features.themes.ActivityOtherThemes import im.vector.app.features.themes.ThemeUtils -import im.vector.app.receivers.DebugReceiver +import im.vector.app.receivers.VectorDebugReceiver import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import org.matrix.android.sdk.api.extensions.orFalse @@ -160,6 +160,8 @@ abstract class VectorBaseActivity : AppCompatActivity(), Maver @Inject lateinit var rageShake: RageShake @Inject lateinit var buildMeta: BuildMeta @Inject lateinit var fontScalePreferences: FontScalePreferences + // For debug only + @Inject lateinit var debugReceiver: VectorDebugReceiver @Inject lateinit var vectorFeatures: VectorFeatures @@ -176,9 +178,6 @@ abstract class VectorBaseActivity : AppCompatActivity(), Maver private var savedInstanceState: Bundle? = null - // For debug only - private var debugReceiver: DebugReceiver? = null - private val restorables = ArrayList() override fun attachBaseContext(base: Context) { @@ -418,13 +417,7 @@ abstract class VectorBaseActivity : AppCompatActivity(), Maver if (this !is BugReportActivity && vectorPreferences.useRageshake()) { rageShake.start() } - DebugReceiver - .getIntentFilter(this) - .takeIf { buildMeta.isDebug } - ?.let { - debugReceiver = DebugReceiver() - registerReceiver(debugReceiver, it) - } + debugReceiver.register(this) } private val postResumeScheduledActions = mutableListOf<() -> Unit>() @@ -454,11 +447,7 @@ abstract class VectorBaseActivity : AppCompatActivity(), Maver Timber.i("onPause Activity ${javaClass.simpleName}") rageShake.stop() - - debugReceiver?.let { - unregisterReceiver(debugReceiver) - debugReceiver = null - } + debugReceiver.unregister(this) } override fun onWindowFocusChanged(hasFocus: Boolean) { diff --git a/vector/src/release/java/im/vector/app/core/di/DebugModule.kt b/vector/src/release/java/im/vector/app/core/di/DebugModule.kt new file mode 100644 index 0000000000..2899b14b7b --- /dev/null +++ b/vector/src/release/java/im/vector/app/core/di/DebugModule.kt @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.debug.di + +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import im.vector.app.core.platform.DebugReceiver + +@InstallIn(SingletonComponent::class) +@Module +object DebugModule { + @Provides + fun providesDebugReceiver() = object: DebugReceiver { + override fun register(context: Context) { + // no op + } + + override fun unregister(context: Context) { + // no op + } + } +} From 19c8b2a630e0e15d1f828bec0e2a3a69e9b9b2d9 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Mon, 8 Aug 2022 17:02:08 +0100 Subject: [PATCH 03/55] moving debug menu access to only the debug sourceset and providing an injectable interface to decouple from the direct access --- vector/src/debug/AndroidManifest.xml | 1 + .../vector/app/features/debug/di/DebugModule.kt | 15 +++++++++++++++ vector/src/main/AndroidManifest.xml | 1 - .../app/features/navigation/DebugNavigator.kt} | 11 ++++++----- .../app/features/navigation/DefaultNavigator.kt | 7 ++++--- .../java/im/vector/app/core/di/DebugModule.kt | 11 ++++++++++- 6 files changed, 36 insertions(+), 10 deletions(-) rename vector/src/{release/java/im/vector/app/features/debug/DebugMenuActivity.kt => main/java/im/vector/app/features/navigation/DebugNavigator.kt} (74%) diff --git a/vector/src/debug/AndroidManifest.xml b/vector/src/debug/AndroidManifest.xml index 84fa2584b9..4ec47d4920 100644 --- a/vector/src/debug/AndroidManifest.xml +++ b/vector/src/debug/AndroidManifest.xml @@ -9,6 +9,7 @@ + - diff --git a/vector/src/release/java/im/vector/app/features/debug/DebugMenuActivity.kt b/vector/src/main/java/im/vector/app/features/navigation/DebugNavigator.kt similarity index 74% rename from vector/src/release/java/im/vector/app/features/debug/DebugMenuActivity.kt rename to vector/src/main/java/im/vector/app/features/navigation/DebugNavigator.kt index c5db033a18..26e8a3e5c6 100644 --- a/vector/src/release/java/im/vector/app/features/debug/DebugMenuActivity.kt +++ b/vector/src/main/java/im/vector/app/features/navigation/DebugNavigator.kt @@ -1,5 +1,5 @@ /* - * Copyright 2019 New Vector Ltd + * Copyright (c) 2022 New Vector Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,9 +14,10 @@ * limitations under the License. */ -package im.vector.app.features.debug +package im.vector.app.features.navigation -import androidx.appcompat.app.AppCompatActivity +import android.content.Context -// This activity is not accessible -class DebugMenuActivity : AppCompatActivity() +interface DebugNavigator { + fun openDebugMenu(context: Context) +} diff --git a/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt b/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt index 38db642287..e9f1619ed5 100644 --- a/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt +++ b/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt @@ -51,7 +51,6 @@ import im.vector.app.features.crypto.recover.BootstrapBottomSheet import im.vector.app.features.crypto.recover.SetupMode import im.vector.app.features.crypto.verification.SupportedVerificationMethodsProvider import im.vector.app.features.crypto.verification.VerificationBottomSheet -import im.vector.app.features.debug.DebugMenuActivity import im.vector.app.features.devtools.RoomDevToolActivity import im.vector.app.features.home.room.detail.RoomDetailActivity import im.vector.app.features.home.room.detail.arguments.TimelineArgs @@ -123,7 +122,8 @@ class DefaultNavigator @Inject constructor( private val spaceStateHandler: SpaceStateHandler, private val supportedVerificationMethodsProvider: SupportedVerificationMethodsProvider, private val features: VectorFeatures, - private val analyticsTracker: AnalyticsTracker + private val analyticsTracker: AnalyticsTracker, + private val debugNavigator: DebugNavigator, ) : Navigator { override fun openLogin(context: Context, loginConfig: LoginConfig?, flags: Int) { @@ -367,7 +367,7 @@ class DefaultNavigator @Inject constructor( } override fun openDebug(context: Context) { - context.startActivity(Intent(context, DebugMenuActivity::class.java)) + debugNavigator.openDebugMenu(context) } override fun openKeysBackupSetup(context: Context, showManualExport: Boolean) { @@ -615,3 +615,4 @@ class DefaultNavigator @Inject constructor( context.startActivity(this) } } + diff --git a/vector/src/release/java/im/vector/app/core/di/DebugModule.kt b/vector/src/release/java/im/vector/app/core/di/DebugModule.kt index 2899b14b7b..c5af1e06c8 100644 --- a/vector/src/release/java/im/vector/app/core/di/DebugModule.kt +++ b/vector/src/release/java/im/vector/app/core/di/DebugModule.kt @@ -21,12 +21,21 @@ import dagger.Module import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent import im.vector.app.core.platform.DebugReceiver +import im.vector.app.features.navigation.DebugNavigator @InstallIn(SingletonComponent::class) @Module object DebugModule { + @Provides - fun providesDebugReceiver() = object: DebugReceiver { + fun providesDebugNavigator() = object : DebugNavigator { + override fun openDebugMenu(context: Context) { + // no op + } + } + + @Provides + fun providesDebugReceiver() = object : DebugReceiver { override fun register(context: Context) { // no op } From 8156a646a118d951af376286b1836f22ab36901b Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Mon, 8 Aug 2022 17:06:57 +0100 Subject: [PATCH 04/55] moving debug interfaces to debug package --- .../debug/java/im/vector/app/features/debug/di/DebugModule.kt | 4 ++-- .../debug/java/im/vector/app/receivers/VectorDebugReceiver.kt | 2 +- .../app/{features/navigation => core/debug}/DebugNavigator.kt | 2 +- .../im/vector/app/core/{platform => debug}/DebugReceiver.kt | 2 +- .../im/vector/app/features/navigation/DefaultNavigator.kt | 1 + vector/src/release/java/im/vector/app/core/di/DebugModule.kt | 4 ++-- 6 files changed, 8 insertions(+), 7 deletions(-) rename vector/src/main/java/im/vector/app/{features/navigation => core/debug}/DebugNavigator.kt (94%) rename vector/src/main/java/im/vector/app/core/{platform => debug}/DebugReceiver.kt (95%) diff --git a/vector/src/debug/java/im/vector/app/features/debug/di/DebugModule.kt b/vector/src/debug/java/im/vector/app/features/debug/di/DebugModule.kt index f5f10bf9c9..fbac319ee9 100644 --- a/vector/src/debug/java/im/vector/app/features/debug/di/DebugModule.kt +++ b/vector/src/debug/java/im/vector/app/features/debug/di/DebugModule.kt @@ -23,9 +23,9 @@ import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent -import im.vector.app.core.platform.DebugReceiver +import im.vector.app.core.debug.DebugReceiver import im.vector.app.features.debug.DebugMenuActivity -import im.vector.app.features.navigation.DebugNavigator +import im.vector.app.core.debug.DebugNavigator import im.vector.app.receivers.VectorDebugReceiver @InstallIn(SingletonComponent::class) diff --git a/vector/src/debug/java/im/vector/app/receivers/VectorDebugReceiver.kt b/vector/src/debug/java/im/vector/app/receivers/VectorDebugReceiver.kt index 9b547a433e..827fc540f7 100644 --- a/vector/src/debug/java/im/vector/app/receivers/VectorDebugReceiver.kt +++ b/vector/src/debug/java/im/vector/app/receivers/VectorDebugReceiver.kt @@ -23,7 +23,7 @@ import android.content.IntentFilter import android.content.SharedPreferences import androidx.core.content.edit import im.vector.app.core.di.DefaultSharedPreferences -import im.vector.app.core.platform.DebugReceiver +import im.vector.app.core.debug.DebugReceiver import im.vector.app.core.utils.lsFiles import timber.log.Timber import javax.inject.Inject diff --git a/vector/src/main/java/im/vector/app/features/navigation/DebugNavigator.kt b/vector/src/main/java/im/vector/app/core/debug/DebugNavigator.kt similarity index 94% rename from vector/src/main/java/im/vector/app/features/navigation/DebugNavigator.kt rename to vector/src/main/java/im/vector/app/core/debug/DebugNavigator.kt index 26e8a3e5c6..16c8dac55c 100644 --- a/vector/src/main/java/im/vector/app/features/navigation/DebugNavigator.kt +++ b/vector/src/main/java/im/vector/app/core/debug/DebugNavigator.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package im.vector.app.features.navigation +package im.vector.app.core.debug import android.content.Context diff --git a/vector/src/main/java/im/vector/app/core/platform/DebugReceiver.kt b/vector/src/main/java/im/vector/app/core/debug/DebugReceiver.kt similarity index 95% rename from vector/src/main/java/im/vector/app/core/platform/DebugReceiver.kt rename to vector/src/main/java/im/vector/app/core/debug/DebugReceiver.kt index aeb99f312d..7cccba3d37 100644 --- a/vector/src/main/java/im/vector/app/core/platform/DebugReceiver.kt +++ b/vector/src/main/java/im/vector/app/core/debug/DebugReceiver.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package im.vector.app.core.platform +package im.vector.app.core.debug import android.content.Context diff --git a/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt b/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt index e9f1619ed5..872f102a0d 100644 --- a/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt +++ b/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt @@ -51,6 +51,7 @@ import im.vector.app.features.crypto.recover.BootstrapBottomSheet import im.vector.app.features.crypto.recover.SetupMode import im.vector.app.features.crypto.verification.SupportedVerificationMethodsProvider import im.vector.app.features.crypto.verification.VerificationBottomSheet +import im.vector.app.core.debug.DebugNavigator import im.vector.app.features.devtools.RoomDevToolActivity import im.vector.app.features.home.room.detail.RoomDetailActivity import im.vector.app.features.home.room.detail.arguments.TimelineArgs diff --git a/vector/src/release/java/im/vector/app/core/di/DebugModule.kt b/vector/src/release/java/im/vector/app/core/di/DebugModule.kt index c5af1e06c8..c340c36aed 100644 --- a/vector/src/release/java/im/vector/app/core/di/DebugModule.kt +++ b/vector/src/release/java/im/vector/app/core/di/DebugModule.kt @@ -20,8 +20,8 @@ import dagger.Binds import dagger.Module import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent -import im.vector.app.core.platform.DebugReceiver -import im.vector.app.features.navigation.DebugNavigator +import im.vector.app.core.debug.DebugNavigator +import im.vector.app.core.debug.DebugReceiver @InstallIn(SingletonComponent::class) @Module From 02286b96b05b8d2529848035753b352355c5f762 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Mon, 8 Aug 2022 17:13:43 +0100 Subject: [PATCH 05/55] decoupling the flipper proxy from the vector module --- .../app/features/debug/di/DebugModule.kt | 6 +++++ ...{FlipperProxy.kt => VectorFlipperProxy.kt} | 13 ++++------ .../java/im/vector/app/di/FlavorModule.kt | 8 ++++++ .../java/im/vector/app/di/FlavorModule.kt | 16 +++++++++--- ...ightlyProxy.kt => FirebaseNightlyProxy.kt} | 8 +++--- .../java/im/vector/app/VectorApplication.kt | 2 +- .../im/vector/app/core/debug/FlipperProxy.kt | 25 +++++++++++++++++++ .../im/vector/app/core/di/SingletonModule.kt | 4 +-- .../app/core/platform/VectorBaseActivity.kt | 5 ++-- .../vector/app/features/home/HomeActivity.kt | 1 - .../vector/app/features/home}/NightlyProxy.kt | 8 +++--- .../java/im/vector/app/core/di/DebugModule.kt | 17 +++++++++++-- 12 files changed, 85 insertions(+), 28 deletions(-) rename vector/src/debug/java/im/vector/app/flipper/{FlipperProxy.kt => VectorFlipperProxy.kt} (91%) rename vector/src/gplay/java/im/vector/app/nightly/{NightlyProxy.kt => FirebaseNightlyProxy.kt} (95%) create mode 100644 vector/src/main/java/im/vector/app/core/debug/FlipperProxy.kt rename vector/src/{fdroid/java/im/vector/app/nightly => main/java/im/vector/app/features/home}/NightlyProxy.kt (82%) diff --git a/vector/src/debug/java/im/vector/app/features/debug/di/DebugModule.kt b/vector/src/debug/java/im/vector/app/features/debug/di/DebugModule.kt index fbac319ee9..56df9fa0bc 100644 --- a/vector/src/debug/java/im/vector/app/features/debug/di/DebugModule.kt +++ b/vector/src/debug/java/im/vector/app/features/debug/di/DebugModule.kt @@ -26,6 +26,8 @@ import dagger.hilt.components.SingletonComponent import im.vector.app.core.debug.DebugReceiver import im.vector.app.features.debug.DebugMenuActivity import im.vector.app.core.debug.DebugNavigator +import im.vector.app.core.debug.FlipperProxy +import im.vector.app.flipper.VectorFlipperProxy import im.vector.app.receivers.VectorDebugReceiver @InstallIn(SingletonComponent::class) @@ -44,4 +46,8 @@ abstract class DebugModule { @Binds abstract fun bindsDebugReceiver(receiver: VectorDebugReceiver): DebugReceiver + + @Binds + abstract fun bindsFlipperProxy(flipperProxy: VectorFlipperProxy): FlipperProxy + } diff --git a/vector/src/debug/java/im/vector/app/flipper/FlipperProxy.kt b/vector/src/debug/java/im/vector/app/flipper/VectorFlipperProxy.kt similarity index 91% rename from vector/src/debug/java/im/vector/app/flipper/FlipperProxy.kt rename to vector/src/debug/java/im/vector/app/flipper/VectorFlipperProxy.kt index 76be7e1b46..2e4336c942 100644 --- a/vector/src/debug/java/im/vector/app/flipper/FlipperProxy.kt +++ b/vector/src/debug/java/im/vector/app/flipper/VectorFlipperProxy.kt @@ -29,19 +29,19 @@ import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPl import com.facebook.soloader.SoLoader import com.kgurgul.flipper.RealmDatabaseDriver import com.kgurgul.flipper.RealmDatabaseProvider +import im.vector.app.core.debug.FlipperProxy import io.realm.RealmConfiguration -import okhttp3.Interceptor import org.matrix.android.sdk.api.Matrix import javax.inject.Inject import javax.inject.Singleton @Singleton -class FlipperProxy @Inject constructor( +class VectorFlipperProxy @Inject constructor( private val context: Context, -) { +) : FlipperProxy { private val networkFlipperPlugin = NetworkFlipperPlugin() - fun init(matrix: Matrix) { + override fun init(matrix: Matrix) { SoLoader.init(context, false) if (FlipperUtils.shouldEnableFlipper(context)) { @@ -65,8 +65,5 @@ class FlipperProxy @Inject constructor( } } - @Suppress("RedundantNullableReturnType") - fun getNetworkInterceptor(): Interceptor? { - return FlipperOkhttpInterceptor(networkFlipperPlugin) - } + override fun networkInterceptor() = FlipperOkhttpInterceptor(networkFlipperPlugin) } diff --git a/vector/src/fdroid/java/im/vector/app/di/FlavorModule.kt b/vector/src/fdroid/java/im/vector/app/di/FlavorModule.kt index 1a3348f4c6..fcad54c3d2 100644 --- a/vector/src/fdroid/java/im/vector/app/di/FlavorModule.kt +++ b/vector/src/fdroid/java/im/vector/app/di/FlavorModule.kt @@ -23,6 +23,7 @@ import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent import im.vector.app.core.services.GuardServiceStarter import im.vector.app.fdroid.service.FDroidGuardServiceStarter +import im.vector.app.features.home.NightlyProxy import im.vector.app.features.settings.VectorPreferences @InstallIn(SingletonComponent::class) @@ -33,4 +34,11 @@ object FlavorModule { fun provideGuardServiceStarter(preferences: VectorPreferences, appContext: Context): GuardServiceStarter { return FDroidGuardServiceStarter(preferences, appContext) } + + @Provides + fun provideNightlyProxy() = object : NightlyProxy { + override fun onHomeResumed() { + // no op + } + } } diff --git a/vector/src/gplay/java/im/vector/app/di/FlavorModule.kt b/vector/src/gplay/java/im/vector/app/di/FlavorModule.kt index 901320be4c..256c908a02 100644 --- a/vector/src/gplay/java/im/vector/app/di/FlavorModule.kt +++ b/vector/src/gplay/java/im/vector/app/di/FlavorModule.kt @@ -16,18 +16,26 @@ package im.vector.app.di +import dagger.Binds import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent import im.vector.app.core.services.GuardServiceStarter +import im.vector.app.features.home.NightlyProxy +import im.vector.app.nightly.FirebaseNightlyProxy @InstallIn(SingletonComponent::class) @Module -object FlavorModule { +abstract class FlavorModule { - @Provides - fun provideGuardServiceStarter(): GuardServiceStarter { - return object : GuardServiceStarter {} + companion object { + @Provides + fun provideGuardServiceStarter(): GuardServiceStarter { + return object : GuardServiceStarter {} + } } + + @Binds + abstract fun bindsNightlyProxy(nightlyProxy: FirebaseNightlyProxy): NightlyProxy } diff --git a/vector/src/gplay/java/im/vector/app/nightly/NightlyProxy.kt b/vector/src/gplay/java/im/vector/app/nightly/FirebaseNightlyProxy.kt similarity index 95% rename from vector/src/gplay/java/im/vector/app/nightly/NightlyProxy.kt rename to vector/src/gplay/java/im/vector/app/nightly/FirebaseNightlyProxy.kt index 7c6685f5ce..59a1e3eb17 100644 --- a/vector/src/gplay/java/im/vector/app/nightly/NightlyProxy.kt +++ b/vector/src/gplay/java/im/vector/app/nightly/FirebaseNightlyProxy.kt @@ -23,15 +23,17 @@ import com.google.firebase.appdistribution.FirebaseAppDistributionException import im.vector.app.BuildConfig import im.vector.app.core.di.DefaultPreferences import im.vector.app.core.time.Clock +import im.vector.app.features.home.NightlyProxy import timber.log.Timber import javax.inject.Inject -class NightlyProxy @Inject constructor( +class FirebaseNightlyProxy @Inject constructor( private val clock: Clock, @DefaultPreferences private val sharedPreferences: SharedPreferences, -) { - fun onHomeResumed() { +) : NightlyProxy { + + override fun onHomeResumed() { if (!canDisplayPopup()) return val firebaseAppDistribution = FirebaseAppDistribution.getInstance() firebaseAppDistribution.updateIfNewReleaseAvailable() diff --git a/vector/src/main/java/im/vector/app/VectorApplication.kt b/vector/src/main/java/im/vector/app/VectorApplication.kt index b1bd0fc308..f31b5d915e 100644 --- a/vector/src/main/java/im/vector/app/VectorApplication.kt +++ b/vector/src/main/java/im/vector/app/VectorApplication.kt @@ -41,6 +41,7 @@ import com.vanniktech.emoji.EmojiManager import com.vanniktech.emoji.google.GoogleEmojiProvider import dagger.hilt.android.HiltAndroidApp import im.vector.app.config.Config +import im.vector.app.core.debug.FlipperProxy import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.resources.BuildMeta import im.vector.app.features.analytics.VectorAnalytics @@ -59,7 +60,6 @@ import im.vector.app.features.settings.VectorLocale import im.vector.app.features.settings.VectorPreferences import im.vector.app.features.themes.ThemeUtils import im.vector.app.features.version.VersionProvider -import im.vector.app.flipper.FlipperProxy import im.vector.app.push.fcm.FcmHelper import org.jitsi.meet.sdk.log.JitsiMeetDefaultLogHandler import org.matrix.android.sdk.api.Matrix diff --git a/vector/src/main/java/im/vector/app/core/debug/FlipperProxy.kt b/vector/src/main/java/im/vector/app/core/debug/FlipperProxy.kt new file mode 100644 index 0000000000..a05da239f5 --- /dev/null +++ b/vector/src/main/java/im/vector/app/core/debug/FlipperProxy.kt @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.core.debug + +import okhttp3.Interceptor +import org.matrix.android.sdk.api.Matrix + +interface FlipperProxy { + fun init(matrix: Matrix) + fun networkInterceptor(): Interceptor? +} diff --git a/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt b/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt index 6959f17586..a060ebe731 100644 --- a/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt +++ b/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt @@ -34,6 +34,7 @@ import im.vector.app.EmojiSpanify import im.vector.app.SpaceStateHandler import im.vector.app.SpaceStateHandlerImpl import im.vector.app.config.Config +import im.vector.app.core.debug.FlipperProxy import im.vector.app.core.dispatchers.CoroutineDispatchers import im.vector.app.core.error.DefaultErrorFormatter import im.vector.app.core.error.ErrorFormatter @@ -57,7 +58,6 @@ import im.vector.app.features.settings.FontScalePreferencesImpl import im.vector.app.features.settings.VectorPreferences import im.vector.app.features.ui.SharedPreferencesUiStateRepository import im.vector.app.features.ui.UiStateRepository -import im.vector.app.flipper.FlipperProxy import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.Dispatchers @@ -144,7 +144,7 @@ object VectorStaticModule { roomDisplayNameFallbackProvider = vectorRoomDisplayNameFallbackProvider, threadMessagesEnabledDefault = vectorPreferences.areThreadMessagesEnabled(), networkInterceptors = listOfNotNull( - flipperProxy.getNetworkInterceptor(), + flipperProxy.networkInterceptor(), ) ) } diff --git a/vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt b/vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt index e5c7ab9228..24a65e1071 100644 --- a/vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt +++ b/vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt @@ -55,6 +55,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.snackbar.Snackbar import dagger.hilt.android.EntryPointAccessors import im.vector.app.R +import im.vector.app.core.debug.DebugReceiver import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.di.ActivityEntryPoint import im.vector.app.core.dialogs.DialogLocker @@ -91,7 +92,6 @@ import im.vector.app.features.settings.FontScalePreferencesImpl import im.vector.app.features.settings.VectorPreferences import im.vector.app.features.themes.ActivityOtherThemes import im.vector.app.features.themes.ThemeUtils -import im.vector.app.receivers.VectorDebugReceiver import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import org.matrix.android.sdk.api.extensions.orFalse @@ -160,8 +160,9 @@ abstract class VectorBaseActivity : AppCompatActivity(), Maver @Inject lateinit var rageShake: RageShake @Inject lateinit var buildMeta: BuildMeta @Inject lateinit var fontScalePreferences: FontScalePreferences + // For debug only - @Inject lateinit var debugReceiver: VectorDebugReceiver + @Inject lateinit var debugReceiver: DebugReceiver @Inject lateinit var vectorFeatures: VectorFeatures diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt index 12cdaecdf9..4dd6f8cfba 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt @@ -79,7 +79,6 @@ import im.vector.app.features.spaces.invite.SpaceInviteBottomSheet import im.vector.app.features.spaces.share.ShareSpaceBottomSheet import im.vector.app.features.themes.ThemeUtils import im.vector.app.features.workers.signout.ServerBackupStatusViewModel -import im.vector.app.nightly.NightlyProxy import im.vector.app.push.fcm.FcmHelper import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach diff --git a/vector/src/fdroid/java/im/vector/app/nightly/NightlyProxy.kt b/vector/src/main/java/im/vector/app/features/home/NightlyProxy.kt similarity index 82% rename from vector/src/fdroid/java/im/vector/app/nightly/NightlyProxy.kt rename to vector/src/main/java/im/vector/app/features/home/NightlyProxy.kt index eecf3a24f2..b25add2ac9 100644 --- a/vector/src/fdroid/java/im/vector/app/nightly/NightlyProxy.kt +++ b/vector/src/main/java/im/vector/app/features/home/NightlyProxy.kt @@ -14,10 +14,8 @@ * limitations under the License. */ -package im.vector.app.nightly +package im.vector.app.features.home -import javax.inject.Inject - -class NightlyProxy @Inject constructor() { - fun onHomeResumed() = Unit +interface NightlyProxy { + fun onHomeResumed() } diff --git a/vector/src/release/java/im/vector/app/core/di/DebugModule.kt b/vector/src/release/java/im/vector/app/core/di/DebugModule.kt index c340c36aed..bedbe97864 100644 --- a/vector/src/release/java/im/vector/app/core/di/DebugModule.kt +++ b/vector/src/release/java/im/vector/app/core/di/DebugModule.kt @@ -14,14 +14,18 @@ * limitations under the License. */ -package im.vector.app.features.debug.di +package im.vector.app.core.di -import dagger.Binds +import android.content.Context import dagger.Module +import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent import im.vector.app.core.debug.DebugNavigator import im.vector.app.core.debug.DebugReceiver +import im.vector.app.core.debug.FlipperProxy +import okhttp3.Interceptor +import org.matrix.android.sdk.api.Matrix @InstallIn(SingletonComponent::class) @Module @@ -44,4 +48,13 @@ object DebugModule { // no op } } + + @Provides + fun providesFlipperProxy() = object : FlipperProxy { + override fun init(matrix: Matrix) { + // no op + } + + override fun networkInterceptor(): Interceptor? = null + } } From f605e0c4791318e3f8b103004b7cd4fa1fa4c223 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Mon, 8 Aug 2022 17:51:08 +0100 Subject: [PATCH 06/55] decoupling the notification test factory from the vector module --- .../vector/app/di/NotificationTestModule.kt | 31 +++++++++++++++++++ ...ficationTroubleshootTestManagerFactory.kt} | 7 +++-- .../vector/app/di/NotificationTestModule.kt | 31 +++++++++++++++++++ ...ficationTroubleshootTestManagerFactory.kt} | 7 +++-- ...ificationTroubleshootTestManagerFactory.kt | 24 ++++++++++++++ ...ttingsNotificationsTroubleshootFragment.kt | 2 +- 6 files changed, 95 insertions(+), 7 deletions(-) create mode 100644 vector/src/fdroid/java/im/vector/app/di/NotificationTestModule.kt rename vector/src/fdroid/java/im/vector/app/push/fcm/{NotificationTroubleshootTestManagerFactory.kt => FdroidNotificationTroubleshootTestManagerFactory.kt} (93%) create mode 100644 vector/src/gplay/java/im/vector/app/di/NotificationTestModule.kt rename vector/src/gplay/java/im/vector/app/push/fcm/{NotificationTroubleshootTestManagerFactory.kt => GoogleNotificationTroubleshootTestManagerFactory.kt} (93%) create mode 100644 vector/src/main/java/im/vector/app/features/push/NotificationTroubleshootTestManagerFactory.kt diff --git a/vector/src/fdroid/java/im/vector/app/di/NotificationTestModule.kt b/vector/src/fdroid/java/im/vector/app/di/NotificationTestModule.kt new file mode 100644 index 0000000000..a171126168 --- /dev/null +++ b/vector/src/fdroid/java/im/vector/app/di/NotificationTestModule.kt @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.di + +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.android.components.ActivityComponent +import im.vector.app.features.push.NotificationTroubleshootTestManagerFactory +import im.vector.app.push.fcm.FdroidNotificationTroubleshootTestManagerFactory + +@InstallIn(ActivityComponent::class) +@Module +abstract class NotificationTestModule { + @Binds + abstract fun bindsNotificationTestFactory(factory: FdroidNotificationTroubleshootTestManagerFactory): NotificationTroubleshootTestManagerFactory +} diff --git a/vector/src/fdroid/java/im/vector/app/push/fcm/NotificationTroubleshootTestManagerFactory.kt b/vector/src/fdroid/java/im/vector/app/push/fcm/FdroidNotificationTroubleshootTestManagerFactory.kt similarity index 93% rename from vector/src/fdroid/java/im/vector/app/push/fcm/NotificationTroubleshootTestManagerFactory.kt rename to vector/src/fdroid/java/im/vector/app/push/fcm/FdroidNotificationTroubleshootTestManagerFactory.kt index 5873b4308f..86843f0e6f 100644 --- a/vector/src/fdroid/java/im/vector/app/push/fcm/NotificationTroubleshootTestManagerFactory.kt +++ b/vector/src/fdroid/java/im/vector/app/push/fcm/FdroidNotificationTroubleshootTestManagerFactory.kt @@ -21,6 +21,7 @@ import im.vector.app.fdroid.features.settings.troubleshoot.TestAutoStartBoot import im.vector.app.fdroid.features.settings.troubleshoot.TestBackgroundRestrictions import im.vector.app.fdroid.features.settings.troubleshoot.TestBatteryOptimization import im.vector.app.features.VectorFeatures +import im.vector.app.features.push.NotificationTroubleshootTestManagerFactory import im.vector.app.features.settings.troubleshoot.NotificationTroubleshootTestManager import im.vector.app.features.settings.troubleshoot.TestAccountSettings import im.vector.app.features.settings.troubleshoot.TestAvailableUnifiedPushDistributors @@ -35,7 +36,7 @@ import im.vector.app.features.settings.troubleshoot.TestUnifiedPushEndpoint import im.vector.app.features.settings.troubleshoot.TestUnifiedPushGateway import javax.inject.Inject -class NotificationTroubleshootTestManagerFactory @Inject constructor( +class FdroidNotificationTroubleshootTestManagerFactory @Inject constructor( private val unifiedPushHelper: UnifiedPushHelper, private val testSystemSettings: TestSystemSettings, private val testAccountSettings: TestAccountSettings, @@ -52,9 +53,9 @@ class NotificationTroubleshootTestManagerFactory @Inject constructor( private val testBatteryOptimization: TestBatteryOptimization, private val testNotification: TestNotification, private val vectorFeatures: VectorFeatures, -) { +): NotificationTroubleshootTestManagerFactory { - fun create(fragment: Fragment): NotificationTroubleshootTestManager { + override fun create(fragment: Fragment): NotificationTroubleshootTestManager { val mgr = NotificationTroubleshootTestManager(fragment) mgr.addTest(testSystemSettings) mgr.addTest(testAccountSettings) diff --git a/vector/src/gplay/java/im/vector/app/di/NotificationTestModule.kt b/vector/src/gplay/java/im/vector/app/di/NotificationTestModule.kt new file mode 100644 index 0000000000..f3dfbccfc1 --- /dev/null +++ b/vector/src/gplay/java/im/vector/app/di/NotificationTestModule.kt @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.di + +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.android.components.ActivityComponent +import im.vector.app.features.push.NotificationTroubleshootTestManagerFactory +import im.vector.app.push.fcm.GoogleNotificationTroubleshootTestManagerFactory + +@InstallIn(ActivityComponent::class) +@Module +abstract class NotificationTestModule { + @Binds + abstract fun bindsNotificationTestFactory(factory: GoogleNotificationTroubleshootTestManagerFactory): NotificationTroubleshootTestManagerFactory +} diff --git a/vector/src/gplay/java/im/vector/app/push/fcm/NotificationTroubleshootTestManagerFactory.kt b/vector/src/gplay/java/im/vector/app/push/fcm/GoogleNotificationTroubleshootTestManagerFactory.kt similarity index 93% rename from vector/src/gplay/java/im/vector/app/push/fcm/NotificationTroubleshootTestManagerFactory.kt rename to vector/src/gplay/java/im/vector/app/push/fcm/GoogleNotificationTroubleshootTestManagerFactory.kt index b3425c778b..154e127fb6 100644 --- a/vector/src/gplay/java/im/vector/app/push/fcm/NotificationTroubleshootTestManagerFactory.kt +++ b/vector/src/gplay/java/im/vector/app/push/fcm/GoogleNotificationTroubleshootTestManagerFactory.kt @@ -18,6 +18,7 @@ package im.vector.app.push.fcm import androidx.fragment.app.Fragment import im.vector.app.core.pushers.UnifiedPushHelper import im.vector.app.features.VectorFeatures +import im.vector.app.features.push.NotificationTroubleshootTestManagerFactory import im.vector.app.features.settings.troubleshoot.NotificationTroubleshootTestManager import im.vector.app.features.settings.troubleshoot.TestAccountSettings import im.vector.app.features.settings.troubleshoot.TestAvailableUnifiedPushDistributors @@ -35,7 +36,7 @@ import im.vector.app.gplay.features.settings.troubleshoot.TestPlayServices import im.vector.app.gplay.features.settings.troubleshoot.TestTokenRegistration import javax.inject.Inject -class NotificationTroubleshootTestManagerFactory @Inject constructor( +class GoogleNotificationTroubleshootTestManagerFactory @Inject constructor( private val unifiedPushHelper: UnifiedPushHelper, private val testSystemSettings: TestSystemSettings, private val testAccountSettings: TestAccountSettings, @@ -52,9 +53,9 @@ class NotificationTroubleshootTestManagerFactory @Inject constructor( private val testPushFromPushGateway: TestPushFromPushGateway, private val testNotification: TestNotification, private val vectorFeatures: VectorFeatures, -) { +) : NotificationTroubleshootTestManagerFactory { - fun create(fragment: Fragment): NotificationTroubleshootTestManager { + override fun create(fragment: Fragment): NotificationTroubleshootTestManager { val mgr = NotificationTroubleshootTestManager(fragment) mgr.addTest(testSystemSettings) mgr.addTest(testAccountSettings) diff --git a/vector/src/main/java/im/vector/app/features/push/NotificationTroubleshootTestManagerFactory.kt b/vector/src/main/java/im/vector/app/features/push/NotificationTroubleshootTestManagerFactory.kt new file mode 100644 index 0000000000..6a3ce04c1a --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/push/NotificationTroubleshootTestManagerFactory.kt @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.push + +import androidx.fragment.app.Fragment +import im.vector.app.features.settings.troubleshoot.NotificationTroubleshootTestManager + +interface NotificationTroubleshootTestManagerFactory { + fun create(fragment: Fragment): NotificationTroubleshootTestManager +} diff --git a/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsNotificationsTroubleshootFragment.kt b/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsNotificationsTroubleshootFragment.kt index 8a3407b428..e75824195e 100644 --- a/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsNotificationsTroubleshootFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsNotificationsTroubleshootFragment.kt @@ -35,11 +35,11 @@ import im.vector.app.core.extensions.registerStartForActivityResult import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentSettingsNotificationsTroubleshootBinding import im.vector.app.features.notifications.NotificationActionIds +import im.vector.app.features.push.NotificationTroubleshootTestManagerFactory import im.vector.app.features.rageshake.BugReporter import im.vector.app.features.settings.VectorSettingsFragmentInteractionListener import im.vector.app.features.settings.troubleshoot.NotificationTroubleshootTestManager import im.vector.app.features.settings.troubleshoot.TroubleshootTest -import im.vector.app.push.fcm.NotificationTroubleshootTestManagerFactory import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.extensions.tryOrNull import javax.inject.Inject From 0c61595ace023f26d22aa85baf6a7fb8c3bdcd78 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Mon, 8 Aug 2022 18:05:04 +0100 Subject: [PATCH 07/55] decoupling the fcm helper from the vector module --- .../java/im/vector/app/di/FlavorModule.kt | 26 ++++++---- .../fcm/{FcmHelper.kt => FdroidFcmHelper.kt} | 17 ++++--- .../java/im/vector/app/di/FlavorModule.kt | 5 ++ .../troubleshoot/TestFirebaseToken.kt | 2 +- .../troubleshoot/TestTokenRegistration.kt | 2 +- .../fcm/{FcmHelper.kt => GoogleFcmHelper.kt} | 17 ++++--- .../java/im/vector/app/VectorApplication.kt | 2 +- .../im/vector/app/core/pushers/FcmHelper.kt | 50 +++++++++++++++++++ .../app/core/pushers/UnifiedPushHelper.kt | 1 - .../vector/app/features/home/HomeActivity.kt | 2 +- .../TestAvailableUnifiedPushDistributors.kt | 2 +- 11 files changed, 95 insertions(+), 31 deletions(-) rename vector/src/fdroid/java/im/vector/app/push/fcm/{FcmHelper.kt => FdroidFcmHelper.kt} (78%) rename vector/src/gplay/java/im/vector/app/push/fcm/{FcmHelper.kt => GoogleFcmHelper.kt} (87%) create mode 100644 vector/src/main/java/im/vector/app/core/pushers/FcmHelper.kt diff --git a/vector/src/fdroid/java/im/vector/app/di/FlavorModule.kt b/vector/src/fdroid/java/im/vector/app/di/FlavorModule.kt index fcad54c3d2..5a7a527c3f 100644 --- a/vector/src/fdroid/java/im/vector/app/di/FlavorModule.kt +++ b/vector/src/fdroid/java/im/vector/app/di/FlavorModule.kt @@ -17,28 +17,36 @@ package im.vector.app.di import android.content.Context +import dagger.Binds import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent +import im.vector.app.core.pushers.FcmHelper import im.vector.app.core.services.GuardServiceStarter import im.vector.app.fdroid.service.FDroidGuardServiceStarter import im.vector.app.features.home.NightlyProxy import im.vector.app.features.settings.VectorPreferences +import im.vector.app.push.fcm.FdroidFcmHelper @InstallIn(SingletonComponent::class) @Module -object FlavorModule { +abstract class FlavorModule { - @Provides - fun provideGuardServiceStarter(preferences: VectorPreferences, appContext: Context): GuardServiceStarter { - return FDroidGuardServiceStarter(preferences, appContext) - } + companion object { + @Provides + fun provideGuardServiceStarter(preferences: VectorPreferences, appContext: Context): GuardServiceStarter { + return FDroidGuardServiceStarter(preferences, appContext) + } - @Provides - fun provideNightlyProxy() = object : NightlyProxy { - override fun onHomeResumed() { - // no op + @Provides + fun provideNightlyProxy() = object : NightlyProxy { + override fun onHomeResumed() { + // no op + } } } + + @Binds + abstract fun bindsFcmHelper(fcmHelper: FdroidFcmHelper): FcmHelper } diff --git a/vector/src/fdroid/java/im/vector/app/push/fcm/FcmHelper.kt b/vector/src/fdroid/java/im/vector/app/push/fcm/FdroidFcmHelper.kt similarity index 78% rename from vector/src/fdroid/java/im/vector/app/push/fcm/FcmHelper.kt rename to vector/src/fdroid/java/im/vector/app/push/fcm/FdroidFcmHelper.kt index 24ff00a353..8d41ce1e00 100755 --- a/vector/src/fdroid/java/im/vector/app/push/fcm/FcmHelper.kt +++ b/vector/src/fdroid/java/im/vector/app/push/fcm/FdroidFcmHelper.kt @@ -20,6 +20,7 @@ package im.vector.app.push.fcm import android.app.Activity import android.content.Context import im.vector.app.core.di.ActiveSessionHolder +import im.vector.app.core.pushers.FcmHelper import im.vector.app.core.pushers.PushersManager import im.vector.app.fdroid.BackgroundSyncStarter import im.vector.app.fdroid.receiver.AlarmSyncBroadcastReceiver @@ -28,19 +29,19 @@ import javax.inject.Inject /** * This class has an alter ego in the gplay variant. */ -class FcmHelper @Inject constructor( +class FdroidFcmHelper @Inject constructor( private val context: Context, private val backgroundSyncStarter: BackgroundSyncStarter, -) { +) : FcmHelper { - fun isFirebaseAvailable(): Boolean = false + override fun isFirebaseAvailable(): Boolean = false /** * Retrieves the FCM registration token. * * @return the FCM token or null if not received from FCM */ - fun getFcmToken(): String? { + override fun getFcmToken(): String? { return null } @@ -49,7 +50,7 @@ class FcmHelper @Inject constructor( * * @param token the token to store */ - fun storeFcmToken(token: String?) { + override fun storeFcmToken(token: String?) { // No op } @@ -58,17 +59,17 @@ class FcmHelper @Inject constructor( * * @param activity the first launch Activity */ - fun ensureFcmTokenIsRetrieved(activity: Activity, pushersManager: PushersManager, registerPusher: Boolean) { + override fun ensureFcmTokenIsRetrieved(activity: Activity, pushersManager: PushersManager, registerPusher: Boolean) { // No op } - fun onEnterForeground(activeSessionHolder: ActiveSessionHolder) { + override fun onEnterForeground(activeSessionHolder: ActiveSessionHolder) { // try to stop all regardless of background mode activeSessionHolder.getSafeActiveSession()?.syncService()?.stopAnyBackgroundSync() AlarmSyncBroadcastReceiver.cancelAlarm(context) } - fun onEnterBackground(activeSessionHolder: ActiveSessionHolder) { + override fun onEnterBackground(activeSessionHolder: ActiveSessionHolder) { backgroundSyncStarter.start(activeSessionHolder) } } diff --git a/vector/src/gplay/java/im/vector/app/di/FlavorModule.kt b/vector/src/gplay/java/im/vector/app/di/FlavorModule.kt index 256c908a02..442f5f2eed 100644 --- a/vector/src/gplay/java/im/vector/app/di/FlavorModule.kt +++ b/vector/src/gplay/java/im/vector/app/di/FlavorModule.kt @@ -21,9 +21,11 @@ import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent +import im.vector.app.core.pushers.FcmHelper import im.vector.app.core.services.GuardServiceStarter import im.vector.app.features.home.NightlyProxy import im.vector.app.nightly.FirebaseNightlyProxy +import im.vector.app.push.fcm.GoogleFcmHelper @InstallIn(SingletonComponent::class) @Module @@ -38,4 +40,7 @@ abstract class FlavorModule { @Binds abstract fun bindsNightlyProxy(nightlyProxy: FirebaseNightlyProxy): NightlyProxy + + @Binds + abstract fun bindsFcmHelper(fcmHelper: GoogleFcmHelper): FcmHelper } diff --git a/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestFirebaseToken.kt b/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestFirebaseToken.kt index e7e3157f6b..d6180a9fe8 100644 --- a/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestFirebaseToken.kt +++ b/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestFirebaseToken.kt @@ -20,10 +20,10 @@ import androidx.activity.result.ActivityResultLauncher import androidx.fragment.app.FragmentActivity import com.google.firebase.messaging.FirebaseMessaging import im.vector.app.R +import im.vector.app.core.pushers.FcmHelper import im.vector.app.core.resources.StringProvider import im.vector.app.core.utils.startAddGoogleAccountIntent import im.vector.app.features.settings.troubleshoot.TroubleshootTest -import im.vector.app.push.fcm.FcmHelper import timber.log.Timber import javax.inject.Inject diff --git a/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestTokenRegistration.kt b/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestTokenRegistration.kt index 8c21404d20..840bde77b1 100644 --- a/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestTokenRegistration.kt +++ b/vector/src/gplay/java/im/vector/app/gplay/features/settings/troubleshoot/TestTokenRegistration.kt @@ -23,10 +23,10 @@ import androidx.work.WorkInfo import androidx.work.WorkManager import im.vector.app.R import im.vector.app.core.di.ActiveSessionHolder +import im.vector.app.core.pushers.FcmHelper import im.vector.app.core.pushers.PushersManager import im.vector.app.core.resources.StringProvider import im.vector.app.features.settings.troubleshoot.TroubleshootTest -import im.vector.app.push.fcm.FcmHelper import org.matrix.android.sdk.api.session.pushers.PusherState import javax.inject.Inject diff --git a/vector/src/gplay/java/im/vector/app/push/fcm/FcmHelper.kt b/vector/src/gplay/java/im/vector/app/push/fcm/GoogleFcmHelper.kt similarity index 87% rename from vector/src/gplay/java/im/vector/app/push/fcm/FcmHelper.kt rename to vector/src/gplay/java/im/vector/app/push/fcm/GoogleFcmHelper.kt index a4eb9efc73..636f4f3189 100755 --- a/vector/src/gplay/java/im/vector/app/push/fcm/FcmHelper.kt +++ b/vector/src/gplay/java/im/vector/app/push/fcm/GoogleFcmHelper.kt @@ -25,6 +25,7 @@ import com.google.firebase.messaging.FirebaseMessaging import im.vector.app.R import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.di.DefaultSharedPreferences +import im.vector.app.core.pushers.FcmHelper import im.vector.app.core.pushers.PushersManager import timber.log.Timber import javax.inject.Inject @@ -33,23 +34,23 @@ import javax.inject.Inject * This class store the FCM token in SharedPrefs and ensure this token is retrieved. * It has an alter ego in the fdroid variant. */ -class FcmHelper @Inject constructor( +class GoogleFcmHelper @Inject constructor( context: Context, -) { +) : FcmHelper { companion object { private const val PREFS_KEY_FCM_TOKEN = "FCM_TOKEN" } private val sharedPrefs = DefaultSharedPreferences.getInstance(context) - fun isFirebaseAvailable(): Boolean = true + override fun isFirebaseAvailable(): Boolean = true /** * Retrieves the FCM registration token. * * @return the FCM token or null if not received from FCM */ - fun getFcmToken(): String? { + override fun getFcmToken(): String? { return sharedPrefs.getString(PREFS_KEY_FCM_TOKEN, null) } @@ -59,7 +60,7 @@ class FcmHelper @Inject constructor( * * @param token the token to store */ - fun storeFcmToken(token: String?) { + override fun storeFcmToken(token: String?) { sharedPrefs.edit { putString(PREFS_KEY_FCM_TOKEN, token) } @@ -70,7 +71,7 @@ class FcmHelper @Inject constructor( * * @param activity the first launch Activity */ - fun ensureFcmTokenIsRetrieved(activity: Activity, pushersManager: PushersManager, registerPusher: Boolean) { + override fun ensureFcmTokenIsRetrieved(activity: Activity, pushersManager: PushersManager, registerPusher: Boolean) { // if (TextUtils.isEmpty(getFcmToken(activity))) { // 'app should always check the device for a compatible Google Play services APK before accessing Google Play services features' if (checkPlayServices(activity)) { @@ -106,12 +107,12 @@ class FcmHelper @Inject constructor( } @Suppress("UNUSED_PARAMETER") - fun onEnterForeground(activeSessionHolder: ActiveSessionHolder) { + override fun onEnterForeground(activeSessionHolder: ActiveSessionHolder) { // No op } @Suppress("UNUSED_PARAMETER") - fun onEnterBackground(activeSessionHolder: ActiveSessionHolder) { + override fun onEnterBackground(activeSessionHolder: ActiveSessionHolder) { // No op } } diff --git a/vector/src/main/java/im/vector/app/VectorApplication.kt b/vector/src/main/java/im/vector/app/VectorApplication.kt index f31b5d915e..53222ab962 100644 --- a/vector/src/main/java/im/vector/app/VectorApplication.kt +++ b/vector/src/main/java/im/vector/app/VectorApplication.kt @@ -43,6 +43,7 @@ import dagger.hilt.android.HiltAndroidApp import im.vector.app.config.Config import im.vector.app.core.debug.FlipperProxy import im.vector.app.core.di.ActiveSessionHolder +import im.vector.app.core.pushers.FcmHelper import im.vector.app.core.resources.BuildMeta import im.vector.app.features.analytics.VectorAnalytics import im.vector.app.features.call.webrtc.WebRtcCallManager @@ -60,7 +61,6 @@ import im.vector.app.features.settings.VectorLocale import im.vector.app.features.settings.VectorPreferences import im.vector.app.features.themes.ThemeUtils import im.vector.app.features.version.VersionProvider -import im.vector.app.push.fcm.FcmHelper import org.jitsi.meet.sdk.log.JitsiMeetDefaultLogHandler import org.matrix.android.sdk.api.Matrix import org.matrix.android.sdk.api.auth.AuthenticationService diff --git a/vector/src/main/java/im/vector/app/core/pushers/FcmHelper.kt b/vector/src/main/java/im/vector/app/core/pushers/FcmHelper.kt new file mode 100644 index 0000000000..601722a036 --- /dev/null +++ b/vector/src/main/java/im/vector/app/core/pushers/FcmHelper.kt @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.core.pushers + +import android.app.Activity +import im.vector.app.core.di.ActiveSessionHolder + +interface FcmHelper { + fun isFirebaseAvailable(): Boolean + + /** + * Retrieves the FCM registration token. + * + * @return the FCM token or null if not received from FCM + */ + fun getFcmToken(): String? + + /** + * Store FCM token to the SharedPrefs + * TODO Store in realm + * + * @param token the token to store + */ + fun storeFcmToken(token: String?) + + /** + * onNewToken may not be called on application upgrade, so ensure my shared pref is set + * + * @param activity the first launch Activity + */ + fun ensureFcmTokenIsRetrieved(activity: Activity, pushersManager: PushersManager, registerPusher: Boolean) + + fun onEnterForeground(activeSessionHolder: ActiveSessionHolder) + + fun onEnterBackground(activeSessionHolder: ActiveSessionHolder) +} diff --git a/vector/src/main/java/im/vector/app/core/pushers/UnifiedPushHelper.kt b/vector/src/main/java/im/vector/app/core/pushers/UnifiedPushHelper.kt index 724d3c7aa6..1f44ab3686 100644 --- a/vector/src/main/java/im/vector/app/core/pushers/UnifiedPushHelper.kt +++ b/vector/src/main/java/im/vector/app/core/pushers/UnifiedPushHelper.kt @@ -28,7 +28,6 @@ import im.vector.app.core.utils.getApplicationLabel import im.vector.app.features.VectorFeatures import im.vector.app.features.settings.BackgroundSyncMode import im.vector.app.features.settings.VectorPreferences -import im.vector.app.push.fcm.FcmHelper import kotlinx.coroutines.launch import org.matrix.android.sdk.api.Matrix import org.matrix.android.sdk.api.cache.CacheStrategy diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt index 4dd6f8cfba..fe57b9f735 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt @@ -44,6 +44,7 @@ import im.vector.app.core.extensions.replaceFragment import im.vector.app.core.extensions.validateBackPressed import im.vector.app.core.platform.VectorBaseActivity import im.vector.app.core.platform.VectorMenuProvider +import im.vector.app.core.pushers.FcmHelper import im.vector.app.core.pushers.PushersManager import im.vector.app.core.pushers.UnifiedPushHelper import im.vector.app.core.utils.startSharePlainTextIntent @@ -79,7 +80,6 @@ import im.vector.app.features.spaces.invite.SpaceInviteBottomSheet import im.vector.app.features.spaces.share.ShareSpaceBottomSheet import im.vector.app.features.themes.ThemeUtils import im.vector.app.features.workers.signout.ServerBackupStatusViewModel -import im.vector.app.push.fcm.FcmHelper import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch diff --git a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestAvailableUnifiedPushDistributors.kt b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestAvailableUnifiedPushDistributors.kt index acc0142924..89e7d8c204 100644 --- a/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestAvailableUnifiedPushDistributors.kt +++ b/vector/src/main/java/im/vector/app/features/settings/troubleshoot/TestAvailableUnifiedPushDistributors.kt @@ -19,9 +19,9 @@ package im.vector.app.features.settings.troubleshoot import android.content.Intent import androidx.activity.result.ActivityResultLauncher import im.vector.app.R +import im.vector.app.core.pushers.FcmHelper import im.vector.app.core.pushers.UnifiedPushHelper import im.vector.app.core.resources.StringProvider -import im.vector.app.push.fcm.FcmHelper import javax.inject.Inject class TestAvailableUnifiedPushDistributors @Inject constructor( From ed3b73a98990dbb6a80a147f90c5a157b0282ebe Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Tue, 9 Aug 2022 10:32:43 +0100 Subject: [PATCH 08/55] decouples the flavor code / OSS licenses activity launching --- .../fdroid/java/im/vector/app/di/FlavorModule.kt | 10 ++++++++++ .../app/{FlavorCode.kt => GoogleFlavorLegals.kt} | 14 ++++++++++++-- .../gplay/java/im/vector/app/di/FlavorModule.kt | 6 ++++++ .../app/features/settings/legals/FlavourLegals.kt} | 10 ++++++---- .../features/settings/legals/LegalsController.kt | 5 +++-- .../app/features/settings/legals/LegalsFragment.kt | 7 +++---- 6 files changed, 40 insertions(+), 12 deletions(-) rename vector/src/gplay/java/im/vector/app/{FlavorCode.kt => GoogleFlavorLegals.kt} (60%) rename vector/src/{fdroid/java/im/vector/app/FlavorCode.kt => main/java/im/vector/app/features/settings/legals/FlavourLegals.kt} (74%) diff --git a/vector/src/fdroid/java/im/vector/app/di/FlavorModule.kt b/vector/src/fdroid/java/im/vector/app/di/FlavorModule.kt index 5a7a527c3f..1936fbda8c 100644 --- a/vector/src/fdroid/java/im/vector/app/di/FlavorModule.kt +++ b/vector/src/fdroid/java/im/vector/app/di/FlavorModule.kt @@ -27,6 +27,7 @@ import im.vector.app.core.services.GuardServiceStarter import im.vector.app.fdroid.service.FDroidGuardServiceStarter import im.vector.app.features.home.NightlyProxy import im.vector.app.features.settings.VectorPreferences +import im.vector.app.features.settings.legals.FlavourLegals import im.vector.app.push.fcm.FdroidFcmHelper @InstallIn(SingletonComponent::class) @@ -45,6 +46,15 @@ abstract class FlavorModule { // no op } } + + @Provides + fun providesFlavorLegals() = object : FlavourLegals { + override fun hasThirdPartyNotices() = false + + override fun navigateToThirdPartyNotices(context: Context) { + // no op + } + } } @Binds diff --git a/vector/src/gplay/java/im/vector/app/FlavorCode.kt b/vector/src/gplay/java/im/vector/app/GoogleFlavorLegals.kt similarity index 60% rename from vector/src/gplay/java/im/vector/app/FlavorCode.kt rename to vector/src/gplay/java/im/vector/app/GoogleFlavorLegals.kt index 040296d755..32849b3741 100644 --- a/vector/src/gplay/java/im/vector/app/FlavorCode.kt +++ b/vector/src/gplay/java/im/vector/app/GoogleFlavorLegals.kt @@ -1,5 +1,5 @@ /* - * Copyright 2020 New Vector Ltd + * Copyright (c) 2022 New Vector Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,5 +19,15 @@ package im.vector.app import android.content.Context import android.content.Intent import com.google.android.gms.oss.licenses.OssLicensesMenuActivity +import im.vector.app.features.settings.legals.FlavourLegals +import javax.inject.Inject -fun openOssLicensesMenuActivity(context: Context) = context.startActivity(Intent(context, OssLicensesMenuActivity::class.java)) +class GoogleFlavorLegals @Inject constructor() : FlavourLegals { + + override fun hasThirdPartyNotices() = true + + override fun navigateToThirdPartyNotices(context: Context) { + // See https://developers.google.com/android/guides/opensource + context.startActivity(Intent(context, OssLicensesMenuActivity::class.java)) + } +} diff --git a/vector/src/gplay/java/im/vector/app/di/FlavorModule.kt b/vector/src/gplay/java/im/vector/app/di/FlavorModule.kt index 442f5f2eed..c97d1bff04 100644 --- a/vector/src/gplay/java/im/vector/app/di/FlavorModule.kt +++ b/vector/src/gplay/java/im/vector/app/di/FlavorModule.kt @@ -21,9 +21,11 @@ import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent +import im.vector.app.GoogleFlavorLegals import im.vector.app.core.pushers.FcmHelper import im.vector.app.core.services.GuardServiceStarter import im.vector.app.features.home.NightlyProxy +import im.vector.app.features.settings.legals.FlavourLegals import im.vector.app.nightly.FirebaseNightlyProxy import im.vector.app.push.fcm.GoogleFcmHelper @@ -43,4 +45,8 @@ abstract class FlavorModule { @Binds abstract fun bindsFcmHelper(fcmHelper: GoogleFcmHelper): FcmHelper + + @Binds + abstract fun bindsFlavorLegals(legals: GoogleFlavorLegals): FlavourLegals } + diff --git a/vector/src/fdroid/java/im/vector/app/FlavorCode.kt b/vector/src/main/java/im/vector/app/features/settings/legals/FlavourLegals.kt similarity index 74% rename from vector/src/fdroid/java/im/vector/app/FlavorCode.kt rename to vector/src/main/java/im/vector/app/features/settings/legals/FlavourLegals.kt index 7d8ef22b44..a33ad23f7e 100644 --- a/vector/src/fdroid/java/im/vector/app/FlavorCode.kt +++ b/vector/src/main/java/im/vector/app/features/settings/legals/FlavourLegals.kt @@ -1,5 +1,5 @@ /* - * Copyright 2020 New Vector Ltd + * Copyright (c) 2022 New Vector Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,9 +14,11 @@ * limitations under the License. */ -package im.vector.app +package im.vector.app.features.settings.legals import android.content.Context -// No op -fun openOssLicensesMenuActivity(@Suppress("UNUSED_PARAMETER") context: Context) = Unit +interface FlavourLegals { + fun hasThirdPartyNotices(): Boolean + fun navigateToThirdPartyNotices(context: Context) +} diff --git a/vector/src/main/java/im/vector/app/features/settings/legals/LegalsController.kt b/vector/src/main/java/im/vector/app/features/settings/legals/LegalsController.kt index f88b73f36c..c64b2e51d3 100644 --- a/vector/src/main/java/im/vector/app/features/settings/legals/LegalsController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/legals/LegalsController.kt @@ -38,7 +38,8 @@ class LegalsController @Inject constructor( private val stringProvider: StringProvider, private val resources: Resources, private val elementLegals: ElementLegals, - private val errorFormatter: ErrorFormatter + private val errorFormatter: ErrorFormatter, + private val flavourLegals: FlavourLegals, ) : TypedEpoxyController() { var listener: Listener? = null @@ -134,7 +135,7 @@ class LegalsController @Inject constructor( clickListener { host.listener?.openThirdPartyNotice() } } // Only on Gplay - if (resources.getBoolean(R.bool.isGplay)) { + if (flavourLegals.hasThirdPartyNotices()) { discoveryPolicyItem { id("eltpn2") name(host.stringProvider.getString(R.string.settings_other_third_party_notices)) diff --git a/vector/src/main/java/im/vector/app/features/settings/legals/LegalsFragment.kt b/vector/src/main/java/im/vector/app/features/settings/legals/LegalsFragment.kt index 9a4090ad1b..7bdcb9b5c9 100644 --- a/vector/src/main/java/im/vector/app/features/settings/legals/LegalsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/legals/LegalsFragment.kt @@ -33,11 +33,11 @@ import im.vector.app.databinding.FragmentGenericRecyclerBinding import im.vector.app.features.analytics.plan.MobileScreen import im.vector.app.features.discovery.ServerPolicy import im.vector.app.features.settings.VectorSettingsUrls -import im.vector.app.openOssLicensesMenuActivity import javax.inject.Inject class LegalsFragment @Inject constructor( - private val controller: LegalsController + private val controller: LegalsController, + private val flavourLegals: FlavourLegals, ) : VectorBaseFragment(), LegalsController.Listener { @@ -100,8 +100,7 @@ class LegalsFragment @Inject constructor( override fun openThirdPartyNoticeGplay() { if (firstThrottler.canHandle() is FirstThrottler.CanHandlerResult.Yes) { - // See https://developers.google.com/android/guides/opensource - openOssLicensesMenuActivity(requireActivity()) + flavourLegals.navigateToThirdPartyNotices(requireContext()) } } } From 045398d06feddff81be334cddf8c834a86383d68 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Tue, 9 Aug 2022 10:42:44 +0100 Subject: [PATCH 09/55] fixing import ordering and duplicated documentation --- .../app/features/debug/di/DebugModule.kt | 5 ++--- .../app/receivers/VectorDebugReceiver.kt | 2 +- .../im/vector/app/push/fcm/FdroidFcmHelper.kt | 15 --------------- ...ificationTroubleshootTestManagerFactory.kt | 2 +- .../java/im/vector/app/di/FlavorModule.kt | 1 - .../im/vector/app/push/fcm/GoogleFcmHelper.kt | 19 +------------------ .../im/vector/app/core/pushers/FcmHelper.kt | 13 +++++++------ .../features/navigation/DefaultNavigator.kt | 3 +-- 8 files changed, 13 insertions(+), 47 deletions(-) diff --git a/vector/src/debug/java/im/vector/app/features/debug/di/DebugModule.kt b/vector/src/debug/java/im/vector/app/features/debug/di/DebugModule.kt index 56df9fa0bc..b15f6dce62 100644 --- a/vector/src/debug/java/im/vector/app/features/debug/di/DebugModule.kt +++ b/vector/src/debug/java/im/vector/app/features/debug/di/DebugModule.kt @@ -23,10 +23,10 @@ import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent -import im.vector.app.core.debug.DebugReceiver -import im.vector.app.features.debug.DebugMenuActivity import im.vector.app.core.debug.DebugNavigator +import im.vector.app.core.debug.DebugReceiver import im.vector.app.core.debug.FlipperProxy +import im.vector.app.features.debug.DebugMenuActivity import im.vector.app.flipper.VectorFlipperProxy import im.vector.app.receivers.VectorDebugReceiver @@ -49,5 +49,4 @@ abstract class DebugModule { @Binds abstract fun bindsFlipperProxy(flipperProxy: VectorFlipperProxy): FlipperProxy - } diff --git a/vector/src/debug/java/im/vector/app/receivers/VectorDebugReceiver.kt b/vector/src/debug/java/im/vector/app/receivers/VectorDebugReceiver.kt index 827fc540f7..550dc055d9 100644 --- a/vector/src/debug/java/im/vector/app/receivers/VectorDebugReceiver.kt +++ b/vector/src/debug/java/im/vector/app/receivers/VectorDebugReceiver.kt @@ -22,8 +22,8 @@ import android.content.Intent import android.content.IntentFilter import android.content.SharedPreferences import androidx.core.content.edit -import im.vector.app.core.di.DefaultSharedPreferences import im.vector.app.core.debug.DebugReceiver +import im.vector.app.core.di.DefaultSharedPreferences import im.vector.app.core.utils.lsFiles import timber.log.Timber import javax.inject.Inject diff --git a/vector/src/fdroid/java/im/vector/app/push/fcm/FdroidFcmHelper.kt b/vector/src/fdroid/java/im/vector/app/push/fcm/FdroidFcmHelper.kt index 8d41ce1e00..5b83769116 100755 --- a/vector/src/fdroid/java/im/vector/app/push/fcm/FdroidFcmHelper.kt +++ b/vector/src/fdroid/java/im/vector/app/push/fcm/FdroidFcmHelper.kt @@ -36,29 +36,14 @@ class FdroidFcmHelper @Inject constructor( override fun isFirebaseAvailable(): Boolean = false - /** - * Retrieves the FCM registration token. - * - * @return the FCM token or null if not received from FCM - */ override fun getFcmToken(): String? { return null } - /** - * Store FCM token to the SharedPrefs - * - * @param token the token to store - */ override fun storeFcmToken(token: String?) { // No op } - /** - * onNewToken may not be called on application upgrade, so ensure my shared pref is set - * - * @param activity the first launch Activity - */ override fun ensureFcmTokenIsRetrieved(activity: Activity, pushersManager: PushersManager, registerPusher: Boolean) { // No op } diff --git a/vector/src/fdroid/java/im/vector/app/push/fcm/FdroidNotificationTroubleshootTestManagerFactory.kt b/vector/src/fdroid/java/im/vector/app/push/fcm/FdroidNotificationTroubleshootTestManagerFactory.kt index 86843f0e6f..d99afa59f7 100644 --- a/vector/src/fdroid/java/im/vector/app/push/fcm/FdroidNotificationTroubleshootTestManagerFactory.kt +++ b/vector/src/fdroid/java/im/vector/app/push/fcm/FdroidNotificationTroubleshootTestManagerFactory.kt @@ -53,7 +53,7 @@ class FdroidNotificationTroubleshootTestManagerFactory @Inject constructor( private val testBatteryOptimization: TestBatteryOptimization, private val testNotification: TestNotification, private val vectorFeatures: VectorFeatures, -): NotificationTroubleshootTestManagerFactory { +) : NotificationTroubleshootTestManagerFactory { override fun create(fragment: Fragment): NotificationTroubleshootTestManager { val mgr = NotificationTroubleshootTestManager(fragment) diff --git a/vector/src/gplay/java/im/vector/app/di/FlavorModule.kt b/vector/src/gplay/java/im/vector/app/di/FlavorModule.kt index c97d1bff04..393ea1e62a 100644 --- a/vector/src/gplay/java/im/vector/app/di/FlavorModule.kt +++ b/vector/src/gplay/java/im/vector/app/di/FlavorModule.kt @@ -49,4 +49,3 @@ abstract class FlavorModule { @Binds abstract fun bindsFlavorLegals(legals: GoogleFlavorLegals): FlavourLegals } - diff --git a/vector/src/gplay/java/im/vector/app/push/fcm/GoogleFcmHelper.kt b/vector/src/gplay/java/im/vector/app/push/fcm/GoogleFcmHelper.kt index 636f4f3189..d64847c124 100755 --- a/vector/src/gplay/java/im/vector/app/push/fcm/GoogleFcmHelper.kt +++ b/vector/src/gplay/java/im/vector/app/push/fcm/GoogleFcmHelper.kt @@ -45,32 +45,17 @@ class GoogleFcmHelper @Inject constructor( override fun isFirebaseAvailable(): Boolean = true - /** - * Retrieves the FCM registration token. - * - * @return the FCM token or null if not received from FCM - */ override fun getFcmToken(): String? { return sharedPrefs.getString(PREFS_KEY_FCM_TOKEN, null) } - /** - * Store FCM token to the SharedPrefs - * TODO Store in realm - * - * @param token the token to store - */ override fun storeFcmToken(token: String?) { + // TODO Store in realm sharedPrefs.edit { putString(PREFS_KEY_FCM_TOKEN, token) } } - /** - * onNewToken may not be called on application upgrade, so ensure my shared pref is set - * - * @param activity the first launch Activity - */ override fun ensureFcmTokenIsRetrieved(activity: Activity, pushersManager: PushersManager, registerPusher: Boolean) { // if (TextUtils.isEmpty(getFcmToken(activity))) { // 'app should always check the device for a compatible Google Play services APK before accessing Google Play services features' @@ -106,12 +91,10 @@ class GoogleFcmHelper @Inject constructor( return resultCode == ConnectionResult.SUCCESS } - @Suppress("UNUSED_PARAMETER") override fun onEnterForeground(activeSessionHolder: ActiveSessionHolder) { // No op } - @Suppress("UNUSED_PARAMETER") override fun onEnterBackground(activeSessionHolder: ActiveSessionHolder) { // No op } diff --git a/vector/src/main/java/im/vector/app/core/pushers/FcmHelper.kt b/vector/src/main/java/im/vector/app/core/pushers/FcmHelper.kt index 601722a036..7b2c5e3959 100644 --- a/vector/src/main/java/im/vector/app/core/pushers/FcmHelper.kt +++ b/vector/src/main/java/im/vector/app/core/pushers/FcmHelper.kt @@ -25,22 +25,23 @@ interface FcmHelper { /** * Retrieves the FCM registration token. * - * @return the FCM token or null if not received from FCM + * @return the FCM token or null if not received from FCM. */ fun getFcmToken(): String? /** - * Store FCM token to the SharedPrefs - * TODO Store in realm + * Store FCM token to the SharedPrefs. * - * @param token the token to store + * @param token the token to store. */ fun storeFcmToken(token: String?) /** - * onNewToken may not be called on application upgrade, so ensure my shared pref is set + * onNewToken may not be called on application upgrade, so ensure my shared pref is set. * - * @param activity the first launch Activity + * @param activity the first launch Activity. + * @param pushersManager the instance to register the pusher on. + * @param registerPusher whether the pusher should be registered. */ fun ensureFcmTokenIsRetrieved(activity: Activity, pushersManager: PushersManager, registerPusher: Boolean) diff --git a/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt b/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt index 872f102a0d..e724084501 100644 --- a/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt +++ b/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt @@ -34,6 +34,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder import im.vector.app.R import im.vector.app.SpaceStateHandler import im.vector.app.config.OnboardingVariant +import im.vector.app.core.debug.DebugNavigator import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.error.fatalError import im.vector.app.features.VectorFeatures @@ -51,7 +52,6 @@ import im.vector.app.features.crypto.recover.BootstrapBottomSheet import im.vector.app.features.crypto.recover.SetupMode import im.vector.app.features.crypto.verification.SupportedVerificationMethodsProvider import im.vector.app.features.crypto.verification.VerificationBottomSheet -import im.vector.app.core.debug.DebugNavigator import im.vector.app.features.devtools.RoomDevToolActivity import im.vector.app.features.home.room.detail.RoomDetailActivity import im.vector.app.features.home.room.detail.arguments.TimelineArgs @@ -616,4 +616,3 @@ class DefaultNavigator @Inject constructor( context.startActivity(this) } } - From 319ec6fbf492fb47265170331445a98c20dc9b8d Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Tue, 9 Aug 2022 11:25:55 +0100 Subject: [PATCH 10/55] removing now unused gplay resource --- vector/build.gradle | 2 -- 1 file changed, 2 deletions(-) diff --git a/vector/build.gradle b/vector/build.gradle index 0edaf5424e..1244a84bfd 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -307,7 +307,6 @@ android { isDefault = true versionName "${versionMajor}.${versionMinor}.${versionPatch}${getGplayVersionSuffix()}" - resValue "bool", "isGplay", "true" buildConfigField "String", "SHORT_FLAVOR_DESCRIPTION", "\"G\"" buildConfigField "String", "FLAVOR_DESCRIPTION", "\"GooglePlay\"" } @@ -317,7 +316,6 @@ android { versionName "${versionMajor}.${versionMinor}.${versionPatch}${getFdroidVersionSuffix()}" - resValue "bool", "isGplay", "false" buildConfigField "String", "SHORT_FLAVOR_DESCRIPTION", "\"F\"" buildConfigField "String", "FLAVOR_DESCRIPTION", "\"FDroid\"" } From d7949307a41f5cceacdb2e1e6f8190a15d9ae1cd Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Tue, 9 Aug 2022 14:01:00 +0100 Subject: [PATCH 11/55] adding changelog entry --- changelog.d/6783.misc | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/6783.misc diff --git a/changelog.d/6783.misc b/changelog.d/6783.misc new file mode 100644 index 0000000000..d1095c1203 --- /dev/null +++ b/changelog.d/6783.misc @@ -0,0 +1 @@ +Decouples the variant logic from the vector module From e81da5d8b44f21ed7843757205fdccf2542014f2 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Wed, 10 Aug 2022 09:02:04 +0100 Subject: [PATCH 12/55] generating 1.4.32 changelog --- CHANGES.md | 35 +++++++++++++++++++ changelog.d/6406.misc | 1 - changelog.d/6598.misc | 1 - changelog.d/6637.misc | 1 - changelog.d/6642.misc | 1 - changelog.d/6647.misc | 1 - changelog.d/6653.misc | 1 - changelog.d/6655.feature | 1 - changelog.d/6674.misc | 1 - changelog.d/6678.misc | 1 - changelog.d/6680.misc | 1 - changelog.d/6687.bugfix | 1 - changelog.d/6706.bugfix | 1 - changelog.d/6711.feature | 1 - changelog.d/6713.bugfix | 1 - changelog.d/6735.bugfix | 1 - changelog.d/6737.bugfix | 1 - changelog.d/6739.misc | 1 - changelog.d/6768.bugfix | 1 - changelog.d/6769.bugfix | 1 - .../android/en-US/changelogs/40104320.txt | 2 ++ 21 files changed, 37 insertions(+), 19 deletions(-) delete mode 100644 changelog.d/6406.misc delete mode 100644 changelog.d/6598.misc delete mode 100644 changelog.d/6637.misc delete mode 100644 changelog.d/6642.misc delete mode 100644 changelog.d/6647.misc delete mode 100644 changelog.d/6653.misc delete mode 100644 changelog.d/6655.feature delete mode 100644 changelog.d/6674.misc delete mode 100644 changelog.d/6678.misc delete mode 100644 changelog.d/6680.misc delete mode 100644 changelog.d/6687.bugfix delete mode 100644 changelog.d/6706.bugfix delete mode 100644 changelog.d/6711.feature delete mode 100644 changelog.d/6713.bugfix delete mode 100644 changelog.d/6735.bugfix delete mode 100644 changelog.d/6737.bugfix delete mode 100644 changelog.d/6739.misc delete mode 100644 changelog.d/6768.bugfix delete mode 100644 changelog.d/6769.bugfix create mode 100644 fastlane/metadata/android/en-US/changelogs/40104320.txt diff --git a/CHANGES.md b/CHANGES.md index 2bddbef133..829b1a0caa 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,38 @@ +Changes in Element v1.4.32 (2022-08-10) +======================================= + +Features ✨ +---------- + - [Location Share] Render fallback UI when map fails to load ([#6711](https://github.com/vector-im/element-android/issues/6711)) + +Bugfixes 🐛 +---------- + - Fix message content sometimes appearing in the log ([#6706](https://github.com/vector-im/element-android/issues/6706)) + - Disable 'Enable biometrics' option if there are not biometric authenticators enrolled. ([#6713](https://github.com/vector-im/element-android/issues/6713)) + - Fix crash when biometric key is used when coming back to foreground and KeyStore reports that the device is still locked. ([#6768](https://github.com/vector-im/element-android/issues/6768)) + - Catch all exceptions on lockscreen system key migrations. ([#6769](https://github.com/vector-im/element-android/issues/6769)) + - Fixes crash when entering non ascii characters during account creation ([#6735](https://github.com/vector-im/element-android/issues/6735)) + - Fixes onboarding login/account creation errors showing after navigation ([#6737](https://github.com/vector-im/element-android/issues/6737)) + - [Location sharing] Invisible text on map symbol ([#6687](https://github.com/vector-im/element-android/issues/6687)) + +In development 🚧 +---------------- + - Adds new app layout toolbar ([#6655](https://github.com/vector-im/element-android/issues/6655)) + +Other changes +------------- + - [Modularization] Provides abstraction to avoid direct usages of BuildConfig ([#6406](https://github.com/vector-im/element-android/issues/6406)) + - Refactors SpaceStateHandler (previously AppStateHandler) and adds unit tests for it ([#6598](https://github.com/vector-im/element-android/issues/6598)) + - Setup Danger to the project ([#6637](https://github.com/vector-im/element-android/issues/6637)) + - [Location Share] Open maximized map on tapping on live sharing notification ([#6642](https://github.com/vector-im/element-android/issues/6642)) + - [Location sharing] Align naming of components for live location feature ([#6647](https://github.com/vector-im/element-android/issues/6647)) + - [Location share] Update minimum sending period to 5 seconds for a live ([#6653](https://github.com/vector-im/element-android/issues/6653)) + - [Location sharing] - Fix the memory leaks ([#6674](https://github.com/vector-im/element-android/issues/6674)) + - [Timeline] Memory leak in audio message playback tracker ([#6678](https://github.com/vector-im/element-android/issues/6678)) + - [FTUE] Memory leak on FtueAuthSplashCarouselFragment ([#6680](https://github.com/vector-im/element-android/issues/6680)) + - Link directly to DCO docs from danger message. ([#6739](https://github.com/vector-im/element-android/issues/6739)) + + Changes in Element v1.4.31 (2022-08-01) ======================================= diff --git a/changelog.d/6406.misc b/changelog.d/6406.misc deleted file mode 100644 index 27cf3c6493..0000000000 --- a/changelog.d/6406.misc +++ /dev/null @@ -1 +0,0 @@ -[Modularization] Provides abstraction to avoids direct usages of BuildConfig diff --git a/changelog.d/6598.misc b/changelog.d/6598.misc deleted file mode 100644 index db65a30bdc..0000000000 --- a/changelog.d/6598.misc +++ /dev/null @@ -1 +0,0 @@ -Refactors SpaceStateHandler (previously AppStateHandler) and adds unit tests for it diff --git a/changelog.d/6637.misc b/changelog.d/6637.misc deleted file mode 100644 index 7fc5ffad98..0000000000 --- a/changelog.d/6637.misc +++ /dev/null @@ -1 +0,0 @@ -Setup Danger to the project diff --git a/changelog.d/6642.misc b/changelog.d/6642.misc deleted file mode 100644 index a32b20716a..0000000000 --- a/changelog.d/6642.misc +++ /dev/null @@ -1 +0,0 @@ -[Location Share] Open maximized map on tapping on live sharing notification diff --git a/changelog.d/6647.misc b/changelog.d/6647.misc deleted file mode 100644 index e183cac57a..0000000000 --- a/changelog.d/6647.misc +++ /dev/null @@ -1 +0,0 @@ -[Location sharing] Align naming of components for live location feature diff --git a/changelog.d/6653.misc b/changelog.d/6653.misc deleted file mode 100644 index 1b5be1b83f..0000000000 --- a/changelog.d/6653.misc +++ /dev/null @@ -1 +0,0 @@ -[Location share] Update minimum sending period to 5 seconds for a live diff --git a/changelog.d/6655.feature b/changelog.d/6655.feature deleted file mode 100644 index 13a4c6d572..0000000000 --- a/changelog.d/6655.feature +++ /dev/null @@ -1 +0,0 @@ -Adds new app layout toolbar (feature flagged) diff --git a/changelog.d/6674.misc b/changelog.d/6674.misc deleted file mode 100644 index 830d528e27..0000000000 --- a/changelog.d/6674.misc +++ /dev/null @@ -1 +0,0 @@ -[Location sharing] - Fix the memory leaks diff --git a/changelog.d/6678.misc b/changelog.d/6678.misc deleted file mode 100644 index a7a53257d8..0000000000 --- a/changelog.d/6678.misc +++ /dev/null @@ -1 +0,0 @@ -[Timeline] Memory leak in audio message playback tracker diff --git a/changelog.d/6680.misc b/changelog.d/6680.misc deleted file mode 100644 index f42160fbba..0000000000 --- a/changelog.d/6680.misc +++ /dev/null @@ -1 +0,0 @@ -[FTUE] Memory leak on FtueAuthSplashCarouselFragment diff --git a/changelog.d/6687.bugfix b/changelog.d/6687.bugfix deleted file mode 100644 index 9b92efdffe..0000000000 --- a/changelog.d/6687.bugfix +++ /dev/null @@ -1 +0,0 @@ -[Location sharing] Invisible text on map symbol diff --git a/changelog.d/6706.bugfix b/changelog.d/6706.bugfix deleted file mode 100644 index 51d5248374..0000000000 --- a/changelog.d/6706.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fix message content sometimes appearing in the log diff --git a/changelog.d/6711.feature b/changelog.d/6711.feature deleted file mode 100644 index cff718affd..0000000000 --- a/changelog.d/6711.feature +++ /dev/null @@ -1 +0,0 @@ -[Location Share] Render fallback UI when map fails to load diff --git a/changelog.d/6713.bugfix b/changelog.d/6713.bugfix deleted file mode 100644 index 6a9926aa13..0000000000 --- a/changelog.d/6713.bugfix +++ /dev/null @@ -1 +0,0 @@ -Disable 'Enable biometrics' option if there are not biometric authenticators enrolled. diff --git a/changelog.d/6735.bugfix b/changelog.d/6735.bugfix deleted file mode 100644 index 814bf3f47c..0000000000 --- a/changelog.d/6735.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fixes crash when entering non ascii characters during account creation diff --git a/changelog.d/6737.bugfix b/changelog.d/6737.bugfix deleted file mode 100644 index 6568e9ff31..0000000000 --- a/changelog.d/6737.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fixes onboarding login/account creation errors showing after navigation diff --git a/changelog.d/6739.misc b/changelog.d/6739.misc deleted file mode 100644 index 5e5de00831..0000000000 --- a/changelog.d/6739.misc +++ /dev/null @@ -1 +0,0 @@ -Link directly to DCO docs from danger message. diff --git a/changelog.d/6768.bugfix b/changelog.d/6768.bugfix deleted file mode 100644 index 764386132b..0000000000 --- a/changelog.d/6768.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fix crash when biometric key is used when coming back to foreground and KeyStore reports that the device is still locked. diff --git a/changelog.d/6769.bugfix b/changelog.d/6769.bugfix deleted file mode 100644 index 5d65bff449..0000000000 --- a/changelog.d/6769.bugfix +++ /dev/null @@ -1 +0,0 @@ -Catch all exceptions on lockscreen system key migrations. diff --git a/fastlane/metadata/android/en-US/changelogs/40104320.txt b/fastlane/metadata/android/en-US/changelogs/40104320.txt new file mode 100644 index 0000000000..61db61727a --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/40104320.txt @@ -0,0 +1,2 @@ +Main changes in this version: Various bug fixes and stability improvements. +Full changelog: https://github.com/vector-im/element-android/releases From fb0b38bb4936c19c45f5ed7fb67ce48ecfdb9894 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Tue, 9 Aug 2022 17:18:56 +0200 Subject: [PATCH 13/55] Adding new feature flag for new device management --- .../app/features/debug/features/DebugFeaturesStateFactory.kt | 5 +++++ .../app/features/debug/features/DebugVectorFeatures.kt | 4 ++++ .../src/main/java/im/vector/app/features/VectorFeatures.kt | 2 ++ 3 files changed, 11 insertions(+) diff --git a/vector/src/debug/java/im/vector/app/features/debug/features/DebugFeaturesStateFactory.kt b/vector/src/debug/java/im/vector/app/features/debug/features/DebugFeaturesStateFactory.kt index d7e402c4dc..c127e3aed6 100644 --- a/vector/src/debug/java/im/vector/app/features/debug/features/DebugFeaturesStateFactory.kt +++ b/vector/src/debug/java/im/vector/app/features/debug/features/DebugFeaturesStateFactory.kt @@ -90,6 +90,11 @@ class DebugFeaturesStateFactory @Inject constructor( key = DebugFeatureKeys.newAppLayoutEnabled, factory = VectorFeatures::isNewAppLayoutEnabled ), + createBooleanFeature( + label = "Enable New Device Management", + key = DebugFeatureKeys.newDeviceManagementEnabled, + factory = VectorFeatures::isNewDeviceManagementEnabled + ), ) ) } diff --git a/vector/src/debug/java/im/vector/app/features/debug/features/DebugVectorFeatures.kt b/vector/src/debug/java/im/vector/app/features/debug/features/DebugVectorFeatures.kt index 031ff11d59..003b9b8084 100644 --- a/vector/src/debug/java/im/vector/app/features/debug/features/DebugVectorFeatures.kt +++ b/vector/src/debug/java/im/vector/app/features/debug/features/DebugVectorFeatures.kt @@ -79,6 +79,9 @@ class DebugVectorFeatures( override fun isNewAppLayoutEnabled(): Boolean = read(DebugFeatureKeys.newAppLayoutEnabled) ?: vectorFeatures.isNewAppLayoutEnabled() + override fun isNewDeviceManagementEnabled(): Boolean = read(DebugFeatureKeys.newDeviceManagementEnabled) + ?: vectorFeatures.isNewDeviceManagementEnabled() + fun override(value: T?, key: Preferences.Key) = updatePreferences { if (value == null) { it.remove(key) @@ -139,4 +142,5 @@ object DebugFeatureKeys { val forceUsageOfOpusEncoder = booleanPreferencesKey("force-usage-of-opus-encoder") val startDmOnFirstMsg = booleanPreferencesKey("start-dm-on-first-msg") val newAppLayoutEnabled = booleanPreferencesKey("new-app-layout-enabled") + val newDeviceManagementEnabled = booleanPreferencesKey("new-device-management-enabled") } diff --git a/vector/src/main/java/im/vector/app/features/VectorFeatures.kt b/vector/src/main/java/im/vector/app/features/VectorFeatures.kt index 290d21879d..e60b225689 100644 --- a/vector/src/main/java/im/vector/app/features/VectorFeatures.kt +++ b/vector/src/main/java/im/vector/app/features/VectorFeatures.kt @@ -34,6 +34,7 @@ interface VectorFeatures { fun forceUsageOfOpusEncoder(): Boolean fun shouldStartDmOnFirstMessage(): Boolean fun isNewAppLayoutEnabled(): Boolean + fun isNewDeviceManagementEnabled(): Boolean } class DefaultVectorFeatures : VectorFeatures { @@ -50,4 +51,5 @@ class DefaultVectorFeatures : VectorFeatures { override fun forceUsageOfOpusEncoder(): Boolean = false override fun shouldStartDmOnFirstMessage(): Boolean = false override fun isNewAppLayoutEnabled(): Boolean = false + override fun isNewDeviceManagementEnabled(): Boolean = false } From db1d0daec077a60f57c1a2670a7d632f6bb680a5 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Wed, 10 Aug 2022 09:50:02 +0200 Subject: [PATCH 14/55] Adding a new setting entry behind feature flag --- .../vector/app/features/settings/VectorPreferences.kt | 1 + .../settings/VectorSettingsSecurityPrivacyFragment.kt | 10 ++++++++++ .../main/res/xml/vector_settings_security_privacy.xml | 7 ++++++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt index ac14bfc3c7..0134fc581b 100755 --- a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt @@ -74,6 +74,7 @@ class VectorPreferences @Inject constructor( const val SETTINGS_ENCRYPTION_IMPORT_E2E_ROOM_KEYS_PREFERENCE_KEY = "SETTINGS_ENCRYPTION_IMPORT_E2E_ROOM_KEYS_PREFERENCE_KEY" const val SETTINGS_ENCRYPTION_NEVER_SENT_TO_PREFERENCE_KEY = "SETTINGS_ENCRYPTION_NEVER_SENT_TO_PREFERENCE_KEY" const val SETTINGS_SHOW_DEVICES_LIST_PREFERENCE_KEY = "SETTINGS_SHOW_DEVICES_LIST_PREFERENCE_KEY" + const val SETTINGS_SHOW_DEVICES_V2_LIST_PREFERENCE_KEY = "SETTINGS_SHOW_DEVICES_V2_LIST_PREFERENCE_KEY" const val SETTINGS_ALLOW_INTEGRATIONS_KEY = "SETTINGS_ALLOW_INTEGRATIONS_KEY" const val SETTINGS_INTEGRATION_MANAGER_UI_URL_KEY = "SETTINGS_INTEGRATION_MANAGER_UI_URL_KEY" const val SETTINGS_SECURE_MESSAGE_RECOVERY_PREFERENCE_KEY = "SETTINGS_SECURE_MESSAGE_RECOVERY_PREFERENCE_KEY" diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsSecurityPrivacyFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsSecurityPrivacyFragment.kt index ac8a47b81e..023bb9e03f 100644 --- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsSecurityPrivacyFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsSecurityPrivacyFragment.kt @@ -50,6 +50,7 @@ import im.vector.app.core.utils.copyToClipboard import im.vector.app.core.utils.openFileSelection import im.vector.app.core.utils.toast import im.vector.app.databinding.DialogImportE2eKeysBinding +import im.vector.app.features.VectorFeatures import im.vector.app.features.analytics.AnalyticsConfig import im.vector.app.features.analytics.plan.MobileScreen import im.vector.app.features.analytics.ui.consent.AnalyticsConsentViewActions @@ -86,6 +87,7 @@ class VectorSettingsSecurityPrivacyFragment @Inject constructor( private val rawService: RawService, private val navigator: Navigator, private val analyticsConfig: AnalyticsConfig, + private val vectorFeatures: VectorFeatures, ) : VectorSettingsBaseFragment() { override var titleRes = R.string.settings_security_and_privacy @@ -135,6 +137,10 @@ class VectorSettingsSecurityPrivacyFragment @Inject constructor( findPreference(VectorPreferences.SETTINGS_SHOW_DEVICES_LIST_PREFERENCE_KEY)!! } + private val showDevicesV2ListPref by lazy { + findPreference(VectorPreferences.SETTINGS_SHOW_DEVICES_V2_LIST_PREFERENCE_KEY)!! + } + // encrypt to unverified devices private val sendToUnverifiedDevicesPref by lazy { findPreference(VectorPreferences.SETTINGS_ENCRYPTION_NEVER_SENT_TO_PREFERENCE_KEY)!! @@ -546,6 +552,10 @@ class VectorSettingsSecurityPrivacyFragment @Inject constructor( showDeviceListPref.isEnabled = devices.isNotEmpty() showDeviceListPref.summary = resources.getQuantityString(R.plurals.settings_active_sessions_count, devices.size, devices.size) + showDevicesV2ListPref.isVisible = vectorFeatures.isNewDeviceManagementEnabled() + showDevicesV2ListPref.title = showDeviceListPref.title.toString() + " (V2, WIP)" + showDevicesV2ListPref.summary = resources.getQuantityString(R.plurals.settings_active_sessions_count, devices.size, devices.size) + val userId = session.myUserId val deviceId = session.sessionParams.deviceId diff --git a/vector/src/main/res/xml/vector_settings_security_privacy.xml b/vector/src/main/res/xml/vector_settings_security_privacy.xml index d4dfed2fcf..d3493fd984 100644 --- a/vector/src/main/res/xml/vector_settings_security_privacy.xml +++ b/vector/src/main/res/xml/vector_settings_security_privacy.xml @@ -62,6 +62,11 @@ android:title="@string/settings_active_sessions_show_all" app:fragment="im.vector.app.features.settings.devices.VectorSettingsDevicesFragment" /> + + - \ No newline at end of file + From 1ebc2a9a8c0485a7d91a72a2e0d69097bc680165 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Wed, 10 Aug 2022 10:18:37 +0200 Subject: [PATCH 15/55] New empty devices list screen --- .../v2/VectorSettingsDevicesFragment.kt | 49 +++++++++++++++++++ .../res/layout/fragment_settings_devices.xml | 5 ++ vector/src/main/res/values/strings.xml | 1 + .../xml/vector_settings_security_privacy.xml | 2 +- 4 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 vector/src/main/java/im/vector/app/features/settings/devices/v2/VectorSettingsDevicesFragment.kt create mode 100644 vector/src/main/res/layout/fragment_settings_devices.xml diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/VectorSettingsDevicesFragment.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/VectorSettingsDevicesFragment.kt new file mode 100644 index 0000000000..0d5dedacc9 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/VectorSettingsDevicesFragment.kt @@ -0,0 +1,49 @@ +/* + * Copyright 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.settings.devices.v2 + +import android.content.Context +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.appcompat.app.AppCompatActivity +import dagger.hilt.android.AndroidEntryPoint +import im.vector.app.R +import im.vector.app.core.platform.VectorBaseFragment +import im.vector.app.databinding.FragmentSettingsDevicesBinding +import javax.inject.Inject + +/** + * Display the list of the user's devices and sessions. + */ +@AndroidEntryPoint +class VectorSettingsDevicesFragment @Inject constructor() : VectorBaseFragment() { + + override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentSettingsDevicesBinding { + return FragmentSettingsDevicesBinding.inflate(inflater, container, false) + } + + override fun onAttach(context: Context) { + super.onAttach(context) + initToolbar() + } + + private fun initToolbar() { + (activity as? AppCompatActivity) + ?.supportActionBar + ?.setTitle(R.string.settings_sessions_list) + } +} diff --git a/vector/src/main/res/layout/fragment_settings_devices.xml b/vector/src/main/res/layout/fragment_settings_devices.xml new file mode 100644 index 0000000000..2a77219ad0 --- /dev/null +++ b/vector/src/main/res/layout/fragment_settings_devices.xml @@ -0,0 +1,5 @@ + + diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index 9fc9756897..7c01eed715 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -2336,6 +2336,7 @@ Show All Sessions Manage Sessions Sign out of this session + Sessions Server name Server version diff --git a/vector/src/main/res/xml/vector_settings_security_privacy.xml b/vector/src/main/res/xml/vector_settings_security_privacy.xml index d3493fd984..b5b21bc017 100644 --- a/vector/src/main/res/xml/vector_settings_security_privacy.xml +++ b/vector/src/main/res/xml/vector_settings_security_privacy.xml @@ -65,7 +65,7 @@ + app:fragment="im.vector.app.features.settings.devices.v2.VectorSettingsDevicesFragment" /> From ed00685514d734afd80b833cc0f0d89f4695b9ad Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Wed, 10 Aug 2022 10:39:27 +0200 Subject: [PATCH 16/55] Adding changelog entry --- changelog.d/6798.wip | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/6798.wip diff --git a/changelog.d/6798.wip b/changelog.d/6798.wip new file mode 100644 index 0000000000..a16270666b --- /dev/null +++ b/changelog.d/6798.wip @@ -0,0 +1 @@ +[Devices management] Add a feature flag and empty screen for future new layout From b9fa4ddfc8dbdfad7afb50cba4eb8d3e08fa60b6 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Wed, 10 Aug 2022 10:53:34 +0200 Subject: [PATCH 17/55] Renaming v2 setting key --- .../vector/app/features/settings/VectorPreferences.kt | 2 +- .../settings/VectorSettingsSecurityPrivacyFragment.kt | 10 +++++----- .../main/res/xml/vector_settings_security_privacy.xml | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt index 0134fc581b..857d2ce7fb 100755 --- a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt @@ -74,7 +74,7 @@ class VectorPreferences @Inject constructor( const val SETTINGS_ENCRYPTION_IMPORT_E2E_ROOM_KEYS_PREFERENCE_KEY = "SETTINGS_ENCRYPTION_IMPORT_E2E_ROOM_KEYS_PREFERENCE_KEY" const val SETTINGS_ENCRYPTION_NEVER_SENT_TO_PREFERENCE_KEY = "SETTINGS_ENCRYPTION_NEVER_SENT_TO_PREFERENCE_KEY" const val SETTINGS_SHOW_DEVICES_LIST_PREFERENCE_KEY = "SETTINGS_SHOW_DEVICES_LIST_PREFERENCE_KEY" - const val SETTINGS_SHOW_DEVICES_V2_LIST_PREFERENCE_KEY = "SETTINGS_SHOW_DEVICES_V2_LIST_PREFERENCE_KEY" + const val SETTINGS_SHOW_DEVICES_LIST_V2_PREFERENCE_KEY = "SETTINGS_SHOW_DEVICES_LIST_V2_PREFERENCE_KEY" const val SETTINGS_ALLOW_INTEGRATIONS_KEY = "SETTINGS_ALLOW_INTEGRATIONS_KEY" const val SETTINGS_INTEGRATION_MANAGER_UI_URL_KEY = "SETTINGS_INTEGRATION_MANAGER_UI_URL_KEY" const val SETTINGS_SECURE_MESSAGE_RECOVERY_PREFERENCE_KEY = "SETTINGS_SECURE_MESSAGE_RECOVERY_PREFERENCE_KEY" diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsSecurityPrivacyFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsSecurityPrivacyFragment.kt index 023bb9e03f..24ad4e55ab 100644 --- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsSecurityPrivacyFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsSecurityPrivacyFragment.kt @@ -137,8 +137,8 @@ class VectorSettingsSecurityPrivacyFragment @Inject constructor( findPreference(VectorPreferences.SETTINGS_SHOW_DEVICES_LIST_PREFERENCE_KEY)!! } - private val showDevicesV2ListPref by lazy { - findPreference(VectorPreferences.SETTINGS_SHOW_DEVICES_V2_LIST_PREFERENCE_KEY)!! + private val showDevicesListV2Pref by lazy { + findPreference(VectorPreferences.SETTINGS_SHOW_DEVICES_LIST_V2_PREFERENCE_KEY)!! } // encrypt to unverified devices @@ -552,9 +552,9 @@ class VectorSettingsSecurityPrivacyFragment @Inject constructor( showDeviceListPref.isEnabled = devices.isNotEmpty() showDeviceListPref.summary = resources.getQuantityString(R.plurals.settings_active_sessions_count, devices.size, devices.size) - showDevicesV2ListPref.isVisible = vectorFeatures.isNewDeviceManagementEnabled() - showDevicesV2ListPref.title = showDeviceListPref.title.toString() + " (V2, WIP)" - showDevicesV2ListPref.summary = resources.getQuantityString(R.plurals.settings_active_sessions_count, devices.size, devices.size) + showDevicesListV2Pref.isVisible = vectorFeatures.isNewDeviceManagementEnabled() + showDevicesListV2Pref.title = showDeviceListPref.title.toString() + " (V2, WIP)" + showDevicesListV2Pref.summary = resources.getQuantityString(R.plurals.settings_active_sessions_count, devices.size, devices.size) val userId = session.myUserId val deviceId = session.sessionParams.deviceId diff --git a/vector/src/main/res/xml/vector_settings_security_privacy.xml b/vector/src/main/res/xml/vector_settings_security_privacy.xml index b5b21bc017..c246a40f71 100644 --- a/vector/src/main/res/xml/vector_settings_security_privacy.xml +++ b/vector/src/main/res/xml/vector_settings_security_privacy.xml @@ -63,7 +63,7 @@ app:fragment="im.vector.app.features.settings.devices.VectorSettingsDevicesFragment" /> From defd848363c35b9394f3cf503bf17a01d173cd7d Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Wed, 10 Aug 2022 12:30:38 +0100 Subject: [PATCH 18/55] updating version for next release cycle --- matrix-sdk-android/build.gradle | 2 +- vector/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle index 45a962f12c..e6b526585b 100644 --- a/matrix-sdk-android/build.gradle +++ b/matrix-sdk-android/build.gradle @@ -60,7 +60,7 @@ android { // that the app's state is completely cleared between tests. testInstrumentationRunnerArguments clearPackageData: 'true' - buildConfigField "String", "SDK_VERSION", "\"1.4.32\"" + buildConfigField "String", "SDK_VERSION", "\"1.4.34\"" buildConfigField "String", "GIT_SDK_REVISION", "\"${gitRevision()}\"" buildConfigField "String", "GIT_SDK_REVISION_UNIX_DATE", "\"${gitRevisionUnixDate()}\"" diff --git a/vector/build.gradle b/vector/build.gradle index e5bd835a8f..cb7ee67a6a 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -37,7 +37,7 @@ ext.versionMinor = 4 // Note: even values are reserved for regular release, odd values for hotfix release. // When creating a hotfix, you should decrease the value, since the current value // is the value for the next regular release. -ext.versionPatch = 32 +ext.versionPatch = 34 static def getGitTimestamp() { def cmd = 'git show -s --format=%ct' From aecf460c96b3a56603c6410ccd6f522c521ae998 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Wed, 10 Aug 2022 14:00:36 +0200 Subject: [PATCH 19/55] Improve tests for lockscreen (#6796) * Improve tests * Address review comments. * Refactor pin code tests and code to improve testability. * Fix lint issues --- .../pin/lockscreen/ui/LockScreenViewModel.kt | 19 +- .../pin/lockscreen/ui/LockScreenViewState.kt | 4 +- .../fragment/LockScreenViewModelTests.kt | 218 +++++++++++------- .../java/im/vector/app/test/Extensions.kt | 5 + .../im/vector/app/test/FlowTestObserver.kt | 10 +- 5 files changed, 155 insertions(+), 101 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/pin/lockscreen/ui/LockScreenViewModel.kt b/vector/src/main/java/im/vector/app/features/pin/lockscreen/ui/LockScreenViewModel.kt index d40f67ea35..33ea590f1d 100644 --- a/vector/src/main/java/im/vector/app/features/pin/lockscreen/ui/LockScreenViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/pin/lockscreen/ui/LockScreenViewModel.kt @@ -64,8 +64,6 @@ class LockScreenViewModel @AssistedInject constructor( private val biometricHelper = biometricHelperFactory.create(initialState.lockScreenConfiguration) - private var firstEnteredCode: String? = null - // BiometricPrompt will automatically disable system auth after too many failed auth attempts private var isSystemAuthTemporarilyDisabledByBiometricPrompt = false @@ -108,18 +106,17 @@ class LockScreenViewModel @AssistedInject constructor( val state = awaitState() when (state.lockScreenConfiguration.mode) { LockScreenMode.CREATE -> { - if (firstEnteredCode == null && state.lockScreenConfiguration.needsNewCodeValidation) { - firstEnteredCode = code - _viewEvents.post(LockScreenViewEvent.ClearPinCode(false)) - emit(PinCodeState.FirstCodeEntered) + val enteredPinCode = (state.pinCodeState as? PinCodeState.FirstCodeEntered)?.pinCode + if (enteredPinCode == null && state.lockScreenConfiguration.needsNewCodeValidation) { + _viewEvents.post(LockScreenViewEvent.ClearPinCode(confirmationFailed = false)) + emit(PinCodeState.FirstCodeEntered(code)) } else { - if (!state.lockScreenConfiguration.needsNewCodeValidation || code == firstEnteredCode) { + if (!state.lockScreenConfiguration.needsNewCodeValidation || code == enteredPinCode) { pinCodeHelper.createPinCode(code) _viewEvents.post(LockScreenViewEvent.CodeCreationComplete) emit(null) } else { - firstEnteredCode = null - _viewEvents.post(LockScreenViewEvent.ClearPinCode(true)) + _viewEvents.post(LockScreenViewEvent.ClearPinCode(confirmationFailed = true)) emit(PinCodeState.Idle) } } @@ -137,7 +134,9 @@ class LockScreenViewModel @AssistedInject constructor( }.catch { error -> _viewEvents.post(LockScreenViewEvent.AuthError(AuthMethod.PIN_CODE, error)) }.onEach { newPinState -> - newPinState?.let { setState { copy(pinCodeState = it) } } + if (newPinState != null) { + setState { copy(pinCodeState = newPinState) } + } }.launchIn(viewModelScope) @SuppressLint("NewApi") diff --git a/vector/src/main/java/im/vector/app/features/pin/lockscreen/ui/LockScreenViewState.kt b/vector/src/main/java/im/vector/app/features/pin/lockscreen/ui/LockScreenViewState.kt index f689e1faf1..c6c6359f4f 100644 --- a/vector/src/main/java/im/vector/app/features/pin/lockscreen/ui/LockScreenViewState.kt +++ b/vector/src/main/java/im/vector/app/features/pin/lockscreen/ui/LockScreenViewState.kt @@ -27,11 +27,11 @@ data class LockScreenViewState( val isBiometricKeyInvalidated: Boolean, ) : MavericksState { constructor(lockScreenConfiguration: LockScreenConfiguration) : this( - lockScreenConfiguration, false, false, PinCodeState.Idle, false + lockScreenConfiguration, false, false, PinCodeState.Idle, false, ) } sealed class PinCodeState { object Idle : PinCodeState() - object FirstCodeEntered : PinCodeState() + data class FirstCodeEntered(val pinCode: String) : PinCodeState() } diff --git a/vector/src/test/java/im/vector/app/features/pin/lockscreen/fragment/LockScreenViewModelTests.kt b/vector/src/test/java/im/vector/app/features/pin/lockscreen/fragment/LockScreenViewModelTests.kt index 18dfdf9145..6037d9933e 100644 --- a/vector/src/test/java/im/vector/app/features/pin/lockscreen/fragment/LockScreenViewModelTests.kt +++ b/vector/src/test/java/im/vector/app/features/pin/lockscreen/fragment/LockScreenViewModelTests.kt @@ -19,9 +19,11 @@ package im.vector.app.features.pin.lockscreen.fragment import android.app.KeyguardManager import android.os.Build import android.security.keystore.KeyPermanentlyInvalidatedException +import androidx.biometric.BiometricPrompt import androidx.fragment.app.FragmentActivity import com.airbnb.mvrx.test.MvRxTestRule import com.airbnb.mvrx.withState +import im.vector.app.features.pin.lockscreen.biometrics.BiometricAuthError import im.vector.app.features.pin.lockscreen.biometrics.BiometricHelper import im.vector.app.features.pin.lockscreen.configuration.LockScreenConfiguration import im.vector.app.features.pin.lockscreen.configuration.LockScreenMode @@ -42,10 +44,8 @@ import io.mockk.every import io.mockk.mockk import io.mockk.verify import kotlinx.coroutines.flow.flowOf -import kotlinx.coroutines.test.advanceUntilIdle import kotlinx.coroutines.test.runTest -import org.amshove.kluent.shouldBeEqualTo -import org.amshove.kluent.shouldBeFalse +import org.amshove.kluent.shouldBeTrue import org.amshove.kluent.shouldNotBeEqualTo import org.junit.Before import org.junit.Rule @@ -76,138 +76,141 @@ class LockScreenViewModelTests { @Test fun `init migrates old keys to new ones if needed`() { + // given val initialState = createViewState() + // when LockScreenViewModel(initialState, pinCodeHelper, biometricHelperFactory, keysMigrator, versionProvider, keyguardManager) - + // then coVerify { keysMigrator.migrateIfNeeded() } } @Test fun `init updates the initial state with biometric info`() = runTest { + // given every { biometricHelper.isSystemAuthEnabledAndValid } returns true val initialState = createViewState() + // when val viewModel = LockScreenViewModel(initialState, pinCodeHelper, biometricHelperFactory, keysMigrator, versionProvider, keyguardManager) - advanceUntilIdle() - val newState = viewModel.awaitState() + // then + val newState = viewModel.awaitState() // Can't use viewModel.test() here since we want to record events emitted on init newState shouldNotBeEqualTo initialState } @Test fun `Updating the initial state with biometric info waits until device is unlocked on Android 12+`() = runTest { + // given val initialState = createViewState() versionProvider.value = Build.VERSION_CODES.S + // when LockScreenViewModel(initialState, pinCodeHelper, biometricHelperFactory, keysMigrator, versionProvider, keyguardManager) - advanceUntilIdle() + // then verify { keyguardManager.isDeviceLocked } } @Test fun `when ViewModel is instantiated initialState is updated with biometric info`() { + // given + givenShowBiometricPromptAutomatically() val initialState = createViewState() - // This should set canUseBiometricAuth to true - every { biometricHelper.isSystemAuthEnabledAndValid } returns true + // when val viewModel = LockScreenViewModel(initialState, pinCodeHelper, biometricHelperFactory, keysMigrator, versionProvider, keyguardManager) - val newState = withState(viewModel) { it } - initialState shouldNotBeEqualTo newState + // then + withState(viewModel) { newState -> + initialState shouldNotBeEqualTo newState + } } @Test - fun `when onPinCodeEntered is called in VERIFY mode, the code is verified and the result is emitted as a ViewEvent`() = runTest { + fun `when onPinCodeEntered is called in VERIFY mode and verification is successful, code is verified and result is emitted as a ViewEvent`() = runTest { + // given val initialState = createViewState() val viewModel = LockScreenViewModel(initialState, pinCodeHelper, biometricHelperFactory, keysMigrator, versionProvider, keyguardManager) coEvery { pinCodeHelper.verifyPinCode(any()) } returns true - - val events = viewModel.test().viewEvents - events.assertNoValues() - - val stateBefore = viewModel.awaitState() - + val test = viewModel.test() + // when viewModel.handle(LockScreenAction.PinCodeEntered("1234")) + // then coVerify { pinCodeHelper.verifyPinCode(any()) } - events.assertValues(LockScreenViewEvent.AuthSuccessful(AuthMethod.PIN_CODE)) + test.assertEvents(LockScreenViewEvent.AuthSuccessful(AuthMethod.PIN_CODE)) + test.assertStates(initialState) + } + @Test + fun `when onPinCodeEntered is called in VERIFY mode and verification fails, the error result is emitted as a ViewEvent`() = runTest { + // given + val initialState = createViewState() + val viewModel = LockScreenViewModel(initialState, pinCodeHelper, biometricHelperFactory, keysMigrator, versionProvider, keyguardManager) coEvery { pinCodeHelper.verifyPinCode(any()) } returns false + val test = viewModel.test() + // when viewModel.handle(LockScreenAction.PinCodeEntered("1234")) - events.assertValues(LockScreenViewEvent.AuthSuccessful(AuthMethod.PIN_CODE), LockScreenViewEvent.AuthFailure(AuthMethod.PIN_CODE)) - - val stateAfter = viewModel.awaitState() - stateBefore shouldBeEqualTo stateAfter + // then + coVerify { pinCodeHelper.verifyPinCode(any()) } + test.assertEvents(LockScreenViewEvent.AuthFailure(AuthMethod.PIN_CODE)) + test.assertStates(initialState) } @Test fun `when onPinCodeEntered is called in CREATE mode with no confirmation needed it creates the pin code`() = runTest { + // given val configuration = createDefaultConfiguration(mode = LockScreenMode.CREATE, needsNewCodeValidation = false) val initialState = createViewState(lockScreenConfiguration = configuration) val viewModel = LockScreenViewModel(initialState, pinCodeHelper, biometricHelperFactory, keysMigrator, versionProvider, keyguardManager) - - val events = viewModel.test().viewEvents - events.assertNoValues() - + val test = viewModel.test() + // when viewModel.handle(LockScreenAction.PinCodeEntered("1234")) + // then coVerify { pinCodeHelper.createPinCode(any()) } - - events.assertValues(LockScreenViewEvent.CodeCreationComplete) + test.assertEvents(LockScreenViewEvent.CodeCreationComplete) } @Test fun `when onPinCodeEntered is called twice in CREATE mode with confirmation needed it verifies and creates the pin code`() = runTest { + // given + val pinCode = "1234" val configuration = createDefaultConfiguration(mode = LockScreenMode.CREATE, needsNewCodeValidation = true) - val initialState = createViewState(lockScreenConfiguration = configuration) + val initialState = createViewState(lockScreenConfiguration = configuration, pinCodeState = PinCodeState.FirstCodeEntered(pinCode)) val viewModel = LockScreenViewModel(initialState, pinCodeHelper, biometricHelperFactory, keysMigrator, versionProvider, keyguardManager) - - val events = viewModel.test().viewEvents - events.assertNoValues() - - viewModel.handle(LockScreenAction.PinCodeEntered("1234")) - - events.assertValues(LockScreenViewEvent.ClearPinCode(false)) - val pinCodeState = viewModel.awaitState().pinCodeState - pinCodeState shouldBeEqualTo PinCodeState.FirstCodeEntered - - viewModel.handle(LockScreenAction.PinCodeEntered("1234")) - events.assertValues(LockScreenViewEvent.ClearPinCode(false), LockScreenViewEvent.CodeCreationComplete) + val test = viewModel.test() + // when + viewModel.handle(LockScreenAction.PinCodeEntered(pinCode)) + // then + test.assertEvents(LockScreenViewEvent.CodeCreationComplete) + .assertLatestState { (it.pinCodeState as? PinCodeState.FirstCodeEntered)?.pinCode == pinCode } } @Test fun `when onPinCodeEntered is called in CREATE mode with incorrect confirmation it clears the pin code`() = runTest { + // given val configuration = createDefaultConfiguration(mode = LockScreenMode.CREATE, needsNewCodeValidation = true) - val initialState = createViewState(lockScreenConfiguration = configuration) + val initialState = createViewState(lockScreenConfiguration = configuration, pinCodeState = PinCodeState.FirstCodeEntered("1234")) val viewModel = LockScreenViewModel(initialState, pinCodeHelper, biometricHelperFactory, keysMigrator, versionProvider, keyguardManager) - - val events = viewModel.test().viewEvents - events.assertNoValues() - - viewModel.handle(LockScreenAction.PinCodeEntered("1234")) - - events.assertValues(LockScreenViewEvent.ClearPinCode(false)) - val pinCodeState = viewModel.awaitState().pinCodeState - pinCodeState shouldBeEqualTo PinCodeState.FirstCodeEntered - + val test = viewModel.test() + // when viewModel.handle(LockScreenAction.PinCodeEntered("4321")) - events.assertValues(LockScreenViewEvent.ClearPinCode(false), LockScreenViewEvent.ClearPinCode(true)) - val newPinCodeState = viewModel.awaitState().pinCodeState - newPinCodeState shouldBeEqualTo PinCodeState.Idle + // then + test.assertEvents(LockScreenViewEvent.ClearPinCode(true)) + .assertLatestState(initialState.copy(pinCodeState = PinCodeState.Idle)) } @Test fun `onPinCodeEntered handles exceptions`() = runTest { + // given val initialState = createViewState() val viewModel = LockScreenViewModel(initialState, pinCodeHelper, biometricHelperFactory, keysMigrator, versionProvider, keyguardManager) val exception = IllegalStateException("Something went wrong") coEvery { pinCodeHelper.verifyPinCode(any()) } throws exception - - val events = viewModel.test().viewEvents - events.assertNoValues() - + val test = viewModel.test() + // when viewModel.handle(LockScreenAction.PinCodeEntered("1234")) - - events.assertValues(LockScreenViewEvent.AuthError(AuthMethod.PIN_CODE, exception)) + // then + test.assertEvents(LockScreenViewEvent.AuthError(AuthMethod.PIN_CODE, exception)) } @Test fun `when showBiometricPrompt catches a KeyPermanentlyInvalidatedException it disables biometric authentication`() = runTest { + // given versionProvider.value = Build.VERSION_CODES.M - every { biometricHelper.isSystemKeyValid } returns false val exception = KeyPermanentlyInvalidatedException() coEvery { biometricHelper.authenticate(any()) } throws exception @@ -218,49 +221,81 @@ class LockScreenViewModelTests { lockScreenConfiguration = configuration ) val viewModel = LockScreenViewModel(initialState, pinCodeHelper, biometricHelperFactory, keysMigrator, versionProvider, keyguardManager) - - val events = viewModel.test().viewEvents - events.assertNoValues() - + val test = viewModel.test() + // when viewModel.handle(LockScreenAction.ShowBiometricPrompt(mockk())) - - events.assertValues(LockScreenViewEvent.ShowBiometricKeyInvalidatedMessage) + // then + test.assertEvents(LockScreenViewEvent.ShowBiometricKeyInvalidatedMessage) + // Biometric key is invalidated so biometric auth is disabled + .assertLatestState { !it.canUseBiometricAuth } verify { biometricHelper.disableAuthentication() } - - // System key was deleted, biometric auth should be disabled - every { biometricHelper.isSystemAuthEnabledAndValid } returns false - val newState = viewModel.awaitState() - newState.canUseBiometricAuth.shouldBeFalse() } @Test fun `when showBiometricPrompt receives an event it propagates it as a ViewEvent`() = runTest { + // given val viewModel = LockScreenViewModel(createViewState(), pinCodeHelper, biometricHelperFactory, keysMigrator, versionProvider, keyguardManager) coEvery { biometricHelper.authenticate(any()) } returns flowOf(false, true) - - val events = viewModel.test().viewEvents - events.assertNoValues() - + val test = viewModel.test() + // when viewModel.handle(LockScreenAction.ShowBiometricPrompt(mockk())) - - events.assertValues(LockScreenViewEvent.AuthFailure(AuthMethod.BIOMETRICS), LockScreenViewEvent.AuthSuccessful(AuthMethod.BIOMETRICS)) + // then + test.assertEvents(LockScreenViewEvent.AuthFailure(AuthMethod.BIOMETRICS), LockScreenViewEvent.AuthSuccessful(AuthMethod.BIOMETRICS)) } @Test fun `showBiometricPrompt handles exceptions`() = runTest { + // given val viewModel = LockScreenViewModel(createViewState(), pinCodeHelper, biometricHelperFactory, keysMigrator, versionProvider, keyguardManager) val exception = IllegalStateException("Something went wrong") coEvery { biometricHelper.authenticate(any()) } throws exception - - val events = viewModel.test().viewEvents - events.assertNoValues() - + val test = viewModel.test() + // when viewModel.handle(LockScreenAction.ShowBiometricPrompt(mockk())) - - events.assertValues(LockScreenViewEvent.AuthError(AuthMethod.BIOMETRICS, exception)) + // then + test.assertEvents(LockScreenViewEvent.AuthError(AuthMethod.BIOMETRICS, exception)) } - private fun createViewState( + @Test + fun `when showBiometricPrompt handles isAuthDisabledError, canUseBiometricAuth becomes false`() = runTest { + // given + val viewModel = LockScreenViewModel(createViewState(), pinCodeHelper, biometricHelperFactory, keysMigrator, versionProvider, keyguardManager) + val exception = BiometricAuthError(BiometricPrompt.ERROR_LOCKOUT_PERMANENT, "Permanent lockout") + coEvery { biometricHelper.authenticate(any()) } throws exception + val test = viewModel.test() + // when + viewModel.handle(LockScreenAction.ShowBiometricPrompt(mockk())) + // then + exception.isAuthDisabledError.shouldBeTrue() + test.assertEvents(LockScreenViewEvent.AuthError(AuthMethod.BIOMETRICS, exception)) + .assertLatestState { !it.canUseBiometricAuth } + } + + @Test + fun `when OnUIReady action is received and showBiometricPromptAutomatically is true it shows prompt`() = runTest { + // given + givenShowBiometricPromptAutomatically() + val viewModel = LockScreenViewModel(createViewState(), pinCodeHelper, biometricHelperFactory, keysMigrator, versionProvider, keyguardManager) + val test = viewModel.test() + // when + viewModel.handle(LockScreenAction.OnUIReady) + // then + test.assertEvents(LockScreenViewEvent.ShowBiometricPromptAutomatically) + } + + @Test + fun `when OnUIReady action is received and isBiometricKeyInvalidated is true it shows prompt`() = runTest { + // given + givenBiometricKeyIsInvalidated() + val viewModel = LockScreenViewModel(createViewState(), pinCodeHelper, biometricHelperFactory, keysMigrator, versionProvider, keyguardManager) + val test = viewModel.test() + // when + viewModel.handle(LockScreenAction.OnUIReady) + // then + test.assertEvents(LockScreenViewEvent.ShowBiometricKeyInvalidatedMessage) + } + + private fun createViewState( lockScreenConfiguration: LockScreenConfiguration = createDefaultConfiguration(), canUseBiometricAuth: Boolean = false, showBiometricPromptAutomatically: Boolean = false, @@ -286,4 +321,13 @@ class LockScreenViewModelTests { isDeviceCredentialUnlockEnabled, needsNewCodeValidation ).let(otherChanges) + + private fun givenBiometricKeyIsInvalidated() { + every { biometricHelper.hasSystemKey } returns true + every { biometricHelper.isSystemKeyValid } returns false + } + + private fun givenShowBiometricPromptAutomatically() { + every { biometricHelper.isSystemAuthEnabledAndValid } returns true + } } diff --git a/vector/src/test/java/im/vector/app/test/Extensions.kt b/vector/src/test/java/im/vector/app/test/Extensions.kt index 5ac17cc5ff..2fbab3b71b 100644 --- a/vector/src/test/java/im/vector/app/test/Extensions.kt +++ b/vector/src/test/java/im/vector/app/test/Extensions.kt @@ -91,6 +91,11 @@ class ViewModelTest( return this } + fun assertLatestState(predicate: (S) -> Boolean): ViewModelTest { + states.assertLatestValue(predicate) + return this + } + fun finish() { states.finish() viewEvents.finish() diff --git a/vector/src/test/java/im/vector/app/test/FlowTestObserver.kt b/vector/src/test/java/im/vector/app/test/FlowTestObserver.kt index db828be232..ce8d27cd2a 100644 --- a/vector/src/test/java/im/vector/app/test/FlowTestObserver.kt +++ b/vector/src/test/java/im/vector/app/test/FlowTestObserver.kt @@ -47,8 +47,14 @@ class FlowTestObserver( return this } - fun assertLatestValue(value: T) { - assertTrue(values.last() == value) + fun assertLatestValue(predicate: (T) -> Boolean): FlowTestObserver { + assertTrue(predicate(values.last())) + return this + } + + fun assertLatestValue(value: T): FlowTestObserver { + assertEquals(value, values.last()) + return this } fun assertValues(values: List): FlowTestObserver { From 31a350eea70ede920002e310c2506a14e5648da4 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Wed, 27 Jul 2022 16:36:16 +0200 Subject: [PATCH 20/55] Enabling leakcanary on debug builds --- dependencies_groups.gradle | 2 ++ vector/build.gradle | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/dependencies_groups.gradle b/dependencies_groups.gradle index f60a77a92d..1c0135ae0f 100644 --- a/dependencies_groups.gradle +++ b/dependencies_groups.gradle @@ -106,7 +106,9 @@ ext.groups = [ 'com.pinterest.ktlint', 'com.posthog.android', 'com.squareup', + 'com.squareup.curtains', 'com.squareup.duktape', + 'com.squareup.leakcanary', 'com.squareup.moshi', 'com.squareup.okhttp3', 'com.squareup.okio', diff --git a/vector/build.gradle b/vector/build.gradle index 1244a84bfd..ee08ad7ae5 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -573,7 +573,7 @@ dependencies { debugImplementation "com.kgurgul.flipper:flipper-realm-android:2.2.0" // Activate when you want to check for leaks, from time to time. - //debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.3' + debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.9.1' androidTestImplementation libs.androidx.testCore androidTestImplementation libs.androidx.testRunner From 36c69a46fdb9d3f9880b3890b779125d045eca04 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Mon, 8 Aug 2022 17:52:58 +0200 Subject: [PATCH 21/55] Adding way to enable leak canary at runtime --- .../vector/app/leakcanary/LeakCanaryProxy.kt | 26 ++++++++++++++++++ .../java/im/vector/app/VectorApplication.kt | 9 +++++++ .../im/vector/app/core/di/FragmentModule.kt | 6 +++++ .../features/settings/VectorPreferences.kt | 6 +++++ .../VectorSettingsAdvancedSettingsFragment.kt | 19 ++++++++++++- vector/src/main/res/values/strings.xml | 3 +++ .../xml/vector_settings_advanced_settings.xml | 9 ++++++- .../vector/app/leakcanary/LeakCanaryProxy.kt | 27 +++++++++++++++++++ 8 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 vector/src/debug/java/im/vector/app/leakcanary/LeakCanaryProxy.kt create mode 100644 vector/src/release/java/im/vector/app/leakcanary/LeakCanaryProxy.kt diff --git a/vector/src/debug/java/im/vector/app/leakcanary/LeakCanaryProxy.kt b/vector/src/debug/java/im/vector/app/leakcanary/LeakCanaryProxy.kt new file mode 100644 index 0000000000..3154c2c04b --- /dev/null +++ b/vector/src/debug/java/im/vector/app/leakcanary/LeakCanaryProxy.kt @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.leakcanary + +import leakcanary.LeakCanary +import javax.inject.Inject + +class LeakCanaryProxy @Inject constructor() { + fun enable(enable: Boolean) { + LeakCanary.config = LeakCanary.config.copy(dumpHeap = enable) + } +} diff --git a/vector/src/main/java/im/vector/app/VectorApplication.kt b/vector/src/main/java/im/vector/app/VectorApplication.kt index 53222ab962..bbff8f35c8 100644 --- a/vector/src/main/java/im/vector/app/VectorApplication.kt +++ b/vector/src/main/java/im/vector/app/VectorApplication.kt @@ -61,6 +61,8 @@ import im.vector.app.features.settings.VectorLocale import im.vector.app.features.settings.VectorPreferences import im.vector.app.features.themes.ThemeUtils import im.vector.app.features.version.VersionProvider +import im.vector.app.leakcanary.LeakCanaryProxy +import im.vector.app.push.fcm.FcmHelper import org.jitsi.meet.sdk.log.JitsiMeetDefaultLogHandler import org.matrix.android.sdk.api.Matrix import org.matrix.android.sdk.api.auth.AuthenticationService @@ -102,6 +104,7 @@ class VectorApplication : @Inject lateinit var matrix: Matrix @Inject lateinit var fcmHelper: FcmHelper @Inject lateinit var buildMeta: BuildMeta + @Inject lateinit var leakCanaryProxy: LeakCanaryProxy // font thread handler private var fontThreadHandler: Handler? = null @@ -196,6 +199,8 @@ class VectorApplication : // Initialize Mapbox before inflating mapViews Mapbox.getInstance(this) + + initMemoryLeakAnalysis() } private fun enableStrictModeIfNeeded() { @@ -251,4 +256,8 @@ class VectorApplication : handlerThread.start() return Handler(handlerThread.looper) } + + private fun initMemoryLeakAnalysis() { + leakCanaryProxy.enable(vectorPreferences.isMemoryLeakAnalysisEnabled()) + } } diff --git a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt index e86b350534..36b1d994c1 100644 --- a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt +++ b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt @@ -150,6 +150,7 @@ import im.vector.app.features.roomprofile.settings.joinrule.advanced.RoomJoinRul import im.vector.app.features.roomprofile.uploads.RoomUploadsFragment import im.vector.app.features.roomprofile.uploads.files.RoomUploadsFilesFragment import im.vector.app.features.roomprofile.uploads.media.RoomUploadsMediaFragment +import im.vector.app.features.settings.VectorSettingsAdvancedSettingsFragment import im.vector.app.features.settings.VectorSettingsGeneralFragment import im.vector.app.features.settings.VectorSettingsHelpAboutFragment import im.vector.app.features.settings.VectorSettingsLabsFragment @@ -624,6 +625,11 @@ interface FragmentModule { @FragmentKey(VectorSettingsSecurityPrivacyFragment::class) fun bindVectorSettingsSecurityPrivacyFragment(fragment: VectorSettingsSecurityPrivacyFragment): Fragment + @Binds + @IntoMap + @FragmentKey(VectorSettingsAdvancedSettingsFragment::class) + fun bindVectorSettingsAdvancedSettingsFragment(fragment: VectorSettingsAdvancedSettingsFragment): Fragment + @Binds @IntoMap @FragmentKey(VectorSettingsHelpAboutFragment::class) diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt index ac14bfc3c7..287b2c64ee 100755 --- a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt @@ -168,6 +168,7 @@ class VectorPreferences @Inject constructor( private const val SETTINGS_LABS_ENABLE_SWIPE_TO_REPLY = "SETTINGS_LABS_ENABLE_SWIPE_TO_REPLY" private const val SETTINGS_DEVELOPER_MODE_FAIL_FAST_PREFERENCE_KEY = "SETTINGS_DEVELOPER_MODE_FAIL_FAST_PREFERENCE_KEY" private const val SETTINGS_DEVELOPER_MODE_SHOW_INFO_ON_SCREEN_KEY = "SETTINGS_DEVELOPER_MODE_SHOW_INFO_ON_SCREEN_KEY" + const val SETTINGS_ENABLE_MEMORY_LEAK_ANALYSIS_KEY = "SETTINGS_ENABLE_MEMORY_LEAK_ANALYSIS_KEY" const val SETTINGS_LABS_MSC3061_SHARE_KEYS_HISTORY = "SETTINGS_LABS_MSC3061_SHARE_KEYS_HISTORY" @@ -268,6 +269,7 @@ class VectorPreferences @Inject constructor( SETTINGS_LABS_SHOW_HIDDEN_EVENTS_PREFERENCE_KEY, SETTINGS_LABS_ALLOW_EXTENDED_LOGS, SETTINGS_DEVELOPER_MODE_FAIL_FAST_PREFERENCE_KEY, + SETTINGS_ENABLE_MEMORY_LEAK_ANALYSIS_KEY, SETTINGS_USE_RAGE_SHAKE_KEY, SETTINGS_SECURITY_USE_FLAG_SECURE, @@ -368,6 +370,10 @@ class VectorPreferences @Inject constructor( return buildMeta.isDebug || (developerMode() && defaultPrefs.getBoolean(SETTINGS_DEVELOPER_MODE_FAIL_FAST_PREFERENCE_KEY, false)) } + fun isMemoryLeakAnalysisEnabled(): Boolean { + return buildMeta.isDebug && developerMode() && defaultPrefs.getBoolean(SETTINGS_ENABLE_MEMORY_LEAK_ANALYSIS_KEY, false) + } + fun didAskUserToEnableSessionPush(): Boolean { return defaultPrefs.getBoolean(DID_ASK_TO_ENABLE_SESSION_PUSH, false) } diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsAdvancedSettingsFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsAdvancedSettingsFragment.kt index b616ce1e1f..1bb7718390 100644 --- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsAdvancedSettingsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsAdvancedSettingsFragment.kt @@ -19,14 +19,19 @@ package im.vector.app.features.settings import android.os.Bundle import androidx.preference.Preference import androidx.preference.SeekBarPreference +import im.vector.app.BuildConfig import im.vector.app.R import im.vector.app.core.platform.VectorBaseActivity import im.vector.app.core.preference.VectorPreferenceCategory import im.vector.app.core.preference.VectorSwitchPreference import im.vector.app.features.analytics.plan.MobileScreen import im.vector.app.features.rageshake.RageShake +import im.vector.app.leakcanary.LeakCanaryProxy +import javax.inject.Inject -class VectorSettingsAdvancedSettingsFragment : VectorSettingsBaseFragment() { +class VectorSettingsAdvancedSettingsFragment @Inject constructor( + private val leakCanaryProxy: LeakCanaryProxy, +) : VectorSettingsBaseFragment() { override var titleRes = R.string.settings_advanced_settings override val preferenceXmlRes = R.xml.vector_settings_advanced_settings @@ -82,5 +87,17 @@ class VectorSettingsAdvancedSettingsFragment : VectorSettingsBaseFragment() { } else { findPreference("SETTINGS_RAGE_SHAKE_CATEGORY_KEY")!!.isVisible = false } + + bindMemoryLeakSetting() + } + + private fun bindMemoryLeakSetting() { + findPreference(VectorPreferences.SETTINGS_ENABLE_MEMORY_LEAK_ANALYSIS_KEY)?.let { pref -> + pref.isVisible = BuildConfig.DEBUG + pref.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue -> + leakCanaryProxy.enable(newValue as? Boolean ?: false) + true + } + } } } diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index d1b2d237d9..1b21642e04 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -2185,6 +2185,9 @@ ${app_name} may crash more often when an unexpected error occurs + Enable memory leak analysis + App performances may be impacted when enabled. + Show debug info on screen Show some useful info to help debugging the application diff --git a/vector/src/main/res/xml/vector_settings_advanced_settings.xml b/vector/src/main/res/xml/vector_settings_advanced_settings.xml index 2fb3fae310..c076fc2238 100644 --- a/vector/src/main/res/xml/vector_settings_advanced_settings.xml +++ b/vector/src/main/res/xml/vector_settings_advanced_settings.xml @@ -44,6 +44,13 @@ android:summary="@string/settings_developer_mode_fail_fast_summary" android:title="@string/settings_developer_mode_fail_fast_title" /> + + - \ No newline at end of file + diff --git a/vector/src/release/java/im/vector/app/leakcanary/LeakCanaryProxy.kt b/vector/src/release/java/im/vector/app/leakcanary/LeakCanaryProxy.kt new file mode 100644 index 0000000000..28c9f1c9d5 --- /dev/null +++ b/vector/src/release/java/im/vector/app/leakcanary/LeakCanaryProxy.kt @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.leakcanary + +import javax.inject.Inject + +/** + * No op version. + */ +@Suppress("UNUSED_PARAMETER") +class LeakCanaryProxy @Inject constructor() { + fun enable(enable: Boolean) {} +} From 12405527e14b010123aa98977be515410ce583c5 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Tue, 9 Aug 2022 16:16:55 +0200 Subject: [PATCH 22/55] Adding changelog entry --- changelog.d/6786.misc | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/6786.misc diff --git a/changelog.d/6786.misc b/changelog.d/6786.misc new file mode 100644 index 0000000000..a916336ae4 --- /dev/null +++ b/changelog.d/6786.misc @@ -0,0 +1 @@ +Add a developer setting to enable LeakCanary at runtime From 250ee1faa1c4a7a9a0ff5aa866aa0f50570faac5 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Wed, 10 Aug 2022 14:19:03 +0200 Subject: [PATCH 23/55] Moving the new setting inside debug screen --- vector/src/debug/AndroidManifest.xml | 1 + .../app/features/debug/DebugMenuActivity.kt | 6 ++ .../debug/di/MavericksViewModelDebugModule.kt | 7 ++ .../debug/leak/DebugMemoryLeaksActivity.kt | 37 ++++++++++ .../debug/leak/DebugMemoryLeaksFragment.kt | 54 +++++++++++++++ .../debug/leak/DebugMemoryLeaksViewActions.kt | 23 +++++++ .../debug/leak/DebugMemoryLeaksViewModel.kt | 67 +++++++++++++++++++ .../debug/leak/DebugMemoryLeaksViewState.kt | 23 +++++++ .../debug/res/layout/activity_debug_menu.xml | 12 +++- .../layout/fragment_debug_memory_leaks.xml | 32 +++++++++ .../im/vector/app/core/di/FragmentModule.kt | 6 -- .../features/settings/VectorPreferences.kt | 9 ++- .../VectorSettingsAdvancedSettingsFragment.kt | 18 +---- vector/src/main/res/values/strings.xml | 3 - .../xml/vector_settings_advanced_settings.xml | 7 -- 15 files changed, 270 insertions(+), 35 deletions(-) create mode 100644 vector/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksActivity.kt create mode 100644 vector/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksFragment.kt create mode 100644 vector/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksViewActions.kt create mode 100644 vector/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksViewModel.kt create mode 100644 vector/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksViewState.kt create mode 100644 vector/src/debug/res/layout/fragment_debug_memory_leaks.xml diff --git a/vector/src/debug/AndroidManifest.xml b/vector/src/debug/AndroidManifest.xml index 4ec47d4920..94fdb1b389 100644 --- a/vector/src/debug/AndroidManifest.xml +++ b/vector/src/debug/AndroidManifest.xml @@ -10,6 +10,7 @@ + () { views.debugAnalytics.setOnClickListener { startActivity(Intent(this, DebugAnalyticsActivity::class.java)) } + views.debugMemoryLeaks.setOnClickListener { openMemoryLeaksSettings() } views.debugTestTextViewLink.setOnClickListener { testTextViewLink() } views.debugOpenButtonStylesLight.setOnClickListener { startActivity(Intent(this, DebugVectorButtonStylesLightActivity::class.java)) @@ -130,6 +132,10 @@ class DebugMenuActivity : VectorBaseActivity() { startActivity(Intent(this, DebugPrivateSettingsActivity::class.java)) } + private fun openMemoryLeaksSettings() { + startActivity(Intent(this, DebugMemoryLeaksActivity::class.java)) + } + private fun renderQrCode(text: String) { views.debugQrCode.setData(text) } diff --git a/vector/src/debug/java/im/vector/app/features/debug/di/MavericksViewModelDebugModule.kt b/vector/src/debug/java/im/vector/app/features/debug/di/MavericksViewModelDebugModule.kt index 6ef7fe441a..8512bb8c6d 100644 --- a/vector/src/debug/java/im/vector/app/features/debug/di/MavericksViewModelDebugModule.kt +++ b/vector/src/debug/java/im/vector/app/features/debug/di/MavericksViewModelDebugModule.kt @@ -24,6 +24,7 @@ import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.MavericksViewModelComponent import im.vector.app.core.di.MavericksViewModelKey import im.vector.app.features.debug.analytics.DebugAnalyticsViewModel +import im.vector.app.features.debug.leak.DebugMemoryLeaksViewModel import im.vector.app.features.debug.settings.DebugPrivateSettingsViewModel @InstallIn(MavericksViewModelComponent::class) @@ -39,4 +40,10 @@ interface MavericksViewModelDebugModule { @IntoMap @MavericksViewModelKey(DebugPrivateSettingsViewModel::class) fun debugPrivateSettingsViewModelFactory(factory: DebugPrivateSettingsViewModel.Factory): MavericksAssistedViewModelFactory<*, *> + + @Binds + @IntoMap + @MavericksViewModelKey(DebugMemoryLeaksViewModel::class) + fun debugMemoryLeaksViewModelFactory(factory: DebugMemoryLeaksViewModel.Factory): MavericksAssistedViewModelFactory<*, *> + } diff --git a/vector/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksActivity.kt b/vector/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksActivity.kt new file mode 100644 index 0000000000..226c65e3ed --- /dev/null +++ b/vector/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksActivity.kt @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.debug.leak + +import dagger.hilt.android.AndroidEntryPoint +import im.vector.app.core.extensions.addFragment +import im.vector.app.core.platform.VectorBaseActivity +import im.vector.app.databinding.ActivitySimpleBinding + +@AndroidEntryPoint +class DebugMemoryLeaksActivity : VectorBaseActivity() { + + override fun getBinding() = ActivitySimpleBinding.inflate(layoutInflater) + + override fun initUiAndData() { + if (isFirstCreation()) { + addFragment( + views.simpleFragmentContainer, + DebugMemoryLeaksFragment::class.java + ) + } + } +} diff --git a/vector/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksFragment.kt b/vector/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksFragment.kt new file mode 100644 index 0000000000..d3e70e26e6 --- /dev/null +++ b/vector/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksFragment.kt @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.debug.leak + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import com.airbnb.mvrx.fragmentViewModel +import com.airbnb.mvrx.withState +import dagger.hilt.android.AndroidEntryPoint +import im.vector.app.core.epoxy.onClick +import im.vector.app.core.platform.VectorBaseFragment +import im.vector.app.databinding.FragmentDebugMemoryLeaksBinding + +@AndroidEntryPoint +class DebugMemoryLeaksFragment : VectorBaseFragment() { + + private val viewModel: DebugMemoryLeaksViewModel by fragmentViewModel() + + override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentDebugMemoryLeaksBinding { + return FragmentDebugMemoryLeaksBinding.inflate(inflater, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + setViewListeners() + } + + private fun setViewListeners() { + views.enableMemoryLeakAnalysis.onClick { + viewModel.handle(DebugMemoryLeaksViewActions.EnableMemoryLeaksAnalysis(views.enableMemoryLeakAnalysis.isChecked)) + } + } + + override fun invalidate() = withState(viewModel) { viewState -> + views.enableMemoryLeakAnalysis.isChecked = viewState.isMemoryLeaksAnalysisEnabled + } +} diff --git a/vector/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksViewActions.kt b/vector/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksViewActions.kt new file mode 100644 index 0000000000..e1447ae345 --- /dev/null +++ b/vector/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksViewActions.kt @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.debug.leak + +import im.vector.app.core.platform.VectorViewModelAction + +sealed interface DebugMemoryLeaksViewActions : VectorViewModelAction { + data class EnableMemoryLeaksAnalysis(val isEnabled: Boolean) : DebugMemoryLeaksViewActions +} diff --git a/vector/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksViewModel.kt b/vector/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksViewModel.kt new file mode 100644 index 0000000000..617a6b2ecb --- /dev/null +++ b/vector/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksViewModel.kt @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.debug.leak + +import com.airbnb.mvrx.MavericksViewModelFactory +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject +import im.vector.app.core.di.MavericksAssistedViewModelFactory +import im.vector.app.core.di.hiltMavericksViewModelFactory +import im.vector.app.core.platform.EmptyViewEvents +import im.vector.app.core.platform.VectorViewModel +import im.vector.app.features.settings.VectorPreferences +import im.vector.app.leakcanary.LeakCanaryProxy +import kotlinx.coroutines.launch + +class DebugMemoryLeaksViewModel @AssistedInject constructor( + @Assisted initialState: DebugMemoryLeaksViewState, + private val vectorPreferences: VectorPreferences, + private val leakCanaryProxy: LeakCanaryProxy, +) : VectorViewModel(initialState) { + + @AssistedFactory + interface Factory : MavericksAssistedViewModelFactory { + override fun create(initialState: DebugMemoryLeaksViewState): DebugMemoryLeaksViewModel + } + + companion object : MavericksViewModelFactory by hiltMavericksViewModelFactory() + + init { + viewModelScope.launch { + refreshStateFromPreferences() + } + } + + override fun handle(action: DebugMemoryLeaksViewActions) { + when (action) { + is DebugMemoryLeaksViewActions.EnableMemoryLeaksAnalysis -> handleEnableMemoryLeaksAnalysis(action) + } + } + + private fun handleEnableMemoryLeaksAnalysis(action: DebugMemoryLeaksViewActions.EnableMemoryLeaksAnalysis) { + viewModelScope.launch { + vectorPreferences.enableMemoryLeakAnalysis(action.isEnabled) + leakCanaryProxy.enable(action.isEnabled) + refreshStateFromPreferences() + } + } + + private fun refreshStateFromPreferences() { + setState { copy(isMemoryLeaksAnalysisEnabled = vectorPreferences.isMemoryLeakAnalysisEnabled()) } + } +} diff --git a/vector/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksViewState.kt b/vector/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksViewState.kt new file mode 100644 index 0000000000..4e9fe4b402 --- /dev/null +++ b/vector/src/debug/java/im/vector/app/features/debug/leak/DebugMemoryLeaksViewState.kt @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.debug.leak + +import com.airbnb.mvrx.MavericksState + +data class DebugMemoryLeaksViewState( + val isMemoryLeaksAnalysisEnabled: Boolean = false +) : MavericksState diff --git a/vector/src/debug/res/layout/activity_debug_menu.xml b/vector/src/debug/res/layout/activity_debug_menu.xml index 8b38c17b35..b5efe0302c 100644 --- a/vector/src/debug/res/layout/activity_debug_menu.xml +++ b/vector/src/debug/res/layout/activity_debug_menu.xml @@ -1,5 +1,6 @@ + android:layout_height="wrap_content" + app:layout_anchor="@+id/scrollView2" + app:layout_anchorGravity="center"> +