diff --git a/.github/workflows/danger.yml b/.github/workflows/danger.yml index a1d754b4de..d36f2d0765 100644 --- a/.github/workflows/danger.yml +++ b/.github/workflows/danger.yml @@ -16,3 +16,5 @@ jobs: args: "--dangerfile tools/danger/dangerfile.js" env: DANGER_GITHUB_API_TOKEN: ${{ secrets.DANGER_GITHUB_API_TOKEN }} + # Fallback for forks + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index 6e5e2e4d67..544d9081f8 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -71,6 +71,8 @@ jobs: args: "--dangerfile tools/danger/dangerfile-lint.js" env: DANGER_GITHUB_API_TOKEN: ${{ secrets.DANGER_GITHUB_API_TOKEN }} + # Fallback for forks + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Gradle dependency analysis using https://github.com/autonomousapps/dependency-analysis-android-gradle-plugin dependency-analysis: 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/build.gradle b/build.gradle index afe51cc734..38cbc3af0f 100644 --- a/build.gradle +++ b/build.gradle @@ -24,7 +24,7 @@ buildscript { classpath libs.gradle.gradlePlugin classpath libs.gradle.kotlinPlugin classpath libs.gradle.hiltPlugin - classpath 'com.google.firebase:firebase-appdistribution-gradle:3.0.2' + classpath 'com.google.firebase:firebase-appdistribution-gradle:3.0.3' classpath 'com.google.gms:google-services:4.3.13' classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.4.0.2513' classpath 'com.google.android.gms:oss-licenses-plugin:0.10.5' @@ -44,7 +44,7 @@ plugins { id "io.gitlab.arturbosch.detekt" version "1.21.0" // Dependency Analysis - id 'com.autonomousapps.dependency-analysis' version "1.11.2" + id 'com.autonomousapps.dependency-analysis' version "1.12.0" } // https://github.com/jeremylong/DependencyCheck @@ -151,6 +151,8 @@ allprojects { "experimental:comment-wrapping", // - A KDoc comment after any other element on the same line must be separated by a new line "experimental:kdoc-wrapping", + // Ignore error "Redundant curly braces", since we use it to fix false positives, for instance in "elementLogs.${i}.txt" + "string-template", ] } diff --git a/changelog.d/5974.misc b/changelog.d/5974.misc new file mode 100644 index 0000000000..d2ddef6f1d --- /dev/null +++ b/changelog.d/5974.misc @@ -0,0 +1 @@ +Removes the Login2 proof of concept - replaced by the FTUE changes 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/6505.wip b/changelog.d/6505.wip new file mode 100644 index 0000000000..1109c5fff1 --- /dev/null +++ b/changelog.d/6505.wip @@ -0,0 +1 @@ +added filter tabs for new App layout's Home screen 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/6645.misc b/changelog.d/6645.misc new file mode 100644 index 0000000000..b24655879d --- /dev/null +++ b/changelog.d/6645.misc @@ -0,0 +1 @@ +Enable auto-capitalization for Room creation Title field 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/6746.feature b/changelog.d/6746.feature new file mode 100644 index 0000000000..7869e7f57a --- /dev/null +++ b/changelog.d/6746.feature @@ -0,0 +1 @@ +[Notification] - Handle creation of notification for live location and poll start diff --git a/changelog.d/6749.wip b/changelog.d/6749.wip new file mode 100644 index 0000000000..d7fac1efc1 --- /dev/null +++ b/changelog.d/6749.wip @@ -0,0 +1 @@ +Adds space list bottom sheet for new app layout 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/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 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 diff --git a/changelog.d/6795.wip b/changelog.d/6795.wip new file mode 100644 index 0000000000..da525a2c67 --- /dev/null +++ b/changelog.d/6795.wip @@ -0,0 +1 @@ +Makes toolbar switch title based on space in New App Layout 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 diff --git a/changelog.d/6799.misc b/changelog.d/6799.misc new file mode 100644 index 0000000000..b756c2c07b --- /dev/null +++ b/changelog.d/6799.misc @@ -0,0 +1 @@ +[Create Room] Reduce some boilerplate with room state event contents diff --git a/changelog.d/6806.wip b/changelog.d/6806.wip new file mode 100644 index 0000000000..9b00139c62 --- /dev/null +++ b/changelog.d/6806.wip @@ -0,0 +1 @@ +[Devices management] Other sessions section in new layout diff --git a/changelog.d/6808.misc b/changelog.d/6808.misc new file mode 100644 index 0000000000..06eeff862b --- /dev/null +++ b/changelog.d/6808.misc @@ -0,0 +1 @@ +[Call] Memory leak after a call diff --git a/changelog.d/6843.misc b/changelog.d/6843.misc new file mode 100644 index 0000000000..5382e27082 --- /dev/null +++ b/changelog.d/6843.misc @@ -0,0 +1 @@ +Fix some string template diff --git a/dependencies.gradle b/dependencies.gradle index 93a62a548e..5083dd4556 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -22,7 +22,7 @@ def markwon = "4.6.2" def moshi = "1.13.0" def lifecycle = "2.5.1" def flowBinding = "1.2.0" -def flipper = "0.156.0" +def flipper = "0.157.0" def epoxy = "4.6.2" def mavericks = "2.7.0" def glide = "4.13.2" @@ -30,7 +30,7 @@ def bigImageViewer = "1.8.1" def jjwt = "0.11.5" def vanniktechEmoji = "0.15.0" -def fragment = "1.5.1" +def fragment = "1.5.2" // Testing def mockk = "1.12.3" // We need to use 1.12.3 to have mocking in androidTest until a new version is released: https://github.com/mockk/mockk/issues/819 diff --git a/dependencies_groups.gradle b/dependencies_groups.gradle index d5972ed846..bcd737acc9 100644 --- a/dependencies_groups.gradle +++ b/dependencies_groups.gradle @@ -107,7 +107,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/docs/danger.md b/docs/danger.md index 19728f00e9..afa3555469 100644 --- a/docs/danger.md +++ b/docs/danger.md @@ -23,6 +23,7 @@ Here are the checks that Danger does so far: - PR description is not empty - Big PR got a warning to recommend to split - PR contains a file for towncrier and extension is checked +- PR does not modify frozen classes - PR contains a Sign-Off, with exception for Element employee contributors - PR with change on layout should include screenshot in the description - PR which adds png file warn about the usage of vector drawables @@ -84,6 +85,8 @@ To let Danger check all the PRs, including PRs form forks, a GitHub account have - password: Stored on Passbolt - GitHub token: A token with limited access has been created and added to the repository https://github.com/vector-im/element-android as secret DANGER_GITHUB_API_TOKEN. This token is not saved anywhere else. In case of problem, just delete it and create a new one, then update the secret. +PRs from forks do not always have access to the secret `secrets.DANGER_GITHUB_API_TOKEN`, so `secrets.GITHUB_TOKEN` is also provided to the job environment. If `secrets.DANGER_GITHUB_API_TOKEN` is available, it will be used, so user `ElementBot` will comment the PR. Else `secrets.GITHUB_TOKEN` will be used, and bot `github-actions` will comment the PR. + ## Useful links - https://danger.systems/ 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ef80eb5051..f7189a776c 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=97a52d145762adc241bad7fd18289bf7f6801e08ece6badf80402fe2b9f250b1 -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip +distributionSha256Sum=db9c8211ed63f61f60292c69e80d89196f9eb36665e369e7f00ac4cc841c2219 +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/library/ui-styles/src/main/res/values/stylable_devices_list_header_view.xml b/library/ui-styles/src/main/res/values/stylable_devices_list_header_view.xml new file mode 100644 index 0000000000..f0807f89c6 --- /dev/null +++ b/library/ui-styles/src/main/res/values/stylable_devices_list_header_view.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/library/ui-styles/src/main/res/values/styles_devices_management.xml b/library/ui-styles/src/main/res/values/styles_devices_management.xml new file mode 100644 index 0000000000..2a63c2ed36 --- /dev/null +++ b/library/ui-styles/src/main/res/values/styles_devices_management.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/library/ui-styles/src/main/res/values/styles_tablayout.xml b/library/ui-styles/src/main/res/values/styles_tablayout.xml new file mode 100644 index 0000000000..ab26972995 --- /dev/null +++ b/library/ui-styles/src/main/res/values/styles_tablayout.xml @@ -0,0 +1,18 @@ + + + + + + + + + + diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle index 45a962f12c..ed3e3cdd7b 100644 --- a/matrix-sdk-android/build.gradle +++ b/matrix-sdk-android/build.gradle @@ -17,7 +17,7 @@ buildscript { } } dependencies { - classpath "io.realm:realm-gradle-plugin:10.11.0" + classpath "io.realm:realm-gradle-plugin:10.11.1" } } @@ -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/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomGuestAccessContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomGuestAccessContent.kt index 7dd853d75d..b229a35458 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomGuestAccessContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomGuestAccessContent.kt @@ -29,14 +29,12 @@ data class RoomGuestAccessContent( // Required. Whether guests can join the room. One of: ["can_join", "forbidden"] @Json(name = "guest_access") val guestAccessStr: String? = null ) { - val guestAccess: GuestAccess? = when (guestAccessStr) { - "can_join" -> GuestAccess.CanJoin - "forbidden" -> GuestAccess.Forbidden - else -> { - Timber.w("Invalid value for GuestAccess: `$guestAccessStr`") - null - } - } + val guestAccess: GuestAccess? = GuestAccess.values() + .find { it.value == guestAccessStr } + ?: run { + Timber.w("Invalid value for GuestAccess: `$guestAccessStr`") + null + } } @JsonClass(generateAdapter = false) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomHistoryVisibility.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomHistoryVisibility.kt index 2b0ea1d8fb..eef986ef96 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomHistoryVisibility.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomHistoryVisibility.kt @@ -23,30 +23,30 @@ import com.squareup.moshi.JsonClass * Ref: https://matrix.org/docs/spec/client_server/latest#room-history-visibility */ @JsonClass(generateAdapter = false) -enum class RoomHistoryVisibility { +enum class RoomHistoryVisibility(val value: String) { /** * All events while this is the m.room.history_visibility value may be shared by any * participating homeserver with anyone, regardless of whether they have ever joined the room. */ - @Json(name = "world_readable") WORLD_READABLE, + @Json(name = "world_readable") WORLD_READABLE("world_readable"), /** * Previous events are always accessible to newly joined members. All events in the * room are accessible, even those sent when the member was not a part of the room. */ - @Json(name = "shared") SHARED, + @Json(name = "shared") SHARED("shared"), /** * Events are accessible to newly joined members from the point they were invited onwards. * Events stop being accessible when the member's state changes to something other than invite or join. */ - @Json(name = "invited") INVITED, + @Json(name = "invited") INVITED("invited"), /** * Events are accessible to newly joined members from the point they joined the room onwards. * Events stop being accessible when the member's state changes to something other than join. */ - @Json(name = "joined") JOINED + @Json(name = "joined") JOINED("joined") } /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomHistoryVisibilityContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomHistoryVisibilityContent.kt index 39b4722c0c..696cd8f613 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomHistoryVisibilityContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomHistoryVisibilityContent.kt @@ -24,14 +24,10 @@ import timber.log.Timber data class RoomHistoryVisibilityContent( @Json(name = "history_visibility") val historyVisibilityStr: String? = null ) { - val historyVisibility: RoomHistoryVisibility? = when (historyVisibilityStr) { - "world_readable" -> RoomHistoryVisibility.WORLD_READABLE - "shared" -> RoomHistoryVisibility.SHARED - "invited" -> RoomHistoryVisibility.INVITED - "joined" -> RoomHistoryVisibility.JOINED - else -> { - Timber.w("Invalid value for RoomHistoryVisibility: `$historyVisibilityStr`") - null - } - } + val historyVisibility: RoomHistoryVisibility? = RoomHistoryVisibility.values() + .find { it.value == historyVisibilityStr } + ?: run { + Timber.w("Invalid value for RoomHistoryVisibility: `$historyVisibilityStr`") + null + } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/create/RoomFeaturePreset.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/create/RoomFeaturePreset.kt index 6487ad947f..3ed3e2d3a6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/create/RoomFeaturePreset.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/create/RoomFeaturePreset.kt @@ -16,7 +16,6 @@ package org.matrix.android.sdk.api.session.room.model.create -import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.toContent import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities @@ -30,7 +29,7 @@ interface RoomFeaturePreset { fun updateRoomParams(params: CreateRoomParams) - fun setupInitialStates(): List? + fun setupInitialStates(): List? } class RestrictedRoomPreset(val homeServerCapabilities: HomeServerCapabilities, val restrictedList: List) : RoomFeaturePreset { @@ -41,9 +40,9 @@ class RestrictedRoomPreset(val homeServerCapabilities: HomeServerCapabilities, v params.roomVersion = homeServerCapabilities.versionOverrideForFeature(HomeServerCapabilities.ROOM_CAP_RESTRICTED) } - override fun setupInitialStates(): List? { + override fun setupInitialStates(): List { return listOf( - Event( + CreateRoomStateEvent( type = EventType.STATE_ROOM_JOIN_RULES, stateKey = "", content = RoomJoinRulesContent( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageBeaconLocationDataContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageBeaconLocationDataContent.kt index e261ab5206..aa2777d0a6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageBeaconLocationDataContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageBeaconLocationDataContent.kt @@ -22,7 +22,7 @@ import org.matrix.android.sdk.api.session.events.model.Content import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent /** - * Content of the state event of type + * Content of the event of type * [EventType.BEACON_LOCATION_DATA][org.matrix.android.sdk.api.session.events.model.EventType.BEACON_LOCATION_DATA] * * It contains location data related to a live location share. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationTransportToDevice.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationTransportToDevice.kt index 861a7a3a77..23a75d2bb3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationTransportToDevice.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationTransportToDevice.kt @@ -76,12 +76,12 @@ internal class VerificationTransportToDevice( .configureWith(SendToDeviceTask.Params(MessageType.MSGTYPE_VERIFICATION_REQUEST, contentMap)) { this.callback = object : MatrixCallback { override fun onSuccess(data: Unit) { - Timber.v("## verification [$tx.transactionId] send toDevice request success") + Timber.v("## verification [${tx?.transactionId}] send toDevice request success") callback.invoke(localId, validKeyReq) } override fun onFailure(failure: Throwable) { - Timber.e("## verification [$tx.transactionId] failed to send toDevice request") + Timber.e("## verification [${tx?.transactionId}] failed to send toDevice request") } } } @@ -103,12 +103,12 @@ internal class VerificationTransportToDevice( .configureWith(SendToDeviceTask.Params(EventType.KEY_VERIFICATION_READY, contentMap)) { this.callback = object : MatrixCallback { override fun onSuccess(data: Unit) { - Timber.v("## verification [$tx.transactionId] send toDevice request success") + Timber.v("## verification [${tx?.transactionId}] send toDevice request success") callback?.invoke() } override fun onFailure(failure: Throwable) { - Timber.e("## verification [$tx.transactionId] failed to send toDevice request") + Timber.e("## verification [${tx?.transactionId}] failed to send toDevice request") } } } @@ -136,7 +136,7 @@ internal class VerificationTransportToDevice( .configureWith(SendToDeviceTask.Params(type, contentMap)) { this.callback = object : MatrixCallback { override fun onSuccess(data: Unit) { - Timber.v("## SAS verification [$tx.transactionId] toDevice type '$type' success.") + Timber.v("## SAS verification [${tx.transactionId}] toDevice type '$type' success.") if (onDone != null) { onDone() } else { @@ -149,7 +149,7 @@ internal class VerificationTransportToDevice( } override fun onFailure(failure: Throwable) { - Timber.e("## SAS verification [$tx.transactionId] failed to send toDevice in state : $tx.state") + Timber.e("## SAS verification [${tx.transactionId}] failed to send toDevice in state : ${tx.state}") tx.cancel(onErrorReason) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/SessionRealmConfigurationFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/SessionRealmConfigurationFactory.kt index 949dd5daa1..5a0fd74bc0 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/SessionRealmConfigurationFactory.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/SessionRealmConfigurationFactory.kt @@ -93,7 +93,7 @@ internal class SessionRealmConfigurationFactory @Inject constructor( return } - listOf(REALM_NAME, "$REALM_NAME.lock", "$REALM_NAME.note", "$REALM_NAME.management").forEach { file -> + listOf(REALM_NAME, "${REALM_NAME}.lock", "${REALM_NAME}.note", "${REALM_NAME}.management").forEach { file -> try { File(directory, file).deleteRecursively() } catch (e: Exception) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomBodyBuilder.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomBodyBuilder.kt index faf68d538f..4105c77cc8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomBodyBuilder.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomBodyBuilder.kt @@ -20,8 +20,13 @@ import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.EventType +import org.matrix.android.sdk.api.session.events.model.content.EncryptionEventContent +import org.matrix.android.sdk.api.session.events.model.toContent import org.matrix.android.sdk.api.session.identity.IdentityServiceError import org.matrix.android.sdk.api.session.identity.toMedium +import org.matrix.android.sdk.api.session.room.model.RoomAvatarContent +import org.matrix.android.sdk.api.session.room.model.RoomGuestAccessContent +import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibilityContent import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams import org.matrix.android.sdk.api.util.MimeTypes import org.matrix.android.sdk.internal.crypto.DeviceListManager @@ -78,7 +83,7 @@ internal class CreateRoomBodyBuilder @Inject constructor( buildAvatarEvent(params), buildGuestAccess(params) ) + - params.featurePreset?.setupInitialStates().orEmpty() + + buildFeaturePresetInitialStates(params) + buildCustomInitialStates(params) ) .takeIf { it.isNotEmpty() } @@ -99,6 +104,16 @@ internal class CreateRoomBodyBuilder @Inject constructor( ) } + private fun buildFeaturePresetInitialStates(params: CreateRoomParams): List { + return params.featurePreset?.setupInitialStates().orEmpty().map { + Event( + type = it.type, + stateKey = it.stateKey, + content = it.content + ) + } + } + private fun buildCustomInitialStates(params: CreateRoomParams): List { return params.initialStates.map { Event( @@ -123,7 +138,7 @@ internal class CreateRoomBodyBuilder @Inject constructor( Event( type = EventType.STATE_ROOM_AVATAR, stateKey = "", - content = mapOf("url" to response.contentUri) + content = RoomAvatarContent(response.contentUri).toContent() ) } } @@ -134,7 +149,7 @@ internal class CreateRoomBodyBuilder @Inject constructor( Event( type = EventType.STATE_ROOM_HISTORY_VISIBILITY, stateKey = "", - content = mapOf("history_visibility" to it) + content = RoomHistoryVisibilityContent(it.value).toContent() ) } } @@ -145,7 +160,7 @@ internal class CreateRoomBodyBuilder @Inject constructor( Event( type = EventType.STATE_ROOM_GUEST_ACCESS, stateKey = "", - content = mapOf("guest_access" to it.value) + content = RoomGuestAccessContent(it.value).toContent() ) } } @@ -167,7 +182,7 @@ internal class CreateRoomBodyBuilder @Inject constructor( Event( type = EventType.STATE_ROOM_ENCRYPTION, stateKey = "", - content = mapOf("algorithm" to it) + content = EncryptionEventContent(it).toContent() ) } } diff --git a/tools/check/check_code_quality.sh b/tools/check/check_code_quality.sh index 79a42083d3..910616176c 100755 --- a/tools/check/check_code_quality.sh +++ b/tools/check/check_code_quality.sh @@ -16,21 +16,6 @@ # limitations under the License. # -####################################################################################################################### -# Check frozen class modification -####################################################################################################################### - -echo "Check if frozen class modified" -git diff "HEAD@{1}" --name-only | grep -e OlmInboundGroupSessionWrapper.kt -e OlmInboundGroupSessionWrapper2.kt -FROZEN_CHANGED=$? -if [ ${FROZEN_CHANGED} -eq 0 ]; then - echo "❌ FROZEN CLASS CHANGED ERROR" - exit 1 -else - echo "Frozen check OK" -fi - - ####################################################################################################################### # Check drawable quantity ####################################################################################################################### diff --git a/tools/check/forbidden_strings_in_code.txt b/tools/check/forbidden_strings_in_code.txt index b12f15fa5d..b4d7ebae1f 100755 --- a/tools/check/forbidden_strings_in_code.txt +++ b/tools/check/forbidden_strings_in_code.txt @@ -185,3 +185,6 @@ System\.currentTimeMillis\(\)===2 onCreateOptionsMenu onOptionsItemSelected onPrepareOptionsMenu + +### Suspicious String template. Please check that the string template will behave as expected, i.e. the class field and not the whole object will be used. For instance `Timber.d("$event.type")` is not correct, you should write `Timber.d("${event.type}")`. In the former the whole event content will be logged, since it's a data class. If this is expected (i.e. to fix false positive), please add explicit curly braces (`{` and `}`) around the variable, for instance `"elementLogs.${i}.txt"` +\$[a-zA-Z_]\w*\??\.[a-zA-Z_] diff --git a/tools/danger/dangerfile.js b/tools/danger/dangerfile.js index 4efd236419..c7db52fa19 100644 --- a/tools/danger/dangerfile.js +++ b/tools/danger/dangerfile.js @@ -52,6 +52,19 @@ if (requiresChangelog) { } } +// check that frozen classes have not been modified +const frozenClasses = [ + "OlmInboundGroupSessionWrapper.kt", + "OlmInboundGroupSessionWrapper2.kt", +] + +frozenClasses.forEach(frozen => { + if (editedFiles.some(file => file.endsWith(frozen))) { + fail("Frozen class `" + frozen + "` has been modified. Please do not modify frozen class.") + } + } +) + // Check for a sign-off const signOff = "Signed-off-by:" diff --git a/tools/emojis/emoji_picker_datasource_formatted.json b/tools/emojis/emoji_picker_datasource_formatted.json index a1b944a7eb..41465a442f 100644 --- a/tools/emojis/emoji_picker_datasource_formatted.json +++ b/tools/emojis/emoji_picker_datasource_formatted.json @@ -2634,7 +2634,8 @@ "mask", "sick", "ill", - "disease" + "disease", + "covid" ] }, "face-with-thermometer": { @@ -2647,7 +2648,8 @@ "thermometer", "temperature", "cold", - "fever" + "fever", + "covid" ] }, "face-with-headbandage": { @@ -4481,7 +4483,9 @@ "hope", "wish", "namaste", - "highfive" + "highfive", + "thank you", + "appreciate" ] }, "writing-hand": { @@ -9581,7 +9585,8 @@ "amoeba", "bacteria", "virus", - "germs" + "germs", + "covid" ] }, "bouquet": { @@ -10260,7 +10265,9 @@ "baguette", "bread", "food", - "french" + "french", + "france", + "bakery" ] }, "flatbread": { @@ -10272,7 +10279,8 @@ "naan", "pita", "flour", - "food" + "food", + "bakery" ] }, "pretzel": { @@ -10282,7 +10290,9 @@ "twisted", "convoluted", "food", - "bread" + "bread", + "germany", + "bakery" ] }, "bagel": { @@ -10293,7 +10303,8 @@ "breakfast", "schmear", "food", - "bread" + "bread", + "jewish" ] }, "pancakes": { @@ -10306,7 +10317,8 @@ "hotcake", "pancake", "flapjacks", - "hotcakes" + "hotcakes", + "brunch" ] }, "waffle": { @@ -10316,7 +10328,8 @@ "breakfast", "indecisive", "iron", - "food" + "food", + "brunch" ] }, "cheese-wedge": { @@ -10325,7 +10338,8 @@ "j": [ "cheese", "food", - "chadder" + "chadder", + "swiss" ] }, "meat-on-bone": { @@ -10376,7 +10390,8 @@ "food", "meat", "pork", - "pig" + "pig", + "brunch" ] }, "hamburger": { @@ -10400,7 +10415,8 @@ "fries", "chips", "snack", - "fast food" + "fast food", + "potato" ] }, "pizza": { @@ -10410,7 +10426,8 @@ "cheese", "slice", "food", - "party" + "party", + "italy" ] }, "hot-dog": { @@ -10420,7 +10437,8 @@ "frankfurter", "hotdog", "sausage", - "food" + "food", + "america" ] }, "sandwich": { @@ -10429,7 +10447,9 @@ "j": [ "bread", "food", - "lunch" + "lunch", + "toast", + "bakery" ] }, "taco": { @@ -10468,7 +10488,8 @@ "food", "gyro", "kebab", - "stuffed" + "stuffed", + "mediterranean" ] }, "falafel": { @@ -10477,7 +10498,8 @@ "j": [ "chickpea", "meatball", - "food" + "food", + "mediterranean" ] }, "egg": { @@ -10498,7 +10520,8 @@ "frying", "pan", "food", - "kitchen" + "kitchen", + "skillet" ] }, "shallow-pan-of-food": { @@ -10510,7 +10533,8 @@ "paella", "pan", "shallow", - "cooking" + "cooking", + "skillet" ] }, "pot-of-food": { @@ -10521,7 +10545,8 @@ "stew", "food", "meat", - "soup" + "soup", + "hot pot" ] }, "fondue": { @@ -10556,7 +10581,8 @@ "green", "salad", "healthy", - "lettuce" + "lettuce", + "vegetable" ] }, "popcorn": { @@ -10566,7 +10592,8 @@ "food", "movie theater", "films", - "snack" + "snack", + "drama" ] }, "butter": { @@ -10592,7 +10619,8 @@ "j": [ "can", "food", - "soup" + "soup", + "tomatoes" ] }, "bento-box": { @@ -10602,7 +10630,8 @@ "bento", "box", "food", - "japanese" + "japanese", + "lunch" ] }, "rice-cracker": { @@ -10612,7 +10641,8 @@ "cracker", "rice", "food", - "japanese" + "japanese", + "snack" ] }, "rice-ball": { @@ -10633,7 +10663,6 @@ "cooked", "rice", "food", - "china", "asian" ] }, @@ -10680,7 +10709,8 @@ "roasted", "sweet", "food", - "nature" + "nature", + "plant" ] }, "oden": { @@ -10745,7 +10775,8 @@ "autumn", "festival", "yuèbǐng", - "food" + "food", + "dessert" ] }, "dango": { @@ -10772,7 +10803,8 @@ "jiaozi", "pierogi", "potsticker", - "food" + "food", + "gyoza" ] }, "fortune-cookie": { @@ -10780,7 +10812,8 @@ "b": "1F960", "j": [ "prophecy", - "food" + "food", + "dessert" ] }, "takeout-box": { @@ -22169,7 +22202,9 @@ "nation", "country", "banner", - "japan" + "japan", + "jp", + "ja" ] }, "flag-kenya": { diff --git a/vector-config/src/main/java/im/vector/app/config/OnboardingVariant.kt b/vector-config/src/main/java/im/vector/app/config/OnboardingVariant.kt index ae8cfd1172..8821c8187e 100644 --- a/vector-config/src/main/java/im/vector/app/config/OnboardingVariant.kt +++ b/vector-config/src/main/java/im/vector/app/config/OnboardingVariant.kt @@ -18,6 +18,5 @@ package im.vector.app.config enum class OnboardingVariant { LEGACY, - LOGIN_2, FTUE_AUTH } diff --git a/vector/build.gradle b/vector/build.gradle index e5bd835a8f..18e094523e 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' @@ -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\"" } @@ -393,7 +391,7 @@ dependencies { implementation libs.androidx.biometric implementation "org.threeten:threetenbp:1.4.0:no-tzdb" - implementation "com.gabrielittner.threetenbp:lazythreetenbp:0.10.0" + implementation "com.gabrielittner.threetenbp:lazythreetenbp:0.11.0" implementation libs.squareup.moshi kapt libs.squareup.moshiKotlin @@ -502,7 +500,7 @@ dependencies { implementation 'com.posthog.android:posthog:1.1.2' // UnifiedPush - implementation 'com.github.UnifiedPush:android-connector:2.0.0' + implementation 'com.github.UnifiedPush:android-connector:2.0.1' // UnifiedPush gplay flavor only gplayImplementation('com.github.UnifiedPush:android-embedded_fcm_distributor:2.1.1') { exclude group: 'com.google.firebase', module: 'firebase-core' @@ -578,7 +576,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 diff --git a/vector/src/androidTest/java/im/vector/app/espresso/tools/ScreenshotFailureRule.kt b/vector/src/androidTest/java/im/vector/app/espresso/tools/ScreenshotFailureRule.kt index b01c1a895f..068c9fb646 100644 --- a/vector/src/androidTest/java/im/vector/app/espresso/tools/ScreenshotFailureRule.kt +++ b/vector/src/androidTest/java/im/vector/app/espresso/tools/ScreenshotFailureRule.kt @@ -83,7 +83,7 @@ private fun useMediaStoreScreenshotStorage( screenshotLocation: String, bitmap: Bitmap ) { - contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, "$screenshotName.jpeg") + contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, "${screenshotName}.jpeg") contentValues.put(MediaStore.Images.Media.RELATIVE_PATH, screenshotLocation) val uri: Uri? = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues) if (uri != null) { @@ -104,7 +104,7 @@ private fun usePublicExternalScreenshotStorage( if (!directory.exists()) { directory.mkdirs() } - val file = File(directory, "$screenshotName.jpeg") + val file = File(directory, "${screenshotName}.jpeg") saveScreenshotToStream(bitmap, FileOutputStream(file)) contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues) } diff --git a/vector/src/debug/AndroidManifest.xml b/vector/src/debug/AndroidManifest.xml index 84fa2584b9..94fdb1b389 100644 --- a/vector/src/debug/AndroidManifest.xml +++ b/vector/src/debug/AndroidManifest.xml @@ -9,6 +9,8 @@ + + () { 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/DebugModule.kt b/vector/src/debug/java/im/vector/app/features/debug/di/DebugModule.kt new file mode 100644 index 0000000000..d409e56349 --- /dev/null +++ b/vector/src/debug/java/im/vector/app/features/debug/di/DebugModule.kt @@ -0,0 +1,57 @@ +/* + * 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 android.content.Context +import android.content.Intent +import dagger.Binds +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 im.vector.app.core.debug.LeakDetector +import im.vector.app.features.debug.DebugMenuActivity +import im.vector.app.flipper.VectorFlipperProxy +import im.vector.app.leakcanary.LeakCanaryLeakDetector +import im.vector.app.receivers.VectorDebugReceiver + +@InstallIn(SingletonComponent::class) +@Module +abstract class DebugModule { + + companion object { + + @Provides + fun providesDebugNavigator() = object : DebugNavigator { + override fun openDebugMenu(context: Context) { + context.startActivity(Intent(context, DebugMenuActivity::class.java)) + } + } + } + + @Binds + abstract fun bindsDebugReceiver(receiver: VectorDebugReceiver): DebugReceiver + + @Binds + abstract fun bindsFlipperProxy(flipperProxy: VectorFlipperProxy): FlipperProxy + + @Binds + abstract fun bindsLeakDetector(leakDetector: LeakCanaryLeakDetector): LeakDetector +} 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..ba5b8abb5e 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,9 @@ 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/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/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..5432cb0888 --- /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.debug.LeakDetector +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 kotlinx.coroutines.launch + +class DebugMemoryLeaksViewModel @AssistedInject constructor( + @Assisted initialState: DebugMemoryLeaksViewState, + private val vectorPreferences: VectorPreferences, + private val leakDetector: LeakDetector, +) : 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) + leakDetector.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/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/debug/java/im/vector/app/leakcanary/LeakCanaryLeakDetector.kt b/vector/src/debug/java/im/vector/app/leakcanary/LeakCanaryLeakDetector.kt new file mode 100644 index 0000000000..15db71cd96 --- /dev/null +++ b/vector/src/debug/java/im/vector/app/leakcanary/LeakCanaryLeakDetector.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 im.vector.app.core.debug.LeakDetector +import leakcanary.LeakCanary +import javax.inject.Inject + +class LeakCanaryLeakDetector @Inject constructor() : LeakDetector { + override fun enable(enable: Boolean) { + LeakCanary.config = LeakCanary.config.copy(dumpHeap = enable) + } +} 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..550dc055d9 100644 --- a/vector/src/debug/java/im/vector/app/receivers/DebugReceiver.kt +++ b/vector/src/debug/java/im/vector/app/receivers/VectorDebugReceiver.kt @@ -22,14 +22,24 @@ import android.content.Intent import android.content.IntentFilter import android.content.SharedPreferences import androidx.core.content.edit +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 /** * 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/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"> +